vl: Subpicture/compositing fixes.
authorYounes Manton <younes.m@gmail.com>
Sat, 6 Mar 2010 04:26:03 +0000 (23:26 -0500)
committerYounes Manton <younes.m@gmail.com>
Sat, 6 Mar 2010 04:26:03 +0000 (23:26 -0500)
src/gallium/auxiliary/vl/vl_compositor.c
src/gallium/drivers/softpipe/sp_video_context.c
src/gallium/include/pipe/p_video_context.h
src/gallium/state_trackers/xorg/xvmc/subpicture.c
src/gallium/state_trackers/xorg/xvmc/surface.c
src/gallium/state_trackers/xorg/xvmc/xvmc_private.h

index 44b3714..e6d787b 100644 (file)
@@ -349,7 +349,7 @@ static void gen_rect_verts(unsigned pos,
    assert(pos < VL_COMPOSITOR_MAX_LAYERS + 2);
    assert(src_rect);
    assert(src_inv_size);
-   assert((dst_rect && dst_inv_size) || (!dst_rect && !dst_inv_size));
+   assert((dst_rect && dst_inv_size) /*|| (!dst_rect && !dst_inv_size)*/);
    assert(vb);
 
    vb[pos * 6 + 0].x = dst_rect->x * dst_inv_size->x;
@@ -383,39 +383,52 @@ static void gen_rect_verts(unsigned pos,
    vb[pos * 6 + 5].w = (src_rect->y + src_rect->h) * src_inv_size->y;
 }
 
-static unsigned gen_verts(struct vl_compositor *c,
-                          struct pipe_video_rect *src_rect,
-                          struct vertex2f *src_inv_size,
-                          struct pipe_video_rect *dst_rect)
+static unsigned gen_data(struct vl_compositor *c,
+                         struct pipe_texture *src_surface,
+                         struct pipe_video_rect *src_rect,
+                         struct pipe_video_rect *dst_rect,
+                         struct pipe_texture **textures)
 {
    void *vb;
    unsigned num_rects = 0;
    unsigned i;
 
    assert(c);
+   assert(src_surface);
    assert(src_rect);
-   assert(src_inv_size);
    assert(dst_rect);
+   assert(textures);
 
    vb = pipe_buffer_map(c->pipe->screen, c->vertex_buf.buffer,
                         PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD);
 
+   if (!vb)
+      return 0;
+
    if (c->dirty_bg) {
       struct vertex2f bg_inv_size = {1.0f / c->bg->width0, 1.0f / c->bg->height0};
-      gen_rect_verts(num_rects++, &c->bg_src_rect, &bg_inv_size, NULL, NULL, vb);
+      gen_rect_verts(num_rects, &c->bg_src_rect, &bg_inv_size, NULL, NULL, vb);
+      textures[num_rects] = c->bg;
+      ++num_rects;
       c->dirty_bg = false;
    }
 
-   gen_rect_verts(num_rects++, src_rect, src_inv_size, dst_rect, &c->fb_inv_size, vb);
-
-   for (i = 0; c->dirty_layers > 0; i++)
    {
+      struct vertex2f src_inv_size = { 1.0f / src_surface->width0, 1.0f / src_surface->height0};
+      gen_rect_verts(num_rects, src_rect, &src_inv_size, dst_rect, &c->fb_inv_size, vb);
+      textures[num_rects] = src_surface;
+      ++num_rects;
+   }
+
+   for (i = 0; c->dirty_layers > 0; i++) {
       assert(i < VL_COMPOSITOR_MAX_LAYERS);
 
       if (c->dirty_layers & (1 << i)) {
          struct vertex2f layer_inv_size = {1.0f / c->layers[i]->width0, 1.0f / c->layers[i]->height0};
-         gen_rect_verts(num_rects++, &c->layer_src_rects[i], &layer_inv_size,
+         gen_rect_verts(num_rects, &c->layer_src_rects[i], &layer_inv_size,
                         &c->layer_dst_rects[i], &c->fb_inv_size, vb);
+         textures[num_rects] = c->layers[i];
+         ++num_rects;
          c->dirty_layers &= ~(1 << i);
       }
    }
@@ -425,6 +438,28 @@ static unsigned gen_verts(struct vl_compositor *c,
    return num_rects;
 }
 
+static void draw_layers(struct vl_compositor *c,
+                        struct pipe_texture *src_surface,
+                        struct pipe_video_rect *src_rect,
+                        struct pipe_video_rect *dst_rect)
+{
+   unsigned num_rects;
+   struct pipe_texture *textures[VL_COMPOSITOR_MAX_LAYERS + 2];
+   unsigned i;
+
+   assert(c);
+   assert(src_surface);
+   assert(src_rect);
+   assert(dst_rect);
+
+   num_rects = gen_data(c, src_surface, src_rect, dst_rect, textures);
+
+   for (i = 0; i < num_rects; ++i) {
+      c->pipe->set_fragment_sampler_textures(c->pipe, 1, &textures[i]);
+      c->pipe->draw_arrays(c->pipe, PIPE_PRIM_TRIANGLES, i * 6, 6);
+   }
+}
+
 void vl_compositor_render(struct vl_compositor          *compositor,
                           struct pipe_texture           *src_surface,
                           enum pipe_mpeg12_picture_type picture_type,
@@ -437,8 +472,6 @@ void vl_compositor_render(struct vl_compositor          *compositor,
                           struct pipe_video_rect        *dst_area,
                           struct pipe_fence_handle      **fence)
 {
-   unsigned num_rects;
-
    assert(compositor);
    assert(src_surface);
    assert(src_area);
@@ -459,7 +492,7 @@ void vl_compositor_render(struct vl_compositor          *compositor,
    (
       compositor->pipe->screen,
       dst_surface,
-      0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+      0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ_WRITE
    );
 
    compositor->viewport.scale[0] = compositor->fb_state.width;
@@ -474,22 +507,15 @@ void vl_compositor_render(struct vl_compositor          *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, 1, &compositor->sampler);
-   compositor->pipe->set_fragment_sampler_textures(compositor->pipe, 1, &src_surface);
    compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader);
    compositor->pipe->bind_fs_state(compositor->pipe, compositor->fragment_shader);
    compositor->pipe->set_vertex_buffers(compositor->pipe, 1, &compositor->vertex_buf);
    compositor->pipe->set_vertex_elements(compositor->pipe, 2, compositor->vertex_elems);
    compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, &compositor->fs_const_buf);
 
-   {
-      struct vertex2f src_inv_size = {1.0f / src_surface->width0, 1.0f / src_surface->height0};
-      num_rects = gen_verts(compositor, src_area, &src_inv_size, dst_area);
-   }
+   draw_layers(compositor, src_surface, src_area, dst_area);
 
    assert(!compositor->dirty_bg && !compositor->dirty_layers);
-   assert(num_rects > 0);
-
-   compositor->pipe->draw_arrays(compositor->pipe, PIPE_PRIM_TRIANGLES, 0, num_rects * 6);
    compositor->pipe->flush(compositor->pipe, PIPE_FLUSH_RENDER_CACHE, fence);
 
    pipe_surface_reference(&compositor->fb_state.cbufs[0], NULL);
@@ -501,7 +527,8 @@ void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float
 
    memcpy
    (
-      pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+      pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf.buffer,
+                      PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD),
       mat,
       sizeof(struct fragment_shader_consts)
    );
index f7231dc..f43b3d6 100644 (file)
@@ -39,7 +39,7 @@ sp_mpeg12_destroy(struct pipe_video_context *vpipe)
    struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
 
    assert(vpipe);
-       
+
    /* Asserted in softpipe_delete_fs_state() for some reason */
    ctx->pipe->bind_vs_state(ctx->pipe, NULL);
    ctx->pipe->bind_fs_state(ctx->pipe, NULL);
@@ -119,8 +119,6 @@ sp_mpeg12_surface_copy(struct pipe_video_context *vpipe,
 
 static void
 sp_mpeg12_render_picture(struct pipe_video_context     *vpipe,
-                         /*struct pipe_surface         *backround,
-                         struct pipe_video_rect        *backround_area,*/
                          struct pipe_video_surface     *src_surface,
                          enum pipe_mpeg12_picture_type picture_type,
                          /*unsigned                    num_past_surfaces,
@@ -130,25 +128,51 @@ sp_mpeg12_render_picture(struct pipe_video_context     *vpipe,
                          struct pipe_video_rect        *src_area,
                          struct pipe_surface           *dst_surface,
                          struct pipe_video_rect        *dst_area,
-                         /*unsigned                      num_layers,
-                         struct pipe_surface           *layers,
-                         struct pipe_video_rect        *layer_src_areas,
-                         struct pipe_video_rect        *layer_dst_areas*/
                          struct pipe_fence_handle      **fence)
 {
    struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
-       
+
    assert(vpipe);
    assert(src_surface);
    assert(src_area);
    assert(dst_surface);
    assert(dst_area);
-       
+
    vl_compositor_render(&ctx->compositor, softpipe_video_surface(src_surface)->tex,
                         picture_type, src_area, dst_surface->texture, dst_area, fence);
 }
 
 static void
+sp_mpeg12_set_picture_background(struct pipe_video_context *vpipe,
+                                  struct pipe_texture *bg,
+                                  struct pipe_video_rect *bg_src_rect)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert(bg);
+   assert(bg_src_rect);
+
+   vl_compositor_set_background(&ctx->compositor, bg, bg_src_rect);
+}
+
+static void
+sp_mpeg12_set_picture_layers(struct pipe_video_context *vpipe,
+                             struct pipe_texture *layers[],
+                             struct pipe_video_rect *src_rects[],
+                             struct pipe_video_rect *dst_rects[],
+                             unsigned num_layers)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+   assert((layers && src_rects && dst_rects) ||
+          (!layers && !src_rects && !dst_rects));
+
+   vl_compositor_set_layers(&ctx->compositor, layers, src_rects, dst_rects, num_layers);
+}
+
+static void
 sp_mpeg12_set_decode_target(struct pipe_video_context *vpipe,
                             struct pipe_video_surface *dt)
 {
@@ -179,7 +203,7 @@ init_pipe_state(struct sp_mpeg12_context *ctx)
    unsigned i;
 
    assert(ctx);
-       
+
    rast.flatshade = 1;
    rast.flatshade_first = 0;
    rast.light_twoside = 0;
@@ -244,7 +268,7 @@ init_pipe_state(struct sp_mpeg12_context *ctx)
    dsa.alpha.ref_value = 0;
    ctx->dsa = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &dsa);
    ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->dsa);
-       
+
    return true;
 }
 
