[g3dvl] introduction of ycbcr buffers

Moves most of the buffer creation out of the idct code.
This commit is contained in:
Christian König 2011-03-27 19:43:02 +02:00
parent 5a351e5129
commit 020328ca32
7 changed files with 433 additions and 152 deletions

View 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 \

View 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;
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;
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;
tex = idct->pipe->screen->resource_create(idct->pipe->screen, &tex_templ);
if (!tex)
goto error_tex;
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(&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;
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;
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);
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;
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, &template);
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
);

View 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);

View 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 (!(cr = vl_idct_init_buffer(&ctx->idct_cr, &buffer->idct_cr))) {
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;
}
if (!(cb = vl_idct_init_buffer(&ctx->idct_cb, &buffer->idct_cb))) {
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(!vl_mpeg12_mc_init_buffer(&ctx->mc_renderer, &buffer->mc, y, cr, cb)) {
if (!vl_idct_init_buffer(&ctx->idct_cb, &buffer->idct_cb,
idct_views->cb, idct_surfaces->cb)) {
FREE(buffer);
return NULL;
}
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,
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);

View 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;

View file

@ -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);
}

View file

@ -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