Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / drivers / softpipe / sp_video_context.c
index ff217d66c85e5e53288bfe85120443a8d378bb50..daebbc54ad8dddb7e9a88d4e5eff38cda47b2867 100644 (file)
 #include "sp_video_context.h"
 #include <util/u_inlines.h>
 #include <util/u_memory.h>
+#include <util/u_keymap.h>
 #include <util/u_rect.h>
 #include <util/u_video.h>
 #include <util/u_surface.h>
 #include "sp_public.h"
 #include "sp_texture.h"
 
+#define NUM_BUFFERS 2
+
+static void
+flush_buffer(struct sp_mpeg12_context *ctx)
+{
+   assert(ctx);
+
+   if(ctx->mc_buffer != NULL) {
+
+      vl_mpeg12_mc_unmap_buffer(&ctx->mc_renderer, ctx->mc_buffer);
+      vl_mpeg12_mc_renderer_flush(&ctx->mc_renderer, ctx->mc_buffer);
+
+      ctx->mc_buffer = NULL;
+   }
+}
+
+static void
+rotate_buffer(struct sp_mpeg12_context *ctx)
+{
+   static unsigned key = 0;
+   struct vl_mpeg12_mc_buffer *buffer;
+
+   assert(ctx);
+
+   flush_buffer(ctx);
+
+   buffer = (struct vl_mpeg12_mc_buffer*)util_keymap_lookup(ctx->buffer_map, &key);
+   if (!buffer) {
+      boolean added_to_map;
+
+      buffer = CALLOC_STRUCT(vl_mpeg12_mc_buffer);
+      if (buffer == NULL)
+         return;
+
+      if(!vl_mpeg12_mc_init_buffer(&ctx->mc_renderer, buffer)) {
+         FREE(buffer);
+         return;
+      }
+
+      added_to_map = util_keymap_insert(ctx->buffer_map, &key, buffer, ctx);
+      assert(added_to_map);
+   }
+   ++key;
+   key %= NUM_BUFFERS;
+   ctx->mc_buffer = buffer;
+
+   vl_mpeg12_mc_map_buffer(&ctx->mc_renderer, ctx->mc_buffer);
+}
+
+static void
+delete_buffer(const struct keymap *map,
+              const void *key, void *data,
+              void *user)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)user;
+   struct vl_mpeg12_mc_buffer *buf = (struct vl_mpeg12_mc_buffer*)data;
+
+   assert(map);
+   assert(key);
+   assert(data);
+   assert(user);
+
+   vl_mpeg12_mc_cleanup_buffer(&ctx->mc_renderer, buf);
+}
+
 static void
 sp_mpeg12_destroy(struct pipe_video_context *vpipe)
 {
@@ -44,6 +110,8 @@ sp_mpeg12_destroy(struct pipe_video_context *vpipe)
 
    assert(vpipe);
 
+   flush_buffer(ctx);
+
    /* 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);
@@ -54,6 +122,7 @@ sp_mpeg12_destroy(struct pipe_video_context *vpipe)
 
    pipe_surface_reference(&ctx->decode_target, NULL);
    vl_compositor_cleanup(&ctx->compositor);
+   util_delete_keymap(ctx->buffer_map, ctx);
    vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
    ctx->pipe->destroy(ctx->pipe);
 
@@ -84,6 +153,18 @@ sp_mpeg12_get_param(struct pipe_video_context *vpipe, int param)
    }
 }
 
+static struct pipe_surface *
+sp_mpeg12_create_surface(struct pipe_video_context *vpipe,
+                         struct pipe_resource *resource,
+                         const struct pipe_surface *templat)
+{
+   struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
+
+   assert(vpipe);
+
+   return ctx->pipe->create_surface(ctx->pipe, resource, templat);
+}
+
 static boolean
 sp_mpeg12_is_format_supported(struct pipe_video_context *vpipe,
                               enum pipe_format format,
@@ -98,6 +179,7 @@ sp_mpeg12_is_format_supported(struct pipe_video_context *vpipe,
    if (geom & PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)
       return FALSE;
 
+
    return ctx->pipe->screen->is_format_supported(ctx->pipe->screen, format, PIPE_TEXTURE_2D,
                                                  0, usage, geom);
 }
@@ -118,19 +200,20 @@ sp_mpeg12_decode_macroblocks(struct pipe_video_context *vpipe,
    assert(macroblocks);
    assert(macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12);
    assert(ctx->decode_target);
+   assert(ctx->mc_buffer);
 
    vl_mpeg12_mc_renderer_render_macroblocks(&ctx->mc_renderer,
+                                            ctx->mc_buffer,
                                             ctx->decode_target,
                                             past, future, num_macroblocks,
                                             mpeg12_macroblocks, fence);
 }
 
 static void
-sp_mpeg12_surface_fill(struct pipe_video_context *vpipe,
+sp_mpeg12_clear_render_target(struct pipe_video_context *vpipe,
                        struct pipe_surface *dst,
                        unsigned dstx, unsigned dsty,
-                       unsigned width, unsigned height,
-                       unsigned value)
+                       unsigned width, unsigned height)
 {
    struct sp_mpeg12_context *ctx = (struct sp_mpeg12_context*)vpipe;
    float rgba[4] = { 0, 0, 0, 0 };
@@ -145,7 +228,7 @@ sp_mpeg12_surface_fill(struct pipe_video_context *vpipe,
 }
 
 static void
-sp_mpeg12_surface_copy(struct pipe_video_context *vpipe,
+sp_mpeg12_resource_copy_region(struct pipe_video_context *vpipe,
                        struct pipe_surface *dst,
                        unsigned dstx, unsigned dsty,
                        struct pipe_surface *src,
@@ -157,26 +240,27 @@ sp_mpeg12_surface_copy(struct pipe_video_context *vpipe,
    assert(vpipe);
    assert(dst);
 
-   struct pipe_subresource subdst, subsrc;
-   subdst.face = dst->face;
-   subdst.level = dst->level;
-   subsrc.face = src->face;
-   subsrc.level = src->level;
+   struct pipe_box box;
+   box.x = srcx;
+   box.y = srcy;
+   box.z = 0;
+   box.width = width;
+   box.height = height;
 
    if (ctx->pipe->resource_copy_region)
-      ctx->pipe->resource_copy_region(ctx->pipe, dst->texture, subdst, dstx, dsty, dst->zslice,
-                                      src->texture, subsrc, srcx, srcy, src->zslice,
-                                      width, height);
+      ctx->pipe->resource_copy_region(ctx->pipe, dst->texture, dst->u.tex.level,
+                                      dstx, dsty, dst->u.tex.first_layer,
+                                      src->texture, src->u.tex.level, &box);
    else
-      util_resource_copy_region(ctx->pipe, dst->texture, subdst, dstx, dsty, dst->zslice,
-                                src->texture, subsrc, srcx, srcy, src->zslice,
-                                width, height);
+      util_resource_copy_region(ctx->pipe, dst->texture, dst->u.tex.level,
+                                dstx, dsty, dst->u.tex.first_layer,
+                                src->texture, src->u.tex.level, &box);
 }
 
 static struct pipe_transfer*
 sp_mpeg12_get_transfer(struct pipe_video_context *vpipe,
                        struct pipe_resource *resource,
-                       struct pipe_subresource subresource,
+                       unsigned level,
                        unsigned usage,  /* a combination of PIPE_TRANSFER_x */
                        const struct pipe_box *box)
 {
@@ -186,7 +270,7 @@ sp_mpeg12_get_transfer(struct pipe_video_context *vpipe,
    assert(resource);
    assert(box);
 
-   return ctx->pipe->get_transfer(ctx->pipe, resource, subresource, usage, box);
+   return ctx->pipe->get_transfer(ctx->pipe, resource, level, usage, box);
 }
 
 static void
@@ -242,7 +326,7 @@ sp_mpeg12_transfer_unmap(struct pipe_video_context *vpipe,
 static void
 sp_mpeg12_transfer_inline_write(struct pipe_video_context *vpipe,
                                 struct pipe_resource *resource,
-                                struct pipe_subresource subresource,
+                                unsigned level,
                                 unsigned usage, /* a combination of PIPE_TRANSFER_x */
                                 const struct pipe_box *box,
                                 const void *data,
@@ -257,7 +341,7 @@ sp_mpeg12_transfer_inline_write(struct pipe_video_context *vpipe,
    assert(data);
    assert(ctx->pipe->transfer_inline_write);
 
-   ctx->pipe->transfer_inline_write(ctx->pipe, resource, subresource, usage,
+   ctx->pipe->transfer_inline_write(ctx->pipe, resource, level, usage,
                                     box, data, stride, slice_stride);
 }
 
@@ -282,6 +366,8 @@ sp_mpeg12_render_picture(struct pipe_video_context     *vpipe,
    assert(dst_surface);
    assert(dst_area);
 
+   flush_buffer(ctx);
+
    vl_compositor_render(&ctx->compositor, src_surface,
                         picture_type, src_area, dst_surface, dst_area, fence);
 }
@@ -325,7 +411,11 @@ sp_mpeg12_set_decode_target(struct pipe_video_context *vpipe,
    assert(vpipe);
    assert(dt);
 
-   pipe_surface_reference(&ctx->decode_target, dt);
+   if (ctx->decode_target != dt || ctx->mc_buffer == NULL) {
+      rotate_buffer(ctx);
+
+      pipe_surface_reference(&ctx->decode_target, dt);
+   }
 }
 
 static void
@@ -372,14 +462,16 @@ init_pipe_state(struct sp_mpeg12_context *ctx)
    rast.line_width = 1;
    rast.point_smooth = 0;
    rast.point_quad_rasterization = 0;
-   rast.point_size = 1;
+   rast.point_size_per_vertex = 1;
    rast.offset_units = 1;
    rast.offset_scale = 1;
    rast.gl_rasterization_rules = 1;
+   
    ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast);
    ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast);
 
    memset(&blend, 0, sizeof blend);
+
    blend.independent_blend_enable = 0;
    blend.rt[0].blend_enable = 0;
    blend.rt[0].rgb_func = PIPE_BLEND_ADD;
@@ -423,10 +515,10 @@ sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
                  enum pipe_video_chroma_format chroma_format,
                  unsigned width, unsigned height,
                  enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
-                 enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
                  bool pot_buffers,
                  enum pipe_format decode_format)
 {
+   unsigned buffer_width, buffer_height;
    struct sp_mpeg12_context *ctx;
 
    assert(u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12);
@@ -436,19 +528,27 @@ sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
    if (!ctx)
       return NULL;
 
+   /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
+   assert(pot_buffers);
+
+   buffer_width = pot_buffers ? util_next_power_of_two(width) : width; 
+   buffer_height = pot_buffers ? util_next_power_of_two(height) : height; 
+
    ctx->base.profile = profile;
    ctx->base.chroma_format = chroma_format;
    ctx->base.width = width;
    ctx->base.height = height;
 
    ctx->base.screen = pipe->screen;
+
    ctx->base.destroy = sp_mpeg12_destroy;
    ctx->base.get_param = sp_mpeg12_get_param;
    ctx->base.is_format_supported = sp_mpeg12_is_format_supported;
+   ctx->base.create_surface = sp_mpeg12_create_surface;
    ctx->base.decode_macroblocks = sp_mpeg12_decode_macroblocks;
    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.clear_render_target = sp_mpeg12_clear_render_target;
+   ctx->base.resource_copy_region = sp_mpeg12_resource_copy_region;
    ctx->base.get_transfer = sp_mpeg12_get_transfer;
    ctx->base.transfer_destroy = sp_mpeg12_transfer_destroy;
    ctx->base.transfer_map = sp_mpeg12_transfer_map;
@@ -465,14 +565,23 @@ sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
    ctx->decode_format = decode_format;
 
    if (!vl_mpeg12_mc_renderer_init(&ctx->mc_renderer, ctx->pipe,
-                                   width, height, chroma_format,
-                                   bufmode, eb_handling, pot_buffers)) {
+                                   buffer_width, buffer_height, chroma_format,
+                                   bufmode)) {
+      ctx->pipe->destroy(ctx->pipe);
+      FREE(ctx);
+      return NULL;
+   }
+
+   ctx->buffer_map = util_new_keymap(sizeof(unsigned), -1, delete_buffer);
+   if (!ctx->buffer_map) {
+      vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
       ctx->pipe->destroy(ctx->pipe);
       FREE(ctx);
       return NULL;
    }
 
    if (!vl_compositor_init(&ctx->compositor, ctx->pipe)) {
+      util_delete_keymap(ctx->buffer_map, ctx);
       vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
       ctx->pipe->destroy(ctx->pipe);
       FREE(ctx);
@@ -481,6 +590,7 @@ sp_mpeg12_create(struct pipe_context *pipe, enum pipe_video_profile profile,
 
    if (!init_pipe_state(ctx)) {
       vl_compositor_cleanup(&ctx->compositor);
+      util_delete_keymap(ctx->buffer_map, ctx);
       vl_mpeg12_mc_renderer_cleanup(&ctx->mc_renderer);
       ctx->pipe->destroy(ctx->pipe);
       FREE(ctx);
@@ -505,12 +615,10 @@ sp_video_create(struct pipe_screen *screen, enum pipe_video_profile profile,
       return NULL;
 
    /* TODO: Use slice buffering for softpipe when implemented, no advantage to buffering an entire picture with softpipe */
-   /* TODO: Use XFER_NONE when implemented */
    return sp_video_create_ex(pipe, profile,
                              chroma_format,
                              width, height,
                              VL_MPEG12_MC_RENDERER_BUFFER_PICTURE,
-                             VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE,
                              true,
                              PIPE_FORMAT_XYUV);
 }
@@ -520,7 +628,6 @@ sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile,
                    enum pipe_video_chroma_format chroma_format,
                    unsigned width, unsigned height,
                    enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
-                   enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
                    bool pot_buffers,
                    enum pipe_format decode_format)
 {
@@ -532,7 +639,7 @@ sp_video_create_ex(struct pipe_context *pipe, enum pipe_video_profile profile,
          return sp_mpeg12_create(pipe, profile,
                                  chroma_format,
                                  width, height,
-                                 bufmode, eb_handling,
+                                 bufmode,
                                  pot_buffers,
                                  decode_format);
       default: