[g3dvl] motion type depends on picture structure not dct type
[mesa.git] / src / gallium / state_trackers / xorg / xvmc / surface.c
index bf9038f356e4d4eb11e5edd2499138343068fcc4..9709f2b23737a36d7e62d26d2ca8073ed8423c22 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.
  * 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.
- * 
+ *
  **************************************************************************/
 
 #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 <util/u_math.h>
 #include "xvmc_private.h"
 
 static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type)
@@ -46,6 +49,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,15 +67,20 @@ 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;
 }
 
-static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_dct_type)
+static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, unsigned int xvmc_picture_structure)
 {
    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_picture_structure == XVMC_FRAME_PICTURE)
+            return PIPE_MPEG12_MOTION_TYPE_FRAME;
+         else
+            return PIPE_MPEG12_MOTION_TYPE_16x8;
+         break;
       case XVMC_PREDICTION_FIELD:
          return PIPE_MPEG12_MOTION_TYPE_FIELD;
       case XVMC_PREDICTION_DUAL_PRIME:
@@ -79,17 +89,23 @@ 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 picture structure 0x%08X).\n", xvmc_motion_type, xvmc_picture_structure);
+
    return -1;
 }
 
+#if 0
 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_texture template;
-   struct pipe_texture *tex;
+   struct pipe_video_context *vpipe;
+   struct pipe_resource template;
+   struct pipe_resource *tex;
+
+   assert(vctx);
 
-   assert(vpipe);
+   vpipe = vctx->vpipe;
 
    if (*backbuffer) {
       if ((*backbuffer)->width != width || (*backbuffer)->height != height)
@@ -98,38 +114,40 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u
          return true;
    }
 
-   memset(&template, 0, sizeof(struct pipe_texture));
+   memset(&template, 0, sizeof(struct pipe_resource));
    template.target = PIPE_TEXTURE_2D;
-   /* XXX: Needs to match the drawable's format? */
-   template.format = PIPE_FORMAT_X8R8G8B8_UNORM;
+   template.format = vctx->vscreen->format;
    template.last_level = 0;
-   template.width[0] = width;
-   template.height[0] = height;
-   template.depth[0] = 1;
-   pf_get_block(template.format, &template.block);
-   template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
-
-   tex = vpipe->screen->texture_create(vpipe->screen, &template);
+   template.width0 = width;
+   template.height0 = height;
+   template.depth0 = 1;
+   template.usage = PIPE_USAGE_DEFAULT;
+   template.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_BLIT_SOURCE;
+   template.flags = 0;
+
+   tex = vpipe->screen->resource_create(vpipe->screen, &template);
    if (!tex)
       return false;
 
    *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
-                                                PIPE_BUFFER_USAGE_GPU_READ |
-                                                PIPE_BUFFER_USAGE_GPU_WRITE);
-   pipe_texture_reference(&tex, NULL);
+                                                template.bind);
+   pipe_resource_reference(&tex, NULL);
 
    if (!*backbuffer)
       return false;
 
    /* 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;
 }
+#endif
 
 static void
-MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
+MacroBlocksToPipe(struct pipe_screen *screen,
+                  unsigned int xvmc_picture_structure,
+                  const XvMCMacroBlockArray *xvmc_macroblocks,
                   const XvMCBlockArray *xvmc_blocks,
                   unsigned int first_macroblock,
                   unsigned int num_macroblocks,
@@ -151,7 +169,7 @@ MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
       pipe_macroblocks->mby = xvmc_mb->y;
       pipe_macroblocks->mb_type = TypeToPipe(xvmc_mb->macroblock_type);
       if (pipe_macroblocks->mb_type != PIPE_MPEG12_MACROBLOCK_TYPE_INTRA)
-         pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_mb->dct_type);
+         pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_picture_structure);
       /* Get rid of Valgrind 'undefined' warnings */
       else
          pipe_macroblocks->mo_type = -1;
@@ -171,12 +189,17 @@ MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
    }
 }
 
+PUBLIC
 Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
 {
    XvMCContextPrivate *context_priv;
    struct pipe_video_context *vpipe;
    XvMCSurfacePrivate *surface_priv;
-   struct pipe_video_surface *vsfc;
+   struct pipe_resource template;
+   struct pipe_resource *vsfc_tex;
+   struct pipe_surface *vsfc;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);
 
    assert(dpy);
 
@@ -186,14 +209,42 @@ 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;
 
