gallium/vl: Remove mpeg12 shader decoder

The decoder has been broken for years. It creates 3-plane video
buffer with RGB16 format for all three planes, which hasn't been
working since 243475b96c.
It also doesn't make sense anymore to use shader decoder for a codec
this old.

Acked-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37507>
This commit is contained in:
David Rosca 2025-03-05 09:24:31 +01:00 committed by Marge Bot
parent b16910031b
commit 214a431caf
20 changed files with 3 additions and 3925 deletions

View file

@ -395,28 +395,18 @@ files_libgalliumvl = files(
'vl/vl_compositor_cs.h',
'vl/vl_csc.c',
'vl/vl_csc.h',
'vl/vl_decoder.c',
'vl/vl_decoder.h',
'vl/vl_defines.h',
'vl/vl_deint_filter.c',
'vl/vl_deint_filter.h',
'vl/vl_deint_filter_cs.c',
'vl/vl_deint_filter_cs.h',
'vl/vl_idct.c',
'vl/vl_idct.h',
'vl/vl_mc.c',
'vl/vl_mc.h',
'vl/vl_mpeg12_bitstream.c',
'vl/vl_mpeg12_bitstream.h',
'vl/vl_mpeg12_decoder.c',
'vl/vl_mpeg12_decoder.h',
'vl/vl_types.h',
'vl/vl_vertex_buffers.c',
'vl/vl_vertex_buffers.h',
'vl/vl_video_buffer.c',
'vl/vl_video_buffer.h',
'vl/vl_zscan.c',
'vl/vl_zscan.h',
)
vlwinsys_deps = []

View file

@ -1,94 +0,0 @@
/**************************************************************************
*
* 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;
}

View file

@ -1,54 +0,0 @@
/**************************************************************************
*
* 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 */

View file

@ -1,855 +0,0 @@
/**************************************************************************
*
* 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(MESA_SHADER_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(MESA_SHADER_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_address[2];
s_address[0] = ureg_src(m[i][0]);
s_address[1] = ureg_src(m[i][1]);
fetch_four(shader, m[i], s_address, 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(MESA_SHADER_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;
unsigned i;
int j;
shader = ureg_create(MESA_SHADER_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_address[2];
s_address[0] = ureg_src(l[i][0]);
s_address[1] = ureg_src(l[i][1]);
fetch_four(shader, l[i], s_address, ureg_DECL_sampler(shader, 0), false);
}
for (i = 0; i < idct->nr_of_render_targets; ++i) {
struct ureg_src s_address[2];
increment_addr(shader, r, r_addr, true, true, i - (signed)idct->nr_of_render_targets / 2, VL_BLOCK_HEIGHT);
s_address[0] = ureg_src(r[0]);
s_address[1] = ureg_src(r[1]);
fetch_four(shader, r, s_address, 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_near = 1;
rs_state.depth_clip_far = 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;
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.texture = tex;
surf_templ.format = tex->format;
surf_templ.first_layer = 0;
surf_templ.last_layer = 0;
buffer->fb_state_mismatch.cbufs[0] = surf_templ;
buffer->viewport_mismatch.scale[0] = tex->width0;
buffer->viewport_mismatch.scale[1] = tex->height0;
buffer->viewport_mismatch.scale[2] = 1;
buffer->viewport_mismatch.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
buffer->viewport_mismatch.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
buffer->viewport_mismatch.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
buffer->viewport_mismatch.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
return true;
}
static void
cleanup_source(struct vl_idct_buffer *buffer)
{
assert(buffer);
memset(&buffer->fb_state_mismatch.cbufs[0], 0, sizeof(struct pipe_surface));
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.texture = tex;
surf_templ.first_layer = i;
surf_templ.last_layer = i;
buffer->fb_state.cbufs[i] = surf_templ;
}
buffer->viewport.scale[0] = tex->width0;
buffer->viewport.scale[1] = tex->height0;
buffer->viewport.scale[2] = 1;
buffer->viewport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
buffer->viewport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
buffer->viewport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
buffer->viewport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
return true;
}
static void
cleanup_intermediate(struct vl_idct_buffer *buffer)
{
assert(buffer);
memset(buffer->fb_state.cbufs, 0, sizeof(buffer->fb_state.cbufs));
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->texture_map(pipe, matrix, 0,
PIPE_MAP_WRITE |
PIPE_MAP_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->texture_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, MESA_SHADER_FRAGMENT,
0, 2, idct->samplers);
idct->pipe->set_sampler_views(idct->pipe, MESA_SHADER_FRAGMENT, 0, 2, 0,
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, MESA_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, MESA_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, MESA_SHADER_FRAGMENT,
0, 2, idct->samplers);
idct->pipe->set_sampler_views(idct->pipe, MESA_SHADER_FRAGMENT,
0, 2, 0, buffer->sampler_views.stage[1]);
}

View file

@ -1,119 +0,0 @@
/**************************************************************************
*
* 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

View file

@ -1,657 +0,0 @@
/**************************************************************************
*
* 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 pipe_screen *screen, struct ureg_program *shader)
{
struct ureg_dst tmp;
struct ureg_src pos;
tmp = ureg_DECL_temporary(shader);
if (screen->caps.fs_position_is_sysval)
pos = ureg_DECL_system_value(shader, TGSI_SEMANTIC_POSITION, 0);
else
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(MESA_SHADER_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(MESA_SHADER_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(r->pipe->screen, 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(MESA_SHADER_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(MESA_SHADER_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(r->pipe->screen, 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;
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_near = 1;
rs_state.depth_clip_far = 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->viewport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
buffer->viewport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
buffer->viewport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
buffer->viewport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
buffer->fb_state.nr_cbufs = 1;
memset(&buffer->fb_state.zsbuf, 0, sizeof(buffer->fb_state.zsbuf));
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] = pipe_surface_width(surface);
buffer->viewport.scale[1] = pipe_surface_height(surface);
buffer->fb_state.width = pipe_surface_width(surface);
buffer->fb_state.height = pipe_surface_height(surface);
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, MESA_SHADER_FRAGMENT,
0, 1, 0, &ref);
renderer->pipe->bind_sampler_states(renderer->pipe, MESA_SHADER_FRAGMENT,
0, 1, &renderer->sampler_ref);
util_draw_arrays_instanced(renderer->pipe, MESA_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, MESA_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, MESA_PRIM_QUADS, 0, 4, 0, num_instances);
}
}

View file

@ -1,97 +0,0 @@
/**************************************************************************
*
* 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 */

