vl: add support for bob deinterlacing
[mesa.git] / src / gallium / state_trackers / xorg / xvmc / surface.c
index fd7d228c996ea2f082c2a55a8b494b4b343275e0..7f7eeadcbc682fdb053ffa11cd41400c6882b3da 100644 (file)
 
 #include <X11/Xlibint.h>
 
-#include <pipe/p_video_decoder.h>
-#include <pipe/p_video_state.h>
-#include <pipe/p_state.h>
+#include "pipe/p_video_decoder.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 "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
 
-#include <vl_winsys.h>
+#include "vl_winsys.h"
 
 #include "xvmc_private.h"
 
@@ -97,32 +97,23 @@ MacroBlocksToPipe(XvMCContextPrivate *context,
 }
 
 static void
-SetDecoderStatus(XvMCSurfacePrivate *surface)
+GetPictureDescription(XvMCSurfacePrivate *surface, struct pipe_mpeg12_picture_desc *desc)
 {
-   struct pipe_video_decoder *decoder;
-   struct pipe_video_buffer *ref_frames[2];
-
-   XvMCContextPrivate *context_priv;
-
    unsigned i, num_refs = 0;
 
-   assert(surface);
-
-   context_priv = surface->context->privData;
-   decoder = context_priv->decoder;
-
-   decoder->set_decode_buffer(decoder, surface->decode_buffer);
-   decoder->set_decode_target(decoder, surface->video_buffer);
+   assert(surface && desc);
 
+   memset(desc, 0, sizeof(*desc));
+   desc->base.profile = PIPE_VIDEO_PROFILE_MPEG1;
+   desc->picture_structure = surface->picture_structure;
    for (i = 0; i < 2; ++i) {
       if (surface->ref[i]) {
          XvMCSurfacePrivate *ref = surface->ref[i]->privData;
 
          if (ref)
-            ref_frames[num_refs++] = ref->video_buffer;
+            desc->ref[num_refs++] = ref->video_buffer;
       }
    }
-   decoder->set_reference_frames(decoder, ref_frames, num_refs);
 }
 
 static void
@@ -147,34 +138,25 @@ RecursiveEndFrame(XvMCSurfacePrivate *surface)
       }
    }
 
-   if (surface->frame_started) {
-      surface->frame_started = 0;
-      SetDecoderStatus(surface);
+   if (surface->picture_structure) {
+      struct pipe_mpeg12_picture_desc desc;
+      GetPictureDescription(surface, &desc);
+      surface->picture_structure = 0;
 
       for (i = 0; i < 2; ++i)
          surface->ref[i] = NULL;
 
-      context_priv->decoder->end_frame(context_priv->decoder);
+      context_priv->decoder->end_frame(context_priv->decoder, surface->video_buffer, &desc.base);
    }
 }
 
 PUBLIC
 Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
 {
-   static const uint8_t dummy_quant[64] = {
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
-   };
-
    XvMCContextPrivate *context_priv;
    struct pipe_context *pipe;
    XvMCSurfacePrivate *surface_priv;
+   struct pipe_video_buffer tmpl;
 
    XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);
 
@@ -192,14 +174,24 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac
    if (!surface_priv)
       return BadAlloc;
 
-   surface_priv->decode_buffer = context_priv->decoder->create_buffer(context_priv->decoder);
-   context_priv->decoder->set_quant_matrix(context_priv->decoder, dummy_quant, dummy_quant);
-   surface_priv->video_buffer = pipe->create_video_buffer
+   memset(&tmpl, 0, sizeof(tmpl));
+   tmpl.buffer_format = pipe->screen->get_video_param
    (
-      pipe, PIPE_FORMAT_NV12, context_priv->decoder->chroma_format,
-      context_priv->decoder->width, context_priv->decoder->height
+      pipe->screen,
+      PIPE_VIDEO_PROFILE_MPEG2_MAIN,
+      PIPE_VIDEO_CAP_PREFERED_FORMAT
    );
-   
+   tmpl.chroma_format = context_priv->decoder->chroma_format;
+   tmpl.width = context_priv->decoder->width;
+   tmpl.height = context_priv->decoder->height;
+   tmpl.interlaced = pipe->screen->get_video_param
+   (
+      pipe->screen,
+      PIPE_VIDEO_PROFILE_MPEG2_MAIN,
+      PIPE_VIDEO_CAP_PREFERS_INTERLACED
+   );
+
+   surface_priv->video_buffer = pipe->create_video_buffer(pipe, &tmpl);
    surface_priv->context = context;
 
    surface->surface_id = XAllocID(dpy);
