[g3dvl] introduction of ycbcr buffers
authorChristian König <deathsimple@vodafone.de>
Sun, 27 Mar 2011 17:43:02 +0000 (19:43 +0200)
committerChristian König <deathsimple@vodafone.de>
Sun, 27 Mar 2011 17:43:02 +0000 (19:43 +0200)
Moves most of the buffer creation out of the idct code.

src/gallium/auxiliary/Makefile
src/gallium/auxiliary/vl/vl_idct.c
src/gallium/auxiliary/vl/vl_idct.h
src/gallium/auxiliary/vl/vl_mpeg12_context.c
src/gallium/auxiliary/vl/vl_mpeg12_context.h
src/gallium/auxiliary/vl/vl_ycbcr_buffer.c [new file with mode: 0644]
src/gallium/auxiliary/vl/vl_ycbcr_buffer.h [new file with mode: 0644]

index 869b2d486a48fd3c18cfb7336924915f110875bb..0464df84e123fabe21960dc4b2d69dd9164a143f 100644 (file)
@@ -153,7 +153,8 @@ C_SOURCES = \
        vl/vl_compositor.c \
        vl/vl_csc.c \
         vl/vl_idct.c \
-        vl/vl_vertex_buffers.c
+        vl/vl_vertex_buffers.c \
+        vl/vl_ycbcr_buffer.c
 
 GALLIVM_SOURCES = \
         gallivm/lp_bld_arit.c \
index 075b892628fef0442a69e3ede7fbda70205d93f6..8cfb56ea41616727190a4e5f1b0b7352ef68f5e6 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "vl_idct.h"
 #include "vl_vertex_buffers.h"
+#include "vl_ycbcr_buffer.h"
 #include "vl_defines.h"
 #include "util/u_draw.h"
 #include <assert.h>
@@ -457,89 +458,91 @@ cleanup_state(struct vl_idct *idct)
 }
 
 static bool
