From 884cb79edfefb1133229a002f41b4d370d717a7e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20K=C3=B6nig?= Date: Thu, 24 Mar 2011 20:33:32 +0100 Subject: [PATCH] [g3dvl] make mapping and flushing of buffers a public interface --- src/gallium/auxiliary/vl/vl_mpeg12_context.c | 151 ++++++++++----------- src/gallium/auxiliary/vl/vl_mpeg12_context.h | 1 - src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c | 62 ++------- src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h | 16 +-- src/gallium/include/pipe/p_video_context.h | 12 +- src/gallium/state_trackers/xorg/xvmc/surface.c | 66 +++++++-- .../state_trackers/xorg/xvmc/xvmc_private.h | 5 + 7 files changed, 156 insertions(+), 157 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_context.c b/src/gallium/auxiliary/vl/vl_mpeg12_context.c index 73e2a95..4c0188c 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_context.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_context.c @@ -45,63 +45,6 @@ static const unsigned const_empty_block_mask_420[3][2][2] = { }; static void -map_buffer(struct vl_mpeg12_buffer *buf) -{ - struct vl_mpeg12_context *ctx; - assert(buf); - - ctx = (struct vl_mpeg12_context *)buf->base.context; - assert(ctx); - - if (!buf->mapped) { - vl_vb_map(&buf->vertex_stream, ctx->pipe); - vl_idct_map_buffers(&ctx->idct_y, &buf->idct_y); - vl_idct_map_buffers(&ctx->idct_cr, &buf->idct_cr); - vl_idct_map_buffers(&ctx->idct_cb, &buf->idct_cb); - buf->mapped = 1; - } -} - -static void -unmap_buffer(struct vl_mpeg12_buffer *buf) -{ - struct vl_mpeg12_context *ctx; - assert(buf); - - ctx = (struct vl_mpeg12_context *)buf->base.context; - assert(ctx); - - if (buf->mapped) { - vl_vb_unmap(&buf->vertex_stream, ctx->pipe); - vl_idct_unmap_buffers(&ctx->idct_y, &buf->idct_y); - vl_idct_unmap_buffers(&ctx->idct_cr, &buf->idct_cr); - vl_idct_unmap_buffers(&ctx->idct_cb, &buf->idct_cb); - buf->mapped = 0; - } -} - -static void -flush_buffer(struct vl_mpeg12_buffer *buf) -{ - unsigned ne_start, ne_num, e_start, e_num; - struct vl_mpeg12_context *ctx; - assert(buf); - - ctx = (struct vl_mpeg12_context *)buf->base.context; - assert(ctx); - - vl_vb_restart(&buf->vertex_stream, &ne_start, &ne_num, &e_start, &e_num); - - ctx->pipe->set_vertex_buffers(ctx->pipe, 2, buf->vertex_bufs.all); - ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->vertex_elems_state); - vl_idct_flush(&ctx->idct_y, &buf->idct_y, ne_num); - vl_idct_flush(&ctx->idct_cr, &buf->idct_cr, ne_num); - vl_idct_flush(&ctx->idct_cb, &buf->idct_cb, ne_num); - vl_mpeg12_mc_renderer_flush(&ctx->mc_renderer, &buf->mc, - ne_start, ne_num, e_start, e_num); -} - -static void upload_buffer(struct vl_mpeg12_context *ctx, struct vl_mpeg12_buffer *buffer, struct pipe_mpeg12_macroblock *mb) @@ -149,24 +92,35 @@ vl_mpeg12_buffer_destroy(struct pipe_video_buffer *buffer) vl_idct_cleanup_buffer(&ctx->idct_y, &buf->idct_y); vl_idct_cleanup_buffer(&ctx->idct_cb, &buf->idct_cb); vl_idct_cleanup_buffer(&ctx->idct_cr, &buf->idct_cr); - vl_mpeg12_mc_cleanup_buffer(&ctx->mc_renderer, &buf->mc); + vl_mpeg12_mc_cleanup_buffer(&buf->mc); pipe_surface_reference(&buf->surface, NULL); FREE(buf); } static void +vl_mpeg12_buffer_map(struct pipe_video_buffer *buffer) +{ + struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; + struct vl_mpeg12_context *ctx; + assert(buf); + + ctx = (struct vl_mpeg12_context *)buf->base.context; + assert(ctx); + + vl_vb_map(&buf->vertex_stream, ctx->pipe); + vl_idct_map_buffers(&ctx->idct_y, &buf->idct_y); + vl_idct_map_buffers(&ctx->idct_cr, &buf->idct_cr); + vl_idct_map_buffers(&ctx->idct_cb, &buf->idct_cb); +} + +static void vl_mpeg12_buffer_add_macroblocks(struct pipe_video_buffer *buffer, - struct pipe_video_buffer *past, - struct pipe_video_buffer *future, unsigned num_macroblocks, - struct pipe_macroblock *macroblocks, - struct pipe_fence_handle **fence) + struct pipe_macroblock *macroblocks) { struct pipe_mpeg12_macroblock *mpeg12_macroblocks = (struct pipe_mpeg12_macroblock*)macroblocks; struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; - struct vl_mpeg12_buffer *buf_past = (struct vl_mpeg12_buffer*)past; - struct vl_mpeg12_buffer *buf_future = (struct vl_mpeg12_buffer*)future; struct vl_mpeg12_context *ctx; unsigned i; @@ -179,28 +133,61 @@ vl_mpeg12_buffer_add_macroblocks(struct pipe_video_buffer *buffer, assert(macroblocks); assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12); - map_buffer(buf); - for ( i = 0; i < num_macroblocks; ++i ) { vl_vb_add_block(&buf->vertex_stream, &mpeg12_macroblocks[i], ctx->empty_block_mask); upload_buffer(ctx, buf, &mpeg12_macroblocks[i]); } +} - // TODO this doesn't belong here - if (buf_past) { - unmap_buffer(buf_past); - flush_buffer(buf_past); - } +static void +vl_mpeg12_buffer_unmap(struct pipe_video_buffer *buffer) +{ + struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer; + struct vl_mpeg12_context *ctx; + assert(buf); - if (buf_future) { - unmap_buffer(buf_future); - flush_buffer(buf_future); - } + ctx = (struct vl_mpeg12_context *)buf->base.context; + assert(ctx); - vl_mpeg12_mc_set_surfaces(&ctx->mc_renderer, &buf->mc, buf->surface, - buf_past ? buf_past->surface : NULL, - buf_future ? buf_future->surface : NULL, - fence); + vl_vb_unmap(&buf->vertex_stream, ctx->pipe); + vl_idct_unmap_buffers(&ctx->idct_y, &buf->idct_y); + vl_idct_unmap_buffers(&ctx->idct_cr, &buf->idct_cr); + vl_idct_unmap_buffers(&ctx->idct_cb, &buf->idct_cb); +} + +static void +vl_mpeg12_buffer_flush(struct pipe_video_buffer *buffer, + struct pipe_video_buffer *refs[2], + struct pipe_fence_handle **fence) +{ + struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer *)buffer; + struct vl_mpeg12_buffer *past = (struct vl_mpeg12_buffer *)refs[0]; + struct vl_mpeg12_buffer *future = (struct vl_mpeg12_buffer *)refs[1]; + + struct pipe_surface *surf_refs[2]; + unsigned ne_start, ne_num, e_start, e_num; + struct vl_mpeg12_context *ctx; + + assert(buf); + + ctx = (struct vl_mpeg12_context *)buf->base.context; + assert(ctx); + + vl_vb_restart(&buf->vertex_stream, &ne_start, &ne_num, &e_start, &e_num); + + ctx->pipe->set_vertex_buffers(ctx->pipe, 2, buf->vertex_bufs.all); + ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->vertex_elems_state); + vl_idct_flush(&ctx->idct_y, &buf->idct_y, ne_num); + vl_idct_flush(&ctx->idct_cr, &buf->idct_cr, ne_num); + vl_idct_flush(&ctx->idct_cb, &buf->idct_cb, ne_num); + + surf_refs[0] = past ? past->surface : NULL; + surf_refs[1] = future ? future->surface : NULL; + + vl_mpeg12_mc_renderer_flush(&ctx->mc_renderer, &buf->mc, + buf->surface, surf_refs, + ne_start, ne_num, e_start, e_num, + fence); } static void @@ -280,7 +267,10 @@ vl_mpeg12_create_buffer(struct pipe_video_context *vpipe) buffer->base.context = vpipe; buffer->base.destroy = vl_mpeg12_buffer_destroy; + buffer->base.map = vl_mpeg12_buffer_map; buffer->base.add_macroblocks = vl_mpeg12_buffer_add_macroblocks; + buffer->base.unmap = vl_mpeg12_buffer_unmap; + buffer->base.flush = vl_mpeg12_buffer_flush; memset(&res_template, 0, sizeof(res_template)); res_template.target = PIPE_TEXTURE_2D; @@ -508,9 +498,6 @@ vl_mpeg12_render_picture(struct pipe_video_context *vpipe, assert(dst_surface); assert(dst_area); - unmap_buffer(buf); - flush_buffer(buf); - vl_compositor_render(&ctx->compositor, buf->surface, picture_type, src_area, dst_surface, dst_area, fence); diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_context.h b/src/gallium/auxiliary/vl/vl_mpeg12_context.h index b2097c2..7269fa9 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_context.h +++ b/src/gallium/auxiliary/vl/vl_mpeg12_context.h @@ -63,7 +63,6 @@ struct vl_mpeg12_buffer { struct pipe_video_buffer base; struct pipe_surface *surface; - bool mapped; struct vl_vertex_buffer vertex_stream; diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c index 6cd811b..2f2c787 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c @@ -282,7 +282,7 @@ fetch_ref(struct ureg_program *shader, struct ureg_dst field) struct ureg_src info; struct ureg_src tc[4], sampler[2]; struct ureg_dst ref[2], result; - unsigned i, intra_label, bi_label, label; + unsigned i, intra_label; info = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_INFO, TGSI_INTERPOLATE_CONSTANT); @@ -549,10 +549,6 @@ vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg1 assert(renderer && buffer); - buffer->surface = NULL; - buffer->past = NULL; - buffer->future = NULL; - pipe_resource_reference(&buffer->textures.individual.y, y); pipe_resource_reference(&buffer->textures.individual.cr, cr); pipe_resource_reference(&buffer->textures.individual.cb, cb); @@ -573,70 +569,45 @@ vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg1 } void -vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer) +vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_buffer *buffer) { unsigned i; - assert(renderer && buffer); + assert(buffer); for (i = 0; i < 3; ++i) { pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL); pipe_resource_reference(&buffer->textures.all[i], NULL); } - - pipe_surface_reference(&buffer->surface, NULL); - pipe_surface_reference(&buffer->past, NULL); - pipe_surface_reference(&buffer->future, NULL); -} - -void -vl_mpeg12_mc_set_surfaces(struct vl_mpeg12_mc_renderer *renderer, - struct vl_mpeg12_mc_buffer *buffer, - struct pipe_surface *surface, - struct pipe_surface *past, - struct pipe_surface *future, - struct pipe_fence_handle **fence) -{ - assert(renderer && buffer); - assert(surface); - - if (surface != buffer->surface) { - pipe_surface_reference(&buffer->surface, surface); - pipe_surface_reference(&buffer->past, past); - pipe_surface_reference(&buffer->future, future); - buffer->fence = fence; - } else { - /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ - assert(buffer->past == past); - assert(buffer->future == future); - } } void vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer, + struct pipe_surface *surface, struct pipe_surface *ref[2], unsigned not_empty_start_instance, unsigned not_empty_num_instances, - unsigned empty_start_instance, unsigned empty_num_instances) + unsigned empty_start_instance, unsigned empty_num_instances, + struct pipe_fence_handle **fence) { assert(renderer && buffer); if (not_empty_num_instances == 0 && empty_num_instances == 0) return; - renderer->fb_state.cbufs[0] = buffer->surface; + renderer->fb_state.cbufs[0] = surface; renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state); renderer->pipe->set_framebuffer_state(renderer->pipe, &renderer->fb_state); renderer->pipe->set_viewport_state(renderer->pipe, &renderer->viewport); - if (buffer->past) { - buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, buffer->past); + if (ref[0]) { + buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, ref[0]); } else { - buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, buffer->surface); + buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, surface); } - if (buffer->future) { - buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, buffer->future); + if (ref[1]) { + buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, ref[1]); } else { - buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, buffer->surface); + buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, surface); } renderer->pipe->set_fragment_sampler_views(renderer->pipe, 5, buffer->sampler_views.all); @@ -653,10 +624,5 @@ vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mp util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, empty_start_instance, empty_num_instances); - renderer->pipe->flush(renderer->pipe, buffer->fence); - - /* Next time we get this surface it may have new ref frames */ - pipe_surface_reference(&buffer->surface, NULL); - pipe_surface_reference(&buffer->past, NULL); - pipe_surface_reference(&buffer->future, NULL); + renderer->pipe->flush(renderer->pipe, fence); } diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h index b761961..fa81c77 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h @@ -73,9 +73,6 @@ struct vl_mpeg12_mc_buffer struct pipe_resource *all[3]; struct { struct pipe_resource *y, *cb, *cr; } individual; } textures; - - struct pipe_surface *surface, *past, *future; - struct pipe_fence_handle **fence; }; bool vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer, @@ -89,17 +86,12 @@ void vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer); bool vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer, struct pipe_resource *y, struct pipe_resource *cr, struct pipe_resource *cb); -void vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer); - -void vl_mpeg12_mc_set_surfaces(struct vl_mpeg12_mc_renderer *renderer, - struct vl_mpeg12_mc_buffer *buffer, - struct pipe_surface *surface, - struct pipe_surface *past, - struct pipe_surface *future, - struct pipe_fence_handle **fence); +void vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_buffer *buffer); void vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer, + struct pipe_surface *surface, struct pipe_surface *ref[2], unsigned not_empty_start_instance, unsigned not_empty_num_instances, - unsigned empty_start_instance, unsigned empty_num_instances); + unsigned empty_start_instance, unsigned empty_num_instances, + struct pipe_fence_handle **fence); #endif /* vl_mpeg12_mc_renderer_h */ diff --git a/src/gallium/include/pipe/p_video_context.h b/src/gallium/include/pipe/p_video_context.h index 08e3c7e..aa903dd 100644 --- a/src/gallium/include/pipe/p_video_context.h +++ b/src/gallium/include/pipe/p_video_context.h @@ -176,13 +176,17 @@ struct pipe_video_buffer void (*destroy)(struct pipe_video_buffer *buffer); + void (*map)(struct pipe_video_buffer *buffer); + void (*add_macroblocks)(struct pipe_video_buffer *buffer, - struct pipe_video_buffer *past, - struct pipe_video_buffer *future, unsigned num_macroblocks, - struct pipe_macroblock *macroblocks, - struct pipe_fence_handle **fence); + struct pipe_macroblock *macroblocks); + + void (*unmap)(struct pipe_video_buffer *buffer); + void (*flush)(struct pipe_video_buffer *buffer, + struct pipe_video_buffer *ref_frames[2], + struct pipe_fence_handle **fence); }; diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 4dedf00..bb60192 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -198,6 +198,37 @@ MacroBlocksToPipe(struct pipe_screen *screen, } } +static void +unmap_and_flush_surface(XvMCSurfacePrivate *surface) +{ + struct pipe_video_buffer *ref_frames[2]; + unsigned i; + + assert(surface); + + for ( i = 0; i < 3; ++i ) { + if (surface->ref_surfaces[i]) { + XvMCSurfacePrivate *ref = surface->ref_surfaces[i]->privData; + + assert(ref); + + unmap_and_flush_surface(ref); + surface->ref_surfaces[i] = NULL; + ref_frames[i] = ref->pipe_buffer; + } else { + ref_frames[i] = NULL; + } + } + + if (surface->mapped) { + surface->pipe_buffer->unmap(surface->pipe_buffer); + surface->pipe_buffer->flush(surface->pipe_buffer, + ref_frames, + &surface->flush_fence); + surface->mapped = 0; + } +} + PUBLIC Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) { @@ -221,8 +252,6 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac if (!surface_priv) return BadAlloc; - - surface_priv->pipe_buffer = vpipe->create_buffer(vpipe); surface_priv->context = context; @@ -248,9 +277,7 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur ) { struct pipe_video_context *vpipe; - struct pipe_video_buffer *t_vsfc; - struct pipe_video_buffer *p_vsfc; - struct pipe_video_buffer *f_vsfc; + struct pipe_video_buffer *t_buffer; XvMCContextPrivate *context_priv; XvMCSurfacePrivate *target_surface_priv; XvMCSurfacePrivate *past_surface_priv; @@ -297,15 +324,30 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur context_priv = context->privData; vpipe = context_priv->vctx->vpipe; - t_vsfc = target_surface_priv->pipe_buffer; - p_vsfc = past_surface ? past_surface_priv->pipe_buffer : NULL; - f_vsfc = future_surface ? future_surface_priv->pipe_buffer : NULL; + t_buffer = target_surface_priv->pipe_buffer; + + // enshure that all reference frames are flushed + // not really nessasary, but speeds ups rendering + if (past_surface) + unmap_and_flush_surface(past_surface->privData); + + if (future_surface) + unmap_and_flush_surface(future_surface->privData); MacroBlocksToPipe(vpipe->screen, picture_structure, macroblocks, blocks, first_macroblock, num_macroblocks, pipe_macroblocks); - t_vsfc->add_macroblocks(t_vsfc, p_vsfc, f_vsfc, num_macroblocks, - &pipe_macroblocks->base, &target_surface_priv->render_fence); + if (!target_surface_priv->mapped) { + t_buffer->map(t_buffer); + target_surface_priv->ref_surfaces[0] = past_surface; + target_surface_priv->ref_surfaces[1] = future_surface; + target_surface_priv->mapped = 1; + } else { + /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ + assert(target_surface_priv->ref_surfaces[0] == past_surface); + assert(target_surface_priv->ref_surfaces[1] == future_surface); + } + t_buffer->add_macroblocks(t_buffer, num_macroblocks, &pipe_macroblocks->base); XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); @@ -320,6 +362,9 @@ Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) if (!surface) return XvMCBadSurface; + // don't call flush here, because this is usually + // called once for every slice instead of every frame + return Success; } @@ -406,6 +451,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable, else vpipe->set_picture_layers(vpipe, 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); diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h index 01b82df..26be1f7 100644 --- a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h +++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h @@ -50,6 +50,11 @@ typedef struct typedef struct { struct pipe_video_buffer *pipe_buffer; + bool mapped; // are we still mapped to memory? + + XvMCSurface *ref_surfaces[2]; + + struct pipe_fence_handle *flush_fence; struct pipe_fence_handle *render_fence; struct pipe_fence_handle *disp_fence; -- 2.7.4