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