-init_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer)
+init_intermediate(struct vl_idct *idct, struct vl_idct_buffer *buffer)
 {
-   struct pipe_resource template;
-   struct pipe_sampler_view sampler_view;
+   struct pipe_resource tex_templ, *tex;
+   struct pipe_sampler_view sv_templ;
+   struct pipe_surface surf_templ;
    unsigned i;
 
    assert(idct && buffer);
 
-   /* create textures */
-   memset(&template, 0, sizeof(struct pipe_resource));
-   template.last_level = 0;
-   template.bind = PIPE_BIND_SAMPLER_VIEW;
-   template.flags = 0;
-
-   template.target = PIPE_TEXTURE_2D;
-   template.format = PIPE_FORMAT_R16G16B16A16_SNORM;
-   template.width0 = idct->buffer_width / 4;
-   template.height0 = idct->buffer_height;
-   template.depth0 = 1;
-   template.array_size = 1;
-   template.usage = PIPE_USAGE_STREAM;
-   buffer->textures.individual.source = idct->pipe->screen->resource_create(idct->pipe->screen, &template);
-   if (!buffer->textures.individual.source)
-      goto error;
-
-   template.target = PIPE_TEXTURE_3D;
-   template.format = PIPE_FORMAT_R16G16B16A16_SNORM;
-   template.width0 = idct->buffer_width / NR_RENDER_TARGETS;
-   template.height0 = idct->buffer_height / 4;
-   template.depth0 = NR_RENDER_TARGETS;
-   template.usage = PIPE_USAGE_STATIC;
-   buffer->textures.individual.intermediate = idct->pipe->screen->resource_create(idct->pipe->screen, &template);
-   if (!buffer->textures.individual.intermediate)
-      goto error;
+   memset(&tex_templ, 0, sizeof(tex_templ));
+   tex_templ.target = PIPE_TEXTURE_3D;
+   tex_templ.format = PIPE_FORMAT_R16G16B16A16_SNORM;
+   tex_templ.width0 = idct->buffer_width / NR_RENDER_TARGETS;
+   tex_templ.height0 = idct->buffer_height / 4;
+   tex_templ.depth0 = NR_RENDER_TARGETS;
+   tex_templ.array_size = 1;
+   tex_templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+   tex_templ.usage = PIPE_USAGE_STATIC;
+
+   tex = idct->pipe->screen->resource_create(idct->pipe->screen, &tex_templ);
+   if (!tex)
+      goto error_tex;
+
+   memset(&sv_templ, 0, sizeof(sv_templ));
+   u_sampler_view_default_template(&sv_templ, tex, tex->format);
+   buffer->sampler_views.individual.intermediate =
+      idct->pipe->create_sampler_view(idct->pipe, tex, &sv_templ);
+   if (!buffer->sampler_views.individual.intermediate)
+         goto error_sampler_view;
+
+   buffer->fb_state[0].width = tex->width0;
+   buffer->fb_state[0].height = tex->height0;
+   buffer->fb_state[0].nr_cbufs = NR_RENDER_TARGETS;
+   for(i = 0; i < NR_RENDER_TARGETS; ++i) {
+      memset(&surf_templ, 0, sizeof(surf_templ));
+      surf_templ.format = tex->format;
+      surf_templ.u.tex.first_layer = i;
+      surf_templ.u.tex.last_layer = i;
+      surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+      buffer->fb_state[0].cbufs[i] = idct->pipe->create_surface(
+         idct->pipe, tex, &surf_templ);
 
-   for (i = 0; i < 4; ++i) {
-      memset(&sampler_view, 0, sizeof(sampler_view));
-      u_sampler_view_default_template(&sampler_view, buffer->textures.all[i], buffer->textures.all[i]->format);
-      buffer->sampler_views.all[i] = idct->pipe->create_sampler_view(idct->pipe, buffer->textures.all[i], &sampler_view);
-      if (!buffer->sampler_views.all[i])
-         goto error;
+      if (!buffer->fb_state[0].cbufs[i])
+         goto error_surfaces;
    }
 
-   template.target = PIPE_TEXTURE_2D;
-   /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
-   template.format = PIPE_FORMAT_R16_SNORM;
-   template.width0 = idct->buffer_width;
-   template.height0 = idct->buffer_height;
-   template.depth0 = 1;
-
-   buffer->destination = idct->pipe->screen->resource_create(idct->pipe->screen, &template);
-   if (!buffer->destination)
-      goto error;
+   buffer->viewport[0].scale[0] = tex->width0;
+   buffer->viewport[0].scale[1] = tex->height0;
 
+   pipe_resource_reference(&tex, NULL);
    return true;
 
-error:
-   for (i = 0; i < 4; ++i) {
-      pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL);
-      pipe_resource_reference(&buffer->textures.all[i], NULL);
-   }
+error_surfaces:
+   for(i = 0; i < NR_RENDER_TARGETS; ++i)
+      pipe_surface_reference(&buffer->fb_state[0].cbufs[i], NULL);
+
+   pipe_sampler_view_reference(&buffer->sampler_views.individual.intermediate, NULL);
+
+error_sampler_view:
+   pipe_resource_reference(&tex, NULL);
+
+error_tex:
    return false;
 }
 
 static void
-cleanup_textures(struct vl_idct *idct, struct vl_idct_buffer *buffer)
+cleanup_intermediate(struct vl_idct *idct, struct vl_idct_buffer *buffer)
 {
    unsigned i;
 
    assert(idct && buffer);
 
-   for (i = 0; i < 4; ++i) {
-      pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL);
-      pipe_resource_reference(&buffer->textures.all[i], NULL);
-   }
+   for(i = 0; i < NR_RENDER_TARGETS; ++i)
+      pipe_surface_reference(&buffer->fb_state[0].cbufs[i], NULL);
+
+   pipe_sampler_view_reference(&buffer->sampler_views.individual.intermediate, NULL);
 }
 
