/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_compositor.c |
---|
0,0 → 1,1161 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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 <assert.h> |
#include "pipe/p_compiler.h" |
#include "pipe/p_context.h" |
#include "util/u_memory.h" |
#include "util/u_draw.h" |
#include "util/u_surface.h" |
#include "util/u_upload_mgr.h" |
#include "tgsi/tgsi_ureg.h" |
#include "vl_csc.h" |
#include "vl_types.h" |
#include "vl_compositor.h" |
#define MIN_DIRTY (0) |
#define MAX_DIRTY (1 << 15) |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_COLOR = 0, |
VS_O_VTEX = 0, |
VS_O_VTOP, |
VS_O_VBOTTOM, |
}; |
static void * |
create_vert_shader(struct vl_compositor *c) |
{ |
struct ureg_program *shader; |
struct ureg_src vpos, vtex, color; |
struct ureg_dst tmp; |
struct ureg_dst o_vpos, o_vtex, o_color; |
struct ureg_dst o_vtop, o_vbottom; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return false; |
vpos = ureg_DECL_vs_input(shader, 0); |
vtex = ureg_DECL_vs_input(shader, 1); |
color = ureg_DECL_vs_input(shader, 2); |
tmp = ureg_DECL_temporary(shader); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR); |
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); |
o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP); |
o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM); |
/* |
* o_vpos = vpos |
* o_vtex = vtex |
* o_color = color |
*/ |
ureg_MOV(shader, o_vpos, vpos); |
ureg_MOV(shader, o_vtex, vtex); |
ureg_MOV(shader, o_color, color); |
/* |
* tmp.x = vtex.w / 2 |
* tmp.y = vtex.w / 4 |
* |
* o_vtop.x = vtex.x |
* o_vtop.y = vtex.y * tmp.x + 0.25f |
* o_vtop.z = vtex.y * tmp.y + 0.25f |
* o_vtop.w = 1 / tmp.x |
* |
* o_vbottom.x = vtex.x |
* o_vbottom.y = vtex.y * tmp.x - 0.25f |
* o_vbottom.z = vtex.y * tmp.y - 0.25f |
* o_vbottom.w = 1 / tmp.y |
*/ |
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), |
ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f)); |
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), |
ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.25f)); |
ureg_MOV(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_X), vtex); |
ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, 0.25f)); |
ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.25f)); |
ureg_RCP(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_W), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); |
ureg_MOV(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_X), vtex); |
ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, -0.25f)); |
ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, -0.25f)); |
ureg_RCP(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_W), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, c->pipe); |
} |
static void * |
create_frag_shader_video_buffer(struct vl_compositor *c) |
{ |
struct ureg_program *shader; |
struct ureg_src tc; |
struct ureg_src csc[3]; |
struct ureg_src sampler[3]; |
struct ureg_dst texel; |
struct ureg_dst fragment; |
unsigned i; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return false; |
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
for (i = 0; i < 3; ++i) { |
csc[i] = ureg_DECL_constant(shader, i); |
sampler[i] = ureg_DECL_sampler(shader, i); |
} |
texel = ureg_DECL_temporary(shader); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* |
* texel.xyz = tex(tc, sampler[i]) |
* fragment = csc * texel |
*/ |
for (i = 0; i < 3; ++i) |
ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D_ARRAY, tc, sampler[i]); |
ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); |
for (i = 0; i < 3; ++i) |
ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); |
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); |
ureg_release_temporary(shader, texel); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, c->pipe); |
} |
static void * |
create_frag_shader_weave(struct vl_compositor *c) |
{ |
struct ureg_program *shader; |
struct ureg_src i_tc[2]; |
struct ureg_src csc[3]; |
struct ureg_src sampler[3]; |
struct ureg_dst t_tc[2]; |
struct ureg_dst t_texel[2]; |
struct ureg_dst o_fragment; |
unsigned i, j; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return false; |
i_tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR); |
i_tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR); |
for (i = 0; i < 3; ++i) { |
csc[i] = ureg_DECL_constant(shader, i); |
sampler[i] = ureg_DECL_sampler(shader, i); |
} |
for (i = 0; i < 2; ++i) { |
t_tc[i] = ureg_DECL_temporary(shader); |
t_texel[i] = ureg_DECL_temporary(shader); |
} |
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* calculate the texture offsets |
* t_tc.x = i_tc.x |
* t_tc.y = (round(i_tc.y - 0.5) + 0.5) / height * 2 |
*/ |
for (i = 0; i < 2; ++i) { |
ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_X), i_tc[i]); |
ureg_SUB(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), |
i_tc[i], ureg_imm1f(shader, 0.5f)); |
ureg_ROUND(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), ureg_src(t_tc[i])); |
ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_W), |
ureg_imm1f(shader, i ? 1.0f : 0.0f)); |
ureg_ADD(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), |
ureg_src(t_tc[i]), ureg_imm1f(shader, 0.5f)); |
ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Y), |
ureg_src(t_tc[i]), ureg_scalar(i_tc[0], TGSI_SWIZZLE_W)); |
ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Z), |
ureg_src(t_tc[i]), ureg_scalar(i_tc[1], TGSI_SWIZZLE_W)); |
} |
/* fetch the texels |
* texel[0..1].x = tex(t_tc[0..1][0]) |
* texel[0..1].y = tex(t_tc[0..1][1]) |
* texel[0..1].z = tex(t_tc[0..1][2]) |
*/ |
for (i = 0; i < 2; ++i) |
for (j = 0; j < 3; ++j) { |
struct ureg_src src = ureg_swizzle(ureg_src(t_tc[i]), |
TGSI_SWIZZLE_X, j ? TGSI_SWIZZLE_Z : TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W); |
ureg_TEX(shader, ureg_writemask(t_texel[i], TGSI_WRITEMASK_X << j), |
TGSI_TEXTURE_2D_ARRAY, src, sampler[j]); |
} |
/* calculate linear interpolation factor |
* factor = |round(i_tc.y) - i_tc.y| * 2 |
*/ |
ureg_ROUND(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), i_tc[0]); |
ureg_ADD(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), |
ureg_src(t_tc[0]), ureg_negate(i_tc[0])); |
ureg_MUL(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), |
ureg_abs(ureg_src(t_tc[0])), ureg_imm1f(shader, 2.0f)); |
ureg_LRP(shader, t_texel[0], ureg_swizzle(ureg_src(t_tc[0]), |
TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z), |
ureg_src(t_texel[0]), ureg_src(t_texel[1])); |
/* and finally do colour space transformation |
* fragment = csc * texel |
*/ |
ureg_MOV(shader, ureg_writemask(t_texel[0], TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); |
for (i = 0; i < 3; ++i) |
ureg_DP4(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(t_texel[0])); |
ureg_MOV(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); |
for (i = 0; i < 2; ++i) { |
ureg_release_temporary(shader, t_texel[i]); |
ureg_release_temporary(shader, t_tc[i]); |
} |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, c->pipe); |
} |
static void * |
create_frag_shader_palette(struct vl_compositor *c, bool include_cc) |
{ |
struct ureg_program *shader; |
struct ureg_src csc[3]; |
struct ureg_src tc; |
struct ureg_src sampler; |
struct ureg_src palette; |
struct ureg_dst texel; |
struct ureg_dst fragment; |
unsigned i; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return false; |
for (i = 0; include_cc && i < 3; ++i) |
csc[i] = ureg_DECL_constant(shader, i); |
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 0); |
palette = ureg_DECL_sampler(shader, 1); |
texel = ureg_DECL_temporary(shader); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* |
* texel = tex(tc, sampler) |
* fragment.xyz = tex(texel, palette) * csc |
* fragment.a = texel.a |
*/ |
ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler); |
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(texel)); |
if (include_cc) { |
ureg_TEX(shader, texel, TGSI_TEXTURE_1D, ureg_src(texel), palette); |
for (i = 0; i < 3; ++i) |
ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); |
} else { |
ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), |
TGSI_TEXTURE_1D, ureg_src(texel), palette); |
} |
ureg_release_temporary(shader, texel); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, c->pipe); |
} |
static void * |
create_frag_shader_rgba(struct vl_compositor *c) |
{ |
struct ureg_program *shader; |
struct ureg_src tc, color, sampler; |
struct ureg_dst texel, fragment; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return false; |
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
color = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 0); |
texel = ureg_DECL_temporary(shader); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* |
* fragment = tex(tc, sampler) |
*/ |
ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler); |
ureg_MUL(shader, fragment, ureg_src(texel), color); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, c->pipe); |
} |
static bool |
init_shaders(struct vl_compositor *c) |
{ |
assert(c); |
c->vs = create_vert_shader(c); |
if (!c->vs) { |
debug_printf("Unable to create vertex shader.\n"); |
return false; |
} |
c->fs_video_buffer = create_frag_shader_video_buffer(c); |
if (!c->fs_video_buffer) { |
debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n"); |
return false; |
} |
c->fs_weave = create_frag_shader_weave(c); |
if (!c->fs_weave) { |
debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n"); |
return false; |
} |
c->fs_palette.yuv = create_frag_shader_palette(c, true); |
if (!c->fs_palette.yuv) { |
debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n"); |
return false; |
} |
c->fs_palette.rgb = create_frag_shader_palette(c, false); |
if (!c->fs_palette.rgb) { |
debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n"); |
return false; |
} |
c->fs_rgba = create_frag_shader_rgba(c); |
if (!c->fs_rgba) { |
debug_printf("Unable to create RGB-to-RGB fragment shader.\n"); |
return false; |
} |
return true; |
} |
static void cleanup_shaders(struct vl_compositor *c) |
{ |
assert(c); |
c->pipe->delete_vs_state(c->pipe, c->vs); |
c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer); |
c->pipe->delete_fs_state(c->pipe, c->fs_weave); |
c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv); |
c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb); |
c->pipe->delete_fs_state(c->pipe, c->fs_rgba); |
} |
static bool |
init_pipe_state(struct vl_compositor *c) |
{ |
struct pipe_rasterizer_state rast; |
struct pipe_sampler_state sampler; |
struct pipe_blend_state blend; |
struct pipe_depth_stencil_alpha_state dsa; |
unsigned i; |
assert(c); |
c->fb_state.nr_cbufs = 1; |
c->fb_state.zsbuf = NULL; |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_r = PIPE_TEX_WRAP_REPEAT; |
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
c->sampler_linear = c->pipe->create_sampler_state(c->pipe, &sampler); |
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
c->sampler_nearest = c->pipe->create_sampler_state(c->pipe, &sampler); |
memset(&blend, 0, sizeof blend); |
blend.independent_blend_enable = 0; |
blend.rt[0].blend_enable = 0; |
blend.logicop_enable = 0; |
blend.logicop_func = PIPE_LOGICOP_CLEAR; |
blend.rt[0].colormask = PIPE_MASK_RGBA; |
blend.dither = 0; |
c->blend_clear = c->pipe->create_blend_state(c->pipe, &blend); |
blend.rt[0].blend_enable = 1; |
blend.rt[0].rgb_func = PIPE_BLEND_ADD; |
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; |
blend.rt[0].alpha_func = PIPE_BLEND_ADD; |
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
c->blend_add = c->pipe->create_blend_state(c->pipe, &blend); |
memset(&rast, 0, sizeof rast); |
rast.flatshade = 0; |
rast.front_ccw = 1; |
rast.cull_face = PIPE_FACE_NONE; |
rast.fill_back = PIPE_POLYGON_MODE_FILL; |
rast.fill_front = PIPE_POLYGON_MODE_FILL; |
rast.scissor = 1; |
rast.line_width = 1; |
rast.point_size_per_vertex = 1; |
rast.offset_units = 1; |
rast.offset_scale = 1; |
rast.half_pixel_center = 1; |
rast.bottom_edge_rule = 1; |
rast.depth_clip = 1; |
c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast); |
memset(&dsa, 0, sizeof dsa); |
dsa.depth.enabled = 0; |
dsa.depth.writemask = 0; |
dsa.depth.func = PIPE_FUNC_ALWAYS; |
for (i = 0; i < 2; ++i) { |
dsa.stencil[i].enabled = 0; |
dsa.stencil[i].func = PIPE_FUNC_ALWAYS; |
dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; |
dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; |
dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; |
dsa.stencil[i].valuemask = 0; |
dsa.stencil[i].writemask = 0; |
} |
dsa.alpha.enabled = 0; |
dsa.alpha.func = PIPE_FUNC_ALWAYS; |
dsa.alpha.ref_value = 0; |
c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa); |
c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa); |
return true; |
} |
static void cleanup_pipe_state(struct vl_compositor *c) |
{ |
assert(c); |
/* Asserted in softpipe_delete_fs_state() for some reason */ |
c->pipe->bind_vs_state(c->pipe, NULL); |
c->pipe->bind_fs_state(c->pipe, NULL); |
c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa); |
c->pipe->delete_sampler_state(c->pipe, c->sampler_linear); |
c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest); |
c->pipe->delete_blend_state(c->pipe, c->blend_clear); |
c->pipe->delete_blend_state(c->pipe, c->blend_add); |
c->pipe->delete_rasterizer_state(c->pipe, c->rast); |
} |
static bool |
init_buffers(struct vl_compositor *c) |
{ |
struct pipe_vertex_element vertex_elems[3]; |
assert(c); |
/* |
* Create our vertex buffer and vertex buffer elements |
*/ |
c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2; |
c->vertex_buf.buffer_offset = 0; |
c->vertex_buf.buffer = NULL; |
vertex_elems[0].src_offset = 0; |
vertex_elems[0].instance_divisor = 0; |
vertex_elems[0].vertex_buffer_index = 0; |
vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; |
vertex_elems[1].src_offset = sizeof(struct vertex2f); |
vertex_elems[1].instance_divisor = 0; |
vertex_elems[1].vertex_buffer_index = 0; |
vertex_elems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; |
vertex_elems[2].src_offset = sizeof(struct vertex2f) + sizeof(struct vertex4f); |
vertex_elems[2].instance_divisor = 0; |
vertex_elems[2].vertex_buffer_index = 0; |
vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; |
c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems); |
return true; |
} |
static void |
cleanup_buffers(struct vl_compositor *c) |
{ |
assert(c); |
c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state); |
pipe_resource_reference(&c->vertex_buf.buffer, NULL); |
} |
static INLINE struct u_rect |
default_rect(struct vl_compositor_layer *layer) |
{ |
struct pipe_resource *res = layer->sampler_views[0]->texture; |
struct u_rect rect = { 0, res->width0, 0, res->height0 * res->array_size }; |
return rect; |
} |
static INLINE struct vertex2f |
calc_topleft(struct vertex2f size, struct u_rect rect) |
{ |
struct vertex2f res = { rect.x0 / size.x, rect.y0 / size.y }; |
return res; |
} |
static INLINE struct vertex2f |
calc_bottomright(struct vertex2f size, struct u_rect rect) |
{ |
struct vertex2f res = { rect.x1 / size.x, rect.y1 / size.y }; |
return res; |
} |
static INLINE void |
calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned height, |
struct u_rect src, struct u_rect dst) |
{ |
struct vertex2f size = { width, height }; |
layer->src.tl = calc_topleft(size, src); |
layer->src.br = calc_bottomright(size, src); |
layer->dst.tl = calc_topleft(size, dst); |
layer->dst.br = calc_bottomright(size, dst); |
layer->zw.x = 0.0f; |
layer->zw.y = size.y; |
} |
static void |
gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer) |
{ |
struct vertex2f tl, tr, br, bl; |
assert(vb && layer); |
switch (layer->rotate) { |
default: |
case VL_COMPOSITOR_ROTATE_0: |
tl = layer->dst.tl; |
tr.x = layer->dst.br.x; |
tr.y = layer->dst.tl.y; |
br = layer->dst.br; |
bl.x = layer->dst.tl.x; |
bl.y = layer->dst.br.y; |
break; |
case VL_COMPOSITOR_ROTATE_90: |
tl.x = layer->dst.br.x; |
tl.y = layer->dst.tl.y; |
tr = layer->dst.br; |
br.x = layer->dst.tl.x; |
br.y = layer->dst.br.y; |
bl = layer->dst.tl; |
break; |
case VL_COMPOSITOR_ROTATE_180: |
tl = layer->dst.br; |
tr.x = layer->dst.tl.x; |
tr.y = layer->dst.br.y; |
br = layer->dst.tl; |
bl.x = layer->dst.br.x; |
bl.y = layer->dst.tl.y; |
break; |
case VL_COMPOSITOR_ROTATE_270: |
tl.x = layer->dst.tl.x; |
tl.y = layer->dst.br.y; |
tr = layer->dst.tl; |
br.x = layer->dst.br.x; |
br.y = layer->dst.tl.y; |
bl = layer->dst.br; |
break; |
} |
vb[ 0].x = tl.x; |
vb[ 0].y = tl.y; |
vb[ 1].x = layer->src.tl.x; |
vb[ 1].y = layer->src.tl.y; |
vb[ 2] = layer->zw; |
vb[ 3].x = layer->colors[0].x; |
vb[ 3].y = layer->colors[0].y; |
vb[ 4].x = layer->colors[0].z; |
vb[ 4].y = layer->colors[0].w; |
vb[ 5].x = tr.x; |
vb[ 5].y = tr.y; |
vb[ 6].x = layer->src.br.x; |
vb[ 6].y = layer->src.tl.y; |
vb[ 7] = layer->zw; |
vb[ 8].x = layer->colors[1].x; |
vb[ 8].y = layer->colors[1].y; |
vb[ 9].x = layer->colors[1].z; |
vb[ 9].y = layer->colors[1].w; |
vb[10].x = br.x; |
vb[10].y = br.y; |
vb[11].x = layer->src.br.x; |
vb[11].y = layer->src.br.y; |
vb[12] = layer->zw; |
vb[13].x = layer->colors[2].x; |
vb[13].y = layer->colors[2].y; |
vb[14].x = layer->colors[2].z; |
vb[14].y = layer->colors[2].w; |
vb[15].x = bl.x; |
vb[15].y = bl.y; |
vb[16].x = layer->src.tl.x; |
vb[16].y = layer->src.br.y; |
vb[17] = layer->zw; |
vb[18].x = layer->colors[3].x; |
vb[18].y = layer->colors[3].y; |
vb[19].x = layer->colors[3].z; |
vb[19].y = layer->colors[3].w; |
} |
static INLINE struct u_rect |
calc_drawn_area(struct vl_compositor_state *s, struct vl_compositor_layer *layer) |
{ |
struct vertex2f tl, br; |
struct u_rect result; |
assert(s && layer); |
// rotate |
switch (layer->rotate) { |
default: |
case VL_COMPOSITOR_ROTATE_0: |
tl = layer->dst.tl; |
br = layer->dst.br; |
break; |
case VL_COMPOSITOR_ROTATE_90: |
tl.x = layer->dst.br.x; |
tl.y = layer->dst.tl.y; |
br.x = layer->dst.tl.x; |
br.y = layer->dst.br.y; |
break; |
case VL_COMPOSITOR_ROTATE_180: |
tl = layer->dst.br; |
br = layer->dst.tl; |
break; |
case VL_COMPOSITOR_ROTATE_270: |
tl.x = layer->dst.tl.x; |
tl.y = layer->dst.br.y; |
br.x = layer->dst.br.x; |
br.y = layer->dst.tl.y; |
break; |
} |
// scale |
result.x0 = tl.x * layer->viewport.scale[0] + layer->viewport.translate[0]; |
result.y0 = tl.y * layer->viewport.scale[1] + layer->viewport.translate[1]; |
result.x1 = br.x * layer->viewport.scale[0] + layer->viewport.translate[0]; |
result.y1 = br.y * layer->viewport.scale[1] + layer->viewport.translate[1]; |
// and clip |
result.x0 = MAX2(result.x0, s->scissor.minx); |
result.y0 = MAX2(result.y0, s->scissor.miny); |
result.x1 = MIN2(result.x1, s->scissor.maxx); |
result.y1 = MIN2(result.y1, s->scissor.maxy); |
return result; |
} |
static void |
gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty) |
{ |
struct vertex2f *vb; |
unsigned i; |
assert(c); |
/* Allocate new memory for vertices. */ |
u_upload_alloc(c->upload, 0, |
c->vertex_buf.stride * VL_COMPOSITOR_MAX_LAYERS * 4, /* size */ |
&c->vertex_buf.buffer_offset, &c->vertex_buf.buffer, |
(void**)&vb); |
for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) { |
if (s->used_layers & (1 << i)) { |
struct vl_compositor_layer *layer = &s->layers[i]; |
gen_rect_verts(vb, layer); |
vb += 20; |
if (!layer->viewport_valid) { |
layer->viewport.scale[0] = c->fb_state.width; |
layer->viewport.scale[1] = c->fb_state.height; |
layer->viewport.translate[0] = 0; |
layer->viewport.translate[1] = 0; |
} |
if (dirty && layer->clearing) { |
struct u_rect drawn = calc_drawn_area(s, layer); |
if ( |
dirty->x0 >= drawn.x0 && |
dirty->y0 >= drawn.y0 && |
dirty->x1 <= drawn.x1 && |
dirty->y1 <= drawn.y1) { |
// We clear the dirty area anyway, no need for clear_render_target |
dirty->x0 = dirty->y0 = MAX_DIRTY; |
dirty->x1 = dirty->y1 = MIN_DIRTY; |
} |
} |
} |
} |
u_upload_unmap(c->upload); |
} |
static void |
draw_layers(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty) |
{ |
unsigned vb_index, i; |
assert(c); |
for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { |
if (s->used_layers & (1 << i)) { |
struct vl_compositor_layer *layer = &s->layers[i]; |
struct pipe_sampler_view **samplers = &layer->sampler_views[0]; |
unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3; |
void *blend = layer->blend ? layer->blend : i ? c->blend_add : c->blend_clear; |
c->pipe->bind_blend_state(c->pipe, blend); |
c->pipe->set_viewport_states(c->pipe, 0, 1, &layer->viewport); |
c->pipe->bind_fs_state(c->pipe, layer->fs); |
c->pipe->bind_sampler_states(c->pipe, PIPE_SHADER_FRAGMENT, 0, |
num_sampler_views, layer->samplers); |
c->pipe->set_sampler_views(c->pipe, PIPE_SHADER_FRAGMENT, 0, |
num_sampler_views, samplers); |
util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4); |
vb_index++; |
if (dirty) { |
// Remember the currently drawn area as dirty for the next draw command |
struct u_rect drawn = calc_drawn_area(s, layer); |
dirty->x0 = MIN2(drawn.x0, dirty->x0); |
dirty->y0 = MIN2(drawn.y0, dirty->y0); |
dirty->x1 = MAX2(drawn.x1, dirty->x1); |
dirty->y1 = MAX2(drawn.y1, dirty->y1); |
} |
} |
} |
} |
void |
vl_compositor_reset_dirty_area(struct u_rect *dirty) |
{ |
assert(dirty); |
dirty->x0 = dirty->y0 = MIN_DIRTY; |
dirty->x1 = dirty->y1 = MAX_DIRTY; |
} |
void |
vl_compositor_set_clear_color(struct vl_compositor_state *s, union pipe_color_union *color) |
{ |
assert(s); |
assert(color); |
s->clear_color = *color; |
} |
void |
vl_compositor_get_clear_color(struct vl_compositor_state *s, union pipe_color_union *color) |
{ |
assert(s); |
assert(color); |
*color = s->clear_color; |
} |
void |
vl_compositor_clear_layers(struct vl_compositor_state *s) |
{ |
unsigned i, j; |
assert(s); |
s->used_layers = 0; |
for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) { |
struct vertex4f v_one = { 1.0f, 1.0f, 1.0f, 1.0f }; |
s->layers[i].clearing = i ? false : true; |
s->layers[i].blend = NULL; |
s->layers[i].fs = NULL; |
s->layers[i].viewport.scale[2] = 1; |
s->layers[i].viewport.translate[2] = 0; |
s->layers[i].rotate = VL_COMPOSITOR_ROTATE_0; |
for ( j = 0; j < 3; j++) |
pipe_sampler_view_reference(&s->layers[i].sampler_views[j], NULL); |
for ( j = 0; j < 4; ++j) |
s->layers[i].colors[j] = v_one; |
} |
} |
void |
vl_compositor_cleanup(struct vl_compositor *c) |
{ |
assert(c); |
u_upload_destroy(c->upload); |
cleanup_buffers(c); |
cleanup_shaders(c); |
cleanup_pipe_state(c); |
} |
void |
vl_compositor_set_csc_matrix(struct vl_compositor_state *s, vl_csc_matrix const *matrix) |
{ |
struct pipe_transfer *buf_transfer; |
assert(s); |
memcpy |
( |
pipe_buffer_map(s->pipe, s->csc_matrix, |
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
&buf_transfer), |
matrix, |
sizeof(vl_csc_matrix) |
); |
pipe_buffer_unmap(s->pipe, buf_transfer); |
} |
void |
vl_compositor_set_dst_clip(struct vl_compositor_state *s, struct u_rect *dst_clip) |
{ |
assert(s); |
s->scissor_valid = dst_clip != NULL; |
if (dst_clip) { |
s->scissor.minx = dst_clip->x0; |
s->scissor.miny = dst_clip->y0; |
s->scissor.maxx = dst_clip->x1; |
s->scissor.maxy = dst_clip->y1; |
} |
} |
void |
vl_compositor_set_layer_blend(struct vl_compositor_state *s, |
unsigned layer, void *blend, |
bool is_clearing) |
{ |
assert(s && blend); |
assert(layer < VL_COMPOSITOR_MAX_LAYERS); |
s->layers[layer].clearing = is_clearing; |
s->layers[layer].blend = blend; |
} |
void |
vl_compositor_set_layer_dst_area(struct vl_compositor_state *s, |
unsigned layer, struct u_rect *dst_area) |
{ |
assert(s); |
assert(layer < VL_COMPOSITOR_MAX_LAYERS); |
s->layers[layer].viewport_valid = dst_area != NULL; |
if (dst_area) { |
s->layers[layer].viewport.scale[0] = dst_area->x1 - dst_area->x0; |
s->layers[layer].viewport.scale[1] = dst_area->y1 - dst_area->y0; |
s->layers[layer].viewport.translate[0] = dst_area->x0; |
s->layers[layer].viewport.translate[1] = dst_area->y0; |
} |
} |
void |
vl_compositor_set_buffer_layer(struct vl_compositor_state *s, |
struct vl_compositor *c, |
unsigned layer, |
struct pipe_video_buffer *buffer, |
struct u_rect *src_rect, |
struct u_rect *dst_rect, |
enum vl_compositor_deinterlace deinterlace) |
{ |
struct pipe_sampler_view **sampler_views; |
unsigned i; |
assert(s && c && buffer); |
assert(layer < VL_COMPOSITOR_MAX_LAYERS); |
s->used_layers |= 1 << layer; |
sampler_views = buffer->get_sampler_view_components(buffer); |
for (i = 0; i < 3; ++i) { |
s->layers[layer].samplers[i] = c->sampler_linear; |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]); |
} |
calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height, |
src_rect ? *src_rect : default_rect(&s->layers[layer]), |
dst_rect ? *dst_rect : default_rect(&s->layers[layer])); |
if (buffer->interlaced) { |
float half_a_line = 0.5f / s->layers[layer].zw.y; |
switch(deinterlace) { |
case VL_COMPOSITOR_WEAVE: |
s->layers[layer].fs = c->fs_weave; |
break; |
case VL_COMPOSITOR_BOB_TOP: |
s->layers[layer].zw.x = 0.0f; |
s->layers[layer].src.tl.y += half_a_line; |
s->layers[layer].src.br.y += half_a_line; |
s->layers[layer].fs = c->fs_video_buffer; |
break; |
case VL_COMPOSITOR_BOB_BOTTOM: |
s->layers[layer].zw.x = 1.0f; |
s->layers[layer].src.tl.y -= half_a_line; |
s->layers[layer].src.br.y -= half_a_line; |
s->layers[layer].fs = c->fs_video_buffer; |
break; |
} |
} else |
s->layers[layer].fs = c->fs_video_buffer; |
} |
void |
vl_compositor_set_palette_layer(struct vl_compositor_state *s, |
struct vl_compositor *c, |
unsigned layer, |
struct pipe_sampler_view *indexes, |
struct pipe_sampler_view *palette, |
struct u_rect *src_rect, |
struct u_rect *dst_rect, |
bool include_color_conversion) |
{ |
assert(s && c && indexes && palette); |
assert(layer < VL_COMPOSITOR_MAX_LAYERS); |
s->used_layers |= 1 << layer; |
s->layers[layer].fs = include_color_conversion ? |
c->fs_palette.yuv : c->fs_palette.rgb; |
s->layers[layer].samplers[0] = c->sampler_linear; |
s->layers[layer].samplers[1] = c->sampler_nearest; |
s->layers[layer].samplers[2] = NULL; |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], indexes); |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], palette); |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL); |
calc_src_and_dst(&s->layers[layer], indexes->texture->width0, indexes->texture->height0, |
src_rect ? *src_rect : default_rect(&s->layers[layer]), |
dst_rect ? *dst_rect : default_rect(&s->layers[layer])); |
} |
void |
vl_compositor_set_rgba_layer(struct vl_compositor_state *s, |
struct vl_compositor *c, |
unsigned layer, |
struct pipe_sampler_view *rgba, |
struct u_rect *src_rect, |
struct u_rect *dst_rect, |
struct vertex4f *colors) |
{ |
unsigned i; |
assert(s && c && rgba); |
assert(layer < VL_COMPOSITOR_MAX_LAYERS); |
s->used_layers |= 1 << layer; |
s->layers[layer].fs = c->fs_rgba; |
s->layers[layer].samplers[0] = c->sampler_linear; |
s->layers[layer].samplers[1] = NULL; |
s->layers[layer].samplers[2] = NULL; |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], rgba); |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], NULL); |
pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL); |
calc_src_and_dst(&s->layers[layer], rgba->texture->width0, rgba->texture->height0, |
src_rect ? *src_rect : default_rect(&s->layers[layer]), |
dst_rect ? *dst_rect : default_rect(&s->layers[layer])); |
if (colors) |
for (i = 0; i < 4; ++i) |
s->layers[layer].colors[i] = colors[i]; |
} |
void |
vl_compositor_set_layer_rotation(struct vl_compositor_state *s, |
unsigned layer, |
enum vl_compositor_rotation rotate) |
{ |
assert(s); |
assert(layer < VL_COMPOSITOR_MAX_LAYERS); |
s->layers[layer].rotate = rotate; |
} |
void |
vl_compositor_render(struct vl_compositor_state *s, |
struct vl_compositor *c, |
struct pipe_surface *dst_surface, |
struct u_rect *dirty_area, |
bool clear_dirty) |
{ |
assert(c); |
assert(dst_surface); |
c->fb_state.width = dst_surface->width; |
c->fb_state.height = dst_surface->height; |
c->fb_state.cbufs[0] = dst_surface; |
if (!s->scissor_valid) { |
s->scissor.minx = 0; |
s->scissor.miny = 0; |
s->scissor.maxx = dst_surface->width; |
s->scissor.maxy = dst_surface->height; |
} |
c->pipe->set_scissor_states(c->pipe, 0, 1, &s->scissor); |
gen_vertex_data(c, s, dirty_area); |
if (clear_dirty && dirty_area && |
(dirty_area->x0 < dirty_area->x1 || dirty_area->y0 < dirty_area->y1)) { |
c->pipe->clear_render_target(c->pipe, dst_surface, &s->clear_color, |
0, 0, dst_surface->width, dst_surface->height); |
dirty_area->x0 = dirty_area->y0 = MAX_DIRTY; |
dirty_area->x1 = dirty_area->y1 = MIN_DIRTY; |
} |
c->pipe->set_framebuffer_state(c->pipe, &c->fb_state); |
c->pipe->bind_vs_state(c->pipe, c->vs); |
c->pipe->set_vertex_buffers(c->pipe, 0, 1, &c->vertex_buf); |
c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state); |
pipe_set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, s->csc_matrix); |
c->pipe->bind_rasterizer_state(c->pipe, c->rast); |
draw_layers(c, s, dirty_area); |
} |
bool |
vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe) |
{ |
assert(c); |
memset(c, 0, sizeof(*c)); |
c->pipe = pipe; |
c->upload = u_upload_create(pipe, 128 * 1024, 4, PIPE_BIND_VERTEX_BUFFER); |
if (!c->upload) |
return false; |
if (!init_pipe_state(c)) { |
u_upload_destroy(c->upload); |
return false; |
} |
if (!init_shaders(c)) { |
u_upload_destroy(c->upload); |
cleanup_pipe_state(c); |
return false; |
} |
if (!init_buffers(c)) { |
u_upload_destroy(c->upload); |
cleanup_shaders(c); |
cleanup_pipe_state(c); |
return false; |
} |
return true; |
} |
bool |
vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pipe) |
{ |
vl_csc_matrix csc_matrix; |
assert(s); |
memset(s, 0, sizeof(*s)); |
s->pipe = pipe; |
s->clear_color.f[0] = s->clear_color.f[1] = 0.0f; |
s->clear_color.f[2] = s->clear_color.f[3] = 0.0f; |
/* |
* Create our fragment shader's constant buffer |
* Const buffer contains the color conversion matrix and bias vectors |
*/ |
/* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */ |
s->csc_matrix = pipe_buffer_create |
( |
pipe->screen, |
PIPE_BIND_CONSTANT_BUFFER, |
PIPE_USAGE_DEFAULT, |
sizeof(csc_matrix) |
); |
vl_compositor_clear_layers(s); |
vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, &csc_matrix); |
vl_compositor_set_csc_matrix(s, (const vl_csc_matrix *)&csc_matrix); |
return true; |
} |
void |
vl_compositor_cleanup_state(struct vl_compositor_state *s) |
{ |
assert(s); |
vl_compositor_clear_layers(s); |
pipe_resource_reference(&s->csc_matrix, NULL); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_compositor.h |
---|
0,0 → 1,261 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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_compositor_h |
#define vl_compositor_h |
#include "pipe/p_state.h" |
#include "pipe/p_video_codec.h" |
#include "pipe/p_video_state.h" |
#include "util/u_rect.h" |
#include "vl_types.h" |
#include "vl_csc.h" |
struct pipe_context; |
/** |
* composing and displaying of image data |
*/ |
#define VL_COMPOSITOR_MAX_LAYERS 16 |
/* deinterlace allgorithem */ |
enum vl_compositor_deinterlace |
{ |
VL_COMPOSITOR_WEAVE, |
VL_COMPOSITOR_BOB_TOP, |
VL_COMPOSITOR_BOB_BOTTOM |
}; |
/* clockwise degree */ |
enum vl_compositor_rotation |
{ |
VL_COMPOSITOR_ROTATE_0, |
VL_COMPOSITOR_ROTATE_90, |
VL_COMPOSITOR_ROTATE_180, |
VL_COMPOSITOR_ROTATE_270 |
}; |
struct vl_compositor_layer |
{ |
bool clearing; |
bool viewport_valid; |
struct pipe_viewport_state viewport; |
void *fs; |
void *samplers[3]; |
void *blend; |
struct pipe_sampler_view *sampler_views[3]; |
struct { |
struct vertex2f tl, br; |
} src, dst; |
struct vertex2f zw; |
struct vertex4f colors[4]; |
enum vl_compositor_rotation rotate; |
}; |
struct vl_compositor_state |
{ |
struct pipe_context *pipe; |
bool scissor_valid; |
struct pipe_scissor_state scissor; |
struct pipe_resource *csc_matrix; |
union pipe_color_union clear_color; |
unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS; |
struct vl_compositor_layer layers[VL_COMPOSITOR_MAX_LAYERS]; |
}; |
struct vl_compositor |
{ |
struct pipe_context *pipe; |
struct u_upload_mgr *upload; |
struct pipe_framebuffer_state fb_state; |
struct pipe_vertex_buffer vertex_buf; |
void *sampler_linear; |
void *sampler_nearest; |
void *blend_clear, *blend_add; |
void *rast; |
void *dsa; |
void *vertex_elems_state; |
void *vs; |
void *fs_video_buffer; |
void *fs_weave; |
void *fs_rgba; |
struct { |
void *rgb; |
void *yuv; |
} fs_palette; |
}; |
/** |
* initialize this compositor |
*/ |
bool |
vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe); |
/** |
* init state bag |
*/ |
bool |
vl_compositor_init_state(struct vl_compositor_state *state, struct pipe_context *pipe); |
/** |
* set yuv -> rgba conversion matrix |
*/ |
void |
vl_compositor_set_csc_matrix(struct vl_compositor_state *settings, const vl_csc_matrix *matrix); |
/** |
* reset dirty area, so it's cleared with the clear colour |
*/ |
void |
vl_compositor_reset_dirty_area(struct u_rect *dirty); |
/** |
* set the clear color |
*/ |
void |
vl_compositor_set_clear_color(struct vl_compositor_state *settings, union pipe_color_union *color); |
/** |
* get the clear color |
*/ |
void |
vl_compositor_get_clear_color(struct vl_compositor_state *settings, union pipe_color_union *color); |
/** |
* set the destination clipping |
*/ |
void |
vl_compositor_set_dst_clip(struct vl_compositor_state *settings, struct u_rect *dst_clip); |
/** |
* set overlay samplers |
*/ |
/*@{*/ |
/** |
* reset all currently set layers |
*/ |
void |
vl_compositor_clear_layers(struct vl_compositor_state *state); |
/** |
* set the blender used to render a layer |
*/ |
void |
vl_compositor_set_layer_blend(struct vl_compositor_state *state, |
unsigned layer, void *blend, bool is_clearing); |
/** |
* set the layer destination area |
*/ |
void |
vl_compositor_set_layer_dst_area(struct vl_compositor_state *settings, |
unsigned layer, struct u_rect *dst_area); |
/** |
* set a video buffer as a layer to render |
*/ |
void |
vl_compositor_set_buffer_layer(struct vl_compositor_state *state, |
struct vl_compositor *compositor, |
unsigned layer, |
struct pipe_video_buffer *buffer, |
struct u_rect *src_rect, |
struct u_rect *dst_rect, |
enum vl_compositor_deinterlace deinterlace); |
/** |
* set a paletted sampler as a layer to render |
*/ |
void |
vl_compositor_set_palette_layer(struct vl_compositor_state *state, |
struct vl_compositor *compositor, |
unsigned layer, |
struct pipe_sampler_view *indexes, |
struct pipe_sampler_view *palette, |
struct u_rect *src_rect, |
struct u_rect *dst_rect, |
bool include_color_conversion); |
/** |
* set a rgba sampler as a layer to render |
*/ |
void |
vl_compositor_set_rgba_layer(struct vl_compositor_state *state, |
struct vl_compositor *compositor, |
unsigned layer, |
struct pipe_sampler_view *rgba, |
struct u_rect *src_rect, |
struct u_rect *dst_rect, |
struct vertex4f *colors); |
/** |
* set the layer rotation |
*/ |
void |
vl_compositor_set_layer_rotation(struct vl_compositor_state *state, |
unsigned layer, |
enum vl_compositor_rotation rotate); |
/*@}*/ |
/** |
* render the layers to the frontbuffer |
*/ |
void |
vl_compositor_render(struct vl_compositor_state *state, |
struct vl_compositor *compositor, |
struct pipe_surface *dst_surface, |
struct u_rect *dirty_area, |
bool clear_dirty); |
/** |
* destroy this compositor |
*/ |
void |
vl_compositor_cleanup(struct vl_compositor *compositor); |
/** |
* destroy this state bag |
*/ |
void |
vl_compositor_cleanup_state(struct vl_compositor_state *state); |
#endif /* vl_compositor_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_csc.c |
---|
0,0 → 1,230 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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 "util/u_math.h" |
#include "util/u_debug.h" |
#include "vl_csc.h" |
/* |
* Color space conversion formulas |
* |
* To convert YCbCr to RGB, |
* vec4 ycbcr, rgb |
* mat44 csc |
* rgb = csc * ycbcr |
* |
* To calculate the color space conversion matrix csc with ProcAmp adjustments, |
* mat44 csc, cstd, procamp, bias |
* csc = cstd * (procamp * bias) |
* |
* Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc) |
* adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full), |
* bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full) |
* |
* To calculate procamp, |
* mat44 procamp, hue, saturation, brightness, contrast |
* procamp = brightness * (saturation * (contrast * hue)) |
* Alternatively, |
* procamp = saturation * (brightness * (contrast * hue)) |
* |
* contrast |
* [ c, 0, 0, 0] |
* [ 0, c, 0, 0] |
* [ 0, 0, c, 0] |
* [ 0, 0, 0, 1] |
* |
* brightness |
* [ 1, 0, 0, b] |
* [ 0, 1, 0, 0] |
* [ 0, 0, 1, 0] |
* [ 0, 0, 0, 1] |
* |
* saturation |
* [ 1, 0, 0, 0] |
* [ 0, s, 0, 0] |
* [ 0, 0, s, 0] |
* [ 0, 0, 0, 1] |
* |
* hue |
* [ 1, 0, 0, 0] |
* [ 0, cos(h), sin(h), 0] |
* [ 0, -sin(h), cos(h), 0] |
* [ 0, 0, 0, 1] |
* |
* procamp |
* [ c, 0, 0, b] |
* [ 0, c*s*cos(h), c*s*sin(h), 0] |
* [ 0, -c*s*sin(h), c*s*cos(h), 0] |
* [ 0, 0, 0, 1] |
* |
* bias |
* [ 1, 0, 0, ybias] |
* [ 0, 1, 0, cbbias] |
* [ 0, 0, 1, crbias] |
* [ 0, 0, 0, 1] |
* |
* csc |
* [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] |
* [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] |
* [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] |
* [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))] |
*/ |
/* |
* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: |
* Y is in [16,235], Cb and Cr are in [16,240] |
* R, G, and B are in [16,235] |
*/ |
static const vl_csc_matrix bt_601 = |
{ |
{ 1.0f, 0.0f, 1.371f, 0.0f, }, |
{ 1.0f, -0.336f, -0.698f, 0.0f, }, |
{ 1.0f, 1.732f, 0.0f, 0.0f, } |
}; |
/* |
* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: |
* Y is in [16,235], Cb and Cr are in [16,240] |
* R, G, and B are in [0,255] |
*/ |
static const vl_csc_matrix bt_601_full = |
{ |
{ 1.164f, 0.0f, 1.596f, 0.0f, }, |
{ 1.164f, -0.391f, -0.813f, 0.0f, }, |
{ 1.164f, 2.018f, 0.0f, 0.0f, } |
}; |
/* |
* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: |
* Y is in [16,235], Cb and Cr are in [16,240] |
* R, G, and B are in [16,235] |
*/ |
static const vl_csc_matrix bt_709 = |
{ |
{ 1.0f, 0.0f, 1.540f, 0.0f, }, |
{ 1.0f, -0.183f, -0.459f, 0.0f, }, |
{ 1.0f, 1.816f, 0.0f, 0.0f, } |
}; |
/* |
* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: |
* Y is in [16,235], Cb and Cr are in [16,240] |
* R, G, and B are in [0,255] |
*/ |
static const vl_csc_matrix bt_709_full = |
{ |
{ 1.164f, 0.0f, 1.793f, 0.0f, }, |
{ 1.164f, -0.213f, -0.534f, 0.0f, }, |
{ 1.164f, 2.115f, 0.0f, 0.0f, } |
}; |
static const vl_csc_matrix smpte240m = |
{ |
{ 1.0f, 0.0f, 1.582f, 0.0f, }, |
{ 1.0f, -0.228f, -0.478f, 0.0f, }, |
{ 1.0f, 1.833f, 0.0f, 0.0f, } |
}; |
static const vl_csc_matrix smpte240m_full = |
{ |
{ 1.164f, 0.0f, 1.794f, 0.0f, }, |
{ 1.164f, -0.258f, -0.543f, 0.0f, }, |
{ 1.164f, 2.079f, 0.0f, 0.0f, } |
}; |
static const vl_csc_matrix identity = |
{ |
{ 1.0f, 0.0f, 0.0f, 0.0f, }, |
{ 0.0f, 1.0f, 0.0f, 0.0f, }, |
{ 0.0f, 0.0f, 1.0f, 0.0f, } |
}; |
const struct vl_procamp vl_default_procamp = { |
0.0f, /* brightness */ |
1.0f, /* contrast */ |
1.0f, /* saturation */ |
0.0f /* hue */ |
}; |
void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, |
struct vl_procamp *procamp, |
bool full_range, |
vl_csc_matrix *matrix) |
{ |
float ybias = full_range ? -16.0f/255.0f : 0.0f; |
float cbbias = -128.0f/255.0f; |
float crbias = -128.0f/255.0f; |
const struct vl_procamp *p = procamp ? procamp : &vl_default_procamp; |
float c = p->contrast; |
float s = p->saturation; |
float b = p->brightness; |
float h = p->hue; |
const vl_csc_matrix *cstd; |
assert(matrix); |
switch (cs) { |
case VL_CSC_COLOR_STANDARD_BT_601: |
cstd = full_range ? &bt_601_full : &bt_601; |
break; |
case VL_CSC_COLOR_STANDARD_BT_709: |
cstd = full_range ? &bt_709_full : &bt_709; |
break; |
case VL_CSC_COLOR_STANDARD_SMPTE_240M: |
cstd = full_range ? &smpte240m_full : &smpte240m; |
break; |
case VL_CSC_COLOR_STANDARD_IDENTITY: |
default: |
assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY); |
memcpy(matrix, identity, sizeof(vl_csc_matrix)); |
return; |
} |
(*matrix)[0][0] = c * (*cstd)[0][0]; |
(*matrix)[0][1] = c * (*cstd)[0][1] * s * cosf(h) - c * (*cstd)[0][2] * s * sinf(h); |
(*matrix)[0][2] = c * (*cstd)[0][2] * s * cosf(h) + c * (*cstd)[0][1] * s * sinf(h); |
(*matrix)[0][3] = (*cstd)[0][3] + (*cstd)[0][0] * (b + c * ybias) + |
(*cstd)[0][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) + |
(*cstd)[0][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h)); |
(*matrix)[1][0] = c * (*cstd)[1][0]; |
(*matrix)[1][1] = c * (*cstd)[1][1] * s * cosf(h) - c * (*cstd)[1][2] * s * sinf(h); |
(*matrix)[1][2] = c * (*cstd)[1][2] * s * cosf(h) + c * (*cstd)[1][1] * s * sinf(h); |
(*matrix)[1][3] = (*cstd)[1][3] + (*cstd)[1][0] * (b + c * ybias) + |
(*cstd)[1][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) + |
(*cstd)[1][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h)); |
(*matrix)[2][0] = c * (*cstd)[2][0]; |
(*matrix)[2][1] = c * (*cstd)[2][1] * s * cosf(h) - c * (*cstd)[2][2] * s * sinf(h); |
(*matrix)[2][2] = c * (*cstd)[2][2] * s * cosf(h) + c * (*cstd)[2][1] * s * sinf(h); |
(*matrix)[2][3] = (*cstd)[2][3] + (*cstd)[2][0] * (b + c * ybias) + |
(*cstd)[2][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) + |
(*cstd)[2][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h)); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_csc.h |
---|
0,0 → 1,58 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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_csc_h |
#define vl_csc_h |
#include "pipe/p_compiler.h" |
typedef float vl_csc_matrix[3][4]; |
struct vl_procamp |
{ |
float brightness; |
float contrast; |
float saturation; |
float hue; |
}; |
enum VL_CSC_COLOR_STANDARD |
{ |
VL_CSC_COLOR_STANDARD_IDENTITY, |
VL_CSC_COLOR_STANDARD_BT_601, |
VL_CSC_COLOR_STANDARD_BT_709, |
VL_CSC_COLOR_STANDARD_SMPTE_240M |
}; |
extern const struct vl_procamp vl_default_procamp; |
void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs, |
struct vl_procamp *procamp, |
bool full_range, |
vl_csc_matrix *matrix); |
#endif /* vl_csc_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_decoder.c |
---|
0,0 → 1,94 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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 "pipe/p_video_codec.h" |
#include "util/u_video.h" |
#include "vl_decoder.h" |
#include "vl_mpeg12_decoder.h" |
bool |
vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile, |
enum pipe_video_entrypoint entrypoint) |
{ |
assert(screen); |
switch (u_reduce_video_profile(profile)) { |
case PIPE_VIDEO_FORMAT_MPEG12: |
return entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE; |
default: |
return false; |
} |
} |
int |
vl_level_supported(struct pipe_screen *screen, enum pipe_video_profile profile) |
{ |
assert(screen); |
switch (profile) { |
case PIPE_VIDEO_PROFILE_MPEG1: |
return 0; |
case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: |
case PIPE_VIDEO_PROFILE_MPEG2_MAIN: |
return 3; |
default: |
return 0; |
} |
} |
struct pipe_video_codec * |
vl_create_decoder(struct pipe_context *pipe, |
const struct pipe_video_codec *templat) |
{ |
unsigned width = templat->width, height = templat->height; |
struct pipe_video_codec temp; |
bool pot_buffers; |
assert(pipe); |
assert(width > 0 && height > 0); |
pot_buffers = !pipe->screen->get_video_param |
( |
pipe->screen, |
templat->profile, |
templat->entrypoint, |
PIPE_VIDEO_CAP_NPOT_TEXTURES |
); |
temp = *templat; |
temp.width = pot_buffers ? util_next_power_of_two(width) : align(width, VL_MACROBLOCK_WIDTH); |
temp.height = pot_buffers ? util_next_power_of_two(height) : align(height, VL_MACROBLOCK_HEIGHT); |
switch (u_reduce_video_profile(temp.profile)) { |
case PIPE_VIDEO_FORMAT_MPEG12: |
return vl_create_mpeg12_decoder(pipe, &temp); |
default: |
return NULL; |
} |
return NULL; |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_decoder.h |
---|
0,0 → 1,54 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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_decoder_h |
#define vl_decoder_h |
#include "pipe/p_video_codec.h" |
/** |
* check if a given profile is supported with shader based decoding |
*/ |
bool |
vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile, |
enum pipe_video_entrypoint entrypoint); |
/** |
* get the maximum supported level for the given profile with shader based decoding |
*/ |
int |
vl_level_supported(struct pipe_screen *screen, enum pipe_video_profile profile); |
/** |
* standard implementation of pipe->create_video_codec |
*/ |
struct pipe_video_codec * |
vl_create_decoder(struct pipe_context *pipe, |
const struct pipe_video_codec *templat); |
#endif /* vl_decoder_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_defines.h |
---|
0,0 → 1,42 |
/************************************************************************** |
* |
* 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 VMWARE 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_defines_h |
#define vl_defines_h |
/* constants usually used with all known codecs */ |
#define VL_MACROBLOCK_WIDTH 16 |
#define VL_MACROBLOCK_HEIGHT 16 |
#define VL_BLOCK_WIDTH 8 |
#define VL_BLOCK_HEIGHT 8 |
#define VL_NUM_COMPONENTS 3 |
#define VL_MAX_SURFACES (VL_NUM_COMPONENTS * 2) |
#define VL_MAX_REF_FRAMES 2 |
#endif |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_deint_filter.c |
---|
0,0 → 1,489 |
/************************************************************************** |
* |
* Copyright 2013 Grigori Goronzy <greg@chown.ath.cx>. |
* 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. |
* |
**************************************************************************/ |
/* |
* References: |
* |
* Lin, S. F., Chang, Y. L., & Chen, L. G. (2003). |
* Motion adaptive interpolation with horizontal motion detection for deinterlacing. |
* Consumer Electronics, IEEE Transactions on, 49(4), 1256-1265. |
* |
* Pei-Yin, C. H. E. N., & Yao-Hsien, L. A. I. (2007). |
* A low-complexity interpolation method for deinterlacing. |
* IEICE transactions on information and systems, 90(2), 606-608. |
* |
*/ |
#include <stdio.h> |
#include "pipe/p_context.h" |
#include "tgsi/tgsi_ureg.h" |
#include "util/u_draw.h" |
#include "util/u_memory.h" |
#include "util/u_math.h" |
#include "vl_types.h" |
#include "vl_video_buffer.h" |
#include "vl_vertex_buffers.h" |
#include "vl_deint_filter.h" |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_VTEX = 0 |
}; |
static void * |
create_vert_shader(struct vl_deint_filter *filter) |
{ |
struct ureg_program *shader; |
struct ureg_src i_vpos; |
struct ureg_dst o_vpos, o_vtex; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
i_vpos = ureg_DECL_vs_input(shader, 0); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); |
ureg_MOV(shader, o_vpos, i_vpos); |
ureg_MOV(shader, o_vtex, i_vpos); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
static void * |
create_copy_frag_shader(struct vl_deint_filter *filter, unsigned field) |
{ |
struct ureg_program *shader; |
struct ureg_src i_vtex; |
struct ureg_src sampler; |
struct ureg_dst o_fragment; |
struct ureg_dst t_tex; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) { |
return NULL; |
} |
t_tex = ureg_DECL_temporary(shader); |
i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 2); |
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
ureg_MOV(shader, t_tex, i_vtex); |
if (field) { |
ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW), |
ureg_imm4f(shader, 0, 0, 1.0f, 0)); |
} else { |
ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW), |
ureg_imm1f(shader, 0)); |
} |
ureg_TEX(shader, o_fragment, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_tex), sampler); |
ureg_release_temporary(shader, t_tex); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
static void * |
create_deint_frag_shader(struct vl_deint_filter *filter, unsigned field, |
struct vertex2f *sizes, bool spatial_filter) |
{ |
struct ureg_program *shader; |
struct ureg_src i_vtex; |
struct ureg_src sampler_cur; |
struct ureg_src sampler_prevprev; |
struct ureg_src sampler_prev; |
struct ureg_src sampler_next; |
struct ureg_dst o_fragment; |
struct ureg_dst t_tex; |
struct ureg_dst t_comp_top, t_comp_bot; |
struct ureg_dst t_diff; |
struct ureg_dst t_a, t_b; |
struct ureg_dst t_weave, t_linear; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) { |
return NULL; |
} |
t_tex = ureg_DECL_temporary(shader); |
t_comp_top = ureg_DECL_temporary(shader); |
t_comp_bot = ureg_DECL_temporary(shader); |
t_diff = ureg_DECL_temporary(shader); |
t_a = ureg_DECL_temporary(shader); |
t_b = ureg_DECL_temporary(shader); |
t_weave = ureg_DECL_temporary(shader); |
t_linear = ureg_DECL_temporary(shader); |
i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
sampler_prevprev = ureg_DECL_sampler(shader, 0); |
sampler_prev = ureg_DECL_sampler(shader, 1); |
sampler_cur = ureg_DECL_sampler(shader, 2); |
sampler_next = ureg_DECL_sampler(shader, 3); |
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
// we don't care about ZW interpolation (allows better optimization) |
ureg_MOV(shader, t_tex, i_vtex); |
ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW), |
ureg_imm1f(shader, 0)); |
// sample between texels for cheap lowpass |
ureg_ADD(shader, t_comp_top, ureg_src(t_tex), |
ureg_imm4f(shader, sizes->x * 0.5f, sizes->y * -0.5f, 0, 0)); |
ureg_ADD(shader, t_comp_bot, ureg_src(t_tex), |
ureg_imm4f(shader, sizes->x * -0.5f, sizes->y * 0.5f, 1.0f, 0)); |
if (field == 0) { |
/* interpolating top field -> current field is a bottom field */ |
// cur vs prev2 |
ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_cur); |
ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_prevprev); |
ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_src(t_a), ureg_src(t_b)); |
// prev vs next |
ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_prev); |
ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_next); |
ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_Y), ureg_src(t_a), ureg_src(t_b)); |
} else { |
/* interpolating bottom field -> current field is a top field */ |
// cur vs prev2 |
ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_cur); |
ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_prevprev); |
ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_src(t_a), ureg_src(t_b)); |
// prev vs next |
ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_prev); |
ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_next); |
ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_Y), ureg_src(t_a), ureg_src(t_b)); |
} |
// absolute maximum of differences |
ureg_MAX(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_abs(ureg_src(t_diff)), |
ureg_scalar(ureg_abs(ureg_src(t_diff)), TGSI_SWIZZLE_Y)); |
if (field == 0) { |
/* weave with prev top field */ |
ureg_TEX(shader, t_weave, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_tex), sampler_prev); |
/* get linear interpolation from current bottom field */ |
ureg_ADD(shader, t_comp_top, ureg_src(t_tex), ureg_imm4f(shader, 0, sizes->y * -1.0f, 1.0f, 0)); |
ureg_TEX(shader, t_linear, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_cur); |
} else { |
/* weave with prev bottom field */ |
ureg_ADD(shader, t_comp_bot, ureg_src(t_tex), ureg_imm4f(shader, 0, 0, 1.0f, 0)); |
ureg_TEX(shader, t_weave, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_prev); |
/* get linear interpolation from current top field */ |
ureg_ADD(shader, t_comp_bot, ureg_src(t_tex), ureg_imm4f(shader, 0, sizes->y * 1.0f, 0, 0)); |
ureg_TEX(shader, t_linear, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_cur); |
} |
// mix between weave and linear |
// fully weave if diff < 6 (0.02353), fully interpolate if diff > 14 (0.05490) |
ureg_ADD(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_src(t_diff), |
ureg_imm4f(shader, -0.02353f, 0, 0, 0)); |
ureg_MUL(shader, ureg_saturate(ureg_writemask(t_diff, TGSI_WRITEMASK_X)), |
ureg_src(t_diff), ureg_imm4f(shader, 31.8750f, 0, 0, 0)); |
ureg_LRP(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X), ureg_src(t_diff), |
ureg_src(t_linear), ureg_src(t_weave)); |
ureg_release_temporary(shader, t_tex); |
ureg_release_temporary(shader, t_comp_top); |
ureg_release_temporary(shader, t_comp_bot); |
ureg_release_temporary(shader, t_diff); |
ureg_release_temporary(shader, t_a); |
ureg_release_temporary(shader, t_b); |
ureg_release_temporary(shader, t_weave); |
ureg_release_temporary(shader, t_linear); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
bool |
vl_deint_filter_init(struct vl_deint_filter *filter, struct pipe_context *pipe, |
unsigned video_width, unsigned video_height, |
bool skip_chroma, bool spatial_filter) |
{ |
struct pipe_rasterizer_state rs_state; |
struct pipe_blend_state blend; |
struct pipe_sampler_state sampler; |
struct pipe_vertex_element ve; |
struct vertex2f sizes; |
struct pipe_video_buffer templ; |
assert(filter && pipe); |
assert(video_width && video_height); |
memset(filter, 0, sizeof(*filter)); |
filter->pipe = pipe; |
filter->skip_chroma = skip_chroma; |
filter->video_width = video_width; |
filter->video_height = video_height; |
/* TODO: handle other than 4:2:0 subsampling */ |
memset(&templ, 0, sizeof(templ)); |
templ.buffer_format = PIPE_FORMAT_YV12; |
templ.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; |
templ.width = video_width; |
templ.height = video_height; |
templ.interlaced = true; |
filter->video_buffer = vl_video_buffer_create(pipe, &templ); |
if (!filter->video_buffer) |
goto error_video_buffer; |
memset(&rs_state, 0, sizeof(rs_state)); |
rs_state.half_pixel_center = true; |
rs_state.bottom_edge_rule = true; |
rs_state.depth_clip = 1; |
filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); |
if (!filter->rs_state) |
goto error_rs_state; |
memset(&blend, 0, sizeof blend); |
blend.rt[0].colormask = PIPE_MASK_RGBA; |
filter->blend = pipe->create_blend_state(pipe, &blend); |
if (!filter->blend) |
goto error_blend; |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; |
sampler.normalized_coords = 1; |
filter->sampler[0] = pipe->create_sampler_state(pipe, &sampler); |
filter->sampler[1] = filter->sampler[2] = filter->sampler[3] = filter->sampler[0]; |
if (!filter->sampler[0]) |
goto error_sampler; |
filter->quad = vl_vb_upload_quads(pipe); |
if(!filter->quad.buffer) |
goto error_quad; |
memset(&ve, 0, sizeof(ve)); |
ve.src_offset = 0; |
ve.instance_divisor = 0; |
ve.vertex_buffer_index = 0; |
ve.src_format = PIPE_FORMAT_R32G32_FLOAT; |
filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve); |
if (!filter->ves) |
goto error_ves; |
sizes.x = 1.0f / video_width; |
sizes.y = 1.0f / video_height; |
filter->vs = create_vert_shader(filter); |
if (!filter->vs) |
goto error_vs; |
filter->fs_copy_top = create_copy_frag_shader(filter, 0); |
if (!filter->fs_copy_top) |
goto error_fs_copy_top; |
filter->fs_copy_bottom = create_copy_frag_shader(filter, 1); |
if (!filter->fs_copy_bottom) |
goto error_fs_copy_bottom; |
filter->fs_deint_top = create_deint_frag_shader(filter, 0, &sizes, spatial_filter); |
if (!filter->fs_deint_top) |
goto error_fs_deint_top; |
filter->fs_deint_bottom = create_deint_frag_shader(filter, 1, &sizes, spatial_filter); |
if (!filter->fs_deint_bottom) |
goto error_fs_deint_bottom; |
return true; |
error_fs_deint_bottom: |
pipe->delete_fs_state(pipe, filter->fs_deint_top); |
error_fs_deint_top: |
pipe->delete_fs_state(pipe, filter->fs_copy_bottom); |
error_fs_copy_bottom: |
pipe->delete_fs_state(pipe, filter->fs_copy_top); |
error_fs_copy_top: |
pipe->delete_vs_state(pipe, filter->vs); |
error_vs: |
pipe->delete_vertex_elements_state(pipe, filter->ves); |
error_ves: |
pipe_resource_reference(&filter->quad.buffer, NULL); |
error_quad: |
pipe->delete_sampler_state(pipe, filter->sampler); |
error_sampler: |
pipe->delete_blend_state(pipe, filter->blend); |
error_blend: |
pipe->delete_rasterizer_state(pipe, filter->rs_state); |
error_rs_state: |
filter->video_buffer->destroy(filter->video_buffer); |
error_video_buffer: |
return false; |
} |
void |
vl_deint_filter_cleanup(struct vl_deint_filter *filter) |
{ |
assert(filter); |
filter->pipe->delete_sampler_state(filter->pipe, filter->sampler[0]); |
filter->pipe->delete_blend_state(filter->pipe, filter->blend); |
filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state); |
filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves); |
pipe_resource_reference(&filter->quad.buffer, NULL); |
filter->pipe->delete_vs_state(filter->pipe, filter->vs); |
filter->pipe->delete_fs_state(filter->pipe, filter->fs_copy_top); |
filter->pipe->delete_fs_state(filter->pipe, filter->fs_copy_bottom); |
filter->pipe->delete_fs_state(filter->pipe, filter->fs_deint_top); |
filter->pipe->delete_fs_state(filter->pipe, filter->fs_deint_bottom); |
filter->video_buffer->destroy(filter->video_buffer); |
} |
bool |
vl_deint_filter_check_buffers(struct vl_deint_filter *filter, |
struct pipe_video_buffer *prevprev, |
struct pipe_video_buffer *prev, |
struct pipe_video_buffer *cur, |
struct pipe_video_buffer *next) |
{ |
int i; |
struct pipe_video_buffer *bufs[] = { prevprev, prev, cur, next }; |
for (i = 0; i < 4; i++) { |
if (bufs[i]->chroma_format != PIPE_VIDEO_CHROMA_FORMAT_420) |
return false; |
if (bufs[i]->width < filter->video_width || |
bufs[i]->height < filter->video_height) |
return false; |
if (!bufs[i]->interlaced) |
return false; |
} |
return true; |
} |
void |
vl_deint_filter_render(struct vl_deint_filter *filter, |
struct pipe_video_buffer *prevprev, |
struct pipe_video_buffer *prev, |
struct pipe_video_buffer *cur, |
struct pipe_video_buffer *next, |
unsigned field) |
{ |
struct pipe_viewport_state viewport; |
struct pipe_framebuffer_state fb_state; |
struct pipe_sampler_view **cur_sv; |
struct pipe_sampler_view **prevprev_sv; |
struct pipe_sampler_view **prev_sv; |
struct pipe_sampler_view **next_sv; |
struct pipe_sampler_view *sampler_views[4]; |
struct pipe_surface **dst_surfaces; |
int j; |
assert(filter && prevprev && prev && cur && next && field <= 1); |
/* set up destination and source */ |
dst_surfaces = filter->video_buffer->get_surfaces(filter->video_buffer); |
cur_sv = cur->get_sampler_view_components(cur); |
prevprev_sv = prevprev->get_sampler_view_components(prevprev); |
prev_sv = prev->get_sampler_view_components(prev); |
next_sv = next->get_sampler_view_components(next); |
/* set up pipe state */ |
filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state); |
filter->pipe->bind_blend_state(filter->pipe, filter->blend); |
filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad); |
filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves); |
filter->pipe->bind_vs_state(filter->pipe, filter->vs); |
filter->pipe->bind_sampler_states(filter->pipe, PIPE_SHADER_FRAGMENT, |
0, 4, filter->sampler); |
/* prepare viewport */ |
memset(&viewport, 0, sizeof(viewport)); |
viewport.scale[2] = 1; |
/* prepare framebuffer */ |
memset(&fb_state, 0, sizeof(fb_state)); |
fb_state.nr_cbufs = 1; |
/* process each plane separately */ |
for (j = 0; j < 3; j++) { |
/* select correct YV12 surfaces */ |
int k = j == 1 ? 2 : |
j == 2 ? 1 : 0; |
struct pipe_surface *blit_surf = dst_surfaces[2 * k + field]; |
struct pipe_surface *dst_surf = dst_surfaces[2 * k + 1 - field]; |
/* update render target state */ |
viewport.scale[0] = blit_surf->texture->width0; |
viewport.scale[1] = blit_surf->texture->height0; |
fb_state.width = blit_surf->texture->width0; |
fb_state.height = blit_surf->texture->height0; |
/* update sampler view sources */ |
sampler_views[0] = prevprev_sv[j]; |
sampler_views[1] = prev_sv[j]; |
sampler_views[2] = cur_sv[j]; |
sampler_views[3] = next_sv[j]; |
filter->pipe->set_sampler_views(filter->pipe, PIPE_SHADER_FRAGMENT, 0, 4, sampler_views); |
/* blit current field */ |
fb_state.cbufs[0] = blit_surf; |
filter->pipe->bind_fs_state(filter->pipe, field ? filter->fs_copy_bottom : filter->fs_copy_top); |
filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); |
filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport); |
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); |
/* blit or interpolate other field */ |
fb_state.cbufs[0] = dst_surf; |
filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); |
if (j > 0 && filter->skip_chroma) { |
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); |
} else { |
filter->pipe->bind_fs_state(filter->pipe, field ? filter->fs_deint_top : filter->fs_deint_bottom); |
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); |
} |
} |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_deint_filter.h |
---|
0,0 → 1,77 |
/************************************************************************** |
* |
* Copyright 2013 Grigori Goronzy <greg@chown.ath.cx> |
* 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. |
* |
**************************************************************************/ |
/* motion adaptive deinterlacer implementation */ |
#ifndef vl_deint_filter_h |
#define vl_deint_filter_h |
#include "pipe/p_state.h" |
struct vl_deint_filter |
{ |
struct pipe_context *pipe; |
struct pipe_vertex_buffer quad; |
void *rs_state; |
void *blend; |
void *sampler[4]; |
void *ves; |
void *vs; |
void *fs_copy_top, *fs_copy_bottom; |
void *fs_deint_top, *fs_deint_bottom; |
unsigned video_width, video_height; |
bool skip_chroma; |
struct pipe_video_buffer *video_buffer; |
}; |
bool |
vl_deint_filter_init(struct vl_deint_filter *filter, struct pipe_context *pipe, |
unsigned video_width, unsigned video_height, |
bool skip_chroma, bool spatial_filter); |
void |
vl_deint_filter_cleanup(struct vl_deint_filter *filter); |
bool |
vl_deint_filter_check_buffers(struct vl_deint_filter *filter, |
struct pipe_video_buffer *prevprev, |
struct pipe_video_buffer *prev, |
struct pipe_video_buffer *cur, |
struct pipe_video_buffer *next); |
void |
vl_deint_filter_render(struct vl_deint_filter *filter, |
struct pipe_video_buffer *prevprev, |
struct pipe_video_buffer *prev, |
struct pipe_video_buffer *cur, |
struct pipe_video_buffer *next, |
unsigned field); |
#endif /* vl_deint_filter_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_idct.c |
---|
0,0 → 1,860 |
/************************************************************************** |
* |
* Copyright 2010 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 VMWARE 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 <assert.h> |
#include "pipe/p_context.h" |
#include "pipe/p_screen.h" |
#include "util/u_draw.h" |
#include "util/u_sampler.h" |
#include "util/u_memory.h" |
#include "tgsi/tgsi_ureg.h" |
#include "vl_defines.h" |
#include "vl_types.h" |
#include "vl_vertex_buffers.h" |
#include "vl_idct.h" |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_L_ADDR0 = 0, |
VS_O_L_ADDR1, |
VS_O_R_ADDR0, |
VS_O_R_ADDR1 |
}; |
/** |
* The DCT matrix stored as hex representation of floats. Equal to the following equation: |
* for (i = 0; i < 8; ++i) |
* for (j = 0; j < 8; ++j) |
* if (i == 0) const_matrix[i][j] = 1.0f / sqrtf(8.0f); |
* else const_matrix[i][j] = sqrtf(2.0f / 8.0f) * cosf((2 * j + 1) * i * M_PI / (2.0f * 8.0f)); |
*/ |
static const uint32_t const_matrix[8][8] = { |
{ 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3 }, |
{ 0x3efb14be, 0x3ed4db31, 0x3e8e39da, 0x3dc7c5c4, 0xbdc7c5c2, 0xbe8e39d9, 0xbed4db32, 0xbefb14bf }, |
{ 0x3eec835f, 0x3e43ef15, 0xbe43ef14, 0xbeec835e, 0xbeec835f, 0xbe43ef1a, 0x3e43ef1b, 0x3eec835f }, |
{ 0x3ed4db31, 0xbdc7c5c2, 0xbefb14bf, 0xbe8e39dd, 0x3e8e39d7, 0x3efb14bf, 0x3dc7c5d0, 0xbed4db34 }, |
{ 0x3eb504f3, 0xbeb504f3, 0xbeb504f4, 0x3eb504f1, 0x3eb504f3, 0xbeb504f0, 0xbeb504ef, 0x3eb504f4 }, |
{ 0x3e8e39da, 0xbefb14bf, 0x3dc7c5c8, 0x3ed4db32, 0xbed4db34, 0xbdc7c5bb, 0x3efb14bf, 0xbe8e39d7 }, |
{ 0x3e43ef15, 0xbeec835f, 0x3eec835f, 0xbe43ef07, 0xbe43ef23, 0x3eec8361, 0xbeec835c, 0x3e43ef25 }, |
{ 0x3dc7c5c4, 0xbe8e39dd, 0x3ed4db32, 0xbefb14c0, 0x3efb14be, 0xbed4db31, 0x3e8e39ce, 0xbdc7c596 }, |
}; |
static void |
calc_addr(struct ureg_program *shader, struct ureg_dst addr[2], |
struct ureg_src tc, struct ureg_src start, bool right_side, |
bool transposed, float size) |
{ |
unsigned wm_start = (right_side == transposed) ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_Y; |
unsigned sw_start = right_side ? TGSI_SWIZZLE_Y : TGSI_SWIZZLE_X; |
unsigned wm_tc = (right_side == transposed) ? TGSI_WRITEMASK_Y : TGSI_WRITEMASK_X; |
unsigned sw_tc = right_side ? TGSI_SWIZZLE_X : TGSI_SWIZZLE_Y; |
/* |
* addr[0..1].(start) = right_side ? start.x : tc.x |
* addr[0..1].(tc) = right_side ? tc.y : start.y |
* addr[0..1].z = tc.z |
* addr[1].(start) += 1.0f / scale |
*/ |
ureg_MOV(shader, ureg_writemask(addr[0], wm_start), ureg_scalar(start, sw_start)); |
ureg_MOV(shader, ureg_writemask(addr[0], wm_tc), ureg_scalar(tc, sw_tc)); |
ureg_ADD(shader, ureg_writemask(addr[1], wm_start), ureg_scalar(start, sw_start), ureg_imm1f(shader, 1.0f / size)); |
ureg_MOV(shader, ureg_writemask(addr[1], wm_tc), ureg_scalar(tc, sw_tc)); |
} |
static void |
increment_addr(struct ureg_program *shader, struct ureg_dst daddr[2], |
struct ureg_src saddr[2], bool right_side, bool transposed, |
int pos, float size) |
{ |
unsigned wm_start = (right_side == transposed) ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_Y; |
unsigned wm_tc = (right_side == transposed) ? TGSI_WRITEMASK_Y : TGSI_WRITEMASK_X; |
/* |
* daddr[0..1].(start) = saddr[0..1].(start) |
* daddr[0..1].(tc) = saddr[0..1].(tc) |
*/ |
ureg_MOV(shader, ureg_writemask(daddr[0], wm_start), saddr[0]); |
ureg_ADD(shader, ureg_writemask(daddr[0], wm_tc), saddr[0], ureg_imm1f(shader, pos / size)); |
ureg_MOV(shader, ureg_writemask(daddr[1], wm_start), saddr[1]); |
ureg_ADD(shader, ureg_writemask(daddr[1], wm_tc), saddr[1], ureg_imm1f(shader, pos / size)); |
} |
static void |
fetch_four(struct ureg_program *shader, struct ureg_dst m[2], struct ureg_src addr[2], |
struct ureg_src sampler, bool resource3d) |
{ |
ureg_TEX(shader, m[0], resource3d ? TGSI_TEXTURE_3D : TGSI_TEXTURE_2D, addr[0], sampler); |
ureg_TEX(shader, m[1], resource3d ? TGSI_TEXTURE_3D : TGSI_TEXTURE_2D, addr[1], sampler); |
} |
static void |
matrix_mul(struct ureg_program *shader, struct ureg_dst dst, struct ureg_dst l[2], struct ureg_dst r[2]) |
{ |
struct ureg_dst tmp; |
tmp = ureg_DECL_temporary(shader); |
/* |
* tmp.xy = dot4(m[0][0..1], m[1][0..1]) |
* dst = tmp.x + tmp.y |
*/ |
ureg_DP4(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(l[0]), ureg_src(r[0])); |
ureg_DP4(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(l[1]), ureg_src(r[1])); |
ureg_ADD(shader, dst, |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), |
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y)); |
ureg_release_temporary(shader, tmp); |
} |
static void * |
create_mismatch_vert_shader(struct vl_idct *idct) |
{ |
struct ureg_program *shader; |
struct ureg_src vpos; |
struct ureg_src scale; |
struct ureg_dst t_tex; |
struct ureg_dst o_vpos, o_addr[2]; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); |
t_tex = ureg_DECL_temporary(shader); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0); |
o_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1); |
/* |
* scale = (VL_BLOCK_WIDTH, VL_BLOCK_HEIGHT) / (dst.width, dst.height) |
* |
* t_vpos = vpos + 7 / VL_BLOCK_WIDTH |
* o_vpos.xy = t_vpos * scale |
* |
* o_addr = calc_addr(...) |
* |
*/ |
scale = ureg_imm2f(shader, |
(float)VL_BLOCK_WIDTH / idct->buffer_width, |
(float)VL_BLOCK_HEIGHT / idct->buffer_height); |
ureg_MAD(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), vpos, scale, scale); |
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f)); |
ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), vpos, scale); |
calc_addr(shader, o_addr, ureg_src(t_tex), ureg_src(t_tex), false, false, idct->buffer_width / 4); |
ureg_release_temporary(shader, t_tex); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, idct->pipe); |
} |
static void * |
create_mismatch_frag_shader(struct vl_idct *idct) |
{ |
struct ureg_program *shader; |
struct ureg_src addr[2]; |
struct ureg_dst m[8][2]; |
struct ureg_dst fragment; |
unsigned i; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return NULL; |
addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR); |
addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
for (i = 0; i < 8; ++i) { |
m[i][0] = ureg_DECL_temporary(shader); |
m[i][1] = ureg_DECL_temporary(shader); |
} |
for (i = 0; i < 8; ++i) { |
increment_addr(shader, m[i], addr, false, false, i, idct->buffer_height); |
} |
for (i = 0; i < 8; ++i) { |
struct ureg_src s_addr[2]; |
s_addr[0] = ureg_src(m[i][0]); |
s_addr[1] = ureg_src(m[i][1]); |
fetch_four(shader, m[i], s_addr, ureg_DECL_sampler(shader, 0), false); |
} |
for (i = 1; i < 8; ++i) { |
ureg_ADD(shader, m[0][0], ureg_src(m[0][0]), ureg_src(m[i][0])); |
ureg_ADD(shader, m[0][1], ureg_src(m[0][1]), ureg_src(m[i][1])); |
} |
ureg_ADD(shader, m[0][0], ureg_src(m[0][0]), ureg_src(m[0][1])); |
ureg_DP4(shader, m[0][0], ureg_abs(ureg_src(m[0][0])), ureg_imm1f(shader, 1 << 14)); |
ureg_MUL(shader, ureg_writemask(m[0][0], TGSI_WRITEMASK_W), ureg_abs(ureg_src(m[7][1])), ureg_imm1f(shader, 1 << 14)); |
ureg_FRC(shader, m[0][0], ureg_src(m[0][0])); |
ureg_SGT(shader, m[0][0], ureg_imm1f(shader, 0.5f), ureg_abs(ureg_src(m[0][0]))); |
ureg_CMP(shader, ureg_writemask(m[0][0], TGSI_WRITEMASK_W), ureg_negate(ureg_src(m[0][0])), |
ureg_imm1f(shader, 1.0f / (1 << 15)), ureg_imm1f(shader, -1.0f / (1 << 15))); |
ureg_MUL(shader, ureg_writemask(m[0][0], TGSI_WRITEMASK_W), ureg_src(m[0][0]), |
ureg_scalar(ureg_src(m[0][0]), TGSI_SWIZZLE_X)); |
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), ureg_src(m[7][1])); |
ureg_ADD(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(m[0][0]), ureg_src(m[7][1])); |
for (i = 0; i < 8; ++i) { |
ureg_release_temporary(shader, m[i][0]); |
ureg_release_temporary(shader, m[i][1]); |
} |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, idct->pipe); |
} |
static void * |
create_stage1_vert_shader(struct vl_idct *idct) |
{ |
struct ureg_program *shader; |
struct ureg_src vrect, vpos; |
struct ureg_src scale; |
struct ureg_dst t_tex, t_start; |
struct ureg_dst o_vpos, o_l_addr[2], o_r_addr[2]; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
vrect = ureg_DECL_vs_input(shader, VS_I_RECT); |
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); |
t_tex = ureg_DECL_temporary(shader); |
t_start = ureg_DECL_temporary(shader); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_l_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0); |
o_l_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1); |
o_r_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0); |
o_r_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1); |
/* |
* scale = (VL_BLOCK_WIDTH, VL_BLOCK_HEIGHT) / (dst.width, dst.height) |
* |
* t_vpos = vpos + vrect |
* o_vpos.xy = t_vpos * scale |
* o_vpos.zw = vpos |
* |
* o_l_addr = calc_addr(...) |
* o_r_addr = calc_addr(...) |
* |
*/ |
scale = ureg_imm2f(shader, |
(float)VL_BLOCK_WIDTH / idct->buffer_width, |
(float)VL_BLOCK_HEIGHT / idct->buffer_height); |
ureg_ADD(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), vpos, vrect); |
ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), ureg_src(t_tex), scale); |
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_tex)); |
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f)); |
ureg_MUL(shader, ureg_writemask(t_start, TGSI_WRITEMASK_XY), vpos, scale); |
calc_addr(shader, o_l_addr, ureg_src(t_tex), ureg_src(t_start), false, false, idct->buffer_width / 4); |
calc_addr(shader, o_r_addr, vrect, ureg_imm1f(shader, 0.0f), true, true, VL_BLOCK_WIDTH / 4); |
ureg_release_temporary(shader, t_tex); |
ureg_release_temporary(shader, t_start); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, idct->pipe); |
} |
static void * |
create_stage1_frag_shader(struct vl_idct *idct) |
{ |
struct ureg_program *shader; |
struct ureg_src l_addr[2], r_addr[2]; |
struct ureg_dst l[4][2], r[2]; |
struct ureg_dst *fragment; |
int i, j; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return NULL; |
fragment = MALLOC(idct->nr_of_render_targets * sizeof(struct ureg_dst)); |
l_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR); |
l_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR); |
r_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0, TGSI_INTERPOLATE_LINEAR); |
r_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1, TGSI_INTERPOLATE_LINEAR); |
for (i = 0; i < idct->nr_of_render_targets; ++i) |
fragment[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, i); |
for (i = 0; i < 4; ++i) { |
l[i][0] = ureg_DECL_temporary(shader); |
l[i][1] = ureg_DECL_temporary(shader); |
} |
r[0] = ureg_DECL_temporary(shader); |
r[1] = ureg_DECL_temporary(shader); |
for (i = 0; i < 4; ++i) { |
increment_addr(shader, l[i], l_addr, false, false, i - 2, idct->buffer_height); |
} |
for (i = 0; i < 4; ++i) { |
struct ureg_src s_addr[2]; |
s_addr[0] = ureg_src(l[i][0]); |
s_addr[1] = ureg_src(l[i][1]); |
fetch_four(shader, l[i], s_addr, ureg_DECL_sampler(shader, 0), false); |
} |
for (i = 0; i < idct->nr_of_render_targets; ++i) { |
struct ureg_src s_addr[2]; |
increment_addr(shader, r, r_addr, true, true, i - (signed)idct->nr_of_render_targets / 2, VL_BLOCK_HEIGHT); |
s_addr[0] = ureg_src(r[0]); |
s_addr[1] = ureg_src(r[1]); |
fetch_four(shader, r, s_addr, ureg_DECL_sampler(shader, 1), false); |
for (j = 0; j < 4; ++j) { |
matrix_mul(shader, ureg_writemask(fragment[i], TGSI_WRITEMASK_X << j), l[j], r); |
} |
} |
for (i = 0; i < 4; ++i) { |
ureg_release_temporary(shader, l[i][0]); |
ureg_release_temporary(shader, l[i][1]); |
} |
ureg_release_temporary(shader, r[0]); |
ureg_release_temporary(shader, r[1]); |
ureg_END(shader); |
FREE(fragment); |
return ureg_create_shader_and_destroy(shader, idct->pipe); |
} |
void |
vl_idct_stage2_vert_shader(struct vl_idct *idct, struct ureg_program *shader, |
unsigned first_output, struct ureg_dst tex) |
{ |
struct ureg_src vrect, vpos; |
struct ureg_src scale; |
struct ureg_dst t_start; |
struct ureg_dst o_l_addr[2], o_r_addr[2]; |
vrect = ureg_DECL_vs_input(shader, VS_I_RECT); |
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); |
t_start = ureg_DECL_temporary(shader); |
--first_output; |
o_l_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_L_ADDR0); |
o_l_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_L_ADDR1); |
o_r_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_R_ADDR0); |
o_r_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_R_ADDR1); |
scale = ureg_imm2f(shader, |
(float)VL_BLOCK_WIDTH / idct->buffer_width, |
(float)VL_BLOCK_HEIGHT / idct->buffer_height); |
ureg_MUL(shader, ureg_writemask(tex, TGSI_WRITEMASK_Z), |
ureg_scalar(vrect, TGSI_SWIZZLE_X), |
ureg_imm1f(shader, VL_BLOCK_WIDTH / idct->nr_of_render_targets)); |
ureg_MUL(shader, ureg_writemask(t_start, TGSI_WRITEMASK_XY), vpos, scale); |
calc_addr(shader, o_l_addr, vrect, ureg_imm1f(shader, 0.0f), false, false, VL_BLOCK_WIDTH / 4); |
calc_addr(shader, o_r_addr, ureg_src(tex), ureg_src(t_start), true, false, idct->buffer_height / 4); |
ureg_MOV(shader, ureg_writemask(o_r_addr[0], TGSI_WRITEMASK_Z), ureg_src(tex)); |
ureg_MOV(shader, ureg_writemask(o_r_addr[1], TGSI_WRITEMASK_Z), ureg_src(tex)); |
} |
void |
vl_idct_stage2_frag_shader(struct vl_idct *idct, struct ureg_program *shader, |
unsigned first_input, struct ureg_dst fragment) |
{ |
struct ureg_src l_addr[2], r_addr[2]; |
struct ureg_dst l[2], r[2]; |
--first_input; |
l_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR); |
l_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR); |
r_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_R_ADDR0, TGSI_INTERPOLATE_LINEAR); |
r_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_R_ADDR1, TGSI_INTERPOLATE_LINEAR); |
l[0] = ureg_DECL_temporary(shader); |
l[1] = ureg_DECL_temporary(shader); |
r[0] = ureg_DECL_temporary(shader); |
r[1] = ureg_DECL_temporary(shader); |
fetch_four(shader, l, l_addr, ureg_DECL_sampler(shader, 1), false); |
fetch_four(shader, r, r_addr, ureg_DECL_sampler(shader, 0), true); |
matrix_mul(shader, fragment, l, r); |
ureg_release_temporary(shader, l[0]); |
ureg_release_temporary(shader, l[1]); |
ureg_release_temporary(shader, r[0]); |
ureg_release_temporary(shader, r[1]); |
} |
static bool |
init_shaders(struct vl_idct *idct) |
{ |
idct->vs_mismatch = create_mismatch_vert_shader(idct); |
if (!idct->vs_mismatch) |
goto error_vs_mismatch; |
idct->fs_mismatch = create_mismatch_frag_shader(idct); |
if (!idct->fs_mismatch) |
goto error_fs_mismatch; |
idct->vs = create_stage1_vert_shader(idct); |
if (!idct->vs) |
goto error_vs; |
idct->fs = create_stage1_frag_shader(idct); |
if (!idct->fs) |
goto error_fs; |
return true; |
error_fs: |
idct->pipe->delete_vs_state(idct->pipe, idct->vs); |
error_vs: |
idct->pipe->delete_vs_state(idct->pipe, idct->vs_mismatch); |
error_fs_mismatch: |
idct->pipe->delete_vs_state(idct->pipe, idct->fs); |
error_vs_mismatch: |
return false; |
} |
static void |
cleanup_shaders(struct vl_idct *idct) |
{ |
idct->pipe->delete_vs_state(idct->pipe, idct->vs_mismatch); |
idct->pipe->delete_fs_state(idct->pipe, idct->fs_mismatch); |
idct->pipe->delete_vs_state(idct->pipe, idct->vs); |
idct->pipe->delete_fs_state(idct->pipe, idct->fs); |
} |
static bool |
init_state(struct vl_idct *idct) |
{ |
struct pipe_blend_state blend; |
struct pipe_rasterizer_state rs_state; |
struct pipe_sampler_state sampler; |
unsigned i; |
assert(idct); |
memset(&rs_state, 0, sizeof(rs_state)); |
rs_state.point_size = 1; |
rs_state.half_pixel_center = true; |
rs_state.bottom_edge_rule = true; |
rs_state.depth_clip = 1; |
idct->rs_state = idct->pipe->create_rasterizer_state(idct->pipe, &rs_state); |
if (!idct->rs_state) |
goto error_rs_state; |
memset(&blend, 0, sizeof blend); |
blend.independent_blend_enable = 0; |
blend.rt[0].blend_enable = 0; |
blend.rt[0].rgb_func = PIPE_BLEND_ADD; |
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_func = PIPE_BLEND_ADD; |
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.logicop_enable = 0; |
blend.logicop_func = PIPE_LOGICOP_CLEAR; |
/* Needed to allow color writes to FB, even if blending disabled */ |
blend.rt[0].colormask = PIPE_MASK_RGBA; |
blend.dither = 0; |
idct->blend = idct->pipe->create_blend_state(idct->pipe, &blend); |
if (!idct->blend) |
goto error_blend; |
for (i = 0; i < 2; ++i) { |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; |
sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; |
sampler.wrap_r = PIPE_TEX_WRAP_REPEAT; |
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
idct->samplers[i] = idct->pipe->create_sampler_state(idct->pipe, &sampler); |
if (!idct->samplers[i]) |
goto error_samplers; |
} |
return true; |
error_samplers: |
for (i = 0; i < 2; ++i) |
if (idct->samplers[i]) |
idct->pipe->delete_sampler_state(idct->pipe, idct->samplers[i]); |
idct->pipe->delete_rasterizer_state(idct->pipe, idct->rs_state); |
error_blend: |
idct->pipe->delete_blend_state(idct->pipe, idct->blend); |
error_rs_state: |
return false; |
} |
static void |
cleanup_state(struct vl_idct *idct) |
{ |
unsigned i; |
for (i = 0; i < 2; ++i) |
idct->pipe->delete_sampler_state(idct->pipe, idct->samplers[i]); |
idct->pipe->delete_rasterizer_state(idct->pipe, idct->rs_state); |
idct->pipe->delete_blend_state(idct->pipe, idct->blend); |
} |
static bool |
init_source(struct vl_idct *idct, struct vl_idct_buffer *buffer) |
{ |
struct pipe_resource *tex; |
struct pipe_surface surf_templ; |
assert(idct && buffer); |
tex = buffer->sampler_views.individual.source->texture; |
buffer->fb_state_mismatch.width = tex->width0; |
buffer->fb_state_mismatch.height = tex->height0; |
buffer->fb_state_mismatch.nr_cbufs = 1; |
memset(&surf_templ, 0, sizeof(surf_templ)); |
surf_templ.format = tex->format; |
surf_templ.u.tex.first_layer = 0; |
surf_templ.u.tex.last_layer = 0; |
buffer->fb_state_mismatch.cbufs[0] = idct->pipe->create_surface(idct->pipe, tex, &surf_templ); |
buffer->viewport_mismatch.scale[0] = tex->width0; |
buffer->viewport_mismatch.scale[1] = tex->height0; |
buffer->viewport_mismatch.scale[2] = 1; |
return true; |
} |
static void |
cleanup_source(struct vl_idct_buffer *buffer) |
{ |
assert(buffer); |
pipe_surface_reference(&buffer->fb_state_mismatch.cbufs[0], NULL); |
pipe_sampler_view_reference(&buffer->sampler_views.individual.source, NULL); |
} |
static bool |
init_intermediate(struct vl_idct *idct, struct vl_idct_buffer *buffer) |
{ |
struct pipe_resource *tex; |
struct pipe_surface surf_templ; |
unsigned i; |
assert(idct && buffer); |
tex = buffer->sampler_views.individual.intermediate->texture; |
buffer->fb_state.width = tex->width0; |
buffer->fb_state.height = tex->height0; |
buffer->fb_state.nr_cbufs = idct->nr_of_render_targets; |
for(i = 0; i < idct->nr_of_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; |
buffer->fb_state.cbufs[i] = idct->pipe->create_surface( |
idct->pipe, tex, &surf_templ); |
if (!buffer->fb_state.cbufs[i]) |
goto error_surfaces; |
} |
buffer->viewport.scale[0] = tex->width0; |
buffer->viewport.scale[1] = tex->height0; |
buffer->viewport.scale[2] = 1; |
return true; |
error_surfaces: |
for(i = 0; i < idct->nr_of_render_targets; ++i) |
pipe_surface_reference(&buffer->fb_state.cbufs[i], NULL); |
return false; |
} |
static void |
cleanup_intermediate(struct vl_idct_buffer *buffer) |
{ |
unsigned i; |
assert(buffer); |
for(i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) |
pipe_surface_reference(&buffer->fb_state.cbufs[i], NULL); |
pipe_sampler_view_reference(&buffer->sampler_views.individual.intermediate, NULL); |
} |
struct pipe_sampler_view * |
vl_idct_upload_matrix(struct pipe_context *pipe, float scale) |
{ |
struct pipe_resource tex_templ, *matrix; |
struct pipe_sampler_view sv_templ, *sv; |
struct pipe_transfer *buf_transfer; |
unsigned i, j, pitch; |
float *f; |
struct pipe_box rect = |
{ |
0, 0, 0, |
VL_BLOCK_WIDTH / 4, |
VL_BLOCK_HEIGHT, |
1 |
}; |
assert(pipe); |
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; |
f = pipe->transfer_map(pipe, matrix, 0, |
PIPE_TRANSFER_WRITE | |
PIPE_TRANSFER_DISCARD_RANGE, |
&rect, &buf_transfer); |
if (!f) |
goto error_map; |
pitch = buf_transfer->stride / sizeof(float); |
for(i = 0; i < VL_BLOCK_HEIGHT; ++i) |
for(j = 0; j < VL_BLOCK_WIDTH; ++j) |
// transpose and scale |
f[i * pitch + j] = ((const float (*)[8])const_matrix)[j][i] * scale; |
pipe->transfer_unmap(pipe, buf_transfer); |
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_resource_reference(&matrix, NULL); |
error_matrix: |
return NULL; |
} |
bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe, |
unsigned buffer_width, unsigned buffer_height, |
unsigned nr_of_render_targets, |
struct pipe_sampler_view *matrix, |
struct pipe_sampler_view *transpose) |
{ |
assert(idct && pipe); |
assert(matrix && transpose); |
idct->pipe = pipe; |
idct->buffer_width = buffer_width; |
idct->buffer_height = buffer_height; |
idct->nr_of_render_targets = nr_of_render_targets; |
pipe_sampler_view_reference(&idct->matrix, matrix); |
pipe_sampler_view_reference(&idct->transpose, transpose); |
if(!init_shaders(idct)) |
return false; |
if(!init_state(idct)) { |
cleanup_shaders(idct); |
return false; |
} |
return true; |
} |
void |
vl_idct_cleanup(struct vl_idct *idct) |
{ |
cleanup_shaders(idct); |
cleanup_state(idct); |
pipe_sampler_view_reference(&idct->matrix, NULL); |
pipe_sampler_view_reference(&idct->transpose, NULL); |
} |
bool |
vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer, |
struct pipe_sampler_view *source, |
struct pipe_sampler_view *intermediate) |
{ |
assert(buffer && idct); |
assert(source && intermediate); |
memset(buffer, 0, sizeof(struct vl_idct_buffer)); |
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->transpose); |
pipe_sampler_view_reference(&buffer->sampler_views.individual.intermediate, intermediate); |
if (!init_source(idct, buffer)) |
return false; |
if (!init_intermediate(idct, buffer)) |
return false; |
return true; |
} |
void |
vl_idct_cleanup_buffer(struct vl_idct_buffer *buffer) |
{ |
assert(buffer); |
cleanup_source(buffer); |
cleanup_intermediate(buffer); |
pipe_sampler_view_reference(&buffer->sampler_views.individual.matrix, NULL); |
pipe_sampler_view_reference(&buffer->sampler_views.individual.transpose, NULL); |
} |
void |
vl_idct_flush(struct vl_idct *idct, struct vl_idct_buffer *buffer, unsigned num_instances) |
{ |
assert(buffer); |
idct->pipe->bind_rasterizer_state(idct->pipe, idct->rs_state); |
idct->pipe->bind_blend_state(idct->pipe, idct->blend); |
idct->pipe->bind_sampler_states(idct->pipe, PIPE_SHADER_FRAGMENT, |
0, 2, idct->samplers); |
idct->pipe->set_sampler_views(idct->pipe, PIPE_SHADER_FRAGMENT, 0, 2, |
buffer->sampler_views.stage[0]); |
/* mismatch control */ |
idct->pipe->set_framebuffer_state(idct->pipe, &buffer->fb_state_mismatch); |
idct->pipe->set_viewport_states(idct->pipe, 0, 1, &buffer->viewport_mismatch); |
idct->pipe->bind_vs_state(idct->pipe, idct->vs_mismatch); |
idct->pipe->bind_fs_state(idct->pipe, idct->fs_mismatch); |
util_draw_arrays_instanced(idct->pipe, PIPE_PRIM_POINTS, 0, 1, 0, num_instances); |
/* first stage */ |
idct->pipe->set_framebuffer_state(idct->pipe, &buffer->fb_state); |
idct->pipe->set_viewport_states(idct->pipe, 0, 1, &buffer->viewport); |
idct->pipe->bind_vs_state(idct->pipe, idct->vs); |
idct->pipe->bind_fs_state(idct->pipe, idct->fs); |
util_draw_arrays_instanced(idct->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); |
} |
void |
vl_idct_prepare_stage2(struct vl_idct *idct, struct vl_idct_buffer *buffer) |
{ |
assert(buffer); |
/* second stage */ |
idct->pipe->bind_rasterizer_state(idct->pipe, idct->rs_state); |
idct->pipe->bind_sampler_states(idct->pipe, PIPE_SHADER_FRAGMENT, |
0, 2, idct->samplers); |
idct->pipe->set_sampler_views(idct->pipe, PIPE_SHADER_FRAGMENT, |
0, 2, buffer->sampler_views.stage[1]); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_idct.h |
---|
0,0 → 1,119 |
/************************************************************************** |
* |
* Copyright 2010 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 VMWARE 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_idct_h |
#define vl_idct_h |
#include "pipe/p_state.h" |
#include "tgsi/tgsi_ureg.h" |
/* shader based inverse distinct cosinus transformation |
* expect usage of vl_vertex_buffers as a todo list |
*/ |
struct vl_idct |
{ |
struct pipe_context *pipe; |
unsigned buffer_width; |
unsigned buffer_height; |
unsigned nr_of_render_targets; |
void *rs_state; |
void *blend; |
void *samplers[2]; |
void *vs_mismatch, *fs_mismatch; |
void *vs, *fs; |
struct pipe_sampler_view *matrix; |
struct pipe_sampler_view *transpose; |
}; |
/* a set of buffers to work with */ |
struct vl_idct_buffer |
{ |
struct pipe_viewport_state viewport_mismatch; |
struct pipe_viewport_state viewport; |
struct pipe_framebuffer_state fb_state_mismatch; |
struct pipe_framebuffer_state fb_state; |
union |
{ |
struct pipe_sampler_view *all[4]; |
struct pipe_sampler_view *stage[2][2]; |
struct { |
struct pipe_sampler_view *source, *matrix; |
struct pipe_sampler_view *intermediate, *transpose; |
} individual; |
} sampler_views; |
}; |
/* upload the idct matrix, which can be shared by all idct instances of a pipe */ |
struct pipe_sampler_view * |
vl_idct_upload_matrix(struct pipe_context *pipe, float scale); |
void |
vl_idct_stage2_vert_shader(struct vl_idct *idct, struct ureg_program *shader, |
unsigned first_output, struct ureg_dst tex); |
void |
vl_idct_stage2_frag_shader(struct vl_idct *idct, struct ureg_program *shader, |
unsigned first_input, struct ureg_dst fragment); |
/* init an idct instance */ |
bool |
vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe, |
unsigned buffer_width, unsigned buffer_height, |
unsigned nr_of_render_targets, |
struct pipe_sampler_view *matrix, |
struct pipe_sampler_view *transpose); |
/* destroy an idct instance */ |
void |
vl_idct_cleanup(struct vl_idct *idct); |
/* init a buffer assosiated with agiven idct instance */ |
bool |
vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer, |
struct pipe_sampler_view *source, |
struct pipe_sampler_view *intermediate); |
/* cleanup a buffer of an idct instance */ |
void |
vl_idct_cleanup_buffer(struct vl_idct_buffer *buffer); |
/* flush the buffer and start rendering, vertex buffers needs to be setup before calling this */ |
void |
vl_idct_flush(struct vl_idct *idct, struct vl_idct_buffer *buffer, unsigned num_verts); |
void |
vl_idct_prepare_stage2(struct vl_idct *idct, struct vl_idct_buffer *buffer); |
#endif |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_matrix_filter.c |
---|
0,0 → 1,320 |
/************************************************************************** |
* |
* Copyright 2012 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 VMWARE 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 <stdio.h> |
#include "pipe/p_context.h" |
#include "tgsi/tgsi_ureg.h" |
#include "util/u_draw.h" |
#include "util/u_memory.h" |
#include "util/u_math.h" |
#include "vl_types.h" |
#include "vl_vertex_buffers.h" |
#include "vl_matrix_filter.h" |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_VTEX = 0 |
}; |
static void * |
create_vert_shader(struct vl_matrix_filter *filter) |
{ |
struct ureg_program *shader; |
struct ureg_src i_vpos; |
struct ureg_dst o_vpos, o_vtex; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
i_vpos = ureg_DECL_vs_input(shader, 0); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); |
ureg_MOV(shader, o_vpos, i_vpos); |
ureg_MOV(shader, o_vtex, i_vpos); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
static inline bool |
is_vec_zero(struct vertex2f v) |
{ |
return v.x == 0.0f && v.y == 0.0f; |
} |
static void * |
create_frag_shader(struct vl_matrix_filter *filter, unsigned num_offsets, |
struct vertex2f *offsets, const float *matrix_values) |
{ |
struct ureg_program *shader; |
struct ureg_src i_vtex; |
struct ureg_src sampler; |
struct ureg_dst *t_array = MALLOC(sizeof(struct ureg_dst) * num_offsets); |
struct ureg_dst t_sum; |
struct ureg_dst o_fragment; |
bool first; |
int i; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) { |
FREE(t_array); |
return NULL; |
} |
i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 0); |
for (i = 0; i < num_offsets; ++i) |
if (matrix_values[i] != 0.0f) |
t_array[i] = ureg_DECL_temporary(shader); |
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* |
* t_array[0..*] = vtex + offset[0..*] |
* t_array[0..*] = tex(t_array[0..*], sampler) |
* o_fragment = sum(t_array[0..*] * matrix_values[0..*]) |
*/ |
for (i = 0; i < num_offsets; ++i) { |
if (matrix_values[i] != 0.0f && !is_vec_zero(offsets[i])) { |
ureg_ADD(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_XY), |
i_vtex, ureg_imm2f(shader, offsets[i].x, offsets[i].y)); |
ureg_MOV(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_ZW), |
ureg_imm1f(shader, 0.0f)); |
} |
} |
for (i = 0; i < num_offsets; ++i) { |
if (matrix_values[i] != 0.0f) { |
struct ureg_src src = is_vec_zero(offsets[i]) ? i_vtex : ureg_src(t_array[i]); |
ureg_TEX(shader, t_array[i], TGSI_TEXTURE_2D, src, sampler); |
} |
} |
for (i = 0, first = true; i < num_offsets; ++i) { |
if (matrix_values[i] != 0.0f) { |
if (first) { |
t_sum = t_array[i]; |
ureg_MUL(shader, t_sum, ureg_src(t_array[i]), |
ureg_imm1f(shader, matrix_values[i])); |
first = false; |
} else |
ureg_MAD(shader, t_sum, ureg_src(t_array[i]), |
ureg_imm1f(shader, matrix_values[i]), ureg_src(t_sum)); |
} |
} |
if (first) |
ureg_MOV(shader, o_fragment, ureg_imm1f(shader, 0.0f)); |
else |
ureg_MOV(shader, o_fragment, ureg_src(t_sum)); |
ureg_END(shader); |
FREE(t_array); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
bool |
vl_matrix_filter_init(struct vl_matrix_filter *filter, struct pipe_context *pipe, |
unsigned video_width, unsigned video_height, |
unsigned matrix_width, unsigned matrix_height, |
const float *matrix_values) |
{ |
struct pipe_rasterizer_state rs_state; |
struct pipe_blend_state blend; |
struct pipe_sampler_state sampler; |
struct pipe_vertex_element ve; |
struct vertex2f *offsets, v, sizes; |
unsigned i, num_offsets = matrix_width * matrix_height; |
assert(filter && pipe); |
assert(video_width && video_height); |
assert(matrix_width && matrix_height); |
memset(filter, 0, sizeof(*filter)); |
filter->pipe = pipe; |
memset(&rs_state, 0, sizeof(rs_state)); |
rs_state.half_pixel_center = true; |
rs_state.bottom_edge_rule = true; |
rs_state.depth_clip = 1; |
filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); |
if (!filter->rs_state) |
goto error_rs_state; |
memset(&blend, 0, sizeof blend); |
blend.rt[0].rgb_func = PIPE_BLEND_ADD; |
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_func = PIPE_BLEND_ADD; |
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.logicop_func = PIPE_LOGICOP_CLEAR; |
blend.rt[0].colormask = PIPE_MASK_RGBA; |
filter->blend = pipe->create_blend_state(pipe, &blend); |
if (!filter->blend) |
goto error_blend; |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
filter->sampler = pipe->create_sampler_state(pipe, &sampler); |
if (!filter->sampler) |
goto error_sampler; |
filter->quad = vl_vb_upload_quads(pipe); |
if(!filter->quad.buffer) |
goto error_quad; |
memset(&ve, 0, sizeof(ve)); |
ve.src_offset = 0; |
ve.instance_divisor = 0; |
ve.vertex_buffer_index = 0; |
ve.src_format = PIPE_FORMAT_R32G32_FLOAT; |
filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve); |
if (!filter->ves) |
goto error_ves; |
offsets = MALLOC(sizeof(struct vertex2f) * num_offsets); |
if (!offsets) |
goto error_offsets; |
sizes.x = (float)(matrix_width - 1) / 2.0f; |
sizes.y = (float)(matrix_height - 1) / 2.0f; |
for (v.x = -sizes.x, i = 0; v.x <= sizes.x; v.x += 1.0f) |
for (v.y = -sizes.y; v.y <= sizes.y; v.y += 1.0f) |
offsets[i++] = v; |
for (i = 0; i < num_offsets; ++i) { |
offsets[i].x /= video_width; |
offsets[i].y /= video_height; |
} |
filter->vs = create_vert_shader(filter); |
if (!filter->vs) |
goto error_vs; |
filter->fs = create_frag_shader(filter, num_offsets, offsets, matrix_values); |
if (!filter->fs) |
goto error_fs; |
FREE(offsets); |
return true; |
error_fs: |
pipe->delete_vs_state(pipe, filter->vs); |
error_vs: |
FREE(offsets); |
error_offsets: |
pipe->delete_vertex_elements_state(pipe, filter->ves); |
error_ves: |
pipe_resource_reference(&filter->quad.buffer, NULL); |
error_quad: |
pipe->delete_sampler_state(pipe, filter->sampler); |
error_sampler: |
pipe->delete_blend_state(pipe, filter->blend); |
error_blend: |
pipe->delete_rasterizer_state(pipe, filter->rs_state); |
error_rs_state: |
return false; |
} |
void |
vl_matrix_filter_cleanup(struct vl_matrix_filter *filter) |
{ |
assert(filter); |
filter->pipe->delete_sampler_state(filter->pipe, filter->sampler); |
filter->pipe->delete_blend_state(filter->pipe, filter->blend); |
filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state); |
filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves); |
pipe_resource_reference(&filter->quad.buffer, NULL); |
filter->pipe->delete_vs_state(filter->pipe, filter->vs); |
filter->pipe->delete_fs_state(filter->pipe, filter->fs); |
} |
void |
vl_matrix_filter_render(struct vl_matrix_filter *filter, |
struct pipe_sampler_view *src, |
struct pipe_surface *dst) |
{ |
struct pipe_viewport_state viewport; |
struct pipe_framebuffer_state fb_state; |
assert(filter && src && dst); |
memset(&viewport, 0, sizeof(viewport)); |
viewport.scale[0] = dst->width; |
viewport.scale[1] = dst->height; |
viewport.scale[2] = 1; |
memset(&fb_state, 0, sizeof(fb_state)); |
fb_state.width = dst->width; |
fb_state.height = dst->height; |
fb_state.nr_cbufs = 1; |
fb_state.cbufs[0] = dst; |
filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state); |
filter->pipe->bind_blend_state(filter->pipe, filter->blend); |
filter->pipe->bind_sampler_states(filter->pipe, PIPE_SHADER_FRAGMENT, |
0, 1, &filter->sampler); |
filter->pipe->set_sampler_views(filter->pipe, PIPE_SHADER_FRAGMENT, |
0, 1, &src); |
filter->pipe->bind_vs_state(filter->pipe, filter->vs); |
filter->pipe->bind_fs_state(filter->pipe, filter->fs); |
filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); |
filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport); |
filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad); |
filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves); |
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_matrix_filter.h |
---|
0,0 → 1,64 |
/************************************************************************** |
* |
* Copyright 2012 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 VMWARE 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. |
* |
**************************************************************************/ |
/* implementation of all matrix based filters like |
gaussian, mean, laplacian, emboss, sharpness etc.. */ |
#ifndef vl_matrix_filter_h |
#define vl_matrix_filter_h |
#include "pipe/p_state.h" |
struct vl_matrix_filter |
{ |
struct pipe_context *pipe; |
struct pipe_vertex_buffer quad; |
void *rs_state; |
void *blend; |
void *sampler; |
void *ves; |
void *vs, *fs; |
}; |
bool |
vl_matrix_filter_init(struct vl_matrix_filter *filter, struct pipe_context *pipe, |
unsigned video_width, unsigned video_height, |
unsigned matrix_width, unsigned matrix_height, |
const float *matrix_values); |
void |
vl_matrix_filter_cleanup(struct vl_matrix_filter *filter); |
void |
vl_matrix_filter_render(struct vl_matrix_filter *filter, |
struct pipe_sampler_view *src, |
struct pipe_surface *dst); |
#endif /* vl_matrix_filter_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_mc.c |
---|
0,0 → 1,648 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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 <assert.h> |
#include "pipe/p_context.h" |
#include "util/u_sampler.h" |
#include "util/u_draw.h" |
#include "tgsi/tgsi_ureg.h" |
#include "vl_defines.h" |
#include "vl_vertex_buffers.h" |
#include "vl_mc.h" |
#include "vl_idct.h" |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_VTOP = 0, |
VS_O_VBOTTOM, |
VS_O_FLAGS = VS_O_VTOP, |
VS_O_VTEX = VS_O_VBOTTOM |
}; |
static struct ureg_dst |
calc_position(struct vl_mc *r, struct ureg_program *shader, struct ureg_src block_scale) |
{ |
struct ureg_src vrect, vpos; |
struct ureg_dst t_vpos; |
struct ureg_dst o_vpos; |
vrect = ureg_DECL_vs_input(shader, VS_I_RECT); |
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); |
t_vpos = ureg_DECL_temporary(shader); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
/* |
* block_scale = (VL_MACROBLOCK_WIDTH, VL_MACROBLOCK_HEIGHT) / (dst.width, dst.height) |
* |
* t_vpos = (vpos + vrect) * block_scale |
* o_vpos.xy = t_vpos |
* o_vpos.zw = vpos |
*/ |
ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect); |
ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), block_scale); |
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos)); |
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f)); |
return t_vpos; |
} |
static struct ureg_dst |
calc_line(struct ureg_program *shader) |
{ |
struct ureg_dst tmp; |
struct ureg_src pos; |
tmp = ureg_DECL_temporary(shader); |
pos = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS, TGSI_INTERPOLATE_LINEAR); |
/* |
* tmp.y = fraction(pos.y / 2) >= 0.5 ? 1 : 0 |
*/ |
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), pos, ureg_imm1f(shader, 0.5f)); |
ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(tmp)); |
ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(tmp), ureg_imm1f(shader, 0.5f)); |
return tmp; |
} |
static void * |
create_ref_vert_shader(struct vl_mc *r) |
{ |
struct ureg_program *shader; |
struct ureg_src mv_scale; |
struct ureg_src vmv[2]; |
struct ureg_dst t_vpos; |
struct ureg_dst o_vmv[2]; |
unsigned i; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
vmv[0] = ureg_DECL_vs_input(shader, VS_I_MV_TOP); |
vmv[1] = ureg_DECL_vs_input(shader, VS_I_MV_BOTTOM); |
t_vpos = calc_position(r, shader, ureg_imm2f(shader, |
(float)VL_MACROBLOCK_WIDTH / r->buffer_width, |
(float)VL_MACROBLOCK_HEIGHT / r->buffer_height) |
); |
o_vmv[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP); |
o_vmv[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM); |
/* |
* mv_scale.xy = 0.5 / (dst.width, dst.height); |
* mv_scale.z = 1.0f / 4.0f |
* mv_scale.w = 1.0f / 255.0f |
* |
* // Apply motion vectors |
* o_vmv[0..1].xy = vmv[0..1] * mv_scale + t_vpos |
* o_vmv[0..1].zw = vmv[0..1] * mv_scale |
* |
*/ |
mv_scale = ureg_imm4f(shader, |
0.5f / r->buffer_width, |
0.5f / r->buffer_height, |
1.0f / 4.0f, |
1.0f / PIPE_VIDEO_MV_WEIGHT_MAX); |
for (i = 0; i < 2; ++i) { |
ureg_MAD(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_XY), mv_scale, vmv[i], ureg_src(t_vpos)); |
ureg_MUL(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_ZW), mv_scale, vmv[i]); |
} |
ureg_release_temporary(shader, t_vpos); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, r->pipe); |
} |
static void * |
create_ref_frag_shader(struct vl_mc *r) |
{ |
const float y_scale = |
r->buffer_height / 2 * |
r->macroblock_size / VL_MACROBLOCK_HEIGHT; |
struct ureg_program *shader; |
struct ureg_src tc[2], sampler; |
struct ureg_dst ref, field; |
struct ureg_dst fragment; |
unsigned label; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return NULL; |
tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR); |
tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 0); |
ref = ureg_DECL_temporary(shader); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
field = calc_line(shader); |
/* |
* ref = field.z ? tc[1] : tc[0] |
* |
* // Adjust tc acording to top/bottom field selection |
* if (|ref.z|) { |
* ref.y *= y_scale |
* ref.y = floor(ref.y) |
* ref.y += ref.z |
* ref.y /= y_scale |
* } |
* fragment.xyz = tex(ref, sampler[0]) |
*/ |
ureg_CMP(shader, ureg_writemask(ref, TGSI_WRITEMASK_XYZ), |
ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), |
tc[1], tc[0]); |
ureg_CMP(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), |
ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), |
tc[1], tc[0]); |
ureg_IF(shader, ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z), &label); |
ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), |
ureg_src(ref), ureg_imm1f(shader, y_scale)); |
ureg_FLR(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), ureg_src(ref)); |
ureg_ADD(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), |
ureg_src(ref), ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z)); |
ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), |
ureg_src(ref), ureg_imm1f(shader, 1.0f / y_scale)); |
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); |
ureg_ENDIF(shader); |
ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), TGSI_TEXTURE_2D, ureg_src(ref), sampler); |
ureg_release_temporary(shader, ref); |
ureg_release_temporary(shader, field); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, r->pipe); |
} |
static void * |
create_ycbcr_vert_shader(struct vl_mc *r, vl_mc_ycbcr_vert_shader vs_callback, void *callback_priv) |
{ |
struct ureg_program *shader; |
struct ureg_src vrect, vpos; |
struct ureg_dst t_vpos, t_vtex; |
struct ureg_dst o_vpos, o_flags; |
struct vertex2f scale = { |
(float)VL_BLOCK_WIDTH / r->buffer_width * VL_MACROBLOCK_WIDTH / r->macroblock_size, |
(float)VL_BLOCK_HEIGHT / r->buffer_height * VL_MACROBLOCK_HEIGHT / r->macroblock_size |
}; |
unsigned label; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
vrect = ureg_DECL_vs_input(shader, VS_I_RECT); |
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); |
t_vpos = calc_position(r, shader, ureg_imm2f(shader, scale.x, scale.y)); |
t_vtex = ureg_DECL_temporary(shader); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_flags = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_FLAGS); |
/* |
* o_vtex.xy = t_vpos |
* o_flags.z = intra * 0.5 |
* |
* if(interlaced) { |
* t_vtex.xy = vrect.y ? { 0, scale.y } : { -scale.y : 0 } |
* t_vtex.z = vpos.y % 2 |
* t_vtex.y = t_vtex.z ? t_vtex.x : t_vtex.y |
* o_vpos.y = t_vtex.y + t_vpos.y |
* |
* o_flags.w = t_vtex.z ? 0 : 1 |
* } |
* |
*/ |
vs_callback(callback_priv, r, shader, VS_O_VTEX, t_vpos); |
ureg_MUL(shader, ureg_writemask(o_flags, TGSI_WRITEMASK_Z), |
ureg_scalar(vpos, TGSI_SWIZZLE_Z), ureg_imm1f(shader, 0.5f)); |
ureg_MOV(shader, ureg_writemask(o_flags, TGSI_WRITEMASK_W), ureg_imm1f(shader, -1.0f)); |
if (r->macroblock_size == VL_MACROBLOCK_HEIGHT) { //TODO |
ureg_IF(shader, ureg_scalar(vpos, TGSI_SWIZZLE_W), &label); |
ureg_CMP(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), |
ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_Y)), |
ureg_imm2f(shader, 0.0f, scale.y), |
ureg_imm2f(shader, -scale.y, 0.0f)); |
ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Z), |
ureg_scalar(vpos, TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.5f)); |
ureg_FRC(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Z), ureg_src(t_vtex)); |
ureg_CMP(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), |
ureg_negate(ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_Z)), |
ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_X), |
ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_Y)); |
ureg_ADD(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_Y), |
ureg_src(t_vpos), ureg_src(t_vtex)); |
ureg_CMP(shader, ureg_writemask(o_flags, TGSI_WRITEMASK_W), |
ureg_negate(ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_Z)), |
ureg_imm1f(shader, 0.0f), ureg_imm1f(shader, 1.0f)); |
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); |
ureg_ENDIF(shader); |
} |
ureg_release_temporary(shader, t_vtex); |
ureg_release_temporary(shader, t_vpos); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, r->pipe); |
} |
static void * |
create_ycbcr_frag_shader(struct vl_mc *r, float scale, bool invert, |
vl_mc_ycbcr_frag_shader fs_callback, void *callback_priv) |
{ |
struct ureg_program *shader; |
struct ureg_src flags; |
struct ureg_dst tmp; |
struct ureg_dst fragment; |
unsigned label; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return NULL; |
flags = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_FLAGS, TGSI_INTERPOLATE_LINEAR); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
tmp = calc_line(shader); |
/* |
* if (field == tc.w) |
* kill(); |
* else { |
* fragment.xyz = tex(tc, sampler) * scale + tc.z |
* fragment.w = 1.0f |
* } |
*/ |
ureg_SEQ(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), |
ureg_scalar(flags, TGSI_SWIZZLE_W), ureg_src(tmp)); |
ureg_IF(shader, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), &label); |
ureg_KILL(shader); |
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); |
ureg_ELSE(shader, &label); |
fs_callback(callback_priv, r, shader, VS_O_VTEX, tmp); |
if (scale != 1.0f) |
ureg_MAD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), |
ureg_src(tmp), ureg_imm1f(shader, scale), |
ureg_scalar(flags, TGSI_SWIZZLE_Z)); |
else |
ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ), |
ureg_src(tmp), ureg_scalar(flags, TGSI_SWIZZLE_Z)); |
ureg_MUL(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), ureg_src(tmp), ureg_imm1f(shader, invert ? -1.0f : 1.0f)); |
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); |
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader)); |
ureg_ENDIF(shader); |
ureg_release_temporary(shader, tmp); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, r->pipe); |
} |
static bool |
init_pipe_state(struct vl_mc *r) |
{ |
struct pipe_sampler_state sampler; |
struct pipe_blend_state blend; |
struct pipe_rasterizer_state rs_state; |
unsigned i; |
assert(r); |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER; |
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
r->sampler_ref = r->pipe->create_sampler_state(r->pipe, &sampler); |
if (!r->sampler_ref) |
goto error_sampler_ref; |
for (i = 0; i < VL_MC_NUM_BLENDERS; ++i) { |
memset(&blend, 0, sizeof blend); |
blend.independent_blend_enable = 0; |
blend.rt[0].blend_enable = 1; |
blend.rt[0].rgb_func = PIPE_BLEND_ADD; |
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; |
blend.rt[0].alpha_func = PIPE_BLEND_ADD; |
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; |
blend.logicop_enable = 0; |
blend.logicop_func = PIPE_LOGICOP_CLEAR; |
blend.rt[0].colormask = i; |
blend.dither = 0; |
r->blend_clear[i] = r->pipe->create_blend_state(r->pipe, &blend); |
if (!r->blend_clear[i]) |
goto error_blend; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
r->blend_add[i] = r->pipe->create_blend_state(r->pipe, &blend); |
if (!r->blend_add[i]) |
goto error_blend; |
blend.rt[0].rgb_func = PIPE_BLEND_REVERSE_SUBTRACT; |
blend.rt[0].alpha_dst_factor = PIPE_BLEND_REVERSE_SUBTRACT; |
r->blend_sub[i] = r->pipe->create_blend_state(r->pipe, &blend); |
if (!r->blend_sub[i]) |
goto error_blend; |
} |
memset(&rs_state, 0, sizeof(rs_state)); |
/*rs_state.sprite_coord_enable */ |
rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT; |
rs_state.point_quad_rasterization = true; |
rs_state.point_size = VL_BLOCK_WIDTH; |
rs_state.half_pixel_center = true; |
rs_state.bottom_edge_rule = true; |
rs_state.depth_clip = 1; |
r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state); |
if (!r->rs_state) |
goto error_rs_state; |
return true; |
error_rs_state: |
error_blend: |
for (i = 0; i < VL_MC_NUM_BLENDERS; ++i) { |
if (r->blend_sub[i]) |
r->pipe->delete_blend_state(r->pipe, r->blend_sub[i]); |
if (r->blend_add[i]) |
r->pipe->delete_blend_state(r->pipe, r->blend_add[i]); |
if (r->blend_clear[i]) |
r->pipe->delete_blend_state(r->pipe, r->blend_clear[i]); |
} |
r->pipe->delete_sampler_state(r->pipe, r->sampler_ref); |
error_sampler_ref: |
return false; |
} |
static void |
cleanup_pipe_state(struct vl_mc *r) |
{ |
unsigned i; |
assert(r); |
r->pipe->delete_sampler_state(r->pipe, r->sampler_ref); |
for (i = 0; i < VL_MC_NUM_BLENDERS; ++i) { |
r->pipe->delete_blend_state(r->pipe, r->blend_clear[i]); |
r->pipe->delete_blend_state(r->pipe, r->blend_add[i]); |
r->pipe->delete_blend_state(r->pipe, r->blend_sub[i]); |
} |
r->pipe->delete_rasterizer_state(r->pipe, r->rs_state); |
} |
bool |
vl_mc_init(struct vl_mc *renderer, struct pipe_context *pipe, |
unsigned buffer_width, unsigned buffer_height, |
unsigned macroblock_size, float scale, |
vl_mc_ycbcr_vert_shader vs_callback, |
vl_mc_ycbcr_frag_shader fs_callback, |
void *callback_priv) |
{ |
assert(renderer); |
assert(pipe); |
memset(renderer, 0, sizeof(struct vl_mc)); |
renderer->pipe = pipe; |
renderer->buffer_width = buffer_width; |
renderer->buffer_height = buffer_height; |
renderer->macroblock_size = macroblock_size; |
if (!init_pipe_state(renderer)) |
goto error_pipe_state; |
renderer->vs_ref = create_ref_vert_shader(renderer); |
if (!renderer->vs_ref) |
goto error_vs_ref; |
renderer->vs_ycbcr = create_ycbcr_vert_shader(renderer, vs_callback, callback_priv); |
if (!renderer->vs_ycbcr) |
goto error_vs_ycbcr; |
renderer->fs_ref = create_ref_frag_shader(renderer); |
if (!renderer->fs_ref) |
goto error_fs_ref; |
renderer->fs_ycbcr = create_ycbcr_frag_shader(renderer, scale, false, fs_callback, callback_priv); |
if (!renderer->fs_ycbcr) |
goto error_fs_ycbcr; |
renderer->fs_ycbcr_sub = create_ycbcr_frag_shader(renderer, scale, true, fs_callback, callback_priv); |
if (!renderer->fs_ycbcr_sub) |
goto error_fs_ycbcr_sub; |
return true; |
error_fs_ycbcr_sub: |
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr); |
error_fs_ycbcr: |
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ref); |
error_fs_ref: |
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ycbcr); |
error_vs_ycbcr: |
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ref); |
error_vs_ref: |
cleanup_pipe_state(renderer); |
error_pipe_state: |
return false; |
} |
void |
vl_mc_cleanup(struct vl_mc *renderer) |
{ |
assert(renderer); |
cleanup_pipe_state(renderer); |
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ref); |
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ycbcr); |
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ref); |
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr); |
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr_sub); |
} |
bool |
vl_mc_init_buffer(struct vl_mc *renderer, struct vl_mc_buffer *buffer) |
{ |
assert(renderer && buffer); |
buffer->viewport.scale[2] = 1; |
buffer->viewport.translate[0] = 0; |
buffer->viewport.translate[1] = 0; |
buffer->viewport.translate[2] = 0; |
buffer->fb_state.nr_cbufs = 1; |
buffer->fb_state.zsbuf = NULL; |
return true; |
} |
void |
vl_mc_cleanup_buffer(struct vl_mc_buffer *buffer) |
{ |
assert(buffer); |
} |
void |
vl_mc_set_surface(struct vl_mc_buffer *buffer, struct pipe_surface *surface) |
{ |
assert(buffer && surface); |
buffer->surface_cleared = false; |
buffer->viewport.scale[0] = surface->width; |
buffer->viewport.scale[1] = surface->height; |
buffer->fb_state.width = surface->width; |
buffer->fb_state.height = surface->height; |
buffer->fb_state.cbufs[0] = surface; |
} |
static void |
prepare_pipe_4_rendering(struct vl_mc *renderer, struct vl_mc_buffer *buffer, unsigned mask) |
{ |
assert(buffer); |
renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state); |
if (buffer->surface_cleared) |
renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_add[mask]); |
else |
renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_clear[mask]); |
renderer->pipe->set_framebuffer_state(renderer->pipe, &buffer->fb_state); |
renderer->pipe->set_viewport_states(renderer->pipe, 0, 1, &buffer->viewport); |
} |
void |
vl_mc_render_ref(struct vl_mc *renderer, struct vl_mc_buffer *buffer, struct pipe_sampler_view *ref) |
{ |
assert(buffer && ref); |
prepare_pipe_4_rendering(renderer, buffer, PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B); |
renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs_ref); |
renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ref); |
renderer->pipe->set_sampler_views(renderer->pipe, PIPE_SHADER_FRAGMENT, |
0, 1, &ref); |
renderer->pipe->bind_sampler_states(renderer->pipe, PIPE_SHADER_FRAGMENT, |
0, 1, &renderer->sampler_ref); |
util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, |
renderer->buffer_width / VL_MACROBLOCK_WIDTH * |
renderer->buffer_height / VL_MACROBLOCK_HEIGHT); |
buffer->surface_cleared = true; |
} |
void |
vl_mc_render_ycbcr(struct vl_mc *renderer, struct vl_mc_buffer *buffer, unsigned component, unsigned num_instances) |
{ |
unsigned mask = 1 << component; |
assert(buffer); |
if (num_instances == 0) |
return; |
prepare_pipe_4_rendering(renderer, buffer, mask); |
renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs_ycbcr); |
renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ycbcr); |
util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); |
if (buffer->surface_cleared) { |
renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_sub[mask]); |
renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ycbcr_sub); |
util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); |
} |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_mc.h |
---|
0,0 → 1,97 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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_mc_h |
#define vl_mc_h |
#include "pipe/p_state.h" |
#include "pipe/p_video_state.h" |
#include "tgsi/tgsi_ureg.h" |
#include "vl_defines.h" |
#include "vl_types.h" |
#define VL_MC_NUM_BLENDERS (1 << VL_NUM_COMPONENTS) |
struct pipe_context; |
struct vl_mc |
{ |
struct pipe_context *pipe; |
unsigned buffer_width; |
unsigned buffer_height; |
unsigned macroblock_size; |
void *rs_state; |
void *blend_clear[VL_MC_NUM_BLENDERS]; |
void *blend_add[VL_MC_NUM_BLENDERS]; |
void *blend_sub[VL_MC_NUM_BLENDERS]; |
void *vs_ref, *vs_ycbcr; |
void *fs_ref, *fs_ycbcr, *fs_ycbcr_sub; |
void *sampler_ref; |
}; |
struct vl_mc_buffer |
{ |
bool surface_cleared; |
struct pipe_viewport_state viewport; |
struct pipe_framebuffer_state fb_state; |
}; |
typedef void (*vl_mc_ycbcr_vert_shader)(void *priv, struct vl_mc *mc, |
struct ureg_program *shader, |
unsigned first_output, |
struct ureg_dst tex); |
typedef void (*vl_mc_ycbcr_frag_shader)(void *priv, struct vl_mc *mc, |
struct ureg_program *shader, |
unsigned first_input, |
struct ureg_dst dst); |
bool vl_mc_init(struct vl_mc *renderer, struct pipe_context *pipe, |
unsigned picture_width, unsigned picture_height, |
unsigned macroblock_size, float scale, |
vl_mc_ycbcr_vert_shader vs_callback, |
vl_mc_ycbcr_frag_shader fs_callback, |
void *callback_priv); |
void vl_mc_cleanup(struct vl_mc *renderer); |
bool vl_mc_init_buffer(struct vl_mc *renderer, struct vl_mc_buffer *buffer); |
void vl_mc_cleanup_buffer(struct vl_mc_buffer *buffer); |
void vl_mc_set_surface(struct vl_mc_buffer *buffer, struct pipe_surface *surface); |
void vl_mc_render_ref(struct vl_mc *renderer, struct vl_mc_buffer *buffer, struct pipe_sampler_view *ref); |
void vl_mc_render_ycbcr(struct vl_mc *renderer, struct vl_mc_buffer *buffer, unsigned component, unsigned num_instances); |
#endif /* vl_mc_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_median_filter.c |
---|
0,0 → 1,399 |
/************************************************************************** |
* |
* Copyright 2012 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 VMWARE 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 "pipe/p_context.h" |
#include "tgsi/tgsi_ureg.h" |
#include "util/u_draw.h" |
#include "util/u_memory.h" |
#include "util/u_math.h" |
#include "vl_types.h" |
#include "vl_vertex_buffers.h" |
#include "vl_median_filter.h" |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_VTEX = 0 |
}; |
static void * |
create_vert_shader(struct vl_median_filter *filter) |
{ |
struct ureg_program *shader; |
struct ureg_src i_vpos; |
struct ureg_dst o_vpos, o_vtex; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
i_vpos = ureg_DECL_vs_input(shader, 0); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); |
ureg_MOV(shader, o_vpos, i_vpos); |
ureg_MOV(shader, o_vtex, i_vpos); |
ureg_END(shader); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
static inline bool |
is_vec_zero(struct vertex2f v) |
{ |
return v.x == 0.0f && v.y == 0.0f; |
} |
static void * |
create_frag_shader(struct vl_median_filter *filter, |
struct vertex2f *offsets, |
unsigned num_offsets) |
{ |
struct pipe_screen *screen = filter->pipe->screen; |
struct ureg_program *shader; |
struct ureg_src i_vtex; |
struct ureg_src sampler; |
struct ureg_dst *t_array = MALLOC(sizeof(struct ureg_dst) * num_offsets); |
struct ureg_dst o_fragment; |
const unsigned median = num_offsets >> 1; |
int i, j; |
assert(num_offsets & 1); /* we need an odd number of offsets */ |
if (!(num_offsets & 1)) { /* yeah, we REALLY need an odd number of offsets!!! */ |
FREE(t_array); |
return NULL; |
} |
if (num_offsets > screen->get_shader_param( |
screen, TGSI_PROCESSOR_FRAGMENT, PIPE_SHADER_CAP_MAX_TEMPS)) { |
FREE(t_array); |
return NULL; |
} |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) { |
FREE(t_array); |
return NULL; |
} |
i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 0); |
for (i = 0; i < num_offsets; ++i) |
t_array[i] = ureg_DECL_temporary(shader); |
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* |
* t_array[0..*] = vtex + offset[0..*] |
* t_array[0..*] = tex(t_array[0..*], sampler) |
* result = partial_bubblesort(t_array)[mid] |
*/ |
for (i = 0; i < num_offsets; ++i) { |
if (!is_vec_zero(offsets[i])) { |
ureg_ADD(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_XY), |
i_vtex, ureg_imm2f(shader, offsets[i].x, offsets[i].y)); |
ureg_MOV(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_ZW), |
ureg_imm1f(shader, 0.0f)); |
} |
} |
for (i = 0; i < num_offsets; ++i) { |
struct ureg_src src = is_vec_zero(offsets[i]) ? i_vtex : ureg_src(t_array[i]); |
ureg_TEX(shader, t_array[i], TGSI_TEXTURE_2D, src, sampler); |
} |
// TODO: Couldn't this be improved even more? |
for (i = 0; i <= median; ++i) { |
for (j = 1; j < (num_offsets - i - 1); ++j) { |
struct ureg_dst tmp = ureg_DECL_temporary(shader); |
ureg_MOV(shader, tmp, ureg_src(t_array[j])); |
ureg_MAX(shader, t_array[j], ureg_src(t_array[j]), ureg_src(t_array[j - 1])); |
ureg_MIN(shader, t_array[j - 1], ureg_src(tmp), ureg_src(t_array[j - 1])); |
ureg_release_temporary(shader, tmp); |
} |
if (i == median) |
ureg_MAX(shader, t_array[j], ureg_src(t_array[j]), ureg_src(t_array[j - 1])); |
else |
ureg_MIN(shader, t_array[j - 1], ureg_src(t_array[j]), ureg_src(t_array[j - 1])); |
} |
ureg_MOV(shader, o_fragment, ureg_src(t_array[median])); |
ureg_END(shader); |
FREE(t_array); |
return ureg_create_shader_and_destroy(shader, filter->pipe); |
} |
static void |
generate_offsets(enum vl_median_filter_shape shape, unsigned size, |
struct vertex2f **offsets, unsigned *num_offsets) |
{ |
int i = 0, half_size; |
struct vertex2f v; |
assert(offsets && num_offsets); |
/* size needs to be odd */ |
size = align(size + 1, 2) - 1; |
half_size = size >> 1; |
switch(shape) { |
case VL_MEDIAN_FILTER_BOX: |
*num_offsets = size*size; |
break; |
case VL_MEDIAN_FILTER_CROSS: |
case VL_MEDIAN_FILTER_X: |
*num_offsets = size + size - 1; |
break; |
case VL_MEDIAN_FILTER_HORIZONTAL: |
case VL_MEDIAN_FILTER_VERTICAL: |
*num_offsets = size; |
break; |
default: |
*num_offsets = 0; |
return; |
} |
*offsets = MALLOC(sizeof(struct vertex2f) * *num_offsets); |
if (!*offsets) |
return; |
switch(shape) { |
case VL_MEDIAN_FILTER_BOX: |
for (v.x = -half_size; v.x <= half_size; ++v.x) |
for (v.y = -half_size; v.y <= half_size; ++v.y) |
(*offsets)[i++] = v; |
break; |
case VL_MEDIAN_FILTER_CROSS: |
v.y = 0.0f; |
for (v.x = -half_size; v.x <= half_size; ++v.x) |
(*offsets)[i++] = v; |
v.x = 0.0f; |
for (v.y = -half_size; v.y <= half_size; ++v.y) |
if (v.y != 0.0f) |
(*offsets)[i++] = v; |
break; |
case VL_MEDIAN_FILTER_X: |
for (v.x = v.y = -half_size; v.x <= half_size; ++v.x, ++v.y) |
(*offsets)[i++] = v; |
for (v.x = -half_size, v.y = half_size; v.x <= half_size; ++v.x, --v.y) |
if (v.y != 0.0f) |
(*offsets)[i++] = v; |
break; |
case VL_MEDIAN_FILTER_HORIZONTAL: |
v.y = 0.0f; |
for (v.x = -half_size; v.x <= half_size; ++v.x) |
(*offsets)[i++] = v; |
break; |
case VL_MEDIAN_FILTER_VERTICAL: |
v.x = 0.0f; |
for (v.y = -half_size; v.y <= half_size; ++v.y) |
(*offsets)[i++] = v; |
break; |
} |
assert(i == *num_offsets); |
} |
bool |
vl_median_filter_init(struct vl_median_filter *filter, struct pipe_context *pipe, |
unsigned width, unsigned height, unsigned size, |
enum vl_median_filter_shape shape) |
{ |
struct pipe_rasterizer_state rs_state; |
struct pipe_blend_state blend; |
struct pipe_sampler_state sampler; |
struct vertex2f *offsets = NULL; |
struct pipe_vertex_element ve; |
unsigned i, num_offsets = 0; |
assert(filter && pipe); |
assert(width && height); |
assert(size > 1 && size < 20); |
memset(filter, 0, sizeof(*filter)); |
filter->pipe = pipe; |
memset(&rs_state, 0, sizeof(rs_state)); |
rs_state.half_pixel_center = true; |
rs_state.bottom_edge_rule = true; |
rs_state.depth_clip = 1; |
filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); |
if (!filter->rs_state) |
goto error_rs_state; |
memset(&blend, 0, sizeof blend); |
blend.rt[0].rgb_func = PIPE_BLEND_ADD; |
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_func = PIPE_BLEND_ADD; |
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.logicop_func = PIPE_LOGICOP_CLEAR; |
blend.rt[0].colormask = PIPE_MASK_RGBA; |
filter->blend = pipe->create_blend_state(pipe, &blend); |
if (!filter->blend) |
goto error_blend; |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
filter->sampler = pipe->create_sampler_state(pipe, &sampler); |
if (!filter->sampler) |
goto error_sampler; |
filter->quad = vl_vb_upload_quads(pipe); |
if(!filter->quad.buffer) |
goto error_quad; |
memset(&ve, 0, sizeof(ve)); |
ve.src_offset = 0; |
ve.instance_divisor = 0; |
ve.vertex_buffer_index = 0; |
ve.src_format = PIPE_FORMAT_R32G32_FLOAT; |
filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve); |
if (!filter->ves) |
goto error_ves; |
generate_offsets(shape, size, &offsets, &num_offsets); |
if (!offsets) |
goto error_offsets; |
for (i = 0; i < num_offsets; ++i) { |
offsets[i].x /= width; |
offsets[i].y /= height; |
} |
filter->vs = create_vert_shader(filter); |
if (!filter->vs) |
goto error_vs; |
filter->fs = create_frag_shader(filter, offsets, num_offsets); |
if (!filter->fs) |
goto error_fs; |
FREE(offsets); |
return true; |
error_fs: |
pipe->delete_vs_state(pipe, filter->vs); |
error_vs: |
FREE(offsets); |
error_offsets: |
pipe->delete_vertex_elements_state(pipe, filter->ves); |
error_ves: |
pipe_resource_reference(&filter->quad.buffer, NULL); |
error_quad: |
pipe->delete_sampler_state(pipe, filter->sampler); |
error_sampler: |
pipe->delete_blend_state(pipe, filter->blend); |
error_blend: |
pipe->delete_rasterizer_state(pipe, filter->rs_state); |
error_rs_state: |
return false; |
} |
void |
vl_median_filter_cleanup(struct vl_median_filter *filter) |
{ |
assert(filter); |
filter->pipe->delete_sampler_state(filter->pipe, filter->sampler); |
filter->pipe->delete_blend_state(filter->pipe, filter->blend); |
filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state); |
filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves); |
pipe_resource_reference(&filter->quad.buffer, NULL); |
filter->pipe->delete_vs_state(filter->pipe, filter->vs); |
filter->pipe->delete_fs_state(filter->pipe, filter->fs); |
} |
void |
vl_median_filter_render(struct vl_median_filter *filter, |
struct pipe_sampler_view *src, |
struct pipe_surface *dst) |
{ |
struct pipe_viewport_state viewport; |
struct pipe_framebuffer_state fb_state; |
assert(filter && src && dst); |
memset(&viewport, 0, sizeof(viewport)); |
viewport.scale[0] = dst->width; |
viewport.scale[1] = dst->height; |
viewport.scale[2] = 1; |
memset(&fb_state, 0, sizeof(fb_state)); |
fb_state.width = dst->width; |
fb_state.height = dst->height; |
fb_state.nr_cbufs = 1; |
fb_state.cbufs[0] = dst; |
filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state); |
filter->pipe->bind_blend_state(filter->pipe, filter->blend); |
filter->pipe->bind_sampler_states(filter->pipe, PIPE_SHADER_FRAGMENT, |
0, 1, &filter->sampler); |
filter->pipe->set_sampler_views(filter->pipe, PIPE_SHADER_FRAGMENT, |
0, 1, &src); |
filter->pipe->bind_vs_state(filter->pipe, filter->vs); |
filter->pipe->bind_fs_state(filter->pipe, filter->fs); |
filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); |
filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport); |
filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad); |
filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves); |
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_median_filter.h |
---|
0,0 → 1,70 |
/************************************************************************** |
* |
* Copyright 2012 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 VMWARE 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. |
* |
**************************************************************************/ |
/* implementation of a median filter for noise reduction */ |
#ifndef vl_median_filter_h |
#define vl_median_filter_h |
#include "pipe/p_state.h" |
enum vl_median_filter_shape |
{ |
VL_MEDIAN_FILTER_BOX, |
VL_MEDIAN_FILTER_CROSS, |
VL_MEDIAN_FILTER_X, |
VL_MEDIAN_FILTER_HORIZONTAL, |
VL_MEDIAN_FILTER_VERTICAL |
}; |
struct vl_median_filter |
{ |
struct pipe_context *pipe; |
struct pipe_vertex_buffer quad; |
void *rs_state; |
void *blend; |
void *sampler; |
void *ves; |
void *vs, *fs; |
}; |
bool |
vl_median_filter_init(struct vl_median_filter *filter, struct pipe_context *pipe, |
unsigned width, unsigned height, unsigned size, |
enum vl_median_filter_shape shape); |
void |
vl_median_filter_cleanup(struct vl_median_filter *filter); |
void |
vl_median_filter_render(struct vl_median_filter *filter, |
struct pipe_sampler_view *src, |
struct pipe_surface *dst); |
#endif /* vl_median_filter_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c |
---|
0,0 → 1,1014 |
/************************************************************************** |
* |
* Copyright 2011 Maarten Lankhorst |
* 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 VMWARE 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 "pipe/p_video_codec.h" |
#include "util/u_memory.h" |
#include "vl_vlc.h" |
#include "vl_mpeg12_bitstream.h" |
enum { |
dct_End_of_Block = 0xFF, |
dct_Escape = 0xFE, |
dct_DC = 0xFD, |
dct_AC = 0xFC |
}; |
struct dct_coeff |
{ |
uint8_t length; |
uint8_t run; |
int16_t level; |
}; |
struct dct_coeff_compressed |
{ |
uint32_t bitcode; |
struct dct_coeff coeff; |
}; |
/* coding table as found in the spec annex B.5 table B-1 */ |
static const struct vl_vlc_compressed macroblock_address_increment[] = { |
{ 0x8000, { 1, 1 } }, |
{ 0x6000, { 3, 2 } }, |
{ 0x4000, { 3, 3 } }, |
{ 0x3000, { 4, 4 } }, |
{ 0x2000, { 4, 5 } }, |
{ 0x1800, { 5, 6 } }, |
{ 0x1000, { 5, 7 } }, |
{ 0x0e00, { 7, 8 } }, |
{ 0x0c00, { 7, 9 } }, |
{ 0x0b00, { 8, 10 } }, |
{ 0x0a00, { 8, 11 } }, |
{ 0x0900, { 8, 12 } }, |
{ 0x0800, { 8, 13 } }, |
{ 0x0700, { 8, 14 } }, |
{ 0x0600, { 8, 15 } }, |
{ 0x05c0, { 10, 16 } }, |
{ 0x0580, { 10, 17 } }, |
{ 0x0540, { 10, 18 } }, |
{ 0x0500, { 10, 19 } }, |
{ 0x04c0, { 10, 20 } }, |
{ 0x0480, { 10, 21 } }, |
{ 0x0460, { 11, 22 } }, |
{ 0x0440, { 11, 23 } }, |
{ 0x0420, { 11, 24 } }, |
{ 0x0400, { 11, 25 } }, |
{ 0x03e0, { 11, 26 } }, |
{ 0x03c0, { 11, 27 } }, |
{ 0x03a0, { 11, 28 } }, |
{ 0x0380, { 11, 29 } }, |
{ 0x0360, { 11, 30 } }, |
{ 0x0340, { 11, 31 } }, |
{ 0x0320, { 11, 32 } }, |
{ 0x0300, { 11, 33 } } |
}; |
#define Q PIPE_MPEG12_MB_TYPE_QUANT |
#define F PIPE_MPEG12_MB_TYPE_MOTION_FORWARD |
#define B PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD |
#define P PIPE_MPEG12_MB_TYPE_PATTERN |
#define I PIPE_MPEG12_MB_TYPE_INTRA |
/* coding table as found in the spec annex B.5 table B-2 */ |
static const struct vl_vlc_compressed macroblock_type_i[] = { |
{ 0x8000, { 1, I } }, |
{ 0x4000, { 2, Q|I } } |
}; |
/* coding table as found in the spec annex B.5 table B-3 */ |
static const struct vl_vlc_compressed macroblock_type_p[] = { |
{ 0x8000, { 1, F|P } }, |
{ 0x4000, { 2, P } }, |
{ 0x2000, { 3, F } }, |
{ 0x1800, { 5, I } }, |
{ 0x1000, { 5, Q|F|P } }, |
{ 0x0800, { 5, Q|P } }, |
{ 0x0400, { 6, Q|I } } |
}; |
/* coding table as found in the spec annex B.5 table B-4 */ |
static const struct vl_vlc_compressed macroblock_type_b[] = { |
{ 0x8000, { 2, F|B } }, |
{ 0xC000, { 2, F|B|P } }, |
{ 0x4000, { 3, B } }, |
{ 0x6000, { 3, B|P } }, |
{ 0x2000, { 4, F } }, |
{ 0x3000, { 4, F|P } }, |
{ 0x1800, { 5, I } }, |
{ 0x1000, { 5, Q|F|B|P } }, |
{ 0x0C00, { 6, Q|F|P } }, |
{ 0x0800, { 6, Q|B|P } }, |
{ 0x0400, { 6, Q|I } } |
}; |
#undef Q |
#undef F |
#undef B |
#undef P |
#undef I |
/* coding table as found in the spec annex B.5 table B-9 */ |
static const struct vl_vlc_compressed coded_block_pattern[] = { |
{ 0xE000, { 3, 60 } }, |
{ 0xD000, { 4, 4 } }, |
{ 0xC000, { 4, 8 } }, |
{ 0xB000, { 4, 16 } }, |
{ 0xA000, { 4, 32 } }, |
{ 0x9800, { 5, 12 } }, |
{ 0x9000, { 5, 48 } }, |
{ 0x8800, { 5, 20 } }, |
{ 0x8000, { 5, 40 } }, |
{ 0x7800, { 5, 28 } }, |
{ 0x7000, { 5, 44 } }, |
{ 0x6800, { 5, 52 } }, |
{ 0x6000, { 5, 56 } }, |
{ 0x5800, { 5, 1 } }, |
{ 0x5000, { 5, 61 } }, |
{ 0x4800, { 5, 2 } }, |
{ 0x4000, { 5, 62 } }, |
{ 0x3C00, { 6, 24 } }, |
{ 0x3800, { 6, 36 } }, |
{ 0x3400, { 6, 3 } }, |
{ 0x3000, { 6, 63 } }, |
{ 0x2E00, { 7, 5 } }, |
{ 0x2C00, { 7, 9 } }, |
{ 0x2A00, { 7, 17 } }, |
{ 0x2800, { 7, 33 } }, |
{ 0x2600, { 7, 6 } }, |
{ 0x2400, { 7, 10 } }, |
{ 0x2200, { 7, 18 } }, |
{ 0x2000, { 7, 34 } }, |
{ 0x1F00, { 8, 7 } }, |
{ 0x1E00, { 8, 11 } }, |
{ 0x1D00, { 8, 19 } }, |
{ 0x1C00, { 8, 35 } }, |
{ 0x1B00, { 8, 13 } }, |
{ 0x1A00, { 8, 49 } }, |
{ 0x1900, { 8, 21 } }, |
{ 0x1800, { 8, 41 } }, |
{ 0x1700, { 8, 14 } }, |
{ 0x1600, { 8, 50 } }, |
{ 0x1500, { 8, 22 } }, |
{ 0x1400, { 8, 42 } }, |
{ 0x1300, { 8, 15 } }, |
{ 0x1200, { 8, 51 } }, |
{ 0x1100, { 8, 23 } }, |
{ 0x1000, { 8, 43 } }, |
{ 0x0F00, { 8, 25 } }, |
{ 0x0E00, { 8, 37 } }, |
{ 0x0D00, { 8, 26 } }, |
{ 0x0C00, { 8, 38 } }, |
{ 0x0B00, { 8, 29 } }, |
{ 0x0A00, { 8, 45 } }, |
{ 0x0900, { 8, 53 } }, |
{ 0x0800, { 8, 57 } }, |
{ 0x0700, { 8, 30 } }, |
{ 0x0600, { 8, 46 } }, |
{ 0x0500, { 8, 54 } }, |
{ 0x0400, { 8, 58 } }, |
{ 0x0380, { 9, 31 } }, |
{ 0x0300, { 9, 47 } }, |
{ 0x0280, { 9, 55 } }, |
{ 0x0200, { 9, 59 } }, |
{ 0x0180, { 9, 27 } }, |
{ 0x0100, { 9, 39 } }, |
{ 0x0080, { 9, 0 } } |
}; |
/* coding table as found in the spec annex B.5 table B-10 */ |
static const struct vl_vlc_compressed motion_code[] = { |
{ 0x0320, { 11, -16 } }, |
{ 0x0360, { 11, -15 } }, |
{ 0x03a0, { 11, -14 } }, |
{ 0x03e0, { 11, -13 } }, |
{ 0x0420, { 11, -12 } }, |
{ 0x0460, { 11, -11 } }, |
{ 0x04c0, { 10, -10 } }, |
{ 0x0540, { 10, -9 } }, |
{ 0x05c0, { 10, -8 } }, |
{ 0x0700, { 8, -7 } }, |
{ 0x0900, { 8, -6 } }, |
{ 0x0b00, { 8, -5 } }, |
{ 0x0e00, { 7, -4 } }, |
{ 0x1800, { 5, -3 } }, |
{ 0x3000, { 4, -2 } }, |
{ 0x6000, { 3, -1 } }, |
{ 0x8000, { 1, 0 } }, |
{ 0x4000, { 3, 1 } }, |
{ 0x2000, { 4, 2 } }, |
{ 0x1000, { 5, 3 } }, |
{ 0x0c00, { 7, 4 } }, |
{ 0x0a00, { 8, 5 } }, |
{ 0x0800, { 8, 6 } }, |
{ 0x0600, { 8, 7 } }, |
{ 0x0580, { 10, 8 } }, |
{ 0x0500, { 10, 9 } }, |
{ 0x0480, { 10, 10 } }, |
{ 0x0440, { 11, 11 } }, |
{ 0x0400, { 11, 12 } }, |
{ 0x03c0, { 11, 13 } }, |
{ 0x0380, { 11, 14 } }, |
{ 0x0340, { 11, 15 } }, |
{ 0x0300, { 11, 16 } } |
}; |
/* coding table as found in the spec annex B.5 table B-11 */ |
static const struct vl_vlc_compressed dmvector[] = { |
{ 0x0000, { 1, 0 } }, |
{ 0x8000, { 2, 1 } }, |
{ 0xc000, { 2, -1 } } |
}; |
/* coding table as found in the spec annex B.5 table B-12 */ |
static const struct vl_vlc_compressed dct_dc_size_luminance[] = { |
{ 0x8000, { 3, 0 } }, |
{ 0x0000, { 2, 1 } }, |
{ 0x4000, { 2, 2 } }, |
{ 0xA000, { 3, 3 } }, |
{ 0xC000, { 3, 4 } }, |
{ 0xE000, { 4, 5 } }, |
{ 0xF000, { 5, 6 } }, |
{ 0xF800, { 6, 7 } }, |
{ 0xFC00, { 7, 8 } }, |
{ 0xFE00, { 8, 9 } }, |
{ 0xFF00, { 9, 10 } }, |
{ 0xFF80, { 9, 11 } } |
}; |
/* coding table as found in the spec annex B.5 table B-13 */ |
static const struct vl_vlc_compressed dct_dc_size_chrominance[] = { |
{ 0x0000, { 2, 0 } }, |
{ 0x4000, { 2, 1 } }, |
{ 0x8000, { 2, 2 } }, |
{ 0xC000, { 3, 3 } }, |
{ 0xE000, { 4, 4 } }, |
{ 0xF000, { 5, 5 } }, |
{ 0xF800, { 6, 6 } }, |
{ 0xFC00, { 7, 7 } }, |
{ 0xFE00, { 8, 8 } }, |
{ 0xFF00, { 9, 9 } }, |
{ 0xFF80, { 10, 10 } }, |
{ 0xFFC0, { 10, 11 } } |
}; |
/* coding table as found in the spec annex B.5 table B-14 */ |
static const struct dct_coeff_compressed dct_coeff_tbl_zero[] = { |
{ 0x8000, { 2, dct_End_of_Block, 0 } }, |
{ 0x8000, { 1, dct_DC, 1 } }, |
{ 0xC000, { 2, dct_AC, 1 } }, |
{ 0x6000, { 3, 1, 1 } }, |
{ 0x4000, { 4, 0, 2 } }, |
{ 0x5000, { 4, 2, 1 } }, |
{ 0x2800, { 5, 0, 3 } }, |
{ 0x3800, { 5, 3, 1 } }, |
{ 0x3000, { 5, 4, 1 } }, |
{ 0x1800, { 6, 1, 2 } }, |
{ 0x1C00, { 6, 5, 1 } }, |
{ 0x1400, { 6, 6, 1 } }, |
{ 0x1000, { 6, 7, 1 } }, |
{ 0x0C00, { 7, 0, 4 } }, |
{ 0x0800, { 7, 2, 2 } }, |
{ 0x0E00, { 7, 8, 1 } }, |
{ 0x0A00, { 7, 9, 1 } }, |
{ 0x0400, { 6, dct_Escape, 0 } }, |
{ 0x2600, { 8, 0, 5 } }, |
{ 0x2100, { 8, 0, 6 } }, |
{ 0x2500, { 8, 1, 3 } }, |
{ 0x2400, { 8, 3, 2 } }, |
{ 0x2700, { 8, 10, 1 } }, |
{ 0x2300, { 8, 11, 1 } }, |
{ 0x2200, { 8, 12, 1 } }, |
{ 0x2000, { 8, 13, 1 } }, |
{ 0x0280, { 10, 0, 7 } }, |
{ 0x0300, { 10, 1, 4 } }, |
{ 0x02C0, { 10, 2, 3 } }, |
{ 0x03C0, { 10, 4, 2 } }, |
{ 0x0240, { 10, 5, 2 } }, |
{ 0x0380, { 10, 14, 1 } }, |
{ 0x0340, { 10, 15, 1 } }, |
{ 0x0200, { 10, 16, 1 } }, |
{ 0x01D0, { 12, 0, 8 } }, |
{ 0x0180, { 12, 0, 9 } }, |
{ 0x0130, { 12, 0, 10 } }, |
{ 0x0100, { 12, 0, 11 } }, |
{ 0x01B0, { 12, 1, 5 } }, |
{ 0x0140, { 12, 2, 4 } }, |
{ 0x01C0, { 12, 3, 3 } }, |
{ 0x0120, { 12, 4, 3 } }, |
{ 0x01E0, { 12, 6, 2 } }, |
{ 0x0150, { 12, 7, 2 } }, |
{ 0x0110, { 12, 8, 2 } }, |
{ 0x01F0, { 12, 17, 1 } }, |
{ 0x01A0, { 12, 18, 1 } }, |
{ 0x0190, { 12, 19, 1 } }, |
{ 0x0170, { 12, 20, 1 } }, |
{ 0x0160, { 12, 21, 1 } }, |
{ 0x00D0, { 13, 0, 12 } }, |
{ 0x00C8, { 13, 0, 13 } }, |
{ 0x00C0, { 13, 0, 14 } }, |
{ 0x00B8, { 13, 0, 15 } }, |
{ 0x00B0, { 13, 1, 6 } }, |
{ 0x00A8, { 13, 1, 7 } }, |
{ 0x00A0, { 13, 2, 5 } }, |
{ 0x0098, { 13, 3, 4 } }, |
{ 0x0090, { 13, 5, 3 } }, |
{ 0x0088, { 13, 9, 2 } }, |
{ 0x0080, { 13, 10, 2 } }, |
{ 0x00F8, { 13, 22, 1 } }, |
{ 0x00F0, { 13, 23, 1 } }, |
{ 0x00E8, { 13, 24, 1 } }, |
{ 0x00E0, { 13, 25, 1 } }, |
{ 0x00D8, { 13, 26, 1 } }, |
{ 0x007C, { 14, 0, 16 } }, |
{ 0x0078, { 14, 0, 17 } }, |
{ 0x0074, { 14, 0, 18 } }, |
{ 0x0070, { 14, 0, 19 } }, |
{ 0x006C, { 14, 0, 20 } }, |
{ 0x0068, { 14, 0, 21 } }, |
{ 0x0064, { 14, 0, 22 } }, |
{ 0x0060, { 14, 0, 23 } }, |
{ 0x005C, { 14, 0, 24 } }, |
{ 0x0058, { 14, 0, 25 } }, |
{ 0x0054, { 14, 0, 26 } }, |
{ 0x0050, { 14, 0, 27 } }, |
{ 0x004C, { 14, 0, 28 } }, |
{ 0x0048, { 14, 0, 29 } }, |
{ 0x0044, { 14, 0, 30 } }, |
{ 0x0040, { 14, 0, 31 } }, |
{ 0x0030, { 15, 0, 32 } }, |
{ 0x002E, { 15, 0, 33 } }, |
{ 0x002C, { 15, 0, 34 } }, |
{ 0x002A, { 15, 0, 35 } }, |
{ 0x0028, { 15, 0, 36 } }, |
{ 0x0026, { 15, 0, 37 } }, |
{ 0x0024, { 15, 0, 38 } }, |
{ 0x0022, { 15, 0, 39 } }, |
{ 0x0020, { 15, 0, 40 } }, |
{ 0x003E, { 15, 1, 8 } }, |
{ 0x003C, { 15, 1, 9 } }, |
{ 0x003A, { 15, 1, 10 } }, |
{ 0x0038, { 15, 1, 11 } }, |
{ 0x0036, { 15, 1, 12 } }, |
{ 0x0034, { 15, 1, 13 } }, |
{ 0x0032, { 15, 1, 14 } }, |
{ 0x0013, { 16, 1, 15 } }, |
{ 0x0012, { 16, 1, 16 } }, |
{ 0x0011, { 16, 1, 17 } }, |
{ 0x0010, { 16, 1, 18 } }, |
{ 0x0014, { 16, 6, 3 } }, |
{ 0x001A, { 16, 11, 2 } }, |
{ 0x0019, { 16, 12, 2 } }, |
{ 0x0018, { 16, 13, 2 } }, |
{ 0x0017, { 16, 14, 2 } }, |
{ 0x0016, { 16, 15, 2 } }, |
{ 0x0015, { 16, 16, 2 } }, |
{ 0x001F, { 16, 27, 1 } }, |
{ 0x001E, { 16, 28, 1 } }, |
{ 0x001D, { 16, 29, 1 } }, |
{ 0x001C, { 16, 30, 1 } }, |
{ 0x001B, { 16, 31, 1 } } |
}; |
/* coding table as found in the spec annex B.5 table B-15 */ |
static const struct dct_coeff_compressed dct_coeff_tbl_one[] = { |
{ 0x6000, { 4, dct_End_of_Block, 0 } }, |
{ 0x8000, { 2, 0, 1 } }, |
{ 0x4000, { 3, 1, 1 } }, |
{ 0xC000, { 3, 0, 2 } }, |
{ 0x2800, { 5, 2, 1 } }, |
{ 0x7000, { 4, 0, 3 } }, |
{ 0x3800, { 5, 3, 1 } }, |
{ 0x1800, { 6, 4, 1 } }, |
{ 0x3000, { 5, 1, 2 } }, |
{ 0x1C00, { 6, 5, 1 } }, |
{ 0x0C00, { 7, 6, 1 } }, |
{ 0x0800, { 7, 7, 1 } }, |
{ 0xE000, { 5, 0, 4 } }, |
{ 0x0E00, { 7, 2, 2 } }, |
{ 0x0A00, { 7, 8, 1 } }, |
{ 0xF000, { 7, 9, 1 } }, |
{ 0x0400, { 6, dct_Escape, 0 } }, |
{ 0xE800, { 5, 0, 5 } }, |
{ 0x1400, { 6, 0, 6 } }, |
{ 0xF200, { 7, 1, 3 } }, |
{ 0x2600, { 8, 3, 2 } }, |
{ 0xF400, { 7, 10, 1 } }, |
{ 0x2100, { 8, 11, 1 } }, |
{ 0x2500, { 8, 12, 1 } }, |
{ 0x2400, { 8, 13, 1 } }, |
{ 0x1000, { 6, 0, 7 } }, |
{ 0x2700, { 8, 1, 4 } }, |
{ 0xFC00, { 8, 2, 3 } }, |
{ 0xFD00, { 8, 4, 2 } }, |
{ 0x0200, { 9, 5, 2 } }, |
{ 0x0280, { 9, 14, 1 } }, |
{ 0x0380, { 9, 15, 1 } }, |
{ 0x0340, { 10, 16, 1 } }, |
{ 0xF600, { 7, 0, 8 } }, |
{ 0xF800, { 7, 0, 9 } }, |
{ 0x2300, { 8, 0, 10 } }, |
{ 0x2200, { 8, 0, 11 } }, |
{ 0x2000, { 8, 1, 5 } }, |
{ 0x0300, { 10, 2, 4 } }, |
{ 0x01C0, { 12, 3, 3 } }, |
{ 0x0120, { 12, 4, 3 } }, |
{ 0x01E0, { 12, 6, 2 } }, |
{ 0x0150, { 12, 7, 2 } }, |
{ 0x0110, { 12, 8, 2 } }, |
{ 0x01F0, { 12, 17, 1 } }, |
{ 0x01A0, { 12, 18, 1 } }, |
{ 0x0190, { 12, 19, 1 } }, |
{ 0x0170, { 12, 20, 1 } }, |
{ 0x0160, { 12, 21, 1 } }, |
{ 0xFA00, { 8, 0, 12 } }, |
{ 0xFB00, { 8, 0, 13 } }, |
{ 0xFE00, { 8, 0, 14 } }, |
{ 0xFF00, { 8, 0, 15 } }, |
{ 0x00B0, { 13, 1, 6 } }, |
{ 0x00A8, { 13, 1, 7 } }, |
{ 0x00A0, { 13, 2, 5 } }, |
{ 0x0098, { 13, 3, 4 } }, |
{ 0x0090, { 13, 5, 3 } }, |
{ 0x0088, { 13, 9, 2 } }, |
{ 0x0080, { 13, 10, 2 } }, |
{ 0x00F8, { 13, 22, 1 } }, |
{ 0x00F0, { 13, 23, 1 } }, |
{ 0x00E8, { 13, 24, 1 } }, |
{ 0x00E0, { 13, 25, 1 } }, |
{ 0x00D8, { 13, 26, 1 } }, |
{ 0x007C, { 14, 0, 16 } }, |
{ 0x0078, { 14, 0, 17 } }, |
{ 0x0074, { 14, 0, 18 } }, |
{ 0x0070, { 14, 0, 19 } }, |
{ 0x006C, { 14, 0, 20 } }, |
{ 0x0068, { 14, 0, 21 } }, |
{ 0x0064, { 14, 0, 22 } }, |
{ 0x0060, { 14, 0, 23 } }, |
{ 0x005C, { 14, 0, 24 } }, |
{ 0x0058, { 14, 0, 25 } }, |
{ 0x0054, { 14, 0, 26 } }, |
{ 0x0050, { 14, 0, 27 } }, |
{ 0x004C, { 14, 0, 28 } }, |
{ 0x0048, { 14, 0, 29 } }, |
{ 0x0044, { 14, 0, 30 } }, |
{ 0x0040, { 14, 0, 31 } }, |
{ 0x0030, { 15, 0, 32 } }, |
{ 0x002E, { 15, 0, 33 } }, |
{ 0x002C, { 15, 0, 34 } }, |
{ 0x002A, { 15, 0, 35 } }, |
{ 0x0028, { 15, 0, 36 } }, |
{ 0x0026, { 15, 0, 37 } }, |
{ 0x0024, { 15, 0, 38 } }, |
{ 0x0022, { 15, 0, 39 } }, |
{ 0x0020, { 15, 0, 40 } }, |
{ 0x003E, { 15, 1, 8 } }, |
{ 0x003C, { 15, 1, 9 } }, |
{ 0x003A, { 15, 1, 10 } }, |
{ 0x0038, { 15, 1, 11 } }, |
{ 0x0036, { 15, 1, 12 } }, |
{ 0x0034, { 15, 1, 13 } }, |
{ 0x0032, { 15, 1, 14 } }, |
{ 0x0013, { 16, 1, 15 } }, |
{ 0x0012, { 16, 1, 16 } }, |
{ 0x0011, { 16, 1, 17 } }, |
{ 0x0010, { 16, 1, 18 } }, |
{ 0x0014, { 16, 6, 3 } }, |
{ 0x001A, { 16, 11, 2 } }, |
{ 0x0019, { 16, 12, 2 } }, |
{ 0x0018, { 16, 13, 2 } }, |
{ 0x0017, { 16, 14, 2 } }, |
{ 0x0016, { 16, 15, 2 } }, |
{ 0x0015, { 16, 16, 2 } }, |
{ 0x001F, { 16, 27, 1 } }, |
{ 0x001E, { 16, 28, 1 } }, |
{ 0x001D, { 16, 29, 1 } }, |
{ 0x001C, { 16, 30, 1 } }, |
{ 0x001B, { 16, 31, 1 } } |
}; |
/* q_scale_type */ |
static const unsigned quant_scale[2][32] = { |
{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, |
32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 }, |
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, |
28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 } |
}; |
static struct vl_vlc_entry tbl_B1[1 << 11]; |
static struct vl_vlc_entry tbl_B2[1 << 2]; |
static struct vl_vlc_entry tbl_B3[1 << 6]; |
static struct vl_vlc_entry tbl_B4[1 << 6]; |
static struct vl_vlc_entry tbl_B9[1 << 9]; |
static struct vl_vlc_entry tbl_B10[1 << 11]; |
static struct vl_vlc_entry tbl_B11[1 << 2]; |
static struct vl_vlc_entry tbl_B12[1 << 10]; |
static struct vl_vlc_entry tbl_B13[1 << 10]; |
static struct dct_coeff tbl_B14_DC[1 << 17]; |
static struct dct_coeff tbl_B14_AC[1 << 17]; |
static struct dct_coeff tbl_B15[1 << 17]; |
static INLINE void |
init_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *src, |
unsigned size, bool is_DC) |
{ |
unsigned i; |
for (i=0;i<(1<<17);++i) { |
dst[i].length = 0; |
dst[i].level = 0; |
dst[i].run = dct_End_of_Block; |
} |
for(; size > 0; --size, ++src) { |
struct dct_coeff coeff = src->coeff; |
bool has_sign = true; |
switch (coeff.run) { |
case dct_End_of_Block: |
if (is_DC) |
continue; |
has_sign = false; |
break; |
case dct_Escape: |
has_sign = false; |
break; |
case dct_DC: |
if (!is_DC) |
continue; |
coeff.length += 1; |
coeff.run = 1; |
break; |
case dct_AC: |
if (is_DC) |
continue; |
coeff.length += 1; |
coeff.run = 1; |
break; |
default: |
coeff.length += 1; |
coeff.run += 1; |
break; |
} |
for(i=0; i<(1 << (17 - coeff.length)); ++i) |
dst[src->bitcode << 1 | i] = coeff; |
if (has_sign) { |
coeff.level = -coeff.level; |
for(; i<(1 << (18 - coeff.length)); ++i) |
dst[src->bitcode << 1 | i] = coeff; |
} |
} |
} |
static INLINE void |
init_tables() |
{ |
vl_vlc_init_table(tbl_B1, Elements(tbl_B1), macroblock_address_increment, Elements(macroblock_address_increment)); |
vl_vlc_init_table(tbl_B2, Elements(tbl_B2), macroblock_type_i, Elements(macroblock_type_i)); |
vl_vlc_init_table(tbl_B3, Elements(tbl_B3), macroblock_type_p, Elements(macroblock_type_p)); |
vl_vlc_init_table(tbl_B4, Elements(tbl_B4), macroblock_type_b, Elements(macroblock_type_b)); |
vl_vlc_init_table(tbl_B9, Elements(tbl_B9), coded_block_pattern, Elements(coded_block_pattern)); |
vl_vlc_init_table(tbl_B10, Elements(tbl_B10), motion_code, Elements(motion_code)); |
vl_vlc_init_table(tbl_B11, Elements(tbl_B11), dmvector, Elements(dmvector)); |
vl_vlc_init_table(tbl_B12, Elements(tbl_B12), dct_dc_size_luminance, Elements(dct_dc_size_luminance)); |
vl_vlc_init_table(tbl_B13, Elements(tbl_B13), dct_dc_size_chrominance, Elements(dct_dc_size_chrominance)); |
init_dct_coeff_table(tbl_B14_DC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), true); |
init_dct_coeff_table(tbl_B14_AC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), false); |
init_dct_coeff_table(tbl_B15, dct_coeff_tbl_one, Elements(dct_coeff_tbl_one), false); |
} |
static INLINE int |
DIV2DOWN(int todiv) |
{ |
return (todiv&~1)/2; |
} |
static INLINE int |
DIV2UP(int todiv) |
{ |
return (todiv+1)/2; |
} |
static INLINE void |
motion_vector(struct vl_mpg12_bs *bs, int r, int s, int dmv, short delta[2], short dmvector[2]) |
{ |
int t; |
for (t = 0; t < 2; ++t) { |
int motion_code; |
int r_size = bs->desc->f_code[s][t]; |
vl_vlc_fillbits(&bs->vlc); |
motion_code = vl_vlc_get_vlclbf(&bs->vlc, tbl_B10, 11); |
assert(r_size >= 0); |
if (r_size && motion_code) { |
int residual = vl_vlc_get_uimsbf(&bs->vlc, r_size) + 1; |
delta[t] = ((abs(motion_code) - 1) << r_size) + residual; |
if (motion_code < 0) |
delta[t] = -delta[t]; |
} else |
delta[t] = motion_code; |
if (dmv) |
dmvector[t] = vl_vlc_get_vlclbf(&bs->vlc, tbl_B11, 2); |
} |
} |
static INLINE int |
wrap(short f, int shift) |
{ |
if (f < (-16 << shift)) |
return f + (32 << shift); |
else if (f >= 16 << shift) |
return f - (32 << shift); |
else |
return f; |
} |
static INLINE void |
motion_vector_frame(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb) |
{ |
int dmv = mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME; |
short dmvector[2], delta[2]; |
if (mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_FIELD) { |
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s; |
motion_vector(bs, 0, s, dmv, delta, dmvector); |
mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc->f_code[s][0]); |
mb->PMV[0][s][1] = wrap(DIV2DOWN(mb->PMV[0][s][1]) + delta[1], bs->desc->f_code[s][1]) * 2; |
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2); |
motion_vector(bs, 1, s, dmv, delta, dmvector); |
mb->PMV[1][s][0] = wrap(mb->PMV[1][s][0] + delta[0], bs->desc->f_code[s][0]); |
mb->PMV[1][s][1] = wrap(DIV2DOWN(mb->PMV[1][s][1]) + delta[1], bs->desc->f_code[s][1]) * 2; |
} else { |
motion_vector(bs, 0, s, dmv, delta, dmvector); |
mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc->f_code[s][0]); |
mb->PMV[0][s][1] = wrap(mb->PMV[0][s][1] + delta[1], bs->desc->f_code[s][1]); |
} |
} |
static INLINE void |
motion_vector_field(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb) |
{ |
int dmv = mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME; |
short dmvector[2], delta[2]; |
if (mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_16x8) { |
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s; |
motion_vector(bs, 0, s, dmv, delta, dmvector); |
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2); |
motion_vector(bs, 1, s, dmv, delta, dmvector); |
} else { |
if (!dmv) |
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s; |
motion_vector(bs, 0, s, dmv, delta, dmvector); |
} |
} |
static INLINE void |
reset_predictor(struct vl_mpg12_bs *bs) { |
bs->pred_dc[0] = bs->pred_dc[1] = bs->pred_dc[2] = 0; |
} |
static INLINE void |
decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale) |
{ |
static const unsigned blk2cc[] = { 0, 0, 0, 0, 1, 2 }; |
static const struct vl_vlc_entry *blk2dcsize[] = { |
tbl_B12, tbl_B12, tbl_B12, tbl_B12, tbl_B13, tbl_B13 |
}; |
bool intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA; |
const struct dct_coeff *table = intra ? bs->intra_dct_tbl : tbl_B14_AC; |
const struct dct_coeff *entry; |
int i, cbp, blk = 0; |
short *dst = mb->blocks; |
vl_vlc_fillbits(&bs->vlc); |
mb->coded_block_pattern = cbp = intra ? 0x3F : vl_vlc_get_vlclbf(&bs->vlc, tbl_B9, 9); |
goto entry; |
while(1) { |
vl_vlc_eatbits(&bs->vlc, entry->length); |
if (entry->run == dct_End_of_Block) { |
next_d: |
dst += 64; |
cbp <<= 1; |
cbp &= 0x3F; |
blk++; |
entry: |
if (!cbp) |
break; |
while(!(cbp & 0x20)) { |
cbp <<= 1; |
blk++; |
} |
vl_vlc_fillbits(&bs->vlc); |
if (intra) { |
unsigned cc = blk2cc[blk]; |
unsigned size = vl_vlc_get_vlclbf(&bs->vlc, blk2dcsize[blk], 10); |
if (size) { |
int dct_diff = vl_vlc_get_uimsbf(&bs->vlc, size); |
int half_range = 1 << (size - 1); |
if (dct_diff < half_range) |
dct_diff = (dct_diff + 1) - (2 * half_range); |
bs->pred_dc[cc] += dct_diff; |
} |
dst[0] = bs->pred_dc[cc]; |
i = 0; |
if (bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_D) |
goto next_d; |
} else { |
entry = tbl_B14_DC + vl_vlc_peekbits(&bs->vlc, 17); |
i = -1; |
continue; |
} |
} else if (entry->run == dct_Escape && |
bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) { |
i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1; |
if (i > 64) |
break; |
dst[i] = vl_vlc_get_simsbf(&bs->vlc, 8); |
if (dst[i] == -128) |
dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8) - 256; |
else if (dst[i] == 0) |
dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8); |
dst[i] *= scale; |
} else if (entry->run == dct_Escape) { |
i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1; |
if (i > 64) |
break; |
dst[i] = vl_vlc_get_simsbf(&bs->vlc, 12) * scale; |
} else { |
i += entry->run; |
if (i > 64) |
break; |
dst[i] = entry->level * scale; |
} |
vl_vlc_fillbits(&bs->vlc); |
entry = table + vl_vlc_peekbits(&bs->vlc, 17); |
} |
if (bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_D) |
vl_vlc_eatbits(&bs->vlc, 1); |
} |
static INLINE void |
decode_slice(struct vl_mpg12_bs *bs, struct pipe_video_buffer *target) |
{ |
struct pipe_mpeg12_macroblock mb; |
short dct_blocks[64*6]; |
unsigned dct_scale; |
signed x = -1; |
memset(&mb, 0, sizeof(mb)); |
mb.base.codec = PIPE_VIDEO_FORMAT_MPEG12; |
mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1; |
mb.blocks = dct_blocks; |
reset_predictor(bs); |
vl_vlc_fillbits(&bs->vlc); |
dct_scale = quant_scale[bs->desc->q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)]; |
if (vl_vlc_get_uimsbf(&bs->vlc, 1)) |
while (vl_vlc_get_uimsbf(&bs->vlc, 9) & 1) |
vl_vlc_fillbits(&bs->vlc); |
vl_vlc_fillbits(&bs->vlc); |
assert(vl_vlc_peekbits(&bs->vlc, 23)); |
do { |
int inc = 0; |
while (1) { |
/* MPEG-1 macroblock stuffing, can appear an arbitrary number of times. */ |
while (vl_vlc_peekbits(&bs->vlc, 11) == 15) { |
vl_vlc_eatbits(&bs->vlc, 11); |
vl_vlc_fillbits(&bs->vlc); |
} |
if (vl_vlc_peekbits(&bs->vlc, 11) == 8) { |
vl_vlc_eatbits(&bs->vlc, 11); |
vl_vlc_fillbits(&bs->vlc); |
inc += 33; |
} else { |
inc += vl_vlc_get_vlclbf(&bs->vlc, tbl_B1, 11); |
break; |
} |
} |
if (x != -1) { |
if (!inc) |
return; |
mb.num_skipped_macroblocks = inc - 1; |
bs->decoder->decode_macroblock(bs->decoder, target, &bs->desc->base, &mb.base, 1); |
} |
mb.x = x += inc; |
if (bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) { |
int width = align(bs->decoder->width, 16) / 16; |
mb.y += mb.x / width; |
mb.x = x %= width; |
} |
switch (bs->desc->picture_coding_type) { |
case PIPE_MPEG12_PICTURE_CODING_TYPE_I: |
mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B2, 2); |
break; |
case PIPE_MPEG12_PICTURE_CODING_TYPE_P: |
mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B3, 6); |
break; |
case PIPE_MPEG12_PICTURE_CODING_TYPE_B: |
mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B4, 6); |
break; |
case PIPE_MPEG12_PICTURE_CODING_TYPE_D: |
vl_vlc_eatbits(&bs->vlc, 1); |
mb.macroblock_type = PIPE_MPEG12_MB_TYPE_INTRA; |
break; |
} |
mb.macroblock_modes.value = 0; |
if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) { |
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) { |
if (bs->desc->frame_pred_frame_dct == 0) |
mb.macroblock_modes.bits.frame_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2); |
else |
mb.macroblock_modes.bits.frame_motion_type = 2; |
} else |
mb.macroblock_modes.bits.field_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2); |
} else if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) && bs->desc->concealment_motion_vectors) { |
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) |
mb.macroblock_modes.bits.frame_motion_type = 2; |
else |
mb.macroblock_modes.bits.field_motion_type = 1; |
} |
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME && |
bs->desc->frame_pred_frame_dct == 0 && |
mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN)) |
mb.macroblock_modes.bits.dct_type = vl_vlc_get_uimsbf(&bs->vlc, 1); |
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_QUANT) |
dct_scale = quant_scale[bs->desc->q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)]; |
if (inc > 1 && bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_P) |
memset(mb.PMV, 0, sizeof(mb.PMV)); |
mb.motion_vertical_field_select = 0; |
if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD) || |
(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc->concealment_motion_vectors)) { |
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) |
motion_vector_frame(bs, 0, &mb); |
else |
motion_vector_field(bs, 0, &mb); |
} |
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD) { |
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) |
motion_vector_frame(bs, 1, &mb); |
else |
motion_vector_field(bs, 1, &mb); |
} |
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc->concealment_motion_vectors) { |
unsigned extra = vl_vlc_get_uimsbf(&bs->vlc, 1); |
mb.PMV[1][0][0] = mb.PMV[0][0][0]; |
mb.PMV[1][0][1] = mb.PMV[0][0][1]; |
assert(extra); |
} else if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA || |
!(mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | |
PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD))) { |
memset(mb.PMV, 0, sizeof(mb.PMV)); |
} |
if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD && |
mb.macroblock_modes.bits.frame_motion_type == 2) || |
(mb.macroblock_modes.bits.frame_motion_type == 3)) { |
mb.PMV[1][0][0] = mb.PMV[0][0][0]; |
mb.PMV[1][0][1] = mb.PMV[0][0][1]; |
} |
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD && |
mb.macroblock_modes.bits.frame_motion_type == 2) { |
mb.PMV[1][1][0] = mb.PMV[0][1][0]; |
mb.PMV[1][1][1] = mb.PMV[0][1][1]; |
} |
if (inc > 1 || !(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA)) |
reset_predictor(bs); |
if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN)) { |
memset(dct_blocks, 0, sizeof(dct_blocks)); |
decode_dct(bs, &mb, dct_scale); |
} else |
mb.coded_block_pattern = 0; |
vl_vlc_fillbits(&bs->vlc); |
} while (vl_vlc_bits_left(&bs->vlc) && vl_vlc_peekbits(&bs->vlc, 23)); |
mb.num_skipped_macroblocks = 0; |
bs->decoder->decode_macroblock(bs->decoder, target, &bs->desc->base, &mb.base, 1); |
} |
void |
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_codec *decoder) |
{ |
static bool tables_initialized = false; |
assert(bs); |
memset(bs, 0, sizeof(struct vl_mpg12_bs)); |
bs->decoder = decoder; |
if (!tables_initialized) { |
init_tables(); |
tables_initialized = true; |
} |
} |
void |
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, |
struct pipe_video_buffer *target, |
struct pipe_mpeg12_picture_desc *picture, |
unsigned num_buffers, |
const void * const *buffers, |
const unsigned *sizes) |
{ |
assert(bs); |
bs->desc = picture; |
bs->intra_dct_tbl = picture->intra_vlc_format ? tbl_B15 : tbl_B14_AC; |
vl_vlc_init(&bs->vlc, num_buffers, buffers, sizes); |
while (vl_vlc_search_byte(&bs->vlc, ~0, 0x00) && vl_vlc_bits_left(&bs->vlc) > 32) { |
uint32_t code = vl_vlc_peekbits(&bs->vlc, 32); |
if (code >= 0x101 && code <= 0x1AF) { |
vl_vlc_eatbits(&bs->vlc, 24); |
decode_slice(bs, target); |
/* align to a byte again */ |
vl_vlc_eatbits(&bs->vlc, vl_vlc_valid_bits(&bs->vlc) & 7); |
} else { |
vl_vlc_eatbits(&bs->vlc, 8); |
} |
vl_vlc_fillbits(&bs->vlc); |
} |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h |
---|
0,0 → 1,56 |
/************************************************************************** |
* |
* 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 VMWARE 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_mpeg12_bitstream_h |
#define vl_mpeg12_bitstream_h |
#include "vl_defines.h" |
#include "vl_vlc.h" |
struct vl_mpg12_bs |
{ |
struct pipe_video_codec *decoder; |
struct pipe_mpeg12_picture_desc *desc; |
struct dct_coeff *intra_dct_tbl; |
struct vl_vlc vlc; |
short pred_dc[3]; |
}; |
void |
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_codec *decoder); |
void |
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, |
struct pipe_video_buffer *target, |
struct pipe_mpeg12_picture_desc *picture, |
unsigned num_buffers, |
const void * const *buffers, |
const unsigned *sizes); |
#endif /* vl_mpeg12_bitstream_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c |
---|
0,0 → 1,1213 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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 <math.h> |
#include <assert.h> |
#include "util/u_memory.h" |
#include "util/u_sampler.h" |
#include "util/u_surface.h" |
#include "util/u_video.h" |
#include "vl_mpeg12_decoder.h" |
#include "vl_defines.h" |
#define SCALE_FACTOR_SNORM (32768.0f / 256.0f) |
#define SCALE_FACTOR_SSCALED (1.0f / 256.0f) |
struct format_config { |
enum pipe_format zscan_source_format; |
enum pipe_format idct_source_format; |
enum pipe_format mc_source_format; |
float idct_scale; |
float mc_scale; |
}; |
static const struct format_config bitstream_format_config[] = { |
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SSCALED }, |
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, 1.0f, SCALE_FACTOR_SSCALED }, |
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SNORM }, |
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1.0f, SCALE_FACTOR_SNORM } |
}; |
static const unsigned num_bitstream_format_configs = |
sizeof(bitstream_format_config) / sizeof(struct format_config); |
static const struct format_config idct_format_config[] = { |
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SSCALED }, |
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, 1.0f, SCALE_FACTOR_SSCALED }, |
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SNORM }, |
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1.0f, SCALE_FACTOR_SNORM } |
}; |
static const unsigned num_idct_format_configs = |
sizeof(idct_format_config) / sizeof(struct format_config); |
static const struct format_config mc_format_config[] = { |
//{ PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_NONE, PIPE_FORMAT_R16_SSCALED, 0.0f, SCALE_FACTOR_SSCALED }, |
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_NONE, PIPE_FORMAT_R16_SNORM, 0.0f, SCALE_FACTOR_SNORM } |
}; |
static const unsigned num_mc_format_configs = |
sizeof(mc_format_config) / sizeof(struct format_config); |
static const unsigned const_empty_block_mask_420[3][2][2] = { |
{ { 0x20, 0x10 }, { 0x08, 0x04 } }, |
{ { 0x02, 0x02 }, { 0x02, 0x02 } }, |
{ { 0x01, 0x01 }, { 0x01, 0x01 } } |
}; |
struct video_buffer_private |
{ |
struct pipe_sampler_view *sampler_view_planes[VL_NUM_COMPONENTS]; |
struct pipe_surface *surfaces[VL_MAX_SURFACES]; |
struct vl_mpeg12_buffer *buffer; |
}; |
static void |
vl_mpeg12_destroy_buffer(struct vl_mpeg12_buffer *buf); |
static void |
destroy_video_buffer_private(void *private) |
{ |
struct video_buffer_private *priv = private; |
unsigned i; |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
pipe_sampler_view_reference(&priv->sampler_view_planes[i], NULL); |
for (i = 0; i < VL_MAX_SURFACES; ++i) |
pipe_surface_reference(&priv->surfaces[i], NULL); |
if (priv->buffer) |
vl_mpeg12_destroy_buffer(priv->buffer); |
FREE(priv); |
} |
static struct video_buffer_private * |
get_video_buffer_private(struct vl_mpeg12_decoder *dec, struct pipe_video_buffer *buf) |
{ |
struct pipe_context *pipe = dec->context; |
struct video_buffer_private *priv; |
struct pipe_sampler_view **sv; |
struct pipe_surface **surf; |
unsigned i; |
priv = vl_video_buffer_get_associated_data(buf, &dec->base); |
if (priv) |
return priv; |
priv = CALLOC_STRUCT(video_buffer_private); |
sv = buf->get_sampler_view_planes(buf); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
if (sv[i]) |
priv->sampler_view_planes[i] = pipe->create_sampler_view(pipe, sv[i]->texture, sv[i]); |
surf = buf->get_surfaces(buf); |
for (i = 0; i < VL_MAX_SURFACES; ++i) |
if (surf[i]) |
priv->surfaces[i] = pipe->create_surface(pipe, surf[i]->texture, surf[i]); |
vl_video_buffer_set_associated_data(buf, &dec->base, priv, destroy_video_buffer_private); |
return priv; |
} |
static bool |
init_zscan_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer) |
{ |
struct pipe_resource *res, res_tmpl; |
struct pipe_sampler_view sv_tmpl; |
struct pipe_surface **destination; |
unsigned i; |
assert(dec && buffer); |
memset(&res_tmpl, 0, sizeof(res_tmpl)); |
res_tmpl.target = PIPE_TEXTURE_2D; |
res_tmpl.format = dec->zscan_source_format; |
res_tmpl.width0 = dec->blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; |
res_tmpl.height0 = align(dec->num_blocks, dec->blocks_per_line) / dec->blocks_per_line; |
res_tmpl.depth0 = 1; |
res_tmpl.array_size = 1; |
res_tmpl.usage = PIPE_USAGE_STREAM; |
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; |
res = dec->context->screen->resource_create(dec->context->screen, &res_tmpl); |
if (!res) |
goto error_source; |
memset(&sv_tmpl, 0, sizeof(sv_tmpl)); |
u_sampler_view_default_template(&sv_tmpl, res, res->format); |
sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = PIPE_SWIZZLE_RED; |
buffer->zscan_source = dec->context->create_sampler_view(dec->context, res, &sv_tmpl); |
pipe_resource_reference(&res, NULL); |
if (!buffer->zscan_source) |
goto error_sampler; |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) |
destination = dec->idct_source->get_surfaces(dec->idct_source); |
else |
destination = dec->mc_source->get_surfaces(dec->mc_source); |
if (!destination) |
goto error_surface; |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
if (!vl_zscan_init_buffer(i == 0 ? &dec->zscan_y : &dec->zscan_c, |
&buffer->zscan[i], buffer->zscan_source, destination[i])) |
goto error_plane; |
return true; |
error_plane: |
for (; i > 0; --i) |
vl_zscan_cleanup_buffer(&buffer->zscan[i - 1]); |
error_surface: |
error_sampler: |
pipe_sampler_view_reference(&buffer->zscan_source, NULL); |
error_source: |
return false; |
} |
static void |
cleanup_zscan_buffer(struct vl_mpeg12_buffer *buffer) |
{ |
unsigned i; |
assert(buffer); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
vl_zscan_cleanup_buffer(&buffer->zscan[i]); |
pipe_sampler_view_reference(&buffer->zscan_source, NULL); |
} |
static bool |
init_idct_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer) |
{ |
struct pipe_sampler_view **idct_source_sv, **mc_source_sv; |
unsigned i; |
assert(dec && buffer); |
idct_source_sv = dec->idct_source->get_sampler_view_planes(dec->idct_source); |
if (!idct_source_sv) |
goto error_source_sv; |
mc_source_sv = dec->mc_source->get_sampler_view_planes(dec->mc_source); |
if (!mc_source_sv) |
goto error_mc_source_sv; |
for (i = 0; i < 3; ++i) |
if (!vl_idct_init_buffer(i == 0 ? &dec->idct_y : &dec->idct_c, |
&buffer->idct[i], idct_source_sv[i], |
mc_source_sv[i])) |
goto error_plane; |
return true; |
error_plane: |
for (; i > 0; --i) |
vl_idct_cleanup_buffer(&buffer->idct[i - 1]); |
error_mc_source_sv: |
error_source_sv: |
return false; |
} |
static void |
cleanup_idct_buffer(struct vl_mpeg12_buffer *buf) |
{ |
unsigned i; |
assert(buf); |
for (i = 0; i < 3; ++i) |
vl_idct_cleanup_buffer(&buf->idct[i]); |
} |
static bool |
init_mc_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buf) |
{ |
assert(dec && buf); |
if(!vl_mc_init_buffer(&dec->mc_y, &buf->mc[0])) |
goto error_mc_y; |
if(!vl_mc_init_buffer(&dec->mc_c, &buf->mc[1])) |
goto error_mc_cb; |
if(!vl_mc_init_buffer(&dec->mc_c, &buf->mc[2])) |
goto error_mc_cr; |
return true; |
error_mc_cr: |
vl_mc_cleanup_buffer(&buf->mc[1]); |
error_mc_cb: |
vl_mc_cleanup_buffer(&buf->mc[0]); |
error_mc_y: |
return false; |
} |
static void |
cleanup_mc_buffer(struct vl_mpeg12_buffer *buf) |
{ |
unsigned i; |
assert(buf); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
vl_mc_cleanup_buffer(&buf->mc[i]); |
} |
static INLINE void |
MacroBlockTypeToPipeWeights(const struct pipe_mpeg12_macroblock *mb, unsigned weights[2]) |
{ |
assert(mb); |
switch (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) { |
case PIPE_MPEG12_MB_TYPE_MOTION_FORWARD: |
weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX; |
weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN; |
break; |
case (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD): |
weights[0] = PIPE_VIDEO_MV_WEIGHT_HALF; |
weights[1] = PIPE_VIDEO_MV_WEIGHT_HALF; |
break; |
case PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD: |
weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN; |
weights[1] = PIPE_VIDEO_MV_WEIGHT_MAX; |
break; |
default: |
if (mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) { |
weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN; |
weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN; |
} else { |
/* no motion vector, but also not intra mb -> |
just copy the old frame content */ |
weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX; |
weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN; |
} |
break; |
} |
} |
static INLINE struct vl_motionvector |
MotionVectorToPipe(const struct pipe_mpeg12_macroblock *mb, unsigned vector, |
unsigned field_select_mask, unsigned weight) |
{ |
struct vl_motionvector mv; |
assert(mb); |
if (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) { |
switch (mb->macroblock_modes.bits.frame_motion_type) { |
case PIPE_MPEG12_MO_TYPE_FRAME: |
mv.top.x = mb->PMV[0][vector][0]; |
mv.top.y = mb->PMV[0][vector][1]; |
mv.top.field_select = PIPE_VIDEO_FRAME; |
mv.top.weight = weight; |
mv.bottom.x = mb->PMV[0][vector][0]; |
mv.bottom.y = mb->PMV[0][vector][1]; |
mv.bottom.weight = weight; |
mv.bottom.field_select = PIPE_VIDEO_FRAME; |
break; |
case PIPE_MPEG12_MO_TYPE_FIELD: |
mv.top.x = mb->PMV[0][vector][0]; |
mv.top.y = mb->PMV[0][vector][1]; |
mv.top.field_select = (mb->motion_vertical_field_select & field_select_mask) ? |
PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD; |
mv.top.weight = weight; |
mv.bottom.x = mb->PMV[1][vector][0]; |
mv.bottom.y = mb->PMV[1][vector][1]; |
mv.bottom.field_select = (mb->motion_vertical_field_select & (field_select_mask << 2)) ? |
PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD; |
mv.bottom.weight = weight; |
break; |
default: // TODO: Support DUALPRIME and 16x8 |
break; |
} |
} else { |
mv.top.x = mv.top.y = 0; |
mv.top.field_select = PIPE_VIDEO_FRAME; |
mv.top.weight = weight; |
mv.bottom.x = mv.bottom.y = 0; |
mv.bottom.field_select = PIPE_VIDEO_FRAME; |
mv.bottom.weight = weight; |
} |
return mv; |
} |
static INLINE void |
UploadYcbcrBlocks(struct vl_mpeg12_decoder *dec, |
struct vl_mpeg12_buffer *buf, |
const struct pipe_mpeg12_macroblock *mb) |
{ |
unsigned intra; |
unsigned tb, x, y, num_blocks = 0; |
assert(dec && buf); |
assert(mb); |
if (!mb->coded_block_pattern) |
return; |
intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA ? 1 : 0; |
for (y = 0; y < 2; ++y) { |
for (x = 0; x < 2; ++x) { |
if (mb->coded_block_pattern & const_empty_block_mask_420[0][y][x]) { |
struct vl_ycbcr_block *stream = buf->ycbcr_stream[0]; |
stream->x = mb->x * 2 + x; |
stream->y = mb->y * 2 + y; |
stream->intra = intra; |
stream->coding = mb->macroblock_modes.bits.dct_type; |
stream->block_num = buf->block_num++; |
buf->num_ycbcr_blocks[0]++; |
buf->ycbcr_stream[0]++; |
num_blocks++; |
} |
} |
} |
/* TODO: Implement 422, 444 */ |
//assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); |
for (tb = 1; tb < 3; ++tb) { |
if (mb->coded_block_pattern & const_empty_block_mask_420[tb][0][0]) { |
struct vl_ycbcr_block *stream = buf->ycbcr_stream[tb]; |
stream->x = mb->x; |
stream->y = mb->y; |
stream->intra = intra; |
stream->coding = 0; |
stream->block_num = buf->block_num++; |
buf->num_ycbcr_blocks[tb]++; |
buf->ycbcr_stream[tb]++; |
num_blocks++; |
} |
} |
memcpy(buf->texels, mb->blocks, 64 * sizeof(short) * num_blocks); |
buf->texels += 64 * num_blocks; |
} |
static void |
vl_mpeg12_destroy_buffer(struct vl_mpeg12_buffer *buf) |
{ |
assert(buf); |
cleanup_zscan_buffer(buf); |
cleanup_idct_buffer(buf); |
cleanup_mc_buffer(buf); |
vl_vb_cleanup(&buf->vertex_stream); |
FREE(buf); |
} |
static void |
vl_mpeg12_destroy(struct pipe_video_codec *decoder) |
{ |
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder*)decoder; |
unsigned i; |
assert(decoder); |
/* Asserted in softpipe_delete_fs_state() for some reason */ |
dec->context->bind_vs_state(dec->context, NULL); |
dec->context->bind_fs_state(dec->context, NULL); |
dec->context->delete_depth_stencil_alpha_state(dec->context, dec->dsa); |
dec->context->delete_sampler_state(dec->context, dec->sampler_ycbcr); |
vl_mc_cleanup(&dec->mc_y); |
vl_mc_cleanup(&dec->mc_c); |
dec->mc_source->destroy(dec->mc_source); |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) { |
vl_idct_cleanup(&dec->idct_y); |
vl_idct_cleanup(&dec->idct_c); |
dec->idct_source->destroy(dec->idct_source); |
} |
vl_zscan_cleanup(&dec->zscan_y); |
vl_zscan_cleanup(&dec->zscan_c); |
dec->context->delete_vertex_elements_state(dec->context, dec->ves_ycbcr); |
dec->context->delete_vertex_elements_state(dec->context, dec->ves_mv); |
pipe_resource_reference(&dec->quads.buffer, NULL); |
pipe_resource_reference(&dec->pos.buffer, NULL); |
pipe_sampler_view_reference(&dec->zscan_linear, NULL); |
pipe_sampler_view_reference(&dec->zscan_normal, NULL); |
pipe_sampler_view_reference(&dec->zscan_alternate, NULL); |
for (i = 0; i < 4; ++i) |
if (dec->dec_buffers[i]) |
vl_mpeg12_destroy_buffer(dec->dec_buffers[i]); |
dec->context->destroy(dec->context); |
FREE(dec); |
} |
static struct vl_mpeg12_buffer * |
vl_mpeg12_get_decode_buffer(struct vl_mpeg12_decoder *dec, struct pipe_video_buffer *target) |
{ |
struct video_buffer_private *priv; |
struct vl_mpeg12_buffer *buffer; |
assert(dec); |
priv = get_video_buffer_private(dec, target); |
if (priv->buffer) |
return priv->buffer; |
buffer = dec->dec_buffers[dec->current_buffer]; |
if (buffer) |
return buffer; |
buffer = CALLOC_STRUCT(vl_mpeg12_buffer); |
if (buffer == NULL) |
return NULL; |
if (!vl_vb_init(&buffer->vertex_stream, dec->context, |
dec->base.width / VL_MACROBLOCK_WIDTH, |
dec->base.height / VL_MACROBLOCK_HEIGHT)) |
goto error_vertex_buffer; |
if (!init_mc_buffer(dec, buffer)) |
goto error_mc; |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) |
if (!init_idct_buffer(dec, buffer)) |
goto error_idct; |
if (!init_zscan_buffer(dec, buffer)) |
goto error_zscan; |
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) |
vl_mpg12_bs_init(&buffer->bs, &dec->base); |
if (dec->base.expect_chunked_decode) |
priv->buffer = buffer; |
else |
dec->dec_buffers[dec->current_buffer] = buffer; |
return buffer; |
error_zscan: |
cleanup_idct_buffer(buffer); |
error_idct: |
cleanup_mc_buffer(buffer); |
error_mc: |
vl_vb_cleanup(&buffer->vertex_stream); |
error_vertex_buffer: |
FREE(buffer); |
return NULL; |
} |
static void |
vl_mpeg12_begin_frame(struct pipe_video_codec *decoder, |
struct pipe_video_buffer *target, |
struct pipe_picture_desc *picture) |
{ |
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder; |
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture; |
struct vl_mpeg12_buffer *buf; |
struct pipe_resource *tex; |
struct pipe_box rect = { 0, 0, 0, 1, 1, 1 }; |
uint8_t intra_matrix[64]; |
uint8_t non_intra_matrix[64]; |
unsigned i; |
assert(dec && target && picture); |
buf = vl_mpeg12_get_decode_buffer(dec, target); |
assert(buf); |
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { |
memcpy(intra_matrix, desc->intra_matrix, sizeof(intra_matrix)); |
memcpy(non_intra_matrix, desc->non_intra_matrix, sizeof(non_intra_matrix)); |
intra_matrix[0] = 1 << (7 - desc->intra_dc_precision); |
} else { |
memset(intra_matrix, 0x10, sizeof(intra_matrix)); |
memset(non_intra_matrix, 0x10, sizeof(non_intra_matrix)); |
} |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
struct vl_zscan *zscan = i == 0 ? &dec->zscan_y : &dec->zscan_c; |
vl_zscan_upload_quant(zscan, &buf->zscan[i], intra_matrix, true); |
vl_zscan_upload_quant(zscan, &buf->zscan[i], non_intra_matrix, false); |
} |
vl_vb_map(&buf->vertex_stream, dec->context); |
tex = buf->zscan_source->texture; |
rect.width = tex->width0; |
rect.height = tex->height0; |
buf->texels = |
dec->context->transfer_map(dec->context, tex, 0, |
PIPE_TRANSFER_WRITE | |
PIPE_TRANSFER_DISCARD_RANGE, |
&rect, &buf->tex_transfer); |
buf->block_num = 0; |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
buf->ycbcr_stream[i] = vl_vb_get_ycbcr_stream(&buf->vertex_stream, i); |
buf->num_ycbcr_blocks[i] = 0; |
} |
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) |
buf->mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i); |
if (dec->base.entrypoint >= PIPE_VIDEO_ENTRYPOINT_IDCT) { |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
vl_zscan_set_layout(&buf->zscan[i], dec->zscan_linear); |
} |
} |
static void |
vl_mpeg12_decode_macroblock(struct pipe_video_codec *decoder, |
struct pipe_video_buffer *target, |
struct pipe_picture_desc *picture, |
const struct pipe_macroblock *macroblocks, |
unsigned num_macroblocks) |
{ |
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder; |
const struct pipe_mpeg12_macroblock *mb = (const struct pipe_mpeg12_macroblock *)macroblocks; |
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture; |
struct vl_mpeg12_buffer *buf; |
unsigned i, j, mv_weights[2]; |
assert(dec && target && picture); |
assert(macroblocks && macroblocks->codec == PIPE_VIDEO_FORMAT_MPEG12); |
buf = vl_mpeg12_get_decode_buffer(dec, target); |
assert(buf); |
for (; num_macroblocks > 0; --num_macroblocks) { |
unsigned mb_addr = mb->y * dec->width_in_macroblocks + mb->x; |
if (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_PATTERN | PIPE_MPEG12_MB_TYPE_INTRA)) |
UploadYcbcrBlocks(dec, buf, mb); |
MacroBlockTypeToPipeWeights(mb, mv_weights); |
for (i = 0; i < 2; ++i) { |
if (!desc->ref[i]) continue; |
buf->mv_stream[i][mb_addr] = MotionVectorToPipe |
( |
mb, i, |
i ? PIPE_MPEG12_FS_FIRST_BACKWARD : PIPE_MPEG12_FS_FIRST_FORWARD, |
mv_weights[i] |
); |
} |
/* see section 7.6.6 of the spec */ |
if (mb->num_skipped_macroblocks > 0) { |
struct vl_motionvector skipped_mv[2]; |
if (desc->ref[0] && !desc->ref[1]) { |
skipped_mv[0].top.x = skipped_mv[0].top.y = 0; |
skipped_mv[0].top.weight = PIPE_VIDEO_MV_WEIGHT_MAX; |
} else { |
skipped_mv[0] = buf->mv_stream[0][mb_addr]; |
skipped_mv[1] = buf->mv_stream[1][mb_addr]; |
} |
skipped_mv[0].top.field_select = PIPE_VIDEO_FRAME; |
skipped_mv[1].top.field_select = PIPE_VIDEO_FRAME; |
skipped_mv[0].bottom = skipped_mv[0].top; |
skipped_mv[1].bottom = skipped_mv[1].top; |
++mb_addr; |
for (i = 0; i < mb->num_skipped_macroblocks; ++i, ++mb_addr) { |
for (j = 0; j < 2; ++j) { |
if (!desc->ref[j]) continue; |
buf->mv_stream[j][mb_addr] = skipped_mv[j]; |
} |
} |
} |
++mb; |
} |
} |
static void |
vl_mpeg12_decode_bitstream(struct pipe_video_codec *decoder, |
struct pipe_video_buffer *target, |
struct pipe_picture_desc *picture, |
unsigned num_buffers, |
const void * const *buffers, |
const unsigned *sizes) |
{ |
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder; |
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture; |
struct vl_mpeg12_buffer *buf; |
unsigned i; |
assert(dec && target && picture); |
buf = vl_mpeg12_get_decode_buffer(dec, target); |
assert(buf); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
vl_zscan_set_layout(&buf->zscan[i], desc->alternate_scan ? |
dec->zscan_alternate : dec->zscan_normal); |
vl_mpg12_bs_decode(&buf->bs, target, desc, num_buffers, buffers, sizes); |
} |
static void |
vl_mpeg12_end_frame(struct pipe_video_codec *decoder, |
struct pipe_video_buffer *target, |
struct pipe_picture_desc *picture) |
{ |
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder; |
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture; |
struct pipe_sampler_view **ref_frames[2]; |
struct pipe_sampler_view **mc_source_sv; |
struct pipe_surface **target_surfaces; |
struct pipe_vertex_buffer vb[3]; |
struct vl_mpeg12_buffer *buf; |
const unsigned *plane_order; |
unsigned i, j, component; |
unsigned nr_components; |
assert(dec && target && picture); |
assert(!target->interlaced); |
buf = vl_mpeg12_get_decode_buffer(dec, target); |
vl_vb_unmap(&buf->vertex_stream, dec->context); |
dec->context->transfer_unmap(dec->context, buf->tex_transfer); |
vb[0] = dec->quads; |
vb[1] = dec->pos; |
target_surfaces = get_video_buffer_private(dec, target)->surfaces; |
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { |
if (desc->ref[i]) |
ref_frames[i] = get_video_buffer_private(dec, desc->ref[i])->sampler_view_planes; |
else |
ref_frames[i] = NULL; |
} |
dec->context->bind_vertex_elements_state(dec->context, dec->ves_mv); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
if (!target_surfaces[i]) continue; |
vl_mc_set_surface(&buf->mc[i], target_surfaces[i]); |
for (j = 0; j < VL_MAX_REF_FRAMES; ++j) { |
if (!ref_frames[j] || !ref_frames[j][i]) continue; |
vb[2] = vl_vb_get_mv(&buf->vertex_stream, j);; |
dec->context->set_vertex_buffers(dec->context, 0, 3, vb); |
vl_mc_render_ref(i ? &dec->mc_c : &dec->mc_y, &buf->mc[i], ref_frames[j][i]); |
} |
} |
dec->context->bind_vertex_elements_state(dec->context, dec->ves_ycbcr); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
if (!buf->num_ycbcr_blocks[i]) continue; |
vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, i); |
dec->context->set_vertex_buffers(dec->context, 0, 2, vb); |
vl_zscan_render(i ? &dec->zscan_c : & dec->zscan_y, &buf->zscan[i] , buf->num_ycbcr_blocks[i]); |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) |
vl_idct_flush(i ? &dec->idct_c : &dec->idct_y, &buf->idct[i], buf->num_ycbcr_blocks[i]); |
} |
plane_order = vl_video_buffer_plane_order(target->buffer_format); |
mc_source_sv = dec->mc_source->get_sampler_view_planes(dec->mc_source); |
for (i = 0, component = 0; component < VL_NUM_COMPONENTS; ++i) { |
if (!target_surfaces[i]) continue; |
nr_components = util_format_get_nr_components(target_surfaces[i]->texture->format); |
for (j = 0; j < nr_components; ++j, ++component) { |
unsigned plane = plane_order[component]; |
if (!buf->num_ycbcr_blocks[plane]) continue; |
vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, plane); |
dec->context->set_vertex_buffers(dec->context, 0, 2, vb); |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) |
vl_idct_prepare_stage2(i ? &dec->idct_c : &dec->idct_y, &buf->idct[plane]); |
else { |
dec->context->set_sampler_views(dec->context, |
PIPE_SHADER_FRAGMENT, 0, 1, |
&mc_source_sv[plane]); |
dec->context->bind_sampler_states(dec->context, |
PIPE_SHADER_FRAGMENT, |
0, 1, &dec->sampler_ycbcr); |
} |
vl_mc_render_ycbcr(i ? &dec->mc_c : &dec->mc_y, &buf->mc[i], j, buf->num_ycbcr_blocks[plane]); |
} |
} |
dec->context->flush(dec->context, NULL, 0); |
++dec->current_buffer; |
dec->current_buffer %= 4; |
} |
static void |
vl_mpeg12_flush(struct pipe_video_codec *decoder) |
{ |
assert(decoder); |
//Noop, for shaders it is much faster to flush everything in end_frame |
} |
static bool |
init_pipe_state(struct vl_mpeg12_decoder *dec) |
{ |
struct pipe_depth_stencil_alpha_state dsa; |
struct pipe_sampler_state sampler; |
unsigned i; |
assert(dec); |
memset(&dsa, 0, sizeof dsa); |
dsa.depth.enabled = 0; |
dsa.depth.writemask = 0; |
dsa.depth.func = PIPE_FUNC_ALWAYS; |
for (i = 0; i < 2; ++i) { |
dsa.stencil[i].enabled = 0; |
dsa.stencil[i].func = PIPE_FUNC_ALWAYS; |
dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; |
dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; |
dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; |
dsa.stencil[i].valuemask = 0; |
dsa.stencil[i].writemask = 0; |
} |
dsa.alpha.enabled = 0; |
dsa.alpha.func = PIPE_FUNC_ALWAYS; |
dsa.alpha.ref_value = 0; |
dec->dsa = dec->context->create_depth_stencil_alpha_state(dec->context, &dsa); |
dec->context->bind_depth_stencil_alpha_state(dec->context, dec->dsa); |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER; |
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
dec->sampler_ycbcr = dec->context->create_sampler_state(dec->context, &sampler); |
if (!dec->sampler_ycbcr) |
return false; |
return true; |
} |
static const struct format_config* |
find_format_config(struct vl_mpeg12_decoder *dec, const struct format_config configs[], unsigned num_configs) |
{ |
struct pipe_screen *screen; |
unsigned i; |
assert(dec); |
screen = dec->context->screen; |
for (i = 0; i < num_configs; ++i) { |
if (!screen->is_format_supported(screen, configs[i].zscan_source_format, PIPE_TEXTURE_2D, |
1, PIPE_BIND_SAMPLER_VIEW)) |
continue; |
if (configs[i].idct_source_format != PIPE_FORMAT_NONE) { |
if (!screen->is_format_supported(screen, configs[i].idct_source_format, PIPE_TEXTURE_2D, |
1, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET)) |
continue; |
if (!screen->is_format_supported(screen, configs[i].mc_source_format, PIPE_TEXTURE_3D, |
1, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET)) |
continue; |
} else { |
if (!screen->is_format_supported(screen, configs[i].mc_source_format, PIPE_TEXTURE_2D, |
1, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET)) |
continue; |
} |
return &configs[i]; |
} |
return NULL; |
} |
static bool |
init_zscan(struct vl_mpeg12_decoder *dec, const struct format_config* format_config) |
{ |
unsigned num_channels; |
assert(dec); |
dec->zscan_source_format = format_config->zscan_source_format; |
dec->zscan_linear = vl_zscan_layout(dec->context, vl_zscan_linear, dec->blocks_per_line); |
dec->zscan_normal = vl_zscan_layout(dec->context, vl_zscan_normal, dec->blocks_per_line); |
dec->zscan_alternate = vl_zscan_layout(dec->context, vl_zscan_alternate, dec->blocks_per_line); |
num_channels = dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT ? 4 : 1; |
if (!vl_zscan_init(&dec->zscan_y, dec->context, dec->base.width, dec->base.height, |
dec->blocks_per_line, dec->num_blocks, num_channels)) |
return false; |
if (!vl_zscan_init(&dec->zscan_c, dec->context, dec->chroma_width, dec->chroma_height, |
dec->blocks_per_line, dec->num_blocks, num_channels)) |
return false; |
return true; |
} |
static bool |
init_idct(struct vl_mpeg12_decoder *dec, const struct format_config* format_config) |
{ |
unsigned nr_of_idct_render_targets, max_inst; |
enum pipe_format formats[3]; |
struct pipe_video_buffer templat; |
struct pipe_sampler_view *matrix = NULL; |
nr_of_idct_render_targets = dec->context->screen->get_param |
( |
dec->context->screen, PIPE_CAP_MAX_RENDER_TARGETS |
); |
max_inst = dec->context->screen->get_shader_param |
( |
dec->context->screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_INSTRUCTIONS |
); |
// Just assume we need 32 inst per render target, not 100% true, but should work in most cases |
if (nr_of_idct_render_targets >= 4 && max_inst >= 32*4) |
// more than 4 render targets usually doesn't makes any seens |
nr_of_idct_render_targets = 4; |
else |
nr_of_idct_render_targets = 1; |
formats[0] = formats[1] = formats[2] = format_config->idct_source_format; |
memset(&templat, 0, sizeof(templat)); |
templat.width = dec->base.width / 4; |
templat.height = dec->base.height; |
templat.chroma_format = dec->base.chroma_format; |
dec->idct_source = vl_video_buffer_create_ex |
( |
dec->context, &templat, |
formats, 1, 1, PIPE_USAGE_DEFAULT |
); |
if (!dec->idct_source) |
goto error_idct_source; |
formats[0] = formats[1] = formats[2] = format_config->mc_source_format; |
memset(&templat, 0, sizeof(templat)); |
templat.width = dec->base.width / nr_of_idct_render_targets; |
templat.height = dec->base.height / 4; |
templat.chroma_format = dec->base.chroma_format; |
dec->mc_source = vl_video_buffer_create_ex |
( |
dec->context, &templat, |
formats, nr_of_idct_render_targets, 1, PIPE_USAGE_DEFAULT |
); |
if (!dec->mc_source) |
goto error_mc_source; |
if (!(matrix = vl_idct_upload_matrix(dec->context, format_config->idct_scale))) |
goto error_matrix; |
if (!vl_idct_init(&dec->idct_y, dec->context, dec->base.width, dec->base.height, |
nr_of_idct_render_targets, matrix, matrix)) |
goto error_y; |
if(!vl_idct_init(&dec->idct_c, dec->context, dec->chroma_width, dec->chroma_height, |
nr_of_idct_render_targets, matrix, matrix)) |
goto error_c; |
pipe_sampler_view_reference(&matrix, NULL); |
return true; |
error_c: |
vl_idct_cleanup(&dec->idct_y); |
error_y: |
pipe_sampler_view_reference(&matrix, NULL); |
error_matrix: |
dec->mc_source->destroy(dec->mc_source); |
error_mc_source: |
dec->idct_source->destroy(dec->idct_source); |
error_idct_source: |
return false; |
} |
static bool |
init_mc_source_widthout_idct(struct vl_mpeg12_decoder *dec, const struct format_config* format_config) |
{ |
enum pipe_format formats[3]; |
struct pipe_video_buffer templat; |
formats[0] = formats[1] = formats[2] = format_config->mc_source_format; |
memset(&templat, 0, sizeof(templat)); |
templat.width = dec->base.width; |
templat.height = dec->base.height; |
templat.chroma_format = dec->base.chroma_format; |
dec->mc_source = vl_video_buffer_create_ex |
( |
dec->context, &templat, |
formats, 1, 1, PIPE_USAGE_DEFAULT |
); |
return dec->mc_source != NULL; |
} |
static void |
mc_vert_shader_callback(void *priv, struct vl_mc *mc, |
struct ureg_program *shader, |
unsigned first_output, |
struct ureg_dst tex) |
{ |
struct vl_mpeg12_decoder *dec = priv; |
struct ureg_dst o_vtex; |
assert(priv && mc); |
assert(shader); |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) { |
struct vl_idct *idct = mc == &dec->mc_y ? &dec->idct_y : &dec->idct_c; |
vl_idct_stage2_vert_shader(idct, shader, first_output, tex); |
} else { |
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output); |
ureg_MOV(shader, ureg_writemask(o_vtex, TGSI_WRITEMASK_XY), ureg_src(tex)); |
} |
} |
static void |
mc_frag_shader_callback(void *priv, struct vl_mc *mc, |
struct ureg_program *shader, |
unsigned first_input, |
struct ureg_dst dst) |
{ |
struct vl_mpeg12_decoder *dec = priv; |
struct ureg_src src, sampler; |
assert(priv && mc); |
assert(shader); |
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) { |
struct vl_idct *idct = mc == &dec->mc_y ? &dec->idct_y : &dec->idct_c; |
vl_idct_stage2_frag_shader(idct, shader, first_input, dst); |
} else { |
src = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input, TGSI_INTERPOLATE_LINEAR); |
sampler = ureg_DECL_sampler(shader, 0); |
ureg_TEX(shader, dst, TGSI_TEXTURE_2D, src, sampler); |
} |
} |
struct pipe_video_codec * |
vl_create_mpeg12_decoder(struct pipe_context *context, |
const struct pipe_video_codec *templat) |
{ |
const unsigned block_size_pixels = VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; |
const struct format_config *format_config; |
struct vl_mpeg12_decoder *dec; |
assert(u_reduce_video_profile(templat->profile) == PIPE_VIDEO_FORMAT_MPEG12); |
dec = CALLOC_STRUCT(vl_mpeg12_decoder); |
if (!dec) |
return NULL; |
dec->base = *templat; |
dec->base.context = context; |
dec->context = context->screen->context_create(context->screen, NULL); |
dec->base.destroy = vl_mpeg12_destroy; |
dec->base.begin_frame = vl_mpeg12_begin_frame; |
dec->base.decode_macroblock = vl_mpeg12_decode_macroblock; |
dec->base.decode_bitstream = vl_mpeg12_decode_bitstream; |
dec->base.end_frame = vl_mpeg12_end_frame; |
dec->base.flush = vl_mpeg12_flush; |
dec->blocks_per_line = MAX2(util_next_power_of_two(dec->base.width) / block_size_pixels, 4); |
dec->num_blocks = (dec->base.width * dec->base.height) / block_size_pixels; |
dec->width_in_macroblocks = align(dec->base.width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH; |
/* TODO: Implement 422, 444 */ |
assert(dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); |
if (dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { |
dec->chroma_width = dec->base.width / 2; |
dec->chroma_height = dec->base.height / 2; |
dec->num_blocks = dec->num_blocks * 2; |
} else if (dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) { |
dec->chroma_width = dec->base.width / 2; |
dec->chroma_height = dec->base.height; |
dec->num_blocks = dec->num_blocks * 2 + dec->num_blocks; |
} else { |
dec->chroma_width = dec->base.width; |
dec->chroma_height = dec->base.height; |
dec->num_blocks = dec->num_blocks * 3; |
} |
dec->quads = vl_vb_upload_quads(dec->context); |
dec->pos = vl_vb_upload_pos( |
dec->context, |
dec->base.width / VL_MACROBLOCK_WIDTH, |
dec->base.height / VL_MACROBLOCK_HEIGHT |
); |
dec->ves_ycbcr = vl_vb_get_ves_ycbcr(dec->context); |
dec->ves_mv = vl_vb_get_ves_mv(dec->context); |
switch (templat->entrypoint) { |
case PIPE_VIDEO_ENTRYPOINT_BITSTREAM: |
format_config = find_format_config(dec, bitstream_format_config, num_bitstream_format_configs); |
break; |
case PIPE_VIDEO_ENTRYPOINT_IDCT: |
format_config = find_format_config(dec, idct_format_config, num_idct_format_configs); |
break; |
case PIPE_VIDEO_ENTRYPOINT_MC: |
format_config = find_format_config(dec, mc_format_config, num_mc_format_configs); |
break; |
default: |
assert(0); |
FREE(dec); |
return NULL; |
} |
if (!format_config) { |
FREE(dec); |
return NULL; |
} |
if (!init_zscan(dec, format_config)) |
goto error_zscan; |
if (templat->entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) { |
if (!init_idct(dec, format_config)) |
goto error_sources; |
} else { |
if (!init_mc_source_widthout_idct(dec, format_config)) |
goto error_sources; |
} |
if (!vl_mc_init(&dec->mc_y, dec->context, dec->base.width, dec->base.height, |
VL_MACROBLOCK_HEIGHT, format_config->mc_scale, |
mc_vert_shader_callback, mc_frag_shader_callback, dec)) |
goto error_mc_y; |
// TODO |
if (!vl_mc_init(&dec->mc_c, dec->context, dec->base.width, dec->base.height, |
VL_BLOCK_HEIGHT, format_config->mc_scale, |
mc_vert_shader_callback, mc_frag_shader_callback, dec)) |
goto error_mc_c; |
if (!init_pipe_state(dec)) |
goto error_pipe_state; |
return &dec->base; |
error_pipe_state: |
vl_mc_cleanup(&dec->mc_c); |
error_mc_c: |
vl_mc_cleanup(&dec->mc_y); |
error_mc_y: |
if (templat->entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) { |
vl_idct_cleanup(&dec->idct_y); |
vl_idct_cleanup(&dec->idct_c); |
dec->idct_source->destroy(dec->idct_source); |
} |
dec->mc_source->destroy(dec->mc_source); |
error_sources: |
vl_zscan_cleanup(&dec->zscan_y); |
vl_zscan_cleanup(&dec->zscan_c); |
error_zscan: |
FREE(dec); |
return NULL; |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h |
---|
0,0 → 1,110 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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_mpeg12_decoder_h |
#define vl_mpeg12_decoder_h |
#include "pipe/p_video_codec.h" |
#include "vl_mpeg12_bitstream.h" |
#include "vl_zscan.h" |
#include "vl_idct.h" |
#include "vl_mc.h" |
#include "vl_vertex_buffers.h" |
#include "vl_video_buffer.h" |
struct pipe_screen; |
struct pipe_context; |
struct vl_mpeg12_decoder |
{ |
struct pipe_video_codec base; |
struct pipe_context *context; |
unsigned chroma_width, chroma_height; |
unsigned blocks_per_line; |
unsigned num_blocks; |
unsigned width_in_macroblocks; |
enum pipe_format zscan_source_format; |
struct pipe_vertex_buffer quads; |
struct pipe_vertex_buffer pos; |
void *ves_ycbcr; |
void *ves_mv; |
void *sampler_ycbcr; |
struct pipe_sampler_view *zscan_linear; |
struct pipe_sampler_view *zscan_normal; |
struct pipe_sampler_view *zscan_alternate; |
struct pipe_video_buffer *idct_source; |
struct pipe_video_buffer *mc_source; |
struct vl_zscan zscan_y, zscan_c; |
struct vl_idct idct_y, idct_c; |
struct vl_mc mc_y, mc_c; |
void *dsa; |
unsigned current_buffer; |
struct vl_mpeg12_buffer *dec_buffers[4]; |
}; |
struct vl_mpeg12_buffer |
{ |
struct vl_vertex_buffer vertex_stream; |
unsigned block_num; |
unsigned num_ycbcr_blocks[3]; |
struct pipe_sampler_view *zscan_source; |
struct vl_mpg12_bs bs; |
struct vl_zscan_buffer zscan[VL_NUM_COMPONENTS]; |
struct vl_idct_buffer idct[VL_NUM_COMPONENTS]; |
struct vl_mc_buffer mc[VL_NUM_COMPONENTS]; |
struct pipe_transfer *tex_transfer; |
short *texels; |
struct vl_ycbcr_block *ycbcr_stream[VL_NUM_COMPONENTS]; |
struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES]; |
}; |
/** |
* creates a shader based mpeg12 decoder |
*/ |
struct pipe_video_codec * |
vl_create_mpeg12_decoder(struct pipe_context *pipe, |
const struct pipe_video_codec *templat); |
#endif /* vl_mpeg12_decoder_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_rbsp.h |
---|
0,0 → 1,164 |
/************************************************************************** |
* |
* Copyright 2013 Advanced Micro Devices, Inc. |
* 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. |
* |
**************************************************************************/ |
/* |
* Authors: |
* Christian König <christian.koenig@amd.com> |
* |
*/ |
/* |
* Functions for reading the raw byte sequence payload of H.264 |
*/ |
#ifndef vl_rbsp_h |
#define vl_rbsp_h |
#include "vl/vl_vlc.h" |
struct vl_rbsp { |
struct vl_vlc nal; |
unsigned escaped; |
}; |
/** |
* Initialize the RBSP object |
*/ |
static INLINE void vl_rbsp_init(struct vl_rbsp *rbsp, struct vl_vlc *nal, unsigned num_bits) |
{ |
unsigned bits_left = vl_vlc_bits_left(nal); |
/* copy the position */ |
rbsp->nal = *nal; |
rbsp->escaped = 0; |
/* search for the end of the NAL unit */ |
while (vl_vlc_search_byte(nal, num_bits, 0x00)) { |
if (vl_vlc_peekbits(nal, 24) == 0x000001 || |
vl_vlc_peekbits(nal, 32) == 0x00000001) { |
vl_vlc_limit(&rbsp->nal, bits_left - vl_vlc_bits_left(nal)); |
return; |
} |
vl_vlc_eatbits(nal, 8); |
} |
} |
/** |
* Make at least 16 more bits available |
*/ |
static INLINE void vl_rbsp_fillbits(struct vl_rbsp *rbsp) |
{ |
unsigned valid = vl_vlc_valid_bits(&rbsp->nal); |
unsigned i, bits; |
/* abort if we still have enough bits */ |
if (valid >= 32) |
return; |
vl_vlc_fillbits(&rbsp->nal); |
/* abort if we have less than 24 bits left in this nal */ |
if (vl_vlc_bits_left(&rbsp->nal) < 24) |
return; |
/* check that we have enough bits left from the last fillbits */ |
assert(valid >= rbsp->escaped); |
/* handle the already escaped bits */ |
valid -= rbsp->escaped; |
/* search for the emulation prevention three byte */ |
rbsp->escaped = 16; |
bits = vl_vlc_valid_bits(&rbsp->nal); |
for (i = valid + 24; i <= bits; i += 8) { |
if ((vl_vlc_peekbits(&rbsp->nal, i) & 0xffffff) == 0x3) { |
vl_vlc_removebits(&rbsp->nal, i - 8, 8); |
rbsp->escaped = bits - i; |
bits -= 8; |
i += 8; |
} |
} |
} |
/** |
* Return an unsigned integer from the first n bits |
*/ |
static INLINE unsigned vl_rbsp_u(struct vl_rbsp *rbsp, unsigned n) |
{ |
if (n == 0) |
return 0; |
vl_rbsp_fillbits(rbsp); |
return vl_vlc_get_uimsbf(&rbsp->nal, n); |
} |
/** |
* Return an unsigned exponential Golomb encoded integer |
*/ |
static INLINE unsigned vl_rbsp_ue(struct vl_rbsp *rbsp) |
{ |
unsigned bits = 0; |
vl_rbsp_fillbits(rbsp); |
while (!vl_vlc_get_uimsbf(&rbsp->nal, 1)) |
++bits; |
return (1 << bits) - 1 + vl_rbsp_u(rbsp, bits); |
} |
/** |
* Return an signed exponential Golomb encoded integer |
*/ |
static INLINE signed vl_rbsp_se(struct vl_rbsp *rbsp) |
{ |
signed codeNum = vl_rbsp_ue(rbsp); |
if (codeNum & 1) |
return (codeNum + 1) >> 1; |
else |
return -(codeNum >> 1); |
} |
/** |
* Are more data available in the RBSP ? |
*/ |
static INLINE bool vl_rbsp_more_data(struct vl_rbsp *rbsp) |
{ |
unsigned bits, value; |
if (vl_vlc_bits_left(&rbsp->nal) > 8) |
return TRUE; |
bits = vl_vlc_valid_bits(&rbsp->nal); |
value = vl_vlc_peekbits(&rbsp->nal, bits); |
if (value == 0 || value == (1 << (bits - 1))) |
return FALSE; |
return TRUE; |
} |
#endif /* vl_rbsp_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_stubs.c |
---|
0,0 → 1,147 |
#include <assert.h> |
#include "vl_decoder.h" |
#include "vl_mpeg12_bitstream.h" |
#include "vl_mpeg12_decoder.h" |
#include "vl_video_buffer.h" |
#include "vl_zscan.h" |
/* |
* vl_decoder stubs |
*/ |
bool |
vl_profile_supported(struct pipe_screen *screen, |
enum pipe_video_profile profile, |
enum pipe_video_entrypoint entrypoint) |
{ |
assert(0); |
return false; |
} |
int |
vl_level_supported(struct pipe_screen *screen, |
enum pipe_video_profile profile) |
{ |
assert(0); |
return 0; |
} |
struct pipe_video_codec * |
vl_create_decoder(struct pipe_context *pipe, |
const struct pipe_video_codec *templat) |
{ |
assert(0); |
return NULL; |
} |
/* |
* vl_video_buffer stubs |
*/ |
const enum pipe_format * |
vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format) |
{ |
assert(0); |
return NULL; |
} |
boolean |
vl_video_buffer_is_format_supported(struct pipe_screen *screen, |
enum pipe_format format, |
enum pipe_video_profile profile, |
enum pipe_video_entrypoint entrypoint) |
{ |
assert(0); |
return false; |
} |
unsigned |
vl_video_buffer_max_size(struct pipe_screen *screen) |
{ |
assert(0); |
return 0; |
} |
void |
vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf, |
struct pipe_video_codec *vcodec, |
void *associated_data, |
void (*destroy_associated_data)(void *)) |
{ |
assert(0); |
} |
void * |
vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf, |
struct pipe_video_codec *vcodec) |
{ |
assert(0); |
return NULL; |
} |
void |
vl_video_buffer_template(struct pipe_resource *templ, |
const struct pipe_video_buffer *tmpl, |
enum pipe_format resource_format, |
unsigned depth, unsigned array_size, |
unsigned usage, unsigned plane) |
{ |
assert(0); |
} |
struct pipe_video_buffer * |
vl_video_buffer_create(struct pipe_context *pipe, |
const struct pipe_video_buffer *tmpl) |
{ |
assert(0); |
return NULL; |
} |
struct pipe_video_buffer * |
vl_video_buffer_create_ex2(struct pipe_context *pipe, |
const struct pipe_video_buffer *tmpl, |
struct pipe_resource *resources[VL_NUM_COMPONENTS]) |
{ |
assert(0); |
return NULL; |
} |
/* |
* vl_mpeg12_bitstream stubs |
*/ |
void |
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_codec *decoder) |
{ |
assert(0); |
} |
void |
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, |
struct pipe_video_buffer *target, |
struct pipe_mpeg12_picture_desc *picture, |
unsigned num_buffers, |
const void * const *buffers, |
const unsigned *sizes) |
{ |
assert(0); |
} |
/* |
* vl_mpeg12_decoder stubs |
*/ |
struct pipe_video_codec * |
vl_create_mpeg12_decoder(struct pipe_context *pipe, |
const struct pipe_video_codec *templat) |
{ |
assert(0); |
return NULL; |
} |
/* |
* vl_zscan |
*/ |
const int vl_zscan_normal[] = {0}; |
const int vl_zscan_alternate[] = {0}; |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_types.h |
---|
0,0 → 1,51 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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_types_h |
#define vl_types_h |
struct vertex2f |
{ |
float x, y; |
}; |
struct vertex2s |
{ |
short x, y; |
}; |
struct vertex4f |
{ |
float x, y, z, w; |
}; |
struct vertex4s |
{ |
short x, y, z, w; |
}; |
#endif /* vl_types_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_vertex_buffers.c |
---|
0,0 → 1,378 |
/************************************************************************** |
* |
* Copyright 2010 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 VMWARE 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 <assert.h> |
#include "util/u_format.h" |
#include "vl_vertex_buffers.h" |
#include "vl_types.h" |
/* vertices for a quad covering a block */ |
static const struct vertex2f block_quad[4] = { |
{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} |
}; |
struct pipe_vertex_buffer |
vl_vb_upload_quads(struct pipe_context *pipe) |
{ |
struct pipe_vertex_buffer quad; |
struct pipe_transfer *buf_transfer; |
struct vertex2f *v; |
unsigned i; |
assert(pipe); |
/* create buffer */ |
quad.stride = sizeof(struct vertex2f); |
quad.buffer_offset = 0; |
quad.buffer = pipe_buffer_create |
( |
pipe->screen, |
PIPE_BIND_VERTEX_BUFFER, |
PIPE_USAGE_DEFAULT, |
sizeof(struct vertex2f) * 4 |
); |
quad.user_buffer = NULL; |
if(!quad.buffer) |
return quad; |
/* and fill it */ |
v = pipe_buffer_map |
( |
pipe, |
quad.buffer, |
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
&buf_transfer |
); |
for (i = 0; i < 4; ++i, ++v) { |
v->x = block_quad[i].x; |
v->y = block_quad[i].y; |
} |
pipe_buffer_unmap(pipe, buf_transfer); |
return quad; |
} |
struct pipe_vertex_buffer |
vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height) |
{ |
struct pipe_vertex_buffer pos; |
struct pipe_transfer *buf_transfer; |
struct vertex2s *v; |
unsigned x, y; |
assert(pipe); |
/* create buffer */ |
pos.stride = sizeof(struct vertex2s); |
pos.buffer_offset = 0; |
pos.buffer = pipe_buffer_create |
( |
pipe->screen, |
PIPE_BIND_VERTEX_BUFFER, |
PIPE_USAGE_DEFAULT, |
sizeof(struct vertex2s) * width * height |
); |
pos.user_buffer = NULL; |
if(!pos.buffer) |
return pos; |
/* and fill it */ |
v = pipe_buffer_map |
( |
pipe, |
pos.buffer, |
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
&buf_transfer |
); |
for ( y = 0; y < height; ++y) { |
for ( x = 0; x < width; ++x, ++v) { |
v->x = x; |
v->y = y; |
} |
} |
pipe_buffer_unmap(pipe, buf_transfer); |
return pos; |
} |
static struct pipe_vertex_element |
vl_vb_get_quad_vertex_element(void) |
{ |
struct pipe_vertex_element element; |
/* setup rectangle element */ |
element.src_offset = 0; |
element.instance_divisor = 0; |
element.vertex_buffer_index = 0; |
element.src_format = PIPE_FORMAT_R32G32_FLOAT; |
return element; |
} |
static void |
vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements, |
unsigned vertex_buffer_index) |
{ |
unsigned i, offset = 0; |
assert(elements && num_elements); |
for ( i = 0; i < num_elements; ++i ) { |
elements[i].src_offset = offset; |
elements[i].instance_divisor = 1; |
elements[i].vertex_buffer_index = vertex_buffer_index; |
offset += util_format_get_blocksize(elements[i].src_format); |
} |
} |
void * |
vl_vb_get_ves_ycbcr(struct pipe_context *pipe) |
{ |
struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; |
assert(pipe); |
memset(&vertex_elems, 0, sizeof(vertex_elems)); |
vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); |
/* Position element */ |
vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED; |
/* block num element */ |
vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R32_FLOAT; |
vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 2, 1); |
return pipe->create_vertex_elements_state(pipe, 3, vertex_elems); |
} |
void * |
vl_vb_get_ves_mv(struct pipe_context *pipe) |
{ |
struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS]; |
assert(pipe); |
memset(&vertex_elems, 0, sizeof(vertex_elems)); |
vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element(); |
/* Position element */ |
vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED; |
vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1); |
/* motion vector TOP element */ |
vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; |
/* motion vector BOTTOM element */ |
vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED; |
vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2); |
return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems); |
} |
bool |
vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe, |
unsigned width, unsigned height) |
{ |
unsigned i, size; |
assert(buffer); |
buffer->width = width; |
buffer->height = height; |
size = width * height; |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
buffer->ycbcr[i].resource = pipe_buffer_create |
( |
pipe->screen, |
PIPE_BIND_VERTEX_BUFFER, |
PIPE_USAGE_STREAM, |
sizeof(struct vl_ycbcr_block) * size * 4 |
); |
if (!buffer->ycbcr[i].resource) |
goto error_ycbcr; |
} |
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { |
buffer->mv[i].resource = pipe_buffer_create |
( |
pipe->screen, |
PIPE_BIND_VERTEX_BUFFER, |
PIPE_USAGE_STREAM, |
sizeof(struct vl_motionvector) * size |
); |
if (!buffer->mv[i].resource) |
goto error_mv; |
} |
vl_vb_map(buffer, pipe); |
return true; |
error_mv: |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
pipe_resource_reference(&buffer->mv[i].resource, NULL); |
error_ycbcr: |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); |
return false; |
} |
unsigned |
vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer) |
{ |
return 1; |
} |
struct pipe_vertex_buffer |
vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component) |
{ |
struct pipe_vertex_buffer buf; |
assert(buffer); |
buf.stride = sizeof(struct vl_ycbcr_block); |
buf.buffer_offset = 0; |
buf.buffer = buffer->ycbcr[component].resource; |
buf.user_buffer = NULL; |
return buf; |
} |
struct pipe_vertex_buffer |
vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector) |
{ |
struct pipe_vertex_buffer buf; |
assert(buffer); |
buf.stride = sizeof(struct vl_motionvector); |
buf.buffer_offset = 0; |
buf.buffer = buffer->mv[motionvector].resource; |
buf.user_buffer = NULL; |
return buf; |
} |
void |
vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) |
{ |
unsigned i; |
assert(buffer && pipe); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
buffer->ycbcr[i].vertex_stream = pipe_buffer_map |
( |
pipe, |
buffer->ycbcr[i].resource, |
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
&buffer->ycbcr[i].transfer |
); |
} |
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { |
buffer->mv[i].vertex_stream = pipe_buffer_map |
( |
pipe, |
buffer->mv[i].resource, |
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
&buffer->mv[i].transfer |
); |
} |
} |
struct vl_ycbcr_block * |
vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component) |
{ |
assert(buffer); |
assert(component < VL_NUM_COMPONENTS); |
return buffer->ycbcr[component].vertex_stream; |
} |
unsigned |
vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer) |
{ |
assert(buffer); |
return buffer->width; |
} |
struct vl_motionvector * |
vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame) |
{ |
assert(buffer); |
assert(ref_frame < VL_MAX_REF_FRAMES); |
return buffer->mv[ref_frame].vertex_stream; |
} |
void |
vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe) |
{ |
unsigned i; |
assert(buffer && pipe); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer); |
} |
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { |
pipe_buffer_unmap(pipe, buffer->mv[i].transfer); |
} |
} |
void |
vl_vb_cleanup(struct vl_vertex_buffer *buffer) |
{ |
unsigned i; |
assert(buffer); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
pipe_resource_reference(&buffer->ycbcr[i].resource, NULL); |
} |
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) { |
pipe_resource_reference(&buffer->mv[i].resource, NULL); |
} |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_vertex_buffers.h |
---|
0,0 → 1,138 |
/************************************************************************** |
* |
* Copyright 2010 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 VMWARE 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_vertex_buffers_h |
#define vl_vertex_buffers_h |
#include "pipe/p_state.h" |
#include "pipe/p_video_state.h" |
#include "vl_defines.h" |
#include "vl_types.h" |
/* vertex buffers act as a todo list |
* uploading all the usefull informations to video ram |
* so a vertex shader can work with them |
*/ |
/* inputs to the vertex shaders */ |
enum VS_INPUT |
{ |
VS_I_RECT = 0, |
VS_I_VPOS = 1, |
VS_I_BLOCK_NUM = 2, |
VS_I_MV_TOP = 2, |
VS_I_MV_BOTTOM = 3, |
NUM_VS_INPUTS = 4 |
}; |
enum vl_mv_weight |
{ |
PIPE_VIDEO_MV_WEIGHT_MIN = 0, |
PIPE_VIDEO_MV_WEIGHT_HALF = 128, |
PIPE_VIDEO_MV_WEIGHT_MAX = 256 |
}; |
enum vl_field_select |
{ |
PIPE_VIDEO_FRAME = 0, |
PIPE_VIDEO_TOP_FIELD = 1, |
PIPE_VIDEO_BOTTOM_FIELD = 3, |
/* TODO |
PIPE_VIDEO_DUALPRIME |
PIPE_VIDEO_16x8 |
*/ |
}; |
struct vl_motionvector |
{ |
struct { |
int16_t x, y; |
int16_t field_select; /**< enum pipe_video_field_select */ |
int16_t weight; /**< enum pipe_video_mv_weight */ |
} top, bottom; |
}; |
struct vl_ycbcr_block |
{ |
uint8_t x, y; |
uint8_t intra; |
uint8_t coding; |
float block_num; |
}; |
struct vl_vertex_buffer |
{ |
unsigned width, height; |
struct { |
struct pipe_resource *resource; |
struct pipe_transfer *transfer; |
struct vl_ycbcr_block *vertex_stream; |
} ycbcr[VL_NUM_COMPONENTS]; |
struct { |
struct pipe_resource *resource; |
struct pipe_transfer *transfer; |
struct vl_motionvector *vertex_stream; |
} mv[VL_MAX_REF_FRAMES]; |
}; |
struct pipe_vertex_buffer vl_vb_upload_quads(struct pipe_context *pipe); |
struct pipe_vertex_buffer vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height); |
void *vl_vb_get_ves_ycbcr(struct pipe_context *pipe); |
void *vl_vb_get_ves_mv(struct pipe_context *pipe); |
bool vl_vb_init(struct vl_vertex_buffer *buffer, |
struct pipe_context *pipe, |
unsigned width, unsigned height); |
unsigned vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer); |
void vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe); |
struct pipe_vertex_buffer vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component); |
struct vl_ycbcr_block *vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component); |
struct pipe_vertex_buffer vl_vb_get_mv(struct vl_vertex_buffer *buffer, int ref_frame); |
unsigned vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer); |
struct vl_motionvector *vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame); |
void vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe); |
void vl_vb_cleanup(struct vl_vertex_buffer *buffer); |
#endif /* vl_vertex_buffers_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_video_buffer.c |
---|
0,0 → 1,513 |
/************************************************************************** |
* |
* 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 VMWARE 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 <assert.h> |
#include "pipe/p_screen.h" |
#include "pipe/p_context.h" |
#include "pipe/p_state.h" |
#include "util/u_format.h" |
#include "util/u_inlines.h" |
#include "util/u_sampler.h" |
#include "util/u_memory.h" |
#include "vl_video_buffer.h" |
const enum pipe_format const_resource_formats_YV12[3] = { |
PIPE_FORMAT_R8_UNORM, |
PIPE_FORMAT_R8_UNORM, |
PIPE_FORMAT_R8_UNORM |
}; |
const enum pipe_format const_resource_formats_NV12[3] = { |
PIPE_FORMAT_R8_UNORM, |
PIPE_FORMAT_R8G8_UNORM, |
PIPE_FORMAT_NONE |
}; |
const enum pipe_format const_resource_formats_YUVA[3] = { |
PIPE_FORMAT_R8G8B8A8_UNORM, |
PIPE_FORMAT_NONE, |
PIPE_FORMAT_NONE |
}; |
const enum pipe_format const_resource_formats_VUYA[3] = { |
PIPE_FORMAT_B8G8R8A8_UNORM, |
PIPE_FORMAT_NONE, |
PIPE_FORMAT_NONE |
}; |
const enum pipe_format const_resource_formats_YUYV[3] = { |
PIPE_FORMAT_R8G8_R8B8_UNORM, |
PIPE_FORMAT_NONE, |
PIPE_FORMAT_NONE |
}; |
const enum pipe_format const_resource_formats_UYVY[3] = { |
PIPE_FORMAT_G8R8_B8R8_UNORM, |
PIPE_FORMAT_NONE, |
PIPE_FORMAT_NONE |
}; |
const unsigned const_resource_plane_order_YUV[3] = { |
0, |
1, |
2 |
}; |
const unsigned const_resource_plane_order_YVU[3] = { |
0, |
2, |
1 |
}; |
const enum pipe_format * |
vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format) |
{ |
switch(format) { |
case PIPE_FORMAT_YV12: |
return const_resource_formats_YV12; |
case PIPE_FORMAT_NV12: |
return const_resource_formats_NV12; |
case PIPE_FORMAT_R8G8B8A8_UNORM: |
return const_resource_formats_YUVA; |
case PIPE_FORMAT_B8G8R8A8_UNORM: |
return const_resource_formats_VUYA; |
case PIPE_FORMAT_YUYV: |
return const_resource_formats_YUYV; |
case PIPE_FORMAT_UYVY: |
return const_resource_formats_UYVY; |
default: |
return NULL; |
} |
} |
const unsigned * |
vl_video_buffer_plane_order(enum pipe_format format) |
{ |
switch(format) { |
case PIPE_FORMAT_YV12: |
return const_resource_plane_order_YVU; |
case PIPE_FORMAT_NV12: |
case PIPE_FORMAT_R8G8B8A8_UNORM: |
case PIPE_FORMAT_B8G8R8A8_UNORM: |
case PIPE_FORMAT_YUYV: |
case PIPE_FORMAT_UYVY: |
return const_resource_plane_order_YUV; |
default: |
return NULL; |
} |
} |
static enum pipe_format |
vl_video_buffer_surface_format(enum pipe_format format) |
{ |
const struct util_format_description *desc = util_format_description(format); |
/* a subsampled formats can't work as surface use RGBA instead */ |
if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) |
return PIPE_FORMAT_R8G8B8A8_UNORM; |
return format; |
} |
boolean |
vl_video_buffer_is_format_supported(struct pipe_screen *screen, |
enum pipe_format format, |
enum pipe_video_profile profile, |
enum pipe_video_entrypoint entrypoint) |
{ |
const enum pipe_format *resource_formats; |
unsigned i; |
resource_formats = vl_video_buffer_formats(screen, format); |
if (!resource_formats) |
return false; |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
enum pipe_format format = resource_formats[i]; |
if (format == PIPE_FORMAT_NONE) |
continue; |
/* we at least need to sample from it */ |
if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW)) |
return false; |
format = vl_video_buffer_surface_format(format); |
if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) |
return false; |
} |
return true; |
} |
unsigned |
vl_video_buffer_max_size(struct pipe_screen *screen) |
{ |
uint32_t max_2d_texture_level; |
max_2d_texture_level = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); |
return 1 << (max_2d_texture_level-1); |
} |
void |
vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf, |
struct pipe_video_codec *vcodec, |
void *associated_data, |
void (*destroy_associated_data)(void *)) |
{ |
vbuf->codec = vcodec; |
if (vbuf->associated_data == associated_data) |
return; |
if (vbuf->associated_data) |
vbuf->destroy_associated_data(vbuf->associated_data); |
vbuf->associated_data = associated_data; |
vbuf->destroy_associated_data = destroy_associated_data; |
} |
void * |
vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf, |
struct pipe_video_codec *vcodec) |
{ |
if (vbuf->codec == vcodec) |
return vbuf->associated_data; |
else |
return NULL; |
} |
void |
vl_video_buffer_template(struct pipe_resource *templ, |
const struct pipe_video_buffer *tmpl, |
enum pipe_format resource_format, |
unsigned depth, unsigned array_size, |
unsigned usage, unsigned plane) |
{ |
memset(templ, 0, sizeof(*templ)); |
if (depth > 1) |
templ->target = PIPE_TEXTURE_3D; |
else if (array_size > 1) |
templ->target = PIPE_TEXTURE_2D_ARRAY; |
else |
templ->target = PIPE_TEXTURE_2D; |
templ->format = resource_format; |
templ->width0 = tmpl->width; |
templ->height0 = tmpl->height; |
templ->depth0 = depth; |
templ->array_size = array_size; |
templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; |
templ->usage = usage; |
if (plane > 0) { |
if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { |
templ->width0 /= 2; |
templ->height0 /= 2; |
} else if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) { |
templ->width0 /= 2; |
} |
} |
} |
static void |
vl_video_buffer_destroy(struct pipe_video_buffer *buffer) |
{ |
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer; |
unsigned i; |
assert(buf); |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL); |
pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); |
pipe_resource_reference(&buf->resources[i], NULL); |
} |
for (i = 0; i < VL_MAX_SURFACES; ++i) |
pipe_surface_reference(&buf->surfaces[i], NULL); |
vl_video_buffer_set_associated_data(buffer, NULL, NULL, NULL); |
FREE(buffer); |
} |
static struct pipe_sampler_view ** |
vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer) |
{ |
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer; |
struct pipe_sampler_view sv_templ; |
struct pipe_context *pipe; |
unsigned i; |
assert(buf); |
pipe = buf->base.context; |
for (i = 0; i < buf->num_planes; ++i ) { |
if (!buf->sampler_view_planes[i]) { |
memset(&sv_templ, 0, sizeof(sv_templ)); |
u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format); |
if (util_format_get_nr_components(buf->resources[i]->format) == 1) |
sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED; |
buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ); |
if (!buf->sampler_view_planes[i]) |
goto error; |
} |
} |
return buf->sampler_view_planes; |
error: |
for (i = 0; i < buf->num_planes; ++i ) |
pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL); |
return NULL; |
} |
static struct pipe_sampler_view ** |
vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer) |
{ |
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer; |
struct pipe_sampler_view sv_templ; |
struct pipe_context *pipe; |
const enum pipe_format *sampler_format; |
const unsigned *plane_order; |
unsigned i, j, component; |
assert(buf); |
pipe = buf->base.context; |
sampler_format = vl_video_buffer_formats(pipe->screen, buf->base.buffer_format); |
plane_order = vl_video_buffer_plane_order(buf->base.buffer_format); |
for (component = 0, i = 0; i < buf->num_planes; ++i ) { |
struct pipe_resource *res = buf->resources[plane_order[i]]; |
const struct util_format_description *desc = util_format_description(res->format); |
unsigned nr_components = util_format_get_nr_components(res->format); |
if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) |
nr_components = 3; |
for (j = 0; j < nr_components && component < VL_NUM_COMPONENTS; ++j, ++component) { |
if (buf->sampler_view_components[component]) |
continue; |
memset(&sv_templ, 0, sizeof(sv_templ)); |
u_sampler_view_default_template(&sv_templ, res, sampler_format[plane_order[i]]); |
sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j; |
sv_templ.swizzle_a = PIPE_SWIZZLE_ONE; |
buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ); |
if (!buf->sampler_view_components[component]) |
goto error; |
} |
} |
assert(component == VL_NUM_COMPONENTS); |
return buf->sampler_view_components; |
error: |
for (i = 0; i < VL_NUM_COMPONENTS; ++i ) |
pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); |
return NULL; |
} |
static struct pipe_surface ** |
vl_video_buffer_surfaces(struct pipe_video_buffer *buffer) |
{ |
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer; |
struct pipe_surface surf_templ; |
struct pipe_context *pipe; |
unsigned i, j, array_size, surf; |
assert(buf); |
pipe = buf->base.context; |
array_size = buffer->interlaced ? 2 : 1; |
for (i = 0, surf = 0; i < VL_NUM_COMPONENTS; ++i) { |
for (j = 0; j < array_size; ++j, ++surf) { |
assert(surf < VL_MAX_SURFACES); |
if (!buf->resources[i]) { |
pipe_surface_reference(&buf->surfaces[surf], NULL); |
continue; |
} |
if (!buf->surfaces[surf]) { |
memset(&surf_templ, 0, sizeof(surf_templ)); |
surf_templ.format = vl_video_buffer_surface_format(buf->resources[i]->format); |
surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = j; |
buf->surfaces[surf] = pipe->create_surface(pipe, buf->resources[i], &surf_templ); |
if (!buf->surfaces[surf]) |
goto error; |
} |
} |
} |
return buf->surfaces; |
error: |
for (i = 0; i < VL_MAX_SURFACES; ++i ) |
pipe_surface_reference(&buf->surfaces[i], NULL); |
return NULL; |
} |
struct pipe_video_buffer * |
vl_video_buffer_create(struct pipe_context *pipe, |
const struct pipe_video_buffer *tmpl) |
{ |
const enum pipe_format *resource_formats; |
struct pipe_video_buffer templat, *result; |
bool pot_buffers; |
assert(pipe); |
assert(tmpl->width > 0 && tmpl->height > 0); |
pot_buffers = !pipe->screen->get_video_param |
( |
pipe->screen, |
PIPE_VIDEO_PROFILE_UNKNOWN, |
PIPE_VIDEO_ENTRYPOINT_UNKNOWN, |
PIPE_VIDEO_CAP_NPOT_TEXTURES |
); |
resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format); |
if (!resource_formats) |
return NULL; |
templat = *tmpl; |
templat.width = pot_buffers ? util_next_power_of_two(tmpl->width) |
: align(tmpl->width, VL_MACROBLOCK_WIDTH); |
templat.height = pot_buffers ? util_next_power_of_two(tmpl->height) |
: align(tmpl->height, VL_MACROBLOCK_HEIGHT); |
if (tmpl->interlaced) |
templat.height /= 2; |
result = vl_video_buffer_create_ex |
( |
pipe, &templat, resource_formats, |
1, tmpl->interlaced ? 2 : 1, PIPE_USAGE_DEFAULT |
); |
if (result && tmpl->interlaced) |
result->height *= 2; |
return result; |
} |
struct pipe_video_buffer * |
vl_video_buffer_create_ex(struct pipe_context *pipe, |
const struct pipe_video_buffer *tmpl, |
const enum pipe_format resource_formats[VL_NUM_COMPONENTS], |
unsigned depth, unsigned array_size, unsigned usage) |
{ |
struct pipe_resource res_tmpl; |
struct pipe_resource *resources[VL_NUM_COMPONENTS]; |
unsigned i; |
assert(pipe); |
memset(resources, 0, sizeof resources); |
vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[0], depth, array_size, usage, 0); |
resources[0] = pipe->screen->resource_create(pipe->screen, &res_tmpl); |
if (!resources[0]) |
goto error; |
if (resource_formats[1] == PIPE_FORMAT_NONE) { |
assert(resource_formats[2] == PIPE_FORMAT_NONE); |
return vl_video_buffer_create_ex2(pipe, tmpl, resources); |
} |
vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[1], depth, array_size, usage, 1); |
resources[1] = pipe->screen->resource_create(pipe->screen, &res_tmpl); |
if (!resources[1]) |
goto error; |
if (resource_formats[2] == PIPE_FORMAT_NONE) |
return vl_video_buffer_create_ex2(pipe, tmpl, resources); |
vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[2], depth, array_size, usage, 2); |
resources[2] = pipe->screen->resource_create(pipe->screen, &res_tmpl); |
if (!resources[2]) |
goto error; |
return vl_video_buffer_create_ex2(pipe, tmpl, resources); |
error: |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) |
pipe_resource_reference(&resources[i], NULL); |
return NULL; |
} |
struct pipe_video_buffer * |
vl_video_buffer_create_ex2(struct pipe_context *pipe, |
const struct pipe_video_buffer *tmpl, |
struct pipe_resource *resources[VL_NUM_COMPONENTS]) |
{ |
struct vl_video_buffer *buffer; |
unsigned i; |
buffer = CALLOC_STRUCT(vl_video_buffer); |
if (!buffer) |
return NULL; |
buffer->base = *tmpl; |
buffer->base.context = pipe; |
buffer->base.destroy = vl_video_buffer_destroy; |
buffer->base.get_sampler_view_planes = vl_video_buffer_sampler_view_planes; |
buffer->base.get_sampler_view_components = vl_video_buffer_sampler_view_components; |
buffer->base.get_surfaces = vl_video_buffer_surfaces; |
buffer->num_planes = 0; |
for (i = 0; i < VL_NUM_COMPONENTS; ++i) { |
buffer->resources[i] = resources[i]; |
if (resources[i]) |
buffer->num_planes++; |
} |
return &buffer->base; |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_video_buffer.h |
---|
0,0 → 1,129 |
/************************************************************************** |
* |
* 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 VMWARE 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_video_buffer_h |
#define vl_video_buffer_h |
#include "pipe/p_context.h" |
#include "pipe/p_video_codec.h" |
#include "vl_defines.h" |
/** |
* implementation of a planar ycbcr buffer |
*/ |
/* planar buffer for vl data upload and manipulation */ |
struct vl_video_buffer |
{ |
struct pipe_video_buffer base; |
unsigned num_planes; |
struct pipe_resource *resources[VL_NUM_COMPONENTS]; |
struct pipe_sampler_view *sampler_view_planes[VL_NUM_COMPONENTS]; |
struct pipe_sampler_view *sampler_view_components[VL_NUM_COMPONENTS]; |
struct pipe_surface *surfaces[VL_MAX_SURFACES]; |
}; |
/** |
* get subformats for each plane |
*/ |
const enum pipe_format * |
vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format); |
/** |
* get YUV plane order |
*/ |
const unsigned * |
vl_video_buffer_plane_order(enum pipe_format format); |
/** |
* get maximum size of video buffers |
*/ |
unsigned |
vl_video_buffer_max_size(struct pipe_screen *screen); |
/** |
* check if video buffer format is supported for a codec/profile |
* can be used as default implementation of screen->is_video_format_supported |
*/ |
boolean |
vl_video_buffer_is_format_supported(struct pipe_screen *screen, |
enum pipe_format format, |
enum pipe_video_profile profile, |
enum pipe_video_entrypoint entrypoint); |
/* |
* set the associated data for the given video buffer |
*/ |
void |
vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf, |
struct pipe_video_codec *vcodec, |
void *associated_data, |
void (*destroy_associated_data)(void *)); |
/* |
* get the associated data for the given video buffer |
*/ |
void * |
vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf, |
struct pipe_video_codec *vcodec); |
/** |
* fill a resource template for the given plane |
*/ |
void |
vl_video_buffer_template(struct pipe_resource *templ, |
const struct pipe_video_buffer *templat, |
enum pipe_format resource_format, |
unsigned depth, unsigned array_size, |
unsigned usage, unsigned plane); |
/** |
* creates a video buffer, can be used as a standard implementation for pipe->create_video_buffer |
*/ |
struct pipe_video_buffer * |
vl_video_buffer_create(struct pipe_context *pipe, |
const struct pipe_video_buffer *templat); |
/** |
* extended create function, gets depth, array_size, usage and formats for each plane seperately |
*/ |
struct pipe_video_buffer * |
vl_video_buffer_create_ex(struct pipe_context *pipe, |
const struct pipe_video_buffer *templat, |
const enum pipe_format resource_formats[VL_NUM_COMPONENTS], |
unsigned depth, unsigned array_size, unsigned usage); |
/** |
* even more extended create function, provide the pipe_resource for each plane |
*/ |
struct pipe_video_buffer * |
vl_video_buffer_create_ex2(struct pipe_context *pipe, |
const struct pipe_video_buffer *templat, |
struct pipe_resource *resources[VL_NUM_COMPONENTS]); |
#endif /* vl_video_buffer_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_vlc.h |
---|
0,0 → 1,382 |
/************************************************************************** |
* |
* 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 VMWARE 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. |
* |
**************************************************************************/ |
/* |
* Functions for fast bitwise access to multiple probably unaligned input buffers |
*/ |
#ifndef vl_vlc_h |
#define vl_vlc_h |
#include "pipe/p_compiler.h" |
#include "util/u_math.h" |
#include "util/u_pointer.h" |
#include "util/u_debug.h" |
struct vl_vlc |
{ |
uint64_t buffer; |
signed invalid_bits; |
const uint8_t *data; |
const uint8_t *end; |
const void *const *inputs; |
const unsigned *sizes; |
unsigned bytes_left; |
}; |
struct vl_vlc_entry |
{ |
int8_t length; |
int8_t value; |
}; |
struct vl_vlc_compressed |
{ |
uint16_t bitcode; |
struct vl_vlc_entry entry; |
}; |
/** |
* initalize and decompress a lookup table |
*/ |
static INLINE void |
vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size) |
{ |
unsigned i, bits = util_logbase2(dst_size); |
assert(dst && dst_size); |
assert(src && src_size); |
for (i=0;i<dst_size;++i) { |
dst[i].length = 0; |
dst[i].value = 0; |
} |
for(; src_size > 0; --src_size, ++src) { |
for(i=0; i<(1 << (bits - src->entry.length)); ++i) |
dst[src->bitcode >> (16 - bits) | i] = src->entry; |
} |
} |
/** |
* switch over to next input buffer |
*/ |
static INLINE void |
vl_vlc_next_input(struct vl_vlc *vlc) |
{ |
unsigned len = vlc->sizes[0]; |
assert(vlc); |
assert(vlc->bytes_left); |
if (len < vlc->bytes_left) |
vlc->bytes_left -= len; |
else { |
len = vlc->bytes_left; |
vlc->bytes_left = 0; |
} |
vlc->data = vlc->inputs[0]; |
vlc->end = vlc->data + len; |
++vlc->inputs; |
++vlc->sizes; |
} |
/** |
* align the data pointer to the next dword |
*/ |
static INLINE void |
vl_vlc_align_data_ptr(struct vl_vlc *vlc) |
{ |
/* align the data pointer */ |
while (vlc->data != vlc->end && pointer_to_uintptr(vlc->data) & 3) { |
vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits); |
++vlc->data; |
vlc->invalid_bits -= 8; |
} |
} |
/** |
* fill the bit buffer, so that at least 32 bits are valid |
*/ |
static INLINE void |
vl_vlc_fillbits(struct vl_vlc *vlc) |
{ |
assert(vlc); |
/* as long as the buffer needs to be filled */ |
while (vlc->invalid_bits > 0) { |
unsigned bytes_left = vlc->end - vlc->data; |
/* if this input is depleted */ |
if (bytes_left == 0) { |
if (vlc->bytes_left) { |
/* go on to next input */ |
vl_vlc_next_input(vlc); |
vl_vlc_align_data_ptr(vlc); |
} else |
/* or give up since we don't have anymore inputs */ |
return; |
} else if (bytes_left >= 4) { |
/* enough bytes in buffer, read in a whole dword */ |
uint64_t value = *(const uint32_t*)vlc->data; |
#ifndef PIPE_ARCH_BIG_ENDIAN |
value = util_bswap32(value); |
#endif |
vlc->buffer |= value << vlc->invalid_bits; |
vlc->data += 4; |
vlc->invalid_bits -= 32; |
/* buffer is now definitely filled up avoid the loop test */ |
break; |
} else while (vlc->data < vlc->end) { |
/* not enough bytes left in buffer, read single bytes */ |
vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits); |
++vlc->data; |
vlc->invalid_bits -= 8; |
} |
} |
} |
/** |
* initialize vlc structure and start reading from first input buffer |
*/ |
static INLINE void |
vl_vlc_init(struct vl_vlc *vlc, unsigned num_inputs, |
const void *const *inputs, const unsigned *sizes) |
{ |
unsigned i; |
assert(vlc); |
assert(num_inputs); |
vlc->buffer = 0; |
vlc->invalid_bits = 32; |
vlc->inputs = inputs; |
vlc->sizes = sizes; |
vlc->bytes_left = 0; |
for (i = 0; i < num_inputs; ++i) |
vlc->bytes_left += sizes[i]; |
if (vlc->bytes_left) { |
vl_vlc_next_input(vlc); |
vl_vlc_align_data_ptr(vlc); |
vl_vlc_fillbits(vlc); |
} |
} |
/** |
* number of bits still valid in bit buffer |
*/ |
static INLINE unsigned |
vl_vlc_valid_bits(struct vl_vlc *vlc) |
{ |
return 32 - vlc->invalid_bits; |
} |
/** |
* number of bits left over all inbut buffers |
*/ |
static INLINE unsigned |
vl_vlc_bits_left(struct vl_vlc *vlc) |
{ |
signed bytes_left = vlc->end - vlc->data; |
bytes_left += vlc->bytes_left; |
return bytes_left * 8 + vl_vlc_valid_bits(vlc); |
} |
/** |
* get num_bits from bit buffer without removing them |
*/ |
static INLINE unsigned |
vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits) |
{ |
assert(vl_vlc_valid_bits(vlc) >= num_bits || vlc->data >= vlc->end); |
return vlc->buffer >> (64 - num_bits); |
} |
/** |
* remove num_bits from bit buffer |
*/ |
static INLINE void |
vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits) |
{ |
assert(vl_vlc_valid_bits(vlc) >= num_bits); |
vlc->buffer <<= num_bits; |
vlc->invalid_bits += num_bits; |
} |
/** |
* get num_bits from bit buffer with removing them |
*/ |
static INLINE unsigned |
vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits) |
{ |
unsigned value; |
assert(vl_vlc_valid_bits(vlc) >= num_bits); |
value = vlc->buffer >> (64 - num_bits); |
vl_vlc_eatbits(vlc, num_bits); |
return value; |
} |
/** |
* treat num_bits as signed value and remove them from bit buffer |
*/ |
static INLINE signed |
vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits) |
{ |
signed value; |
assert(vl_vlc_valid_bits(vlc) >= num_bits); |
value = ((int64_t)vlc->buffer) >> (64 - num_bits); |
vl_vlc_eatbits(vlc, num_bits); |
return value; |
} |
/** |
* lookup a value and length in a decompressed table |
*/ |
static INLINE int8_t |
vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits) |
{ |
tbl += vl_vlc_peekbits(vlc, num_bits); |
vl_vlc_eatbits(vlc, tbl->length); |
return tbl->value; |
} |
/** |
* fast forward search for a specific byte value |
*/ |
static INLINE boolean |
vl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value) |
{ |
/* make sure we are on a byte boundary */ |
assert((vl_vlc_valid_bits(vlc) % 8) == 0); |
assert(num_bits == ~0 || (num_bits % 8) == 0); |
/* deplete the bit buffer */ |
while (vl_vlc_valid_bits(vlc) > 0) { |
if (vl_vlc_peekbits(vlc, 8) == value) { |
vl_vlc_fillbits(vlc); |
return TRUE; |
} |
vl_vlc_eatbits(vlc, 8); |
if (num_bits != ~0) { |
num_bits -= 8; |
if (num_bits == 0) |
return FALSE; |
} |
} |
/* deplete the byte buffers */ |
while (1) { |
/* if this input is depleted */ |
if (vlc->data == vlc->end) { |
if (vlc->bytes_left) |
/* go on to next input */ |
vl_vlc_next_input(vlc); |
else |
/* or give up since we don't have anymore inputs */ |
return FALSE; |
} |
if (*vlc->data == value) { |
vl_vlc_align_data_ptr(vlc); |
vl_vlc_fillbits(vlc); |
return TRUE; |
} |
++vlc->data; |
if (num_bits != ~0) { |
num_bits -= 8; |
if (num_bits == 0) { |
vl_vlc_align_data_ptr(vlc); |
return FALSE; |
} |
} |
} |
} |
/** |
* remove num_bits bits starting at pos from the bitbuffer |
*/ |
static INLINE void |
vl_vlc_removebits(struct vl_vlc *vlc, unsigned pos, unsigned num_bits) |
{ |
uint64_t lo = (vlc->buffer & (~0UL >> (pos + num_bits))) << num_bits; |
uint64_t hi = (vlc->buffer & (~0UL << (64 - pos))); |
vlc->buffer = lo | hi; |
vlc->invalid_bits += num_bits; |
} |
/** |
* limit the number of bits left for fetching |
*/ |
static INLINE void |
vl_vlc_limit(struct vl_vlc *vlc, unsigned bits_left) |
{ |
assert(bits_left <= vl_vlc_bits_left(vlc)); |
vl_vlc_fillbits(vlc); |
if (bits_left < vl_vlc_valid_bits(vlc)) { |
vlc->invalid_bits = 32 - bits_left; |
vlc->buffer &= ~0L << (vlc->invalid_bits + 32); |
vlc->end = vlc->data; |
vlc->bytes_left = 0; |
} else { |
assert((bits_left - vl_vlc_valid_bits(vlc)) % 8 == 0); |
vlc->bytes_left = (bits_left - vl_vlc_valid_bits(vlc)) / 8; |
if (vlc->bytes_left < (vlc->end - vlc->data)) { |
vlc->end = vlc->data + vlc->bytes_left; |
vlc->bytes_left = 0; |
} else |
vlc->bytes_left -= vlc->end - vlc->data; |
} |
} |
#endif /* vl_vlc_h */ |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_winsys.h |
---|
0,0 → 1,69 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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. |
* |
**************************************************************************/ |
/* |
* Target makefiles directly refer to vl_winsys_dri.c to avoid DRI dependency |
*/ |
#ifndef vl_winsys_h |
#define vl_winsys_h |
#include <X11/Xlib.h> |
#include "pipe/p_defines.h" |
#include "pipe/p_format.h" |
struct pipe_screen; |
struct pipe_surface; |
struct pipe_loader_device; |
struct vl_screen |
{ |
struct pipe_screen *pscreen; |
struct pipe_loader_device *dev; |
}; |
struct vl_screen* |
vl_screen_create(Display *display, int screen); |
void vl_screen_destroy(struct vl_screen *vscreen); |
struct pipe_resource* |
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable); |
struct u_rect * |
vl_screen_get_dirty_area(struct vl_screen *vscreen); |
uint64_t |
vl_screen_get_timestamp(struct vl_screen *vscreen, Drawable drawable); |
void |
vl_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp); |
void* |
vl_screen_get_private(struct vl_screen *vscreen); |
#endif |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_winsys_dri.c |
---|
0,0 → 1,436 |
/************************************************************************** |
* |
* Copyright 2009 Younes Manton. |
* 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 VMWARE 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. |
* |
**************************************************************************/ |
/* directly referenced from target Makefile, because of X dependencies */ |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <fcntl.h> |
#include <X11/Xlib-xcb.h> |
#include <X11/extensions/dri2tokens.h> |
#include <xcb/dri2.h> |
#include <xf86drm.h> |
#include <errno.h> |
#include "pipe/p_screen.h" |
#include "pipe/p_context.h" |
#include "pipe/p_state.h" |
#include "pipe-loader/pipe_loader.h" |
#include "state_tracker/drm_driver.h" |
#include "util/u_memory.h" |
#include "util/u_hash.h" |
#include "util/u_hash_table.h" |
#include "util/u_inlines.h" |
#include "vl/vl_compositor.h" |
#include "vl/vl_winsys.h" |
struct vl_dri_screen |
{ |
struct vl_screen base; |
xcb_connection_t *conn; |
xcb_drawable_t drawable; |
unsigned width, height; |
bool current_buffer; |
uint32_t buffer_names[2]; |
struct u_rect dirty_areas[2]; |
bool flushed; |
xcb_dri2_swap_buffers_cookie_t swap_cookie; |
xcb_dri2_wait_sbc_cookie_t wait_cookie; |
xcb_dri2_get_buffers_cookie_t buffers_cookie; |
int64_t last_ust, ns_frame, last_msc, next_msc; |
}; |
static const unsigned int attachments[1] = { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT }; |
static void |
vl_dri2_handle_stamps(struct vl_dri_screen* scrn, |
uint32_t ust_hi, uint32_t ust_lo, |
uint32_t msc_hi, uint32_t msc_lo) |
{ |
int64_t ust = ((((uint64_t)ust_hi) << 32) | ust_lo) * 1000; |
int64_t msc = (((uint64_t)msc_hi) << 32) | msc_lo; |
if (scrn->last_ust && scrn->last_msc && (ust > scrn->last_ust) && (msc > scrn->last_msc)) |
scrn->ns_frame = (ust - scrn->last_ust) / (msc - scrn->last_msc); |
scrn->last_ust = ust; |
scrn->last_msc = msc; |
} |
static xcb_dri2_get_buffers_reply_t* |
vl_dri2_get_flush_reply(struct vl_dri_screen *scrn) |
{ |
xcb_dri2_wait_sbc_reply_t *wait_sbc_reply; |
assert(scrn); |
if (!scrn->flushed) |
return NULL; |
scrn->flushed = false; |
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL)); |
wait_sbc_reply = xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL); |
if (!wait_sbc_reply) |
return NULL; |
vl_dri2_handle_stamps(scrn, wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo, |
wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo); |
free(wait_sbc_reply); |
return xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL); |
} |
static void |
vl_dri2_flush_frontbuffer(struct pipe_screen *screen, |
struct pipe_resource *resource, |
unsigned level, unsigned layer, |
void *context_private, struct pipe_box *sub_box) |
{ |
struct vl_dri_screen *scrn = (struct vl_dri_screen*)context_private; |
uint32_t msc_hi, msc_lo; |
assert(screen); |
assert(resource); |
assert(context_private); |
free(vl_dri2_get_flush_reply(scrn)); |
msc_hi = scrn->next_msc >> 32; |
msc_lo = scrn->next_msc & 0xFFFFFFFF; |
scrn->swap_cookie = xcb_dri2_swap_buffers_unchecked(scrn->conn, scrn->drawable, msc_hi, msc_lo, 0, 0, 0, 0); |
scrn->wait_cookie = xcb_dri2_wait_sbc_unchecked(scrn->conn, scrn->drawable, 0, 0); |
scrn->buffers_cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, scrn->drawable, 1, 1, attachments); |
scrn->flushed = true; |
scrn->current_buffer = !scrn->current_buffer; |
} |
static void |
vl_dri2_destroy_drawable(struct vl_dri_screen *scrn) |
{ |
xcb_void_cookie_t destroy_cookie; |
if (scrn->drawable) { |
free(vl_dri2_get_flush_reply(scrn)); |
destroy_cookie = xcb_dri2_destroy_drawable_checked(scrn->conn, scrn->drawable); |
/* ignore any error here, since the drawable can be destroyed long ago */ |
free(xcb_request_check(scrn->conn, destroy_cookie)); |
} |
} |
static void |
vl_dri2_set_drawable(struct vl_dri_screen *scrn, Drawable drawable) |
{ |
assert(scrn); |
assert(drawable); |
if (scrn->drawable == drawable) |
return; |
vl_dri2_destroy_drawable(scrn); |
xcb_dri2_create_drawable(scrn->conn, drawable); |
scrn->current_buffer = false; |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); |
scrn->drawable = drawable; |
} |
struct pipe_resource* |
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable) |
{ |
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
struct winsys_handle dri2_handle; |
struct pipe_resource template, *tex; |
xcb_dri2_get_buffers_reply_t *reply; |
xcb_dri2_dri2_buffer_t *buffers, *back_left; |
unsigned i; |
assert(scrn); |
vl_dri2_set_drawable(scrn, drawable); |
reply = vl_dri2_get_flush_reply(scrn); |
if (!reply) { |
xcb_dri2_get_buffers_cookie_t cookie; |
cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, drawable, 1, 1, attachments); |
reply = xcb_dri2_get_buffers_reply(scrn->conn, cookie, NULL); |
} |
if (!reply) |
return NULL; |
buffers = xcb_dri2_get_buffers_buffers(reply); |
if (!buffers) { |
free(reply); |
return NULL; |
} |
for (i = 0; i < reply->count; ++i) { |
if (buffers[i].attachment == XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT) { |
back_left = &buffers[i]; |
break; |
} |
} |
if (i == reply->count) { |
free(reply); |
return NULL; |
} |
if (reply->width != scrn->width || reply->height != scrn->height) { |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); |
scrn->width = reply->width; |
scrn->height = reply->height; |
} else if (back_left->name != scrn->buffer_names[scrn->current_buffer]) { |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->current_buffer]); |
scrn->buffer_names[scrn->current_buffer] = back_left->name; |
} |
memset(&dri2_handle, 0, sizeof(dri2_handle)); |
dri2_handle.type = DRM_API_HANDLE_TYPE_SHARED; |
dri2_handle.handle = back_left->name; |
dri2_handle.stride = back_left->pitch; |
memset(&template, 0, sizeof(template)); |
template.target = PIPE_TEXTURE_2D; |
template.format = PIPE_FORMAT_B8G8R8X8_UNORM; |
template.last_level = 0; |
template.width0 = reply->width; |
template.height0 = reply->height; |
template.depth0 = 1; |
template.array_size = 1; |
template.usage = PIPE_USAGE_DEFAULT; |
template.bind = PIPE_BIND_RENDER_TARGET; |
template.flags = 0; |
tex = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &template, &dri2_handle); |
free(reply); |
return tex; |
} |
struct u_rect * |
vl_screen_get_dirty_area(struct vl_screen *vscreen) |
{ |
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
assert(scrn); |
return &scrn->dirty_areas[scrn->current_buffer]; |
} |
uint64_t |
vl_screen_get_timestamp(struct vl_screen *vscreen, Drawable drawable) |
{ |
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
xcb_dri2_get_msc_cookie_t cookie; |
xcb_dri2_get_msc_reply_t *reply; |
assert(scrn); |
vl_dri2_set_drawable(scrn, drawable); |
if (!scrn->last_ust) { |
cookie = xcb_dri2_get_msc_unchecked(scrn->conn, drawable); |
reply = xcb_dri2_get_msc_reply(scrn->conn, cookie, NULL); |
if (reply) { |
vl_dri2_handle_stamps(scrn, reply->ust_hi, reply->ust_lo, |
reply->msc_hi, reply->msc_lo); |
free(reply); |
} |
} |
return scrn->last_ust; |
} |
void |
vl_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp) |
{ |
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
assert(scrn); |
if (stamp && scrn->last_ust && scrn->ns_frame && scrn->last_msc) |
scrn->next_msc = ((int64_t)stamp - scrn->last_ust + scrn->ns_frame/2) / scrn->ns_frame + scrn->last_msc; |
else |
scrn->next_msc = 0; |
} |
void* |
vl_screen_get_private(struct vl_screen *vscreen) |
{ |
return vscreen; |
} |
struct vl_screen* |
vl_screen_create(Display *display, int screen) |
{ |
struct vl_dri_screen *scrn; |
const xcb_query_extension_reply_t *extension; |
xcb_dri2_query_version_cookie_t dri2_query_cookie; |
xcb_dri2_query_version_reply_t *dri2_query = NULL; |
xcb_dri2_connect_cookie_t connect_cookie; |
xcb_dri2_connect_reply_t *connect = NULL; |
xcb_dri2_authenticate_cookie_t authenticate_cookie; |
xcb_dri2_authenticate_reply_t *authenticate = NULL; |
xcb_screen_iterator_t s; |
xcb_generic_error_t *error = NULL; |
char *device_name; |
int fd, device_name_length; |
unsigned int driverType; |
drm_magic_t magic; |
assert(display); |
scrn = CALLOC_STRUCT(vl_dri_screen); |
if (!scrn) |
return NULL; |
scrn->conn = XGetXCBConnection(display); |
if (!scrn->conn) |
goto free_screen; |
xcb_prefetch_extension_data(scrn->conn, &xcb_dri2_id); |
extension = xcb_get_extension_data(scrn->conn, &xcb_dri2_id); |
if (!(extension && extension->present)) |
goto free_screen; |
dri2_query_cookie = xcb_dri2_query_version (scrn->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION); |
dri2_query = xcb_dri2_query_version_reply (scrn->conn, dri2_query_cookie, &error); |
if (dri2_query == NULL || error != NULL || dri2_query->minor_version < 2) |
goto free_query; |
s = xcb_setup_roots_iterator(xcb_get_setup(scrn->conn)); |
while (screen--) |
xcb_screen_next(&s); |
driverType = XCB_DRI2_DRIVER_TYPE_DRI; |
#ifdef DRI2DriverPrimeShift |
{ |
char *prime = getenv("DRI_PRIME"); |
if (prime) { |
unsigned int primeid; |
errno = 0; |
primeid = strtoul(prime, NULL, 0); |
if (errno == 0) |
driverType |= |
((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift); |
} |
} |
#endif |
connect_cookie = xcb_dri2_connect_unchecked(scrn->conn, s.data->root, driverType); |
connect = xcb_dri2_connect_reply(scrn->conn, connect_cookie, NULL); |
if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0) |
goto free_connect; |
device_name_length = xcb_dri2_connect_device_name_length(connect); |
device_name = CALLOC(1, device_name_length + 1); |
if (!device_name) |
goto free_connect; |
memcpy(device_name, xcb_dri2_connect_device_name(connect), device_name_length); |
fd = open(device_name, O_RDWR); |
free(device_name); |
if (fd < 0) |
goto free_connect; |
if (drmGetMagic(fd, &magic)) |
goto free_connect; |
authenticate_cookie = xcb_dri2_authenticate_unchecked(scrn->conn, s.data->root, magic); |
authenticate = xcb_dri2_authenticate_reply(scrn->conn, authenticate_cookie, NULL); |
if (authenticate == NULL || !authenticate->authenticated) |
goto free_authenticate; |
#if GALLIUM_STATIC_TARGETS |
scrn->base.pscreen = dd_create_screen(fd); |
#else |
if (pipe_loader_drm_probe_fd(&scrn->base.dev, fd, false)) |
scrn->base.pscreen = pipe_loader_create_screen(scrn->base.dev, PIPE_SEARCH_DIR); |
#endif // GALLIUM_STATIC_TARGETS |
if (!scrn->base.pscreen) |
goto release_pipe; |
scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer; |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); |
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); |
free(authenticate); |
free(connect); |
free(dri2_query); |
free(error); |
return &scrn->base; |
release_pipe: |
#if !GALLIUM_STATIC_TARGETS |
if (scrn->base.dev) |
pipe_loader_release(&scrn->base.dev, 1); |
#endif // !GALLIUM_STATIC_TARGETS |
free_authenticate: |
free(authenticate); |
free_connect: |
free(connect); |
free_query: |
free(dri2_query); |
free(error); |
free_screen: |
FREE(scrn); |
return NULL; |
} |
void vl_screen_destroy(struct vl_screen *vscreen) |
{ |
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen; |
assert(vscreen); |
if (scrn->flushed) { |
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL)); |
free(xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL)); |
free(xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL)); |
} |
vl_dri2_destroy_drawable(scrn); |
scrn->base.pscreen->destroy(scrn->base.pscreen); |
#if !GALLIUM_STATIC_TARGETS |
pipe_loader_release(&scrn->base.dev, 1); |
#endif // !GALLIUM_STATIC_TARGETS |
FREE(scrn); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_zscan.c |
---|
0,0 → 1,584 |
/************************************************************************** |
* |
* 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 VMWARE 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 <assert.h> |
#include "pipe/p_screen.h" |
#include "pipe/p_context.h" |
#include "util/u_draw.h" |
#include "util/u_sampler.h" |
#include "util/u_inlines.h" |
#include "util/u_memory.h" |
#include "tgsi/tgsi_ureg.h" |
#include "vl_defines.h" |
#include "vl_types.h" |
#include "vl_zscan.h" |
#include "vl_vertex_buffers.h" |
enum VS_OUTPUT |
{ |
VS_O_VPOS = 0, |
VS_O_VTEX = 0 |
}; |
const int vl_zscan_linear[] = |
{ |
/* Linear scan pattern */ |
0, 1, 2, 3, 4, 5, 6, 7, |
8, 9,10,11,12,13,14,15, |
16,17,18,19,20,21,22,23, |
24,25,26,27,28,29,30,31, |
32,33,34,35,36,37,38,39, |
40,41,42,43,44,45,46,47, |
48,49,50,51,52,53,54,55, |
56,57,58,59,60,61,62,63 |
}; |
const int vl_zscan_normal[] = |
{ |
/* Zig-Zag scan pattern */ |
0, 1, 8,16, 9, 2, 3,10, |
17,24,32,25,18,11, 4, 5, |
12,19,26,33,40,48,41,34, |
27,20,13, 6, 7,14,21,28, |
35,42,49,56,57,50,43,36, |
29,22,15,23,30,37,44,51, |
58,59,52,45,38,31,39,46, |
53,60,61,54,47,55,62,63 |
}; |
const int vl_zscan_alternate[] = |
{ |
/* Alternate scan pattern */ |
0, 8,16,24, 1, 9, 2,10, |
17,25,32,40,48,56,57,49, |
41,33,26,18, 3,11, 4,12, |
19,27,34,42,50,58,35,43, |
51,59,20,28, 5,13, 6,14, |
21,29,36,44,52,60,37,45, |
53,61,22,30, 7,15,23,31, |
38,46,54,62,39,47,55,63 |
}; |
static void * |
create_vert_shader(struct vl_zscan *zscan) |
{ |
struct ureg_program *shader; |
struct ureg_src scale; |
struct ureg_src vrect, vpos, block_num; |
struct ureg_dst tmp; |
struct ureg_dst o_vpos; |
struct ureg_dst *o_vtex; |
signed i; |
shader = ureg_create(TGSI_PROCESSOR_VERTEX); |
if (!shader) |
return NULL; |
o_vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_dst)); |
scale = ureg_imm2f(shader, |
(float)VL_BLOCK_WIDTH / zscan->buffer_width, |
(float)VL_BLOCK_HEIGHT / zscan->buffer_height); |
vrect = ureg_DECL_vs_input(shader, VS_I_RECT); |
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); |
block_num = ureg_DECL_vs_input(shader, VS_I_BLOCK_NUM); |
tmp = ureg_DECL_temporary(shader); |
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); |
for (i = 0; i < zscan->num_channels; ++i) |
o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i); |
/* |
* o_vpos.xy = (vpos + vrect) * scale |
* o_vpos.zw = 1.0f |
* |
* tmp.xy = InstanceID / blocks_per_line |
* tmp.x = frac(tmp.x) |
* tmp.y = floor(tmp.y) |
* |
* o_vtex.x = vrect.x / blocks_per_line + tmp.x |
* o_vtex.y = vrect.y |
* o_vtex.z = tmp.z * blocks_per_line / blocks_total |
*/ |
ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), vpos, vrect); |
ureg_MUL(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(tmp), scale); |
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f)); |
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XW), ureg_scalar(block_num, TGSI_SWIZZLE_X), |
ureg_imm1f(shader, 1.0f / zscan->blocks_per_line)); |
ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); |
ureg_FLR(shader, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_src(tmp)); |
for (i = 0; i < zscan->num_channels; ++i) { |
ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), |
ureg_imm1f(shader, 1.0f / (zscan->blocks_per_line * VL_BLOCK_WIDTH) |
* (i - (signed)zscan->num_channels / 2))); |
ureg_MAD(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_X), vrect, |
ureg_imm1f(shader, 1.0f / zscan->blocks_per_line), ureg_src(tmp)); |
ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Y), vrect); |
ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Z), vpos); |
ureg_MUL(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_W), ureg_src(tmp), |
ureg_imm1f(shader, (float)zscan->blocks_per_line / zscan->blocks_total)); |
} |
ureg_release_temporary(shader, tmp); |
ureg_END(shader); |
FREE(o_vtex); |
return ureg_create_shader_and_destroy(shader, zscan->pipe); |
} |
static void * |
create_frag_shader(struct vl_zscan *zscan) |
{ |
struct ureg_program *shader; |
struct ureg_src *vtex; |
struct ureg_src samp_src, samp_scan, samp_quant; |
struct ureg_dst *tmp; |
struct ureg_dst quant, fragment; |
unsigned i; |
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); |
if (!shader) |
return NULL; |
vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_src)); |
tmp = MALLOC(zscan->num_channels * sizeof(struct ureg_dst)); |
for (i = 0; i < zscan->num_channels; ++i) |
vtex[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i, TGSI_INTERPOLATE_LINEAR); |
samp_src = ureg_DECL_sampler(shader, 0); |
samp_scan = ureg_DECL_sampler(shader, 1); |
samp_quant = ureg_DECL_sampler(shader, 2); |
for (i = 0; i < zscan->num_channels; ++i) |
tmp[i] = ureg_DECL_temporary(shader); |
quant = ureg_DECL_temporary(shader); |
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); |
/* |
* tmp.x = tex(vtex, 1) |
* tmp.y = vtex.z |
* fragment = tex(tmp, 0) * quant |
*/ |
for (i = 0; i < zscan->num_channels; ++i) |
ureg_TEX(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_X), TGSI_TEXTURE_2D, vtex[i], samp_scan); |
for (i = 0; i < zscan->num_channels; ++i) |
ureg_MOV(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_Y), ureg_scalar(vtex[i], TGSI_SWIZZLE_W)); |
for (i = 0; i < zscan->num_channels; ++i) { |
ureg_TEX(shader, ureg_writemask(tmp[0], TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D, ureg_src(tmp[i]), samp_src); |
ureg_TEX(shader, ureg_writemask(quant, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, vtex[i], samp_quant); |
} |
ureg_MUL(shader, quant, ureg_src(quant), ureg_imm1f(shader, 16.0f)); |
ureg_MUL(shader, fragment, ureg_src(tmp[0]), ureg_src(quant)); |
for (i = 0; i < zscan->num_channels; ++i) |
ureg_release_temporary(shader, tmp[i]); |
ureg_END(shader); |
FREE(vtex); |
FREE(tmp); |
return ureg_create_shader_and_destroy(shader, zscan->pipe); |
} |
static bool |
init_shaders(struct vl_zscan *zscan) |
{ |
assert(zscan); |
zscan->vs = create_vert_shader(zscan); |
if (!zscan->vs) |
goto error_vs; |
zscan->fs = create_frag_shader(zscan); |
if (!zscan->fs) |
goto error_fs; |
return true; |
error_fs: |
zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs); |
error_vs: |
return false; |
} |
static void |
cleanup_shaders(struct vl_zscan *zscan) |
{ |
assert(zscan); |
zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs); |
zscan->pipe->delete_fs_state(zscan->pipe, zscan->fs); |
} |
static bool |
init_state(struct vl_zscan *zscan) |
{ |
struct pipe_blend_state blend; |
struct pipe_rasterizer_state rs_state; |
struct pipe_sampler_state sampler; |
unsigned i; |
assert(zscan); |
memset(&rs_state, 0, sizeof(rs_state)); |
rs_state.half_pixel_center = true; |
rs_state.bottom_edge_rule = true; |
rs_state.depth_clip = 1; |
zscan->rs_state = zscan->pipe->create_rasterizer_state(zscan->pipe, &rs_state); |
if (!zscan->rs_state) |
goto error_rs_state; |
memset(&blend, 0, sizeof blend); |
blend.independent_blend_enable = 0; |
blend.rt[0].blend_enable = 0; |
blend.rt[0].rgb_func = PIPE_BLEND_ADD; |
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_func = PIPE_BLEND_ADD; |
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; |
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
blend.logicop_enable = 0; |
blend.logicop_func = PIPE_LOGICOP_CLEAR; |
/* Needed to allow color writes to FB, even if blending disabled */ |
blend.rt[0].colormask = PIPE_MASK_RGBA; |
blend.dither = 0; |
zscan->blend = zscan->pipe->create_blend_state(zscan->pipe, &blend); |
if (!zscan->blend) |
goto error_blend; |
for (i = 0; i < 3; ++i) { |
memset(&sampler, 0, sizeof(sampler)); |
sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; |
sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; |
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; |
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; |
sampler.compare_mode = PIPE_TEX_COMPARE_NONE; |
sampler.compare_func = PIPE_FUNC_ALWAYS; |
sampler.normalized_coords = 1; |
zscan->samplers[i] = zscan->pipe->create_sampler_state(zscan->pipe, &sampler); |
if (!zscan->samplers[i]) |
goto error_samplers; |
} |
return true; |
error_samplers: |
for (i = 0; i < 2; ++i) |
if (zscan->samplers[i]) |
zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]); |
zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state); |
error_blend: |
zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend); |
error_rs_state: |
return false; |
} |
static void |
cleanup_state(struct vl_zscan *zscan) |
{ |
unsigned i; |
assert(zscan); |
for (i = 0; i < 3; ++i) |
zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]); |
zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state); |
zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend); |
} |
struct pipe_sampler_view * |
vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line) |
{ |
const unsigned total_size = blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; |
int patched_layout[64]; |
struct pipe_resource res_tmpl, *res; |
struct pipe_sampler_view sv_tmpl, *sv; |
struct pipe_transfer *buf_transfer; |
unsigned x, y, i, pitch; |
float *f; |
struct pipe_box rect = |
{ |
0, 0, 0, |
VL_BLOCK_WIDTH * blocks_per_line, |
VL_BLOCK_HEIGHT, |
1 |
}; |
assert(pipe && layout && blocks_per_line); |
for (i = 0; i < 64; ++i) |
patched_layout[layout[i]] = i; |
memset(&res_tmpl, 0, sizeof(res_tmpl)); |
res_tmpl.target = PIPE_TEXTURE_2D; |
res_tmpl.format = PIPE_FORMAT_R32_FLOAT; |
res_tmpl.width0 = VL_BLOCK_WIDTH * blocks_per_line; |
res_tmpl.height0 = VL_BLOCK_HEIGHT; |
res_tmpl.depth0 = 1; |
res_tmpl.array_size = 1; |
res_tmpl.usage = PIPE_USAGE_IMMUTABLE; |
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; |
res = pipe->screen->resource_create(pipe->screen, &res_tmpl); |
if (!res) |
goto error_resource; |
f = pipe->transfer_map(pipe, res, |
0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, |
&rect, &buf_transfer); |
if (!f) |
goto error_map; |
pitch = buf_transfer->stride / sizeof(float); |
for (i = 0; i < blocks_per_line; ++i) |
for (y = 0; y < VL_BLOCK_HEIGHT; ++y) |
for (x = 0; x < VL_BLOCK_WIDTH; ++x) { |
float addr = patched_layout[x + y * VL_BLOCK_WIDTH] + |
i * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; |
addr /= total_size; |
f[i * VL_BLOCK_WIDTH + y * pitch + x] = addr; |
} |
pipe->transfer_unmap(pipe, buf_transfer); |
memset(&sv_tmpl, 0, sizeof(sv_tmpl)); |
u_sampler_view_default_template(&sv_tmpl, res, res->format); |
sv = pipe->create_sampler_view(pipe, res, &sv_tmpl); |
pipe_resource_reference(&res, NULL); |
if (!sv) |
goto error_map; |
return sv; |
error_map: |
pipe_resource_reference(&res, NULL); |
error_resource: |
return NULL; |
} |
bool |
vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe, |
unsigned buffer_width, unsigned buffer_height, |
unsigned blocks_per_line, unsigned blocks_total, |
unsigned num_channels) |
{ |
assert(zscan && pipe); |
zscan->pipe = pipe; |
zscan->buffer_width = buffer_width; |
zscan->buffer_height = buffer_height; |
zscan->num_channels = num_channels; |
zscan->blocks_per_line = blocks_per_line; |
zscan->blocks_total = blocks_total; |
if(!init_shaders(zscan)) |
return false; |
if(!init_state(zscan)) { |
cleanup_shaders(zscan); |
return false; |
} |
return true; |
} |
void |
vl_zscan_cleanup(struct vl_zscan *zscan) |
{ |
assert(zscan); |
cleanup_shaders(zscan); |
cleanup_state(zscan); |
} |
bool |
vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, |
struct pipe_sampler_view *src, struct pipe_surface *dst) |
{ |
struct pipe_resource res_tmpl, *res; |
struct pipe_sampler_view sv_tmpl; |
assert(zscan && buffer); |
memset(buffer, 0, sizeof(struct vl_zscan_buffer)); |
pipe_sampler_view_reference(&buffer->src, src); |
buffer->viewport.scale[0] = dst->width; |
buffer->viewport.scale[1] = dst->height; |
buffer->viewport.scale[2] = 1; |
buffer->viewport.translate[0] = 0; |
buffer->viewport.translate[1] = 0; |
buffer->viewport.translate[2] = 0; |
buffer->fb_state.width = dst->width; |
buffer->fb_state.height = dst->height; |
buffer->fb_state.nr_cbufs = 1; |
pipe_surface_reference(&buffer->fb_state.cbufs[0], dst); |
memset(&res_tmpl, 0, sizeof(res_tmpl)); |
res_tmpl.target = PIPE_TEXTURE_3D; |
res_tmpl.format = PIPE_FORMAT_R8_UNORM; |
res_tmpl.width0 = VL_BLOCK_WIDTH * zscan->blocks_per_line; |
res_tmpl.height0 = VL_BLOCK_HEIGHT; |
res_tmpl.depth0 = 2; |
res_tmpl.array_size = 1; |
res_tmpl.usage = PIPE_USAGE_IMMUTABLE; |
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; |
res = zscan->pipe->screen->resource_create(zscan->pipe->screen, &res_tmpl); |
if (!res) |
return false; |
memset(&sv_tmpl, 0, sizeof(sv_tmpl)); |
u_sampler_view_default_template(&sv_tmpl, res, res->format); |
sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = TGSI_SWIZZLE_X; |
buffer->quant = zscan->pipe->create_sampler_view(zscan->pipe, res, &sv_tmpl); |
pipe_resource_reference(&res, NULL); |
if (!buffer->quant) |
return false; |
return true; |
} |
void |
vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer) |
{ |
assert(buffer); |
pipe_sampler_view_reference(&buffer->src, NULL); |
pipe_sampler_view_reference(&buffer->layout, NULL); |
pipe_sampler_view_reference(&buffer->quant, NULL); |
pipe_surface_reference(&buffer->fb_state.cbufs[0], NULL); |
} |
void |
vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout) |
{ |
assert(buffer); |
assert(layout); |
pipe_sampler_view_reference(&buffer->layout, layout); |
} |
void |
vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, |
const uint8_t matrix[64], bool intra) |
{ |
struct pipe_context *pipe; |
struct pipe_transfer *buf_transfer; |
unsigned x, y, i, pitch; |
uint8_t *data; |
struct pipe_box rect = |
{ |
0, 0, intra ? 1 : 0, |
VL_BLOCK_WIDTH, |
VL_BLOCK_HEIGHT, |
1 |
}; |
assert(buffer); |
assert(matrix); |
pipe = zscan->pipe; |
rect.width *= zscan->blocks_per_line; |
data = pipe->transfer_map(pipe, buffer->quant->texture, |
0, PIPE_TRANSFER_WRITE | |
PIPE_TRANSFER_DISCARD_RANGE, |
&rect, &buf_transfer); |
if (!data) |
return; |
pitch = buf_transfer->stride; |
for (i = 0; i < zscan->blocks_per_line; ++i) |
for (y = 0; y < VL_BLOCK_HEIGHT; ++y) |
for (x = 0; x < VL_BLOCK_WIDTH; ++x) |
data[i * VL_BLOCK_WIDTH + y * pitch + x] = matrix[x + y * VL_BLOCK_WIDTH]; |
pipe->transfer_unmap(pipe, buf_transfer); |
} |
void |
vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances) |
{ |
assert(buffer); |
zscan->pipe->bind_rasterizer_state(zscan->pipe, zscan->rs_state); |
zscan->pipe->bind_blend_state(zscan->pipe, zscan->blend); |
zscan->pipe->bind_sampler_states(zscan->pipe, PIPE_SHADER_FRAGMENT, |
0, 3, zscan->samplers); |
zscan->pipe->set_framebuffer_state(zscan->pipe, &buffer->fb_state); |
zscan->pipe->set_viewport_states(zscan->pipe, 0, 1, &buffer->viewport); |
zscan->pipe->set_sampler_views(zscan->pipe, PIPE_SHADER_FRAGMENT, |
0, 3, &buffer->src); |
zscan->pipe->bind_vs_state(zscan->pipe, zscan->vs); |
zscan->pipe->bind_fs_state(zscan->pipe, zscan->fs); |
util_draw_arrays_instanced(zscan->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); |
} |
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/gallium/auxiliary/vl/vl_zscan.h |
---|
0,0 → 1,100 |
/************************************************************************** |
* |
* 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 VMWARE 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_zscan_h |
#define vl_zscan_h |
#include "pipe/p_compiler.h" |
#include "pipe/p_state.h" |
/* |
* shader based zscan and quantification |
* expect usage of vl_vertex_buffers as a todo list |
*/ |
struct vl_zscan |
{ |
struct pipe_context *pipe; |
unsigned buffer_width; |
unsigned buffer_height; |
unsigned num_channels; |
unsigned blocks_per_line; |
unsigned blocks_total; |
void *rs_state; |
void *blend; |
void *samplers[3]; |
void *vs, *fs; |
}; |
struct vl_zscan_buffer |
{ |
struct pipe_viewport_state viewport; |
struct pipe_framebuffer_state fb_state; |
struct pipe_sampler_view *src, *layout, *quant; |
struct pipe_surface *dst; |
}; |
extern const int vl_zscan_linear[]; |
extern const int vl_zscan_normal[]; |
extern const int vl_zscan_alternate[]; |
struct pipe_sampler_view * |
vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line); |
bool |
vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe, |
unsigned buffer_width, unsigned buffer_height, |
unsigned blocks_per_line, unsigned blocks_total, |
unsigned num_channels); |
void |
vl_zscan_cleanup(struct vl_zscan *zscan); |
bool |
vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, |
struct pipe_sampler_view *src, struct pipe_surface *dst); |
void |
vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer); |
void |
vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout); |
void |
vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, |
const uint8_t matrix[64], bool intra); |
void |
vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances); |
#endif |