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