-struct pipe_resource *
+struct pipe_sampler_view *
 vl_idct_upload_matrix(struct pipe_context *pipe)
 {
    const float scale = sqrtf(SCALE_FACTOR_16_TO_9);
 
-   struct pipe_resource template, *matrix;
+   struct pipe_resource tex_templ, *matrix;
+   struct pipe_sampler_view sv_templ, *sv;
    struct pipe_transfer *buf_transfer;
    unsigned i, j, pitch;
    float *f;
@@ -554,19 +557,19 @@ vl_idct_upload_matrix(struct pipe_context *pipe)
 
    assert(pipe);
 
-   memset(&template, 0, sizeof(struct pipe_resource));
-   template.target = PIPE_TEXTURE_2D;
-   template.format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-   template.last_level = 0;
-   template.width0 = 2;
-   template.height0 = 8;
-   template.depth0 = 1;
-   template.array_size = 1;
-   template.usage = PIPE_USAGE_IMMUTABLE;
-   template.bind = PIPE_BIND_SAMPLER_VIEW;
-   template.flags = 0;
-
-   matrix = pipe->screen->resource_create(pipe->screen, &template);
+   memset(&tex_templ, 0, sizeof(tex_templ));
+   tex_templ.target = PIPE_TEXTURE_2D;
+   tex_templ.format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   tex_templ.last_level = 0;
+   tex_templ.width0 = 2;
+   tex_templ.height0 = 8;
+   tex_templ.depth0 = 1;
+   tex_templ.array_size = 1;
+   tex_templ.usage = PIPE_USAGE_IMMUTABLE;
+   tex_templ.bind = PIPE_BIND_SAMPLER_VIEW;
+   tex_templ.flags = 0;
+
+   matrix = pipe->screen->resource_create(pipe->screen, &tex_templ);
    if (!matrix)
       goto error_matrix;
 
@@ -593,7 +596,14 @@ vl_idct_upload_matrix(struct pipe_context *pipe)
    pipe->transfer_unmap(pipe, buf_transfer);
    pipe->transfer_destroy(pipe, buf_transfer);
 
-   return matrix;
+   memset(&sv_templ, 0, sizeof(sv_templ));
+   u_sampler_view_default_template(&sv_templ, matrix, matrix->format);
+   sv = pipe->create_sampler_view(pipe, matrix, &sv_templ);
+   pipe_resource_reference(&matrix, NULL);
+   if (!sv)
+      goto error_map;
+
+   return sv;
 
 error_map:
    pipe->transfer_destroy(pipe, buf_transfer);
@@ -608,7 +618,7 @@ error_matrix:
 bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe,
                   unsigned buffer_width, unsigned buffer_height,
                   unsigned blocks_x, unsigned blocks_y,
-                  int color_swizzle, struct pipe_resource *matrix)
+                  int color_swizzle, struct pipe_sampler_view *matrix)
 {
    assert(idct && pipe && matrix);
 
@@ -617,7 +627,7 @@ bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe,
    idct->buffer_height = buffer_height;
    idct->blocks_x = blocks_x;
    idct->blocks_y = blocks_y;
-   pipe_resource_reference(&idct->matrix, matrix);
+   pipe_sampler_view_reference(&idct->matrix, matrix);
 
    if(!init_shaders(idct, color_swizzle))
       return false;
@@ -636,63 +646,35 @@ vl_idct_cleanup(struct vl_idct *idct)
    cleanup_shaders(idct);
    cleanup_state(idct);
 
-   pipe_resource_reference(&idct->matrix, NULL);
+   pipe_sampler_view_reference(&idct->matrix, NULL);
 }
 
