From e5f78a74f8294ee02015552db664dae1e7da9f47 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20K=C3=B6nig?= Date: Sun, 3 Apr 2011 16:09:23 +0200 Subject: [PATCH] [g3dvl] split compositor out of video context Also redesign the compositor a bit and make the result a public available interface --- src/gallium/auxiliary/vl/vl_compositor.c | 556 +++++++++--------- src/gallium/auxiliary/vl/vl_compositor.h | 63 +- src/gallium/auxiliary/vl/vl_mpeg12_context.c | 90 +-- src/gallium/auxiliary/vl/vl_mpeg12_context.h | 1 - src/gallium/include/pipe/p_video_context.h | 106 +++- .../state_trackers/xorg/xvmc/context.c | 12 +- .../state_trackers/xorg/xvmc/surface.c | 21 +- .../state_trackers/xorg/xvmc/xvmc_private.h | 2 + 8 files changed, 423 insertions(+), 428 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index f62706e5066..45e9cea9f66 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -36,38 +36,11 @@ #include #include #include "vl_csc.h" +#include "vl_types.h" -struct vertex_shader_consts -{ - struct vertex4f dst_scale; - struct vertex4f dst_trans; - struct vertex4f src_scale; - struct vertex4f src_trans; -}; - -struct fragment_shader_consts -{ - float matrix[16]; -}; - -static bool -u_video_rects_equal(struct pipe_video_rect *a, struct pipe_video_rect *b) -{ - assert(a && b); - - if (a->x != b->x) - return false; - if (a->y != b->y) - return false; - if (a->w != b->w) - return false; - if (a->h != b->h) - return false; - - return true; -} +typedef float csc_matrix[16]; -static bool +static void * create_vert_shader(struct vl_compositor *c) { struct ureg_program *shader; @@ -92,15 +65,11 @@ create_vert_shader(struct vl_compositor *c) ureg_END(shader); - c->vertex_shader = ureg_create_shader_and_destroy(shader, c->pipe); - if (!c->vertex_shader) - return false; - - return true; + return ureg_create_shader_and_destroy(shader, c->pipe); } -static bool -create_frag_shader_ycbcr_2_rgb(struct vl_compositor *c) +static void * +create_frag_shader_video_buffer(struct vl_compositor *c) { struct ureg_program *shader; struct ureg_src tc; @@ -139,15 +108,11 @@ create_frag_shader_ycbcr_2_rgb(struct vl_compositor *c) ureg_release_temporary(shader, texel); ureg_END(shader); - c->fragment_shader.ycbcr_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe); - if (!c->fragment_shader.ycbcr_2_rgb) - return false; - - return true; + return ureg_create_shader_and_destroy(shader, c->pipe); } -static bool -create_frag_shader_palette_2_rgb(struct vl_compositor *c) +static void * +create_frag_shader_palette(struct vl_compositor *c) { struct ureg_program *shader; struct ureg_src tc; @@ -167,7 +132,9 @@ create_frag_shader_palette_2_rgb(struct vl_compositor *c) texel = ureg_DECL_temporary(shader); /* - * fragment = tex(tc, sampler) + * texel = tex(tc, sampler) + * fragment.xyz = tex(texel, palette) + * fragment.a = texel.a */ ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler); ureg_TEX(shader, fragment, TGSI_TEXTURE_1D, ureg_src(texel), palette); @@ -176,15 +143,11 @@ create_frag_shader_palette_2_rgb(struct vl_compositor *c) ureg_release_temporary(shader, texel); ureg_END(shader); - c->fragment_shader.palette_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe); - if (!c->fragment_shader.palette_2_rgb) - return false; - - return true; + return ureg_create_shader_and_destroy(shader, c->pipe); } -static bool -create_frag_shader_rgb_2_rgb(struct vl_compositor *c) +static void * +create_frag_shader_rgba(struct vl_compositor *c) { struct ureg_program *shader; struct ureg_src tc; @@ -205,13 +168,51 @@ create_frag_shader_rgb_2_rgb(struct vl_compositor *c) ureg_TEX(shader, fragment, TGSI_TEXTURE_2D, tc, sampler); ureg_END(shader); - c->fragment_shader.rgb_2_rgb = ureg_create_shader_and_destroy(shader, c->pipe); - if (!c->fragment_shader.rgb_2_rgb) + return ureg_create_shader_and_destroy(shader, c->pipe); +} + +static bool +init_shaders(struct vl_compositor *c) +{ + assert(c); + + c->vs = create_vert_shader(c); + if (!c->vs) { + debug_printf("Unable to create vertex shader.\n"); return false; + } + + c->fs_video_buffer = create_frag_shader_video_buffer(c); + if (!c->fs_video_buffer) { + debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n"); + return false; + } + + c->fs_palette = create_frag_shader_palette(c); + if (!c->fs_palette) { + debug_printf("Unable to create Palette-to-RGB fragment shader.\n"); + return false; + } + + c->fs_rgba = create_frag_shader_rgba(c); + if (!c->fs_rgba) { + debug_printf("Unable to create RGB-to-RGB fragment shader.\n"); + return false; + } return true; } +static void cleanup_shaders(struct vl_compositor *c) +{ + assert(c); + + c->pipe->delete_vs_state(c->pipe, c->vs); + c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer); + c->pipe->delete_fs_state(c->pipe, c->fs_palette); + c->pipe->delete_fs_state(c->pipe, c->fs_rgba); +} + static bool init_pipe_state(struct vl_compositor *c) { @@ -223,6 +224,13 @@ init_pipe_state(struct vl_compositor *c) c->fb_state.nr_cbufs = 1; c->fb_state.zsbuf = NULL; + c->viewport.scale[2] = 1; + c->viewport.scale[3] = 1; + c->viewport.translate[0] = 0; + c->viewport.translate[1] = 0; + c->viewport.translate[2] = 0; + c->viewport.translate[3] = 0; + memset(&sampler, 0, sizeof(sampler)); sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -266,45 +274,9 @@ static void cleanup_pipe_state(struct vl_compositor *c) c->pipe->delete_blend_state(c->pipe, c->blend); } -static bool -init_shaders(struct vl_compositor *c) -{ - assert(c); - - if (!create_vert_shader(c)) { - debug_printf("Unable to create vertex shader.\n"); - return false; - } - if (!create_frag_shader_ycbcr_2_rgb(c)) { - debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n"); - return false; - } - if (!create_frag_shader_palette_2_rgb(c)) { - debug_printf("Unable to create Palette-to-RGB fragment shader.\n"); - return false; - } - if (!create_frag_shader_rgb_2_rgb(c)) { - debug_printf("Unable to create RGB-to-RGB fragment shader.\n"); - return false; - } - - return true; -} - -static void cleanup_shaders(struct vl_compositor *c) -{ - assert(c); - - c->pipe->delete_vs_state(c->pipe, c->vertex_shader); - c->pipe->delete_fs_state(c->pipe, c->fragment_shader.ycbcr_2_rgb); - c->pipe->delete_fs_state(c->pipe, c->fragment_shader.palette_2_rgb); - c->pipe->delete_fs_state(c->pipe, c->fragment_shader.rgb_2_rgb); -} - static bool init_buffers(struct vl_compositor *c) { - struct fragment_shader_consts fsc; struct pipe_vertex_element vertex_elems[2]; assert(c); @@ -338,18 +310,14 @@ init_buffers(struct vl_compositor *c) * Const buffer contains the color conversion matrix and bias vectors */ /* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */ - c->fs_const_buf = pipe_buffer_create + c->csc_matrix = pipe_buffer_create ( c->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC, - sizeof(struct fragment_shader_consts) + sizeof(csc_matrix) ); - vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, fsc.matrix); - - vl_compositor_set_csc_matrix(c, fsc.matrix); - return true; } @@ -360,99 +328,27 @@ cleanup_buffers(struct vl_compositor *c) c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state); pipe_resource_reference(&c->vertex_buf.buffer, NULL); - pipe_resource_reference(&c->fs_const_buf, NULL); + pipe_resource_reference(&c->csc_matrix, NULL); } -bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe) +static inline struct pipe_video_rect +default_rect(struct vl_compositor_layer *layer) { - unsigned i; - - assert(compositor); - - memset(compositor, 0, sizeof(struct vl_compositor)); - - compositor->pipe = pipe; - - if (!init_pipe_state(compositor)) - return false; - - if (!init_shaders(compositor)) { - cleanup_pipe_state(compositor); - return false; - } - if (!init_buffers(compositor)) { - cleanup_shaders(compositor); - cleanup_pipe_state(compositor); - return false; - } - - compositor->fb_state.width = 0; - compositor->fb_state.height = 0; - for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) - compositor->layers[i] = NULL; - compositor->dirty_layers = 0; - - return true; + struct pipe_resource *res = layer->sampler_views[0]->texture; + struct pipe_video_rect rect = { 0, 0, res->width0, res->height0 }; + return rect; } -void vl_compositor_cleanup(struct vl_compositor *compositor) -{ - assert(compositor); - - cleanup_buffers(compositor); - cleanup_shaders(compositor); - cleanup_pipe_state(compositor); -} - -void vl_compositor_set_layers(struct vl_compositor *compositor, - struct pipe_sampler_view *layers[], - struct pipe_sampler_view *palettes[], - struct pipe_video_rect *src_rects[], - struct pipe_video_rect *dst_rects[], - unsigned num_layers) -{ - unsigned i; - - assert(compositor); - assert(num_layers <= VL_COMPOSITOR_MAX_LAYERS); - - for (i = 0; i < num_layers; ++i) - { - assert((layers[i] && src_rects[i] && dst_rects[i]) || - (!layers[i] && !src_rects[i] && !dst_rects[i])); - - if (compositor->layers[i] != layers[i] || - compositor->palettes[i] != palettes[i] || - !u_video_rects_equal(&compositor->layer_src_rects[i], src_rects[i]) || - !u_video_rects_equal(&compositor->layer_dst_rects[i], dst_rects[i])) - { - pipe_sampler_view_reference(&compositor->layers[i], layers[i]); - pipe_sampler_view_reference(&compositor->palettes[i], palettes[i]); - compositor->layer_src_rects[i] = *src_rects[i]; - compositor->layer_dst_rects[i] = *dst_rects[i]; - compositor->dirty_layers |= 1 << i; - } - - if (layers[i]) - compositor->dirty_layers |= 1 << i; - } - - for (; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { - pipe_sampler_view_reference(&compositor->layers[i], NULL); - pipe_sampler_view_reference(&compositor->palettes[i], NULL); - } -} - -static void gen_rect_verts(struct pipe_video_rect *src_rect, - struct vertex2f *src_inv_size, - struct pipe_video_rect *dst_rect, - struct vertex2f *dst_inv_size, - struct vertex4f *vb) +static void +gen_rect_verts(struct vertex4f *vb, + struct pipe_video_rect *src_rect, + struct vertex2f *src_inv_size, + struct pipe_video_rect *dst_rect, + struct vertex2f *dst_inv_size) { - assert(src_rect); - assert(src_inv_size); - assert((dst_rect && dst_inv_size) /*|| (!dst_rect && !dst_inv_size)*/); assert(vb); + assert(src_rect && src_inv_size); + assert(dst_rect && dst_inv_size); vb[0].x = dst_rect->x * dst_inv_size->x; vb[0].y = dst_rect->y * dst_inv_size->y; @@ -475,162 +371,252 @@ static void gen_rect_verts(struct pipe_video_rect *src_rect, vb[3].w = (src_rect->y + src_rect->h) * src_inv_size->y; } -static unsigned gen_data(struct vl_compositor *c, - struct pipe_sampler_view *src_surface, - struct pipe_video_rect *src_rect, - struct pipe_video_rect *dst_rect, - struct pipe_sampler_view *textures[VL_COMPOSITOR_MAX_LAYERS + 1][2], - void **frag_shaders) +static void +gen_vertex_data(struct vl_compositor *c, struct pipe_video_rect *dst_rect, struct vertex2f *dst_inv_size) { struct vertex4f *vb; struct pipe_transfer *buf_transfer; - unsigned num_rects = 0; unsigned i; assert(c); - assert(src_surface); - assert(src_rect); assert(dst_rect); - assert(textures); vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, &buf_transfer); if (!vb) - return 0; - - { - struct vertex2f src_inv_size = { 1.0f / src_surface->texture->width0, 1.0f / src_surface->texture->height0}; - gen_rect_verts(src_rect, &src_inv_size, dst_rect, &c->fb_inv_size, vb); - textures[num_rects][0] = src_surface; - textures[num_rects][1] = NULL; - /* XXX: Hack, sort of */ - frag_shaders[num_rects] = c->fragment_shader.ycbcr_2_rgb; - ++num_rects; - vb += 4; - } + return; - for (i = 0; c->dirty_layers > 0; i++) { - assert(i < VL_COMPOSITOR_MAX_LAYERS); + for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) { + if (c->used_layers & (1 << i)) { + struct pipe_sampler_view *sv = c->layers[i].sampler_views[0]; + struct vertex2f src_inv_size = {1.0f / sv->texture->width0, 1.0f / sv->texture->height0}; - if (c->dirty_layers & (1 << i)) { - struct vertex2f layer_inv_size = {1.0f / c->layers[i]->texture->width0, 1.0f / c->layers[i]->texture->height0}; - gen_rect_verts(&c->layer_src_rects[i], &layer_inv_size, &c->layer_dst_rects[i], &layer_inv_size, vb); - textures[num_rects][0] = c->layers[i]; - textures[num_rects][1] = c->palettes[i]; - - if (c->palettes[i]) - frag_shaders[num_rects] = c->fragment_shader.palette_2_rgb; + if (&c->layers[i].fs == c->fs_video_buffer) + gen_rect_verts(vb, &c->layers[i].src_rect, &src_inv_size, dst_rect, dst_inv_size); else - frag_shaders[num_rects] = c->fragment_shader.rgb_2_rgb; + gen_rect_verts(vb, &c->layers[i].src_rect, &src_inv_size, &c->layers[i].dst_rect, &src_inv_size); - ++num_rects; vb += 4; - c->dirty_layers &= ~(1 << i); } } pipe_buffer_unmap(c->pipe, buf_transfer); - - return num_rects; } -static void draw_layers(struct vl_compositor *c, - struct vl_ycbcr_sampler_views *src_sampler, - struct pipe_video_rect *src_rect, - struct pipe_video_rect *dst_rect) +static void +draw_layers(struct vl_compositor *c) { - unsigned num_rects; - struct pipe_sampler_view *surfaces[VL_COMPOSITOR_MAX_LAYERS + 1][2]; - void *frag_shaders[VL_COMPOSITOR_MAX_LAYERS + 1]; - unsigned i; + unsigned vb_index, i; assert(c); - assert(src_sampler); - assert(src_rect); - assert(dst_rect); - num_rects = gen_data(c, src_sampler->y, src_rect, dst_rect, surfaces, frag_shaders); + for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { + if (c->used_layers & (1 << i)) { + struct pipe_sampler_view **samplers = &c->layers[i].sampler_views[0]; + unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3; - c->pipe->bind_blend_state(c->pipe, c->blend); - for (i = 0; i < num_rects; ++i) { - c->pipe->bind_fs_state(c->pipe, frag_shaders[i]); - if (i == 0) { - c->pipe->set_fragment_sampler_views(c->pipe, 3, &src_sampler->y); - } else { - c->pipe->set_fragment_sampler_views(c->pipe, surfaces[i][1] ? 2 : 1, &surfaces[i][0]); + c->pipe->bind_fs_state(c->pipe, c->layers[i].fs); + c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers); + util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4); + vb_index++; } - - util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, i * 4, 4); } } -void vl_compositor_render(struct vl_compositor *compositor, - struct vl_ycbcr_sampler_views *src_sampler, - struct pipe_video_rect *src_area, - struct pipe_surface *dst_surface, - struct pipe_video_rect *dst_area, - struct pipe_fence_handle **fence) +static void +vl_compositor_clear_layers(struct pipe_video_compositor *compositor) { - void *samplers[3]; + struct vl_compositor *c = (struct vl_compositor *)compositor; + unsigned i, j; assert(compositor); - assert(src_sampler); - assert(src_area); - assert(dst_surface); - assert(dst_area); - if (compositor->fb_state.width != dst_surface->width) { - compositor->fb_inv_size.x = 1.0f / dst_surface->width; - compositor->fb_state.width = dst_surface->width; - } - if (compositor->fb_state.height != dst_surface->height) { - compositor->fb_inv_size.y = 1.0f / dst_surface->height; - compositor->fb_state.height = dst_surface->height; + c->used_layers = 0; + for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { + c->layers[i].fs = NULL; + for ( j = 0; j < 3; j++) + pipe_sampler_view_reference(&c->layers[i].sampler_views[j], NULL); } +} - compositor->fb_state.cbufs[0] = dst_surface; - - compositor->viewport.scale[0] = compositor->fb_state.width; - compositor->viewport.scale[1] = compositor->fb_state.height; - compositor->viewport.scale[2] = 1; - compositor->viewport.scale[3] = 1; - compositor->viewport.translate[0] = 0; - compositor->viewport.translate[1] = 0; - compositor->viewport.translate[2] = 0; - compositor->viewport.translate[3] = 0; - - samplers[0] = samplers[1] = samplers[2] = compositor->sampler; +static void +vl_compositor_destroy(struct pipe_video_compositor *compositor) +{ + struct vl_compositor *c = (struct vl_compositor *)compositor; + assert(compositor); - compositor->pipe->set_framebuffer_state(compositor->pipe, &compositor->fb_state); - compositor->pipe->set_viewport_state(compositor->pipe, &compositor->viewport); - compositor->pipe->bind_fragment_sampler_states(compositor->pipe, 3, &samplers[0]); - compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader); - compositor->pipe->set_vertex_buffers(compositor->pipe, 1, &compositor->vertex_buf); - compositor->pipe->bind_vertex_elements_state(compositor->pipe, compositor->vertex_elems_state); - compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, compositor->fs_const_buf); + vl_compositor_clear_layers(compositor); - draw_layers(compositor, src_sampler, src_area, dst_area); + cleanup_buffers(c); + cleanup_shaders(c); + cleanup_pipe_state(c); - assert(!compositor->dirty_layers); - compositor->pipe->flush(compositor->pipe, fence); + FREE(compositor); } -void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat) +static void +vl_compositor_set_csc_matrix(struct pipe_video_compositor *compositor, const float matrix[16]) { + struct vl_compositor *c = (struct vl_compositor *)compositor; struct pipe_transfer *buf_transfer; assert(compositor); memcpy ( - pipe_buffer_map(compositor->pipe, compositor->fs_const_buf, + pipe_buffer_map(c->pipe, c->csc_matrix, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, &buf_transfer), - mat, - sizeof(struct fragment_shader_consts) + matrix, + sizeof(csc_matrix) ); - pipe_buffer_unmap(compositor->pipe, buf_transfer); + pipe_buffer_unmap(c->pipe, buf_transfer); +} + +static void +vl_compositor_set_buffer_layer(struct pipe_video_compositor *compositor, + unsigned layer, + struct pipe_video_buffer *buffer, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect) +{ + struct vl_compositor *c = (struct vl_compositor *)compositor; + assert(compositor && buffer); + + assert(layer < VL_COMPOSITOR_MAX_LAYERS); + + c->used_layers |= 1 << layer; + c->layers[layer].fs = c->fs_video_buffer; + buffer->get_sampler_views(buffer, c->layers[layer].sampler_views); + c->layers[layer].src_rect = src_rect ? *src_rect : default_rect(&c->layers[layer]); + c->layers[layer].dst_rect = dst_rect ? *dst_rect : default_rect(&c->layers[layer]); +} + +static void +vl_compositor_set_palette_layer(struct pipe_video_compositor *compositor, + unsigned layer, + struct pipe_sampler_view *indexes, + struct pipe_sampler_view *palette, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect) +{ + struct vl_compositor *c = (struct vl_compositor *)compositor; + assert(compositor && indexes && palette); + + assert(layer < VL_COMPOSITOR_MAX_LAYERS); + + c->used_layers |= 1 << layer; + c->layers[layer].fs = c->fs_palette; + pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], indexes); + pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], palette); + pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL); + c->layers[layer].src_rect = src_rect ? *src_rect : default_rect(&c->layers[layer]); + c->layers[layer].dst_rect = dst_rect ? *dst_rect : default_rect(&c->layers[layer]); +} + +static void +vl_compositor_set_rgba_layer(struct pipe_video_compositor *compositor, + unsigned layer, + struct pipe_sampler_view *rgba, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect) +{ + struct vl_compositor *c = (struct vl_compositor *)compositor; + assert(compositor && rgba); + + assert(layer < VL_COMPOSITOR_MAX_LAYERS); + + c->used_layers |= 1 << layer; + c->layers[layer].fs = c->fs_rgba; + pipe_sampler_view_reference(&c->layers[layer].sampler_views[0], rgba); + pipe_sampler_view_reference(&c->layers[layer].sampler_views[1], NULL); + pipe_sampler_view_reference(&c->layers[layer].sampler_views[2], NULL); + c->layers[layer].src_rect = src_rect ? *src_rect : default_rect(&c->layers[layer]); + c->layers[layer].dst_rect = dst_rect ? *dst_rect : default_rect(&c->layers[layer]); +} + +static void +vl_compositor_render(struct pipe_video_compositor *compositor, + enum pipe_mpeg12_picture_type picture_type, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence) +{ + struct vl_compositor *c = (struct vl_compositor *)compositor; + struct vertex2f dst_inv_size; + void *samplers[3]; + + assert(compositor); + assert(dst_surface); + assert(dst_area); + + c->fb_state.width = dst_surface->width; + c->fb_state.height = dst_surface->height; + c->fb_state.cbufs[0] = dst_surface; + + c->viewport.scale[0] = dst_surface->width; + c->viewport.scale[1] = dst_surface->height; + + dst_inv_size.x = 1.0f / dst_surface->width; + dst_inv_size.y = 1.0f / dst_surface->height; + + samplers[0] = samplers[1] = samplers[2] = c->sampler; + + gen_vertex_data(c, dst_area, &dst_inv_size); + + c->pipe->set_framebuffer_state(c->pipe, &c->fb_state); + c->pipe->set_viewport_state(c->pipe, &c->viewport); + c->pipe->bind_fragment_sampler_states(c->pipe, 3, &samplers[0]); + c->pipe->bind_vs_state(c->pipe, c->vs); + c->pipe->set_vertex_buffers(c->pipe, 1, &c->vertex_buf); + c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state); + c->pipe->set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, c->csc_matrix); + c->pipe->bind_blend_state(c->pipe, c->blend); + + draw_layers(c); + + c->pipe->flush(c->pipe, fence); +} + +struct pipe_video_compositor * +vl_compositor_init(struct pipe_video_context *vpipe, struct pipe_context *pipe) +{ + csc_matrix csc_matrix; + struct vl_compositor *compositor; + + compositor = CALLOC_STRUCT(vl_compositor); + + compositor->base.context = vpipe; + compositor->base.destroy = vl_compositor_destroy; + compositor->base.set_csc_matrix = vl_compositor_set_csc_matrix; + compositor->base.clear_layers = vl_compositor_clear_layers; + compositor->base.set_buffer_layer = vl_compositor_set_buffer_layer; + compositor->base.set_palette_layer = vl_compositor_set_palette_layer; + compositor->base.set_rgba_layer = vl_compositor_set_rgba_layer; + compositor->base.render_picture = vl_compositor_render; + + compositor->pipe = pipe; + + if (!init_pipe_state(compositor)) + return false; + + if (!init_shaders(compositor)) { + cleanup_pipe_state(compositor); + return false; + } + if (!init_buffers(compositor)) { + cleanup_shaders(compositor); + cleanup_pipe_state(compositor); + return false; + } + + vl_compositor_clear_layers(&compositor->base); + + vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, csc_matrix); + vl_compositor_set_csc_matrix(&compositor->base, csc_matrix); + + return &compositor->base; } diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h index e10a663f860..0e4badb65d2 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.h +++ b/src/gallium/auxiliary/vl/vl_compositor.h @@ -28,63 +28,46 @@ #ifndef vl_compositor_h #define vl_compositor_h -#include #include +#include #include -#include "vl_types.h" -#include "vl_ycbcr_buffer.h" struct pipe_context; -struct keymap; #define VL_COMPOSITOR_MAX_LAYERS 16 +struct vl_compositor_layer +{ + void *fs; + struct pipe_sampler_view *sampler_views[3]; + struct pipe_video_rect src_rect; + struct pipe_video_rect dst_rect; +}; + struct vl_compositor { + struct pipe_video_compositor base; struct pipe_context *pipe; struct pipe_framebuffer_state fb_state; - struct vertex2f fb_inv_size; - void *sampler; - void *blend; - struct pipe_sampler_view *sampler_view; - void *vertex_shader; - struct - { - void *ycbcr_2_rgb; - void *rgb_2_rgb; - void *palette_2_rgb; - } fragment_shader; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buf; - void *vertex_elems_state; - struct pipe_resource *fs_const_buf; + struct pipe_resource *csc_matrix; - struct pipe_sampler_view *layers[VL_COMPOSITOR_MAX_LAYERS]; - struct pipe_sampler_view *palettes[VL_COMPOSITOR_MAX_LAYERS]; - struct pipe_video_rect layer_src_rects[VL_COMPOSITOR_MAX_LAYERS]; - struct pipe_video_rect layer_dst_rects[VL_COMPOSITOR_MAX_LAYERS]; - unsigned dirty_layers; -}; - -bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe); - -void vl_compositor_cleanup(struct vl_compositor *compositor); + void *sampler; + void *blend; + void *vertex_elems_state; -void vl_compositor_set_layers(struct vl_compositor *compositor, - struct pipe_sampler_view *layers[], - struct pipe_sampler_view *palettes[], - struct pipe_video_rect *src_rects[], - struct pipe_video_rect *dst_rects[], - unsigned num_layers); + void *vs; + void *fs_video_buffer; + void *fs_palette; + void *fs_rgba; -void vl_compositor_render(struct vl_compositor *compositor, - struct vl_ycbcr_sampler_views *src_sampler, - struct pipe_video_rect *src_area, - struct pipe_surface *dst_surface, - struct pipe_video_rect *dst_area, - struct pipe_fence_handle **fence); + unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS; + struct vl_compositor_layer layers[VL_COMPOSITOR_MAX_LAYERS]; +}; -void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat); +struct pipe_video_compositor *vl_compositor_init(struct pipe_video_context *vpipe, + struct pipe_context *pipe); #endif /* vl_compositor_h */ diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_context.c b/src/gallium/auxiliary/vl/vl_mpeg12_context.c index be598a8b55f..d8605398d49 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_context.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_context.c @@ -221,6 +221,24 @@ vl_mpeg12_buffer_flush(struct pipe_video_buffer *buffer, sv_refs, ne_start, ne_num, e_start, e_num, fence); } +static void +vl_mpeg12_buffer_get_sampler_views(struct pipe_video_buffer *buffer, + struct pipe_sampler_view *sampler_views[3]) +{ + struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; + struct vl_ycbcr_sampler_views *samplers; + + assert(buf); + + samplers = vl_ycbcr_get_sampler_views(&buf->render_result); + + assert(samplers); + + pipe_sampler_view_reference(&sampler_views[0], samplers->y); + pipe_sampler_view_reference(&sampler_views[1], samplers->cb); + pipe_sampler_view_reference(&sampler_views[2], samplers->cr); +} + static void vl_mpeg12_destroy(struct pipe_video_context *vpipe) { @@ -236,7 +254,6 @@ vl_mpeg12_destroy(struct pipe_video_context *vpipe) ctx->pipe->delete_rasterizer_state(ctx->pipe, ctx->rast); ctx->pipe->delete_depth_stencil_alpha_state(ctx->pipe, ctx->dsa); - vl_compositor_cleanup(&ctx->compositor); vl_mpeg12_mc_renderer_cleanup(&ctx->mc); vl_idct_cleanup(&ctx->idct_y); vl_idct_cleanup(&ctx->idct_c); @@ -308,6 +325,7 @@ vl_mpeg12_create_buffer(struct pipe_video_context *vpipe) buffer->base.add_macroblocks = vl_mpeg12_buffer_add_macroblocks; buffer->base.unmap = vl_mpeg12_buffer_unmap; buffer->base.flush = vl_mpeg12_buffer_flush; + buffer->base.get_sampler_views = vl_mpeg12_buffer_get_sampler_views; buffer->vertex_bufs.individual.quad.stride = ctx->quads.stride; buffer->vertex_bufs.individual.quad.buffer_offset = ctx->quads.buffer_offset; @@ -494,56 +512,14 @@ error_map: ctx->pipe->transfer_destroy(ctx->pipe, transfer); } -static void -vl_mpeg12_render_picture(struct pipe_video_context *vpipe, - struct pipe_video_buffer *src_surface, - struct pipe_video_rect *src_area, - enum pipe_mpeg12_picture_type picture_type, - struct pipe_surface *dst_surface, - struct pipe_video_rect *dst_area, - struct pipe_fence_handle **fence) +static struct pipe_video_compositor * +vl_mpeg12_create_compositor(struct pipe_video_context *vpipe) { struct vl_mpeg12_context *ctx = (struct vl_mpeg12_context*)vpipe; - struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)src_surface; - struct vl_ycbcr_sampler_views *sampler_views; assert(vpipe); - assert(src_surface); - assert(src_area); - assert(dst_surface); - assert(dst_area); - - sampler_views = vl_ycbcr_get_sampler_views(&buf->render_result); - vl_compositor_render(&ctx->compositor, sampler_views, src_area, - dst_surface, dst_area, fence); -} - -static void -vl_mpeg12_set_picture_layers(struct pipe_video_context *vpipe, - struct pipe_sampler_view *layers[], - struct pipe_sampler_view *palettes[], - struct pipe_video_rect *src_rects[], - struct pipe_video_rect *dst_rects[], - unsigned num_layers) -{ - struct vl_mpeg12_context *ctx = (struct vl_mpeg12_context*)vpipe; - - assert(vpipe); - assert((layers && src_rects && dst_rects) || - (!layers && !src_rects && !dst_rects)); - - vl_compositor_set_layers(&ctx->compositor, layers, palettes, src_rects, dst_rects, num_layers); -} - -static void -vl_mpeg12_set_csc_matrix(struct pipe_video_context *vpipe, const float *mat) -{ - struct vl_mpeg12_context *ctx = (struct vl_mpeg12_context*)vpipe; - - assert(vpipe); - - vl_compositor_set_csc_matrix(&ctx->compositor, mat); + return vl_compositor_init(vpipe, ctx->pipe); } static bool @@ -707,11 +683,9 @@ vl_create_mpeg12_context(struct pipe_context *pipe, ctx->base.create_surface = vl_mpeg12_create_surface; ctx->base.create_sampler_view = vl_mpeg12_create_sampler_view; ctx->base.create_buffer = vl_mpeg12_create_buffer; - ctx->base.render_picture = vl_mpeg12_render_picture; ctx->base.clear_sampler = vl_mpeg12_clear_sampler; ctx->base.upload_sampler = vl_mpeg12_upload_sampler; - ctx->base.set_picture_layers = vl_mpeg12_set_picture_layers; - ctx->base.set_csc_matrix = vl_mpeg12_set_csc_matrix; + ctx->base.create_compositor = vl_mpeg12_create_compositor; ctx->pipe = pipe; ctx->pot_buffers = pot_buffers; @@ -731,26 +705,20 @@ vl_create_mpeg12_context(struct pipe_context *pipe, if (!vl_mpeg12_mc_renderer_init(&ctx->mc, ctx->pipe, ctx->buffer_width, ctx->buffer_height)) goto error_mc; - if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) - goto error_compositor; - if (!init_pipe_state(ctx)) goto error_pipe_state; return &ctx->base; error_pipe_state: - vl_compositor_cleanup(&ctx->compositor); - -error_compositor: - vl_mpeg12_mc_renderer_cleanup(&ctx->mc); + vl_mpeg12_mc_renderer_cleanup(&ctx->mc); error_mc: - vl_idct_cleanup(&ctx->idct_y); - vl_idct_cleanup(&ctx->idct_c); + vl_idct_cleanup(&ctx->idct_y); + vl_idct_cleanup(&ctx->idct_c); error_idct: - ctx->pipe->destroy(ctx->pipe); - FREE(ctx); - return NULL; + ctx->pipe->destroy(ctx->pipe); + FREE(ctx); + return NULL; } diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_context.h b/src/gallium/auxiliary/vl/vl_mpeg12_context.h index 3cc052941b2..a90110bf61b 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_context.h +++ b/src/gallium/auxiliary/vl/vl_mpeg12_context.h @@ -52,7 +52,6 @@ struct vl_mpeg12_context struct vl_idct idct_y, idct_c; struct vl_mpeg12_mc_renderer mc; - struct vl_compositor compositor; void *rast; void *dsa; diff --git a/src/gallium/include/pipe/p_video_context.h b/src/gallium/include/pipe/p_video_context.h index 7786f0a6f6f..dec524d5290 100644 --- a/src/gallium/include/pipe/p_video_context.h +++ b/src/gallium/include/pipe/p_video_context.h @@ -109,11 +109,17 @@ struct pipe_video_context struct pipe_sampler_view *dst, const struct pipe_box *dst_box, const float *rgba); + /** * Creates a buffer as decoding target */ struct pipe_video_buffer *(*create_buffer)(struct pipe_video_context *vpipe); + /** + * Creates a video compositor + */ + struct pipe_video_compositor *(*create_compositor)(struct pipe_video_context *vpipe); + /** * Picture decoding and displaying */ @@ -124,38 +130,6 @@ struct pipe_video_context struct pipe_buffer **bitstream_buf); #endif - /** - * render a video buffer to the frontbuffer - */ - void (*render_picture)(struct pipe_video_context *vpipe, - struct pipe_video_buffer *src_surface, - struct pipe_video_rect *src_area, - enum pipe_mpeg12_picture_type picture_type, - struct pipe_surface *dst_surface, - struct pipe_video_rect *dst_area, - struct pipe_fence_handle **fence); - - /*@}*/ - - /** - * Parameter-like states (or properties) - */ - /*@{*/ - - /** - * set overlay samplers - */ - void (*set_picture_layers)(struct pipe_video_context *vpipe, - struct pipe_sampler_view *layers[], - struct pipe_sampler_view *palettes[], - struct pipe_video_rect *src_rects[], - struct pipe_video_rect *dst_rects[], - unsigned num_layers); - - void (*set_csc_matrix)(struct pipe_video_context *vpipe, const float *mat); - - /* TODO: Interface for scaling modes, post-processing, etc. */ - /*@}*/ }; struct pipe_video_buffer @@ -191,6 +165,74 @@ struct pipe_video_buffer struct pipe_video_buffer *ref_frames[2], struct pipe_fence_handle **fence); + + void (*get_sampler_views)(struct pipe_video_buffer *buffer, + struct pipe_sampler_view *sampler_views[3]); +}; + +struct pipe_video_compositor +{ + struct pipe_video_context* context; + + /** + * destroy this compositor + */ + void (*destroy)(struct pipe_video_compositor *compositor); + + /** + * set yuv -> rgba conversion matrix + */ + void (*set_csc_matrix)(struct pipe_video_compositor *compositor, const float mat[16]); + + /** + * set overlay samplers + */ + /*@{*/ + + /** + * reset all currently set layers + */ + void (*clear_layers)(struct pipe_video_compositor *compositor); + + /** + * set a video buffer as a layer to render + */ + void (*set_buffer_layer)(struct pipe_video_compositor *compositor, + unsigned layer, + struct pipe_video_buffer *buffer, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect); + + /** + * set a paletted sampler as a layer to render + */ + void (*set_palette_layer)(struct pipe_video_compositor *compositor, + unsigned layer, + struct pipe_sampler_view *indexes, + struct pipe_sampler_view *palette, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect); + + /** + * set a rgba sampler as a layer to render + */ + void (*set_rgba_layer)(struct pipe_video_compositor *compositor, + unsigned layer, + struct pipe_sampler_view *rgba, + struct pipe_video_rect *src_rect, + struct pipe_video_rect *dst_rect); + + /*@}*/ + + /** + * render the layers to the frontbuffer + */ + void (*render_picture)(struct pipe_video_compositor *compositor, + enum pipe_mpeg12_picture_type picture_type, + struct pipe_surface *dst_surface, + struct pipe_video_rect *dst_area, + struct pipe_fence_handle **fence); + }; #ifdef __cplusplus diff --git a/src/gallium/state_trackers/xorg/xvmc/context.c b/src/gallium/state_trackers/xorg/xvmc/context.c index bcfd085de39..bdcba72d7cf 100644 --- a/src/gallium/state_trackers/xorg/xvmc/context.c +++ b/src/gallium/state_trackers/xorg/xvmc/context.c @@ -241,6 +241,15 @@ Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, return BadAlloc; } + context_priv->compositor = vctx->vpipe->create_compositor(vctx->vpipe); + if (!context_priv->compositor) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n"); + vl_video_destroy(vctx); + vl_screen_destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + /* TODO: Define some Xv attribs to allow users to specify color standard, procamp */ vl_csc_get_matrix ( @@ -248,7 +257,7 @@ Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601, NULL, true, csc ); - vctx->vpipe->set_csc_matrix(vctx->vpipe, csc); + context_priv->compositor->set_csc_matrix(context_priv->compositor, csc); context_priv->vctx = vctx; context_priv->subpicture_max_width = subpic_max_w; @@ -286,6 +295,7 @@ Status XvMCDestroyContext(Display *dpy, XvMCContext *context) context_priv = context->privData; vctx = context_priv->vctx; vscreen = vctx->vscreen; + context_priv->compositor->destroy(context_priv->compositor); vl_video_destroy(vctx); vl_screen_destroy(vscreen); FREE(context_priv); diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 23f97b3dac5..679b5cf6651 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -343,6 +343,8 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, static int dump_window = -1; struct pipe_video_context *vpipe; + struct pipe_video_compositor *compositor; + XvMCSurfacePrivate *surface_priv; XvMCContextPrivate *context_priv; XvMCSubpicturePrivate *subpicture_priv; @@ -383,27 +385,30 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; vpipe = context_priv->vctx->vpipe; + compositor = context_priv->compositor; + + unmap_and_flush_surface(surface_priv); + + compositor->clear_layers(compositor); + compositor->set_buffer_layer(compositor, 0, surface_priv->pipe_buffer, &src_rect, NULL); if (subpicture_priv) { struct pipe_video_rect src_rect = {surface_priv->subx, surface_priv->suby, surface_priv->subw, surface_priv->subh}; struct pipe_video_rect dst_rect = {surface_priv->surfx, surface_priv->surfy, surface_priv->surfw, surface_priv->surfh}; - struct pipe_video_rect *src_rects[1] = {&src_rect}; - struct pipe_video_rect *dst_rects[1] = {&dst_rect}; XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); assert(subpicture_priv->surface == surface); - vpipe->set_picture_layers(vpipe, &subpicture_priv->sampler, &subpicture_priv->palette, src_rects, dst_rects, 1); + if (subpicture_priv->palette) + compositor->set_palette_layer(compositor, 1, subpicture_priv->sampler, subpicture_priv->palette, &src_rect, &dst_rect); + else + compositor->set_rgba_layer(compositor, 1, subpicture_priv->sampler, &src_rect, &dst_rect); surface_priv->subpicture = NULL; subpicture_priv->surface = NULL; } - else - vpipe->set_picture_layers(vpipe, NULL, NULL, NULL, NULL, 0); - unmap_and_flush_surface(surface_priv); - vpipe->render_picture(vpipe, surface_priv->pipe_buffer, &src_rect, PictureToPipe(flags), - drawable_surface, &dst_rect, &surface_priv->disp_fence); + compositor->render_picture(compositor, PictureToPipe(flags), drawable_surface, &dst_rect, &surface_priv->disp_fence); XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h index 330c8c2cf9d..29518b36dbf 100644 --- a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h +++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h @@ -42,6 +42,8 @@ struct pipe_fence_handle; typedef struct { struct vl_context *vctx; + struct pipe_video_compositor *compositor; + unsigned short subpicture_max_width; unsigned short subpicture_max_height; } XvMCContextPrivate; -- 2.30.2