{ { 0x01, 0x01 }, { 0x01, 0x01 } }
};
-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,
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;
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
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;
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);
{
struct pipe_video_buffer base;
struct pipe_surface *surface;
- bool mapped;
struct vl_vertex_buffer vertex_stream;
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);
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);
}
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);
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);
}
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,
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 */
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);
};
}
}
+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)
{
if (!surface_priv)
return BadAlloc;
-
-
surface_priv->pipe_buffer = vpipe->create_buffer(vpipe);
surface_priv->context = context;
)
{
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;
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);
if (!surface)
return XvMCBadSurface;
+ // don't call flush here, because this is usually
+ // called once for every slice instead of every frame
+
return Success;
}
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);
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;