-struct pipe_resource *
-vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer)
+bool
+vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer,
+                    struct pipe_sampler_view *source, struct pipe_surface *destination)
 {
-   struct pipe_surface template;
-
    unsigned i;
 
    assert(buffer);
    assert(idct);
+   assert(source);
+   assert(destination);
 
-   pipe_resource_reference(&buffer->textures.individual.matrix, idct->matrix);
-   pipe_resource_reference(&buffer->textures.individual.transpose, idct->matrix);
+   pipe_sampler_view_reference(&buffer->sampler_views.individual.matrix, idct->matrix);
+   pipe_sampler_view_reference(&buffer->sampler_views.individual.source, source);
+   pipe_sampler_view_reference(&buffer->sampler_views.individual.transpose, idct->matrix);
 
-   if (!init_textures(idct, buffer))
-      goto error_textures;
+   if (!init_intermediate(idct, buffer))
+      return false;
 
    /* init state */
-   buffer->viewport[0].scale[0] = buffer->textures.individual.intermediate->width0;
-   buffer->viewport[0].scale[1] = buffer->textures.individual.intermediate->height0;
-
-   buffer->viewport[1].scale[0] = buffer->destination->width0;
-   buffer->viewport[1].scale[1] = buffer->destination->height0;
-
-   buffer->fb_state[0].width = buffer->textures.individual.intermediate->width0;
-   buffer->fb_state[0].height = buffer->textures.individual.intermediate->height0;
-
-   buffer->fb_state[0].nr_cbufs = NR_RENDER_TARGETS;
-   for(i = 0; i < NR_RENDER_TARGETS; ++i) {
-      memset(&template, 0, sizeof(template));
-      template.format = buffer->textures.individual.intermediate->format;
-      template.u.tex.first_layer = i;
-      template.u.tex.last_layer = i;
-      template.usage = PIPE_BIND_RENDER_TARGET;
-      buffer->fb_state[0].cbufs[i] = idct->pipe->create_surface(
-         idct->pipe, buffer->textures.individual.intermediate,
-         &template);
-
-      if (!buffer->fb_state[0].cbufs[i])
-         goto error_matrix_surfaces;
-   }
-
-   buffer->fb_state[1].width = buffer->destination->width0;
-   buffer->fb_state[1].height = buffer->destination->height0;
-
+   buffer->fb_state[1].width = destination->texture->width0;
+   buffer->fb_state[1].height = destination->texture->height0;
    buffer->fb_state[1].nr_cbufs = 1;
+   pipe_surface_reference(&buffer->fb_state[1].cbufs[0], destination);
 
-   memset(&template, 0, sizeof(template));
-   template.format = buffer->destination->format;
-   template.usage = PIPE_BIND_RENDER_TARGET;
-   buffer->fb_state[1].cbufs[0] = idct->pipe->create_surface(
-      idct->pipe, buffer->destination, &template);
-
-   if (!buffer->fb_state[1].cbufs[0])
-      goto error_transpose_surface;
+   buffer->viewport[1].scale[0] = destination->texture->width0;
+   buffer->viewport[1].scale[1] = destination->texture->height0;
 
    for(i = 0; i < 2; ++i) {
       buffer->viewport[i].scale[2] = 1;
@@ -705,17 +687,7 @@ vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer)
       buffer->fb_state[i].zsbuf = NULL;
    }
 
-   return buffer->destination;
-
-error_transpose_surface:
-   pipe_surface_reference(&buffer->fb_state[1].cbufs[0], NULL);
-
-error_matrix_surfaces:
-   for(i = 0; i < NR_RENDER_TARGETS; ++i)
-      pipe_surface_reference(&buffer->fb_state[0].cbufs[i], NULL);
-
-error_textures:
-   return NULL;
+   return true;
 }
 
 void
@@ -730,25 +702,29 @@ vl_idct_cleanup_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer)
 
    pipe_surface_reference(&buffer->fb_state[1].cbufs[0], NULL);
 
