diff options
-rw-r--r-- | src/gallium/auxiliary/Makefile | 3 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_idct.c | 240 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_idct.h | 22 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_mpeg12_context.c | 41 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_mpeg12_context.h | 5 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_ycbcr_buffer.c | 191 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_ycbcr_buffer.h | 89 |
7 files changed, 436 insertions, 155 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 869b2d486a4..0464df84e12 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -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 \ 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 |