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