X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fvdpau%2Foutput.c;h=8237eaceb266f46c46d24cd80903c8cdf4e8c07f;hb=1bac4a1e6fef40cb0adef1a4af0050fc6fb71c7f;hp=72e63fc2f3222f6f29d90ffd7a729c440f7caa44;hpb=aa63ebc48a2ee1ee9afbf2112d4d25e8a9a8d1e8;p=mesa.git diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c index 72e63fc2f32..8237eaceb26 100644 --- a/src/gallium/state_trackers/vdpau/output.c +++ b/src/gallium/state_trackers/vdpau/output.c @@ -28,25 +28,31 @@ #include -#include -#include +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_sampler.h" +#include "util/u_format.h" + +#include "vl/vl_csc.h" #include "vdpau_private.h" +/** + * Create a VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfaceCreate(VdpDevice device, VdpRGBAFormat rgba_format, uint32_t width, uint32_t height, VdpOutputSurface *surface) { - struct pipe_video_context *context; + struct pipe_context *pipe; struct pipe_resource res_tmpl, *res; struct pipe_sampler_view sv_templ; struct pipe_surface surf_templ; vlVdpOutputSurface *vlsurface = NULL; - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating output surface\n"); if (!(width && height)) return VDP_STATUS_INVALID_SIZE; @@ -54,14 +60,16 @@ vlVdpOutputSurfaceCreate(VdpDevice device, if (!dev) return VDP_STATUS_INVALID_HANDLE; - context = dev->context->vpipe; - if (!context) + pipe = dev->context; + if (!pipe) return VDP_STATUS_INVALID_HANDLE; vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); if (!vlsurface) return VDP_STATUS_RESOURCES; + vlsurface->device = dev; + memset(&res_tmpl, 0, sizeof(res_tmpl)); res_tmpl.target = PIPE_TEXTURE_2D; @@ -73,55 +81,74 @@ vlVdpOutputSurfaceCreate(VdpDevice device, res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; res_tmpl.usage = PIPE_USAGE_STATIC; - res = context->screen->resource_create(context->screen, &res_tmpl); + pipe_mutex_lock(dev->mutex); + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); if (!res) { + pipe_mutex_unlock(dev->mutex); FREE(dev); + FREE(vlsurface); return VDP_STATUS_ERROR; } - memset(&sv_templ, 0, sizeof(sv_templ)); - u_sampler_view_default_template(&sv_templ, res, res->format); - - // as long as we don't have a background picture we don't want an alpha channel - sv_templ.swizzle_a = PIPE_SWIZZLE_ONE; - - vlsurface->sampler_view = context->create_sampler_view(context, res, &sv_templ); + vlVdpDefaultSamplerViewTemplate(&sv_templ, res); + vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); if (!vlsurface->sampler_view) { + pipe_resource_reference(&res, NULL); + pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } memset(&surf_templ, 0, sizeof(surf_templ)); surf_templ.format = res->format; - surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - vlsurface->surface = context->create_surface(context, res, &surf_templ); + vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); if (!vlsurface->surface) { + pipe_resource_reference(&res, NULL); + pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } *surface = vlAddDataHTAB(vlsurface); if (*surface == 0) { + pipe_resource_reference(&res, NULL); + pipe_mutex_unlock(dev->mutex); FREE(dev); return VDP_STATUS_ERROR; } + + pipe_resource_reference(&res, NULL); + + vl_compositor_init_state(&vlsurface->cstate, pipe); + vl_compositor_reset_dirty_area(&vlsurface->dirty_area); + pipe_mutex_unlock(dev->mutex); return VDP_STATUS_OK; } +/** + * Destroy a VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) { vlVdpOutputSurface *vlsurface; - - VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying output surface\n"); + struct pipe_context *pipe; vlsurface = vlGetDataHTAB(surface); if (!vlsurface) return VDP_STATUS_INVALID_HANDLE; + pipe = vlsurface->device->context; + + pipe_mutex_lock(vlsurface->device->mutex); + vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); + pipe_surface_reference(&vlsurface->surface, NULL); pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); + pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL); + vl_compositor_cleanup_state(&vlsurface->cstate); + pipe_mutex_unlock(vlsurface->device->mutex); vlRemoveDataHTAB(surface); FREE(vlsurface); @@ -129,32 +156,110 @@ vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) return VDP_STATUS_OK; } +/** + * Retrieve the parameters used to create a VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, VdpRGBAFormat *rgba_format, uint32_t *width, uint32_t *height) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *vlsurface; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); + *width = vlsurface->sampler_view->texture->width0; + *height = vlsurface->sampler_view->texture->height0; + + return VDP_STATUS_OK; } +/** + * Copy image data from a VdpOutputSurface to application memory in the + * surface's native format. + */ VdpStatus vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, VdpRect const *source_rect, void *const *destination_data, uint32_t const *destination_pitches) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *vlsurface; + struct pipe_context *pipe; + struct pipe_resource *res; + struct pipe_box box; + struct pipe_transfer *transfer; + uint8_t *map; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe = vlsurface->device->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + pipe_mutex_lock(vlsurface->device->mutex); + vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); + + res = vlsurface->sampler_view->texture; + box = RectToPipeBox(source_rect, res); + map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box, &transfer); + if (!map) { + pipe_mutex_unlock(vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + + pipe_transfer_unmap(pipe, transfer); + pipe_mutex_unlock(vlsurface->device->mutex); + + return VDP_STATUS_OK; } +/** + * Copy image data from application memory in the surface's native format to + * a VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, void const *const *source_data, uint32_t const *source_pitches, VdpRect const *destination_rect) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *vlsurface; + struct pipe_box dst_box; + struct pipe_context *pipe; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe = vlsurface->device->context; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + pipe_mutex_lock(vlsurface->device->mutex); + vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); + + dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); + pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0, + PIPE_TRANSFER_WRITE, &dst_box, *source_data, + *source_pitches, 0); + pipe_mutex_unlock(vlsurface->device->mutex); + + return VDP_STATUS_OK; } +/** + * Copy image data from application memory in a specific indexed format to + * a VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, VdpIndexedFormat source_indexed_format, @@ -164,9 +269,138 @@ vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, VdpColorTableFormat color_table_format, void const *color_table) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *vlsurface; + struct pipe_context *context; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + enum pipe_format index_format; + enum pipe_format colortbl_format; + + struct pipe_resource *res, res_tmpl; + struct pipe_sampler_view sv_tmpl; + struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; + + struct pipe_box box; + struct u_rect dst_rect; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + context = vlsurface->device->context; + compositor = &vlsurface->device->compositor; + cstate = &vlsurface->cstate; + + index_format = FormatIndexedToPipe(source_indexed_format); + if (index_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_INDEXED_FORMAT; + + if (!source_data || !source_pitch) + return VDP_STATUS_INVALID_POINTER; + + colortbl_format = FormatColorTableToPipe(color_table_format); + if (colortbl_format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; + + if (!color_table) + return VDP_STATUS_INVALID_POINTER; + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = index_format; + + if (destination_rect) { + res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); + res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); + } else { + res_tmpl.width0 = vlsurface->surface->texture->width0; + res_tmpl.height0 = vlsurface->surface->texture->height0; + } + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.usage = PIPE_USAGE_STAGING; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; + + pipe_mutex_lock(vlsurface->device->mutex); + vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); + + res = context->screen->resource_create(context->screen, &res_tmpl); + if (!res) + goto error_resource; + + box.x = box.y = box.z = 0; + box.width = res->width0; + box.height = res->height0; + box.depth = res->depth0; + + context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, + source_data[0], source_pitch[0], + source_pitch[0] * res->height0); + + memset(&sv_tmpl, 0, sizeof(sv_tmpl)); + u_sampler_view_default_template(&sv_tmpl, res, res->format); + + sv_idx = context->create_sampler_view(context, res, &sv_tmpl); + pipe_resource_reference(&res, NULL); + + if (!sv_idx) + goto error_resource; + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + res_tmpl.target = PIPE_TEXTURE_1D; + res_tmpl.format = colortbl_format; + res_tmpl.width0 = 1 << util_format_get_component_bits( + index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); + res_tmpl.height0 = 1; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.usage = PIPE_USAGE_STAGING; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; + + res = context->screen->resource_create(context->screen, &res_tmpl); + if (!res) + goto error_resource; + + box.x = box.y = box.z = 0; + box.width = res->width0; + box.height = res->height0; + box.depth = res->depth0; + + context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, + util_format_get_stride(colortbl_format, res->width0), 0); + + memset(&sv_tmpl, 0, sizeof(sv_tmpl)); + u_sampler_view_default_template(&sv_tmpl, res, res->format); + + sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); + pipe_resource_reference(&res, NULL); + + if (!sv_tbl) + goto error_resource; + + vl_compositor_clear_layers(cstate); + vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); + + pipe_sampler_view_reference(&sv_idx, NULL); + pipe_sampler_view_reference(&sv_tbl, NULL); + pipe_mutex_unlock(vlsurface->device->mutex); + + return VDP_STATUS_OK; + +error_resource: + pipe_sampler_view_reference(&sv_idx, NULL); + pipe_sampler_view_reference(&sv_tbl, NULL); + pipe_mutex_unlock(vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; } +/** + * Copy image data from application memory in a specific YCbCr format to + * a VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, VdpYCbCrFormat source_ycbcr_format, @@ -175,9 +409,208 @@ vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, VdpRect const *destination_rect, VdpCSCMatrix const *csc_matrix) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *vlsurface; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + struct pipe_context *pipe; + enum pipe_format format; + struct pipe_video_buffer vtmpl, *vbuffer; + struct u_rect dst_rect; + struct pipe_sampler_view **sampler_views; + + unsigned i; + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + + pipe = vlsurface->device->context; + compositor = &vlsurface->device->compositor; + cstate = &vlsurface->cstate; + + format = FormatYCBCRToPipe(source_ycbcr_format); + if (format == PIPE_FORMAT_NONE) + return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; + + if (!source_data || !source_pitches) + return VDP_STATUS_INVALID_POINTER; + + pipe_mutex_lock(vlsurface->device->mutex); + vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); + memset(&vtmpl, 0, sizeof(vtmpl)); + vtmpl.buffer_format = format; + vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + + if (destination_rect) { + vtmpl.width = abs(destination_rect->x0-destination_rect->x1); + vtmpl.height = abs(destination_rect->y0-destination_rect->y1); + } else { + vtmpl.width = vlsurface->surface->texture->width0; + vtmpl.height = vlsurface->surface->texture->height0; + } + + vbuffer = pipe->create_video_buffer(pipe, &vtmpl); + if (!vbuffer) { + pipe_mutex_unlock(vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + sampler_views = vbuffer->get_sampler_view_planes(vbuffer); + if (!sampler_views) { + vbuffer->destroy(vbuffer); + pipe_mutex_unlock(vlsurface->device->mutex); + return VDP_STATUS_RESOURCES; + } + + for (i = 0; i < 3; ++i) { + struct pipe_sampler_view *sv = sampler_views[i]; + if (!sv) continue; + + struct pipe_box dst_box = { + 0, 0, 0, + sv->texture->width0, sv->texture->height0, 1 + }; + + pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box, + source_data[i], source_pitches[i], 0); + } + + if (!csc_matrix) { + vl_csc_matrix csc; + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc); + vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc); + } else { + vl_compositor_set_csc_matrix(cstate, csc_matrix); + } + + vl_compositor_clear_layers(cstate); + vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); + + vbuffer->destroy(vbuffer); + pipe_mutex_unlock(vlsurface->device->mutex); + + return VDP_STATUS_OK; } +static unsigned +BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) +{ + switch (factor) { + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: + return PIPE_BLENDFACTOR_ZERO; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: + return PIPE_BLENDFACTOR_ONE; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: + return PIPE_BLENDFACTOR_SRC_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: + return PIPE_BLENDFACTOR_INV_SRC_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: + return PIPE_BLENDFACTOR_SRC_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: + return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: + return PIPE_BLENDFACTOR_DST_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: + return PIPE_BLENDFACTOR_INV_DST_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: + return PIPE_BLENDFACTOR_DST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: + return PIPE_BLENDFACTOR_INV_DST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: + return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_CONST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_INV_CONST_COLOR; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_CONST_ALPHA; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_INV_CONST_ALPHA; + default: + assert(0); + return PIPE_BLENDFACTOR_ONE; + } +} + +static unsigned +BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) +{ + switch (equation) { + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: + return PIPE_BLEND_SUBTRACT; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: + return PIPE_BLEND_REVERSE_SUBTRACT; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: + return PIPE_BLEND_ADD; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: + return PIPE_BLEND_MIN; + case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: + return PIPE_BLEND_MAX; + default: + assert(0); + return PIPE_BLEND_ADD; + } +} + +static void * +BlenderToPipe(struct pipe_context *context, + VdpOutputSurfaceRenderBlendState const *blend_state) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof blend); + blend.independent_blend_enable = 0; + + if (blend_state) { + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); + blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); + blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); + blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); + blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); + blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); + } else { + blend.rt[0].blend_enable = 0; + } + + blend.logicop_enable = 0; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + blend.rt[0].colormask = PIPE_MASK_RGBA; + blend.dither = 0; + + return context->create_blend_state(context, &blend); +} + +static struct vertex4f * +ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4]) +{ + unsigned i; + struct vertex4f *dst = result; + + if (!colors) + return NULL; + + for (i = 0; i < 4; ++i) { + dst->x = colors->red; + dst->y = colors->green; + dst->z = colors->blue; + dst->w = colors->alpha; + + ++dst; + if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) + ++colors; + } + return result; +} + +/** + * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of + * another VdpOutputSurface; Output Surface object VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, VdpRect const *destination_rect, @@ -187,9 +620,56 @@ vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, VdpOutputSurfaceRenderBlendState const *blend_state, uint32_t flags) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *dst_vlsurface; + vlVdpOutputSurface *src_vlsurface; + + struct pipe_context *context; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + struct u_rect src_rect, dst_rect; + + struct vertex4f vlcolors[4]; + void *blend; + + dst_vlsurface = vlGetDataHTAB(destination_surface); + if (!dst_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + src_vlsurface = vlGetDataHTAB(source_surface); + if (!src_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (dst_vlsurface->device != src_vlsurface->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + pipe_mutex_lock(dst_vlsurface->device->mutex); + vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); + + context = dst_vlsurface->device->context; + compositor = &dst_vlsurface->device->compositor; + cstate = &dst_vlsurface->cstate; + + blend = BlenderToPipe(context, blend_state); + + vl_compositor_clear_layers(cstate); + vl_compositor_set_layer_blend(cstate, 0, blend, false); + vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, + RectToPipe(source_rect, &src_rect), NULL, + ColorsToPipe(colors, flags, vlcolors)); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); + + context->delete_blend_state(context, blend); + pipe_mutex_unlock(dst_vlsurface->device->mutex); + + return VDP_STATUS_OK; } +/** + * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of + * a VdpOutputSurface; Output Surface object VdpOutputSurface. + */ VdpStatus vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, VdpRect const *destination_rect, @@ -199,5 +679,48 @@ vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, VdpOutputSurfaceRenderBlendState const *blend_state, uint32_t flags) { - return VDP_STATUS_NO_IMPLEMENTATION; + vlVdpOutputSurface *dst_vlsurface; + vlVdpBitmapSurface *src_vlsurface; + + struct pipe_context *context; + struct vl_compositor *compositor; + struct vl_compositor_state *cstate; + + struct u_rect src_rect, dst_rect; + + struct vertex4f vlcolors[4]; + void *blend; + + dst_vlsurface = vlGetDataHTAB(destination_surface); + if (!dst_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + src_vlsurface = vlGetDataHTAB(source_surface); + if (!src_vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + if (dst_vlsurface->device != src_vlsurface->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + context = dst_vlsurface->device->context; + compositor = &dst_vlsurface->device->compositor; + cstate = &dst_vlsurface->cstate; + + pipe_mutex_lock(dst_vlsurface->device->mutex); + vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); + + blend = BlenderToPipe(context, blend_state); + + vl_compositor_clear_layers(cstate); + vl_compositor_set_layer_blend(cstate, 0, blend, false); + vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, + RectToPipe(source_rect, &src_rect), NULL, + ColorsToPipe(colors, flags, vlcolors)); + vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); + vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); + + context->delete_blend_state(context, blend); + pipe_mutex_unlock(dst_vlsurface->device->mutex); + + return VDP_STATUS_OK; }