-   cleanup_textures(idct, buffer);
+   cleanup_intermediate(idct, buffer);
 }
 
 void
 vl_idct_map_buffers(struct vl_idct *idct, struct vl_idct_buffer *buffer)
 {
+   struct pipe_resource *tex;
+
    assert(idct && buffer);
 
+   tex = buffer->sampler_views.individual.source->texture;
+
    struct pipe_box rect =
    {
       0, 0, 0,
-      buffer->textures.individual.source->width0,
-      buffer->textures.individual.source->height0,
+      tex->width0,
+      tex->height0,
       1
    };
 
    buffer->tex_transfer = idct->pipe->get_transfer
    (
-      idct->pipe, buffer->textures.individual.source,
+      idct->pipe, tex,
       0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
       &rect
    );
index 14f66f858eb638e27ab2b8007d2427e28fc5dec2..e0d441265fffffafc4007d275d942315322e1069 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <pipe/p_state.h>
 #include "vl_vertex_buffers.h"
+#include "vl_ycbcr_buffer.h"
 
 /* shader based inverse distinct cosinus transformation
  * expect usage of vl_vertex_buffers as a todo list
@@ -49,7 +50,7 @@ struct vl_idct
    void *matrix_vs, *transpose_vs;
    void *matrix_fs, *transpose_fs;
 
-   struct pipe_resource *matrix;
+   struct pipe_sampler_view *matrix;
 };
 
 /* a set of buffers to work with */
@@ -58,8 +59,6 @@ struct vl_idct_buffer
    struct pipe_viewport_state viewport[2];
    struct pipe_framebuffer_state fb_state[2];
 
-   struct pipe_resource *destination;
-
    union
    {
       struct pipe_sampler_view *all[4];
@@ -70,34 +69,25 @@ struct vl_idct_buffer
       } individual;
    } sampler_views;
 
-   union
-   {
-      struct pipe_resource *all[4];
-      struct pipe_resource *stage[2][2];
-      struct {
-         struct pipe_resource *matrix, *source;
-         struct pipe_resource *transpose, *intermediate;
-      } individual;
-   } textures;
-
    struct pipe_transfer *tex_transfer;
    short *texels;
 };
 
 /* upload the idct matrix, which can be shared by all idct instances of a pipe */
-struct pipe_resource *vl_idct_upload_matrix(struct pipe_context *pipe);
+struct pipe_sampler_view *vl_idct_upload_matrix(struct pipe_context *pipe);
 
 /* init an idct instance */
 bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe,
                   unsigned buffer_width, unsigned buffer_height,
                   unsigned blocks_x, unsigned blocks_y,
-                  int color_swizzle, struct pipe_resource *matrix);
+                  int color_swizzle, struct pipe_sampler_view *matrix);
 
 /* destroy an idct instance */
 void vl_idct_cleanup(struct vl_idct *idct);
 
 /* init a buffer assosiated with agiven idct instance */
-struct pipe_resource *vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer);
+bool vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer,
+                         struct pipe_sampler_view *source, struct pipe_surface *destination);
 
 /* cleanup a buffer of an idct instance */
 void vl_idct_cleanup_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer);
