You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1685 lines
47 KiB
1685 lines
47 KiB
/* |
|
* Copyright (c) 2007 Intel Corporation. All Rights Reserved. |
|
* |
|
* Permission is hereby granted, free of charge, to any person obtaining a |
|
* copy of this software and associated documentation files (the |
|
* "Software"), to deal in the Software without restriction, including |
|
* without limitation the rights to use, copy, modify, merge, publish, |
|
* distribute, sub license, and/or sell copies of the Software, and to |
|
* permit persons to whom the Software is furnished to do so, subject to |
|
* the following conditions: |
|
* |
|
* The above copyright notice and this permission notice (including the |
|
* next paragraph) shall be included in all copies or substantial portions |
|
* of the Software. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
|
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR |
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
#define _GNU_SOURCE 1 |
|
#include "sysdeps.h" |
|
#include "va.h" |
|
#include "va_backend.h" |
|
#include "va_backend_vpp.h" |
|
#include "va_trace.h" |
|
#include "va_fool.h" |
|
|
|
#include <assert.h> |
|
#include <stdarg.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <dlfcn.h> |
|
#include <unistd.h> |
|
|
|
#define DRIVER_EXTENSION "_drv_video.so" |
|
|
|
#define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext) |
|
#define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; } |
|
|
|
#define ASSERT assert |
|
#define CHECK_VTABLE(s, ctx, func) if (!va_checkVtable(ctx->vtable->va##func, #func)) s = VA_STATUS_ERROR_UNKNOWN; |
|
#define CHECK_MAXIMUM(s, ctx, var) if (!va_checkMaximum(ctx->max_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN; |
|
#define CHECK_STRING(s, ctx, var) if (!va_checkString(ctx->str_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN; |
|
|
|
|
|
/* |
|
* read a config "env" for libva.conf or from environment setting |
|
* liva.conf has higher priority |
|
* return 0: the "env" is set, and the value is copied into env_value |
|
* 1: the env is not set |
|
*/ |
|
int va_parseConfig(char *env, char *env_value) |
|
{ |
|
char *token, *value, *saveptr; |
|
char oneline[1024]; |
|
FILE *fp=NULL; |
|
|
|
if (env == NULL) |
|
return 1; |
|
|
|
fp = fopen("/etc/libva.conf", "r"); |
|
while (fp && (fgets(oneline, 1024, fp) != NULL)) { |
|
if (strlen(oneline) == 1) |
|
continue; |
|
token = strtok_r(oneline, "=\n", &saveptr); |
|
value = strtok_r(NULL, "=\n", &saveptr); |
|
|
|
if (NULL == token || NULL == value) |
|
continue; |
|
|
|
if (strcmp(token, env) == 0) { |
|
if (env_value) |
|
strncpy(env_value,value, 1024); |
|
|
|
fclose(fp); |
|
|
|
return 0; |
|
} |
|
} |
|
if (fp) |
|
fclose(fp); |
|
|
|
/* no setting in config file, use env setting */ |
|
value = getenv(env); |
|
if (value) { |
|
if (env_value) |
|
strncpy(env_value, value, 1024); |
|
return 0; |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
int vaDisplayIsValid(VADisplay dpy) |
|
{ |
|
VADisplayContextP pDisplayContext = (VADisplayContextP)dpy; |
|
return pDisplayContext && (pDisplayContext->vadpy_magic == VA_DISPLAY_MAGIC) && pDisplayContext->vaIsValid(pDisplayContext); |
|
} |
|
|
|
void va_errorMessage(const char *msg, ...) |
|
{ |
|
char buf[512], *dynbuf; |
|
va_list args; |
|
int n, len; |
|
|
|
va_start(args, msg); |
|
len = vsnprintf(buf, sizeof(buf), msg, args); |
|
va_end(args); |
|
|
|
if (len >= (int)sizeof(buf)) { |
|
dynbuf = malloc(len + 1); |
|
if (!dynbuf) |
|
return; |
|
va_start(args, msg); |
|
n = vsnprintf(dynbuf, len + 1, msg, args); |
|
va_end(args); |
|
if (n == len) |
|
va_log_error(dynbuf); |
|
free(dynbuf); |
|
} |
|
else if (len > 0) |
|
va_log_error(buf); |
|
} |
|
|
|
void va_infoMessage(const char *msg, ...) |
|
{ |
|
char buf[512], *dynbuf; |
|
va_list args; |
|
int n, len; |
|
|
|
va_start(args, msg); |
|
len = vsnprintf(buf, sizeof(buf), msg, args); |
|
va_end(args); |
|
|
|
if (len >= (int)sizeof(buf)) { |
|
dynbuf = malloc(len + 1); |
|
if (!dynbuf) |
|
return; |
|
va_start(args, msg); |
|
n = vsnprintf(dynbuf, len + 1, msg, args); |
|
va_end(args); |
|
if (n == len) |
|
va_log_info(dynbuf); |
|
free(dynbuf); |
|
} |
|
else if (len > 0) |
|
va_log_info(buf); |
|
} |
|
|
|
static bool va_checkVtable(void *ptr, char *function) |
|
{ |
|
if (!ptr) { |
|
va_errorMessage("No valid vtable entry for va%s\n", function); |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
static bool va_checkMaximum(int value, char *variable) |
|
{ |
|
if (!value) { |
|
va_errorMessage("Failed to define max_%s in init\n", variable); |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
static bool va_checkString(const char* value, char *variable) |
|
{ |
|
if (!value) { |
|
va_errorMessage("Failed to define str_%s in init\n", variable); |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
static inline int |
|
va_getDriverInitName(char *name, int namelen, int major, int minor) |
|
{ |
|
int ret = snprintf(name, namelen, "__vaDriverInit_%d_%d", major, minor); |
|
return ret > 0 && ret < namelen; |
|
} |
|
|
|
static VAStatus va_getDriverName(VADisplay dpy, char **driver_name) |
|
{ |
|
VADisplayContextP pDisplayContext = (VADisplayContextP)dpy; |
|
|
|
return pDisplayContext->vaGetDriverName(pDisplayContext, driver_name); |
|
} |
|
|
|
static VAStatus va_openDriver(VADisplay dpy, char *driver_name) |
|
{ |
|
VADriverContextP ctx = CTX(dpy); |
|
VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN; |
|
char *search_path = NULL; |
|
char *saveptr; |
|
char *driver_dir; |
|
|
|
if (geteuid() == getuid()) |
|
/* don't allow setuid apps to use LIBVA_DRIVERS_PATH */ |
|
search_path = getenv("LIBVA_DRIVERS_PATH"); |
|
if (!search_path) |
|
search_path = VA_DRIVERS_PATH; |
|
|
|
search_path = strdup((const char *)search_path); |
|
driver_dir = strtok_r(search_path, ":", &saveptr); |
|
while (driver_dir) { |
|
void *handle = NULL; |
|
char *driver_path = (char *) malloc( strlen(driver_dir) + |
|
strlen(driver_name) + |
|
strlen(DRIVER_EXTENSION) + 2 ); |
|
if (!driver_path) { |
|
va_errorMessage("%s L%d Out of memory!n", |
|
__FUNCTION__, __LINE__); |
|
free(search_path); |
|
return VA_STATUS_ERROR_ALLOCATION_FAILED; |
|
} |
|
|
|
strncpy( driver_path, driver_dir, strlen(driver_dir) + 1); |
|
strncat( driver_path, "/", strlen("/") ); |
|
strncat( driver_path, driver_name, strlen(driver_name) ); |
|
strncat( driver_path, DRIVER_EXTENSION, strlen(DRIVER_EXTENSION) ); |
|
|
|
va_infoMessage("Trying to open %s\n", driver_path); |
|
#ifndef ANDROID |
|
handle = dlopen( driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE ); |
|
#else |
|
handle = dlopen( driver_path, RTLD_NOW| RTLD_GLOBAL); |
|
#endif |
|
if (!handle) { |
|
/* Don't give errors for non-existing files */ |
|
if (0 == access( driver_path, F_OK)) |
|
va_errorMessage("dlopen of %s failed: %s\n", driver_path, dlerror()); |
|
} else { |
|
VADriverInit init_func = NULL; |
|
char init_func_s[256]; |
|
int i; |
|
|
|
static const struct { |
|
int major; |
|
int minor; |
|
} compatible_versions[] = { |
|
{ VA_MAJOR_VERSION, VA_MINOR_VERSION }, |
|
{ 0, 33 }, |
|
{ 0, 32 }, |
|
{ -1, 0} |
|
}; |
|
|
|
for (i = 0; compatible_versions[i].major >= 0; i++) { |
|
if (va_getDriverInitName(init_func_s, sizeof(init_func_s), |
|
compatible_versions[i].major, |
|
compatible_versions[i].minor)) { |
|
init_func = (VADriverInit)dlsym(handle, init_func_s); |
|
if (init_func) { |
|
va_infoMessage("Found init function %s\n", init_func_s); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if (compatible_versions[i].major < 0) { |
|
va_errorMessage("%s has no function %s\n", |
|
driver_path, init_func_s); |
|
dlclose(handle); |
|
} else { |
|
struct VADriverVTable *vtable = ctx->vtable; |
|
struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp; |
|
|
|
vaStatus = VA_STATUS_SUCCESS; |
|
if (!vtable) { |
|
vtable = calloc(1, sizeof(*vtable)); |
|
if (!vtable) |
|
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
|
} |
|
ctx->vtable = vtable; |
|
|
|
if (!vtable_vpp) { |
|
vtable_vpp = calloc(1, sizeof(*vtable_vpp)); |
|
if (vtable_vpp) |
|
vtable_vpp->version = VA_DRIVER_VTABLE_VPP_VERSION; |
|
else |
|
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
|
} |
|
ctx->vtable_vpp = vtable_vpp; |
|
|
|
if (init_func && VA_STATUS_SUCCESS == vaStatus) |
|
vaStatus = (*init_func)(ctx); |
|
|
|
if (VA_STATUS_SUCCESS == vaStatus) { |
|
CHECK_MAXIMUM(vaStatus, ctx, profiles); |
|
CHECK_MAXIMUM(vaStatus, ctx, entrypoints); |
|
CHECK_MAXIMUM(vaStatus, ctx, attributes); |
|
CHECK_MAXIMUM(vaStatus, ctx, image_formats); |
|
CHECK_MAXIMUM(vaStatus, ctx, subpic_formats); |
|
CHECK_MAXIMUM(vaStatus, ctx, display_attributes); |
|
CHECK_STRING(vaStatus, ctx, vendor); |
|
CHECK_VTABLE(vaStatus, ctx, Terminate); |
|
CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles); |
|
CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints); |
|
CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes); |
|
CHECK_VTABLE(vaStatus, ctx, CreateConfig); |
|
CHECK_VTABLE(vaStatus, ctx, DestroyConfig); |
|
CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes); |
|
CHECK_VTABLE(vaStatus, ctx, CreateSurfaces); |
|
CHECK_VTABLE(vaStatus, ctx, DestroySurfaces); |
|
CHECK_VTABLE(vaStatus, ctx, CreateContext); |
|
CHECK_VTABLE(vaStatus, ctx, DestroyContext); |
|
CHECK_VTABLE(vaStatus, ctx, CreateBuffer); |
|
CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements); |
|
CHECK_VTABLE(vaStatus, ctx, MapBuffer); |
|
CHECK_VTABLE(vaStatus, ctx, UnmapBuffer); |
|
CHECK_VTABLE(vaStatus, ctx, DestroyBuffer); |
|
CHECK_VTABLE(vaStatus, ctx, BeginPicture); |
|
CHECK_VTABLE(vaStatus, ctx, RenderPicture); |
|
CHECK_VTABLE(vaStatus, ctx, EndPicture); |
|
CHECK_VTABLE(vaStatus, ctx, SyncSurface); |
|
CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus); |
|
CHECK_VTABLE(vaStatus, ctx, PutSurface); |
|
CHECK_VTABLE(vaStatus, ctx, QueryImageFormats); |
|
CHECK_VTABLE(vaStatus, ctx, CreateImage); |
|
CHECK_VTABLE(vaStatus, ctx, DeriveImage); |
|
CHECK_VTABLE(vaStatus, ctx, DestroyImage); |
|
CHECK_VTABLE(vaStatus, ctx, SetImagePalette); |
|
CHECK_VTABLE(vaStatus, ctx, GetImage); |
|
CHECK_VTABLE(vaStatus, ctx, PutImage); |
|
CHECK_VTABLE(vaStatus, ctx, QuerySubpictureFormats); |
|
CHECK_VTABLE(vaStatus, ctx, CreateSubpicture); |
|
CHECK_VTABLE(vaStatus, ctx, DestroySubpicture); |
|
CHECK_VTABLE(vaStatus, ctx, SetSubpictureImage); |
|
CHECK_VTABLE(vaStatus, ctx, SetSubpictureChromakey); |
|
CHECK_VTABLE(vaStatus, ctx, SetSubpictureGlobalAlpha); |
|
CHECK_VTABLE(vaStatus, ctx, AssociateSubpicture); |
|
CHECK_VTABLE(vaStatus, ctx, DeassociateSubpicture); |
|
CHECK_VTABLE(vaStatus, ctx, QueryDisplayAttributes); |
|
CHECK_VTABLE(vaStatus, ctx, GetDisplayAttributes); |
|
CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes); |
|
} |
|
if (VA_STATUS_SUCCESS != vaStatus) { |
|
va_errorMessage("%s init failed\n", driver_path); |
|
dlclose(handle); |
|
} |
|
if (VA_STATUS_SUCCESS == vaStatus) |
|
ctx->handle = handle; |
|
free(driver_path); |
|
break; |
|
} |
|
} |
|
free(driver_path); |
|
|
|
driver_dir = strtok_r(NULL, ":", &saveptr); |
|
} |
|
|
|
free(search_path); |
|
|
|
return vaStatus; |
|
} |
|
|
|
VAPrivFunc vaGetLibFunc(VADisplay dpy, const char *func) |
|
{ |
|
VADriverContextP ctx; |
|
if (!vaDisplayIsValid(dpy)) |
|
return NULL; |
|
ctx = CTX(dpy); |
|
|
|
if (NULL == ctx->handle) |
|
return NULL; |
|
|
|
return (VAPrivFunc) dlsym(ctx->handle, func); |
|
} |
|
|
|
|
|
/* |
|
* Returns a short english description of error_status |
|
*/ |
|
const char *vaErrorStr(VAStatus error_status) |
|
{ |
|
switch(error_status) { |
|
case VA_STATUS_SUCCESS: |
|
return "success (no error)"; |
|
case VA_STATUS_ERROR_OPERATION_FAILED: |
|
return "operation failed"; |
|
case VA_STATUS_ERROR_ALLOCATION_FAILED: |
|
return "resource allocation failed"; |
|
case VA_STATUS_ERROR_INVALID_DISPLAY: |
|
return "invalid VADisplay"; |
|
case VA_STATUS_ERROR_INVALID_CONFIG: |
|
return "invalid VAConfigID"; |
|
case VA_STATUS_ERROR_INVALID_CONTEXT: |
|
return "invalid VAContextID"; |
|
case VA_STATUS_ERROR_INVALID_SURFACE: |
|
return "invalid VASurfaceID"; |
|
case VA_STATUS_ERROR_INVALID_BUFFER: |
|
return "invalid VABufferID"; |
|
case VA_STATUS_ERROR_INVALID_IMAGE: |
|
return "invalid VAImageID"; |
|
case VA_STATUS_ERROR_INVALID_SUBPICTURE: |
|
return "invalid VASubpictureID"; |
|
case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED: |
|
return "attribute not supported"; |
|
case VA_STATUS_ERROR_MAX_NUM_EXCEEDED: |
|
return "list argument exceeds maximum number"; |
|
case VA_STATUS_ERROR_UNSUPPORTED_PROFILE: |
|
return "the requested VAProfile is not supported"; |
|
case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT: |
|
return "the requested VAEntryPoint is not supported"; |
|
case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT: |
|
return "the requested RT Format is not supported"; |
|
case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE: |
|
return "the requested VABufferType is not supported"; |
|
case VA_STATUS_ERROR_SURFACE_BUSY: |
|
return "surface is in use"; |
|
case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED: |
|
return "flag not supported"; |
|
case VA_STATUS_ERROR_INVALID_PARAMETER: |
|
return "invalid parameter"; |
|
case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED: |
|
return "resolution not supported"; |
|
case VA_STATUS_ERROR_UNIMPLEMENTED: |
|
return "the requested function is not implemented"; |
|
case VA_STATUS_ERROR_SURFACE_IN_DISPLAYING: |
|
return "surface is in displaying (may by overlay)" ; |
|
case VA_STATUS_ERROR_INVALID_IMAGE_FORMAT: |
|
return "invalid VAImageFormat"; |
|
case VA_STATUS_ERROR_INVALID_VALUE: |
|
return "an invalid/unsupported value was supplied"; |
|
case VA_STATUS_ERROR_UNSUPPORTED_FILTER: |
|
return "the requested filter is not supported"; |
|
case VA_STATUS_ERROR_INVALID_FILTER_CHAIN: |
|
return "an invalid filter chain was supplied"; |
|
case VA_STATUS_ERROR_UNKNOWN: |
|
return "unknown libva error"; |
|
} |
|
return "unknown libva error / description missing"; |
|
} |
|
|
|
VAStatus vaInitialize ( |
|
VADisplay dpy, |
|
int *major_version, /* out */ |
|
int *minor_version /* out */ |
|
) |
|
{ |
|
const char *driver_name_env = NULL; |
|
char *driver_name = NULL; |
|
VAStatus vaStatus; |
|
|
|
CHECK_DISPLAY(dpy); |
|
|
|
va_TraceInit(dpy); |
|
|
|
va_FoolInit(dpy); |
|
|
|
va_infoMessage("VA-API version %s\n", VA_VERSION_S); |
|
|
|
vaStatus = va_getDriverName(dpy, &driver_name); |
|
va_infoMessage("va_getDriverName() returns %d\n", vaStatus); |
|
|
|
driver_name_env = getenv("LIBVA_DRIVER_NAME"); |
|
if ((VA_STATUS_SUCCESS == vaStatus) && |
|
driver_name_env && (geteuid() == getuid())) { |
|
/* Don't allow setuid apps to use LIBVA_DRIVER_NAME */ |
|
driver_name = "pvr"; |
|
vaStatus = VA_STATUS_SUCCESS; |
|
va_infoMessage("User requested driver '%s'\n", driver_name); |
|
} |
|
|
|
if ((VA_STATUS_SUCCESS == vaStatus) && (driver_name != NULL)) { |
|
vaStatus = va_openDriver(dpy, driver_name); |
|
va_infoMessage("va_openDriver() returns %d, driver_name = %s\n", vaStatus, driver_name); |
|
|
|
*major_version = VA_MAJOR_VERSION; |
|
*minor_version = VA_MINOR_VERSION; |
|
} else |
|
va_errorMessage("va_getDriverName() failed with %s,driver_name=%s\n", |
|
vaErrorStr(vaStatus), driver_name); |
|
|
|
VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version); |
|
|
|
return vaStatus; |
|
} |
|
|
|
|
|
/* |
|
* After this call, all library internal resources will be cleaned up |
|
*/ |
|
VAStatus vaTerminate ( |
|
VADisplay dpy |
|
) |
|
{ |
|
VAStatus vaStatus = VA_STATUS_SUCCESS; |
|
VADisplayContextP pDisplayContext = (VADisplayContextP)dpy; |
|
VADriverContextP old_ctx; |
|
|
|
CHECK_DISPLAY(dpy); |
|
old_ctx = CTX(dpy); |
|
|
|
if (old_ctx->handle) { |
|
vaStatus = old_ctx->vtable->vaTerminate(old_ctx); |
|
dlclose(old_ctx->handle); |
|
old_ctx->handle = NULL; |
|
} |
|
free(old_ctx->vtable); |
|
old_ctx->vtable = NULL; |
|
free(old_ctx->vtable_vpp); |
|
old_ctx->vtable_vpp = NULL; |
|
|
|
VA_TRACE_LOG(va_TraceTerminate, dpy); |
|
|
|
va_TraceEnd(dpy); |
|
|
|
va_FoolEnd(dpy); |
|
|
|
if (VA_STATUS_SUCCESS == vaStatus) |
|
pDisplayContext->vaDestroy(pDisplayContext); |
|
|
|
return vaStatus; |
|
} |
|
|
|
/* |
|
* vaQueryVendorString returns a pointer to a zero-terminated string |
|
* describing some aspects of the VA implemenation on a specific |
|
* hardware accelerator. The format of the returned string is: |
|
* <vendorname>-<major_version>-<minor_version>-<addtional_info> |
|
* e.g. for the Intel GMA500 implementation, an example would be: |
|
* "IntelGMA500-1.0-0.2-patch3 |
|
*/ |
|
const char *vaQueryVendorString ( |
|
VADisplay dpy |
|
) |
|
{ |
|
if (!vaDisplayIsValid(dpy)) |
|
return NULL; |
|
|
|
return CTX(dpy)->str_vendor; |
|
} |
|
|
|
|
|
/* Get maximum number of profiles supported by the implementation */ |
|
int vaMaxNumProfiles ( |
|
VADisplay dpy |
|
) |
|
{ |
|
if (!vaDisplayIsValid(dpy)) |
|
return 0; |
|
|
|
return CTX(dpy)->max_profiles; |
|
} |
|
|
|
/* Get maximum number of entrypoints supported by the implementation */ |
|
int vaMaxNumEntrypoints ( |
|
VADisplay dpy |
|
) |
|
{ |
|
if (!vaDisplayIsValid(dpy)) |
|
return 0; |
|
|
|
return CTX(dpy)->max_entrypoints; |
|
} |
|
|
|
|
|
/* Get maximum number of attributs supported by the implementation */ |
|
int vaMaxNumConfigAttributes ( |
|
VADisplay dpy |
|
) |
|
{ |
|
if (!vaDisplayIsValid(dpy)) |
|
return 0; |
|
|
|
return CTX(dpy)->max_attributes; |
|
} |
|
|
|
VAStatus vaQueryConfigEntrypoints ( |
|
VADisplay dpy, |
|
VAProfile profile, |
|
VAEntrypoint *entrypoints, /* out */ |
|
int *num_entrypoints /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints); |
|
} |
|
|
|
VAStatus vaGetConfigAttributes ( |
|
VADisplay dpy, |
|
VAProfile profile, |
|
VAEntrypoint entrypoint, |
|
VAConfigAttrib *attrib_list, /* in/out */ |
|
int num_attribs |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs ); |
|
} |
|
|
|
VAStatus vaQueryConfigProfiles ( |
|
VADisplay dpy, |
|
VAProfile *profile_list, /* out */ |
|
int *num_profiles /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaQueryConfigProfiles ( ctx, profile_list, num_profiles ); |
|
} |
|
|
|
VAStatus vaCreateConfig ( |
|
VADisplay dpy, |
|
VAProfile profile, |
|
VAEntrypoint entrypoint, |
|
VAConfigAttrib *attrib_list, |
|
int num_attribs, |
|
VAConfigID *config_id /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus vaStatus = VA_STATUS_SUCCESS; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id ); |
|
|
|
/* record the current entrypoint for further trace/fool determination */ |
|
VA_TRACE_ALL(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id); |
|
VA_FOOL_FUNC(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id); |
|
|
|
return vaStatus; |
|
} |
|
|
|
VAStatus vaDestroyConfig ( |
|
VADisplay dpy, |
|
VAConfigID config_id |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaDestroyConfig ( ctx, config_id ); |
|
} |
|
|
|
VAStatus vaQueryConfigAttributes ( |
|
VADisplay dpy, |
|
VAConfigID config_id, |
|
VAProfile *profile, /* out */ |
|
VAEntrypoint *entrypoint, /* out */ |
|
VAConfigAttrib *attrib_list,/* out */ |
|
int *num_attribs /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs); |
|
} |
|
|
|
/* XXX: this is a slow implementation that will be removed */ |
|
static VAStatus |
|
va_impl_query_surface_attributes( |
|
VADriverContextP ctx, |
|
VAConfigID config, |
|
VASurfaceAttrib *out_attribs, |
|
unsigned int *out_num_attribs_ptr |
|
) |
|
{ |
|
VASurfaceAttrib *attribs = NULL; |
|
unsigned int num_attribs, n; |
|
VASurfaceAttrib *out_attrib; |
|
unsigned int out_num_attribs; |
|
VAImageFormat *image_formats = NULL; |
|
int num_image_formats, i; |
|
VAStatus va_status; |
|
|
|
/* List of surface attributes to query */ |
|
struct va_surface_attrib_map { |
|
VASurfaceAttribType type; |
|
VAGenericValueType value_type; |
|
}; |
|
static const struct va_surface_attrib_map attribs_map[] = { |
|
{ VASurfaceAttribMinWidth, VAGenericValueTypeInteger }, |
|
{ VASurfaceAttribMaxWidth, VAGenericValueTypeInteger }, |
|
{ VASurfaceAttribMinHeight, VAGenericValueTypeInteger }, |
|
{ VASurfaceAttribMaxHeight, VAGenericValueTypeInteger }, |
|
{ VASurfaceAttribMemoryType, VAGenericValueTypeInteger }, |
|
{ VASurfaceAttribNone, } |
|
}; |
|
|
|
if (!out_attribs || !out_num_attribs_ptr) |
|
return VA_STATUS_ERROR_INVALID_PARAMETER; |
|
if (!ctx->vtable->vaGetSurfaceAttributes) |
|
return VA_STATUS_ERROR_UNIMPLEMENTED; |
|
|
|
num_image_formats = ctx->max_image_formats; |
|
image_formats = malloc(num_image_formats * sizeof(*image_formats)); |
|
if (!image_formats) { |
|
va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; |
|
goto end; |
|
} |
|
|
|
va_status = ctx->vtable->vaQueryImageFormats( |
|
ctx, image_formats, &num_image_formats); |
|
if (va_status != VA_STATUS_SUCCESS) |
|
goto end; |
|
|
|
num_attribs = VASurfaceAttribCount + num_image_formats; |
|
attribs = malloc(num_attribs * sizeof(*attribs)); |
|
if (!attribs) { |
|
va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; |
|
goto end; |
|
} |
|
|
|
/* Initialize with base surface attributes, except pixel-formats */ |
|
for (n = 0; attribs_map[n].type != VASurfaceAttribNone; n++) { |
|
VASurfaceAttrib * const attrib = &attribs[n]; |
|
attrib->type = attribs_map[n].type; |
|
attrib->flags = VA_SURFACE_ATTRIB_GETTABLE; |
|
attrib->value.type = attribs_map[n].value_type; |
|
} |
|
|
|
/* Append image formats */ |
|
for (i = 0; i < num_image_formats; i++) { |
|
VASurfaceAttrib * const attrib = &attribs[n]; |
|
attrib->type = VASurfaceAttribPixelFormat; |
|
attrib->flags = VA_SURFACE_ATTRIB_GETTABLE|VA_SURFACE_ATTRIB_SETTABLE; |
|
attrib->value.type = VAGenericValueTypeInteger; |
|
attrib->value.value.i = image_formats[i].fourcc; |
|
if (++n == num_attribs) { |
|
va_status = VA_STATUS_ERROR_ALLOCATION_FAILED; |
|
goto end; |
|
} |
|
} |
|
num_attribs = n; |
|
|
|
va_status = ctx->vtable->vaGetSurfaceAttributes( |
|
ctx, config, attribs, num_attribs); |
|
if (va_status != VA_STATUS_SUCCESS) |
|
goto end; |
|
|
|
/* Remove invalid entries */ |
|
out_num_attribs = 0; |
|
for (n = 0; n < num_attribs; n++) { |
|
VASurfaceAttrib * const attrib = &attribs[n]; |
|
|
|
if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED) |
|
continue; |
|
|
|
// Accept all surface attributes that are not pixel-formats |
|
if (attrib->type != VASurfaceAttribPixelFormat) { |
|
out_num_attribs++; |
|
continue; |
|
} |
|
|
|
// Drop invalid pixel-format attribute |
|
if (!attrib->value.value.i) { |
|
attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED; |
|
continue; |
|
} |
|
|
|
// Check for duplicates |
|
int is_duplicate = 0; |
|
for (i = n - 1; i >= 0 && !is_duplicate; i--) { |
|
const VASurfaceAttrib * const prev_attrib = &attribs[i]; |
|
if (prev_attrib->type != VASurfaceAttribPixelFormat) |
|
break; |
|
is_duplicate = prev_attrib->value.value.i == attrib->value.value.i; |
|
} |
|
if (is_duplicate) |
|
attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED; |
|
else |
|
out_num_attribs++; |
|
} |
|
|
|
if (*out_num_attribs_ptr < out_num_attribs) { |
|
*out_num_attribs_ptr = out_num_attribs; |
|
va_status = VA_STATUS_ERROR_MAX_NUM_EXCEEDED; |
|
goto end; |
|
} |
|
|
|
out_attrib = out_attribs; |
|
for (n = 0; n < num_attribs; n++) { |
|
const VASurfaceAttrib * const attrib = &attribs[n]; |
|
if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED) |
|
continue; |
|
*out_attrib++ = *attrib; |
|
} |
|
|
|
end: |
|
free(attribs); |
|
free(image_formats); |
|
return va_status; |
|
} |
|
|
|
VAStatus |
|
vaQuerySurfaceAttributes( |
|
VADisplay dpy, |
|
VAConfigID config, |
|
VASurfaceAttrib *attrib_list, |
|
unsigned int *num_attribs |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus vaStatus; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
if (!ctx) |
|
return VA_STATUS_ERROR_INVALID_DISPLAY; |
|
|
|
if (!ctx->vtable->vaQuerySurfaceAttributes) |
|
vaStatus = va_impl_query_surface_attributes(ctx, config, |
|
attrib_list, num_attribs); |
|
else |
|
vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config, |
|
attrib_list, num_attribs); |
|
|
|
VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs); |
|
|
|
return vaStatus; |
|
} |
|
|
|
VAStatus |
|
vaCreateSurfaces( |
|
VADisplay dpy, |
|
unsigned int format, |
|
unsigned int width, |
|
unsigned int height, |
|
VASurfaceID *surfaces, |
|
unsigned int num_surfaces, |
|
VASurfaceAttrib *attrib_list, |
|
unsigned int num_attribs |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus vaStatus; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
if (!ctx) |
|
return VA_STATUS_ERROR_INVALID_DISPLAY; |
|
|
|
if (ctx->vtable->vaCreateSurfaces2) |
|
vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height, |
|
surfaces, num_surfaces, |
|
attrib_list, num_attribs); |
|
else if (attrib_list && num_attribs > 0) |
|
vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; |
|
else |
|
vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format, |
|
num_surfaces, surfaces); |
|
VA_TRACE_LOG(va_TraceCreateSurfaces, |
|
dpy, width, height, format, num_surfaces, surfaces, |
|
attrib_list, num_attribs); |
|
|
|
return vaStatus; |
|
} |
|
|
|
|
|
VAStatus vaDestroySurfaces ( |
|
VADisplay dpy, |
|
VASurfaceID *surface_list, |
|
int num_surfaces |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus vaStatus; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_TRACE_LOG(va_TraceDestroySurfaces, |
|
dpy, surface_list, num_surfaces); |
|
|
|
vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces ); |
|
|
|
return vaStatus; |
|
} |
|
|
|
VAStatus vaCreateContext ( |
|
VADisplay dpy, |
|
VAConfigID config_id, |
|
int picture_width, |
|
int picture_height, |
|
int flag, |
|
VASurfaceID *render_targets, |
|
int num_render_targets, |
|
VAContextID *context /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus vaStatus; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
vaStatus = ctx->vtable->vaCreateContext( ctx, config_id, picture_width, picture_height, |
|
flag, render_targets, num_render_targets, context ); |
|
|
|
/* keep current encode/decode resoluton */ |
|
VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context); |
|
|
|
return vaStatus; |
|
} |
|
|
|
VAStatus vaDestroyContext ( |
|
VADisplay dpy, |
|
VAContextID context |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaDestroyContext( ctx, context ); |
|
} |
|
|
|
VAStatus vaCreateBuffer ( |
|
VADisplay dpy, |
|
VAContextID context, /* in */ |
|
VABufferType type, /* in */ |
|
unsigned int size, /* in */ |
|
unsigned int num_elements, /* in */ |
|
void *data, /* in */ |
|
VABufferID *buf_id /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus vaStatus; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id); |
|
|
|
vaStatus = ctx->vtable->vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id); |
|
|
|
VA_TRACE_LOG(va_TraceCreateBuffer, |
|
dpy, context, type, size, num_elements, data, buf_id); |
|
|
|
return vaStatus; |
|
} |
|
|
|
VAStatus vaBufferSetNumElements ( |
|
VADisplay dpy, |
|
VABufferID buf_id, /* in */ |
|
unsigned int num_elements /* in */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); |
|
|
|
return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements ); |
|
} |
|
|
|
|
|
VAStatus vaMapBuffer ( |
|
VADisplay dpy, |
|
VABufferID buf_id, /* in */ |
|
void **pbuf /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus va_status; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf); |
|
|
|
va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf ); |
|
|
|
VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf); |
|
|
|
return va_status; |
|
} |
|
|
|
VAStatus vaUnmapBuffer ( |
|
VADisplay dpy, |
|
VABufferID buf_id /* in */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); |
|
|
|
return ctx->vtable->vaUnmapBuffer( ctx, buf_id ); |
|
} |
|
|
|
VAStatus vaDestroyBuffer ( |
|
VADisplay dpy, |
|
VABufferID buffer_id |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); |
|
|
|
VA_TRACE_LOG(va_TraceDestroyBuffer, |
|
dpy, buffer_id); |
|
|
|
return ctx->vtable->vaDestroyBuffer( ctx, buffer_id ); |
|
} |
|
|
|
VAStatus vaBufferInfo ( |
|
VADisplay dpy, |
|
VAContextID __maybe_unused context, /* in */ |
|
VABufferID buf_id, /* in */ |
|
VABufferType *type, /* out */ |
|
unsigned int *size, /* out */ |
|
unsigned int *num_elements /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements); |
|
|
|
return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements ); |
|
} |
|
|
|
VAStatus vaBeginPicture ( |
|
VADisplay dpy, |
|
VAContextID context, |
|
VASurfaceID render_target |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus va_status; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target); |
|
VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); |
|
|
|
va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target ); |
|
|
|
return va_status; |
|
} |
|
|
|
VAStatus vaRenderPicture ( |
|
VADisplay dpy, |
|
VAContextID context, |
|
VABufferID *buffers, |
|
int num_buffers |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers); |
|
VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); |
|
|
|
return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers ); |
|
} |
|
|
|
VAStatus vaEndPicture ( |
|
VADisplay dpy, |
|
VAContextID context |
|
) |
|
{ |
|
VAStatus va_status = VA_STATUS_SUCCESS; |
|
VADriverContextP ctx; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); |
|
|
|
va_status = ctx->vtable->vaEndPicture( ctx, context ); |
|
|
|
/* dump surface content */ |
|
VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1); |
|
|
|
return va_status; |
|
} |
|
|
|
VAStatus vaSyncSurface ( |
|
VADisplay dpy, |
|
VASurfaceID render_target |
|
) |
|
{ |
|
VAStatus va_status; |
|
VADriverContextP ctx; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
va_status = ctx->vtable->vaSyncSurface( ctx, render_target ); |
|
VA_TRACE_LOG(va_TraceSyncSurface, dpy, render_target); |
|
|
|
return va_status; |
|
} |
|
|
|
VAStatus vaQuerySurfaceStatus ( |
|
VADisplay dpy, |
|
VASurfaceID render_target, |
|
VASurfaceStatus *status /* out */ |
|
) |
|
{ |
|
VAStatus va_status; |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
va_status = ctx->vtable->vaQuerySurfaceStatus( ctx, render_target, status ); |
|
|
|
VA_TRACE_LOG(va_TraceQuerySurfaceStatus, dpy, render_target, status); |
|
|
|
return va_status; |
|
} |
|
|
|
VAStatus vaQuerySurfaceError ( |
|
VADisplay dpy, |
|
VASurfaceID surface, |
|
VAStatus error_status, |
|
void **error_info /*out*/ |
|
) |
|
{ |
|
VAStatus va_status; |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
va_status = ctx->vtable->vaQuerySurfaceError( ctx, surface, error_status, error_info ); |
|
|
|
VA_TRACE_LOG(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info); |
|
|
|
return va_status; |
|
} |
|
|
|
/* Get maximum number of image formats supported by the implementation */ |
|
int vaMaxNumImageFormats ( |
|
VADisplay dpy |
|
) |
|
{ |
|
if (!vaDisplayIsValid(dpy)) |
|
return 0; |
|
|
|
return CTX(dpy)->max_image_formats; |
|
} |
|
|
|
VAStatus vaQueryImageFormats ( |
|
VADisplay dpy, |
|
VAImageFormat *format_list, /* out */ |
|
int *num_formats /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaQueryImageFormats ( ctx, format_list, num_formats); |
|
} |
|
|
|
/* |
|
* The width and height fields returned in the VAImage structure may get |
|
* enlarged for some YUV formats. The size of the data buffer that needs |
|
* to be allocated will be given in the "data_size" field in VAImage. |
|
* Image data is not allocated by this function. The client should |
|
* allocate the memory and fill in the VAImage structure's data field |
|
* after looking at "data_size" returned from the library. |
|
*/ |
|
VAStatus vaCreateImage ( |
|
VADisplay dpy, |
|
VAImageFormat *format, |
|
int width, |
|
int height, |
|
VAImage *image /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaCreateImage ( ctx, format, width, height, image); |
|
} |
|
|
|
/* |
|
* Should call DestroyImage before destroying the surface it is bound to |
|
*/ |
|
VAStatus vaDestroyImage ( |
|
VADisplay dpy, |
|
VAImageID image |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaDestroyImage ( ctx, image); |
|
} |
|
|
|
VAStatus vaSetImagePalette ( |
|
VADisplay dpy, |
|
VAImageID image, |
|
unsigned char *palette |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaSetImagePalette ( ctx, image, palette); |
|
} |
|
|
|
/* |
|
* Retrieve surface data into a VAImage |
|
* Image must be in a format supported by the implementation |
|
*/ |
|
VAStatus vaGetImage ( |
|
VADisplay dpy, |
|
VASurfaceID surface, |
|
int x, /* coordinates of the upper left source pixel */ |
|
int y, |
|
unsigned int width, /* width and height of the region */ |
|
unsigned int height, |
|
VAImageID image |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaGetImage ( ctx, surface, x, y, width, height, image); |
|
} |
|
|
|
/* |
|
* Copy data from a VAImage to a surface |
|
* Image must be in a format supported by the implementation |
|
*/ |
|
VAStatus vaPutImage ( |
|
VADisplay dpy, |
|
VASurfaceID surface, |
|
VAImageID image, |
|
int src_x, |
|
int src_y, |
|
unsigned int src_width, |
|
unsigned int src_height, |
|
int dest_x, |
|
int dest_y, |
|
unsigned int dest_width, |
|
unsigned int dest_height |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaPutImage ( ctx, surface, image, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height ); |
|
} |
|
|
|
/* |
|
* Derive an VAImage from an existing surface. |
|
* This interface will derive a VAImage and corresponding image buffer from |
|
* an existing VA Surface. The image buffer can then be mapped/unmapped for |
|
* direct CPU access. This operation is only possible on implementations with |
|
* direct rendering capabilities and internal surface formats that can be |
|
* represented with a VAImage. When the operation is not possible this interface |
|
* will return VA_STATUS_ERROR_OPERATION_FAILED. Clients should then fall back |
|
* to using vaCreateImage + vaPutImage to accomplish the same task in an |
|
* indirect manner. |
|
* |
|
* Implementations should only return success when the resulting image buffer |
|
* would be useable with vaMap/Unmap. |
|
* |
|
* When directly accessing a surface special care must be taken to insure |
|
* proper synchronization with the graphics hardware. Clients should call |
|
* vaQuerySurfaceStatus to insure that a surface is not the target of concurrent |
|
* rendering or currently being displayed by an overlay. |
|
* |
|
* Additionally nothing about the contents of a surface should be assumed |
|
* following a vaPutSurface. Implementations are free to modify the surface for |
|
* scaling or subpicture blending within a call to vaPutImage. |
|
* |
|
* Calls to vaPutImage or vaGetImage using the same surface from which the image |
|
* has been derived will return VA_STATUS_ERROR_SURFACE_BUSY. vaPutImage or |
|
* vaGetImage with other surfaces is supported. |
|
* |
|
* An image created with vaDeriveImage should be freed with vaDestroyImage. The |
|
* image and image buffer structures will be destroyed; however, the underlying |
|
* surface will remain unchanged until freed with vaDestroySurfaces. |
|
*/ |
|
VAStatus vaDeriveImage ( |
|
VADisplay dpy, |
|
VASurfaceID surface, |
|
VAImage *image /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaDeriveImage ( ctx, surface, image ); |
|
} |
|
|
|
|
|
/* Get maximum number of subpicture formats supported by the implementation */ |
|
int vaMaxNumSubpictureFormats ( |
|
VADisplay dpy |
|
) |
|
{ |
|
if (!vaDisplayIsValid(dpy)) |
|
return 0; |
|
|
|
return CTX(dpy)->max_subpic_formats; |
|
} |
|
|
|
/* |
|
* Query supported subpicture formats |
|
* The caller must provide a "format_list" array that can hold at |
|
* least vaMaxNumSubpictureFormats() entries. The flags arrary holds the flag |
|
* for each format to indicate additional capabilities for that format. The actual |
|
* number of formats returned in "format_list" is returned in "num_formats". |
|
*/ |
|
VAStatus vaQuerySubpictureFormats ( |
|
VADisplay dpy, |
|
VAImageFormat *format_list, /* out */ |
|
unsigned int *flags, /* out */ |
|
unsigned int *num_formats /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats); |
|
} |
|
|
|
/* |
|
* Subpictures are created with an image associated. |
|
*/ |
|
VAStatus vaCreateSubpicture ( |
|
VADisplay dpy, |
|
VAImageID image, |
|
VASubpictureID *subpicture /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaCreateSubpicture ( ctx, image, subpicture ); |
|
} |
|
|
|
/* |
|
* Destroy the subpicture before destroying the image it is assocated to |
|
*/ |
|
VAStatus vaDestroySubpicture ( |
|
VADisplay dpy, |
|
VASubpictureID subpicture |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaDestroySubpicture ( ctx, subpicture); |
|
} |
|
|
|
VAStatus vaSetSubpictureImage ( |
|
VADisplay dpy, |
|
VASubpictureID subpicture, |
|
VAImageID image |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaSetSubpictureImage ( ctx, subpicture, image); |
|
} |
|
|
|
|
|
/* |
|
* If chromakey is enabled, then the area where the source value falls within |
|
* the chromakey [min, max] range is transparent |
|
*/ |
|
VAStatus vaSetSubpictureChromakey ( |
|
VADisplay dpy, |
|
VASubpictureID subpicture, |
|
unsigned int chromakey_min, |
|
unsigned int chromakey_max, |
|
unsigned int chromakey_mask |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask ); |
|
} |
|
|
|
|
|
/* |
|
* Global alpha value is between 0 and 1. A value of 1 means fully opaque and |
|
* a value of 0 means fully transparent. If per-pixel alpha is also specified then |
|
* the overall alpha is per-pixel alpha multiplied by the global alpha |
|
*/ |
|
VAStatus vaSetSubpictureGlobalAlpha ( |
|
VADisplay dpy, |
|
VASubpictureID subpicture, |
|
float global_alpha |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha ); |
|
} |
|
|
|
/* |
|
vaAssociateSubpicture associates the subpicture with the target_surface. |
|
It defines the region mapping between the subpicture and the target |
|
surface through source and destination rectangles (with the same width and height). |
|
Both will be displayed at the next call to vaPutSurface. Additional |
|
associations before the call to vaPutSurface simply overrides the association. |
|
*/ |
|
VAStatus vaAssociateSubpicture ( |
|
VADisplay dpy, |
|
VASubpictureID subpicture, |
|
VASurfaceID *target_surfaces, |
|
int num_surfaces, |
|
short src_x, /* upper left offset in subpicture */ |
|
short src_y, |
|
unsigned short src_width, |
|
unsigned short src_height, |
|
short dest_x, /* upper left offset in surface */ |
|
short dest_y, |
|
unsigned short dest_width, |
|
unsigned short dest_height, |
|
/* |
|
* whether to enable chroma-keying or global-alpha |
|
* see VA_SUBPICTURE_XXX values |
|
*/ |
|
unsigned int flags |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
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 ); |
|
} |
|
|
|
/* |
|
* vaDeassociateSubpicture removes the association of the subpicture with target_surfaces. |
|
*/ |
|
VAStatus vaDeassociateSubpicture ( |
|
VADisplay dpy, |
|
VASubpictureID subpicture, |
|
VASurfaceID *target_surfaces, |
|
int num_surfaces |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces ); |
|
} |
|
|
|
|
|
/* Get maximum number of display attributes supported by the implementation */ |
|
int vaMaxNumDisplayAttributes ( |
|
VADisplay dpy |
|
) |
|
{ |
|
int tmp; |
|
|
|
if (!vaDisplayIsValid(dpy)) |
|
return 0; |
|
|
|
tmp = CTX(dpy)->max_display_attributes; |
|
|
|
VA_TRACE_LOG(va_TraceMaxNumDisplayAttributes, dpy, tmp); |
|
|
|
return tmp; |
|
} |
|
|
|
/* |
|
* Query display attributes |
|
* The caller must provide a "attr_list" array that can hold at |
|
* least vaMaxNumDisplayAttributes() entries. The actual number of attributes |
|
* returned in "attr_list" is returned in "num_attributes". |
|
*/ |
|
VAStatus vaQueryDisplayAttributes ( |
|
VADisplay dpy, |
|
VADisplayAttribute *attr_list, /* out */ |
|
int *num_attributes /* out */ |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus va_status; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
va_status = ctx->vtable->vaQueryDisplayAttributes ( ctx, attr_list, num_attributes ); |
|
|
|
VA_TRACE_LOG(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes); |
|
|
|
return va_status; |
|
|
|
} |
|
|
|
/* |
|
* Get display attributes |
|
* This function returns the current attribute values in "attr_list". |
|
* Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field |
|
* from vaQueryDisplayAttributes() can have their values retrieved. |
|
*/ |
|
VAStatus vaGetDisplayAttributes ( |
|
VADisplay dpy, |
|
VADisplayAttribute *attr_list, /* in/out */ |
|
int num_attributes |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus va_status; |
|
|
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
va_status = ctx->vtable->vaGetDisplayAttributes ( ctx, attr_list, num_attributes ); |
|
|
|
VA_TRACE_LOG(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes); |
|
|
|
return va_status; |
|
} |
|
|
|
/* |
|
* Set display attributes |
|
* Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field |
|
* from vaQueryDisplayAttributes() can be set. If the attribute is not settable or |
|
* the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED |
|
*/ |
|
VAStatus vaSetDisplayAttributes ( |
|
VADisplay dpy, |
|
VADisplayAttribute *attr_list, |
|
int num_attributes |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus va_status; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
va_status = ctx->vtable->vaSetDisplayAttributes ( ctx, attr_list, num_attributes ); |
|
VA_TRACE_LOG(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes); |
|
|
|
return va_status; |
|
} |
|
|
|
VAStatus vaLockSurface(VADisplay dpy, |
|
VASurfaceID surface, |
|
unsigned int *fourcc, /* following are output argument */ |
|
unsigned int *luma_stride, |
|
unsigned int *chroma_u_stride, |
|
unsigned int *chroma_v_stride, |
|
unsigned int *luma_offset, |
|
unsigned int *chroma_u_offset, |
|
unsigned int *chroma_v_offset, |
|
unsigned int *buffer_name, |
|
void **buffer |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
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); |
|
} |
|
|
|
|
|
VAStatus vaUnlockSurface(VADisplay dpy, |
|
VASurfaceID surface |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
CHECK_DISPLAY(dpy); |
|
ctx = CTX(dpy); |
|
|
|
return ctx->vtable->vaUnlockSurface( ctx, surface ); |
|
} |
|
|
|
/* Video Processing */ |
|
#define VA_VPP_INIT_CONTEXT(ctx, dpy) do { \ |
|
CHECK_DISPLAY(dpy); \ |
|
ctx = CTX(dpy); \ |
|
if (!ctx) \ |
|
return VA_STATUS_ERROR_INVALID_DISPLAY; \ |
|
} while (0) |
|
|
|
#define VA_VPP_INVOKE(dpy, func, args) do { \ |
|
if (!ctx->vtable_vpp->va##func) \ |
|
return VA_STATUS_ERROR_UNIMPLEMENTED; \ |
|
status = ctx->vtable_vpp->va##func args; \ |
|
} while (0) |
|
|
|
VAStatus |
|
vaQueryVideoProcFilters( |
|
VADisplay dpy, |
|
VAContextID context, |
|
VAProcFilterType *filters, |
|
unsigned int *num_filters |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus status; |
|
|
|
VA_VPP_INIT_CONTEXT(ctx, dpy); |
|
VA_VPP_INVOKE( |
|
ctx, |
|
QueryVideoProcFilters, |
|
(ctx, context, filters, num_filters) |
|
); |
|
return status; |
|
} |
|
|
|
VAStatus |
|
vaQueryVideoProcFilterCaps( |
|
VADisplay dpy, |
|
VAContextID context, |
|
VAProcFilterType type, |
|
void *filter_caps, |
|
unsigned int *num_filter_caps |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus status; |
|
|
|
VA_VPP_INIT_CONTEXT(ctx, dpy); |
|
VA_VPP_INVOKE( |
|
ctx, |
|
QueryVideoProcFilterCaps, |
|
(ctx, context, type, filter_caps, num_filter_caps) |
|
); |
|
return status; |
|
} |
|
|
|
VAStatus |
|
vaQueryVideoProcPipelineCaps( |
|
VADisplay dpy, |
|
VAContextID context, |
|
VABufferID *filters, |
|
unsigned int num_filters, |
|
VAProcPipelineCaps *pipeline_caps |
|
) |
|
{ |
|
VADriverContextP ctx; |
|
VAStatus status; |
|
|
|
VA_VPP_INIT_CONTEXT(ctx, dpy); |
|
VA_VPP_INVOKE( |
|
ctx, |
|
QueryVideoProcPipelineCaps, |
|
(ctx, context, filters, num_filters, pipeline_caps) |
|
); |
|
return status; |
|
}
|
|
|