2 * Copyright (c) 2007 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "va_backend.h"
29 #include "va_backend_vpp.h"
41 #define DRIVER_EXTENSION "_drv_video.so"
43 #define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext)
44 #define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; }
47 #define CHECK_VTABLE(s, ctx, func) if (!va_checkVtable(ctx->vtable->va##func, #func)) s = VA_STATUS_ERROR_UNKNOWN;
48 #define CHECK_MAXIMUM(s, ctx, var) if (!va_checkMaximum(ctx->max_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN;
49 #define CHECK_STRING(s, ctx, var) if (!va_checkString(ctx->str_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN;
52 * read a config "env" for libva.conf or from environment setting
53 * liva.conf has higher priority
54 * return 0: the "env" is set, and the value is copied into env_value
55 * 1: the env is not set
57 int va_parseConfig(char *env, char *env_value)
59 char *token, *value, *saveptr;
66 fp = fopen("/etc/libva.conf", "r");
67 while (fp && (fgets(oneline, 1024, fp) != NULL)) {
68 if (strlen(oneline) == 1)
70 token = strtok_r(oneline, "=\n", &saveptr);
71 value = strtok_r(NULL, "=\n", &saveptr);
73 if (NULL == token || NULL == value)
76 if (strcmp(token, env) == 0) {
78 strncpy(env_value,value, 1024);
79 env_value[1023] = '\0';
90 /* no setting in config file, use env setting */
94 strncpy(env_value, value, 1024);
95 env_value[1023] = '\0';
103 int vaDisplayIsValid(VADisplay dpy)
105 VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
106 return pDisplayContext && (pDisplayContext->vadpy_magic == VA_DISPLAY_MAGIC) && pDisplayContext->vaIsValid(pDisplayContext);
109 void va_errorMessage(const char *msg, ...)
111 char buf[512], *dynbuf;
116 len = vsnprintf(buf, sizeof(buf), msg, args);
119 if (len >= (int)sizeof(buf)) {
120 dynbuf = malloc(len + 1);
124 n = vsnprintf(dynbuf, len + 1, msg, args);
127 va_log_error(dynbuf);
134 void va_infoMessage(const char *msg, ...)
136 char buf[512], *dynbuf;
141 len = vsnprintf(buf, sizeof(buf), msg, args);
144 if (len >= (int)sizeof(buf)) {
145 dynbuf = malloc(len + 1);
149 n = vsnprintf(dynbuf, len + 1, msg, args);
159 static bool va_checkVtable(void *ptr, char *function)
162 va_errorMessage("No valid vtable entry for va%s\n", function);
168 static bool va_checkMaximum(int value, char *variable)
171 va_errorMessage("Failed to define max_%s in init\n", variable);
177 static bool va_checkString(const char* value, char *variable)
180 va_errorMessage("Failed to define str_%s in init\n", variable);
187 va_getDriverInitName(char *name, int namelen, int major, int minor)
189 int ret = snprintf(name, namelen, "__vaDriverInit_%d_%d", major, minor);
190 return ret > 0 && ret < namelen;
193 static VAStatus va_getDriverName(VADisplay dpy, char **driver_name)
195 VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
197 return pDisplayContext->vaGetDriverName(pDisplayContext, driver_name);
200 static VAStatus va_openDriver(VADisplay dpy, char *driver_name)
202 VADriverContextP ctx = CTX(dpy);
203 VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
204 char *search_path = NULL;
208 if (geteuid() == getuid())
209 /* don't allow setuid apps to use LIBVA_DRIVERS_PATH */
210 search_path = getenv("LIBVA_DRIVERS_PATH");
212 search_path = VA_DRIVERS_PATH;
214 search_path = strdup((const char *)search_path);
215 driver_dir = strtok_r(search_path, ":", &saveptr);
218 char *driver_path = (char *) malloc( strlen(driver_dir) +
219 strlen(driver_name) +
220 strlen(DRIVER_EXTENSION) + 2 );
222 va_errorMessage("%s L%d Out of memory!n",
223 __FUNCTION__, __LINE__);
225 return VA_STATUS_ERROR_ALLOCATION_FAILED;
228 strncpy( driver_path, driver_dir, strlen(driver_dir) + 1);
229 strncat( driver_path, "/", strlen("/") );
230 strncat( driver_path, driver_name, strlen(driver_name) );
231 strncat( driver_path, DRIVER_EXTENSION, strlen(DRIVER_EXTENSION) );
233 va_infoMessage("Trying to open %s\n", driver_path);
235 handle = dlopen( driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE );
237 handle = dlopen( driver_path, RTLD_NOW| RTLD_GLOBAL);
240 /* Don't give errors for non-existing files */
241 if (0 == access( driver_path, F_OK))
242 va_errorMessage("dlopen of %s failed: %s\n", driver_path, dlerror());
244 VADriverInit init_func = NULL;
245 char init_func_s[256];
248 static const struct {
251 } compatible_versions[] = {
252 { VA_MAJOR_VERSION, VA_MINOR_VERSION },
263 for (i = 0; compatible_versions[i].major >= 0; i++) {
264 if (va_getDriverInitName(init_func_s, sizeof(init_func_s),
265 compatible_versions[i].major,
266 compatible_versions[i].minor)) {
267 init_func = (VADriverInit)dlsym(handle, init_func_s);
269 va_infoMessage("Found init function %s\n", init_func_s);
275 if (compatible_versions[i].major < 0) {
276 va_errorMessage("%s has no function %s\n",
277 driver_path, init_func_s);
280 struct VADriverVTable *vtable = ctx->vtable;
281 struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp;
283 vaStatus = VA_STATUS_SUCCESS;
285 vtable = calloc(1, sizeof(*vtable));
287 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
289 ctx->vtable = vtable;
292 vtable_vpp = calloc(1, sizeof(*vtable_vpp));
294 vtable_vpp->version = VA_DRIVER_VTABLE_VPP_VERSION;
296 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
298 ctx->vtable_vpp = vtable_vpp;
300 if (init_func && VA_STATUS_SUCCESS == vaStatus)
301 vaStatus = (*init_func)(ctx);
303 if (VA_STATUS_SUCCESS == vaStatus) {
304 CHECK_MAXIMUM(vaStatus, ctx, profiles);
305 CHECK_MAXIMUM(vaStatus, ctx, entrypoints);
306 CHECK_MAXIMUM(vaStatus, ctx, attributes);
307 CHECK_MAXIMUM(vaStatus, ctx, image_formats);
308 CHECK_MAXIMUM(vaStatus, ctx, subpic_formats);
309 CHECK_MAXIMUM(vaStatus, ctx, display_attributes);
310 CHECK_STRING(vaStatus, ctx, vendor);
311 CHECK_VTABLE(vaStatus, ctx, Terminate);
312 CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles);
313 CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints);
314 CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes);
315 CHECK_VTABLE(vaStatus, ctx, CreateConfig);
316 CHECK_VTABLE(vaStatus, ctx, DestroyConfig);
317 CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes);
318 CHECK_VTABLE(vaStatus, ctx, CreateSurfaces);
319 CHECK_VTABLE(vaStatus, ctx, DestroySurfaces);
320 CHECK_VTABLE(vaStatus, ctx, CreateContext);
321 CHECK_VTABLE(vaStatus, ctx, DestroyContext);
322 CHECK_VTABLE(vaStatus, ctx, CreateBuffer);
323 CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements);
324 CHECK_VTABLE(vaStatus, ctx, MapBuffer);
325 CHECK_VTABLE(vaStatus, ctx, UnmapBuffer);
326 CHECK_VTABLE(vaStatus, ctx, DestroyBuffer);
327 CHECK_VTABLE(vaStatus, ctx, BeginPicture);
328 CHECK_VTABLE(vaStatus, ctx, RenderPicture);
329 CHECK_VTABLE(vaStatus, ctx, EndPicture);
330 CHECK_VTABLE(vaStatus, ctx, SyncSurface);
331 CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus);
332 CHECK_VTABLE(vaStatus, ctx, PutSurface);
333 CHECK_VTABLE(vaStatus, ctx, QueryImageFormats);
334 CHECK_VTABLE(vaStatus, ctx, CreateImage);
335 CHECK_VTABLE(vaStatus, ctx, DeriveImage);
336 CHECK_VTABLE(vaStatus, ctx, DestroyImage);
337 CHECK_VTABLE(vaStatus, ctx, SetImagePalette);
338 CHECK_VTABLE(vaStatus, ctx, GetImage);
339 CHECK_VTABLE(vaStatus, ctx, PutImage);
340 CHECK_VTABLE(vaStatus, ctx, QuerySubpictureFormats);
341 CHECK_VTABLE(vaStatus, ctx, CreateSubpicture);
342 CHECK_VTABLE(vaStatus, ctx, DestroySubpicture);
343 CHECK_VTABLE(vaStatus, ctx, SetSubpictureImage);
344 CHECK_VTABLE(vaStatus, ctx, SetSubpictureChromakey);
345 CHECK_VTABLE(vaStatus, ctx, SetSubpictureGlobalAlpha);
346 CHECK_VTABLE(vaStatus, ctx, AssociateSubpicture);
347 CHECK_VTABLE(vaStatus, ctx, DeassociateSubpicture);
348 CHECK_VTABLE(vaStatus, ctx, QueryDisplayAttributes);
349 CHECK_VTABLE(vaStatus, ctx, GetDisplayAttributes);
350 CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes);
352 if (VA_STATUS_SUCCESS != vaStatus) {
353 va_errorMessage("%s init failed\n", driver_path);
356 if (VA_STATUS_SUCCESS == vaStatus)
357 ctx->handle = handle;
364 driver_dir = strtok_r(NULL, ":", &saveptr);
372 VAPrivFunc vaGetLibFunc(VADisplay dpy, const char *func)
374 VADriverContextP ctx;
375 if (!vaDisplayIsValid(dpy))
379 if (NULL == ctx->handle)
382 return (VAPrivFunc) dlsym(ctx->handle, func);
387 * Returns a short english description of error_status
389 const char *vaErrorStr(VAStatus error_status)
391 switch(error_status) {
392 case VA_STATUS_SUCCESS:
393 return "success (no error)";
394 case VA_STATUS_ERROR_OPERATION_FAILED:
395 return "operation failed";
396 case VA_STATUS_ERROR_ALLOCATION_FAILED:
397 return "resource allocation failed";
398 case VA_STATUS_ERROR_INVALID_DISPLAY:
399 return "invalid VADisplay";
400 case VA_STATUS_ERROR_INVALID_CONFIG:
401 return "invalid VAConfigID";
402 case VA_STATUS_ERROR_INVALID_CONTEXT:
403 return "invalid VAContextID";
404 case VA_STATUS_ERROR_INVALID_SURFACE:
405 return "invalid VASurfaceID";
406 case VA_STATUS_ERROR_INVALID_BUFFER:
407 return "invalid VABufferID";
408 case VA_STATUS_ERROR_INVALID_IMAGE:
409 return "invalid VAImageID";
410 case VA_STATUS_ERROR_INVALID_SUBPICTURE:
411 return "invalid VASubpictureID";
412 case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
413 return "attribute not supported";
414 case VA_STATUS_ERROR_MAX_NUM_EXCEEDED:
415 return "list argument exceeds maximum number";
416 case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
417 return "the requested VAProfile is not supported";
418 case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
419 return "the requested VAEntryPoint is not supported";
420 case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
421 return "the requested RT Format is not supported";
422 case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
423 return "the requested VABufferType is not supported";
424 case VA_STATUS_ERROR_SURFACE_BUSY:
425 return "surface is in use";
426 case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED:
427 return "flag not supported";
428 case VA_STATUS_ERROR_INVALID_PARAMETER:
429 return "invalid parameter";
430 case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED:
431 return "resolution not supported";
432 case VA_STATUS_ERROR_UNIMPLEMENTED:
433 return "the requested function is not implemented";
434 case VA_STATUS_ERROR_SURFACE_IN_DISPLAYING:
435 return "surface is in displaying (may by overlay)" ;
436 case VA_STATUS_ERROR_INVALID_IMAGE_FORMAT:
437 return "invalid VAImageFormat";
438 case VA_STATUS_ERROR_INVALID_VALUE:
439 return "an invalid/unsupported value was supplied";
440 case VA_STATUS_ERROR_UNSUPPORTED_FILTER:
441 return "the requested filter is not supported";
442 case VA_STATUS_ERROR_INVALID_FILTER_CHAIN:
443 return "an invalid filter chain was supplied";
444 case VA_STATUS_ERROR_UNKNOWN:
445 return "unknown libva error";
447 return "unknown libva error / description missing";
450 const static char *prefer_driver_list[4] = {
457 VAStatus vaSetDriverName(
462 VADriverContextP ctx;
463 VAStatus vaStatus = VA_STATUS_SUCCESS;
464 char *override_driver_name = NULL;
468 if (geteuid() != getuid()) {
469 vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
470 va_errorMessage("no permission to vaSetDriverName\n");
474 if (strlen(driver_name) == 0 || strlen(driver_name) >=256) {
475 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
476 va_errorMessage("vaSetDriverName returns %s\n",
477 vaErrorStr(vaStatus));
482 for (i = 0; i < sizeof(prefer_driver_list) / sizeof(char *); i++) {
483 if (strlen(prefer_driver_list[i]) != strlen(driver_name))
485 if (!strncmp(prefer_driver_list[i], driver_name, strlen(driver_name))) {
492 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
493 va_errorMessage("vaSetDriverName returns %s. Incorrect parameter\n",
494 vaErrorStr(vaStatus));
498 override_driver_name = strdup(driver_name);
500 if (!override_driver_name) {
501 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
502 va_errorMessage("vaSetDriverName returns %s. Out of Memory\n",
503 vaErrorStr(vaStatus));
507 ctx->override_driver_name = override_driver_name;
508 return VA_STATUS_SUCCESS;
511 VAStatus vaInitialize (
513 int *major_version, /* out */
514 int *minor_version /* out */
517 const char *driver_name_env = NULL;
518 char *driver_name = NULL;
520 VADriverContextP ctx;
530 va_infoMessage("VA-API version %s\n", VA_VERSION_S);
532 vaStatus = va_getDriverName(dpy, &driver_name);
534 if (!ctx->override_driver_name) {
535 va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
537 driver_name_env = getenv("LIBVA_DRIVER_NAME");
538 } else if (vaStatus == VA_STATUS_SUCCESS) {
542 driver_name = strdup(ctx->override_driver_name);
544 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
545 va_errorMessage("vaInitialize() failed with %s, out of memory\n",
546 vaErrorStr(vaStatus));
549 va_infoMessage("User requested driver '%s'\n", driver_name);
552 if (driver_name_env && (geteuid() == getuid())) {
553 /* Don't allow setuid apps to use LIBVA_DRIVER_NAME */
554 if (driver_name) /* memory is allocated in va_getDriverName */
557 driver_name = strdup(driver_name_env);
558 vaStatus = VA_STATUS_SUCCESS;
559 va_infoMessage("User requested driver '%s'\n", driver_name);
562 if ((VA_STATUS_SUCCESS == vaStatus) && (driver_name != NULL)) {
563 vaStatus = va_openDriver(dpy, driver_name);
564 va_infoMessage("va_openDriver() returns %d\n", vaStatus);
566 *major_version = VA_MAJOR_VERSION;
567 *minor_version = VA_MINOR_VERSION;
569 va_errorMessage("va_getDriverName() failed with %s,driver_name=%s\n",
570 vaErrorStr(vaStatus), driver_name);
575 VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version);
582 * After this call, all library internal resources will be cleaned up
584 VAStatus vaTerminate (
588 VAStatus vaStatus = VA_STATUS_SUCCESS;
589 VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
590 VADriverContextP old_ctx;
595 if (old_ctx->handle) {
596 vaStatus = old_ctx->vtable->vaTerminate(old_ctx);
597 dlclose(old_ctx->handle);
598 old_ctx->handle = NULL;
600 free(old_ctx->vtable);
601 old_ctx->vtable = NULL;
602 free(old_ctx->vtable_vpp);
603 old_ctx->vtable_vpp = NULL;
605 if (old_ctx->override_driver_name) {
606 free(old_ctx->override_driver_name);
607 old_ctx->override_driver_name = NULL;
610 VA_TRACE_LOG(va_TraceTerminate, dpy);
616 if (VA_STATUS_SUCCESS == vaStatus)
617 pDisplayContext->vaDestroy(pDisplayContext);
623 * vaQueryVendorString returns a pointer to a zero-terminated string
624 * describing some aspects of the VA implemenation on a specific
625 * hardware accelerator. The format of the returned string is:
626 * <vendorname>-<major_version>-<minor_version>-<addtional_info>
627 * e.g. for the Intel GMA500 implementation, an example would be:
628 * "IntelGMA500-1.0-0.2-patch3
630 const char *vaQueryVendorString (
634 if (!vaDisplayIsValid(dpy))
637 return CTX(dpy)->str_vendor;
641 /* Get maximum number of profiles supported by the implementation */
642 int vaMaxNumProfiles (
646 if (!vaDisplayIsValid(dpy))
649 return CTX(dpy)->max_profiles;
652 /* Get maximum number of entrypoints supported by the implementation */
653 int vaMaxNumEntrypoints (
657 if (!vaDisplayIsValid(dpy))
660 return CTX(dpy)->max_entrypoints;
664 /* Get maximum number of attributs supported by the implementation */
665 int vaMaxNumConfigAttributes (
669 if (!vaDisplayIsValid(dpy))
672 return CTX(dpy)->max_attributes;
675 VAStatus vaQueryConfigEntrypoints (
678 VAEntrypoint *entrypoints, /* out */
679 int *num_entrypoints /* out */
682 VADriverContextP ctx;
686 return ctx->vtable->vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
689 VAStatus vaGetConfigAttributes (
692 VAEntrypoint entrypoint,
693 VAConfigAttrib *attrib_list, /* in/out */
697 VADriverContextP ctx;
701 return ctx->vtable->vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
704 VAStatus vaQueryConfigProfiles (
706 VAProfile *profile_list, /* out */
707 int *num_profiles /* out */
710 VADriverContextP ctx;
714 return ctx->vtable->vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
717 VAStatus vaCreateConfig (
720 VAEntrypoint entrypoint,
721 VAConfigAttrib *attrib_list,
723 VAConfigID *config_id /* out */
726 VADriverContextP ctx;
727 VAStatus vaStatus = VA_STATUS_SUCCESS;
732 vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
734 /* record the current entrypoint for further trace/fool determination */
735 VA_TRACE_ALL(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
736 VA_FOOL_FUNC(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
741 VAStatus vaDestroyConfig (
746 VADriverContextP ctx;
747 VAStatus vaStatus = VA_STATUS_SUCCESS;
752 vaStatus = ctx->vtable->vaDestroyConfig ( ctx, config_id );
754 VA_TRACE_ALL(va_TraceDestroyConfig, dpy, config_id);
759 VAStatus vaQueryConfigAttributes (
761 VAConfigID config_id,
762 VAProfile *profile, /* out */
763 VAEntrypoint *entrypoint, /* out */
764 VAConfigAttrib *attrib_list,/* out */
765 int *num_attribs /* out */
768 VADriverContextP ctx;
772 return ctx->vtable->vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
775 /* XXX: this is a slow implementation that will be removed */
777 va_impl_query_surface_attributes(
778 VADriverContextP ctx,
780 VASurfaceAttrib *out_attribs,
781 unsigned int *out_num_attribs_ptr
784 VASurfaceAttrib *attribs = NULL;
785 unsigned int num_attribs, n;
786 VASurfaceAttrib *out_attrib;
787 unsigned int out_num_attribs;
788 VAImageFormat *image_formats = NULL;
789 int num_image_formats, i;
792 /* List of surface attributes to query */
793 struct va_surface_attrib_map {
794 VASurfaceAttribType type;
795 VAGenericValueType value_type;
797 static const struct va_surface_attrib_map attribs_map[] = {
798 { VASurfaceAttribMinWidth, VAGenericValueTypeInteger },
799 { VASurfaceAttribMaxWidth, VAGenericValueTypeInteger },
800 { VASurfaceAttribMinHeight, VAGenericValueTypeInteger },
801 { VASurfaceAttribMaxHeight, VAGenericValueTypeInteger },
802 { VASurfaceAttribMemoryType, VAGenericValueTypeInteger },
803 { VASurfaceAttribNone, }
806 if (!out_attribs || !out_num_attribs_ptr)
807 return VA_STATUS_ERROR_INVALID_PARAMETER;
808 if (!ctx->vtable->vaGetSurfaceAttributes)
809 return VA_STATUS_ERROR_UNIMPLEMENTED;
811 num_image_formats = ctx->max_image_formats;
812 image_formats = malloc(num_image_formats * sizeof(*image_formats));
813 if (!image_formats) {
814 va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
818 va_status = ctx->vtable->vaQueryImageFormats(
819 ctx, image_formats, &num_image_formats);
820 if (va_status != VA_STATUS_SUCCESS)
823 num_attribs = VASurfaceAttribCount + num_image_formats;
824 attribs = malloc(num_attribs * sizeof(*attribs));
826 va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
830 /* Initialize with base surface attributes, except pixel-formats */
831 for (n = 0; attribs_map[n].type != VASurfaceAttribNone; n++) {
832 VASurfaceAttrib * const attrib = &attribs[n];
833 attrib->type = attribs_map[n].type;
834 attrib->flags = VA_SURFACE_ATTRIB_GETTABLE;
835 attrib->value.type = attribs_map[n].value_type;
838 /* Append image formats */
839 for (i = 0; i < num_image_formats; i++) {
840 VASurfaceAttrib * const attrib = &attribs[n];
841 attrib->type = VASurfaceAttribPixelFormat;
842 attrib->flags = VA_SURFACE_ATTRIB_GETTABLE|VA_SURFACE_ATTRIB_SETTABLE;
843 attrib->value.type = VAGenericValueTypeInteger;
844 attrib->value.value.i = image_formats[i].fourcc;
845 if (++n == num_attribs) {
846 va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
852 va_status = ctx->vtable->vaGetSurfaceAttributes(
853 ctx, config, attribs, num_attribs);
854 if (va_status != VA_STATUS_SUCCESS)
857 /* Remove invalid entries */
859 for (n = 0; n < num_attribs; n++) {
860 VASurfaceAttrib * const attrib = &attribs[n];
862 if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
865 // Accept all surface attributes that are not pixel-formats
866 if (attrib->type != VASurfaceAttribPixelFormat) {
871 // Drop invalid pixel-format attribute
872 if (!attrib->value.value.i) {
873 attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
877 // Check for duplicates
878 int is_duplicate = 0;
879 for (i = n - 1; i >= 0 && !is_duplicate; i--) {
880 const VASurfaceAttrib * const prev_attrib = &attribs[i];
881 if (prev_attrib->type != VASurfaceAttribPixelFormat)
883 is_duplicate = prev_attrib->value.value.i == attrib->value.value.i;
886 attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
891 if (*out_num_attribs_ptr < out_num_attribs) {
892 *out_num_attribs_ptr = out_num_attribs;
893 va_status = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
897 out_attrib = out_attribs;
898 for (n = 0; n < num_attribs; n++) {
899 const VASurfaceAttrib * const attrib = &attribs[n];
900 if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
902 *out_attrib++ = *attrib;
912 vaQuerySurfaceAttributes(
915 VASurfaceAttrib *attrib_list,
916 unsigned int *num_attribs
919 VADriverContextP ctx;
925 return VA_STATUS_ERROR_INVALID_DISPLAY;
927 if (!ctx->vtable->vaQuerySurfaceAttributes)
928 vaStatus = va_impl_query_surface_attributes(ctx, config,
929 attrib_list, num_attribs);
931 vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
932 attrib_list, num_attribs);
934 VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs);
945 VASurfaceID *surfaces,
946 unsigned int num_surfaces,
947 VASurfaceAttrib *attrib_list,
948 unsigned int num_attribs
951 VADriverContextP ctx;
957 return VA_STATUS_ERROR_INVALID_DISPLAY;
959 if (ctx->vtable->vaCreateSurfaces2)
960 vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
961 surfaces, num_surfaces,
962 attrib_list, num_attribs);
963 else if (attrib_list && num_attribs > 0)
964 vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
966 vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
967 num_surfaces, surfaces);
968 VA_TRACE_LOG(va_TraceCreateSurfaces,
969 dpy, width, height, format, num_surfaces, surfaces,
970 attrib_list, num_attribs);
976 VAStatus vaDestroySurfaces (
978 VASurfaceID *surface_list,
982 VADriverContextP ctx;
988 VA_TRACE_LOG(va_TraceDestroySurfaces,
989 dpy, surface_list, num_surfaces);
991 vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
996 VAStatus vaCreateContext (
998 VAConfigID config_id,
1002 VASurfaceID *render_targets,
1003 int num_render_targets,
1004 VAContextID *context /* out */
1007 VADriverContextP ctx;
1013 vaStatus = ctx->vtable->vaCreateContext( ctx, config_id, picture_width, picture_height,
1014 flag, render_targets, num_render_targets, context );
1016 /* keep current encode/decode resoluton */
1017 VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context);
1022 VAStatus vaDestroyContext (
1027 VADriverContextP ctx;
1033 vaStatus = ctx->vtable->vaDestroyContext( ctx, context );
1035 VA_TRACE_ALL(va_TraceDestroyContext, dpy, context);
1040 VAStatus vaCreateBuffer (
1042 VAContextID context, /* in */
1043 VABufferType type, /* in */
1044 unsigned int size, /* in */
1045 unsigned int num_elements, /* in */
1046 void *data, /* in */
1047 VABufferID *buf_id /* out */
1050 VADriverContextP ctx;
1056 VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id);
1058 vaStatus = ctx->vtable->vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id);
1060 VA_TRACE_LOG(va_TraceCreateBuffer,
1061 dpy, context, type, size, num_elements, data, buf_id);
1066 VAStatus vaBufferSetNumElements (
1068 VABufferID buf_id, /* in */
1069 unsigned int num_elements /* in */
1072 VADriverContextP ctx;
1076 VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1078 return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements );
1082 VAStatus vaMapBuffer (
1084 VABufferID buf_id, /* in */
1085 void **pbuf /* out */
1088 VADriverContextP ctx;
1094 VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf);
1096 va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf );
1098 VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf);
1103 VAStatus vaUnmapBuffer (
1105 VABufferID buf_id /* in */
1108 VADriverContextP ctx;
1112 VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1114 return ctx->vtable->vaUnmapBuffer( ctx, buf_id );
1117 VAStatus vaDestroyBuffer (
1119 VABufferID buffer_id
1122 VADriverContextP ctx;
1126 VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1128 VA_TRACE_LOG(va_TraceDestroyBuffer,
1131 return ctx->vtable->vaDestroyBuffer( ctx, buffer_id );
1134 VAStatus vaBufferInfo (
1136 VAContextID context, /* in */
1137 VABufferID buf_id, /* in */
1138 VABufferType *type, /* out */
1139 unsigned int *size, /* out */
1140 unsigned int *num_elements /* out */
1143 VADriverContextP ctx;
1148 VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements);
1150 return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements );
1153 /* Locks buffer for external API usage */
1155 vaAcquireBufferHandle(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info)
1157 VADriverContextP ctx;
1162 if (!ctx->vtable->vaAcquireBufferHandle)
1163 return VA_STATUS_ERROR_UNIMPLEMENTED;
1164 return ctx->vtable->vaAcquireBufferHandle(ctx, buf_id, buf_info);
1167 /* Unlocks buffer after usage from external API */
1169 vaReleaseBufferHandle(VADisplay dpy, VABufferID buf_id)
1171 VADriverContextP ctx;
1176 if (!ctx->vtable->vaReleaseBufferHandle)
1177 return VA_STATUS_ERROR_UNIMPLEMENTED;
1178 return ctx->vtable->vaReleaseBufferHandle(ctx, buf_id);
1181 VAStatus vaBeginPicture (
1183 VAContextID context,
1184 VASurfaceID render_target
1187 VADriverContextP ctx;
1193 VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target);
1194 VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1196 va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target );
1201 VAStatus vaRenderPicture (
1203 VAContextID context,
1204 VABufferID *buffers,
1208 VADriverContextP ctx;
1213 VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
1214 VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1216 return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers );
1219 VAStatus vaEndPicture (
1224 VAStatus va_status = VA_STATUS_SUCCESS;
1225 VADriverContextP ctx;
1230 VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1232 va_status = ctx->vtable->vaEndPicture( ctx, context );
1234 /* dump surface content */
1235 VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1);
1240 VAStatus vaSyncSurface (
1242 VASurfaceID render_target
1246 VADriverContextP ctx;
1251 va_status = ctx->vtable->vaSyncSurface( ctx, render_target );
1252 VA_TRACE_LOG(va_TraceSyncSurface, dpy, render_target);
1257 VAStatus vaQuerySurfaceStatus (
1259 VASurfaceID render_target,
1260 VASurfaceStatus *status /* out */
1264 VADriverContextP ctx;
1268 va_status = ctx->vtable->vaQuerySurfaceStatus( ctx, render_target, status );
1270 VA_TRACE_LOG(va_TraceQuerySurfaceStatus, dpy, render_target, status);
1275 VAStatus vaQuerySurfaceError (
1277 VASurfaceID surface,
1278 VAStatus error_status,
1279 void **error_info /*out*/
1283 VADriverContextP ctx;
1287 va_status = ctx->vtable->vaQuerySurfaceError( ctx, surface, error_status, error_info );
1289 VA_TRACE_LOG(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info);
1294 /* Get maximum number of image formats supported by the implementation */
1295 int vaMaxNumImageFormats (
1299 if (!vaDisplayIsValid(dpy))
1302 return CTX(dpy)->max_image_formats;
1305 VAStatus vaQueryImageFormats (
1307 VAImageFormat *format_list, /* out */
1308 int *num_formats /* out */
1311 VADriverContextP ctx;
1315 return ctx->vtable->vaQueryImageFormats ( ctx, format_list, num_formats);
1319 * The width and height fields returned in the VAImage structure may get
1320 * enlarged for some YUV formats. The size of the data buffer that needs
1321 * to be allocated will be given in the "data_size" field in VAImage.
1322 * Image data is not allocated by this function. The client should
1323 * allocate the memory and fill in the VAImage structure's data field
1324 * after looking at "data_size" returned from the library.
1326 VAStatus vaCreateImage (
1328 VAImageFormat *format,
1331 VAImage *image /* out */
1334 VADriverContextP ctx;
1338 return ctx->vtable->vaCreateImage ( ctx, format, width, height, image);
1342 * Should call DestroyImage before destroying the surface it is bound to
1344 VAStatus vaDestroyImage (
1349 VADriverContextP ctx;
1353 return ctx->vtable->vaDestroyImage ( ctx, image);
1356 VAStatus vaSetImagePalette (
1359 unsigned char *palette
1362 VADriverContextP ctx;
1366 return ctx->vtable->vaSetImagePalette ( ctx, image, palette);
1370 * Retrieve surface data into a VAImage
1371 * Image must be in a format supported by the implementation
1373 VAStatus vaGetImage (
1375 VASurfaceID surface,
1376 int x, /* coordinates of the upper left source pixel */
1378 unsigned int width, /* width and height of the region */
1379 unsigned int height,
1383 VADriverContextP ctx;
1387 return ctx->vtable->vaGetImage ( ctx, surface, x, y, width, height, image);
1391 * Copy data from a VAImage to a surface
1392 * Image must be in a format supported by the implementation
1394 VAStatus vaPutImage (
1396 VASurfaceID surface,
1400 unsigned int src_width,
1401 unsigned int src_height,
1404 unsigned int dest_width,
1405 unsigned int dest_height
1408 VADriverContextP ctx;
1412 return ctx->vtable->vaPutImage ( ctx, surface, image, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height );
1416 * Derive an VAImage from an existing surface.
1417 * This interface will derive a VAImage and corresponding image buffer from
1418 * an existing VA Surface. The image buffer can then be mapped/unmapped for
1419 * direct CPU access. This operation is only possible on implementations with
1420 * direct rendering capabilities and internal surface formats that can be
1421 * represented with a VAImage. When the operation is not possible this interface
1422 * will return VA_STATUS_ERROR_OPERATION_FAILED. Clients should then fall back
1423 * to using vaCreateImage + vaPutImage to accomplish the same task in an
1426 * Implementations should only return success when the resulting image buffer
1427 * would be useable with vaMap/Unmap.
1429 * When directly accessing a surface special care must be taken to insure
1430 * proper synchronization with the graphics hardware. Clients should call
1431 * vaQuerySurfaceStatus to insure that a surface is not the target of concurrent
1432 * rendering or currently being displayed by an overlay.
1434 * Additionally nothing about the contents of a surface should be assumed
1435 * following a vaPutSurface. Implementations are free to modify the surface for
1436 * scaling or subpicture blending within a call to vaPutImage.
1438 * Calls to vaPutImage or vaGetImage using the same surface from which the image
1439 * has been derived will return VA_STATUS_ERROR_SURFACE_BUSY. vaPutImage or
1440 * vaGetImage with other surfaces is supported.
1442 * An image created with vaDeriveImage should be freed with vaDestroyImage. The
1443 * image and image buffer structures will be destroyed; however, the underlying
1444 * surface will remain unchanged until freed with vaDestroySurfaces.
1446 VAStatus vaDeriveImage (
1448 VASurfaceID surface,
1449 VAImage *image /* out */
1452 VADriverContextP ctx;
1456 return ctx->vtable->vaDeriveImage ( ctx, surface, image );
1460 /* Get maximum number of subpicture formats supported by the implementation */
1461 int vaMaxNumSubpictureFormats (
1465 if (!vaDisplayIsValid(dpy))
1468 return CTX(dpy)->max_subpic_formats;
1472 * Query supported subpicture formats
1473 * The caller must provide a "format_list" array that can hold at
1474 * least vaMaxNumSubpictureFormats() entries. The flags arrary holds the flag
1475 * for each format to indicate additional capabilities for that format. The actual
1476 * number of formats returned in "format_list" is returned in "num_formats".
1478 VAStatus vaQuerySubpictureFormats (
1480 VAImageFormat *format_list, /* out */
1481 unsigned int *flags, /* out */
1482 unsigned int *num_formats /* out */
1485 VADriverContextP ctx;
1490 return ctx->vtable->vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats);
1494 * Subpictures are created with an image associated.
1496 VAStatus vaCreateSubpicture (
1499 VASubpictureID *subpicture /* out */
1502 VADriverContextP ctx;
1506 return ctx->vtable->vaCreateSubpicture ( ctx, image, subpicture );
1510 * Destroy the subpicture before destroying the image it is assocated to
1512 VAStatus vaDestroySubpicture (
1514 VASubpictureID subpicture
1517 VADriverContextP ctx;
1521 return ctx->vtable->vaDestroySubpicture ( ctx, subpicture);
1524 VAStatus vaSetSubpictureImage (
1526 VASubpictureID subpicture,
1530 VADriverContextP ctx;
1534 return ctx->vtable->vaSetSubpictureImage ( ctx, subpicture, image);
1539 * If chromakey is enabled, then the area where the source value falls within
1540 * the chromakey [min, max] range is transparent
1542 VAStatus vaSetSubpictureChromakey (
1544 VASubpictureID subpicture,
1545 unsigned int chromakey_min,
1546 unsigned int chromakey_max,
1547 unsigned int chromakey_mask
1550 VADriverContextP ctx;
1554 return ctx->vtable->vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask );
1559 * Global alpha value is between 0 and 1. A value of 1 means fully opaque and
1560 * a value of 0 means fully transparent. If per-pixel alpha is also specified then
1561 * the overall alpha is per-pixel alpha multiplied by the global alpha
1563 VAStatus vaSetSubpictureGlobalAlpha (
1565 VASubpictureID subpicture,
1569 VADriverContextP ctx;
1573 return ctx->vtable->vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha );
1577 vaAssociateSubpicture associates the subpicture with the target_surface.
1578 It defines the region mapping between the subpicture and the target
1579 surface through source and destination rectangles (with the same width and height).
1580 Both will be displayed at the next call to vaPutSurface. Additional
1581 associations before the call to vaPutSurface simply overrides the association.
1583 VAStatus vaAssociateSubpicture (
1585 VASubpictureID subpicture,
1586 VASurfaceID *target_surfaces,
1588 short src_x, /* upper left offset in subpicture */
1590 unsigned short src_width,
1591 unsigned short src_height,
1592 short dest_x, /* upper left offset in surface */
1594 unsigned short dest_width,
1595 unsigned short dest_height,
1597 * whether to enable chroma-keying or global-alpha
1598 * see VA_SUBPICTURE_XXX values
1603 VADriverContextP ctx;
1607 return ctx->vtable->vaAssociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height, flags );
1611 * vaDeassociateSubpicture removes the association of the subpicture with target_surfaces.
1613 VAStatus vaDeassociateSubpicture (
1615 VASubpictureID subpicture,
1616 VASurfaceID *target_surfaces,
1620 VADriverContextP ctx;
1624 return ctx->vtable->vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces );
1628 /* Get maximum number of display attributes supported by the implementation */
1629 int vaMaxNumDisplayAttributes (
1635 if (!vaDisplayIsValid(dpy))
1638 tmp = CTX(dpy)->max_display_attributes;
1640 VA_TRACE_LOG(va_TraceMaxNumDisplayAttributes, dpy, tmp);
1646 * Query display attributes
1647 * The caller must provide a "attr_list" array that can hold at
1648 * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1649 * returned in "attr_list" is returned in "num_attributes".
1651 VAStatus vaQueryDisplayAttributes (
1653 VADisplayAttribute *attr_list, /* out */
1654 int *num_attributes /* out */
1657 VADriverContextP ctx;
1662 va_status = ctx->vtable->vaQueryDisplayAttributes ( ctx, attr_list, num_attributes );
1664 VA_TRACE_LOG(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes);
1671 * Get display attributes
1672 * This function returns the current attribute values in "attr_list".
1673 * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
1674 * from vaQueryDisplayAttributes() can have their values retrieved.
1676 VAStatus vaGetDisplayAttributes (
1678 VADisplayAttribute *attr_list, /* in/out */
1682 VADriverContextP ctx;
1687 va_status = ctx->vtable->vaGetDisplayAttributes ( ctx, attr_list, num_attributes );
1689 VA_TRACE_LOG(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes);
1695 * Set display attributes
1696 * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
1697 * from vaQueryDisplayAttributes() can be set. If the attribute is not settable or
1698 * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
1700 VAStatus vaSetDisplayAttributes (
1702 VADisplayAttribute *attr_list,
1706 VADriverContextP ctx;
1711 va_status = ctx->vtable->vaSetDisplayAttributes ( ctx, attr_list, num_attributes );
1712 VA_TRACE_LOG(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes);
1717 VAStatus vaLockSurface(VADisplay dpy,
1718 VASurfaceID surface,
1719 unsigned int *fourcc, /* following are output argument */
1720 unsigned int *luma_stride,
1721 unsigned int *chroma_u_stride,
1722 unsigned int *chroma_v_stride,
1723 unsigned int *luma_offset,
1724 unsigned int *chroma_u_offset,
1725 unsigned int *chroma_v_offset,
1726 unsigned int *buffer_name,
1730 VADriverContextP ctx;
1734 return ctx->vtable->vaLockSurface( ctx, surface, fourcc, luma_stride, chroma_u_stride, chroma_v_stride, luma_offset, chroma_u_offset, chroma_v_offset, buffer_name, buffer);
1738 VAStatus vaUnlockSurface(VADisplay dpy,
1742 VADriverContextP ctx;
1746 return ctx->vtable->vaUnlockSurface( ctx, surface );
1749 /* Video Processing */
1750 #define VA_VPP_INIT_CONTEXT(ctx, dpy) do { \
1751 CHECK_DISPLAY(dpy); \
1754 return VA_STATUS_ERROR_INVALID_DISPLAY; \
1757 #define VA_VPP_INVOKE(dpy, func, args) do { \
1758 if (!ctx->vtable_vpp->va##func) \
1759 return VA_STATUS_ERROR_UNIMPLEMENTED; \
1760 status = ctx->vtable_vpp->va##func args; \
1764 vaQueryVideoProcFilters(
1766 VAContextID context,
1767 VAProcFilterType *filters,
1768 unsigned int *num_filters
1771 VADriverContextP ctx;
1774 VA_VPP_INIT_CONTEXT(ctx, dpy);
1777 QueryVideoProcFilters,
1778 (ctx, context, filters, num_filters)
1784 vaQueryVideoProcFilterCaps(
1786 VAContextID context,
1787 VAProcFilterType type,
1789 unsigned int *num_filter_caps
1792 VADriverContextP ctx;
1795 VA_VPP_INIT_CONTEXT(ctx, dpy);
1798 QueryVideoProcFilterCaps,
1799 (ctx, context, type, filter_caps, num_filter_caps)
1805 vaQueryVideoProcPipelineCaps(
1807 VAContextID context,
1808 VABufferID *filters,
1809 unsigned int num_filters,
1810 VAProcPipelineCaps *pipeline_caps
1813 VADriverContextP ctx;
1816 VA_VPP_INIT_CONTEXT(ctx, dpy);
1819 QueryVideoProcPipelineCaps,
1820 (ctx, context, filters, num_filters, pipeline_caps)