File diff suppressed because it is too large Load diff

View file

@ -1,114 +0,0 @@
/**************************************************************************
*
* 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 "util/list.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 list_head buffer_privates;
};
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 */

View file

@ -1,39 +1,7 @@
#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;
}
/*
@ -143,15 +111,3 @@ vl_mpg12_bs_decode(struct vl_mpg12_bs *bs,
{
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;
}

View file

@ -1,543 +0,0 @@
/**************************************************************************
*
* 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
};
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;
unsigned i;
shader = ureg_create(MESA_SHADER_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)
* ((signed)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(MESA_SHADER_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_near = 1;
rs_state.depth_clip_far = 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;
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;
u_box_3d(0, 0, 0,
VL_BLOCK_WIDTH * blocks_per_line,
VL_BLOCK_HEIGHT,
1, &rect);
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->texture_map(pipe, res,
0, PIPE_MAP_WRITE | PIPE_MAP_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->texture_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] = pipe_surface_width(dst);
buffer->viewport.scale[1] = pipe_surface_height(dst);
buffer->viewport.scale[2] = 1;
buffer->viewport.translate[0] = 0;
buffer->viewport.translate[1] = 0;
buffer->viewport.translate[2] = 0;
buffer->viewport.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
buffer->viewport.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
buffer->viewport.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
buffer->viewport.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
buffer->fb_state.width = pipe_surface_width(dst);
buffer->fb_state.height = pipe_surface_height(dst);
buffer->fb_state.nr_cbufs = 1;
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);
memset(&buffer->fb_state.cbufs[0], 0, sizeof(struct pipe_surface));
}
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;
u_box_3d(0, 0, intra ? 1 : 0,
VL_BLOCK_WIDTH,
VL_BLOCK_HEIGHT,
1, &rect);
assert(buffer);
assert(matrix);
pipe = zscan->pipe;
rect.width *= zscan->blocks_per_line;
data = pipe->texture_map(pipe, buffer->quant->texture,
0, PIPE_MAP_WRITE |
PIPE_MAP_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->texture_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, MESA_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, MESA_SHADER_FRAGMENT,
0, 3, 0, &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, MESA_PRIM_QUADS, 0, 4, 0, num_instances);
}

View file

@ -1,105 +0,0 @@
/**************************************************************************
*
* 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 "util/vl_zscan_data.h"
#include "util/compiler.h"
#include "pipe/p_state.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* 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;
};
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);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -23,7 +23,7 @@
#include "d3d12_video_dec.h"
#include "d3d12_video_dec_h264.h"
#include "vl/vl_zscan.h"
#include "util/vl_zscan_data.h"
#include <cmath>

View file

@ -28,7 +28,7 @@
#include "util/format/u_format.h"
#include "util/u_sampler.h"
#include "util/u_surface.h"
#include "vl/vl_zscan.h"
#include "util/vl_zscan_data.h"
#include "nv50/nv84_video.h"

View file

@ -23,7 +23,6 @@
#ifndef NV84_VIDEO_H_
#define NV84_VIDEO_H_
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "vl/vl_types.h"

View file

@ -24,7 +24,6 @@
#include "nv50/nv50_screen.h"
#include "nouveau_vp3_video.h"
#include "vl/vl_decoder.h"
#include "vl/vl_types.h"
#include "util/u_video.h"

View file

@ -24,7 +24,6 @@
#include "nvc0/nvc0_screen.h"
#include "nouveau_vp3_video.h"
#include "vl/vl_decoder.h"
#include "vl/vl_types.h"
#include "util/u_video.h"

View file

@ -32,7 +32,6 @@
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "nir/nir_to_tgsi.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "virgl_screen.h"

View file

@ -67,7 +67,6 @@
#include <string.h>
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "util/u_video.h"
#include "util/u_memory.h"

View file

@ -28,7 +28,7 @@
#include "util/macros.h"
#include "util/u_qsort.h"
#include "util/vl_rbsp.h"
#include "vl/vl_zscan.h"
#include "util/vl_zscan_data.h"
#include "va_private.h"
struct ref_cmp {