summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/vl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/vl')
-rw-r--r--src/gallium/auxiliary/vl/vl_idct.c240
-rw-r--r--src/gallium/auxiliary/vl/vl_idct.h22
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_context.c41
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_context.h5
-rw-r--r--src/gallium/auxiliary/vl/vl_ycbcr_buffer.c191
-rw-r--r--src/gallium/auxiliary/vl/vl_ycbcr_buffer.h89
6 files changed, 434 insertions, 154 deletions
diff --git a/src/gallium/auxiliary/vl/vl_idct.c b/src/gallium/auxiliary/vl/vl_idct.c
index 075b892628f..8cfb56ea416 100644
--- a/src/gallium/auxiliary/vl/vl_idct.c
+++ b/src/gallium/auxiliary/vl/vl_idct.c
@@ -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
);
diff --git a/src/gallium/auxiliary/vl/vl_idct.h b/src/gallium/auxiliary/vl/vl_idct.h
index 14f66f858eb..e0d441265ff 100644
--- a/src/gallium/auxiliary/vl/vl_idct.h
+++ b/src/gallium/auxiliary/vl/vl_idct.h
@@ -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);
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_context.c b/src/gallium/auxiliary/vl/vl_mpeg12_context.c
index 7fd3a0377c9..004d79d7324 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_context.c
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_context.c
@@ -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);
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_context.h b/src/gallium/auxiliary/vl/vl_mpeg12_context.h
index e4236adcec3..d1af5cd2ac3 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_context.h
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_context.h
@@ -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
index 00000000000..56183891f9b
--- /dev/null
+++ b/src/gallium/auxiliary/vl/vl_ycbcr_buffer.c
@@ -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
index 00000000000..a116ed2a882
--- /dev/null
+++ b/src/gallium/auxiliary/vl/vl_ycbcr_buffer.h
@@ -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