summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/g3dvl/vl_surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/g3dvl/vl_surface.c')
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_surface.c539
1 files changed, 539 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c
new file mode 100644
index 0000000000..e58e434dab
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_surface.c
@@ -0,0 +1,539 @@
+#include "vl_surface.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_state.h>
+#include <pipe/p_format.h>
+#include <pipe/p_inlines.h>
+#include "vl_context.h"
+#include "vl_defs.h"
+
+static int vlGrabBlocks
+(
+ struct VL_CONTEXT *context,
+ unsigned int coded_block_pattern,
+ enum VL_DCT_TYPE dct_type,
+ enum VL_SAMPLE_TYPE sample_type,
+ short *blocks
+)
+{
+ struct pipe_surface *tex_surface;
+ short *texels;
+ unsigned int b, x, y, y2;
+
+ assert(context);
+ assert(blocks);
+
+ tex_surface = context->pipe->screen->get_tex_surface
+ (
+ context->pipe->screen,
+ context->states.mc.textures[0],
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ texels = pipe_surface_map(tex_surface, 0);
+
+ for (b = 0; b < 4; ++b)
+ {
+ if ((coded_block_pattern >> b) & 1)
+ {
+ if (dct_type == VL_DCT_FRAME_CODED)
+ {
+ if (sample_type == VL_FULL_SAMPLE)
+ {
+ for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y)
+ memcpy
+ (
+ texels + y * tex_surface->pitch,
+ blocks + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+ }
+ else
+ {
+ for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y)
+ for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+ texels[y * tex_surface->pitch + x] =
+ blocks[y * VL_BLOCK_WIDTH + x] + 0x100;
+ }
+ }
+ else
+ {
+ if (sample_type == VL_FULL_SAMPLE)
+ {
+ for
+ (
+ y = VL_BLOCK_HEIGHT * (b % 2), y2 = VL_BLOCK_HEIGHT * b;
+ y < VL_BLOCK_HEIGHT * ((b % 2) + 1);
+ y += 2, ++y2
+ )
+ memcpy
+ (
+ texels + y * tex_surface->pitch,
+ blocks + y2 * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+ for
+ (
+ y = VL_BLOCK_HEIGHT * ((b % 2) + 2);
+ y < VL_BLOCK_HEIGHT * (((b % 2) + 2) + 1);
+ y += 2, ++y2
+ )
+ memcpy
+ (
+ texels + y * tex_surface->pitch,
+ blocks + y2 * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+ }
+ else
+ {
+ for
+ (
+ y = VL_BLOCK_HEIGHT * (b % 2), y2 = VL_BLOCK_HEIGHT * b;
+ y < VL_BLOCK_HEIGHT * ((b % 2) + 1);
+ y += 2, ++y2
+ )
+ for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+ texels[y * tex_surface->pitch + x] =
+ blocks[y2 * VL_BLOCK_WIDTH + x] + 0x100;
+ for
+ (
+ y = VL_BLOCK_HEIGHT * ((b % 2) + 2);
+ y < VL_BLOCK_HEIGHT * (((b % 2) + 2) + 1);
+ y += 2, ++y2
+ )
+ for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+ texels[y * tex_surface->pitch + x] =
+ blocks[y2 * VL_BLOCK_WIDTH + x] + 0x100;
+ }
+ }
+ }
+ else
+ {
+ for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y)
+ {
+ for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+ texels[y * tex_surface->pitch + x] = 0x100;
+ }
+ }
+ }
+
+ pipe_surface_unmap(tex_surface);
+
+ /* TODO: Implement 422, 444 */
+ for (b = 0; b < 2; ++b)
+ {
+ tex_surface = context->pipe->screen->get_tex_surface
+ (
+ context->pipe->screen,
+ context->states.mc.textures[b + 1],
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ texels = pipe_surface_map(tex_surface, 0);
+
+ if ((coded_block_pattern >> (b + 4)) & 1)
+ {
+ if (sample_type == VL_FULL_SAMPLE)
+ {
+ for (y = 0; y < tex_surface->height; ++y)
+ memcpy
+ (
+ texels + y * tex_surface->pitch,
+ blocks + VL_BLOCK_SIZE * (b + 4) + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+ }
+ else
+ {
+ for (y = 0; y < tex_surface->height; ++y)
+ for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+ texels[y * tex_surface->pitch + x] =
+ blocks[VL_BLOCK_SIZE * (b + 4) + y * VL_BLOCK_WIDTH + x] + 0x100;
+ }
+ }
+ else
+ {
+ for (y = 0; y < tex_surface->height; ++y)
+ {
+ for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+ texels[y * tex_surface->pitch + x] = 0x100;
+ }
+ }
+
+ pipe_surface_unmap(tex_surface);
+ }
+
+ return 0;
+}
+
+int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface)
+{
+ struct pipe_context *pipe;
+ struct pipe_texture template;
+ struct VL_SURFACE *sfc;
+
+ assert(context);
+ assert(surface);
+
+ pipe = context->pipe;
+
+ sfc = calloc(1, sizeof(struct VL_SURFACE));
+
+ sfc->context = context;
+ sfc->width = context->video_width;
+ sfc->height = context->video_height;
+ sfc->format = context->video_format;
+
+ memset(&template, 0, sizeof(struct pipe_texture));
+ template.target = PIPE_TEXTURE_2D;
+ template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ template.last_level = 0;
+ template.width[0] = sfc->width;
+ template.height[0] = sfc->height;
+ template.depth[0] = 1;
+ template.compressed = 0;
+ template.cpp = 4;
+
+ sfc->texture = pipe->screen->texture_create(pipe->screen, &template);
+
+ *surface = sfc;
+
+ return 0;
+}
+
+int vlDestroySurface(struct VL_SURFACE *surface)
+{
+ assert(surface);
+ pipe_texture_release(&surface->texture);
+ free(surface);
+
+ return 0;
+}
+
+int vlRenderIMacroBlock
+(
+ enum VL_PICTURE picture_type,
+ enum VL_FIELD_ORDER field_order,
+ unsigned int mbx,
+ unsigned int mby,
+ unsigned int coded_block_pattern,
+ enum VL_DCT_TYPE dct_type,
+ short *blocks,
+ struct VL_SURFACE *surface
+)
+{
+ struct pipe_context *pipe;
+ struct VL_MC_VS_CONSTS *vscbdata;
+
+ assert(blocks);
+ assert(surface);
+
+ /* TODO: Implement interlaced rendering */
+ /*assert(picture_type == VL_FRAME_PICTURE);*/
+ if (picture_type != VL_FRAME_PICTURE)
+ {
+ /*fprintf(stderr, "field picture (I) unimplemented, ignoring\n");*/
+ return 0;
+ }
+
+ pipe = surface->context->pipe;
+
+ vscbdata = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ surface->context->states.mc.vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
+ vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
+ vscbdata->scale.z = 1.0f;
+ vscbdata->scale.w = 1.0f;
+ vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
+ vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
+ vscbdata->mb_pos_trans.z = 0.0f;
+ vscbdata->mb_pos_trans.w = 0.0f;
+
+ pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
+
+ vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_FULL_SAMPLE, blocks);
+
+ surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ surface->texture,
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+ pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
+ pipe->set_sampler_textures(pipe, 3, surface->context->states.mc.textures);
+ pipe->bind_sampler_states(pipe, 3, (void**)surface->context->states.mc.samplers);
+ pipe->set_vertex_buffers(pipe, 4, surface->context->states.mc.vertex_bufs);
+ pipe->set_vertex_elements(pipe, 4, surface->context->states.mc.vertex_buf_elems);
+ pipe->bind_vs_state(pipe, surface->context->states.mc.i_vs);
+ pipe->bind_fs_state(pipe, surface->context->states.mc.i_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+
+ return 0;
+}
+
+int vlRenderPMacroBlock
+(
+ enum VL_PICTURE picture_type,
+ enum VL_FIELD_ORDER field_order,
+ unsigned int mbx,
+ unsigned int mby,
+ enum VL_MC_TYPE mc_type,
+ struct VL_MOTION_VECTOR *motion_vector,
+ unsigned int coded_block_pattern,
+ enum VL_DCT_TYPE dct_type,
+ short *blocks,
+ struct VL_SURFACE *ref_surface,
+ struct VL_SURFACE *surface
+)
+{
+ struct pipe_context *pipe;
+ struct VL_MC_VS_CONSTS *vscbdata;
+
+ assert(motion_vectors);
+ assert(blocks);
+ assert(ref_surface);
+ assert(surface);
+
+ /* TODO: Implement interlaced rendering */
+ /*assert(picture_type == VL_FRAME_PICTURE);*/
+ if (picture_type != VL_FRAME_PICTURE)
+ {
+ /*fprintf(stderr, "field picture (P) unimplemented, ignoring\n");*/
+ return 0;
+ }
+ /* TODO: Implement field based motion compensation */
+ /*assert(mc_type == VL_FRAME_MC);*/
+ if (mc_type != VL_FRAME_MC)
+ {
+ /*fprintf(stderr, "field MC (P) unimplemented, ignoring\n");*/
+ return 0;
+ }
+
+ pipe = surface->context->pipe;
+
+ vscbdata = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ surface->context->states.mc.vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
+ vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
+ vscbdata->scale.z = 1.0f;
+ vscbdata->scale.w = 1.0f;
+ vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
+ vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
+ vscbdata->mb_pos_trans.z = 0.0f;
+ vscbdata->mb_pos_trans.w = 0.0f;
+ vscbdata->mb_tc_trans[0].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->top_field.x * 0.5f) / (float)surface->width;
+ vscbdata->mb_tc_trans[0].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->top_field.y * 0.5f) / (float)surface->height;
+ vscbdata->mb_tc_trans[0].z = 0.0f;
+ vscbdata->mb_tc_trans[0].w = 0.0f;
+
+ pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
+
+ vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
+
+ surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ surface->texture,
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+ pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
+
+ surface->context->states.mc.textures[3] = ref_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, surface->context->states.mc.textures);
+ pipe->bind_sampler_states(pipe, 4, (void**)surface->context->states.mc.samplers);
+ pipe->set_vertex_buffers(pipe, 5, surface->context->states.mc.vertex_bufs);
+ pipe->set_vertex_elements(pipe, 5, surface->context->states.mc.vertex_buf_elems);
+ pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs);
+ pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+
+ return 0;
+}
+
+int vlRenderBMacroBlock
+(
+ enum VL_PICTURE picture_type,
+ enum VL_FIELD_ORDER field_order,
+ unsigned int mbx,
+ unsigned int mby,
+ enum VL_MC_TYPE mc_type,
+ struct VL_MOTION_VECTOR *motion_vector,
+ unsigned int coded_block_pattern,
+ enum VL_DCT_TYPE dct_type,
+ short *blocks,
+ struct VL_SURFACE *past_surface,
+ struct VL_SURFACE *future_surface,
+ struct VL_SURFACE *surface
+)
+{
+ struct pipe_context *pipe;
+ struct VL_MC_VS_CONSTS *vscbdata;
+
+ assert(motion_vectors);
+ assert(blocks);
+ assert(ref_surface);
+ assert(surface);
+
+ /* TODO: Implement interlaced rendering */
+ /*assert(picture_type == VL_FRAME_PICTURE);*/
+ if (picture_type != VL_FRAME_PICTURE)
+ {
+ /*fprintf(stderr, "field picture (B) unimplemented, ignoring\n");*/
+ return 0;
+ }
+ /* TODO: Implement field based motion compensation */
+ /*assert(mc_type == VL_FRAME_MC);*/
+ if (mc_type != VL_FRAME_MC)
+ {
+ /*fprintf(stderr, "field MC (B) unimplemented, ignoring\n");*/
+ return 0;
+ }
+
+ pipe = surface->context->pipe;
+
+ vscbdata = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ surface->context->states.mc.vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
+ vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
+ vscbdata->scale.z = 1.0f;
+ vscbdata->scale.w = 1.0f;
+ vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
+ vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
+ vscbdata->mb_pos_trans.z = 0.0f;
+ vscbdata->mb_pos_trans.w = 0.0f;
+ vscbdata->mb_tc_trans[0].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].top_field.x * 0.5f) / (float)surface->width;
+ vscbdata->mb_tc_trans[0].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].top_field.y * 0.5f) / (float)surface->height;
+ vscbdata->mb_tc_trans[0].z = 0.0f;
+ vscbdata->mb_tc_trans[0].w = 0.0f;
+ vscbdata->mb_tc_trans[1].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].top_field.x * 0.5f) / (float)surface->width;
+ vscbdata->mb_tc_trans[1].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].top_field.y * 0.5f) / (float)surface->height;
+ vscbdata->mb_tc_trans[1].z = 0.0f;
+ vscbdata->mb_tc_trans[1].w = 0.0f;
+
+ pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
+
+ vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
+
+ surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ surface->texture,
+ 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+ pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
+
+ surface->context->states.mc.textures[3] = past_surface->texture;
+ surface->context->states.mc.textures[4] = future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, surface->context->states.mc.textures);
+ pipe->bind_sampler_states(pipe, 5, (void**)surface->context->states.mc.samplers);
+ pipe->set_vertex_buffers(pipe, 6, surface->context->states.mc.vertex_bufs);
+ pipe->set_vertex_elements(pipe, 6, surface->context->states.mc.vertex_buf_elems);
+ pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs);
+ pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+
+ return 0;
+}
+
+int vlPutSurface
+(
+ struct VL_SURFACE *surface,
+ Drawable drawable,
+ unsigned int srcx,
+ unsigned int srcy,
+ unsigned int srcw,
+ unsigned int srch,
+ unsigned int destx,
+ unsigned int desty,
+ unsigned int destw,
+ unsigned int desth,
+ enum VL_PICTURE picture_type
+)
+{
+ unsigned int create_fb = 0;
+ struct pipe_context *pipe;
+
+ assert(surface);
+
+ pipe = surface->context->pipe;
+
+ if (!surface->context->states.csc.framebuffer.cbufs[0])
+ create_fb = 1;
+ else if
+ (
+ surface->context->states.csc.framebuffer.width != destw ||
+ surface->context->states.csc.framebuffer.height != desth
+ )
+ {
+ pipe->winsys->surface_release
+ (
+ pipe->winsys,
+ &surface->context->states.csc.framebuffer.cbufs[0]
+ );
+
+ create_fb = 1;
+ }
+
+ if (create_fb)
+ {
+ surface->context->states.csc.viewport.scale[0] = destw;
+ surface->context->states.csc.viewport.scale[1] = desth;
+ surface->context->states.csc.viewport.scale[2] = 1;
+ surface->context->states.csc.viewport.scale[3] = 1;
+ surface->context->states.csc.viewport.translate[0] = 0;
+ surface->context->states.csc.viewport.translate[1] = 0;
+ surface->context->states.csc.viewport.translate[2] = 0;
+ surface->context->states.csc.viewport.translate[3] = 0;
+
+ surface->context->states.csc.framebuffer.width = destw;
+ surface->context->states.csc.framebuffer.height = desth;
+ surface->context->states.csc.framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys);
+ pipe->winsys->surface_alloc_storage
+ (
+ pipe->winsys,
+ surface->context->states.csc.framebuffer.cbufs[0],
+ destw,
+ desth,
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE,
+ 0
+ );
+ }
+
+ vlEndRender(surface->context);
+
+ pipe->set_sampler_textures(pipe, 1, &surface->texture);
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ pipe->winsys->flush_frontbuffer
+ (
+ pipe->winsys,
+ surface->context->states.csc.framebuffer.cbufs[0],
+ &drawable
+ );
+
+ vlBeginRender(surface->context);
+
+ return 0;
+}
+