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         driver_name = "pvr";
    468         vaStatus = VA_STATUS_SUCCESS;
    469         va_infoMessage("User requested driver '%s'\n", driver_name);
    470     }
    471 
    472     if ((VA_STATUS_SUCCESS == vaStatus) && (driver_name != NULL)) {
    473         vaStatus = va_openDriver(dpy, driver_name);
    474         va_infoMessage("va_openDriver() returns %d, driver_name = %s\n", vaStatus, driver_name);
    475 
    476         *major_version = VA_MAJOR_VERSION;
    477         *minor_version = VA_MINOR_VERSION;
    478     } else
    479         va_errorMessage("va_getDriverName() failed with %s,driver_name=%s\n",
    480                         vaErrorStr(vaStatus), driver_name);
    481 
    482     VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version);
    483 
    484     return vaStatus;
    485 }
    486 
    487 
    488 /*
    489  * After this call, all library internal resources will be cleaned up
    490  */
    491 VAStatus vaTerminate (
    492     VADisplay dpy
    493 )
    494 {
    495   VAStatus vaStatus = VA_STATUS_SUCCESS;
    496   VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
    497   VADriverContextP old_ctx;
    498 
    499   CHECK_DISPLAY(dpy);
    500   old_ctx = CTX(dpy);
    501 
    502   if (old_ctx->handle) {
    503       vaStatus = old_ctx->vtable->vaTerminate(old_ctx);
    504       dlclose(old_ctx->handle);
    505       old_ctx->handle = NULL;
    506   }
    507   free(old_ctx->vtable);
    508   old_ctx->vtable = NULL;
    509   free(old_ctx->vtable_vpp);
    510   old_ctx->vtable_vpp = NULL;
    511 
    512   VA_TRACE_LOG(va_TraceTerminate, dpy);
    513 
    514   va_TraceEnd(dpy);
    515 
    516   va_FoolEnd(dpy);
    517 
    518   if (VA_STATUS_SUCCESS == vaStatus)
    519       pDisplayContext->vaDestroy(pDisplayContext);
    520 
    521   return vaStatus;
    522 }
    523 
    524 /*
    525  * vaQueryVendorString returns a pointer to a zero-terminated string
    526  * describing some aspects of the VA implemenation on a specific
    527  * hardware accelerator. The format of the returned string is:
    528  * <vendorname>-<major_version>-<minor_version>-<addtional_info>
    529  * e.g. for the Intel GMA500 implementation, an example would be:
    530  * "IntelGMA500-1.0-0.2-patch3
    531  */
    532 const char *vaQueryVendorString (
    533     VADisplay dpy
    534 )
    535 {
    536   if (!vaDisplayIsValid(dpy))
    537       return NULL;
    538 
    539   return CTX(dpy)->str_vendor;
    540 }
    541 
    542 
    543 /* Get maximum number of profiles supported by the implementation */
    544 int vaMaxNumProfiles (
    545     VADisplay dpy
    546 )
    547 {
    548   if (!vaDisplayIsValid(dpy))
    549       return 0;
    550 
    551   return CTX(dpy)->max_profiles;
    552 }
    553 
    554 /* Get maximum number of entrypoints supported by the implementation */
    555 int vaMaxNumEntrypoints (
    556     VADisplay dpy
    557 )
    558 {
    559   if (!vaDisplayIsValid(dpy))
    560       return 0;
    561 
    562   return CTX(dpy)->max_entrypoints;
    563 }
    564 
    565 
    566 /* Get maximum number of attributs supported by the implementation */
    567 int vaMaxNumConfigAttributes (
    568     VADisplay dpy
    569 )
    570 {
    571   if (!vaDisplayIsValid(dpy))
    572       return 0;
    573 
    574   return CTX(dpy)->max_attributes;
    575 }
    576 
    577 VAStatus vaQueryConfigEntrypoints (
    578     VADisplay dpy,
    579     VAProfile profile,
    580     VAEntrypoint *entrypoints,	/* out */
    581     int *num_entrypoints	/* out */
    582 )
    583 {
    584   VADriverContextP ctx;
    585   CHECK_DISPLAY(dpy);
    586   ctx = CTX(dpy);
    587 
    588   return ctx->vtable->vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
    589 }
    590 
    591 VAStatus vaGetConfigAttributes (
    592     VADisplay dpy,
    593     VAProfile profile,
    594     VAEntrypoint entrypoint,
    595     VAConfigAttrib *attrib_list, /* in/out */
    596     int num_attribs
    597 )
    598 {
    599   VADriverContextP ctx;
    600   CHECK_DISPLAY(dpy);
    601   ctx = CTX(dpy);
    602 
    603   return ctx->vtable->vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
    604 }
    605 
    606 VAStatus vaQueryConfigProfiles (
    607     VADisplay dpy,
    608     VAProfile *profile_list,	/* out */
    609     int *num_profiles		/* out */
    610 )
    611 {
    612   VADriverContextP ctx;
    613   CHECK_DISPLAY(dpy);
    614   ctx = CTX(dpy);
    615 
    616   return ctx->vtable->vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
    617 }
    618 
    619 VAStatus vaCreateConfig (
    620     VADisplay dpy,
    621     VAProfile profile,
    622     VAEntrypoint entrypoint,
    623     VAConfigAttrib *attrib_list,
    624     int num_attribs,
    625     VAConfigID *config_id /* out */
    626 )
    627 {
    628   VADriverContextP ctx;
    629   VAStatus vaStatus = VA_STATUS_SUCCESS;
    630 
    631   CHECK_DISPLAY(dpy);
    632   ctx = CTX(dpy);
    633 
    634   vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
    635 
    636   /* record the current entrypoint for further trace/fool determination */
    637   VA_TRACE_ALL(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
    638   VA_FOOL_FUNC(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
    639 
    640   return vaStatus;
    641 }
    642 
    643 VAStatus vaDestroyConfig (
    644     VADisplay dpy,
    645     VAConfigID config_id
    646 )
    647 {
    648   VADriverContextP ctx;
    649   CHECK_DISPLAY(dpy);
    650   ctx = CTX(dpy);
    651 
    652   return ctx->vtable->vaDestroyConfig ( ctx, config_id );
    653 }
    654 
    655 VAStatus vaQueryConfigAttributes (
    656     VADisplay dpy,
    657     VAConfigID config_id,
    658     VAProfile *profile, 	/* out */
    659     VAEntrypoint *entrypoint, 	/* out */
    660     VAConfigAttrib *attrib_list,/* out */
    661     int *num_attribs		/* out */
    662 )
    663 {
    664   VADriverContextP ctx;
    665   CHECK_DISPLAY(dpy);
    666   ctx = CTX(dpy);
    667 
    668   return ctx->vtable->vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
    669 }
    670 
    671 /* XXX: this is a slow implementation that will be removed */
    672 static VAStatus
    673 va_impl_query_surface_attributes(
    674     VADriverContextP    ctx,
    675     VAConfigID          config,
    676     VASurfaceAttrib    *out_attribs,
    677     unsigned int       *out_num_attribs_ptr
    678 )
    679 {
    680     VASurfaceAttrib *attribs = NULL;
    681     unsigned int num_attribs, n;
    682     VASurfaceAttrib *out_attrib;
    683     unsigned int out_num_attribs;
    684     VAImageFormat *image_formats = NULL;
    685     int num_image_formats, i;
    686     VAStatus va_status;
    687 
    688     /* List of surface attributes to query */
    689     struct va_surface_attrib_map {
    690         VASurfaceAttribType type;
    691         VAGenericValueType  value_type;
    692     };
    693     static const struct va_surface_attrib_map attribs_map[] = {
    694         { VASurfaceAttribMinWidth,      VAGenericValueTypeInteger },
    695         { VASurfaceAttribMaxWidth,      VAGenericValueTypeInteger },
    696         { VASurfaceAttribMinHeight,     VAGenericValueTypeInteger },
    697         { VASurfaceAttribMaxHeight,     VAGenericValueTypeInteger },
    698         { VASurfaceAttribMemoryType,    VAGenericValueTypeInteger },
    699         { VASurfaceAttribNone, }
    700     };
    701 
    702     if (!out_attribs || !out_num_attribs_ptr)
    703         return VA_STATUS_ERROR_INVALID_PARAMETER;
    704     if (!ctx->vtable->vaGetSurfaceAttributes)
    705         return VA_STATUS_ERROR_UNIMPLEMENTED;
    706 
    707     num_image_formats = ctx->max_image_formats;
    708     image_formats = malloc(num_image_formats * sizeof(*image_formats));
    709     if (!image_formats) {
    710         va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
    711         goto end;
    712     }
    713 
    714     va_status = ctx->vtable->vaQueryImageFormats(
    715         ctx, image_formats, &num_image_formats);
    716     if (va_status != VA_STATUS_SUCCESS)
    717         goto end;
    718 
    719     num_attribs = VASurfaceAttribCount + num_image_formats;
    720     attribs = malloc(num_attribs * sizeof(*attribs));
    721     if (!attribs) {
    722         va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
    723         goto end;
    724     }
    725 
    726     /* Initialize with base surface attributes, except pixel-formats */
    727     for (n = 0; attribs_map[n].type != VASurfaceAttribNone; n++) {
    728         VASurfaceAttrib * const attrib = &attribs[n];
    729         attrib->type = attribs_map[n].type;
    730         attrib->flags = VA_SURFACE_ATTRIB_GETTABLE;
    731         attrib->value.type = attribs_map[n].value_type;
    732     }
    733 
    734     /* Append image formats */
    735     for (i = 0; i < num_image_formats; i++) {
    736         VASurfaceAttrib * const attrib = &attribs[n];
    737         attrib->type = VASurfaceAttribPixelFormat;
    738         attrib->flags = VA_SURFACE_ATTRIB_GETTABLE|VA_SURFACE_ATTRIB_SETTABLE;
    739         attrib->value.type = VAGenericValueTypeInteger;
    740         attrib->value.value.i = image_formats[i].fourcc;
    741         if (++n == num_attribs) {
    742             va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
    743             goto end;
    744         }
    745     }
    746     num_attribs = n;
    747 
    748     va_status = ctx->vtable->vaGetSurfaceAttributes(
    749         ctx, config, attribs, num_attribs);
    750     if (va_status != VA_STATUS_SUCCESS)
    751         goto end;
    752 
    753     /* Remove invalid entries */
    754     out_num_attribs = 0;
    755     for (n = 0; n < num_attribs; n++) {
    756         VASurfaceAttrib * const attrib = &attribs[n];
    757 
    758         if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
    759             continue;
    760 
    761         // Accept all surface attributes that are not pixel-formats
    762         if (attrib->type != VASurfaceAttribPixelFormat) {
    763             out_num_attribs++;
    764             continue;
    765         }
    766 
    767         // Drop invalid pixel-format attribute
    768         if (!attrib->value.value.i) {
    769             attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
    770             continue;
    771         }
    772 
    773         // Check for duplicates
    774         int is_duplicate = 0;
    775         for (i = n - 1; i >= 0 && !is_duplicate; i--) {
    776             const VASurfaceAttrib * const prev_attrib = &attribs[i];
    777             if (prev_attrib->type != VASurfaceAttribPixelFormat)
    778                 break;
    779             is_duplicate = prev_attrib->value.value.i == attrib->value.value.i;
    780         }
    781         if (is_duplicate)
    782             attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
    783         else
    784             out_num_attribs++;
    785     }
    786 
    787     if (*out_num_attribs_ptr < out_num_attribs) {
    788         *out_num_attribs_ptr = out_num_attribs;
    789         va_status = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
    790         goto end;
    791     }
    792 
    793     out_attrib = out_attribs;
    794     for (n = 0; n < num_attribs; n++) {
    795         const VASurfaceAttrib * const attrib = &attribs[n];
    796         if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
    797             continue;
    798         *out_attrib++ = *attrib;
    799     }
    800 
    801 end:
    802     free(attribs);
    803     free(image_formats);
    804     return va_status;
    805 }
    806 
    807 VAStatus
    808 vaQuerySurfaceAttributes(
    809     VADisplay           dpy,
    810     VAConfigID          config,
    811     VASurfaceAttrib    *attrib_list,
    812     unsigned int       *num_attribs
    813 )
    814 {
    815     VADriverContextP ctx;
    816     VAStatus vaStatus;
    817 
    818     CHECK_DISPLAY(dpy);
    819     ctx = CTX(dpy);
    820     if (!ctx)
    821         return VA_STATUS_ERROR_INVALID_DISPLAY;
    822 
    823     if (!ctx->vtable->vaQuerySurfaceAttributes)
    824         vaStatus = va_impl_query_surface_attributes(ctx, config,
    825                                                     attrib_list, num_attribs);
    826     else
    827         vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
    828                                                          attrib_list, num_attribs);
    829 
    830     VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs);
    831 
    832     return vaStatus;
    833 }
    834 
    835 VAStatus
    836 vaCreateSurfaces(
    837     VADisplay           dpy,
    838     unsigned int        format,
    839     unsigned int        width,
    840     unsigned int        height,
    841     VASurfaceID        *surfaces,
    842     unsigned int        num_surfaces,
    843     VASurfaceAttrib    *attrib_list,
    844     unsigned int        num_attribs
    845 )
    846 {
    847     VADriverContextP ctx;
    848     VAStatus vaStatus;
    849 
    850     CHECK_DISPLAY(dpy);
    851     ctx = CTX(dpy);
    852     if (!ctx)
    853         return VA_STATUS_ERROR_INVALID_DISPLAY;
    854 
    855     if (ctx->vtable->vaCreateSurfaces2)
    856         vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
    857                                               surfaces, num_surfaces,
    858                                               attrib_list, num_attribs);
    859     else if (attrib_list && num_attribs > 0)
    860         vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
    861     else
    862         vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
    863                                                  num_surfaces, surfaces);
    864     VA_TRACE_LOG(va_TraceCreateSurfaces,
    865                  dpy, width, height, format, num_surfaces, surfaces,
    866                  attrib_list, num_attribs);
    867 
    868     return vaStatus;
    869 }
    870 
    871 
    872 VAStatus vaDestroySurfaces (
    873     VADisplay dpy,
    874     VASurfaceID *surface_list,
    875     int num_surfaces
    876 )
    877 {
    878   VADriverContextP ctx;
    879   VAStatus vaStatus;
    880 
    881   CHECK_DISPLAY(dpy);
    882   ctx = CTX(dpy);
    883 
    884   VA_TRACE_LOG(va_TraceDestroySurfaces,
    885                dpy, surface_list, num_surfaces);
    886 
    887   vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
    888 
    889   return vaStatus;
    890 }
    891 
    892 VAStatus vaCreateContext (
    893     VADisplay dpy,
    894     VAConfigID config_id,
    895     int picture_width,
    896     int picture_height,
    897     int flag,
    898     VASurfaceID *render_targets,
    899     int num_render_targets,
    900     VAContextID *context		/* out */
    901 )
    902 {
    903   VADriverContextP ctx;
    904   VAStatus vaStatus;
    905 
    906   CHECK_DISPLAY(dpy);
    907   ctx = CTX(dpy);
    908 
    909   vaStatus = ctx->vtable->vaCreateContext( ctx, config_id, picture_width, picture_height,
    910                                       flag, render_targets, num_render_targets, context );
    911 
    912   /* keep current encode/decode resoluton */
    913   VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context);
    914 
    915   return vaStatus;
    916 }
    917 
    918 VAStatus vaDestroyContext (
    919     VADisplay dpy,
    920     VAContextID context
    921 )
    922 {
    923   VADriverContextP ctx;
    924   CHECK_DISPLAY(dpy);
    925   ctx = CTX(dpy);
    926 
    927   return ctx->vtable->vaDestroyContext( ctx, context );
    928 }
    929 
    930 VAStatus vaCreateBuffer (
    931     VADisplay dpy,
    932     VAContextID context,	/* in */
    933     VABufferType type,		/* in */
    934     unsigned int size,		/* in */
    935     unsigned int num_elements,	/* in */
    936     void *data,			/* in */
    937     VABufferID *buf_id		/* out */
    938 )
    939 {
    940   VADriverContextP ctx;
    941   VAStatus vaStatus;
    942 
    943   CHECK_DISPLAY(dpy);
    944   ctx = CTX(dpy);
    945 
    946   VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id);
    947 
    948   vaStatus = ctx->vtable->vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id);
    949 
    950   VA_TRACE_LOG(va_TraceCreateBuffer,
    951                dpy, context, type, size, num_elements, data, buf_id);
    952 
    953   return vaStatus;
    954 }
    955 
    956 VAStatus vaBufferSetNumElements (
    957     VADisplay dpy,
    958     VABufferID buf_id,	/* in */
    959     unsigned int num_elements /* in */
    960 )
    961 {
    962   VADriverContextP ctx;
    963   CHECK_DISPLAY(dpy);
    964   ctx = CTX(dpy);
    965 
    966   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
    967 
    968   return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements );
    969 }
    970 
    971 
    972 VAStatus vaMapBuffer (
    973     VADisplay dpy,
    974     VABufferID buf_id,	/* in */
    975     void **pbuf 	/* out */
    976 )
    977 {
    978   VADriverContextP ctx;
    979   VAStatus va_status;
    980 
    981   CHECK_DISPLAY(dpy);
    982   ctx = CTX(dpy);
    983 
    984   VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf);
    985 
    986   va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf );
    987 
    988   VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf);
    989 
    990   return va_status;
    991 }
    992 
    993 VAStatus vaUnmapBuffer (
    994     VADisplay dpy,
    995     VABufferID buf_id	/* in */
    996 )
    997 {
    998   VADriverContextP ctx;
    999   CHECK_DISPLAY(dpy);
   1000   ctx = CTX(dpy);
   1001 
   1002   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1003 
   1004   return ctx->vtable->vaUnmapBuffer( ctx, buf_id );
   1005 }
   1006 
   1007 VAStatus vaDestroyBuffer (
   1008     VADisplay dpy,
   1009     VABufferID buffer_id
   1010 )
   1011 {
   1012   VADriverContextP ctx;
   1013   CHECK_DISPLAY(dpy);
   1014   ctx = CTX(dpy);
   1015 
   1016   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1017 
   1018   VA_TRACE_LOG(va_TraceDestroyBuffer,
   1019                dpy, buffer_id);
   1020 
   1021   return ctx->vtable->vaDestroyBuffer( ctx, buffer_id );
   1022 }
   1023 
   1024 VAStatus vaBufferInfo (
   1025     VADisplay dpy,
   1026     VAContextID __maybe_unused context,	/* in */
   1027     VABufferID buf_id,		/* in */
   1028     VABufferType *type,		/* out */
   1029     unsigned int *size,		/* out */
   1030     unsigned int *num_elements	/* out */
   1031 )
   1032 {
   1033     VADriverContextP ctx;
   1034 
   1035     CHECK_DISPLAY(dpy);
   1036     ctx = CTX(dpy);
   1037 
   1038     VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements);
   1039 
   1040     return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements );
   1041 }
   1042 
   1043 VAStatus vaBeginPicture (
   1044     VADisplay dpy,
   1045     VAContextID context,
   1046     VASurfaceID render_target
   1047 )
   1048 {
   1049   VADriverContextP ctx;
   1050   VAStatus va_status;
   1051 
   1052   CHECK_DISPLAY(dpy);
   1053   ctx = CTX(dpy);
   1054 
   1055   VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target);
   1056   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1057 
   1058   va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target );
   1059 
   1060   return va_status;
   1061 }
   1062 
   1063 VAStatus vaRenderPicture (
   1064     VADisplay dpy,
   1065     VAContextID context,
   1066     VABufferID *buffers,
   1067     int num_buffers
   1068 )
   1069 {
   1070   VADriverContextP ctx;
   1071 
   1072   CHECK_DISPLAY(dpy);
   1073   ctx = CTX(dpy);
   1074 
   1075   VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
   1076   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1077 
   1078   return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers );
   1079 }
   1080 
   1081 VAStatus vaEndPicture (
   1082     VADisplay dpy,
   1083     VAContextID context
   1084 )
   1085 {
   1086   VAStatus va_status = VA_STATUS_SUCCESS;
   1087   VADriverContextP ctx;
   1088 
   1089   CHECK_DISPLAY(dpy);
   1090   ctx = CTX(dpy);
   1091 
   1092   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   1093 
   1094   va_status = ctx->vtable->vaEndPicture( ctx, context );
   1095 
   1096   /* dump surface content */
   1097   VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1);
   1098 
   1099   return va_status;
   1100 }
   1101 
   1102 VAStatus vaSyncSurface (
   1103     VADisplay dpy,
   1104     VASurfaceID render_target
   1105 )
   1106 {
   1107   VAStatus va_status;
   1108   VADriverContextP ctx;
   1109 
   1110   CHECK_DISPLAY(dpy);
   1111   ctx = CTX(dpy);
   1112 
   1113   va_status = ctx->vtable->vaSyncSurface( ctx, render_target );
   1114   VA_TRACE_LOG(va_TraceSyncSurface, dpy, render_target);
   1115 
   1116   return va_status;
   1117 }
   1118 
   1119 VAStatus vaQuerySurfaceStatus (
   1120     VADisplay dpy,
   1121     VASurfaceID render_target,
   1122     VASurfaceStatus *status	/* out */
   1123 )
   1124 {
   1125   VAStatus va_status;
   1126   VADriverContextP ctx;
   1127   CHECK_DISPLAY(dpy);
   1128   ctx = CTX(dpy);
   1129 
   1130   va_status = ctx->vtable->vaQuerySurfaceStatus( ctx, render_target, status );
   1131 
   1132   VA_TRACE_LOG(va_TraceQuerySurfaceStatus, dpy, render_target, status);
   1133 
   1134   return va_status;
   1135 }
   1136 
   1137 VAStatus vaQuerySurfaceError (
   1138 	VADisplay dpy,
   1139 	VASurfaceID surface,
   1140 	VAStatus error_status,
   1141 	void **error_info /*out*/
   1142 )
   1143 {
   1144   VAStatus va_status;
   1145   VADriverContextP ctx;
   1146   CHECK_DISPLAY(dpy);
   1147   ctx = CTX(dpy);
   1148 
   1149   va_status = ctx->vtable->vaQuerySurfaceError( ctx, surface, error_status, error_info );
   1150 
   1151   VA_TRACE_LOG(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info);
   1152 
   1153   return va_status;
   1154 }
   1155 
   1156 /* Get maximum number of image formats supported by the implementation */
   1157 int vaMaxNumImageFormats (
   1158     VADisplay dpy
   1159 )
   1160 {
   1161   if (!vaDisplayIsValid(dpy))
   1162       return 0;
   1163 
   1164   return CTX(dpy)->max_image_formats;
   1165 }
   1166 
   1167 VAStatus vaQueryImageFormats (
   1168     VADisplay dpy,
   1169     VAImageFormat *format_list,	/* out */
   1170     int *num_formats		/* out */
   1171 )
   1172 {
   1173   VADriverContextP ctx;
   1174   CHECK_DISPLAY(dpy);
   1175   ctx = CTX(dpy);
   1176 
   1177   return ctx->vtable->vaQueryImageFormats ( ctx, format_list, num_formats);
   1178 }
   1179 
   1180 /*
   1181  * The width and height fields returned in the VAImage structure may get
   1182  * enlarged for some YUV formats. The size of the data buffer that needs
   1183  * to be allocated will be given in the "data_size" field in VAImage.
   1184  * Image data is not allocated by this function.  The client should
   1185  * allocate the memory and fill in the VAImage structure's data field
   1186  * after looking at "data_size" returned from the library.
   1187  */
   1188 VAStatus vaCreateImage (
   1189     VADisplay dpy,
   1190     VAImageFormat *format,
   1191     int width,
   1192     int height,
   1193     VAImage *image	/* out */
   1194 )
   1195 {
   1196   VADriverContextP ctx;
   1197   CHECK_DISPLAY(dpy);
   1198   ctx = CTX(dpy);
   1199 
   1200   return ctx->vtable->vaCreateImage ( ctx, format, width, height, image);
   1201 }
   1202 
   1203 /*
   1204  * Should call DestroyImage before destroying the surface it is bound to
   1205  */
   1206 VAStatus vaDestroyImage (
   1207     VADisplay dpy,
   1208     VAImageID image
   1209 )
   1210 {
   1211   VADriverContextP ctx;
   1212   CHECK_DISPLAY(dpy);
   1213   ctx = CTX(dpy);
   1214 
   1215   return ctx->vtable->vaDestroyImage ( ctx, image);
   1216 }
   1217 
   1218 VAStatus vaSetImagePalette (
   1219     VADisplay dpy,
   1220     VAImageID image,
   1221     unsigned char *palette
   1222 )
   1223 {
   1224   VADriverContextP ctx;
   1225   CHECK_DISPLAY(dpy);
   1226   ctx = CTX(dpy);
   1227 
   1228   return ctx->vtable->vaSetImagePalette ( ctx, image, palette);
   1229 }
   1230 
   1231 /*
   1232  * Retrieve surface data into a VAImage
   1233  * Image must be in a format supported by the implementation
   1234  */
   1235 VAStatus vaGetImage (
   1236     VADisplay dpy,
   1237     VASurfaceID surface,
   1238     int x,	/* coordinates of the upper left source pixel */
   1239     int y,
   1240     unsigned int width, /* width and height of the region */
   1241     unsigned int height,
   1242     VAImageID image
   1243 )
   1244 {
   1245   VADriverContextP ctx;
   1246   CHECK_DISPLAY(dpy);
   1247   ctx = CTX(dpy);
   1248 
   1249   return ctx->vtable->vaGetImage ( ctx, surface, x, y, width, height, image);
   1250 }
   1251 
   1252 /*
   1253  * Copy data from a VAImage to a surface
   1254  * Image must be in a format supported by the implementation
   1255  */
   1256 VAStatus vaPutImage (
   1257     VADisplay dpy,
   1258     VASurfaceID surface,
   1259     VAImageID image,
   1260     int src_x,
   1261     int src_y,
   1262     unsigned int src_width,
   1263     unsigned int src_height,
   1264     int dest_x,
   1265     int dest_y,
   1266     unsigned int dest_width,
   1267     unsigned int dest_height
   1268 )
   1269 {
   1270   VADriverContextP ctx;
   1271   CHECK_DISPLAY(dpy);
   1272   ctx = CTX(dpy);
   1273 
   1274   return ctx->vtable->vaPutImage ( ctx, surface, image, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height );
   1275 }
   1276 
   1277 /*
   1278  * Derive an VAImage from an existing surface.
   1279  * This interface will derive a VAImage and corresponding image buffer from
   1280  * an existing VA Surface. The image buffer can then be mapped/unmapped for
   1281  * direct CPU access. This operation is only possible on implementations with
   1282  * direct rendering capabilities and internal surface formats that can be
   1283  * represented with a VAImage. When the operation is not possible this interface
   1284  * will return VA_STATUS_ERROR_OPERATION_FAILED. Clients should then fall back
   1285  * to using vaCreateImage + vaPutImage to accomplish the same task in an
   1286  * indirect manner.
   1287  *
   1288  * Implementations should only return success when the resulting image buffer
   1289  * would be useable with vaMap/Unmap.
   1290  *
   1291  * When directly accessing a surface special care must be taken to insure
   1292  * proper synchronization with the graphics hardware. Clients should call
   1293  * vaQuerySurfaceStatus to insure that a surface is not the target of concurrent
   1294  * rendering or currently being displayed by an overlay.
   1295  *
   1296  * Additionally nothing about the contents of a surface should be assumed
   1297  * following a vaPutSurface. Implementations are free to modify the surface for
   1298  * scaling or subpicture blending within a call to vaPutImage.
   1299  *
   1300  * Calls to vaPutImage or vaGetImage using the same surface from which the image
   1301  * has been derived will return VA_STATUS_ERROR_SURFACE_BUSY. vaPutImage or
   1302  * vaGetImage with other surfaces is supported.
   1303  *
   1304  * An image created with vaDeriveImage should be freed with vaDestroyImage. The
   1305  * image and image buffer structures will be destroyed; however, the underlying
   1306  * surface will remain unchanged until freed with vaDestroySurfaces.
   1307  */
   1308 VAStatus vaDeriveImage (
   1309     VADisplay dpy,
   1310     VASurfaceID surface,
   1311     VAImage *image	/* out */
   1312 )
   1313 {
   1314   VADriverContextP ctx;
   1315   CHECK_DISPLAY(dpy);
   1316   ctx = CTX(dpy);
   1317 
   1318   return ctx->vtable->vaDeriveImage ( ctx, surface, image );
   1319 }
   1320 
   1321 
   1322 /* Get maximum number of subpicture formats supported by the implementation */
   1323 int vaMaxNumSubpictureFormats (
   1324     VADisplay dpy
   1325 )
   1326 {
   1327   if (!vaDisplayIsValid(dpy))
   1328       return 0;
   1329 
   1330   return CTX(dpy)->max_subpic_formats;
   1331 }
   1332 
   1333 /*
   1334  * Query supported subpicture formats
   1335  * The caller must provide a "format_list" array that can hold at
   1336  * least vaMaxNumSubpictureFormats() entries. The flags arrary holds the flag
   1337  * for each format to indicate additional capabilities for that format. The actual
   1338  * number of formats returned in "format_list" is returned in "num_formats".
   1339  */
   1340 VAStatus vaQuerySubpictureFormats (
   1341     VADisplay dpy,
   1342     VAImageFormat *format_list,	/* out */
   1343     unsigned int *flags,	/* out */
   1344     unsigned int *num_formats	/* out */
   1345 )
   1346 {
   1347   VADriverContextP ctx;
   1348 
   1349   CHECK_DISPLAY(dpy);
   1350   ctx = CTX(dpy);
   1351 
   1352   return ctx->vtable->vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats);
   1353 }
   1354 
   1355 /*
   1356  * Subpictures are created with an image associated.
   1357  */
   1358 VAStatus vaCreateSubpicture (
   1359     VADisplay dpy,
   1360     VAImageID image,
   1361     VASubpictureID *subpicture	/* out */
   1362 )
   1363 {
   1364   VADriverContextP ctx;
   1365   CHECK_DISPLAY(dpy);
   1366   ctx = CTX(dpy);
   1367 
   1368   return ctx->vtable->vaCreateSubpicture ( ctx, image, subpicture );
   1369 }
   1370 
   1371 /*
   1372  * Destroy the subpicture before destroying the image it is assocated to
   1373  */
   1374 VAStatus vaDestroySubpicture (
   1375     VADisplay dpy,
   1376     VASubpictureID subpicture
   1377 )
   1378 {
   1379   VADriverContextP ctx;
   1380   CHECK_DISPLAY(dpy);
   1381   ctx = CTX(dpy);
   1382 
   1383   return ctx->vtable->vaDestroySubpicture ( ctx, subpicture);
   1384 }
   1385 
   1386 VAStatus vaSetSubpictureImage (
   1387     VADisplay dpy,
   1388     VASubpictureID subpicture,
   1389     VAImageID image
   1390 )
   1391 {
   1392   VADriverContextP ctx;
   1393   CHECK_DISPLAY(dpy);
   1394   ctx = CTX(dpy);
   1395 
   1396   return ctx->vtable->vaSetSubpictureImage ( ctx, subpicture, image);
   1397 }
   1398 
   1399 
   1400 /*
   1401  * If chromakey is enabled, then the area where the source value falls within
   1402  * the chromakey [min, max] range is transparent
   1403  */
   1404 VAStatus vaSetSubpictureChromakey (
   1405     VADisplay dpy,
   1406     VASubpictureID subpicture,
   1407     unsigned int chromakey_min,
   1408     unsigned int chromakey_max,
   1409     unsigned int chromakey_mask
   1410 )
   1411 {
   1412   VADriverContextP ctx;
   1413   CHECK_DISPLAY(dpy);
   1414   ctx = CTX(dpy);
   1415 
   1416   return ctx->vtable->vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask );
   1417 }
   1418 
   1419 
   1420 /*
   1421  * Global alpha value is between 0 and 1. A value of 1 means fully opaque and
   1422  * a value of 0 means fully transparent. If per-pixel alpha is also specified then
   1423  * the overall alpha is per-pixel alpha multiplied by the global alpha
   1424  */
   1425 VAStatus vaSetSubpictureGlobalAlpha (
   1426     VADisplay dpy,
   1427     VASubpictureID subpicture,
   1428     float global_alpha
   1429 )
   1430 {
   1431   VADriverContextP ctx;
   1432   CHECK_DISPLAY(dpy);
   1433   ctx = CTX(dpy);
   1434 
   1435   return ctx->vtable->vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha );
   1436 }
   1437 
   1438 /*
   1439   vaAssociateSubpicture associates the subpicture with the target_surface.
   1440   It defines the region mapping between the subpicture and the target
   1441   surface through source and destination rectangles (with the same width and height).
   1442   Both will be displayed at the next call to vaPutSurface.  Additional
   1443   associations before the call to vaPutSurface simply overrides the association.
   1444 */
   1445 VAStatus vaAssociateSubpicture (
   1446     VADisplay dpy,
   1447     VASubpictureID subpicture,
   1448     VASurfaceID *target_surfaces,
   1449     int num_surfaces,
   1450     short src_x, /* upper left offset in subpicture */
   1451     short src_y,
   1452     unsigned short src_width,
   1453     unsigned short src_height,
   1454     short dest_x, /* upper left offset in surface */
   1455     short dest_y,
   1456     unsigned short dest_width,
   1457     unsigned short dest_height,
   1458     /*
   1459      * whether to enable chroma-keying or global-alpha
   1460      * see VA_SUBPICTURE_XXX values
   1461      */
   1462     unsigned int flags
   1463 )
   1464 {
   1465   VADriverContextP ctx;
   1466   CHECK_DISPLAY(dpy);
   1467   ctx = CTX(dpy);
   1468 
   1469   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 );
   1470 }
   1471 
   1472 /*
   1473  * vaDeassociateSubpicture removes the association of the subpicture with target_surfaces.
   1474  */
   1475 VAStatus vaDeassociateSubpicture (
   1476     VADisplay dpy,
   1477     VASubpictureID subpicture,
   1478     VASurfaceID *target_surfaces,
   1479     int num_surfaces
   1480 )
   1481 {
   1482   VADriverContextP ctx;
   1483   CHECK_DISPLAY(dpy);
   1484   ctx = CTX(dpy);
   1485 
   1486   return ctx->vtable->vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces );
   1487 }
   1488 
   1489 
   1490 /* Get maximum number of display attributes supported by the implementation */
   1491 int vaMaxNumDisplayAttributes (
   1492     VADisplay dpy
   1493 )
   1494 {
   1495   int tmp;
   1496 
   1497   if (!vaDisplayIsValid(dpy))
   1498       return 0;
   1499 
   1500   tmp = CTX(dpy)->max_display_attributes;
   1501 
   1502   VA_TRACE_LOG(va_TraceMaxNumDisplayAttributes, dpy, tmp);
   1503 
   1504   return tmp;
   1505 }
   1506 
   1507 /*
   1508  * Query display attributes
   1509  * The caller must provide a "attr_list" array that can hold at
   1510  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
   1511  * returned in "attr_list" is returned in "num_attributes".
   1512  */
   1513 VAStatus vaQueryDisplayAttributes (
   1514     VADisplay dpy,
   1515     VADisplayAttribute *attr_list,	/* out */
   1516     int *num_attributes			/* out */
   1517 )
   1518 {
   1519   VADriverContextP ctx;
   1520   VAStatus va_status;
   1521 
   1522   CHECK_DISPLAY(dpy);
   1523   ctx = CTX(dpy);
   1524   va_status = ctx->vtable->vaQueryDisplayAttributes ( ctx, attr_list, num_attributes );
   1525 
   1526   VA_TRACE_LOG(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes);
   1527 
   1528   return va_status;
   1529 
   1530 }
   1531 
   1532 /*
   1533  * Get display attributes
   1534  * This function returns the current attribute values in "attr_list".
   1535  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
   1536  * from vaQueryDisplayAttributes() can have their values retrieved.
   1537  */
   1538 VAStatus vaGetDisplayAttributes (
   1539     VADisplay dpy,
   1540     VADisplayAttribute *attr_list,	/* in/out */
   1541     int num_attributes
   1542 )
   1543 {
   1544   VADriverContextP ctx;
   1545   VAStatus va_status;
   1546 
   1547   CHECK_DISPLAY(dpy);
   1548   ctx = CTX(dpy);
   1549   va_status = ctx->vtable->vaGetDisplayAttributes ( ctx, attr_list, num_attributes );
   1550 
   1551   VA_TRACE_LOG(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes);
   1552 
   1553   return va_status;
   1554 }
   1555 
   1556 /*
   1557  * Set display attributes
   1558  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
   1559  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or
   1560  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
   1561  */
   1562 VAStatus vaSetDisplayAttributes (
   1563     VADisplay dpy,
   1564     VADisplayAttribute *attr_list,
   1565     int num_attributes
   1566 )
   1567 {
   1568   VADriverContextP ctx;
   1569   VAStatus va_status;
   1570   CHECK_DISPLAY(dpy);
   1571   ctx = CTX(dpy);
   1572 
   1573   va_status = ctx->vtable->vaSetDisplayAttributes ( ctx, attr_list, num_attributes );
   1574   VA_TRACE_LOG(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes);
   1575 
   1576   return va_status;
   1577 }
   1578 
   1579 VAStatus vaLockSurface(VADisplay dpy,
   1580     VASurfaceID surface,
   1581     unsigned int *fourcc, /* following are output argument */
   1582     unsigned int *luma_stride,
   1583     unsigned int *chroma_u_stride,
   1584     unsigned int *chroma_v_stride,
   1585     unsigned int *luma_offset,
   1586     unsigned int *chroma_u_offset,
   1587     unsigned int *chroma_v_offset,
   1588     unsigned int *buffer_name,
   1589     void **buffer
   1590 )
   1591 {
   1592   VADriverContextP ctx;
   1593   CHECK_DISPLAY(dpy);
   1594   ctx = CTX(dpy);
   1595 
   1596   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);
   1597 }
   1598 
   1599 
   1600 VAStatus vaUnlockSurface(VADisplay dpy,
   1601     VASurfaceID surface
   1602 )
   1603 {
   1604   VADriverContextP ctx;
   1605   CHECK_DISPLAY(dpy);
   1606   ctx = CTX(dpy);
   1607 
   1608   return ctx->vtable->vaUnlockSurface( ctx, surface );
   1609 }
   1610 
   1611 /* Video Processing */
   1612 #define VA_VPP_INIT_CONTEXT(ctx, dpy) do {              \
   1613         CHECK_DISPLAY(dpy);                             \
   1614         ctx = CTX(dpy);                                 \
   1615         if (!ctx)                                       \
   1616             return VA_STATUS_ERROR_INVALID_DISPLAY;     \
   1617     } while (0)
   1618 
   1619 #define VA_VPP_INVOKE(dpy, func, args) do {             \
   1620         if (!ctx->vtable_vpp->va##func)                 \
   1621             return VA_STATUS_ERROR_UNIMPLEMENTED;       \
   1622         status = ctx->vtable_vpp->va##func args;        \
   1623     } while (0)
   1624 
   1625 VAStatus
   1626 vaQueryVideoProcFilters(
   1627     VADisplay           dpy,
   1628     VAContextID         context,
   1629     VAProcFilterType   *filters,
   1630     unsigned int       *num_filters
   1631 )
   1632 {
   1633     VADriverContextP ctx;
   1634     VAStatus status;
   1635 
   1636     VA_VPP_INIT_CONTEXT(ctx, dpy);
   1637     VA_VPP_INVOKE(
   1638         ctx,
   1639         QueryVideoProcFilters,
   1640         (ctx, context, filters, num_filters)
   1641     );
   1642     return status;
   1643 }
   1644 
   1645 VAStatus
   1646 vaQueryVideoProcFilterCaps(
   1647     VADisplay           dpy,
   1648     VAContextID         context,
   1649     VAProcFilterType    type,
   1650     void               *filter_caps,
   1651     unsigned int       *num_filter_caps
   1652 )
   1653 {
   1654     VADriverContextP ctx;
   1655     VAStatus status;
   1656 
   1657     VA_VPP_INIT_CONTEXT(ctx, dpy);
   1658     VA_VPP_INVOKE(
   1659         ctx,
   1660         QueryVideoProcFilterCaps,
   1661         (ctx, context, type, filter_caps, num_filter_caps)
   1662     );
   1663     return status;
   1664 }
   1665 
   1666 VAStatus
   1667 vaQueryVideoProcPipelineCaps(
   1668     VADisplay           dpy,
   1669     VAContextID         context,
   1670     VABufferID         *filters,
   1671     unsigned int        num_filters,
   1672     VAProcPipelineCaps *pipeline_caps
   1673 )
   1674 {
   1675     VADriverContextP ctx;
   1676     VAStatus status;
   1677 
   1678     VA_VPP_INIT_CONTEXT(ctx, dpy);
   1679     VA_VPP_INVOKE(
   1680         ctx,
   1681         QueryVideoProcPipelineCaps,
   1682         (ctx, context, filters, num_filters, pipeline_caps)
   1683     );
   1684     return status;
   1685 }
   1686