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