@@ -276,6 +300,8 @@ sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
    ctx->base.render_picture = sp_mpeg12_render_picture;
    ctx->base.surface_fill = sp_mpeg12_surface_fill;
    ctx->base.surface_copy = sp_mpeg12_surface_copy;
+   ctx->base.set_picture_background = sp_mpeg12_set_picture_background;
+   ctx->base.set_picture_layers = sp_mpeg12_set_picture_layers;
    ctx->base.set_decode_target = sp_mpeg12_set_decode_target;
    ctx->base.set_csc_matrix = sp_mpeg12_set_csc_matrix;
 
@@ -288,14 +314,14 @@ sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
       FREE(ctx);
       return NULL;
    }
-       
+
    if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) {
       vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
       ctx->pipe->destroy(ctx->pipe);
       FREE(ctx);
       return NULL;
    }
-       
+
    if (!init_pipe_state(ctx)) {
       vl_compositor_cleanup(&ctx->compositor);
       vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
index 9ae595b..b3346b2 100644 (file)
@@ -109,6 +109,16 @@ struct pipe_video_context
     * Parameter-like states (or properties)
     */
    /*@{*/
+   void (*set_picture_background)(struct pipe_video_context *vpipe,
+                                  struct pipe_texture *bg,
+                                  struct pipe_video_rect *bg_src_rect);
+
+   void (*set_picture_layers)(struct pipe_video_context *vpipe,
+                              struct pipe_texture *layers[],
+                              struct pipe_video_rect *src_rects[],
+                              struct pipe_video_rect *dst_rects[],
+                              unsigned num_layers);
+
    void (*set_picture_desc)(struct pipe_video_context *vpipe,
                             const struct pipe_picture_desc *desc);
 
index d64d075..4f75c73 100644 (file)
@@ -42,7 +42,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
                             unsigned short width, unsigned short height, int xvimage_id)
 {
    XvMCContextPrivate *context_priv;
-   XvMCSubPicturePrivate *subpicture_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
    struct pipe_video_context *vpipe;
    struct pipe_texture template;
    struct pipe_texture *tex;
@@ -67,7 +67,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
    if (xvimage_id != FOURCC_RGB)
       return BadMatch;
 
-   subpicture_priv = CALLOC(1, sizeof(XvMCSubPicturePrivate));
+   subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate));
    if (!subpicture_priv)
       return BadAlloc;
 
