#include "sysdeps.h"
#include "va.h"
#include "va_backend.h"
+#include "va_backend_vpp.h"
#include "va_trace.h"
#include "va_fool.h"
#include <dlfcn.h>
#include <unistd.h>
-#define DRIVER_INIT_FUNC "__vaDriverInit_0_31"
-
#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_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;
-extern int trace_flag;
-#define VA_TRACE(trace_func,...) \
- if (trace_flag) { \
- trace_func(__VA_ARGS__); \
- }
-
-extern int fool_decode;
-extern int fool_encode;
-#define VA_FOOL(fool_func,...) \
- if (fool_decode || fool_encode) { \
- ret = fool_func(__VA_ARGS__); \
- }
-
/*
* read a config "env" for libva.conf or from environment setting
* liva.conf has higher priority
char oneline[1024];
FILE *fp=NULL;
-
if (env == NULL)
return 1;
fclose(fp);
/* no setting in config file, use env setting */
- if (getenv(env)) {
+ value = getenv(env);
+ if (value) {
if (env_value)
- strncpy(env_value, getenv(env), 1024);
-
+ strncpy(env_value, value, 1024);
return 0;
}
void va_errorMessage(const char *msg, ...)
{
+ char buf[512], *dynbuf;
va_list args;
+ int n, len;
- fprintf(stderr, "libva error: ");
va_start(args, msg);
- vfprintf(stderr, msg, args);
+ 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;
- fprintf(stderr, "libva: ");
va_start(args, msg);
- vfprintf(stderr, msg, args);
+ 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)
+static bool va_checkVtable(void *ptr, char *function)
{
- if (!ptr)
- {
+ if (!ptr) {
va_errorMessage("No valid vtable entry for va%s\n", function);
- return False;
+ return false;
}
- return True;
+ return true;
}
-static Bool va_checkMaximum(int value, char *variable)
+static bool va_checkMaximum(int value, char *variable)
{
- if (!value)
- {
+ if (!value) {
va_errorMessage("Failed to define max_%s in init\n", variable);
- return False;
+ return false;
}
- return True;
+ return true;
}
-static Bool va_checkString(const char* value, char *variable)
+static bool va_checkString(const char* value, char *variable)
{
- if (!value)
- {
+ if (!value) {
va_errorMessage("Failed to define str_%s in init\n", variable);
- return False;
+ return false;
}
- return True;
+ 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)
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((const char *)search_path, ":", &saveptr);
- while(driver_dir)
- {
+ 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) );
#else
handle = dlopen( driver_path, RTLD_NOW| RTLD_GLOBAL);
#endif
- if (!handle)
- {
+ 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, 37 },
+ { 0, 36 },
+ { 0, 35 },
+ { 0, 34 },
+ { 0, 33 },
+ { 0, 32 },
+ { -1, }
+ };
+
+ 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;
+ }
+ }
}
- }
- else
- {
- VADriverInit init_func;
- init_func = (VADriverInit) dlsym(handle, DRIVER_INIT_FUNC);
- if (!init_func)
- {
- va_errorMessage("%s has no function %s\n", driver_path, DRIVER_INIT_FUNC);
+
+ if (compatible_versions[i].major < 0) {
+ va_errorMessage("%s has no function %s\n",
+ driver_path, init_func_s);
dlclose(handle);
- }
- else
- {
- vaStatus = (*init_func)(ctx);
+ } 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 (VA_STATUS_SUCCESS == vaStatus)
- {
+ 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_VTABLE(vaStatus, ctx, GetDisplayAttributes);
CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes);
}
- if (VA_STATUS_SUCCESS != vaStatus)
- {
+ 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;
}
VAPrivFunc vaGetLibFunc(VADisplay dpy, const char *func)
{
VADriverContextP ctx;
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return NULL;
ctx = CTX(dpy);
*/
const char *vaErrorStr(VAStatus error_status)
{
- switch(error_status)
- {
+ switch(error_status) {
case VA_STATUS_SUCCESS:
return "success (no error)";
case VA_STATUS_ERROR_OPERATION_FAILED:
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";
}
-
+
+const static char *prefer_driver_list[4] = {
+ "i965",
+ "hybrid",
+ "pvr",
+ "iHD",
+};
+
+VAStatus vaSetDriverName(
+ VADisplay dpy,
+ char *driver_name
+)
+{
+ VADriverContextP ctx;
+ VAStatus vaStatus = VA_STATUS_SUCCESS;
+ char *override_driver_name = NULL;
+ int i, found;
+ ctx = CTX(dpy);
+
+ if (geteuid() != getuid()) {
+ vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+ va_errorMessage("no permission to vaSetDriverName\n");
+ return vaStatus;
+ }
+
+ if (strlen(driver_name) == 0 || strlen(driver_name) >=256) {
+ vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
+ va_errorMessage("vaSetDriverName returns %s\n",
+ vaErrorStr(vaStatus));
+ return vaStatus;
+ }
+
+ found = 0;
+ for (i = 0; i < sizeof(prefer_driver_list) / sizeof(char *); i++) {
+ if (strlen(prefer_driver_list[i]) != strlen(driver_name))
+ continue;
+ if (!strncmp(prefer_driver_list[i], driver_name, strlen(driver_name))) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
+ va_errorMessage("vaSetDriverName returns %s. Incorrect parameter\n",
+ vaErrorStr(vaStatus));
+ return vaStatus;
+ }
+
+ override_driver_name = strdup(driver_name);
+
+ if (!override_driver_name) {
+ vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
+ va_errorMessage("vaSetDriverName returns %s. Out of Memory\n",
+ vaErrorStr(vaStatus));
+ return vaStatus;
+ }
+
+ ctx->override_driver_name = override_driver_name;
+ return VA_STATUS_SUCCESS;
+}
+
VAStatus vaInitialize (
VADisplay dpy,
int *major_version, /* out */
const char *driver_name_env = NULL;
char *driver_name = NULL;
VAStatus vaStatus;
+ VADriverContextP ctx;
CHECK_DISPLAY(dpy);
+ ctx = CTX(dpy);
+
va_TraceInit(dpy);
va_FoolInit(dpy);
- va_infoMessage("libva version %s\n", VA_VERSION_S);
+ va_infoMessage("VA-API version %s\n", VA_VERSION_S);
+
+ vaStatus = va_getDriverName(dpy, &driver_name);
- driver_name_env = getenv("LIBVA_DRIVER_NAME");
- if (driver_name_env && geteuid() == getuid())
- {
+ if (!ctx->override_driver_name) {
+ va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
+
+ driver_name_env = getenv("LIBVA_DRIVER_NAME");
+ } else if (vaStatus == VA_STATUS_SUCCESS) {
+ if (driver_name)
+ free(driver_name);
+
+ driver_name = strdup(ctx->override_driver_name);
+ if (!driver_name) {
+ vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
+ va_errorMessage("vaInitialize() failed with %s, out of memory\n",
+ vaErrorStr(vaStatus));
+ return vaStatus;
+ }
+ va_infoMessage("User requested driver '%s'\n", driver_name);
+ }
+
+ if ((VA_STATUS_SUCCESS == vaStatus) &&
+ driver_name_env && (geteuid() == getuid())) {
/* Don't allow setuid apps to use LIBVA_DRIVER_NAME */
+ if (driver_name) /* memory is allocated in va_getDriverName */
+ free(driver_name);
+
driver_name = strdup(driver_name_env);
vaStatus = VA_STATUS_SUCCESS;
va_infoMessage("User requested driver '%s'\n", driver_name);
}
- else
- {
- vaStatus = va_getDriverName(dpy, &driver_name);
- va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
- }
- if (VA_STATUS_SUCCESS == vaStatus)
- {
+ if ((VA_STATUS_SUCCESS == vaStatus) && (driver_name != NULL)) {
vaStatus = va_openDriver(dpy, driver_name);
va_infoMessage("va_openDriver() returns %d\n", vaStatus);
*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);
if (driver_name)
free(driver_name);
+
+ VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version);
+
return vaStatus;
}
old_ctx = CTX(dpy);
if (old_ctx->handle) {
- vaStatus = old_ctx->vtable.vaTerminate(old_ctx);
+ 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;
+
+ if (old_ctx->override_driver_name) {
+ free(old_ctx->override_driver_name);
+ old_ctx->override_driver_name = NULL;
+ }
- if (VA_STATUS_SUCCESS == vaStatus)
- pDisplayContext->vaDestroy(pDisplayContext);
+ VA_TRACE_LOG(va_TraceTerminate, dpy);
va_TraceEnd(dpy);
va_FoolEnd(dpy);
+ if (VA_STATUS_SUCCESS == vaStatus)
+ pDisplayContext->vaDestroy(pDisplayContext);
+
return vaStatus;
}
VADisplay dpy
)
{
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return NULL;
return CTX(dpy)->str_vendor;
VADisplay dpy
)
{
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return 0;
return CTX(dpy)->max_profiles;
VADisplay dpy
)
{
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return 0;
return CTX(dpy)->max_entrypoints;
VADisplay dpy
)
{
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return 0;
return CTX(dpy)->max_attributes;
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
+ return ctx->vtable->vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
}
VAStatus vaGetConfigAttributes (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
+ return ctx->vtable->vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
}
VAStatus vaQueryConfigProfiles (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
+ return ctx->vtable->vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
}
VAStatus vaCreateConfig (
{
VADriverContextP ctx;
VAStatus vaStatus = VA_STATUS_SUCCESS;
- int ret = 0;
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_FOOL(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
-
- vaStatus = ctx->vtable.vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
+ vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
- VA_TRACE(va_TraceCreateConfig, dpy, 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;
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDestroyConfig ( ctx, config_id );
+ return ctx->vtable->vaDestroyConfig ( ctx, config_id );
}
VAStatus vaQueryConfigAttributes (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
+ return ctx->vtable->vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
}
-VAStatus vaCreateSurfaces (
- VADisplay dpy,
- int width,
- int height,
- int format,
- int num_surfaces,
- VASurfaceID *surfaces /* out */
+/* 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
)
{
- VADriverContextP ctx;
- VAStatus vaStatus;
- int ret = 0;
-
- CHECK_DISPLAY(dpy);
- ctx = CTX(dpy);
+ 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;
- vaStatus = ctx->vtable.vaCreateSurfaces( ctx, width, height, format, num_surfaces, surfaces );
+ num_attribs = VASurfaceAttribCount + num_image_formats;
+ attribs = malloc(num_attribs * sizeof(*attribs));
+ if (!attribs) {
+ va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
+ goto end;
+ }
- VA_TRACE(va_TraceCreateSurface, dpy, width, height, format, num_surfaces, surfaces);
+ /* 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;
+ }
- VA_FOOL(va_FoolCreateSurfaces, dpy, width, height, format, num_surfaces, surfaces);
-
- return vaStatus;
+ /* 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;
}
)
{
VADriverContextP ctx;
+ VAStatus vaStatus;
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDestroySurfaces( ctx, surface_list, num_surfaces );
+ VA_TRACE_LOG(va_TraceDestroySurfaces,
+ dpy, surface_list, num_surfaces);
+
+ vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
+
+ return vaStatus;
}
VAStatus vaCreateContext (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- vaStatus = ctx->vtable.vaCreateContext( ctx, config_id, picture_width, picture_height,
+ vaStatus = ctx->vtable->vaCreateContext( ctx, config_id, picture_width, picture_height,
flag, render_targets, num_render_targets, context );
- VA_TRACE(va_TraceCreateContext, dpy, 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;
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDestroyContext( ctx, context );
+ return ctx->vtable->vaDestroyContext( ctx, context );
}
VAStatus vaCreateBuffer (
)
{
VADriverContextP ctx;
+ VAStatus vaStatus;
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- int ret = 0;
-
- VA_FOOL(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id);
- if (ret)
- return VA_STATUS_SUCCESS;
+
+ 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 ctx->vtable.vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id);
+ return vaStatus;
}
VAStatus vaBufferSetNumElements (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaBufferSetNumElements( ctx, buf_id, num_elements );
+ VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
+
+ return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements );
}
{
VADriverContextP ctx;
VAStatus va_status;
- int ret = 0;
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_FOOL(va_FoolMapBuffer, dpy, buf_id, pbuf);
- if (ret)
- return VA_STATUS_SUCCESS;
+ VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf);
- va_status = ctx->vtable.vaMapBuffer( ctx, buf_id, pbuf );
+ va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf );
- if (va_status == VA_STATUS_SUCCESS)
- VA_TRACE(va_TraceMapBuffer, dpy, buf_id, pbuf);
+ VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf);
return va_status;
}
VADriverContextP ctx;
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- int ret = 0;
-
- VA_FOOL(va_FoolUnmapBuffer, dpy, buf_id);
- if (ret)
- return VA_STATUS_SUCCESS;
-
- return ctx->vtable.vaUnmapBuffer( ctx, buf_id );
+
+ VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
+
+ return ctx->vtable->vaUnmapBuffer( ctx, buf_id );
}
VAStatus vaDestroyBuffer (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDestroyBuffer( ctx, buffer_id );
+ VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
+
+ VA_TRACE_LOG(va_TraceDestroyBuffer,
+ dpy, buffer_id);
+
+ return ctx->vtable->vaDestroyBuffer( ctx, buffer_id );
}
VAStatus vaBufferInfo (
)
{
VADriverContextP ctx;
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaBufferInfo( ctx, context, buf_id, type, size, num_elements );
+ VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements);
+
+ return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements );
+}
+
+/* Locks buffer for external API usage */
+VAStatus
+vaAcquireBufferHandle(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info)
+{
+ VADriverContextP ctx;
+
+ CHECK_DISPLAY(dpy);
+ ctx = CTX(dpy);
+
+ if (!ctx->vtable->vaAcquireBufferHandle)
+ return VA_STATUS_ERROR_UNIMPLEMENTED;
+ return ctx->vtable->vaAcquireBufferHandle(ctx, buf_id, buf_info);
+}
+
+/* Unlocks buffer after usage from external API */
+VAStatus
+vaReleaseBufferHandle(VADisplay dpy, VABufferID buf_id)
+{
+ VADriverContextP ctx;
+
+ CHECK_DISPLAY(dpy);
+ ctx = CTX(dpy);
+
+ if (!ctx->vtable->vaReleaseBufferHandle)
+ return VA_STATUS_ERROR_UNIMPLEMENTED;
+ return ctx->vtable->vaReleaseBufferHandle(ctx, buf_id);
}
VAStatus vaBeginPicture (
)
{
VADriverContextP ctx;
- int ret = 0;
-
+ VAStatus va_status;
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_TRACE(va_TraceBeginPicture, dpy, context, render_target);
-
- VA_FOOL(va_FoolBeginPicture, dpy, context, render_target);
- if (ret)
- return VA_STATUS_SUCCESS;
-
- return ctx->vtable.vaBeginPicture( ctx, context, render_target );
+ 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 (
)
{
VADriverContextP ctx;
- int ret = 0;
-
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_FOOL(va_FoolRenderPicture, dpy, context, buffers, num_buffers);
- if (ret)
- return VA_STATUS_SUCCESS;
+ VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
+ VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
- VA_TRACE(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
-
- return ctx->vtable.vaRenderPicture( ctx, context, buffers, num_buffers );
+ return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers );
}
VAStatus vaEndPicture (
VAContextID context
)
{
- VAStatus va_status;
+ VAStatus va_status = VA_STATUS_SUCCESS;
VADriverContextP ctx;
- int ret = 0;
-
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_FOOL(va_FoolEndPicture, dpy, context);
- if (ret) {
- VA_TRACE(va_TraceEndPicture, dpy, context);
- return VA_STATUS_SUCCESS;
- }
-
- va_status = ctx->vtable.vaEndPicture( ctx, context );
-
- VA_TRACE(va_TraceEndPicture, dpy, context);
+ 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 va_status;
VADriverContextP ctx;
- int ret = 0;
-
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_FOOL(va_FoolSyncSurface, dpy, render_target);
- if (ret)
- return VA_STATUS_SUCCESS;
-
- va_status = ctx->vtable.vaSyncSurface( ctx, render_target );
- VA_TRACE(va_TraceSyncSurface, dpy, render_target);
+ va_status = ctx->vtable->vaSyncSurface( ctx, render_target );
+ VA_TRACE_LOG(va_TraceSyncSurface, dpy, render_target);
return va_status;
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- va_status = ctx->vtable.vaQuerySurfaceStatus( ctx, render_target, status );
+ va_status = ctx->vtable->vaQuerySurfaceStatus( ctx, render_target, status );
- VA_TRACE(va_TraceQuerySurfaceStatus, dpy, render_target, status);
+ VA_TRACE_LOG(va_TraceQuerySurfaceStatus, dpy, render_target, status);
return va_status;
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- va_status = ctx->vtable.vaQuerySurfaceError( ctx, surface, error_status, error_info );
+ va_status = ctx->vtable->vaQuerySurfaceError( ctx, surface, error_status, error_info );
- VA_TRACE(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info);
+ VA_TRACE_LOG(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info);
return va_status;
}
VADisplay dpy
)
{
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return 0;
return CTX(dpy)->max_image_formats;
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaQueryImageFormats ( ctx, format_list, num_formats);
+ return ctx->vtable->vaQueryImageFormats ( ctx, format_list, num_formats);
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaCreateImage ( ctx, format, width, height, image);
+ return ctx->vtable->vaCreateImage ( ctx, format, width, height, image);
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDestroyImage ( ctx, image);
+ return ctx->vtable->vaDestroyImage ( ctx, image);
}
VAStatus vaSetImagePalette (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaSetImagePalette ( ctx, image, palette);
+ return ctx->vtable->vaSetImagePalette ( ctx, image, palette);
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaGetImage ( ctx, surface, x, y, width, height, image);
+ return ctx->vtable->vaGetImage ( ctx, surface, x, y, width, height, image);
}
/*
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 );
+ return ctx->vtable->vaPutImage ( ctx, surface, image, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height );
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDeriveImage ( ctx, surface, image );
+ return ctx->vtable->vaDeriveImage ( ctx, surface, image );
}
VADisplay dpy
)
{
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return 0;
return CTX(dpy)->max_subpic_formats;
)
{
VADriverContextP ctx;
- int ret = 0;
-
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
-
- VA_FOOL(va_FoolQuerySubpictureFormats, dpy, format_list, flags, num_formats);
- if (ret)
- return VA_STATUS_SUCCESS;
-
- return ctx->vtable.vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats);
+
+ return ctx->vtable->vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats);
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaCreateSubpicture ( ctx, image, subpicture );
+ return ctx->vtable->vaCreateSubpicture ( ctx, image, subpicture );
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDestroySubpicture ( ctx, subpicture);
+ return ctx->vtable->vaDestroySubpicture ( ctx, subpicture);
}
VAStatus vaSetSubpictureImage (
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaSetSubpictureImage ( ctx, subpicture, image);
+ return ctx->vtable->vaSetSubpictureImage ( ctx, subpicture, image);
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask );
+ return ctx->vtable->vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask );
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha );
+ return ctx->vtable->vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha );
}
/*
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 );
+ 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 );
}
/*
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces );
+ return ctx->vtable->vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces );
}
{
int tmp;
- if( !vaDisplayIsValid(dpy) )
+ if (!vaDisplayIsValid(dpy))
return 0;
tmp = CTX(dpy)->max_display_attributes;
- VA_TRACE(va_TraceMaxNumDisplayAttributes, dpy, tmp);
+ VA_TRACE_LOG(va_TraceMaxNumDisplayAttributes, dpy, tmp);
return tmp;
}
)
{
VADriverContextP ctx;
- CHECK_DISPLAY(dpy);
- ctx = CTX(dpy);
-
VAStatus va_status;
- va_status = ctx->vtable.vaQueryDisplayAttributes ( ctx, attr_list, num_attributes );
+ CHECK_DISPLAY(dpy);
+ ctx = CTX(dpy);
+ va_status = ctx->vtable->vaQueryDisplayAttributes ( ctx, attr_list, num_attributes );
- VA_TRACE(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes);
+ VA_TRACE_LOG(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes);
return va_status;
)
{
VADriverContextP ctx;
+ VAStatus va_status;
+
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
+ va_status = ctx->vtable->vaGetDisplayAttributes ( ctx, attr_list, num_attributes );
- VAStatus va_status;
-
- va_status = ctx->vtable.vaGetDisplayAttributes ( ctx, attr_list, num_attributes );
-
- VA_TRACE(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes);
+ VA_TRACE_LOG(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes);
return va_status;
}
)
{
VADriverContextP ctx;
+ VAStatus va_status;
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- VA_TRACE(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes);
-
+ va_status = ctx->vtable->vaSetDisplayAttributes ( ctx, attr_list, num_attributes );
+ VA_TRACE_LOG(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes);
- return ctx->vtable.vaSetDisplayAttributes ( ctx, attr_list, num_attributes );
+ return va_status;
}
VAStatus vaLockSurface(VADisplay dpy,
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);
+ 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);
}
CHECK_DISPLAY(dpy);
ctx = CTX(dpy);
- return ctx->vtable.vaUnlockSurface( ctx, surface );
+ 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;
}