@@ -225,6 +217,7 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur
 {
    struct pipe_mpeg12_macroblock mb[num_macroblocks];
    struct pipe_video_decoder *decoder;
+   struct pipe_mpeg12_picture_desc desc;
 
    XvMCContextPrivate *context_priv;
    XvMCSurfacePrivate *target_surface_priv;
@@ -283,7 +276,8 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur
    xvmc_mb = macroblocks->macro_blocks + first_macroblock;
 
    /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
-   if (target_surface_priv->frame_started && (
+   if (target_surface_priv->picture_structure > 0 && (
+       target_surface_priv->picture_structure != picture_structure ||
        target_surface_priv->ref[0] != past_surface ||
        target_surface_priv->ref[1] != future_surface ||
        (xvmc_mb->x == 0 && xvmc_mb->y == 0))) {
@@ -295,17 +289,21 @@ Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int pictur
    target_surface_priv->ref[0] = past_surface;
    target_surface_priv->ref[1] = future_surface;
 
-   SetDecoderStatus(target_surface_priv);
-
-   if (!target_surface_priv->frame_started) {
-      target_surface_priv->frame_started = 1;
-      decoder->begin_frame(decoder);
+   if (target_surface_priv->picture_structure)
+      GetPictureDescription(target_surface_priv, &desc);
+   else {
+      target_surface_priv->picture_structure = picture_structure;
+      GetPictureDescription(target_surface_priv, &desc);
+      decoder->begin_frame(decoder, target_surface_priv->video_buffer, &desc.base);
    }
 
    MacroBlocksToPipe(context_priv, target_surface_priv, picture_structure,
                      xvmc_mb, blocks, mb, num_macroblocks);
 
-   context_priv->decoder->decode_macroblock(context_priv->decoder, &mb[0].base, num_macroblocks);
+   context_priv->decoder->decode_macroblock(context_priv->decoder,
+                                            target_surface_priv->video_buffer,
+                                            &desc.base,
+                                            &mb[0].base, num_macroblocks);
 
    XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);
 
@@ -385,7 +383,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
       pipe_surface_reference(&context_priv->drawable_surface, NULL);
       context_priv->drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable);
       context_priv->dst_rect = dst_rect;
-      vl_compositor_reset_dirty_area(compositor);
+      vl_compositor_reset_dirty_area(&context_priv->dirty_area);
    }
 
    if (!context_priv->drawable_surface)
@@ -408,7 +406,8 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    context_priv->decoder->flush(context_priv->decoder);
 
    vl_compositor_clear_layers(compositor);
-   vl_compositor_set_buffer_layer(compositor, 0, surface_priv->video_buffer, &src_rect, NULL);
+   vl_compositor_set_buffer_layer(compositor, 0, surface_priv->video_buffer,
+                                  &src_rect, NULL, VL_COMPOSITOR_WEAVE);
 
    if (subpicture_priv) {
       XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture);
@@ -417,7 +416,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
 
       if (subpicture_priv->palette)
          vl_compositor_set_palette_layer(compositor, 1, subpicture_priv->sampler, subpicture_priv->palette,
-                                         &subpicture_priv->src_rect, &subpicture_priv->dst_rect);
+                                         &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true);
       else
          vl_compositor_set_rgba_layer(compositor, 1, subpicture_priv->sampler,
                                       &subpicture_priv->src_rect, &subpicture_priv->dst_rect);
@@ -429,7 +428,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    // Workaround for r600g, there seems to be a bug in the fence refcounting code
    pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL);
 
-   vl_compositor_render(compositor, context_priv->drawable_surface, &dst_rect, NULL);
+   vl_compositor_render(compositor, context_priv->drawable_surface, &dst_rect, NULL, &context_priv->dirty_area);
                         
    pipe->flush(pipe, &surface_priv->fence);
 
@@ -504,11 +503,11 @@ Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
    surface_priv = surface->privData;
    context_priv = surface_priv->context->privData;
    
-   if (surface_priv->frame_started) {
-      SetDecoderStatus(surface_priv);
-      context_priv->decoder->end_frame(context_priv->decoder);
+   if (surface_priv->picture_structure) {
+      struct pipe_mpeg12_picture_desc desc;
+      GetPictureDescription(surface_priv, &desc);
+      context_priv->decoder->end_frame(context_priv->decoder, surface_priv->video_buffer, &desc.base);
    }
-   context_priv->decoder->destroy_buffer(context_priv->decoder, surface_priv->decode_buffer);
    surface_priv->video_buffer->destroy(surface_priv->video_buffer);
    FREE(surface_priv);
    surface->privData = NULL;