@@ -84,12 +84,13 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
       template.height0 = util_next_power_of_two(height);
    }
    template.depth0 = 1;
-   template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET;
+   template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
 
    subpicture_priv->context = context;
    tex = vpipe->screen->texture_create(vpipe->screen, &template);
    subpicture_priv->sfc = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
-                                                         PIPE_BUFFER_USAGE_GPU_READ_WRITE);
+                                                         PIPE_BUFFER_USAGE_CPU_WRITE |
+                                                         PIPE_BUFFER_USAGE_GPU_READ);
    pipe_texture_reference(&tex, NULL);
    if (!subpicture_priv->sfc)
    {
@@ -120,8 +121,9 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
 Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
                            unsigned short width, unsigned short height, unsigned int color)
 {
-   XvMCSubPicturePrivate *subpicture_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
    XvMCContextPrivate *context_priv;
+
    assert(dpy);
 
    if (!subpicture)
@@ -141,6 +143,15 @@ Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage
                                short srcx, short srcy, unsigned short width, unsigned short height,
                                short dstx, short dsty)
 {
+   XvMCSubpicturePrivate *subpicture_priv;
+   XvMCContextPrivate *context_priv;
+   struct pipe_screen *screen;
+   struct pipe_transfer *xfer;
+   unsigned char *src, *dst;
+   unsigned x, y;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture);
+
    assert(dpy);
 
    if (!subpicture)