index 7fd3a0377c916833eb05c15fa16df46c93263e15..004d79d732462663d07142aef5407f18192fda75 100644 (file)
@@ -268,12 +268,13 @@ static struct pipe_video_buffer *
 vl_mpeg12_create_buffer(struct pipe_video_context *vpipe)
 {
    struct vl_mpeg12_context *ctx = (struct vl_mpeg12_context*)vpipe;
-   struct pipe_resource *y, *cr, *cb;
    struct vl_mpeg12_buffer *buffer;
 
    struct pipe_resource res_template, *resource;
    struct pipe_surface surf_template;
    struct pipe_sampler_view sv_template;
+   struct vl_ycbcr_sampler_views *idct_views;
+   struct vl_ycbcr_surfaces *idct_surfaces;
 
    assert(ctx);
 
@@ -329,22 +330,50 @@ vl_mpeg12_create_buffer(struct pipe_video_context *vpipe)
 
    buffer->vertex_bufs.individual.stream = vl_vb_init(&buffer->vertex_stream, ctx->pipe,
                                                       ctx->vertex_buffer_size);
-   if (!(y = vl_idct_init_buffer(&ctx->idct_y, &buffer->idct_y))) {
+
+   if (!vl_ycbcr_buffer_init(&buffer->idct_source, ctx->pipe,
+                             ctx->buffer_width, ctx->buffer_height,
+                             ctx->base.chroma_format,
+                             PIPE_FORMAT_R16G16B16A16_SNORM,
+                             PIPE_USAGE_STREAM)) {
+      FREE(buffer);
+      return NULL;
+   }
+
+   if (!vl_ycbcr_buffer_init(&buffer->idct_2_mc, ctx->pipe,
+                             ctx->buffer_width, ctx->buffer_height,
+                             ctx->base.chroma_format,
+                             PIPE_FORMAT_R16_SNORM,
+                             PIPE_USAGE_STATIC)) {
+      FREE(buffer);
+      return NULL;
+   }
+
+   idct_views = vl_ycbcr_get_sampler_views(&buffer->idct_source);
+   idct_surfaces = vl_ycbcr_get_surfaces(&buffer->idct_2_mc);
+
+   if (!vl_idct_init_buffer(&ctx->idct_y, &buffer->idct_y,
+                            idct_views->y, idct_surfaces->y)) {
       FREE(buffer);
       return NULL;
    }
 
-   if (!(cr = vl_idct_init_buffer(&ctx->idct_cr, &buffer->idct_cr))) {
+   if (!vl_idct_init_buffer(&ctx->idct_cb, &buffer->idct_cb,
+                            idct_views->cb, idct_surfaces->cb)) {
       FREE(buffer);
       return NULL;
    }
 
-   if (!(cb = vl_idct_init_buffer(&ctx->idct_cb, &buffer->idct_cb))) {
+   if (!vl_idct_init_buffer(&ctx->idct_cr, &buffer->idct_cr,
+                            idct_views->cr, idct_surfaces->cr)) {
       FREE(buffer);
       return NULL;
    }
 
-   if(!vl_mpeg12_mc_init_buffer(&ctx->mc_renderer, &buffer->mc, y, cr, cb)) {
+   if(!vl_mpeg12_mc_init_buffer(&ctx->mc_renderer, &buffer->mc,
+                                buffer->idct_2_mc.resources.y,
+                                buffer->idct_2_mc.resources.cr,
+                                buffer->idct_2_mc.resources.cb)) {
       FREE(buffer);
       return NULL;
    }
@@ -572,7 +601,7 @@ static bool
 init_idct(struct vl_mpeg12_context *ctx, unsigned buffer_width, unsigned buffer_height)
 {
    unsigned chroma_width, chroma_height, chroma_blocks_x, chroma_blocks_y;
-   struct pipe_resource *idct_matrix;
+   struct pipe_sampler_view *idct_matrix;
 
    /* TODO: Implement 422, 444 */
    assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
index e4236adcec3caa0fa9f77c1ea9224d4f8d72b949..d1af5cd2ac378f182bf62cefa45d493bdbb59ffc 100644 (file)
@@ -32,6 +32,7 @@
 #include "vl_idct.h"
 #include "vl_mpeg12_mc_renderer.h"
 #include "vl_compositor.h"
+#include "vl_ycbcr_buffer.h"
 
 struct pipe_screen;
 struct pipe_context;
@@ -62,6 +63,10 @@ struct vl_mpeg12_context
 struct vl_mpeg12_buffer
 {
    struct pipe_video_buffer base;
+
+   struct vl_ycbcr_buffer idct_source;
+   struct vl_ycbcr_buffer idct_2_mc;
+
    struct pipe_surface *surface;
    struct pipe_sampler_view *sampler_view;
 
diff --git a/src/gallium/auxiliary/vl/vl_ycbcr_buffer.c b/src/gallium/auxiliary/vl/vl_ycbcr_buffer.c
new file mode 100644 (file)
index 0000000..5618389
--- /dev/null
@@ -0,0 +1,191 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Christian König.
+ * 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
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * 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.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * 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 "vl_ycbcr_buffer.h"
+#include <util/u_format.h>
+#include <util/u_inlines.h>
+#include <util/u_sampler.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_context.h>
+#include <assert.h>
+
+bool vl_ycbcr_buffer_init(struct vl_ycbcr_buffer *buffer,
+                          struct pipe_context *pipe,
+                          unsigned width, unsigned height,
+                          enum pipe_video_chroma_format chroma_format,
+                          enum pipe_format resource_format,
+                          unsigned usage)
+{
+   struct pipe_resource templ;
+
+   assert(buffer && pipe);
+
+   memset(buffer, 0, sizeof(struct vl_ycbcr_buffer));
+   buffer->pipe = pipe;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_TEXTURE_2D;
+   templ.format = resource_format;
+   templ.width0 = width / util_format_get_nr_components(resource_format);
+   templ.height0 = height;
+   templ.depth0 = 1;
+   templ.array_size = 1;
+   templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+   templ.usage = usage;
+
+   buffer->resources.y = pipe->screen->resource_create(pipe->screen, &templ);
+   if (!buffer->resources.y)
+      goto error_resource_y;
+
+   if (chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
+      templ.width0 /= 2;
+      templ.height0 /= 2;
+   } else if (chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
+      templ.height0 /= 2;
+   }
+
+   buffer->resources.cb = pipe->screen->resource_create(pipe->screen, &templ);
+   if (!buffer->resources.cb)
+      goto error_resource_cb;
+
+   buffer->resources.cr = pipe->screen->resource_create(pipe->screen, &templ);
+   if (!buffer->resources.cr)
+      goto error_resource_cr;
+
+   return true;
+
+error_resource_cr:
+   pipe_resource_reference(&buffer->resources.cb, NULL);
+
+error_resource_cb:
+   pipe_resource_reference(&buffer->resources.y, NULL);
+
+error_resource_y:
+   return false;
+}
+
+struct vl_ycbcr_sampler_views *vl_ycbcr_get_sampler_views(struct vl_ycbcr_buffer *buffer)
+{
+   struct pipe_sampler_view sv_templ;
+   struct pipe_context *pipe;
+
+   assert(buffer);
+
+   pipe = buffer->pipe;
+
+   if (!buffer->sampler_views.y) {
+      memset(&sv_templ, 0, sizeof(sv_templ));
+      u_sampler_view_default_template(&sv_templ, buffer->resources.y, buffer->resources.y->format);
+      buffer->sampler_views.y = pipe->create_sampler_view(pipe, buffer->resources.y, &sv_templ);
+      if (!buffer->sampler_views.y)
+         goto error;
+   }
+
+   if (!buffer->sampler_views.cb) {
+      memset(&sv_templ, 0, sizeof(sv_templ));
+      u_sampler_view_default_template(&sv_templ, buffer->resources.cb, buffer->resources.cb->format);
+      buffer->sampler_views.cb = pipe->create_sampler_view(pipe, buffer->resources.cb, &sv_templ);
+      if (!buffer->sampler_views.cb)
+         goto error;
+   }
+
+   if (!buffer->sampler_views.cr) {
+      memset(&sv_templ, 0, sizeof(sv_templ));
+      u_sampler_view_default_template(&sv_templ, buffer->resources.cr, buffer->resources.cr->format);
+      buffer->sampler_views.cr = pipe->create_sampler_view(pipe, buffer->resources.cr, &sv_templ);
+      if (!buffer->sampler_views.cr)
+         goto error;
+   }
+
+   return &buffer->sampler_views;
+
+error:
+   pipe_sampler_view_reference(&buffer->sampler_views.y, NULL);
+   pipe_sampler_view_reference(&buffer->sampler_views.cb, NULL);
+   pipe_sampler_view_reference(&buffer->sampler_views.cr, NULL);
+   return NULL;
+}
+
+struct vl_ycbcr_surfaces *vl_ycbcr_get_surfaces(struct vl_ycbcr_buffer *buffer)
+{
+   struct pipe_surface surf_templ;
+   struct pipe_context *pipe;
+
+   assert(buffer);
+
+   pipe = buffer->pipe;
+
+   if (!buffer->surfaces.y) {
+      memset(&surf_templ, 0, sizeof(surf_templ));
+      surf_templ.format = buffer->resources.y->format;
+      surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+      buffer->surfaces.y = pipe->create_surface(pipe, buffer->resources.y, &surf_templ);
+      if (!buffer->surfaces.y)
+         goto error;
+   }
+
+   if (!buffer->surfaces.cb) {
+      memset(&surf_templ, 0, sizeof(surf_templ));
+      surf_templ.format = buffer->resources.cb->format;
+      surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+      buffer->surfaces.cb = pipe->create_surface(pipe, buffer->resources.cb, &surf_templ);
+      if (!buffer->surfaces.cb)
+         goto error;
+   }
+
+   if (!buffer->surfaces.cr) {
+      memset(&surf_templ, 0, sizeof(surf_templ));
+      surf_templ.format = buffer->resources.cr->format;
+      surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+      buffer->surfaces.cr = pipe->create_surface(pipe, buffer->resources.cr, &surf_templ);
+      if (!buffer->surfaces.cr)
+         goto error;
+   }
+
+   return &buffer->surfaces;
+
+error:
+   pipe_surface_reference(&buffer->surfaces.y, NULL);
+   pipe_surface_reference(&buffer->surfaces.cb, NULL);
+   pipe_surface_reference(&buffer->surfaces.cr, NULL);
+   return NULL;
+}
+
+void vl_ycbcr_buffer_cleanup(struct vl_ycbcr_buffer *buffer)
+{
+   pipe_surface_reference(&buffer->surfaces.y, NULL);
+   pipe_surface_reference(&buffer->surfaces.cb, NULL);
+   pipe_surface_reference(&buffer->surfaces.cr, NULL);
+
+   pipe_sampler_view_reference(&buffer->sampler_views.y, NULL);
+   pipe_sampler_view_reference(&buffer->sampler_views.cb, NULL);
+   pipe_sampler_view_reference(&buffer->sampler_views.cr, NULL);
+
+   pipe_resource_reference(&buffer->resources.y, NULL);
+   pipe_resource_reference(&buffer->resources.cb, NULL);
+   pipe_resource_reference(&buffer->resources.cr, NULL);
+}
diff --git a/src/gallium/auxiliary/vl/vl_ycbcr_buffer.h b/src/gallium/auxiliary/vl/vl_ycbcr_buffer.h
new file mode 100644 (file)
index 0000000..a116ed2
--- /dev/null
@@ -0,0 +1,89 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Christian König.
+ * 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
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * 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.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * 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 vl_ycbcr_buffer_h
+#define vl_ycbcr_buffer_h
+
+#include <pipe/p_state.h>
+
+/**
+ * implementation of a planar ycbcr buffer
+ */
+
+/* resources of a buffer */
+struct vl_ycbcr_resources
+{
+   struct pipe_resource *y, *cb, *cr;
+};
+
+/* sampler views of a buffer */
+struct vl_ycbcr_sampler_views
+{
+   struct pipe_sampler_view *y, *cb, *cr;
+};
+
+/* surfaces of a buffer */
+struct vl_ycbcr_surfaces
+{
+   struct pipe_surface *y, *cb, *cr;
+};
+
+/* planar buffer for vl data upload and manipulation */
+struct vl_ycbcr_buffer
+{
+   struct pipe_context           *pipe;
+   struct vl_ycbcr_resources     resources;
+   struct vl_ycbcr_sampler_views sampler_views;
+   struct vl_ycbcr_surfaces      surfaces;
+};
+
+/**
+ * initialize a buffer, creating its resources
+ */
+bool vl_ycbcr_buffer_init(struct vl_ycbcr_buffer *buffer,
+                          struct pipe_context *pipe,
+                          unsigned width, unsigned height,
+                          enum pipe_video_chroma_format chroma_format,
+                          enum pipe_format resource_format,
+                          unsigned usage);
+
+/**
+ * create default sampler views for the buffer on demand
+ */
+struct vl_ycbcr_sampler_views *vl_ycbcr_get_sampler_views(struct vl_ycbcr_buffer *buffer);
+
+/**
+ * create default surfaces for the buffer on demand
+ */
+struct vl_ycbcr_surfaces *vl_ycbcr_get_surfaces(struct vl_ycbcr_buffer *buffer);
+
+/**
+ * cleanup the buffer destroying all its resources
+ */
+void vl_ycbcr_buffer_cleanup(struct vl_ycbcr_buffer *buffer);
+
+#endif