summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c')
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c1147
1 files changed, 1147 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
new file mode 100644
index 00000000000..650528ed8fa
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
@@ -0,0 +1,1147 @@
+#define VL_INTERNAL
+#include "vl_r16snorm_mc_buf.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+#include <util/u_math.h>
+#include "vl_render.h"
+#include "vl_shader_build.h"
+#include "vl_surface.h"
+#include "vl_util.h"
+#include "vl_types.h"
+#include "vl_defs.h"
+
+/*
+ * TODO: Dynamically determine number of buf sets to use, based on
+ * video size and available mem, since we can easily run out of memory
+ * for high res videos.
+ * Note: Destroying previous frame's buffers and creating new ones
+ * doesn't work, since the buffer are not actually destroyed until their
+ * fence is signalled, and if we render fast enough we will create faster
+ * than we destroy.
+ */
+#define NUM_BUF_SETS 4 /* Number of rotating buffer sets to use */
+
+enum vlMacroBlockTypeEx
+{
+ vlMacroBlockExTypeIntra,
+ vlMacroBlockExTypeFwdPredictedFrame,
+ vlMacroBlockExTypeFwdPredictedField,
+ vlMacroBlockExTypeBkwdPredictedFrame,
+ vlMacroBlockExTypeBkwdPredictedField,
+ vlMacroBlockExTypeBiPredictedFrame,
+ vlMacroBlockExTypeBiPredictedField,
+
+ vlNumMacroBlockExTypes
+};
+
+struct vlVertexShaderConsts
+{
+ struct vlVertex4f denorm;
+};
+
+struct vlFragmentShaderConsts
+{
+ struct vlVertex4f multiplier;
+ struct vlVertex4f div;
+};
+
+struct vlR16SnormBufferedMC
+{
+ struct vlRender base;
+
+ unsigned int picture_width, picture_height;
+ enum vlFormat picture_format;
+
+ unsigned int cur_buf;
+ struct vlSurface *buffered_surface;
+ struct vlSurface *past_surface, *future_surface;
+ struct vlVertex2f surface_tex_inv_size;
+ struct vlVertex2f zero_block[3];
+ unsigned int num_macroblocks;
+ struct vlMpeg2MacroBlock *macroblocks;
+
+ struct pipe_context *pipe;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state render_target;
+ struct pipe_sampler_state *samplers[5];
+ struct pipe_texture *textures[NUM_BUF_SETS][5];
+ struct pipe_surface *tex_surface[3];
+ short *texels[3];
+ void *i_vs, *p_vs[2], *b_vs[2];
+ void *i_fs, *p_fs[2], *b_fs[2];
+ struct pipe_vertex_buffer vertex_bufs[NUM_BUF_SETS][3];
+ struct pipe_vertex_element vertex_elems[8];
+ struct pipe_constant_buffer vs_const_buf, fs_const_buf;
+};
+
+static int vlBegin
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static inline int vlGrabFrameCodedBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memcpy
+ (
+ dst + y * dst_pitch,
+ src + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memcpy
+ (
+ dst + y * dst_pitch * 2,
+ src + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memset
+ (
+ dst + y * dst_pitch,
+ 0,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabBlocks
+(
+ struct vlR16SnormBufferedMC *mc,
+ unsigned int mbx,
+ unsigned int mby,
+ enum vlDCTType dct_type,
+ unsigned int coded_block_pattern,
+ short *blocks
+)
+{
+ short *texels;
+ unsigned int tex_pitch;
+ unsigned int x, y, tb = 0, sb = 0;
+ unsigned int mbpx = mbx * VL_MACROBLOCK_WIDTH, mbpy = mby * VL_MACROBLOCK_HEIGHT;
+
+ assert(mc);
+ assert(blocks);
+
+ tex_pitch = mc->tex_surface[0]->stride / mc->tex_surface[0]->block.size;
+ texels = mc->texels[0] + mbpy * tex_pitch + mbpx;
+
+ for (y = 0; y < 2; ++y)
+ {
+ for (x = 0; x < 2; ++x, ++tb)
+ {
+ if ((coded_block_pattern >> (5 - tb)) & 1)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+ if (dct_type == vlDCTTypeFrameCoded)
+ {
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH,
+ tex_pitch
+ );
+ }
+ else
+ {
+ vlGrabFieldCodedBlock
+ (
+ cur_block,
+ texels + y * tex_pitch + x * VL_BLOCK_WIDTH,
+ tex_pitch
+ );
+ }
+
+ ++sb;
+ }
+ else if (mc->zero_block[0].x < 0.0f)
+ {
+ vlGrabNoBlock(texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, tex_pitch);
+
+ mc->zero_block[0].x = (mbpx + x * 8) * mc->surface_tex_inv_size.x;
+ mc->zero_block[0].y = (mbpy + y * 8) * mc->surface_tex_inv_size.y;
+ }
+ }
+ }
+
+ /* TODO: Implement 422, 444 */
+ mbpx >>= 1;
+ mbpy >>= 1;
+
+ for (tb = 0; tb < 2; ++tb)
+ {
+ tex_pitch = mc->tex_surface[tb + 1]->stride / mc->tex_surface[tb + 1]->block.size;
+ texels = mc->texels[tb + 1] + mbpy * tex_pitch + mbpx;
+
+ if ((coded_block_pattern >> (1 - tb)) & 1)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels,
+ tex_pitch
+ );
+
+ ++sb;
+ }
+ else if (mc->zero_block[tb + 1].x < 0.0f)
+ {
+ vlGrabNoBlock(texels, tex_pitch);
+
+ mc->zero_block[tb + 1].x = (mbpx << 1) * mc->surface_tex_inv_size.x;
+ mc->zero_block[tb + 1].y = (mbpy << 1) * mc->surface_tex_inv_size.y;
+ }
+ }
+
+ return 0;
+}
+
+static inline enum vlMacroBlockTypeEx vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock *mb)
+{
+ assert(mb);
+
+ switch (mb->mb_type)
+ {
+ case vlMacroBlockTypeIntra:
+ return vlMacroBlockExTypeIntra;
+ case vlMacroBlockTypeFwdPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeFwdPredictedFrame : vlMacroBlockExTypeFwdPredictedField;
+ case vlMacroBlockTypeBkwdPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeBkwdPredictedFrame : vlMacroBlockExTypeBkwdPredictedField;
+ case vlMacroBlockTypeBiPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeBiPredictedFrame : vlMacroBlockExTypeBiPredictedField;
+ default:
+ assert(0);
+ }
+
+ /* Unreachable */
+ return -1;
+}
+
+static inline int vlGrabMacroBlock
+(
+ struct vlR16SnormBufferedMC *mc,
+ struct vlMpeg2MacroBlock *macroblock
+)
+{
+ assert(mc);
+ assert(macroblock);
+
+ mc->macroblocks[mc->num_macroblocks].mbx = macroblock->mbx;
+ mc->macroblocks[mc->num_macroblocks].mby = macroblock->mby;
+ mc->macroblocks[mc->num_macroblocks].mb_type = macroblock->mb_type;
+ mc->macroblocks[mc->num_macroblocks].mo_type = macroblock->mo_type;
+ mc->macroblocks[mc->num_macroblocks].dct_type = macroblock->dct_type;
+ mc->macroblocks[mc->num_macroblocks].PMV[0][0][0] = macroblock->PMV[0][0][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][0][1] = macroblock->PMV[0][0][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][1][0] = macroblock->PMV[0][1][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][1][1] = macroblock->PMV[0][1][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][0][0] = macroblock->PMV[1][0][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][0][1] = macroblock->PMV[1][0][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][1][0] = macroblock->PMV[1][1][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][1][1] = macroblock->PMV[1][1][1];
+ mc->macroblocks[mc->num_macroblocks].cbp = macroblock->cbp;
+ mc->macroblocks[mc->num_macroblocks].blocks = macroblock->blocks;
+
+ vlGrabBlocks
+ (
+ mc,
+ macroblock->mbx,
+ macroblock->mby,
+ macroblock->dct_type,
+ macroblock->cbp,
+ macroblock->blocks
+ );
+
+ mc->num_macroblocks++;
+
+ return 0;
+}
+
+#define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \
+ (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].pos.x = (mbx) * (unitx) + (ofsx); (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ \
+ if ((cbp) & (lm)) \
+ { \
+ (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].luma_tc.x = (zb)[0].x; (vb)[0].luma_tc.y = (zb)[0].y; \
+ (vb)[1].luma_tc.x = (zb)[0].x; (vb)[1].luma_tc.y = (zb)[0].y + (hy); \
+ (vb)[2].luma_tc.x = (zb)[0].x + (hx); (vb)[2].luma_tc.y = (zb)[0].y; \
+ (vb)[3].luma_tc.x = (zb)[0].x + (hx); (vb)[3].luma_tc.y = (zb)[0].y; \
+ (vb)[4].luma_tc.x = (zb)[0].x; (vb)[4].luma_tc.y = (zb)[0].y + (hy); \
+ (vb)[5].luma_tc.x = (zb)[0].x + (hx); (vb)[5].luma_tc.y = (zb)[0].y + (hy); \
+ } \
+ \
+ if ((cbp) & (cbm)) \
+ { \
+ (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].cb_tc.x = (zb)[1].x; (vb)[0].cb_tc.y = (zb)[1].y; \
+ (vb)[1].cb_tc.x = (zb)[1].x; (vb)[1].cb_tc.y = (zb)[1].y + (hy); \
+ (vb)[2].cb_tc.x = (zb)[1].x + (hx); (vb)[2].cb_tc.y = (zb)[1].y; \
+ (vb)[3].cb_tc.x = (zb)[1].x + (hx); (vb)[3].cb_tc.y = (zb)[1].y; \
+ (vb)[4].cb_tc.x = (zb)[1].x; (vb)[4].cb_tc.y = (zb)[1].y + (hy); \
+ (vb)[5].cb_tc.x = (zb)[1].x + (hx); (vb)[5].cb_tc.y = (zb)[1].y + (hy); \
+ } \
+ \
+ if ((cbp) & (crm)) \
+ { \
+ (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].cr_tc.x = (zb)[2].x; (vb)[0].cr_tc.y = (zb)[2].y; \
+ (vb)[1].cr_tc.x = (zb)[2].x; (vb)[1].cr_tc.y = (zb)[2].y + (hy); \
+ (vb)[2].cr_tc.x = (zb)[2].x + (hx); (vb)[2].cr_tc.y = (zb)[2].y; \
+ (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \
+ (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \
+ (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \
+ }
+
+static inline int vlGrabMacroBlockVB
+(
+ struct vlR16SnormBufferedMC *mc,
+ struct vlMpeg2MacroBlock *macroblock,
+ unsigned int pos
+)
+{
+ struct vlVertex2f mo_vec[2];
+ unsigned int i;
+
+ assert(mc);
+ assert(macroblock);
+
+ switch (macroblock->mb_type)
+ {
+ case vlMacroBlockTypeBiPredicted:
+ {
+ struct vlVertex2f *vb;
+
+ vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
+ (
+ mc->pipe->winsys,
+ mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][2].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ ) + pos * 2 * 24;
+
+ mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeFrame)
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ }
+ }
+ else
+ {
+ mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ vb[i + 1].x = mo_vec[1].x;
+ vb[i + 1].y = mo_vec[1].y;
+ }
+ }
+
+ mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][2].buffer);
+
+ /* fall-through */
+ }
+ case vlMacroBlockTypeFwdPredicted:
+ case vlMacroBlockTypeBkwdPredicted:
+ {
+ struct vlVertex2f *vb;
+
+ vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
+ (
+ mc->pipe->winsys,
+ mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][1].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ ) + pos * 2 * 24;
+
+ if (macroblock->mb_type == vlMacroBlockTypeBkwdPredicted)
+ {
+ mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeField)
+ {
+ mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+ }
+ }
+ else
+ {
+ mo_vec[0].x = macroblock->PMV[0][0][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][0][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeField)
+ {
+ mo_vec[1].x = macroblock->PMV[1][0][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][0][1] * 0.5f * mc->surface_tex_inv_size.y;
+ }
+ }
+
+ if (macroblock->mo_type == vlMotionTypeFrame)
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ vb[i + 1].x = mo_vec[1].x;
+ vb[i + 1].y = mo_vec[1].y;
+ }
+ }
+
+ mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][1].buffer);
+
+ /* fall-through */
+ }
+ case vlMacroBlockTypeIntra:
+ {
+ const struct vlVertex2f unit =
+ {
+ mc->surface_tex_inv_size.x * VL_MACROBLOCK_WIDTH,
+ mc->surface_tex_inv_size.y * VL_MACROBLOCK_HEIGHT
+ };
+ const struct vlVertex2f half =
+ {
+ mc->surface_tex_inv_size.x * (VL_MACROBLOCK_WIDTH / 2),
+ mc->surface_tex_inv_size.y * (VL_MACROBLOCK_HEIGHT / 2)
+ };
+
+ struct vlMacroBlockVertexStream0
+ {
+ struct vlVertex2f pos;
+ struct vlVertex2f luma_tc;
+ struct vlVertex2f cb_tc;
+ struct vlVertex2f cr_tc;
+ } *vb;
+
+ vb = (struct vlMacroBlockVertexStream0*)mc->pipe->winsys->buffer_map
+ (
+ mc->pipe->winsys,
+ mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][0].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ ) + pos * 24;
+
+ SET_BLOCK
+ (
+ vb,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, 0, 0, half.x, half.y,
+ 32, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 6,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, half.x, 0, half.x, half.y,
+ 16, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 12,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, 0, half.y, half.x, half.y,
+ 8, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 18,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, half.x, half.y, half.x, half.y,
+ 4, 2, 1, mc->zero_block
+ );
+
+ mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][0].buffer);
+
+ break;
+ }
+ default:
+ assert(0);
+ }
+
+ return 0;
+}
+
+static int vlFlush
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+ unsigned int num_macroblocks[vlNumMacroBlockExTypes] = {0};
+ unsigned int offset[vlNumMacroBlockExTypes];
+ unsigned int vb_start = 0;
+ unsigned int mbw;
+ unsigned int mbh;
+ unsigned int num_mb_per_frame;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+
+ if (!mc->buffered_surface)
+ return 0;
+
+ mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
+ mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
+ num_mb_per_frame = mbw * mbh;
+
+ if (mc->num_macroblocks < num_mb_per_frame)
+ return 0;
+
+ pipe = mc->pipe;
+
+ for (i = 0; i < mc->num_macroblocks; ++i)
+ {
+ enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
+
+ num_macroblocks[mb_type_ex]++;
+ }
+
+ offset[0] = 0;
+
+ for (i = 1; i < vlNumMacroBlockExTypes; ++i)
+ offset[i] = offset[i - 1] + num_macroblocks[i - 1];
+
+ for (i = 0; i < mc->num_macroblocks; ++i)
+ {
+ enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
+
+ vlGrabMacroBlockVB(mc, &mc->macroblocks[i], offset[mb_type_ex]);
+
+ offset[mb_type_ex]++;
+ }
+
+ for (i = 0; i < 3; ++i)
+ {
+ pipe_surface_unmap(mc->tex_surface[i]);
+ mc->pipe->screen->tex_surface_release(mc->pipe->screen, &mc->tex_surface[i]);
+ }
+
+ mc->render_target.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ mc->buffered_surface->texture,
+ 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+ );
+
+ pipe->set_framebuffer_state(pipe, &mc->render_target);
+ pipe->set_viewport_state(pipe, &mc->viewport);
+ vs_consts = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ mc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vs_consts->denorm.x = mc->buffered_surface->texture->width[0];
+ vs_consts->denorm.y = mc->buffered_surface->texture->height[0];
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf);
+
+ if (num_macroblocks[vlMacroBlockExTypeIntra] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 4, mc->vertex_elems);
+ pipe->set_sampler_textures(pipe, 3, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 3, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->i_vs);
+ pipe->bind_fs_state(pipe, mc->i_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeIntra] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeIntra] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][4] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->b_vs[0]);
+ pipe->bind_fs_state(pipe, mc->b_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][4] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->b_vs[1]);
+ pipe->bind_fs_state(pipe, mc->b_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24;
+ }
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence);
+
+ for (i = 0; i < 3; ++i)
+ mc->zero_block[i].x = -1.0f;
+
+ mc->buffered_surface = NULL;
+ mc->num_macroblocks = 0;
+ mc->cur_buf++;
+
+ return 0;
+}
+
+static int vlRenderMacroBlocksMpeg2R16SnormBuffered
+(
+ struct vlRender *render,
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+
+ if (mc->buffered_surface)
+ {
+ if (mc->buffered_surface != surface)
+ {
+ vlFlush(&mc->base);
+ mc->buffered_surface = surface;
+ mc->past_surface = batch->past_surface;
+ mc->future_surface = batch->future_surface;
+ mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
+ mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
+
+ for (i = 0; i < 3; ++i)
+ {
+ mc->tex_surface[i] = mc->pipe->screen->get_tex_surface
+ (
+ mc->pipe->screen,
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][i],
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE);
+ }
+ }
+ }
+ else
+ {
+ mc->buffered_surface = surface;
+ mc->past_surface = batch->past_surface;
+ mc->future_surface = batch->future_surface;
+ mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
+ mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
+
+ for (i = 0; i < 3; ++i)
+ {
+ mc->tex_surface[i] = mc->pipe->screen->get_tex_surface
+ (
+ mc->pipe->screen,
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][i],
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE);
+ }
+ }
+
+ for (i = 0; i < batch->num_macroblocks; ++i)
+ vlGrabMacroBlock(mc, &batch->macroblocks[i]);
+
+ return 0;
+}
+
+static int vlEnd
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static int vlDestroy
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ struct pipe_context *pipe;
+ unsigned int h, i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+ pipe = mc->pipe;
+
+ for (i = 0; i < 5; ++i)
+ pipe->delete_sampler_state(pipe, mc->samplers[i]);
+
+ for (h = 0; h < NUM_BUF_SETS; ++h)
+ for (i = 0; i < 3; ++i)
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs[h][i].buffer);
+
+ /* Textures 3 & 4 are not created directly, no need to release them here */
+ for (i = 0; i < NUM_BUF_SETS; ++i)
+ {
+ pipe_texture_release(&mc->textures[i][0]);
+ pipe_texture_release(&mc->textures[i][1]);
+ pipe_texture_release(&mc->textures[i][2]);
+ }
+
+ pipe->delete_vs_state(pipe, mc->i_vs);
+ pipe->delete_fs_state(pipe, mc->i_fs);
+
+ for (i = 0; i < 2; ++i)
+ {
+ pipe->delete_vs_state(pipe, mc->p_vs[i]);
+ pipe->delete_fs_state(pipe, mc->p_fs[i]);
+ pipe->delete_vs_state(pipe, mc->b_vs[i]);
+ pipe->delete_fs_state(pipe, mc->b_fs[i]);
+ }
+
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->vs_const_buf.buffer);
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->fs_const_buf.buffer);
+
+ free(mc->macroblocks);
+ free(mc);
+
+ return 0;
+}
+
+/*
+ * Muliplier renormalizes block samples from 16 bits to 12 bits.
+ * Divider is used when calculating Y % 2 for choosing top or bottom
+ * field for P or B macroblocks.
+ * TODO: Use immediates.
+ */
+static const struct vlFragmentShaderConsts fs_consts =
+{
+ {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
+ {0.5f, 2.0f, 0.0f, 0.0f}
+};
+
+#include "vl_r16snorm_mc_buf_shaders.inc"
+
+static int vlCreateDataBufs
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
+ const unsigned int mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
+ const unsigned int num_mb_per_frame = mbw * mbh;
+
+ struct pipe_context *pipe;
+ unsigned int h, i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ /* Create our vertex buffers */
+ for (h = 0; h < NUM_BUF_SETS; ++h)
+ {
+ mc->vertex_bufs[h][0].pitch = sizeof(struct vlVertex2f) * 4;
+ mc->vertex_bufs[h][0].max_index = 24 * num_mb_per_frame - 1;
+ mc->vertex_bufs[h][0].buffer_offset = 0;
+ mc->vertex_bufs[h][0].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 4 * 24 * num_mb_per_frame
+ );
+
+ for (i = 1; i < 3; ++i)
+ {
+ mc->vertex_bufs[h][i].pitch = sizeof(struct vlVertex2f) * 2;
+ mc->vertex_bufs[h][i].max_index = 24 * num_mb_per_frame - 1;
+ mc->vertex_bufs[h][i].buffer_offset = 0;
+ mc->vertex_bufs[h][i].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 2 * 24 * num_mb_per_frame
+ );
+ }
+ }
+
+ /* Position element */
+ mc->vertex_elems[0].src_offset = 0;
+ mc->vertex_elems[0].vertex_buffer_index = 0;
+ mc->vertex_elems[0].nr_components = 2;
+ mc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Luma, texcoord element */
+ mc->vertex_elems[1].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[1].vertex_buffer_index = 0;
+ mc->vertex_elems[1].nr_components = 2;
+ mc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Chroma Cr texcoord element */
+ mc->vertex_elems[2].src_offset = sizeof(struct vlVertex2f) * 2;
+ mc->vertex_elems[2].vertex_buffer_index = 0;
+ mc->vertex_elems[2].nr_components = 2;
+ mc->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Chroma Cb texcoord element */
+ mc->vertex_elems[3].src_offset = sizeof(struct vlVertex2f) * 3;
+ mc->vertex_elems[3].vertex_buffer_index = 0;
+ mc->vertex_elems[3].nr_components = 2;
+ mc->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* First ref surface top field texcoord element */
+ mc->vertex_elems[4].src_offset = 0;
+ mc->vertex_elems[4].vertex_buffer_index = 1;
+ mc->vertex_elems[4].nr_components = 2;
+ mc->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* First ref surface bottom field texcoord element */
+ mc->vertex_elems[5].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[5].vertex_buffer_index = 1;
+ mc->vertex_elems[5].nr_components = 2;
+ mc->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Second ref surface top field texcoord element */
+ mc->vertex_elems[6].src_offset = 0;
+ mc->vertex_elems[6].vertex_buffer_index = 2;
+ mc->vertex_elems[6].nr_components = 2;
+ mc->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Second ref surface bottom field texcoord element */
+ mc->vertex_elems[7].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[7].vertex_buffer_index = 2;
+ mc->vertex_elems[7].nr_components = 2;
+ mc->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Create our constant buffer */
+ mc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts);
+ mc->vs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ mc->vs_const_buf.size
+ );
+
+ mc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts);
+ mc->fs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ mc->fs_const_buf.size
+ );
+
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ &fs_consts,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->fs_const_buf.buffer);
+
+ mc->macroblocks = malloc(sizeof(struct vlMpeg2MacroBlock) * num_mb_per_frame);
+
+ return 0;
+}
+
+static int vlInit
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ struct pipe_context *pipe;
+ struct pipe_sampler_state sampler;
+ struct pipe_texture template;
+ unsigned int filters[5];
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ /* For MC we render to textures, which are rounded up to nearest POT */
+ mc->viewport.scale[0] = vlRoundUpPOT(mc->picture_width);
+ mc->viewport.scale[1] = vlRoundUpPOT(mc->picture_height);
+ mc->viewport.scale[2] = 1;
+ mc->viewport.scale[3] = 1;
+ mc->viewport.translate[0] = 0;
+ mc->viewport.translate[1] = 0;
+ mc->viewport.translate[2] = 0;
+ mc->viewport.translate[3] = 0;
+
+ mc->render_target.width = vlRoundUpPOT(mc->picture_width);
+ mc->render_target.height = vlRoundUpPOT(mc->picture_height);
+ mc->render_target.num_cbufs = 1;
+ /* FB for MC stage is a vlSurface created by the user, set at render time */
+ mc->render_target.zsbuf = NULL;
+
+ filters[0] = PIPE_TEX_FILTER_NEAREST;
+ /* FIXME: Linear causes discoloration around block edges */
+ filters[1] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
+ filters[2] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
+ filters[3] = PIPE_TEX_FILTER_LINEAR;
+ filters[4] = PIPE_TEX_FILTER_LINEAR;
+
+ for (i = 0; i < 5; ++i)
+ {
+ 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 = filters[i];
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.mag_img_filter = filters[i];
+ sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+ sampler.compare_func = PIPE_FUNC_ALWAYS;
+ sampler.normalized_coords = 1;
+ /*sampler.prefilter = ;*/
+ /*sampler.shadow_ambient = ;*/
+ /*sampler.lod_bias = ;*/
+ sampler.min_lod = 0;
+ /*sampler.max_lod = ;*/
+ /*sampler.border_color[i] = ;*/
+ /*sampler.max_anisotropy = ;*/
+ mc->samplers[i] = pipe->create_sampler_state(pipe, &sampler);
+ }
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = PIPE_FORMAT_R16_SNORM;
+ template.last_level = 0;
+ template.width[0] = vlRoundUpPOT(mc->picture_width);
+ template.height[0] = vlRoundUpPOT(mc->picture_height);
+ template.depth[0] = 1;
+ template.compressed = 0;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+
+ for (i = 0; i < NUM_BUF_SETS; ++i)
+ mc->textures[i][0] = pipe->screen->texture_create(pipe->screen, &template);
+
+ if (mc->picture_format == vlFormatYCbCr420)
+ {
+ template.width[0] = vlRoundUpPOT(mc->picture_width / 2);
+ template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
+ }
+ else if (mc->picture_format == vlFormatYCbCr422)
+ template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
+
+ for (i = 0; i < NUM_BUF_SETS; ++i)
+ {
+ mc->textures[i][1] = pipe->screen->texture_create(pipe->screen, &template);
+ mc->textures[i][2] = pipe->screen->texture_create(pipe->screen, &template);
+ }
+
+ /* textures[3] & textures[4] are assigned from vlSurfaces for P and B macroblocks at render time */
+
+ vlCreateVertexShaderIMB(mc);
+ vlCreateFragmentShaderIMB(mc);
+ vlCreateVertexShaderFramePMB(mc);
+ vlCreateVertexShaderFieldPMB(mc);
+ vlCreateFragmentShaderFramePMB(mc);
+ vlCreateFragmentShaderFieldPMB(mc);
+ vlCreateVertexShaderFrameBMB(mc);
+ vlCreateVertexShaderFieldBMB(mc);
+ vlCreateFragmentShaderFrameBMB(mc);
+ vlCreateFragmentShaderFieldBMB(mc);
+ vlCreateDataBufs(mc);
+
+ return 0;
+}
+
+int vlCreateR16SNormBufferedMC
+(
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ struct vlRender **render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ unsigned int i;
+
+ assert(pipe);
+ assert(render);
+
+ mc = calloc(1, sizeof(struct vlR16SnormBufferedMC));
+
+ mc->base.vlBegin = &vlBegin;
+ mc->base.vlRenderMacroBlocksMpeg2 = &vlRenderMacroBlocksMpeg2R16SnormBuffered;
+ mc->base.vlEnd = &vlEnd;
+ mc->base.vlFlush = &vlFlush;
+ mc->base.vlDestroy = &vlDestroy;
+ mc->pipe = pipe;
+ mc->picture_width = picture_width;
+ mc->picture_height = picture_height;
+
+ mc->cur_buf = 0;
+ mc->buffered_surface = NULL;
+ mc->past_surface = NULL;
+ mc->future_surface = NULL;
+ for (i = 0; i < 3; ++i)
+ mc->zero_block[i].x = -1.0f;
+ mc->num_macroblocks = 0;
+
+ vlInit(mc);
+
+ *render = &mc->base;
+
+ return 0;
+}