9 #include "va_egl_private.h"
10 #include "va_egl_impl.h"
13 check_extension(const char *name, const char *exts)
21 end = exts + strlen(exts);
22 name_len = strlen(name);
25 n = strcspn(exts, " ");
27 if (n == name_len && strncmp(name, exts, n) == 0)
37 check_pixmap_extensions(VADriverContextP ctx, EGLDisplay egl_display)
41 exts = (const char *)eglQueryString(egl_display, EGL_EXTENSIONS);
43 if (!check_extension("EGL_KHR_image_pixmap", exts))
49 /* ========================================================================= */
50 /* === VA/EGL implementation from the driver (fordward calls) === */
51 /* ========================================================================= */
56 #define INVOKE(ctx, func, args) do { \
57 VADriverVTableEGLP vtable = (ctx)->vtable_egl; \
58 if (!vtable->va##func##EGL) \
59 return VA_STATUS_ERROR_UNIMPLEMENTED; \
61 VAStatus status = vtable->va##func##EGL args; \
62 if (status != VA_STATUS_SUCCESS) \
68 vaQuerySurfaceTargetsEGL_impl_driver(VADisplay dpy,
72 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
74 INVOKE(ctx, QuerySurfaceTargets, (ctx, target_list, num_targets));
76 return VA_STATUS_SUCCESS;
80 vaCreateSurfaceEGL_impl_driver(VADisplay dpy,
84 VASurfaceEGL *gl_surface)
86 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
88 INVOKE(ctx, CreateSurface, (ctx, target, width, height, gl_surface));
90 return VA_STATUS_SUCCESS;
94 vaDestroySurfaceEGL_impl_driver(VADisplay dpy, VASurfaceEGL egl_surface)
96 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
98 INVOKE(ctx, DestroySurface, (ctx, egl_surface));
100 return VA_STATUS_SUCCESS;
104 vaAssociateSurfaceEGL_impl_driver(VADisplay dpy,
105 VASurfaceEGL egl_surface,
109 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
111 INVOKE(ctx, AssociateSurface, (ctx, egl_surface, surface, flags));
113 return VA_STATUS_SUCCESS;
117 vaSyncSurfaceEGL_impl_driver(VADisplay dpy,
118 VASurfaceEGL egl_surface)
120 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
122 INVOKE(ctx, SyncSurface, (ctx, egl_surface));
124 return VA_STATUS_SUCCESS;
128 vaGetSurfaceInfoEGL_impl_driver(VADisplay dpy,
129 VASurfaceEGL egl_surface,
131 EGLClientBuffer *buffer,
135 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
137 INVOKE(ctx, GetSurfaceInfo, (ctx, egl_surface, target, buffer, attrib_list, num_attribs));
139 return VA_STATUS_SUCCESS;
143 vaDeassociateSurfaceEGL_impl_driver(VADisplay dpy,
144 VASurfaceEGL egl_surface)
146 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
148 INVOKE(ctx, DeassociateSurface, (ctx, egl_surface));
150 return VA_STATUS_SUCCESS;
155 /* ========================================================================= */
156 /* === VA/EGL helpers === */
157 /* ========================================================================= */
158 /** Unique VASurfaceImplEGL identifier */
159 #define VA_SURFACE_IMPL_EGL_MAGIC VA_FOURCC('V','E','G','L')
161 struct VASurfaceImplEGL {
162 uint32_t magic; ///< Magic number identifying a VASurfaceImplEGL
163 VASurfaceID surface; ///< Associated VA surface
164 EGLenum target; ///< EGL target
165 EGLClientBuffer buffer;
172 create_native_pixmap(VADisplay dpy, unsigned int width, unsigned int height)
174 VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
176 void *native_pixmap = NULL;
178 status = pDisplayContext->vaCreateNativePixmap(pDisplayContext, width, height, &native_pixmap);
180 if (status != VA_STATUS_SUCCESS)
181 native_pixmap = NULL;
183 return native_pixmap;
187 destroy_native_pixmap(VADisplay dpy, void *native_pixmap)
189 VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
191 pDisplayContext->vaFreeNativePixmap(pDisplayContext, native_pixmap);
194 // Check VASurfaceImplEGL is valid
195 static inline int check_surface(VASurfaceImplEGLP pSurfaceImplEGL)
197 return pSurfaceImplEGL && pSurfaceImplEGL->magic == VA_SURFACE_IMPL_EGL_MAGIC;
200 static inline VAStatus
201 deassociate_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
203 pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
205 return VA_STATUS_SUCCESS;
209 associate_surface(VADriverContextP ctx,
210 VASurfaceImplEGLP pSurfaceImplEGL,
215 status = deassociate_surface(ctx, pSurfaceImplEGL);
217 if (status != VA_STATUS_SUCCESS)
220 pSurfaceImplEGL->surface = surface;
221 pSurfaceImplEGL->flags = flags;
223 return VA_STATUS_SUCCESS;
226 static inline VAStatus
227 sync_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
229 if (pSurfaceImplEGL->surface == VA_INVALID_SURFACE)
230 return VA_STATUS_ERROR_INVALID_SURFACE;
232 return ctx->vtable->vaSyncSurface(ctx, pSurfaceImplEGL->surface);
236 sync_associated_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
240 status = sync_surface(ctx, pSurfaceImplEGL);
242 if (status != VA_STATUS_SUCCESS)
245 if (pSurfaceImplEGL->target != EGL_NATIVE_PIXMAP_KHR)
246 return VA_STATUS_ERROR_UNIMPLEMENTED;
248 status = ctx->vtable->vaPutSurface(
250 pSurfaceImplEGL->surface,
251 (void *)pSurfaceImplEGL->buffer,
252 0, 0, pSurfaceImplEGL->width, pSurfaceImplEGL->height,
253 0, 0, pSurfaceImplEGL->width, pSurfaceImplEGL->height,
255 pSurfaceImplEGL->flags
258 if (status == VA_STATUS_SUCCESS) {
259 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
265 /* ========================================================================= */
266 /* === VA/EGL implementation from libVA (generic and suboptimal path) === */
267 /* ========================================================================= */
272 #define INIT_SURFACE(surface, egl_surface) do { \
273 surface = (VASurfaceImplEGLP)(egl_surface); \
274 if (!check_surface(surface)) \
275 return VA_STATUS_ERROR_INVALID_SURFACE; \
279 vaQuerySurfaceTargetsEGL_impl_libva(VADisplay dpy,
280 EGLenum *target_list,
285 /* FIXME: support other targets ??? */
286 target_list[i++] = EGL_NATIVE_PIXMAP_KHR;
288 assert(i <= IMPL_MAX_EGL_SURFACE_TARGETS);
290 return VA_STATUS_SUCCESS;
294 vaCreateSurfaceEGL_impl_libva(VADisplay dpy,
298 VASurfaceEGL *egl_surface)
300 VASurfaceImplEGLP pSurfaceImplEGL = NULL;
302 /* So far only support for EGL_NATIVE_PIXMAP_KHR */
303 if (target != 0 && target != EGL_NATIVE_PIXMAP_KHR)
304 return VA_STATUS_ERROR_INVALID_PARAMETER;
306 pSurfaceImplEGL = calloc(1, sizeof(*pSurfaceImplEGL));
308 if (!pSurfaceImplEGL) {
310 return VA_STATUS_ERROR_ALLOCATION_FAILED;
313 pSurfaceImplEGL->magic = VA_SURFACE_IMPL_EGL_MAGIC;
314 pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
315 pSurfaceImplEGL->target = target == 0 ? EGL_NATIVE_PIXMAP_KHR : target;
316 pSurfaceImplEGL->buffer = 0;
317 pSurfaceImplEGL->width = width;
318 pSurfaceImplEGL->height = height;
319 *egl_surface = (VASurfaceEGL)pSurfaceImplEGL;
321 return VA_STATUS_SUCCESS;
325 vaDestroySurfaceEGL_impl_libva(VADisplay dpy, VASurfaceEGL egl_surface)
327 VASurfaceImplEGLP pSurfaceImplEGL;
329 INIT_SURFACE(pSurfaceImplEGL, egl_surface);
331 if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
332 if (pSurfaceImplEGL->buffer) {
333 destroy_native_pixmap(dpy, pSurfaceImplEGL->buffer);
334 pSurfaceImplEGL->buffer = 0;
338 free(pSurfaceImplEGL);
340 return VA_STATUS_SUCCESS;
344 vaAssociateSurfaceEGL_impl_libva(
346 VASurfaceEGL egl_surface,
351 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
352 VASurfaceImplEGLP pSurfaceImplEGL;
355 INIT_SURFACE(pSurfaceImplEGL, egl_surface);
357 if (surface == VA_INVALID_SURFACE)
358 return VA_STATUS_ERROR_INVALID_SURFACE;
360 if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
361 if (pSurfaceImplEGL->buffer)
362 destroy_native_pixmap(dpy, pSurfaceImplEGL->buffer);
364 pSurfaceImplEGL->buffer = create_native_pixmap(dpy, pSurfaceImplEGL->width, pSurfaceImplEGL->height);
367 pSurfaceImplEGL->surface = surface;
368 pSurfaceImplEGL->flags = flags;
370 if (pSurfaceImplEGL->buffer)
371 return VA_STATUS_SUCCESS;
373 return VA_STATUS_ERROR_UNKNOWN;
377 vaSyncSurfaceEGL_impl_libva(VADisplay dpy,
378 VASurfaceEGL egl_surface)
380 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
381 VASurfaceImplEGLP pSurfaceImplEGL;
384 INIT_SURFACE(pSurfaceImplEGL, egl_surface);
386 status = sync_associated_surface(ctx, pSurfaceImplEGL);
392 vaGetSurfaceInfoEGL_impl_libva(VADisplay dpy,
393 VASurfaceEGL egl_surface,
395 EGLClientBuffer *buffer,
399 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
400 VASurfaceImplEGLP pSurfaceImplEGL;
404 INIT_SURFACE(pSurfaceImplEGL, egl_surface);
406 if (pSurfaceImplEGL->surface == VA_INVALID_SURFACE)
407 return VA_STATUS_ERROR_INVALID_SURFACE;
409 if (*num_attribs < IMPL_MAX_EGL_SURFACE_ATTRIBUTES)
410 return VA_STATUS_ERROR_INVALID_PARAMETER;
412 *target = pSurfaceImplEGL->target;
413 *buffer = pSurfaceImplEGL->buffer;
415 if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
416 attrib_list[i++] = EGL_IMAGE_PRESERVED_KHR;
417 attrib_list[i + 1] = EGL_TRUE;
418 attrib_list[i++] = EGL_NONE;
421 attrib_list[i++] = EGL_NONE;
426 return VA_STATUS_SUCCESS;
430 vaDeassociateSurfaceEGL_impl_libva(
432 VASurfaceEGL egl_surface
435 VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
436 VASurfaceImplEGLP pSurfaceImplEGL;
439 INIT_SURFACE(pSurfaceImplEGL, egl_surface);
441 if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
442 if (pSurfaceImplEGL->buffer)
443 destroy_native_pixmap(dpy, pSurfaceImplEGL->buffer);
445 pSurfaceImplEGL->buffer = 0;
448 pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
450 return VA_STATUS_SUCCESS;
455 /* ========================================================================= */
456 /* === Private VA/EGL vtable initialization === */
457 /* ========================================================================= */
459 // Initialize EGL driver context
460 VAStatus va_egl_init_context(VADisplay dpy)
462 VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
463 VADriverContextP ctx = pDisplayContext->pDriverContext;
464 VADriverContextEGLP egl_ctx = VA_DRIVER_CONTEXT_EGL(ctx);
465 VADriverVTablePrivEGLP vtable = &egl_ctx->vtable;
467 if (egl_ctx->is_initialized)
468 return VA_STATUS_SUCCESS;
470 if (ctx->vtable_egl && ctx->vtable_egl->vaCreateSurfaceEGL) {
471 vtable->vaQuerySurfaceTargetsEGL = vaQuerySurfaceTargetsEGL_impl_driver;
472 vtable->vaCreateSurfaceEGL = vaCreateSurfaceEGL_impl_driver;
473 vtable->vaDestroySurfaceEGL = vaDestroySurfaceEGL_impl_driver;
474 vtable->vaAssociateSurfaceEGL = vaAssociateSurfaceEGL_impl_driver;
475 vtable->vaSyncSurfaceEGL = vaSyncSurfaceEGL_impl_driver;
476 vtable->vaGetSurfaceInfoEGL = vaGetSurfaceInfoEGL_impl_driver;
477 vtable->vaDeassociateSurfaceEGL = vaDeassociateSurfaceEGL_impl_driver;
480 if (pDisplayContext->vaCreateNativePixmap == NULL ||
481 pDisplayContext->vaFreeNativePixmap == NULL)
482 return VA_STATUS_ERROR_UNIMPLEMENTED;
484 if (!check_pixmap_extensions(ctx, egl_ctx->egl_display))
485 return VA_STATUS_ERROR_UNIMPLEMENTED;
487 vtable->vaQuerySurfaceTargetsEGL = vaQuerySurfaceTargetsEGL_impl_libva;
488 vtable->vaCreateSurfaceEGL = vaCreateSurfaceEGL_impl_libva;
489 vtable->vaDestroySurfaceEGL = vaDestroySurfaceEGL_impl_libva;
490 vtable->vaAssociateSurfaceEGL = vaAssociateSurfaceEGL_impl_libva;
491 vtable->vaSyncSurfaceEGL = vaSyncSurfaceEGL_impl_libva;
492 vtable->vaGetSurfaceInfoEGL = vaGetSurfaceInfoEGL_impl_libva;
493 vtable->vaDeassociateSurfaceEGL = vaDeassociateSurfaceEGL_impl_libva;
496 egl_ctx->is_initialized = 1;
498 return VA_STATUS_SUCCESS;