@@ -151,14 +162,56 @@ Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage
    if (subpicture->xvimage_id != image->id)
       return BadMatch;
 
+   /* No planar support for now */
+   if (image->num_planes != 1)
+      return BadMatch;
+
+   subpicture_priv = subpicture->privData;
+   context_priv = subpicture_priv->context->privData;
+   screen = context_priv->vctx->vpipe->screen;
+
    /* TODO: Assert rects are within bounds? Or clip? */
 
+   xfer = screen->get_tex_transfer(screen, subpicture_priv->sfc->texture, 0, 0, 0,
+                                   PIPE_TRANSFER_WRITE, dstx, dsty, width, height);
+   if (!xfer)
+      return BadAlloc;
+
+   src = image->data;
+   dst = screen->transfer_map(screen, xfer);
+   if (!dst) {
+      screen->tex_transfer_destroy(xfer);
+      return BadAlloc;
+   }
+
+   switch (image->id)
+   {
+      case FOURCC_RGB:
+         assert(subpicture_priv->sfc->format == PIPE_FORMAT_X8R8G8B8_UNORM);
+         for (y = 0; y < height; ++y) {
+            for (x = 0; x < width; ++x, src += 3, dst += 4) {
+               /* TODO: Confirm or fix */
+               dst[0] = src[0];
+               dst[1] = src[1];
+               dst[2] = src[2];
+            }
+         }
+         break;
+      default:
+         assert(false);
+   }
+
+   screen->transfer_unmap(screen, xfer);
+   screen->tex_transfer_destroy(xfer);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture);
+
    return Success;
 }
 
 Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
 {
-   XvMCSubPicturePrivate *subpicture_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
 
    XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture);
 
@@ -193,6 +246,11 @@ Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpic
                            short subx, short suby, unsigned short subw, unsigned short subh,
                            short surfx, short surfy, unsigned short surfw, unsigned short surfh)
 {
+   XvMCSurfacePrivate *surface_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface);
+
    assert(dpy);
 
    if (!target_surface)
@@ -204,7 +262,24 @@ Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpic
    if (target_surface->context_id != subpicture->context_id)
       return BadMatch;
 
+   /* TODO: Verify against subpicture independent scaling */
+
+   surface_priv = target_surface->privData;
+   subpicture_priv = subpicture->privData;
+
    /* TODO: Assert rects are within bounds? Or clip? */
