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  */
va_parseConfig(char * env,char * env_value)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 
vaDisplayIsValid(VADisplay dpy)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 
va_errorMessage(const char * msg,...)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 
va_infoMessage(const char * msg,...)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 
va_checkVtable(void * ptr,char * function)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 
va_checkMaximum(int value,char * variable)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 
va_checkString(const char * value,char * variable)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
va_getDriverInitName(char * name,int namelen,int major,int minor)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 
va_getDriverName(VADisplay dpy,char ** driver_name)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 
va_openDriver(VADisplay dpy,char * driver_name)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 
vaGetLibFunc(VADisplay dpy,const char * func)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  */
vaErrorStr(VAStatus error_status)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 
vaInitialize(VADisplay dpy,int * major_version,int * minor_version)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  */
vaTerminate(VADisplay dpy)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  */
vaQueryVendorString(VADisplay dpy)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 */
vaMaxNumProfiles(VADisplay dpy)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 */
vaMaxNumEntrypoints(VADisplay dpy)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 */
vaMaxNumConfigAttributes(VADisplay dpy)567 int vaMaxNumConfigAttributes (
568     VADisplay dpy
569 )
570 {
571   if (!vaDisplayIsValid(dpy))
572       return 0;
573 
574   return CTX(dpy)->max_attributes;
575 }
576 
vaQueryConfigEntrypoints(VADisplay dpy,VAProfile profile,VAEntrypoint * entrypoints,int * num_entrypoints)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 
vaGetConfigAttributes(VADisplay dpy,VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib_list,int num_attribs)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 
vaQueryConfigProfiles(VADisplay dpy,VAProfile * profile_list,int * num_profiles)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 
vaCreateConfig(VADisplay dpy,VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib_list,int num_attribs,VAConfigID * config_id)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 
vaDestroyConfig(VADisplay dpy,VAConfigID config_id)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 
vaQueryConfigAttributes(VADisplay dpy,VAConfigID config_id,VAProfile * profile,VAEntrypoint * entrypoint,VAConfigAttrib * attrib_list,int * num_attribs)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
va_impl_query_surface_attributes(VADriverContextP ctx,VAConfigID config,VASurfaceAttrib * out_attribs,unsigned int * out_num_attribs_ptr)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
vaQuerySurfaceAttributes(VADisplay dpy,VAConfigID config,VASurfaceAttrib * attrib_list,unsigned int * num_attribs)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
vaCreateSurfaces(VADisplay dpy,unsigned int format,unsigned int width,unsigned int height,VASurfaceID * surfaces,unsigned int num_surfaces,VASurfaceAttrib * attrib_list,unsigned int num_attribs)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 
vaDestroySurfaces(VADisplay dpy,VASurfaceID * surface_list,int num_surfaces)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 
vaCreateContext(VADisplay dpy,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID * render_targets,int num_render_targets,VAContextID * context)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 
vaDestroyContext(VADisplay dpy,VAContextID context)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 
vaCreateBuffer(VADisplay dpy,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void * data,VABufferID * buf_id)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 
vaBufferSetNumElements(VADisplay dpy,VABufferID buf_id,unsigned int num_elements)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 
vaMapBuffer(VADisplay dpy,VABufferID buf_id,void ** pbuf)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 
vaUnmapBuffer(VADisplay dpy,VABufferID buf_id)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 
vaDestroyBuffer(VADisplay dpy,VABufferID buffer_id)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 
vaBufferInfo(VADisplay dpy,VAContextID __maybe_unused context,VABufferID buf_id,VABufferType * type,unsigned int * size,unsigned int * num_elements)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 
vaBeginPicture(VADisplay dpy,VAContextID context,VASurfaceID render_target)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 
vaRenderPicture(VADisplay dpy,VAContextID context,VABufferID * buffers,int num_buffers)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 
vaEndPicture(VADisplay dpy,VAContextID context)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 
vaSyncSurface(VADisplay dpy,VASurfaceID render_target)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 
vaQuerySurfaceStatus(VADisplay dpy,VASurfaceID render_target,VASurfaceStatus * status)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 
vaQuerySurfaceError(VADisplay dpy,VASurfaceID surface,VAStatus error_status,void ** error_info)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 */
vaMaxNumImageFormats(VADisplay dpy)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 
vaQueryImageFormats(VADisplay dpy,VAImageFormat * format_list,int * num_formats)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  */
vaCreateImage(VADisplay dpy,VAImageFormat * format,int width,int height,VAImage * image)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  */
vaDestroyImage(VADisplay dpy,VAImageID image)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 
vaSetImagePalette(VADisplay dpy,VAImageID image,unsigned char * palette)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  */
vaGetImage(VADisplay dpy,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image)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  */
vaPutImage(VADisplay dpy,VASurfaceID surface,VAImageID image,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y,unsigned int dest_width,unsigned int dest_height)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  */
vaDeriveImage(VADisplay dpy,VASurfaceID surface,VAImage * image)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 */
vaMaxNumSubpictureFormats(VADisplay dpy)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  */
vaQuerySubpictureFormats(VADisplay dpy,VAImageFormat * format_list,unsigned int * flags,unsigned int * num_formats)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  */
vaCreateSubpicture(VADisplay dpy,VAImageID image,VASubpictureID * subpicture)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  */
vaDestroySubpicture(VADisplay dpy,VASubpictureID subpicture)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 
vaSetSubpictureImage(VADisplay dpy,VASubpictureID subpicture,VAImageID image)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  */
vaSetSubpictureChromakey(VADisplay dpy,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask)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  */
vaSetSubpictureGlobalAlpha(VADisplay dpy,VASubpictureID subpicture,float global_alpha)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 */
vaAssociateSubpicture(VADisplay dpy,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces,short src_x,short src_y,unsigned short src_width,unsigned short src_height,short dest_x,short dest_y,unsigned short dest_width,unsigned short dest_height,unsigned int flags)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  */
vaDeassociateSubpicture(VADisplay dpy,VASubpictureID subpicture,VASurfaceID * target_surfaces,int num_surfaces)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 */
vaMaxNumDisplayAttributes(VADisplay dpy)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  */
vaQueryDisplayAttributes(VADisplay dpy,VADisplayAttribute * attr_list,int * num_attributes)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  */
vaGetDisplayAttributes(VADisplay dpy,VADisplayAttribute * attr_list,int num_attributes)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  */
vaSetDisplayAttributes(VADisplay dpy,VADisplayAttribute * attr_list,int num_attributes)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 
vaLockSurface(VADisplay dpy,VASurfaceID surface,unsigned int * fourcc,unsigned int * luma_stride,unsigned int * chroma_u_stride,unsigned int * chroma_v_stride,unsigned int * luma_offset,unsigned int * chroma_u_offset,unsigned int * chroma_v_offset,unsigned int * buffer_name,void ** buffer)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 
vaUnlockSurface(VADisplay dpy,VASurfaceID surface)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
vaQueryVideoProcFilters(VADisplay dpy,VAContextID context,VAProcFilterType * filters,unsigned int * num_filters)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
vaQueryVideoProcFilterCaps(VADisplay dpy,VAContextID context,VAProcFilterType type,void * filter_caps,unsigned int * num_filter_caps)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
vaQueryVideoProcPipelineCaps(VADisplay dpy,VAContextID context,VABufferID * filters,unsigned int num_filters,VAProcPipelineCaps * pipeline_caps)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