Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / state_trackers / xorg / xvmc / surface.c
index 87d1dfaace29ab21b86918b6edd67ae4247f1a5c..db630c9e790f422524226c090db37399dfb1296f 100644 (file)
 
 #include <assert.h>
 #include <X11/Xlibint.h>
+#include <vl_winsys.h>
 #include <pipe/p_video_context.h>
 #include <pipe/p_video_state.h>
 #include <pipe/p_state.h>
+#include <util/u_inlines.h>
 #include <util/u_memory.h>
 #include "xvmc_private.h"
 
@@ -46,6 +48,8 @@ static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type)
 
    assert(0);
 
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized mb type 0x%08X.\n", xvmc_mb_type);
+
    return -1;
 }
 
@@ -62,6 +66,8 @@ static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic)
          assert(0);
    }
 
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized picture type 0x%08X.\n", xvmc_pic);
+
    return -1;
 }
 
@@ -69,8 +75,11 @@ static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_
 {
    switch (xvmc_motion_type) {
       case XVMC_PREDICTION_FRAME:
-         return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ?
-            PIPE_MPEG12_MOTION_TYPE_16x8 : PIPE_MPEG12_MOTION_TYPE_FRAME;
+         if (xvmc_dct_type == XVMC_DCT_TYPE_FIELD)
+            return PIPE_MPEG12_MOTION_TYPE_16x8;
+         else if (xvmc_dct_type == XVMC_DCT_TYPE_FRAME)
+            return PIPE_MPEG12_MOTION_TYPE_FRAME;
+         break;
       case XVMC_PREDICTION_FIELD:
          return PIPE_MPEG12_MOTION_TYPE_FIELD;
       case XVMC_PREDICTION_DUAL_PRIME:
@@ -79,17 +88,22 @@ static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_
          assert(0);
    }
 
+   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized motion type 0x%08X (with DCT type 0x%08X).\n", xvmc_motion_type, xvmc_dct_type);
+
    return -1;
 }
 
 static bool
-CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, unsigned int height,
+CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned int height,
                          struct pipe_surface **backbuffer)
 {
+   struct pipe_video_context *vpipe;
    struct pipe_texture template;
    struct pipe_texture *tex;
 
-   assert(vpipe);
+   assert(vctx);
+
+   vpipe = vctx->vpipe;
 
    if (*backbuffer) {
       if ((*backbuffer)->width != width || (*backbuffer)->height != height)
@@ -100,8 +114,7 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u
 
    memset(&template, 0, sizeof(struct pipe_texture));
    template.target = PIPE_TEXTURE_2D;
-   /* XXX: Needs to match the drawable's format? */
-   template.format = PIPE_FORMAT_B8G8R8X8_UNORM;
+   template.format = vctx->vscreen->format;
    template.last_level = 0;
    template.width0 = width;
    template.height0 = height;
@@ -122,13 +135,14 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u
 
    /* Clear the backbuffer in case the video doesn't cover the whole window */
    /* FIXME: Need to clear every time a frame moves and leaves dirty rects */
-   vpipe->clear_surface(vpipe, 0, 0, width, height, 0, *backbuffer);
+   vpipe->surface_fill(vpipe, *backbuffer, 0, 0, width, height, 0);
 
    return true;
 }
 
 static void
-MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
+MacroBlocksToPipe(struct pipe_screen *screen,
+                  const XvMCMacroBlockArray *xvmc_macroblocks,
                   const XvMCBlockArray *xvmc_blocks,
                   unsigned int first_macroblock,
                   unsigned int num_macroblocks,
@@ -163,7 +177,8 @@ MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
                pipe_macroblocks->pmv[j][k][l] = xvmc_mb->PMV[j][k][l];
 
       pipe_macroblocks->cbp = xvmc_mb->coded_block_pattern;
-      pipe_macroblocks->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES;
+      pipe_macroblocks->blocks = pipe_user_buffer_create(screen, xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES,
+                                                         BLOCK_SIZE_BYTES);
 
       ++pipe_macroblocks;
       ++xvmc_mb;
@@ -177,6 +192,8 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac
    XvMCSurfacePrivate *surface_priv;
    struct pipe_video_surface *vsfc;
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);
+
    assert(dpy);
 
    if (!context)
@@ -185,12 +202,13 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac
       return XvMCBadSurface;
 
    context_priv = context->privData;
-   vpipe = context_priv->vpipe;
+   vpipe = context_priv->vctx->vpipe;
 
    surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
    if (!surface_priv)
       return BadAlloc;
 
+   assert(vpipe->screen->video_surface_create);
    vsfc = vpipe->screen->video_surface_create(vpipe->screen, vpipe->chroma_format,
                                               vpipe->width, vpipe->height);
    if (!vsfc) {
@@ -210,6 +228,8 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac
 
    SyncHandle();
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface);
+
    return Success;
 }
 
@@ -228,6 +248,9 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur
    XvMCSurfacePrivate *past_surface_priv;
    XvMCSurfacePrivate *future_surface_priv;
    struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks];
+   unsigned int i;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p.\n", target_surface);
 
    assert(dpy);
 
@@ -265,19 +288,24 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur
    assert(!future_surface || future_surface_priv->context == context);
 
    context_priv = context->privData;
-   vpipe = context_priv->vpipe;
+   vpipe = context_priv->vctx->vpipe;
 
    t_vsfc = target_surface_priv->pipe_vsfc;
    p_vsfc = past_surface ? past_surface_priv->pipe_vsfc : NULL;
    f_vsfc = future_surface ? future_surface_priv->pipe_vsfc : NULL;
 
-   MacroBlocksToPipe(macroblocks, blocks, first_macroblock,
+   MacroBlocksToPipe(vpipe->screen, macroblocks, blocks, first_macroblock,
                      num_macroblocks, pipe_macroblocks);
 
    vpipe->set_decode_target(vpipe, t_vsfc);
    vpipe->decode_macroblocks(vpipe, p_vsfc, f_vsfc, num_macroblocks,
                              &pipe_macroblocks->base, target_surface_priv->render_fence);
 
+   for (i = 0; i < num_macroblocks; ++i)
+      vpipe->screen->buffer_destroy(pipe_macroblocks[i].blocks);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);
+
    return Success;
 }
 
@@ -314,10 +342,13 @@ 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};
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface);
+
    assert(dpy);
 
    if (!surface || !surface->privData)
@@ -344,16 +375,36 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    surface_priv = surface->privData;
    context = surface_priv->context;
    context_priv = context->privData;
-   vpipe = context_priv->vpipe;
+   subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL;
+   vpipe = context_priv->vctx->vpipe;
 
-   if (!CreateOrResizeBackBuffer(vpipe, width, height, &context_priv->backbuffer))
+   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);
 
-   vl_video_bind_drawable(vpipe, drawable);
-       
+   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
    (
       vpipe->screen,
@@ -361,6 +412,8 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
       vpipe->priv
    );
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);
+
    return Success;
 }
 
@@ -382,6 +435,8 @@ Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
 {
    XvMCSurfacePrivate *surface_priv;
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface);
+
    assert(dpy);
 
    if (!surface || !surface->privData)
@@ -392,6 +447,8 @@ Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
    FREE(surface_priv);
    surface->privData = NULL;
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface);
+
    return Success;
 }