+
+   surface_priv->subpicture = subpicture;
+   surface_priv->subx = subx;
+   surface_priv->suby = suby;
+   surface_priv->subw = subw;
+   surface_priv->subh = subh;
+   surface_priv->surfx = surfx;
+   surface_priv->surfy = surfy;
+   surface_priv->surfw = surfw;
+   surface_priv->surfh = surfh;
+   subpicture_priv->surface = target_surface;
+
    return Success;
 }
 
@@ -227,6 +302,7 @@ Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurfa
       return BadMatch;
 
    /* TODO: Assert rects are within bounds? Or clip? */
+
    return Success;
 }
 
index 79dae3f..4d6c524 100644 (file)
@@ -342,6 +342,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    struct pipe_video_context *vpipe;
    XvMCSurfacePrivate *surface_priv;
    XvMCContextPrivate *context_priv;
+   XvMCSubpicturePrivate *subpicture_priv;
    XvMCContext *context;
    struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
    struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
@@ -374,14 +375,34 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    surface_priv = surface->privData;
    context = surface_priv->context;
    context_priv = context->privData;
+   subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL;
    vpipe = context_priv->vctx->vpipe;
 
    if (!CreateOrResizeBackBuffer(context_priv->vctx, width, height, &context_priv->backbuffer))
       return BadAlloc;
 
+   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->sfc->texture, &src_rects, &dst_rects, 1);
+
+      surface_priv->subpicture = NULL;
+      subpicture_priv->surface = NULL;
+   }
+   else
+      vpipe->set_picture_layers(vpipe, NULL, NULL, NULL, 0);
+
    vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect,
                          context_priv->backbuffer, &dst_rect, surface_priv->disp_fence);
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface);
+
    vl_video_bind_drawable(context_priv->vctx, drawable);
 
    vpipe->screen->flush_frontbuffer
@@ -391,7 +412,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
       vpipe->priv
    );
 
-   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display.\n", surface);
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);
 
    return Success;
 }
index 96fe7a9..df2a0dc 100644 (file)
@@ -1,8 +1,8 @@
 /**************************************************************************
- * 
+ *
  * Copyright 2009 Younes Manton.
  * All Rights Reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * distribute, sub license, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the
  * next paragraph) shall be included in all copies or substantial portions
  * of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,7 +22,7 @@
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
+ *
  **************************************************************************/
 
 #ifndef xvmc_private_h
@@ -41,28 +41,39 @@ struct pipe_fence_handle;
 
 typedef struct
 {
-       struct vl_context *vctx;
-       struct pipe_surface *backbuffer;
+   struct vl_context *vctx;
+   struct pipe_surface *backbuffer;
 } XvMCContextPrivate;
 
 typedef struct
 {
-       struct pipe_video_surface *pipe_vsfc;
-       struct pipe_fence_handle *render_fence;
-       struct pipe_fence_handle *disp_fence;
-       
-       /* Some XvMC functions take a surface but not a context,
-          so we keep track of which context each surface belongs to. */
-       XvMCContext *context;
+   struct pipe_video_surface *pipe_vsfc;
+   struct pipe_fence_handle *render_fence;
+   struct pipe_fence_handle *disp_fence;
+
+   /* The subpicture associated with this surface, if any. */
+   XvMCSubpicture *subpicture;
+   short subx, suby;
+   unsigned short subw, subh;
+   short surfx, surfy;
+   unsigned short surfw, surfh;
+
+   /* Some XvMC functions take a surface but not a context,
+      so we keep track of which context each surface belongs to. */
+   XvMCContext *context;
 } XvMCSurfacePrivate;
 
 typedef struct
 {
-       struct pipe_surface *sfc;
-       /* Some XvMC functions take a subpicture but not a context,
-          so we keep track of which context each subpicture belongs to. */
-       XvMCContext *context;
-} XvMCSubPicturePrivate;
+   struct pipe_surface *sfc;
+
+   /* The surface this subpicture is currently associated with, if any. */
+   XvMCSurface *surface;
+
+   /* Some XvMC functions take a subpicture but not a context,
+      so we keep track of which context each subpicture belongs to. */
+   XvMCContext *context;
+} XvMCSubpicturePrivate;
 
 #define XVMC_OUT   0
 #define XVMC_ERR   1