X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=va%2Fva.c;h=0a129a9d2adecdd43428ddaab7565ba918e433d2;hb=b4d0874dcbe99d1f47bd39d0c156ea89ecd0ebcc;hp=aab00f00795f802fa1f15439d41735a4ebfe31e4;hpb=ca1798e77b6fa99dbb010f202a057f75415afd52;p=android-x86%2Fhardware-intel-common-libva.git diff --git a/va/va.c b/va/va.c index aab00f0..0a129a9 100644 --- a/va/va.c +++ b/va/va.c @@ -26,6 +26,7 @@ #include "sysdeps.h" #include "va.h" #include "va_backend.h" +#include "va_backend_vpp.h" #include "va_trace.h" #include "va_fool.h" @@ -36,6 +37,16 @@ #include #include #include +#ifdef ANDROID +#include +/* support versions < JellyBean */ +#ifndef ALOGE +#define ALOGE LOGE +#endif +#ifndef ALOGI +#define ALOGI LOGI +#endif +#endif #define DRIVER_EXTENSION "_drv_video.so" @@ -47,10 +58,9 @@ #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 + * libva.conf has higher priority * return 0: the "env" is set, and the value is copied into env_value * 1: the env is not set */ @@ -65,17 +75,19 @@ int va_parseConfig(char *env, char *env_value) fp = fopen("/etc/libva.conf", "r"); while (fp && (fgets(oneline, 1024, fp) != NULL)) { - if (strlen(oneline) == 1) - continue; + if (strlen(oneline) == 1) + continue; token = strtok_r(oneline, "=\n", &saveptr); - value = strtok_r(NULL, "=\n", &saveptr); + value = strtok_r(NULL, "=\n", &saveptr); - if (NULL == token || NULL == value) - continue; + if (NULL == token || NULL == value) + continue; if (strcmp(token, env) == 0) { - if (env_value) + if (env_value) { strncpy(env_value,value, 1024); + env_value[1023] = '\0'; + } fclose(fp); @@ -86,10 +98,12 @@ int va_parseConfig(char *env, char *env_value) fclose(fp); /* no setting in config file, use env setting */ - if (getenv(env)) { - if (env_value) - strncpy(env_value, getenv(env), 1024); - + value = getenv(env); + if (value) { + if (env_value) { + strncpy(env_value, value, 1024); + env_value[1023] = '\0'; + } return 0; } @@ -102,51 +116,152 @@ int vaDisplayIsValid(VADisplay dpy) return pDisplayContext && (pDisplayContext->vadpy_magic == VA_DISPLAY_MAGIC) && pDisplayContext->vaIsValid(pDisplayContext); } +static void default_log_error(const char *buffer) +{ +# ifdef ANDROID + ALOGE("%s", buffer); +# else + fprintf(stderr, "libva error: %s", buffer); +# endif +} + +static void default_log_info(const char *buffer) +{ +# ifdef ANDROID + ALOGI("%s", buffer); +# else + fprintf(stderr, "libva info: %s", buffer); +# endif +} + +static vaMessageCallback va_log_error = default_log_error; +static vaMessageCallback va_log_info = default_log_info; + +/** + * Set the callback for error messages, or NULL for no logging. + * Returns the previous one, or NULL if it was disabled. + */ +vaMessageCallback vaSetErrorCallback(vaMessageCallback callback) +{ + vaMessageCallback old_callback = va_log_error; + va_log_error = callback; + return old_callback; +} + +/** + * Set the callback for info messages, or NULL for no logging. + * Returns the previous one, or NULL if it was disabled. + */ +vaMessageCallback vaSetInfoCallback(vaMessageCallback callback) +{ + vaMessageCallback old_callback = va_log_info; + va_log_info = callback; + return old_callback; +} + +void va_MessagingInit() +{ +#if ENABLE_VA_MESSAGING + char env_value[1024]; + + if (va_parseConfig("LIBVA_MESSAGING_LEVEL", &env_value[0]) == 0) { + if (strcmp(env_value, "0") == 0) { + vaSetInfoCallback(NULL); + vaSetErrorCallback(NULL); + } + + if (strcmp(env_value, "1") == 0) { + vaSetInfoCallback(NULL); + } + } +#endif +} + void va_errorMessage(const char *msg, ...) { +#if ENABLE_VA_MESSAGING + char buf[512], *dynbuf; va_list args; + int n, len; + + if (va_log_error == NULL) + return; - 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); +#endif } void va_infoMessage(const char *msg, ...) { +#if ENABLE_VA_MESSAGING + char buf[512], *dynbuf; va_list args; + int n, len; + + if (va_log_info == NULL) + return; - 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); +#endif } -static Bool va_checkVtable(void *ptr, char *function) +static bool va_checkVtable(void *ptr, char *function) { 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) { 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) { va_errorMessage("Failed to define str_%s in init\n", variable); - return False; + return false; } - return True; + return true; } static inline int @@ -184,6 +299,13 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name) 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) ); @@ -202,15 +324,43 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name) } else { VADriverInit init_func = NULL; char init_func_s[256]; - if (va_getDriverInitName(init_func_s, sizeof(init_func_s), - VA_MAJOR_VERSION, VA_MINOR_VERSION)) - init_func = (VADriverInit) dlsym(handle, init_func_s); - if (!init_func) { + int i; + + static const struct { + int major; + int minor; + } compatible_versions[] = { + { VA_MAJOR_VERSION, VA_MINOR_VERSION }, + { 0, 39 }, + { 0, 38 }, + { 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; + } + } + } + + 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) { @@ -220,7 +370,16 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name) } ctx->vtable = vtable; - if (VA_STATUS_SUCCESS == vaStatus) + 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) { @@ -358,12 +517,79 @@ const char *vaErrorStr(VAStatus error_status) 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 */ @@ -373,33 +599,59 @@ VAStatus vaInitialize ( 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_MessagingInit(); + + 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 (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); @@ -431,9 +683,13 @@ VAStatus vaTerminate ( } free(old_ctx->vtable); old_ctx->vtable = NULL; + free(old_ctx->vtable_vpp); + old_ctx->vtable_vpp = NULL; - if (VA_STATUS_SUCCESS == vaStatus) - pDisplayContext->vaDestroy(pDisplayContext); + if (old_ctx->override_driver_name) { + free(old_ctx->override_driver_name); + old_ctx->override_driver_name = NULL; + } VA_TRACE_LOG(va_TraceTerminate, dpy); @@ -441,6 +697,9 @@ VAStatus vaTerminate ( va_FoolEnd(dpy); + if (VA_STATUS_SUCCESS == vaStatus) + pDisplayContext->vaDestroy(pDisplayContext); + return vaStatus; } @@ -550,7 +809,6 @@ VAStatus vaCreateConfig ( { VADriverContextP ctx; VAStatus vaStatus = VA_STATUS_SUCCESS; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); @@ -558,7 +816,7 @@ VAStatus vaCreateConfig ( vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id ); /* record the current entrypoint for further trace/fool determination */ - VA_TRACE_FUNC(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id); + 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; @@ -570,10 +828,16 @@ VAStatus vaDestroyConfig ( ) { VADriverContextP ctx; + VAStatus vaStatus = VA_STATUS_SUCCESS; + CHECK_DISPLAY(dpy); ctx = CTX(dpy); - return ctx->vtable->vaDestroyConfig ( ctx, config_id ); + vaStatus = ctx->vtable->vaDestroyConfig ( ctx, config_id ); + + VA_TRACE_ALL(va_TraceDestroyConfig, dpy, config_id); + + return vaStatus; } VAStatus vaQueryConfigAttributes ( @@ -592,27 +856,204 @@ VAStatus vaQueryConfigAttributes ( 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; + 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; + } - CHECK_DISPLAY(dpy); - ctx = CTX(dpy); + 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_LOG(va_TraceCreateSurface, dpy, width, height, format, num_surfaces, surfaces); - - return vaStatus; + /* 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; } @@ -623,10 +1064,17 @@ VAStatus vaDestroySurfaces ( ) { 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 ( @@ -650,7 +1098,7 @@ VAStatus vaCreateContext ( flag, render_targets, num_render_targets, context ); /* keep current encode/decode resoluton */ - VA_TRACE_FUNC(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context); + VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context); return vaStatus; } @@ -661,10 +1109,16 @@ VAStatus vaDestroyContext ( ) { VADriverContextP ctx; + VAStatus vaStatus; + CHECK_DISPLAY(dpy); ctx = CTX(dpy); - return ctx->vtable->vaDestroyContext( ctx, context ); + vaStatus = ctx->vtable->vaDestroyContext( ctx, context ); + + VA_TRACE_ALL(va_TraceDestroyContext, dpy, context); + + return vaStatus; } VAStatus vaCreateBuffer ( @@ -678,15 +1132,19 @@ VAStatus vaCreateBuffer ( ) { VADriverContextP ctx; + VAStatus vaStatus; + CHECK_DISPLAY(dpy); ctx = CTX(dpy); - int ret = 0; VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id); - if (ret) - return VA_STATUS_SUCCESS; - return ctx->vtable->vaCreateBuffer( ctx, 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 ( @@ -698,8 +1156,8 @@ VAStatus vaBufferSetNumElements ( VADriverContextP ctx; CHECK_DISPLAY(dpy); ctx = CTX(dpy); - - VA_FOOL_RETURN(); + + VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements ); } @@ -713,18 +1171,15 @@ VAStatus vaMapBuffer ( { VADriverContextP ctx; VAStatus va_status; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); - + VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf); - if (ret) - return VA_STATUS_SUCCESS; va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf ); - VA_TRACE_LOG(va_TraceMapBuffer, dpy, buf_id, pbuf); + VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf); return va_status; } @@ -737,11 +1192,8 @@ VAStatus vaUnmapBuffer ( VADriverContextP ctx; CHECK_DISPLAY(dpy); ctx = CTX(dpy); - int ret = 0; - VA_FOOL_FUNC(va_FoolUnmapBuffer, dpy, buf_id); - if (ret) - return VA_STATUS_SUCCESS; + VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); return ctx->vtable->vaUnmapBuffer( ctx, buf_id ); } @@ -755,7 +1207,10 @@ VAStatus vaDestroyBuffer ( CHECK_DISPLAY(dpy); ctx = CTX(dpy); - VA_FOOL_RETURN(); + VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); + + VA_TRACE_LOG(va_TraceDestroyBuffer, + dpy, buffer_id); return ctx->vtable->vaDestroyBuffer( ctx, buffer_id ); } @@ -770,18 +1225,43 @@ VAStatus vaBufferInfo ( ) { VADriverContextP ctx; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements); - if (ret) - return VA_STATUS_SUCCESS; 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 ( VADisplay dpy, VAContextID context, @@ -790,13 +1270,12 @@ VAStatus vaBeginPicture ( { VADriverContextP ctx; VAStatus va_status; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); - VA_TRACE_FUNC(va_TraceBeginPicture, dpy, context, render_target); - VA_FOOL_RETURN(); + VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target); + VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target ); @@ -811,13 +1290,12 @@ VAStatus vaRenderPicture ( ) { VADriverContextP ctx; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers); - VA_FOOL_RETURN(); + VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers ); } @@ -827,21 +1305,18 @@ VAStatus vaEndPicture ( VAContextID context ) { - VAStatus va_status; + VAStatus va_status = VA_STATUS_SUCCESS; VADriverContextP ctx; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); - /* dump encode source surface */ - VA_TRACE_SURFACE(va_TraceEndPicture, dpy, context, 0); - /* return directly if do dummy operation */ - VA_FOOL_RETURN(); - + VA_FOOL_FUNC(va_FoolCheckContinuity, dpy); + va_status = ctx->vtable->vaEndPicture( ctx, context ); - /* dump decode dest surface */ - VA_TRACE_SURFACE(va_TraceEndPicture, dpy, context, 1); + + /* dump surface content */ + VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1); return va_status; } @@ -853,7 +1328,6 @@ VAStatus vaSyncSurface ( { VAStatus va_status; VADriverContextP ctx; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); @@ -1093,7 +1567,6 @@ VAStatus vaQuerySubpictureFormats ( ) { VADriverContextP ctx; - int ret = 0; CHECK_DISPLAY(dpy); ctx = CTX(dpy); @@ -1356,3 +1829,79 @@ VAStatus vaUnlockSurface(VADisplay 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; +}