-   vsfc = vpipe->screen->video_surface_create(vpipe->screen, vpipe->chroma_format,
-                                              vpipe->width, vpipe->height);
+   memset(&template, 0, sizeof(struct pipe_resource));
+   template.target = PIPE_TEXTURE_2D;
+   template.format = (enum pipe_format)vpipe->get_param(vpipe, PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT);
+   template.last_level = 0;
+   if (vpipe->is_format_supported(vpipe, template.format,
+                                  PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+                                  PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) {
+      template.width0 = context->width;
+      template.height0 = context->height;
+   }
+   else {
+      assert(vpipe->is_format_supported(vpipe, template.format,
+                                       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
+                                       PIPE_TEXTURE_GEOM_NON_SQUARE));
+      template.width0 = util_next_power_of_two(context->width);
+      template.height0 = util_next_power_of_two(context->height);
+   }
+   template.depth0 = 1;
+   template.usage = PIPE_USAGE_DEFAULT;
+   template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+   template.flags = 0;
+   vsfc_tex = vpipe->screen->resource_create(vpipe->screen, &template);
+   if (!vsfc_tex) {
+      FREE(surface_priv);
+      return BadAlloc;
+   }
+
+   vsfc = vpipe->screen->get_tex_surface(vpipe->screen, vsfc_tex, 0, 0, 0,
+                                         PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET);
+   pipe_resource_reference(&vsfc_tex, NULL);
    if (!vsfc) {
       FREE(surface_priv);
       return BadAlloc;
@@ -211,9 +262,12 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac
 
    SyncHandle();
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface);
+
    return Success;
 }
 
+PUBLIC
 Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
                          XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
                          unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
@@ -230,6 +284,8 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur
    XvMCSurfacePrivate *future_surface_priv;
    struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks];
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p.\n", target_surface);
+
    assert(dpy);
 
    if (!context || !context->privData)
@@ -266,22 +322,25 @@ 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, picture_structure, 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);
+                             &pipe_macroblocks->base, &target_surface_priv->render_fence);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);
 
    return Success;
 }
 
+PUBLIC
 Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
 {
    assert(dpy);
@@ -292,6 +351,7 @@ Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
    return Success;
 }
 
+PUBLIC
 Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
 {
    assert(dpy);
@@ -302,29 +362,34 @@ Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
    return Success;
 }
 
+PUBLIC
 Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
                       short srcx, short srcy, unsigned short srcw, unsigned short srch,
                       short destx, short desty, unsigned short destw, unsigned short desth,
                       int flags)
 {
-   Window root;
-   int x, y;
-   unsigned int width, height;
-   unsigned int border_width;
-   unsigned int depth;
    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};
+   struct pipe_surface *drawable_surface;
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface);
 
    assert(dpy);
 
    if (!surface || !surface->privData)
       return XvMCBadSurface;
 
-   if (XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+   surface_priv = surface->privData;
+   context = surface_priv->context;
+   context_priv = context->privData;
+
+   drawable_surface = vl_drawable_surface_get(context_priv->vctx->vscreen, drawable);
+   if (!drawable_surface)
       return BadDrawable;
 
    assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
@@ -338,33 +403,55 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
     * until the app updates destw and desth.
     */
    /*
-   assert(destx + destw - 1 < width);
-   assert(desty + desth - 1 < height);
+   assert(destx + destw - 1 < drawable_surface->width);
+   assert(desty + desth - 1 < drawable_surface->height);
     */
 
-   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 0
+   if (!CreateOrResizeBackBuffer(context_priv->vctx, width, height, &context_priv->backbuffer))
       return BadAlloc;
+#endif
+
+   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, 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);
+                         drawable_surface, &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(vpipe, drawable);
-       
    vpipe->screen->flush_frontbuffer
    (
       vpipe->screen,
-      context_priv->backbuffer,
-      vpipe->priv
+      drawable_surface,
+      vl_contextprivate_get(context_priv->vctx, drawable_surface)
    );
 
+   pipe_surface_reference(&drawable_surface, NULL);
+
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);
+
    return Success;
 }
 
+PUBLIC
 Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
 {
    assert(dpy);
@@ -379,23 +466,29 @@ Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
    return Success;
 }
 
+PUBLIC
 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)
       return XvMCBadSurface;
 
    surface_priv = surface->privData;
-   pipe_video_surface_reference(&surface_priv->pipe_vsfc, NULL);
+   pipe_surface_reference(&surface_priv->pipe_vsfc, NULL);
    FREE(surface_priv);
    surface->privData = NULL;
 
+   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface);
+
    return Success;
 }
 
+PUBLIC
 Status XvMCHideSurface(Display *dpy, XvMCSurface *surface)
 {
    assert(dpy);