OSDN Git Service

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