Home | History | Annotate | Download | only in va
      1 /*
      2  * Copyright (c) 2007 Intel Corporation. All Rights Reserved.
      3  *
      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:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial portions
     14  * of the Software.
     15  *
     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.
     23  */
     24 
     25 #define _GNU_SOURCE 1
     26 #include "sysdeps.h"
     27 #include "va.h"
     28 #include "va_backend.h"
     29 #include "va_backend_vpp.h"
     30 #include "va_trace.h"
     31 #include "va_fool.h"
     32 
     33 #include <assert.h>
     34 #include <stdarg.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <dlfcn.h>
     39 #include <unistd.h>
     40 
     41 #define DRIVER_EXTENSION	"_drv_video.so"
     42 
     43 #define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext)
     44 #define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; }
     45 
     46 #define ASSERT		assert
     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;
     50 
     51 
     52 /*
     53  * read a config "env" for libva.conf or from environment setting
     54  * liva.conf has higher priority
     55  * return 0: the "env" is set, and the value is copied into env_value
     56  *        1: the env is not set
     57  */
     58 int va_parseConfig(char *env, char *env_value)
     59 {
     60     char *token, *value, *saveptr;
     61     char oneline[1024];
     62     FILE *fp=NULL;
     63 
     64     if (env == NULL)
     65         return 1;
     66 
     67     fp = fopen("/etc/libva.conf", "r");
     68     while (fp && (fgets(oneline, 1024, fp) != NULL)) {
     69 	if (strlen(oneline) == 1)
     70 	    continue;
     71         token = strtok_r(oneline, "=\n", &saveptr);
     72 	value = strtok_r(NULL, "=\n", &saveptr);
     73 
     74 	if (NULL == token || NULL == value)
     75 	    continue;
     76 
     77         if (strcmp(token, env) == 0) {
     78             if (env_value)
     79                 strncpy(env_value,value, 1024);
     80 
     81             fclose(fp);
     82 
     83             return 0;
     84         }
     85     }
     86     if (fp)
     87         fclose(fp);
     88 
     89     /* no setting in config file, use env setting */
     90     value = getenv(env);
     91     if (value) {
     92         if (env_value)
     93             strncpy(env_value, value, 1024);
     94         return 0;
     95     }
     96 
     97     return 1;
     98 }
     99 
    100 int vaDisplayIsValid(VADisplay dpy)
    101 {
    102     VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
    103     return pDisplayContext && (pDisplayContext->vadpy_magic == VA_DISPLAY_MAGIC) && pDisplayContext->vaIsValid(pDisplayContext);
    104 }
    105 
    106 void va_errorMessage(const char *msg, ...)
    107 {
    108     char buf[512], *dynbuf;
    109     va_list args;
    110     int n, len;
    111 
    112     va_start(args, msg);
    113     len = vsnprintf(buf, sizeof(buf), msg, args);
    114     va_end(args);
    115 
    116     if (len >= (int)sizeof(buf)) {
    117         dynbuf = malloc(len + 1);
    118         if (!dynbuf)
    119             return;
    120         va_start(args, msg);
    121         n = vsnprintf(dynbuf, len + 1, msg, args);
    122         va_end(args);
    123         if (n == len)
    124             va_log_error(dynbuf);
    125         free(dynbuf);
    126     }
    127     else if (len > 0)
    128         va_log_error(buf);
    129 }
    130 
    131 void va_infoMessage(const char *msg, ...)
    132 {
    133     char buf[512], *dynbuf;
    134     va_list args;
    135     int n, len;
    136 
    137     va_start(args, msg);
    138     len = vsnprintf(buf, sizeof(buf), msg, args);
    139     va_end(args);
    140 
    141     if (len >= (int)sizeof(buf)) {
    142         dynbuf = malloc(len + 1);
    143         if (!dynbuf)
    144             return;
    145         va_start(args, msg);
    146         n = vsnprintf(dynbuf, len + 1, msg, args);
    147         va_end(args);
    148         if (n == len)
    149             va_log_info(dynbuf);
    150         free(dynbuf);
    151     }
    152     else if (len > 0)
    153         va_log_info(buf);
    154 }
    155 
    156 static bool va_checkVtable(void *ptr, char *function)
    157 {
    158     if (!ptr) {
    159         va_errorMessage("No valid vtable entry for va%s\n", function);
    160         return false;
    161     }
    162     return true;
    163 }
    164 
    165 static bool va_checkMaximum(int value, char *variable)
    166 {
    167     if (!value) {
    168         va_errorMessage("Failed to define max_%s in init\n", variable);
    169         return false;
    170     }
    171     return true;
    172 }
    173 
    174 static bool va_checkString(const char* value, char *variable)
    175 {
    176     if (!value) {
    177         va_errorMessage("Failed to define str_%s in init\n", variable);
    178         return false;
    179     }
    180     return true;
    181 }
    182 
    183 static inline int
    184 va_getDriverInitName(char *name, int namelen, int major, int minor)
    185 {
    186     int ret = snprintf(name, namelen, "__vaDriverInit_%d_%d", major, minor);
    187     return ret > 0 && ret < namelen;
    188 }
    189 
    190 static VAStatus va_getDriverName(VADisplay dpy, char **driver_name)
    191 {
    192     VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
    193 
    194     return pDisplayContext->vaGetDriverName(pDisplayContext, driver_name);
    195 }
    196 
    197 static VAStatus va_openDriver(VADisplay dpy, char *driver_name)
    198 {
    199     VADriverContextP ctx = CTX(dpy);
    200     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
    201     char *search_path = NULL;
    202     char *saveptr;
    203     char *driver_dir;
    204 
    205     if (geteuid() == getuid())
    206         /* don't allow setuid apps to use LIBVA_DRIVERS_PATH */
    207         search_path = getenv("LIBVA_DRIVERS_PATH");
    208     if (!search_path)
    209         search_path = VA_DRIVERS_PATH;
    210 
    211     search_path = strdup((const char *)search_path);
    212     driver_dir = strtok_r(search_path, ":", &saveptr);
    213     while (driver_dir) {
    214         void *handle = NULL;
    215         char *driver_path = (char *) malloc( strlen(driver_dir) +
    216                                              strlen(driver_name) +
    217                                              strlen(DRIVER_EXTENSION) + 2 );
    218         if (!driver_path) {
    219             va_errorMessage("%s L%d Out of memory!n",
    220                                 __FUNCTION__, __LINE__);
    221             free(search_path);
    222             return VA_STATUS_ERROR_ALLOCATION_FAILED;
    223         }
    224 
    225         strncpy( driver_path, driver_dir, strlen(driver_dir) + 1);
    226         strncat( driver_path, "/", strlen("/") );
    227         strncat( driver_path, driver_name, strlen(driver_name) );
    228         strncat( driver_path, DRIVER_EXTENSION, strlen(DRIVER_EXTENSION) );
    229 
    230         va_infoMessage("Trying to open %s\n", driver_path);
    231 #ifndef ANDROID
    232         handle = dlopen( driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE );
    233 #else
    234         handle = dlopen( driver_path, RTLD_NOW| RTLD_GLOBAL);
    235 #endif
    236         if (!handle) {
    237             /* Don't give errors for non-existing files */
    238             if (0 == access( driver_path, F_OK))
    239                 va_errorMessage("dlopen of %s failed: %s\n", driver_path, dlerror());
    240         } else {
    241             VADriverInit init_func = NULL;
    242             char init_func_s[256];
    243             int i;
    244 
    245             static const struct {
    246                 int major;
    247                 int minor;
    248             } compatible_versions[] = {
    249                 { VA_MAJOR_VERSION, VA_MINOR_VERSION },
    250                 { 0, 33 },
    251                 { 0, 32 },
    252                 { -1, 0}
    253             };
    254 
    255             for (i = 0; compatible_versions[i].major >= 0; i++) {
    256                 if (va_getDriverInitName(init_func_s, sizeof(init_func_s),
    257                                          compatible_versions[i].major,
    258                                          compatible_versions[i].minor)) {
    259                     init_func = (VADriverInit)dlsym(handle, init_func_s);
    260                     if (init_func) {
    261                         va_infoMessage("Found init function %s\n", init_func_s);
    262                         break;
    263                     }
    264                 }
    265             }
    266 
    267             if (compatible_versions[i].major < 0) {
    268                 va_errorMessage("%s has no function %s\n",
    269                                 driver_path, init_func_s);
    270                 dlclose(handle);
    271             } else {
    272                 struct VADriverVTable *vtable = ctx->vtable;
    273                 struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp;
    274 
    275                 vaStatus = VA_STATUS_SUCCESS;
    276                 if (!vtable) {
    277                     vtable = calloc(1, sizeof(*vtable));
    278                     if (!vtable)
    279                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    280                 }
    281                 ctx->vtable = vtable;
    282 
    283                 if (!vtable_vpp) {
    284                     vtable_vpp = calloc(1, sizeof(*vtable_vpp));
    285                     if (vtable_vpp)
    286                         vtable_vpp->version = VA_DRIVER_VTABLE_VPP_VERSION;
    287                     else
    288                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    289                 }
    290                 ctx->vtable_vpp = vtable_vpp;
    291 
    292                 if (init_func && VA_STATUS_SUCCESS == vaStatus)
    293                     vaStatus = (*init_func)(ctx);
    294 
    295                 if (VA_STATUS_SUCCESS == vaStatus) {
    296                     CHECK_MAXIMUM(vaStatus, ctx, profiles);
    297                     CHECK_MAXIMUM(vaStatus, ctx, entrypoints);
    298                     CHECK_MAXIMUM(vaStatus, ctx, attributes);
    299                     CHECK_MAXIMUM(vaStatus, ctx, image_formats);
    300                     CHECK_MAXIMUM(vaStatus, ctx, subpic_formats);
    301                     CHECK_MAXIMUM(vaStatus, ctx, display_attributes);
    302                     CHECK_STRING(vaStatus, ctx, vendor);
    303                     CHECK_VTABLE(vaStatus, ctx, Terminate);
    304                     CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles);
    305                     CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints);
    306                     CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes);
    307                     CHECK_VTABLE(vaStatus, ctx, CreateConfig);
    308                     CHECK_VTABLE(vaStatus, ctx, DestroyConfig);
    309                     CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes);
    310                     CHECK_VTABLE(vaStatus, ctx, CreateSurfaces);
    311                     CHECK_VTABLE(vaStatus, ctx, DestroySurfaces);
    312                     CHECK_VTABLE(vaStatus, ctx, CreateContext);
    313                     CHECK_VTABLE(vaStatus, ctx, DestroyContext);
    314                     CHECK_VTABLE(vaStatus, ctx, CreateBuffer);
    315                     CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements);
    316                     CHECK_VTABLE(vaStatus, ctx, MapBuffer);
    317                     CHECK_VTABLE(vaStatus, ctx, UnmapBuffer);
    318                     CHECK_VTABLE(vaStatus, ctx, DestroyBuffer);
    319                     CHECK_VTABLE(vaStatus, ctx, BeginPicture);
    320                     CHECK_VTABLE(vaStatus, ctx, RenderPicture);
    321                     CHECK_VTABLE(vaStatus, ctx, EndPicture);
    322                     CHECK_VTABLE(vaStatus, ctx, SyncSurface);
    323                     CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus);
    324                     CHECK_VTABLE(vaStatus, ctx, PutSurface);
    325                     CHECK_VTABLE(vaStatus, ctx, QueryImageFormats);
    326                     CHECK_VTABLE(vaStatus, ctx, CreateImage);
    327                     CHECK_VTABLE(vaStatus, ctx, DeriveImage);
    328                     CHECK_VTABLE(vaStatus, ctx, DestroyImage);
    329                     CHECK_VTABLE(vaStatus, ctx, SetImagePalette);
    330                     CHECK_VTABLE(vaStatus, ctx, GetImage);
    331                     CHECK_VTABLE(vaStatus, ctx, PutImage);
    332                     CHECK_VTABLE(vaStatus, ctx, QuerySubpictureFormats);
    333                     CHECK_VTABLE(vaStatus, ctx, CreateSubpicture);
    334                     CHECK_VTABLE(vaStatus, ctx, DestroySubpicture);
    335                     CHECK_VTABLE(vaStatus, ctx, SetSubpictureImage);
    336                     CHECK_VTABLE(vaStatus, ctx, SetSubpictureChromakey);
    337                     CHECK_VTABLE(vaStatus, ctx, SetSubpictureGlobalAlpha);
    338                     CHECK_VTABLE(vaStatus, ctx, AssociateSubpicture);
    339                     CHECK_VTABLE(vaStatus, ctx, DeassociateSubpicture);
    340                     CHECK_VTABLE(vaStatus, ctx, QueryDisplayAttributes);
    341                     CHECK_VTABLE(vaStatus, ctx, GetDisplayAttributes);
    342                     CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes);
    343                 }
    344                 if (VA_STATUS_SUCCESS != vaStatus) {
    345                     va_errorMessage("%s init failed\n", driver_path);
    346                     dlclose(handle);
    347                 }
    348                 if (VA_STATUS_SUCCESS == vaStatus)
    349                     ctx->handle = handle;
    350                 free(driver_path);
    351                 break;
    352             }
    353         }
    354         free(driver_path);
    355 
    356         driver_dir = strtok_r(NULL, ":", &saveptr);
    357     }
    358 
    359     free(search_path);
    360 
    361     return vaStatus;
    362 }
    363 
    364 VAPrivFunc vaGetLibFunc(VADisplay dpy, const char *func)
    365 {
    366     VADriverContextP ctx;
    367     if (!vaDisplayIsValid(dpy))
    368         return NULL;
    369     ctx = CTX(dpy);
    370 
    371     if (NULL == ctx->handle)
    372         return NULL;
    373 
    374     return (VAPrivFunc) dlsym(ctx->handle, func);
    375 }
    376 
    377 
    378 /*
    379  * Returns a short english description of error_status
    380  */
    381 const char *vaErrorStr(VAStatus error_status)
    382 {
    383     switch(error_status) {
    384         case VA_STATUS_SUCCESS:
    385             return "success (no error)";
    386         case VA_STATUS_ERROR_OPERATION_FAILED:
    387             return "operation failed";
    388         case VA_STATUS_ERROR_ALLOCATION_FAILED:
    389             return "resource allocation failed";
    390         case VA_STATUS_ERROR_INVALID_DISPLAY:
    391             return "invalid VADisplay";
    392         case VA_STATUS_ERROR_INVALID_CONFIG:
    393             return "invalid VAConfigID";
    394         case VA_STATUS_ERROR_INVALID_CONTEXT:
    395             return "invalid VAContextID";
    396         case VA_STATUS_ERROR_INVALID_SURFACE:
    397             return "invalid VASurfaceID";
    398         case VA_STATUS_ERROR_INVALID_BUFFER:
    399             return "invalid VABufferID";
    400         case VA_STATUS_ERROR_INVALID_IMAGE:
    401             return "invalid VAImageID";
    402         case VA_STATUS_ERROR_INVALID_SUBPICTURE:
    403             return "invalid VASubpictureID";
    404         case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
    405             return "attribute not supported";
    406         case VA_STATUS_ERROR_MAX_NUM_EXCEEDED:
    407             return "list argument exceeds maximum number";
    408         case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
    409             return "the requested VAProfile is not supported";
    410         case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
    411             return "the requested VAEntryPoint is not supported";
    412         case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
    413             return "the requested RT Format is not supported";
    414         case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
    415             return "the requested VABufferType is not supported";
    416         case VA_STATUS_ERROR_SURFACE_BUSY:
    417             return "surface is in use";
    418         case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED:
    419             return "flag not supported";
    420         case VA_STATUS_ERROR_INVALID_PARAMETER:
    421             return "invalid parameter";
    422         case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED:
    423             return "resolution not supported";
    424         case VA_STATUS_ERROR_UNIMPLEMENTED:
    425             return "the requested function is not implemented";
    426         case VA_STATUS_ERROR_SURFACE_IN_DISPLAYING:
    427             return "surface is in displaying (may by overlay)" ;
    428         case VA_STATUS_ERROR_INVALID_IMAGE_FORMAT:
    429             return "invalid VAImageFormat";
    430         case VA_STATUS_ERROR_INVALID_VALUE:
    431             return "an invalid/unsupported value was supplied";
    432         case VA_STATUS_ERROR_UNSUPPORTED_FILTER:
    433             return "the requested filter is not supported";
    434         case VA_STATUS_ERROR_INVALID_FILTER_CHAIN:
    435             return "an invalid filter chain was supplied";
    436         case VA_STATUS_ERROR_UNKNOWN:
    437             return "unknown libva error";
    438     }
    439     return "unknown libva error / description missing";
    440 }
    441 
    442 VAStatus vaInitialize (
    443     VADisplay dpy,
    444     int *major_version,	 /* out */
    445     int *minor_version 	 /* out */
    446 )
    447 {
    448     const char *driver_name_env = NULL;
    449     char *driver_name = NULL;
    450     VAStatus vaStatus;
    451 
    452     CHECK_DISPLAY(dpy);
    453 
    454     va_TraceInit(dpy);
    455 
    456     va_FoolInit(dpy);
    457 
    458     va_infoMessage("VA-API version %s\n", VA_VERSION_S);
    459 
    460     vaStatus = va_getDriverName(dpy, &driver_name);
    461     va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
    462 
    463     driver_name_env = getenv("LIBVA_DRIVER_NAME");
    464     if ((VA_STATUS_SUCCESS == vaStatus) &&
    465         driver_name_env && (geteuid() == getuid())) {
    466         /* Don't allow setuid apps to use LIBVA_DRIVER_NAME */
    467         if (driver_name) /* memory is allocated in va_getDriverName */
    468             free(driver_name);
    469 
    470         driver_name = strdup(driver_name_env);
    471         vaStatus = VA_STATUS_SUCCESS;
    472         va_infoMessage("User requested driver '%s'\n", driver_name);
    473     }
    474 
    475     if ((VA_STATUS_SUCCESS == vaStatus) && (driver_name != NULL)) {
    476         vaStatus = va_openDriver(dpy, driver_name);
    477         va_infoMessage("va_openDriver() returns %d\n", vaStatus);
    478 
    479         *major_version = VA_MAJOR_VERSION;
    480         *minor_version = VA_MINOR_VERSION;
    481     } else
    482         va_errorMessage("va_getDriverName() failed with %s,driver_name=%s\n",
    483                         vaErrorStr(vaStatus), driver_name);
    484 
    485     if (driver_name)
    486         free(driver_name);
    487 
    488     VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version);
    489 
    490     return vaStatus;
    491 }
    492 
    493 
    494 /*
    495  * After this call, all library internal resources will be cleaned up
    496  */
    497 VAStatus vaTerminate (
    498     VADisplay dpy
    499 )
    500 {
    501   VAStatus vaStatus = VA_STATUS_SUCCESS;
    502   VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
    503   VADriverContextP old_ctx;
    504 
    505   CHECK_DISPLAY(dpy);
    506   old_ctx = CTX(dpy);
    507 
    508   if (old_ctx->handle) {
    509       vaStatus = old_ctx->vtable->vaTerminate(old_ctx);
    510       dlclose(old_ctx->handle);
    511       old_ctx->handle = NULL;
    512   }
    513   free(old_ctx->vtable);
    514   old_ctx->vtable = NULL;
    515   free(old_ctx->vtable_vpp);
    516   old_ctx->vtable_vpp = NULL;
    517 
    518   VA_TRACE_LOG(va_TraceTerminate, dpy);
    519 
    520   va_TraceEnd(dpy);
    521 
    522   va_FoolEnd(dpy);
    523 
    524   if (VA_STATUS_SUCCESS == vaStatus)
    525       pDisplayContext->vaDestroy(pDisplayContext);
    526 
    527   return vaStatus;
    528 }
    529 
    530 /*
    531  * vaQueryVendorString returns a pointer to a zero-terminated string
    532  * describing some aspects of the VA implemenation on a specific
    533  * hardware accelerator. The format of the returned string is:
    534  * <vendorname>-<major_version>-<minor_version>-<addtional_info>
    535  * e.g. for the Intel GMA500 implementation, an example would be:
    536  * "IntelGMA500-1.0-0.2-patch3
    537  */
    538 const char *vaQueryVendorString (
    539     VADisplay dpy
    540 )
    541 {
    542   if (!vaDisplayIsValid(dpy))
    543       return NULL;
    544 
    545   return CTX(dpy)->str_vendor;
    546 }
    547 
    548 
    549 /* Get maximum number of profiles supported by the implementation */
    550 int vaMaxNumProfiles (
    551     VADisplay dpy
    552 )
    553 {
    554   if (!vaDisplayIsValid(dpy))
    555       return 0;
    556 
    557   return CTX(dpy)->max_profiles;
    558 }
    559 
    560 /* Get maximum number of entrypoints supported by the implementation */
    561 int vaMaxNumEntrypoints (
    562     VADisplay dpy
    563 )
    564 {
    565   if (!vaDisplayIsValid(dpy))
    566       return 0;
    567 
    568   return CTX(dpy)->max_entrypoints;
    569 }
    570 
    571 
    572 /* Get maximum number of attributs supported by the implementation */
    573 int vaMaxNumConfigAttributes (
    574     VADisplay dpy
    575 )
    576 {
    577   if (!vaDisplayIsValid(dpy))
    578       return 0;
    579 
    580   return CTX(dpy)->max_attributes;
    581 }
    582 
    583 VAStatus vaQueryConfigEntrypoints (
    584     VADisplay dpy,
    585     VAProfile profile,
    586     VAEntrypoint *entrypoints,	/* out */
    587     int *num_entrypoints	/* out */
    588 )
    589 {
    590   VADriverContextP ctx;
    591   CHECK_DISPLAY(dpy);
    592   ctx = CTX(dpy);
    593 
    594   return ctx->vtable->vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
    595 }
    596 
    597 VAStatus vaGetConfigAttributes (
    598     VADisplay dpy,
    599     VAProfile profile,
    600     VAEntrypoint entrypoint,
    601     VAConfigAttrib *attrib_list, /* in/out */
    602     int num_attribs
    603 )
    604 {
    605   VADriverContextP ctx;
    606   CHECK_DISPLAY(dpy);
    607   ctx = CTX(dpy);
    608 
    609   return ctx->vtable->vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
    610 }
    611 
    612 VAStatus vaQueryConfigProfiles (
    613     VADisplay dpy,
    614     VAProfile *profile_list,	/* out */
    615     int *num_profiles		/* out */
    616 )
    617 {
    618   VADriverContextP ctx;
    619   CHECK_DISPLAY(dpy);
    620   ctx = CTX(dpy);
    621 
    622   return ctx->vtable->vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
    623 }
    624 
    625 VAStatus vaCreateConfig (
    626     VADisplay dpy,
    627     VAProfile profile,
    628     VAEntrypoint entrypoint,
    629     VAConfigAttrib *attrib_list,
    630     int num_attribs,
    631     VAConfigID *config_id /* out */
    632 )
    633 {
    634   VADriverContextP ctx;
    635   VAStatus vaStatus = VA_STATUS_SUCCESS;
    636 
    637   CHECK_DISPLAY(dpy);
    638   ctx = CTX(dpy);
    639 
    640   vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
    641 
    642   /* record the current entrypoint for further trace/fool determination */
    643   VA_TRACE_ALL(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
    644   VA_FOOL_FUNC(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
    645 
    646   return vaStatus;
    647 }
    648 
    649 VAStatus vaDestroyConfig (
    650     VADisplay dpy,
    651     VAConfigID config_id
    652 )
    653 {
    654   VADriverContextP ctx;
    655   CHECK_DISPLAY(dpy);
    656   ctx = CTX(dpy);
    657 
    658   return ctx->vtable->vaDestroyConfig ( ctx, config_id );
    659 }
    660 
    661 VAStatus vaQueryConfigAttributes (
    662     VADisplay dpy,
    663     VAConfigID config_id,
    664     VAProfile *profile, 	/* out */
    665     VAEntrypoint *entrypoint, 	/* out */
    666     VAConfigAttrib *attrib_list,/* out */
    667     int *num_attribs		/* out */
    668 )
    669 {
    670   VADriverContextP ctx;
    671   CHECK_DISPLAY(dpy);
    672   ctx = CTX(dpy);
    673 
    674   return ctx->vtable->vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
    675 }
    676 
    677 /* XXX: this is a slow implementation that will be removed */
    678 static VAStatus
    679 va_impl_query_surface_attributes(
    680     VADriverContextP    ctx,
    681     VAConfigID          config,
    682     VASurfaceAttrib    *out_attribs,
    683     unsigned int       *out_num_attribs_ptr
    684 )
    685 {
    686     VASurfaceAttrib *attribs = NULL;
    687     unsigned int num_attribs, n;
    688     VASurfaceAttrib *out_attrib;
    689     unsigned int out_num_attribs;
    690     VAImageFormat *image_formats = NULL;
    691     int num_image_formats, i;
    692     VAStatus va_status;
    693 
    694     /* List of surface attributes to query */
    695     struct va_surface_attrib_map {
    696         VASurfaceAttribType type;
    697         VAGenericValueType  value_type;
    698     };
    699     static const struct va_surface_attrib_map attribs_map[] = {
    700         { VASurfaceAttribMinWidth,      VAGenericValueTypeInteger },
    701         { VASurfaceAttribMaxWidth,      VAGenericValueTypeInteger },
    702         { VASurfaceAttribMinHeight,     VAGenericValueTypeInteger },
    703         { VASurfaceAttribMaxHeight,     VAGenericValueTypeInteger },
    704         { VASurfaceAttribMemoryType,    VAGenericValueTypeInteger },
    705         { VASurfaceAttribNone, }
    706     };
    707 
    708     if (!out_attribs || !out_num_attribs_ptr)
    709         return VA_STATUS_ERROR_INVALID_PARAMETER;
    710     if (!ctx->vtable->vaGetSurfaceAttributes)
    711         return VA_STATUS_ERROR_UNIMPLEMENTED;
    712 
    713     num_image_formats = ctx->max_image_formats;
    714     image_formats = malloc(num_image_formats * sizeof(*image_formats));
    715     if (!image_formats) {
    716         va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
    717         goto end;
    718     }
    719 
    720     va_status = ctx->vtable->vaQueryImageFormats(
    721         ctx, image_formats, &num_image_formats);
    722     if (va_status != VA_STATUS_SUCCESS)
    723         goto end;
    724 
    725     num_attribs = VASurfaceAttribCount + num_image_formats;
    726     attribs = malloc(num_attribs * sizeof(*attribs));
    727     if (!attribs) {
    728         va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
    729         goto end;
    730     }
    731 
    732     /* Initialize with base surface attributes, except pixel-formats */
    733     for (n = 0; attribs_map[n].type != VASurfaceAttribNone; n++) {
    734         VASurfaceAttrib * const attrib = &attribs[n];
    735         attrib->type = attribs_map[n].type;
    736         attrib->flags = VA_SURFACE_ATTRIB_GETTABLE;
    737         attrib->value.type = attribs_map[n].value_type;
    738     }
    739 
    740     /* Append image formats */
    741     for (i = 0; i < num_image_formats; i++) {
    742         VASurfaceAttrib * const attrib = &attribs[n];
    743         attrib->type = VASurfaceAttribPixelFormat;
    744         attrib->flags = VA_SURFACE_ATTRIB_GETTABLE|VA_SURFACE_ATTRIB_SETTABLE;
    745         attrib->value.type = VAGenericValueTypeInteger;
    746         attrib->value.value.i = image_formats[i].fourcc;
    747         if (++n == num_attribs) {
    748             va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
    749             goto end;
    750         }
    751     }
    752     num_attribs = n;
    753 
    754     va_status = ctx->vtable->vaGetSurfaceAttributes(
    755         ctx, config, attribs, num_attribs);
    756     if (va_status != VA_STATUS_SUCCESS)
    757         goto end;
    758 
    759     /* Remove invalid entries */
    760     out_num_attribs = 0;
    761     for (n = 0; n < num_attribs; n++) {
    762         VASurfaceAttrib * const attrib = &attribs[n];
    763 
    764         if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
    765             continue;
    766 
    767         // Accept all surface attributes that are not pixel-formats
    768         if (attrib->type != VASurfaceAttribPixelFormat) {
    769             out_num_attribs++;
    770             continue;
    771         }
    772 
    773         // Drop invalid pixel-format attribute
    774         if (!attrib->value.value.i) {
    775             attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
    776             continue;
    777         }
    778 
    779         // Check for duplicates
    780         int is_duplicate = 0;
    781         for (i = n - 1; i >= 0 && !is_duplicate; i--) {
    782             const VASurfaceAttrib * const prev_attrib = &attribs[i];
    783             if (prev_attrib->type != VASurfaceAttribPixelFormat)
    784                 break;
    785             is_duplicate = prev_attrib->value.value.i == attrib->value.value.i;
    786         }
    787         if (is_duplicate)
    788             attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
    789         else
    790             out_num_attribs++;
    791     }
    792 
    793     if (*out_num_attribs_ptr < out_num_attribs) {
    794         *out_num_attribs_ptr = out_num_attribs;
    795         va_status = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
    796         goto end;
    797     }
    798 
    799     out_attrib = out_attribs;
    800     for (n = 0; n < num_attribs; n++) {
    801         const VASurfaceAttrib * const attrib = &attribs[n];
    802         if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
    803             continue;
    804         *out_attrib++ = *attrib;
    805     }
    806 
    807 end:
    808     free(attribs);
    809     free(image_formats);
    810     return va_status;
    811 }
    812 
    813 VAStatus
    814 vaQuerySurfaceAttributes(
    815     VADisplay           dpy,
    816     VAConfigID          config,
    817     VASurfaceAttrib    *attrib_list,
    818     unsigned int       *num_attribs
    819 )
    820 {
    821     VADriverContextP ctx;
    822     VAStatus vaStatus;
    823 
    824     CHECK_DISPLAY(dpy);
    825     ctx = CTX(dpy);
    826     if (!ctx)
    827         return VA_STATUS_ERROR_INVALID_DISPLAY;
    828 
    829     if (!ctx->vtable->vaQuerySurfaceAttributes)
    830         vaStatus = va_impl_query_surface_attributes(ctx, config,
    831                                                     attrib_list, num_attribs);
    832     else
    833         vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
    834                                                          attrib_list, num_attribs);
    835 
    836     VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs);
    837 
    838     return vaStatus;
    839 }
    840 
    841 VAStatus
    842 vaCreateSurfaces(
    843     VADisplay           dpy,
    844     unsigned int        format,
    845     unsigned int        width,
    846     unsigned int        height,
    847     VASurfaceID        *surfaces,
    848     unsigned int        num_surfaces,
    849     VASurfaceAttrib    *attrib_list,
    850     unsigned int        num_attribs
    851 )
    852 {
    853     VADriverContextP ctx;
    854     VAStatus vaStatus;
    855 
    856     CHECK_DISPLAY(dpy);
    857     ctx = CTX(dpy);
    858     if (!ctx)
    859         return VA_STATUS_ERROR_INVALID_DISPLAY;
    860 
    861     if (ctx->vtable->vaCreateSurfaces2)
    862         vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
    863                                               surfaces, num_surfaces,
    864                                               attrib_list, num_attribs);
    865     else if (attrib_list && num_attribs > 0)
    866         vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
    867     else
    868         vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
    869                                                  num_surfaces, surfaces);
    870     VA_TRACE_LOG(va_TraceCreateSurfaces,
    871                  dpy, width, height, format, num_surfaces, surfaces,
    872                  attrib_list, num_attribs);
    873 
    874     return vaStatus;
    875 }
    876 
    877 
    878 VAStatus vaDestroySurfaces (
    879     VADisplay dpy,
    880     VASurfaceID *surface_list,
    881     int num_surfaces
    882 )
    883 {
    884   VADriverContextP ctx;
    885   VAStatus vaStatus;
    886 
    887   CHECK_DISPLAY(dpy);
    888   ctx = CTX(dpy);
    889 
    890   VA_TRACE_LOG(va_TraceDestroySurfaces,
    891                dpy, surface_list, num_surfaces);
    892 
    893   vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
    894 
    895   return vaStatus;
    896 }
    897 
    898 VAStatus vaCreateContext (
    899     VADisplay dpy,
    900     VAConfigID config_id,
    901     int picture_width,
    902     int picture_height,
    903     int flag,
    904     VASurfaceID *render_targets,
    905     int num_render_targets,
    906     VAContextID *context		/* out */
    907 )
    908 {
    909   VADriverContextP ctx;
    910   VAStatus vaStatus;
    911 
    912   CHECK_DISPLAY(dpy);
    913   ctx = CTX(dpy);
    914 
    915   vaStatus = ctx->vtable->vaCreateContext( ctx, config_id, picture_width, picture_height,
    916                                       flag, render_targets, num_render_targets, context );
    917 
    918   /* keep current encode/decode resoluton */
    919   VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context);
    920 
    921   return vaStatus;
    922 }
    923 
    924 VAStatus vaDestroyContext (
    925     VADisplay dpy,
    926     VAContextID context
    927 )
    928 {
    929   VADriverContextP ctx;
    930   CHECK_DISPLAY(dpy);
    931   ctx = CTX(dpy);
    932 
    933   return ctx->vtable->vaDestroyContext( ctx, context );
    934 }
    935 
    936 VAStatus vaCreateBuffer (
    937     VADisplay dpy,
    938     VAContextID context,	/* in */
    939     VABufferType type,		/* in */
    940     unsigned int size,		/* in */
    941     unsigned int num_elements,	/* in */
    942     void *data,			/* in */
    943     VABufferID *buf_id		/* out */
    944 )
    945 {
    946   VADriverContextP ctx;
    947   VAStatus vaStatus;
    948 
    949   CHECK_DISPLAY(dpy);
    950   ctx = CTX(dpy);
    951 
    952   VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id);
    953 
    954   vaStatus = ctx->vtable->vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id);
    955 
    956   VA_TRACE_LOG(va_TraceCreateBuffer,
    957                dpy, context, type, size, num_elements, data, buf_id);
    958 
    959   return vaStatus;
    960 }
    961 
    962 VAStatus vaBufferSetNumElements (
    963     VADisplay dpy,
    964     VABufferID buf_id,	/* in */
    965     unsigned int num_elements /* in */
    966 )
    967 {
    968   VADriverContextP ctx;
    969   CHECK_DISPLAY(dpy);
    970   ctx = CTX(dpy);
    971 
    972   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
    973 
    974   return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements );
    975 }
    976 
    977 
    978 VAStatus vaMapBuffer (
    979     VADisplay dpy,
    980     VABufferID buf_id,	/* in */
    981     void **pbuf 	/* out */
    982 )
    983 {
    984   VADriverContextP ctx;
    985   VAStatus va_status;
    986 
    987   CHECK_DISPLAY(dpy);
    988   ctx = CTX(dpy);
    989 
    990   VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf);
    991 
    992   va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf );
    993 
    994   VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf);
    995 
    996   return va_status;
    997 }
    998 
    999 VAStatus vaUnmapBuffer (
   1000     VADisplay dpy,
   1001     VABufferID buf_id	/* in */
   1002 )
   1003 {
   1004   VADriverContextP ctx;
   1005   CHECK_DISPLAY(dpy);
   1006   ctx = CTX(dpy);
   1007 
   1008   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1009 
   1010   return ctx->vtable->vaUnmapBuffer( ctx, buf_id );
   1011 }
   1012 
   1013 VAStatus vaDestroyBuffer (
   1014     VADisplay dpy,
   1015     VABufferID buffer_id
   1016 )
   1017 {
   1018   VADriverContextP ctx;
   1019   CHECK_DISPLAY(dpy);
   1020   ctx = CTX(dpy);
   1021 
   1022   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1023 
   1024   VA_TRACE_LOG(va_TraceDestroyBuffer,
   1025                dpy, buffer_id);
   1026 
   1027   return ctx->vtable->vaDestroyBuffer( ctx, buffer_id );
   1028 }
   1029 
   1030 VAStatus vaBufferInfo (
   1031     VADisplay dpy,
   1032     VAContextID __maybe_unused context,	/* in */
   1033     VABufferID buf_id,		/* in */
   1034     VABufferType *type,		/* out */
   1035     unsigned int *size,		/* out */
   1036     unsigned int *num_elements	/* out */
   1037 )
   1038 {
   1039     VADriverContextP ctx;
   1040 
   1041     CHECK_DISPLAY(dpy);
   1042     ctx = CTX(dpy);
   1043 
   1044     VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements);
   1045 
   1046     return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements );
   1047 }
   1048 
   1049 VAStatus vaBeginPicture (
   1050     VADisplay dpy,
   1051     VAContextID context,
   1052     VASurfaceID render_target
   1053 )
   1054 {
   1055   VADriverContextP ctx;
   1056   VAStatus va_status;
   1057 
   1058   CHECK_DISPLAY(dpy);
   1059   ctx = CTX(dpy);
   1060 
   1061   VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target);
   1062   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1063 
   1064   va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target );
   1065 
   1066   return va_status;
   1067 }
   1068 
   1069 VAStatus vaRenderPicture (
   1070     VADisplay dpy,
   1071     VAContextID context,
   1072     VABufferID *buffers,
   1073     int num_buffers
   1074 )
   1075 {
   1076   VADriverContextP ctx;
   1077 
   1078   CHECK_DISPLAY(dpy);
   1079   ctx = CTX(dpy);
   1080 
   1081   VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
   1082   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1083 
   1084   return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers );
   1085 }
   1086 
   1087 VAStatus vaEndPicture (
   1088     VADisplay dpy,
   1089     VAContextID context
   1090 )
   1091 {
   1092   VAStatus va_status = VA_STATUS_SUCCESS;
   1093   VADriverContextP ctx;
   1094 
   1095   CHECK_DISPLAY(dpy);
   1096   ctx = CTX(dpy);
   1097 
   1098   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1099 
   1100   va_status = ctx->vtable->vaEndPicture( ctx, context );
   1101 
   1102   /* dump surface content */
   1103   VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1);
   1104 
   1105   return va_status;
   1106 }
   1107 
   1108 VAStatus vaSyncSurface (
   1109     VADisplay dpy,
   1110     VASurfaceID render_target
   1111 )
   1112 {
   1113   VAStatus va_status;
   1114   VADriverContextP ctx;
   1115 
   1116   CHECK_DISPLAY(dpy);
   1117   ctx = CTX(dpy);
   1118 
   1119   va_status = ctx->vtable->vaSyncSurface( ctx, render_target );
   1120   VA_TRACE_LOG(va_TraceSyncSurface, dpy, render_target);
   1121 
   1122   return va_status;
   1123 }
   1124 
   1125 VAStatus vaQuerySurfaceStatus (
   1126     VADisplay dpy,
   1127     VASurfaceID render_target,
   1128     VASurfaceStatus *status	/* out */
   1129 )
   1130 {
   1131   VAStatus va_status;
   1132   VADriverContextP ctx;
   1133   CHECK_DISPLAY(dpy);
   1134   ctx = CTX(dpy);
   1135 
   1136   va_status = ctx->vtable->vaQuerySurfaceStatus( ctx, render_target, status );
   1137 
   1138   VA_TRACE_LOG(va_TraceQuerySurfaceStatus, dpy, render_target, status);
   1139 
   1140   return va_status;
   1141 }
   1142 
   1143 VAStatus vaQuerySurfaceError (
   1144 	VADisplay dpy,
   1145 	VASurfaceID surface,
   1146 	VAStatus error_status,
   1147 	void **error_info /*out*/
   1148 )
   1149 {
   1150   VAStatus va_status;
   1151   VADriverContextP ctx;
   1152   CHECK_DISPLAY(dpy);
   1153   ctx = CTX(dpy);
   1154 
   1155   va_status = ctx->vtable->vaQuerySurfaceError( ctx, surface, error_status, error_info );
   1156 
   1157   VA_TRACE_LOG(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info);
   1158 
   1159   return va_status;
   1160 }
   1161 
   1162 /* Get maximum number of image formats supported by the implementation */
   1163 int vaMaxNumImageFormats (
   1164     VADisplay dpy
   1165 )
   1166 {
   1167   if (!vaDisplayIsValid(dpy))
   1168       return 0;
   1169 
   1170   return CTX(dpy)->max_image_formats;
   1171 }
   1172 
   1173 VAStatus vaQueryImageFormats (
   1174     VADisplay dpy,
   1175     VAImageFormat *format_list,	/* out */
   1176     int *num_formats		/* out */
   1177 )
   1178 {
   1179   VADriverContextP ctx;
   1180   CHECK_DISPLAY(dpy);
   1181   ctx = CTX(dpy);
   1182 
   1183   return ctx->vtable->vaQueryImageFormats ( ctx, format_list, num_formats);
   1184 }
   1185 
   1186 /*
   1187  * The width and height fields returned in the VAImage structure may get
   1188  * enlarged for some YUV formats. The size of the data buffer that needs
   1189  * to be allocated will be given in the "data_size" field in VAImage.
   1190  * Image data is not allocated by this function.  The client should
   1191  * allocate the memory and fill in the VAImage structure's data field
   1192  * after looking at "data_size" returned from the library.
   1193  */
   1194 VAStatus vaCreateImage (
   1195     VADisplay dpy,
   1196     VAImageFormat *format,
   1197     int width,
   1198     int height,
   1199     VAImage *image	/* out */
   1200 )
   1201 {
   1202   VADriverContextP ctx;
   1203   CHECK_DISPLAY(dpy);
   1204   ctx = CTX(dpy);
   1205 
   1206   return ctx->vtable->vaCreateImage ( ctx, format, width, height, image);
   1207 }
   1208 
   1209 /*
   1210  * Should call DestroyImage before destroying the surface it is bound to
   1211  */
   1212 VAStatus vaDestroyImage (
   1213     VADisplay dpy,
   1214     VAImageID image
   1215 )
   1216 {
   1217   VADriverContextP ctx;
   1218   CHECK_DISPLAY(dpy);
   1219   ctx = CTX(dpy);
   1220 
   1221   return ctx->vtable->vaDestroyImage ( ctx, image);
   1222 }
   1223 
   1224 VAStatus vaSetImagePalette (
   1225     VADisplay dpy,
   1226     VAImageID image,
   1227     unsigned char *palette
   1228 )
   1229 {
   1230   VADriverContextP ctx;
   1231   CHECK_DISPLAY(dpy);
   1232   ctx = CTX(dpy);
   1233 
   1234   return ctx->vtable->vaSetImagePalette ( ctx, image, palette);
   1235 }
   1236 
   1237 /*
   1238  * Retrieve surface data into a VAImage
   1239  * Image must be in a format supported by the implementation
   1240  */
   1241 VAStatus vaGetImage (
   1242     VADisplay dpy,
   1243     VASurfaceID surface,
   1244     int x,	/* coordinates of the upper left source pixel */
   1245     int y,
   1246     unsigned int width, /* width and height of the region */
   1247     unsigned int height,
   1248     VAImageID image
   1249 )
   1250 {
   1251   VADriverContextP ctx;
   1252   CHECK_DISPLAY(dpy);
   1253   ctx = CTX(dpy);
   1254 
   1255   return ctx->vtable->vaGetImage ( ctx, surface, x, y, width, height, image);
   1256 }
   1257 
   1258 /*
   1259  * Copy data from a VAImage to a surface
   1260  * Image must be in a format supported by the implementation
   1261  */
   1262 VAStatus vaPutImage (
   1263     VADisplay dpy,
   1264     VASurfaceID surface,
   1265     VAImageID image,
   1266     int src_x,
   1267     int src_y,
   1268     unsigned int src_width,
   1269     unsigned int src_height,
   1270     int dest_x,
   1271     int dest_y,
   1272     unsigned int dest_width,
   1273     unsigned int dest_height
   1274 )
   1275 {
   1276   VADriverContextP ctx;
   1277   CHECK_DISPLAY(dpy);
   1278   ctx = CTX(dpy);
   1279 
   1280   return ctx->vtable->vaPutImage ( ctx, surface, image, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height );
   1281 }
   1282 
   1283 /*
   1284  * Derive an VAImage from an existing surface.
   1285  * This interface will derive a VAImage and corresponding image buffer from
   1286  * an existing VA Surface. The image buffer can then be mapped/unmapped for
   1287  * direct CPU access. This operation is only possible on implementations with
   1288  * direct rendering capabilities and internal surface formats that can be
   1289  * represented with a VAImage. When the operation is not possible this interface
   1290  * will return VA_STATUS_ERROR_OPERATION_FAILED. Clients should then fall back
   1291  * to using vaCreateImage + vaPutImage to accomplish the same task in an
   1292  * indirect manner.
   1293  *
   1294  * Implementations should only return success when the resulting image buffer
   1295  * would be useable with vaMap/Unmap.
   1296  *
   1297  * When directly accessing a surface special care must be taken to insure
   1298  * proper synchronization with the graphics hardware. Clients should call
   1299  * vaQuerySurfaceStatus to insure that a surface is not the target of concurrent
   1300  * rendering or currently being displayed by an overlay.
   1301  *
   1302  * Additionally nothing about the contents of a surface should be assumed
   1303  * following a vaPutSurface. Implementations are free to modify the surface for
   1304  * scaling or subpicture blending within a call to vaPutImage.
   1305  *
   1306  * Calls to vaPutImage or vaGetImage using the same surface from which the image
   1307  * has been derived will return VA_STATUS_ERROR_SURFACE_BUSY. vaPutImage or
   1308  * vaGetImage with other surfaces is supported.
   1309  *
   1310  * An image created with vaDeriveImage should be freed with vaDestroyImage. The
   1311  * image and image buffer structures will be destroyed; however, the underlying
   1312  * surface will remain unchanged until freed with vaDestroySurfaces.
   1313  */
   1314 VAStatus vaDeriveImage (
   1315     VADisplay dpy,
   1316     VASurfaceID surface,
   1317     VAImage *image	/* out */
   1318 )
   1319 {
   1320   VADriverContextP ctx;
   1321   CHECK_DISPLAY(dpy);
   1322   ctx = CTX(dpy);
   1323 
   1324   return ctx->vtable->vaDeriveImage ( ctx, surface, image );
   1325 }
   1326 
   1327 
   1328 /* Get maximum number of subpicture formats supported by the implementation */
   1329 int vaMaxNumSubpictureFormats (
   1330     VADisplay dpy
   1331 )
   1332 {
   1333   if (!vaDisplayIsValid(dpy))
   1334       return 0;
   1335 
   1336   return CTX(dpy)->max_subpic_formats;
   1337 }
   1338 
   1339 /*
   1340  * Query supported subpicture formats
   1341  * The caller must provide a "format_list" array that can hold at
   1342  * least vaMaxNumSubpictureFormats() entries. The flags arrary holds the flag
   1343  * for each format to indicate additional capabilities for that format. The actual
   1344  * number of formats returned in "format_list" is returned in "num_formats".
   1345  */
   1346 VAStatus vaQuerySubpictureFormats (
   1347     VADisplay dpy,
   1348     VAImageFormat *format_list,	/* out */
   1349     unsigned int *flags,	/* out */
   1350     unsigned int *num_formats	/* out */
   1351 )
   1352 {
   1353   VADriverContextP ctx;
   1354 
   1355   CHECK_DISPLAY(dpy);
   1356   ctx = CTX(dpy);
   1357 
   1358   return ctx->vtable->vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats);
   1359 }
   1360 
   1361 /*
   1362  * Subpictures are created with an image associated.
   1363  */
   1364 VAStatus vaCreateSubpicture (
   1365     VADisplay dpy,
   1366     VAImageID image,
   1367     VASubpictureID *subpicture	/* out */
   1368 )
   1369 {
   1370   VADriverContextP ctx;
   1371   CHECK_DISPLAY(dpy);
   1372   ctx = CTX(dpy);
   1373 
   1374   return ctx->vtable->vaCreateSubpicture ( ctx, image, subpicture );
   1375 }
   1376 
   1377 /*
   1378  * Destroy the subpicture before destroying the image it is assocated to
   1379  */
   1380 VAStatus vaDestroySubpicture (
   1381     VADisplay dpy,
   1382     VASubpictureID subpicture
   1383 )
   1384 {
   1385   VADriverContextP ctx;
   1386   CHECK_DISPLAY(dpy);
   1387   ctx = CTX(dpy);
   1388 
   1389   return ctx->vtable->vaDestroySubpicture ( ctx, subpicture);
   1390 }
   1391 
   1392 VAStatus vaSetSubpictureImage (
   1393     VADisplay dpy,
   1394     VASubpictureID subpicture,
   1395     VAImageID image
   1396 )
   1397 {
   1398   VADriverContextP ctx;
   1399   CHECK_DISPLAY(dpy);
   1400   ctx = CTX(dpy);
   1401 
   1402   return ctx->vtable->vaSetSubpictureImage ( ctx, subpicture, image);
   1403 }
   1404 
   1405 
   1406 /*
   1407  * If chromakey is enabled, then the area where the source value falls within
   1408  * the chromakey [min, max] range is transparent
   1409  */
   1410 VAStatus vaSetSubpictureChromakey (
   1411     VADisplay dpy,
   1412     VASubpictureID subpicture,
   1413     unsigned int chromakey_min,
   1414     unsigned int chromakey_max,
   1415     unsigned int chromakey_mask
   1416 )
   1417 {
   1418   VADriverContextP ctx;
   1419   CHECK_DISPLAY(dpy);
   1420   ctx = CTX(dpy);
   1421 
   1422   return ctx->vtable->vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask );
   1423 }
   1424 
   1425 
   1426 /*
   1427  * Global alpha value is between 0 and 1. A value of 1 means fully opaque and
   1428  * a value of 0 means fully transparent. If per-pixel alpha is also specified then
   1429  * the overall alpha is per-pixel alpha multiplied by the global alpha
   1430  */
   1431 VAStatus vaSetSubpictureGlobalAlpha (
   1432     VADisplay dpy,
   1433     VASubpictureID subpicture,
   1434     float global_alpha
   1435 )
   1436 {
   1437   VADriverContextP ctx;
   1438   CHECK_DISPLAY(dpy);
   1439   ctx = CTX(dpy);
   1440 
   1441   return ctx->vtable->vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha );
   1442 }
   1443 
   1444 /*
   1445   vaAssociateSubpicture associates the subpicture with the target_surface.
   1446   It defines the region mapping between the subpicture and the target
   1447   surface through source and destination rectangles (with the same width and height).
   1448   Both will be displayed at the next call to vaPutSurface.  Additional
   1449   associations before the call to vaPutSurface simply overrides the association.
   1450 */
   1451 VAStatus vaAssociateSubpicture (
   1452     VADisplay dpy,
   1453     VASubpictureID subpicture,
   1454     VASurfaceID *target_surfaces,
   1455     int num_surfaces,
   1456     short src_x, /* upper left offset in subpicture */
   1457     short src_y,
   1458     unsigned short src_width,
   1459     unsigned short src_height,
   1460     short dest_x, /* upper left offset in surface */
   1461     short dest_y,
   1462     unsigned short dest_width,
   1463     unsigned short dest_height,
   1464     /*
   1465      * whether to enable chroma-keying or global-alpha
   1466      * see VA_SUBPICTURE_XXX values
   1467      */
   1468     unsigned int flags
   1469 )
   1470 {
   1471   VADriverContextP ctx;
   1472   CHECK_DISPLAY(dpy);
   1473   ctx = CTX(dpy);
   1474 
   1475   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 );
   1476 }
   1477 
   1478 /*
   1479  * vaDeassociateSubpicture removes the association of the subpicture with target_surfaces.
   1480  */
   1481 VAStatus vaDeassociateSubpicture (
   1482     VADisplay dpy,
   1483     VASubpictureID subpicture,
   1484     VASurfaceID *target_surfaces,
   1485     int num_surfaces
   1486 )
   1487 {
   1488   VADriverContextP ctx;
   1489   CHECK_DISPLAY(dpy);
   1490   ctx = CTX(dpy);
   1491 
   1492   return ctx->vtable->vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces );
   1493 }
   1494 
   1495 
   1496 /* Get maximum number of display attributes supported by the implementation */
   1497 int vaMaxNumDisplayAttributes (
   1498     VADisplay dpy
   1499 )
   1500 {
   1501   int tmp;
   1502 
   1503   if (!vaDisplayIsValid(dpy))
   1504       return 0;
   1505 
   1506   tmp = CTX(dpy)->max_display_attributes;
   1507 
   1508   VA_TRACE_LOG(va_TraceMaxNumDisplayAttributes, dpy, tmp);
   1509 
   1510   return tmp;
   1511 }
   1512 
   1513 /*
   1514  * Query display attributes
   1515  * The caller must provide a "attr_list" array that can hold at
   1516  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
   1517  * returned in "attr_list" is returned in "num_attributes".
   1518  */
   1519 VAStatus vaQueryDisplayAttributes (
   1520     VADisplay dpy,
   1521     VADisplayAttribute *attr_list,	/* out */
   1522     int *num_attributes			/* out */
   1523 )
   1524 {
   1525   VADriverContextP ctx;
   1526   VAStatus va_status;
   1527 
   1528   CHECK_DISPLAY(dpy);
   1529   ctx = CTX(dpy);
   1530   va_status = ctx->vtable->vaQueryDisplayAttributes ( ctx, attr_list, num_attributes );
   1531 
   1532   VA_TRACE_LOG(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes);
   1533 
   1534   return va_status;
   1535 
   1536 }
   1537 
   1538 /*
   1539  * Get display attributes
   1540  * This function returns the current attribute values in "attr_list".
   1541  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
   1542  * from vaQueryDisplayAttributes() can have their values retrieved.
   1543  */
   1544 VAStatus vaGetDisplayAttributes (
   1545     VADisplay dpy,
   1546     VADisplayAttribute *attr_list,	/* in/out */
   1547     int num_attributes
   1548 )
   1549 {
   1550   VADriverContextP ctx;
   1551   VAStatus va_status;
   1552 
   1553   CHECK_DISPLAY(dpy);
   1554   ctx = CTX(dpy);
   1555   va_status = ctx->vtable->vaGetDisplayAttributes ( ctx, attr_list, num_attributes );
   1556 
   1557   VA_TRACE_LOG(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes);
   1558 
   1559   return va_status;
   1560 }
   1561 
   1562 /*
   1563  * Set display attributes
   1564  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
   1565  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or
   1566  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
   1567  */
   1568 VAStatus vaSetDisplayAttributes (
   1569     VADisplay dpy,
   1570     VADisplayAttribute *attr_list,
   1571     int num_attributes
   1572 )
   1573 {
   1574   VADriverContextP ctx;
   1575   VAStatus va_status;
   1576   CHECK_DISPLAY(dpy);
   1577   ctx = CTX(dpy);
   1578 
   1579   va_status = ctx->vtable->vaSetDisplayAttributes ( ctx, attr_list, num_attributes );
   1580   VA_TRACE_LOG(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes);
   1581 
   1582   return va_status;
   1583 }
   1584 
   1585 VAStatus vaLockSurface(VADisplay dpy,
   1586     VASurfaceID surface,
   1587     unsigned int *fourcc, /* following are output argument */
   1588     unsigned int *luma_stride,
   1589     unsigned int *chroma_u_stride,
   1590     unsigned int *chroma_v_stride,
   1591     unsigned int *luma_offset,
   1592     unsigned int *chroma_u_offset,
   1593     unsigned int *chroma_v_offset,
   1594     unsigned int *buffer_name,
   1595     void **buffer
   1596 )
   1597 {
   1598   VADriverContextP ctx;
   1599   CHECK_DISPLAY(dpy);
   1600   ctx = CTX(dpy);
   1601 
   1602   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);
   1603 }
   1604 
   1605 
   1606 VAStatus vaUnlockSurface(VADisplay dpy,
   1607     VASurfaceID surface
   1608 )
   1609 {
   1610   VADriverContextP ctx;
   1611   CHECK_DISPLAY(dpy);
   1612   ctx = CTX(dpy);
   1613 
   1614   return ctx->vtable->vaUnlockSurface( ctx, surface );
   1615 }
   1616 
   1617 /* Video Processing */
   1618 #define VA_VPP_INIT_CONTEXT(ctx, dpy) do {              \
   1619         CHECK_DISPLAY(dpy);                             \
   1620         ctx = CTX(dpy);                                 \
   1621         if (!ctx)                                       \
   1622             return VA_STATUS_ERROR_INVALID_DISPLAY;     \
   1623     } while (0)
   1624 
   1625 #define VA_VPP_INVOKE(dpy, func, args) do {             \
   1626         if (!ctx->vtable_vpp->va##func)                 \
   1627             return VA_STATUS_ERROR_UNIMPLEMENTED;       \
   1628         status = ctx->vtable_vpp->va##func args;        \
   1629     } while (0)
   1630 
   1631 VAStatus
   1632 vaQueryVideoProcFilters(
   1633     VADisplay           dpy,
   1634     VAContextID         context,
   1635     VAProcFilterType   *filters,
   1636     unsigned int       *num_filters
   1637 )
   1638 {
   1639     VADriverContextP ctx;
   1640     VAStatus status;
   1641 
   1642     VA_VPP_INIT_CONTEXT(ctx, dpy);
   1643     VA_VPP_INVOKE(
   1644         ctx,
   1645         QueryVideoProcFilters,
   1646         (ctx, context, filters, num_filters)
   1647     );
   1648     return status;
   1649 }
   1650 
   1651 VAStatus
   1652 vaQueryVideoProcFilterCaps(
   1653     VADisplay           dpy,
   1654     VAContextID         context,
   1655     VAProcFilterType    type,
   1656     void               *filter_caps,
   1657     unsigned int       *num_filter_caps
   1658 )
   1659 {
   1660     VADriverContextP ctx;
   1661     VAStatus status;
   1662 
   1663     VA_VPP_INIT_CONTEXT(ctx, dpy);
   1664     VA_VPP_INVOKE(
   1665         ctx,
   1666         QueryVideoProcFilterCaps,
   1667         (ctx, context, type, filter_caps, num_filter_caps)
   1668     );
   1669     return status;
   1670 }
   1671 
   1672 VAStatus
   1673 vaQueryVideoProcPipelineCaps(
   1674     VADisplay           dpy,
   1675     VAContextID         context,
   1676     VABufferID         *filters,
   1677     unsigned int        num_filters,
   1678     VAProcPipelineCaps *pipeline_caps
   1679 )
   1680 {
   1681     VADriverContextP ctx;
   1682     VAStatus status;
   1683 
   1684     VA_VPP_INIT_CONTEXT(ctx, dpy);
   1685     VA_VPP_INVOKE(
   1686         ctx,
   1687         QueryVideoProcPipelineCaps,
   1688         (ctx, context, filters, num_filters, pipeline_caps)
   1689     );
   1690     return status;
   1691 }
   1692