| /************************************************************************** |
| * |
| * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. |
| * Copyright 2014 Advanced Micro Devices, Inc. |
| * 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. |
| * |
| **************************************************************************/ |
| |
| #include "util/u_memory.h" |
| #include "util/u_handle_table.h" |
| #include "util/u_sampler.h" |
| |
| #include "va_private.h" |
| |
| static VAImageFormat subpic_formats[] = { |
| { |
| .fourcc = VA_FOURCC_BGRA, |
| .byte_order = VA_LSB_FIRST, |
| .bits_per_pixel = 32, |
| .depth = 32, |
| .red_mask = 0x00ff0000ul, |
| .green_mask = 0x0000ff00ul, |
| .blue_mask = 0x000000fful, |
| .alpha_mask = 0xff000000ul, |
| }, |
| }; |
| |
| VAStatus |
| vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, |
| unsigned int *flags, unsigned int *num_formats) |
| { |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| |
| if (!(format_list && flags && num_formats)) |
| return VA_STATUS_ERROR_UNKNOWN; |
| |
| *num_formats = sizeof(subpic_formats)/sizeof(VAImageFormat); |
| memcpy(format_list, subpic_formats, sizeof(subpic_formats)); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus |
| vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image, |
| VASubpictureID *subpicture) |
| { |
| vlVaDriver *drv; |
| vlVaSubpicture *sub; |
| VAImage *img; |
| |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| |
| drv = VL_VA_DRIVER(ctx); |
| mtx_lock(&drv->mutex); |
| img = handle_table_get(drv->htab, image); |
| if (!img) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_IMAGE; |
| } |
| |
| sub = CALLOC(1, sizeof(*sub)); |
| if (!sub) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| |
| sub->image = img; |
| *subpicture = handle_table_add(VL_VA_DRIVER(ctx)->htab, sub); |
| pipe_mutex_unlock(drv->mutex); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus |
| vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture) |
| { |
| vlVaDriver *drv; |
| vlVaSubpicture *sub; |
| |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| |
| drv = VL_VA_DRIVER(ctx); |
| mtx_lock(&drv->mutex); |
| |
| sub = handle_table_get(drv->htab, subpicture); |
| if (!sub) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_SUBPICTURE; |
| } |
| |
| FREE(sub); |
| handle_table_remove(drv->htab, subpicture); |
| pipe_mutex_unlock(drv->mutex); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus |
| vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image) |
| { |
| vlVaDriver *drv; |
| vlVaSubpicture *sub; |
| VAImage *img; |
| |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| |
| drv = VL_VA_DRIVER(ctx); |
| mtx_lock(&drv->mutex); |
| |
| img = handle_table_get(drv->htab, image); |
| if (!img) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_IMAGE; |
| } |
| |
| sub = handle_table_get(drv->htab, subpicture); |
| pipe_mutex_unlock(drv->mutex); |
| if (!sub) |
| return VA_STATUS_ERROR_INVALID_SUBPICTURE; |
| |
| sub->image = img; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus |
| vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture, |
| unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask) |
| { |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| |
| return VA_STATUS_ERROR_UNIMPLEMENTED; |
| } |
| |
| VAStatus |
| vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha) |
| { |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| |
| return VA_STATUS_ERROR_UNIMPLEMENTED; |
| } |
| |
| VAStatus |
| vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, |
| VASurfaceID *target_surfaces, int num_surfaces, |
| short src_x, short src_y, unsigned short src_width, |
| unsigned short src_height, short dest_x, short dest_y, |
| unsigned short dest_width, unsigned short dest_height, |
| unsigned int flags) |
| { |
| vlVaSubpicture *sub; |
| struct pipe_resource tex_temp, *tex; |
| struct pipe_sampler_view sampler_templ; |
| vlVaDriver *drv; |
| vlVaSurface *surf; |
| int i; |
| struct u_rect src_rect = {src_x, src_x + src_width, src_y, src_y + src_height}; |
| struct u_rect dst_rect = {dest_x, dest_x + dest_width, dest_y, dest_y + dest_height}; |
| |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| drv = VL_VA_DRIVER(ctx); |
| mtx_lock(&drv->mutex); |
| |
| sub = handle_table_get(drv->htab, subpicture); |
| if (!sub) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_SUBPICTURE; |
| } |
| |
| for (i = 0; i < num_surfaces; i++) { |
| surf = handle_table_get(drv->htab, target_surfaces[i]); |
| if (!surf) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_SURFACE; |
| } |
| } |
| |
| sub->src_rect = src_rect; |
| sub->dst_rect = dst_rect; |
| |
| memset(&tex_temp, 0, sizeof(tex_temp)); |
| tex_temp.target = PIPE_TEXTURE_2D; |
| tex_temp.format = PIPE_FORMAT_B8G8R8A8_UNORM; |
| tex_temp.last_level = 0; |
| tex_temp.width0 = src_width; |
| tex_temp.height0 = src_height; |
| tex_temp.depth0 = 1; |
| tex_temp.array_size = 1; |
| tex_temp.usage = PIPE_USAGE_DYNAMIC; |
| tex_temp.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; |
| tex_temp.flags = 0; |
| if (!drv->pipe->screen->is_format_supported( |
| drv->pipe->screen, tex_temp.format, tex_temp.target, |
| tex_temp.nr_samples, tex_temp.bind)) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| |
| tex = drv->pipe->screen->resource_create(drv->pipe->screen, &tex_temp); |
| |
| memset(&sampler_templ, 0, sizeof(sampler_templ)); |
| u_sampler_view_default_template(&sampler_templ, tex, tex->format); |
| sub->sampler = drv->pipe->create_sampler_view(drv->pipe, tex, &sampler_templ); |
| pipe_resource_reference(&tex, NULL); |
| if (!sub->sampler) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| |
| for (i = 0; i < num_surfaces; i++) { |
| surf = handle_table_get(drv->htab, target_surfaces[i]); |
| util_dynarray_append(&surf->subpics, vlVaSubpicture *, sub); |
| } |
| pipe_mutex_unlock(drv->mutex); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus |
| vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, |
| VASurfaceID *target_surfaces, int num_surfaces) |
| { |
| int i; |
| int j; |
| vlVaSurface *surf; |
| vlVaSubpicture *sub, **array; |
| vlVaDriver *drv; |
| |
| if (!ctx) |
| return VA_STATUS_ERROR_INVALID_CONTEXT; |
| drv = VL_VA_DRIVER(ctx); |
| mtx_lock(&drv->mutex); |
| |
| sub = handle_table_get(drv->htab, subpicture); |
| if (!sub) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_SUBPICTURE; |
| } |
| |
| for (i = 0; i < num_surfaces; i++) { |
| surf = handle_table_get(drv->htab, target_surfaces[i]); |
| if (!surf) { |
| pipe_mutex_unlock(drv->mutex); |
| return VA_STATUS_ERROR_INVALID_SURFACE; |
| } |
| |
| array = surf->subpics.data; |
| if (!array) |
| continue; |
| |
| for (j = 0; j < surf->subpics.size/sizeof(vlVaSubpicture *); j++) { |
| if (array[j] == sub) |
| array[j] = NULL; |
| } |
| |
| while (surf->subpics.size && util_dynarray_top(&surf->subpics, vlVaSubpicture *) == NULL) |
| (void)util_dynarray_pop(&surf->subpics, vlVaSubpicture *); |
| } |
| pipe_mutex_unlock(drv->mutex); |
| |
| return VA_STATUS_SUCCESS; |
| } |