Initial commit for g3dvl.
authorYounes Manton <younes.m@gmail.com>
Sun, 8 Jun 2008 07:04:14 +0000 (03:04 -0400)
committerYounes Manton <younes.m@gmail.com>
Sun, 8 Jun 2008 07:04:14 +0000 (03:04 -0400)
Initial commit for g3dvl, contains support for basic XvMC features.

- Context, surface, block, macroblock creation and deletion
- Surface rendering
  - Frame pictures
  - Frame based motion compensation
  - Intra-coded macroblocks
  - Predicted macroblocks
  - Bi-directionally predicted macroblocks
- Surface display
  - Color conversion
  - Scaling

32 files changed:
src/gallium/state_trackers/g3dvl/Makefile [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/.gitignore [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/Makefile [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_context.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_surface.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_context.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_context.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_data.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_data.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_defs.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_surface.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_surface.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_types.h [new file with mode: 0644]
src/gallium/winsys/g3dvl/xsp_winsys.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/xsp_winsys.h [new file with mode: 0644]
src/libXvMC/Makefile [new file with mode: 0644]
src/libXvMC/attributes.c [new file with mode: 0644]
src/libXvMC/block.c [new file with mode: 0644]
src/libXvMC/context.c [new file with mode: 0644]
src/libXvMC/subpicture.c [new file with mode: 0644]
src/libXvMC/surface.c [new file with mode: 0644]
src/libXvMC/tests/.gitignore [new file with mode: 0644]
src/libXvMC/tests/Makefile [new file with mode: 0644]
src/libXvMC/tests/test_blocks.c [new file with mode: 0644]
src/libXvMC/tests/test_context.c [new file with mode: 0644]
src/libXvMC/tests/test_rendering.c [new file with mode: 0644]
src/libXvMC/tests/test_surface.c [new file with mode: 0644]
src/libXvMC/tests/testlib.c [new file with mode: 0644]
src/libXvMC/tests/testlib.h [new file with mode: 0644]

diff --git a/src/gallium/state_trackers/g3dvl/Makefile b/src/gallium/state_trackers/g3dvl/Makefile
new file mode 100644 (file)
index 0000000..a0d85fb
--- /dev/null
@@ -0,0 +1,18 @@
+TARGET         = libg3dvl.a
+OBJECTS                = vl_context.o vl_data.o vl_surface.o
+GALLIUMDIR     = ../..
+
+CFLAGS         += -g -Wall -fPIC -Werror -I${GALLIUMDIR}/include -I${GALLIUMDIR}/auxiliary
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+       ar rcs $@ $^
+
+clean:
+       rm -rf ${OBJECTS} ${TARGET}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/.gitignore b/src/gallium/state_trackers/g3dvl/tests/.gitignore
new file mode 100644 (file)
index 0000000..939666d
--- /dev/null
@@ -0,0 +1,6 @@
+test_context
+test_surface
+test_i_rendering
+test_p_rendering
+test_b_rendering
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/Makefile b/src/gallium/state_trackers/g3dvl/tests/Makefile
new file mode 100644 (file)
index 0000000..8f98359
--- /dev/null
@@ -0,0 +1,42 @@
+GALLIUMDIR     = ../../..
+
+CFLAGS += -g -Wall -Werror                             \
+          -I${GALLIUMDIR}/state_trackers/g3dvl         \
+          -I${GALLIUMDIR}/winsys/g3dvl                 \
+          -I${GALLIUMDIR}/include                      \
+          -I${GALLIUMDIR}/auxiliary                    \
+          -I${GALLIUMDIR}/drivers
+LDFLAGS        += -L${GALLIUMDIR}/state_trackers/g3dvl         \
+          -L${GALLIUMDIR}/drivers/softpipe             \
+          -L${GALLIUMDIR}/auxiliary/tgsi               \
+          -L${GALLIUMDIR}/auxiliary/draw               \
+          -L${GALLIUMDIR}/auxiliary/util               \
+          -L${GALLIUMDIR}/auxiliary/translate          \
+          -L${GALLIUMDIR}/auxiliary/cso_cache          \
+          -L${GALLIUMDIR}/auxiliary/rtasm
+LIBS   += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lX11 -lm
+
+#############################################
+
+.PHONY = all clean
+
+all: test_context test_surface test_i_rendering test_p_rendering test_b_rendering
+
+test_context: test_context.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_surface: test_surface.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_i_rendering: test_i_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_p_rendering: test_p_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_b_rendering: test_b_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+clean:
+       rm -rf *.o test_context test_surface test_i_rendering test_p_rendering test_b_rendering
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c
new file mode 100644 (file)
index 0000000..b78cc85
--- /dev/null
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+static const signed short ycbcr16x16_420_2[8*8*6] =
+{
+       -0x00A5,-0x00A5,-0x00A5,-0x0072,-0x00A5,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x00A5,-0x0072,-0x0072,-0x00A5,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x00A5,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x00A5,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x00A5,-0x00A5,
+       
+       -0x004F,-0x004F,-0x004F,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x004F,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x004F,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x004F,-0x004F,
+       
+       -0x003E,-0x003E,-0x003E,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x003E,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x003E,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x003E,-0x003E
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc, *past_sfc, *future_sfc;
+       struct VL_MOTION_VECTOR motion_vector[2] =
+       {
+               {
+                       {0, 0}, {0, 0}
+               },
+               {
+                       {0, 0}, {0, 0}
+               }
+       };
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlCreateSurface(ctx, &past_sfc);
+       vlCreateSurface(ctx, &future_sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderBMacroBlock
+       (
+               VL_FRAME_PICTURE,
+               VL_FIELD_FIRST,
+               0,
+               0,
+               VL_FRAME_MC,
+               motion_vector,
+               0x3F,
+               VL_DCT_FRAME_CODED,
+               (short*)ycbcr16x16_420_2,
+               past_sfc,
+               future_sfc,
+               sfc
+       );
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroySurface(past_sfc);
+       vlDestroySurface(future_sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_context.c b/src/gallium/state_trackers/g3dvl/tests/test_context.c
new file mode 100644 (file)
index 0000000..2002977
--- /dev/null
@@ -0,0 +1,22 @@
+#include <vl_context.h>
+#include <xsp_winsys.h>
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       
+       Display                 *display;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       
+       display = XOpenDisplay(NULL);
+       pipe = create_pipe_context(display);
+       
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlDestroyContext(ctx);
+       
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c
new file mode 100644 (file)
index 0000000..1f96471
--- /dev/null
@@ -0,0 +1,137 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc;
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c
new file mode 100644 (file)
index 0000000..2203349
--- /dev/null
@@ -0,0 +1,214 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+static const signed short ycbcr16x16_420_2[8*8*6] =
+{
+       -51,-51,-51,  0,-51,  0,  0,  0,
+         0,-51,  0,  0,-51,  0,  0,  0,
+         0,-51,  0,  0,-51,-51,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+       
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+        99, 99, 99,  0,  0,  0,  0,  0,
+         0,  0, 99,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+        33, 33, 33,  0,  0,  0,  0,  0,
+         0,  0, 33,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc, *ref_sfc;
+       struct VL_MOTION_VECTOR motion_vector =
+       {
+               {0, 0}, {0, 0}
+       };
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlCreateSurface(ctx, &ref_sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderPMacroBlock
+       (
+               VL_FRAME_PICTURE,
+               VL_FIELD_FIRST,
+               0,
+               0,
+               VL_FRAME_MC,
+               &motion_vector,
+               0x3F,
+               VL_DCT_FRAME_CODED,
+               (short*)ycbcr16x16_420_2,
+               ref_sfc,
+               sfc
+       );
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroySurface(ref_sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_surface.c b/src/gallium/state_trackers/g3dvl/tests/test_surface.c
new file mode 100644 (file)
index 0000000..4d19463
--- /dev/null
@@ -0,0 +1,26 @@
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       
+       Display                 *display;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc;
+       
+       display = XOpenDisplay(NULL);
+       pipe = create_pipe_context(display);
+       
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlDestroySurface(sfc);
+       vlDestroyContext(ctx);
+       
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.c b/src/gallium/state_trackers/g3dvl/vl_context.c
new file mode 100644 (file)
index 0000000..7193f7c
--- /dev/null
@@ -0,0 +1,2293 @@
+#include "vl_context.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 <pipe/p_shader_tokens.h>
+#include <tgsi/util/tgsi_parse.h>
+#include <tgsi/util/tgsi_build.h>
+#include "vl_data.h"
+
+static int vlInitIDCT(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       
+       
+       return 0;
+}
+
+static int vlDestroyIDCT(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderIMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       const unsigned int              num_attribs = 4;
+       const unsigned int              semantic_names[4] =
+                                       {
+                                               TGSI_SEMANTIC_POSITION,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC
+                                       };
+       const unsigned int              semantic_indexes[4] = {0, 1, 2, 3};
+       const unsigned int              proc_type = TGSI_PROCESSOR_VERTEX;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* Declare constant inputs */
+       /* C[0] scales the normalized MB to cover 16x16 pixels,
+          C[1] translates the macroblock into position on the surface */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 1;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* Declare outputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_OUTPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t0, i0, c0       ; Scale normalized coords to window coords */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* add o0, t0, c1       ; Translate vertex into position */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /*
+       mov o1, i1              ; Move texcoords to output
+       mov o2, i2
+       mov o3, i3
+       */
+       for (i = 1; i < num_attribs; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = i;
+               inst.Instruction.NumSrcRegs = 1;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* END */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       vs.tokens = tokens;
+       
+       context->states.mc.i_vs = pipe->create_vs_state(pipe, &vs);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderIMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       const unsigned int              proc_type = TGSI_PROCESSOR_FRAGMENT;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (texcoords) */
+       for (i = 0; i < 3; ++i)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+               decl.Semantic.SemanticIndex = i + 1;
+               decl.Declaration.Interpolate = 1;
+               decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* Declare output (color) */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_OUTPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 0;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* Declare samplers */
+       for (i = 0; i < 3; ++i)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_SAMPLER;
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /*
+       tex2d o0.x, i0, s0              ; Read texel from luma texture into .x channel
+       tex2d o0.y, i1, s1              ; Read texel from chroma Cb texture into .y channel
+       tex2d o0.z, i2, s2              ; Read texel from chroma Cr texture into .z channel
+       */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = 0;
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+               inst.FullSrcRegisters[1].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* END */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       fs.tokens = tokens;
+       
+       context->states.mc.i_fs = pipe->create_fs_state(pipe, &fs);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderPMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       const unsigned int              num_attribs = 5;
+       const unsigned int              semantic_names[5] =
+                                       {
+                                               TGSI_SEMANTIC_POSITION,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC
+                                       };
+       const unsigned int              semantic_indexes[5] = {0, 1, 2, 3, 4};
+       const unsigned int              proc_type = TGSI_PROCESSOR_VERTEX;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* Declare constant inputs */
+       /* C[0] scales the normalized MB to cover 16x16 pixels,
+          C[1] translates the macroblock into position on the surface
+          C[2] translates the ref surface texcoords to the ref macroblock */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 2;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* Declare outputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_OUTPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t0, i0, c0       ; Scale normalized coords to window coords */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* add o0, t0, c1       ; Translate vertex into position */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /*
+       mov o1, i1              ; Move luma & chroma texcoords to output
+       mov o2, i2
+       mov o3, i3
+       */
+       for (i = 1; i < num_attribs - 1; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = i;
+               inst.Instruction.NumSrcRegs = 1;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t0, i4, c0       ; Scale normalized coords to window coords */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 4;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* add o4, t0, c2       ; Translate texcoords into position */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+       inst.FullDstRegisters[0].DstRegister.Index = 4;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 2;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* END */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       vs.tokens = tokens;
+       
+       context->states.mc.p_vs = pipe->create_vs_state(pipe, &vs);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderPMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       const unsigned int              proc_type = TGSI_PROCESSOR_FRAGMENT;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (texcoords) */
+       for (i = 0; i < 4; ++i)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+               decl.Semantic.SemanticIndex = i + 1;
+               decl.Declaration.Interpolate = 1;
+               decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* Declare constant input */
+       /* C[0] is a multiplier to use when concatenating differential into a single channel
+          C[0] is a bias to get differential back to -1,1 range*/
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 1;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* Declare output */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_OUTPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 0;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* Declare samplers */
+       for (i = 0; i < 4; ++i)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_SAMPLER;
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /*
+       tex2d t0.xw, i0, s0     ; Read texel from luma texture into .x and .w channels
+       mov t1.x, t0.w          ; Move high part from .w channel to .x
+       tex2d t0.yw, i1, s1     ; Read texel from chroma Cb texture into .y and .w channels
+       mov t1.y, t0.w          ; Move high part from .w channel to .y
+       tex2d t0.zw, i2, s2     ; Read texel from chroma Cr texture into .z and .w channels
+       mov t1.z, t0.w          ; Move high part from .w channel to .z
+       */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullDstRegisters[0].DstRegister.Index = 0;
+               inst.FullDstRegisters[0].DstRegister.WriteMask = (TGSI_WRITEMASK_X << i) | TGSI_WRITEMASK_W;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+               inst.FullSrcRegisters[1].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+               
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullDstRegisters[0].DstRegister.Index = 1;
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.Instruction.NumSrcRegs = 1;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t1, t1, c0       ; Muliply high part by multiplier to get back its full value */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 1;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 1;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* add t0, t0, t1       ; Add luma and chroma low and high parts to get a single value */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* sub t0, t0, c1       ; Subtract bias to get back the signed value */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_SUB;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* tex2d t1, i3, s3     ; Read texel from ref macroblock */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 1;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 3;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 3;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* add o0, t0, t1       ; Add ref and differential to form final output */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* END */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       fs.tokens = tokens;
+       
+       context->states.mc.p_fs = pipe->create_fs_state(pipe, &fs);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderBMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       const unsigned int              num_attribs = 6;
+       const unsigned int              semantic_names[6] =
+                                       {
+                                               TGSI_SEMANTIC_POSITION,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC,
+                                               TGSI_SEMANTIC_GENERIC
+                                       };
+       const unsigned int              semantic_indexes[6] = {0, 1, 2, 3, 4, 5};
+       const unsigned int              proc_type = TGSI_PROCESSOR_VERTEX;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* Declare constant inputs */
+       /* C[0] scales the normalized MB to cover 16x16 pixels,
+          C[1] translates the macroblock into position on the surface
+          C[2] translates the past surface texcoords to the ref macroblock
+          C[3] translates the future surface texcoords to the ref macroblock */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 3;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* Declare outputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_OUTPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t0, i0, c0       ; Scale normalized coords to window coords */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* add o0, t0, c1       ; Translate vertex into position */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /*
+       mov o1, i1              ; Move luma & chroma texcoords to output
+       mov o2, i2
+       mov o3, i3
+       */
+       for (i = 1; i < num_attribs - 1; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = i;
+               inst.Instruction.NumSrcRegs = 1;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t0, i4, c0       ; Scale normalized coords to window coords
+          add o4, t0, c2       ; Translate texcoords into position
+          mul t1, i5, c0       ; Repeat for the future surface
+          add o5, t1, c3 */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullDstRegisters[0].DstRegister.Index = i;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i + 4;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+               inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = i + 4;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+               inst.FullSrcRegisters[1].SrcRegister.Index = i + 2;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* END */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       vs.tokens = tokens;
+       
+       context->states.mc.b_vs = pipe->create_vs_state(pipe, &vs);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderBMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       const unsigned int              proc_type = TGSI_PROCESSOR_FRAGMENT;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (texcoords) */
+       for (i = 0; i < 5; ++i)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+               decl.Semantic.SemanticIndex = i + 1;
+               decl.Declaration.Interpolate = 1;
+               decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* Declare constant input */
+       /* C[0] is a multiplier to use when concatenating differential into a single channel
+          C[0] is a bias to get differential back to -1,1 range*/
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 1;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* Declare output */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_OUTPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 0;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* Declare samplers */
+       for (i = 0; i < 5; ++i)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_SAMPLER;
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /*
+       tex2d t0.xw, i0, s0     ; Read texel from luma texture into .x and .w channels
+       mov t1.x, t0.w          ; Move high part from .w channel to .x
+       tex2d t0.yw, i1, s1     ; Read texel from chroma Cb texture into .y and .w channels
+       mov t1.y, t0.w          ; Move high part from .w channel to .y
+       tex2d t0.zw, i2, s2     ; Read texel from chroma Cr texture into .z and .w channels
+       mov t1.z, t0.w          ; Move high part from .w channel to .z
+       */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullDstRegisters[0].DstRegister.Index = 0;
+               inst.FullDstRegisters[0].DstRegister.WriteMask = (TGSI_WRITEMASK_X << i) | TGSI_WRITEMASK_W;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+               inst.FullSrcRegisters[1].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+               
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullDstRegisters[0].DstRegister.Index = 1;
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.Instruction.NumSrcRegs = 1;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* mul t1, t1, c0       ; Muliply high part by multiplier to get back its full value */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_MUL;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 1;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 1;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* add t0, t0, t1       ; Add luma and chroma low and high parts to get a single value */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* sub t0, t0, c1       ; Subtract bias to get back the signed value */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_SUB;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* tex2d t1, i3, s3     ; Read texel from past macroblock
+          tex2d t2, i4, s4     ; Read texel from future macroblock */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullDstRegisters[0].DstRegister.Index = i + 1;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i + 3;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+               inst.FullSrcRegisters[1].SrcRegister.Index = i + 3;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /* add t0, t0, t1       ; Add past and differential to form partial output */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 1;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* add o0, t0, t2       ; Add future and differential to form final output */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_ADD;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 2;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* END */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       fs.tokens = tokens;
+       
+       context->states.mc.b_fs = pipe->create_fs_state(pipe, &fs);
+       
+       return 0;
+}
+
+int vlCreateDataBufsMC(struct VL_CONTEXT *context)
+{
+       struct pipe_context     *pipe;
+       unsigned int            i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* Create our vertex buffer and vertex buffer element */
+       context->states.mc.vertex_bufs[0].pitch = sizeof(struct VL_VERTEX2F);
+       context->states.mc.vertex_bufs[0].max_index = 23;
+       context->states.mc.vertex_bufs[0].buffer_offset = 0;
+       context->states.mc.vertex_bufs[0].buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_VERTEX,
+               sizeof(struct VL_VERTEX2F) * 24
+       );
+       
+       context->states.mc.vertex_buf_elems[0].src_offset = 0;
+       context->states.mc.vertex_buf_elems[0].vertex_buffer_index = 0;
+       context->states.mc.vertex_buf_elems[0].nr_components = 2;
+       context->states.mc.vertex_buf_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       
+       /* Create our texcoord buffers and texcoord buffer elements */
+       /* TODO: Should be able to use 1 texcoord buf for chroma textures, 1 buf for ref surfaces */
+       for (i = 1; i < 6; ++i)
+       {
+               context->states.mc.vertex_bufs[i].pitch = sizeof(struct VL_TEXCOORD2F);
+               context->states.mc.vertex_bufs[i].max_index = 23;
+               context->states.mc.vertex_bufs[i].buffer_offset = 0;
+               context->states.mc.vertex_bufs[i].buffer = pipe->winsys->buffer_create
+               (
+                       pipe->winsys,
+                       1,
+                       PIPE_BUFFER_USAGE_VERTEX,
+                       sizeof(struct VL_TEXCOORD2F) * 24
+               );
+       
+               context->states.mc.vertex_buf_elems[i].src_offset = 0;
+               context->states.mc.vertex_buf_elems[i].vertex_buffer_index = i;
+               context->states.mc.vertex_buf_elems[i].nr_components = 2;
+               context->states.mc.vertex_buf_elems[i].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       }
+       
+       /* Fill buffers */
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_chroma_420_texcoords,
+               sizeof(struct VL_VERTEX2F) * 24
+       );
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_luma_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       /* TODO: Accomodate 422, 444 */
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[2].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_chroma_420_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[3].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_chroma_420_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[4].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_ref_surface_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[5].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_ref_surface_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       
+       for (i = 0; i < 6; ++i)
+               pipe->winsys->buffer_unmap(pipe->winsys, context->states.mc.vertex_bufs[i].buffer);
+       
+       /* Create our constant buffer */
+       context->states.mc.vs_const_buf.size = sizeof(struct VL_MC_VS_CONSTS);
+       context->states.mc.vs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.mc.vs_const_buf.size
+       );
+       
+       context->states.mc.fs_const_buf.size = sizeof(struct VL_MC_FS_CONSTS);
+       context->states.mc.fs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.mc.fs_const_buf.size
+       );
+       
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               &vl_mc_fs_consts,
+               sizeof(struct VL_MC_FS_CONSTS)
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.mc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlInitMC(struct VL_CONTEXT *context)
+{      
+       struct pipe_context             *pipe;
+       struct pipe_sampler_state       sampler;
+       struct pipe_texture             template;
+       unsigned int                    filters[5];
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       context->states.mc.viewport.scale[0] = context->video_width;
+       context->states.mc.viewport.scale[1] = context->video_height;
+       context->states.mc.viewport.scale[2] = 1;
+       context->states.mc.viewport.scale[3] = 1;
+       context->states.mc.viewport.translate[0] = 0;
+       context->states.mc.viewport.translate[1] = 0;
+       context->states.mc.viewport.translate[2] = 0;
+       context->states.mc.viewport.translate[3] = 0;
+       
+       context->states.mc.render_target.width = context->video_width;
+       context->states.mc.render_target.height = context->video_height;
+       context->states.mc.render_target.num_cbufs = 1;
+       /* FB for MC stage is a VL_SURFACE, set in vlSetRenderSurface() */
+       /*context->states.mc.render_target.cbufs[0] = ;*/
+       context->states.mc.render_target.zsbuf = NULL;
+       
+       filters[0] = PIPE_TEX_FILTER_NEAREST;
+       filters[1] = context->video_format == VL_FORMAT_YCBCR_444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+       filters[2] = context->video_format == VL_FORMAT_YCBCR_444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+       filters[3] = PIPE_TEX_FILTER_NEAREST;
+       filters[4] = PIPE_TEX_FILTER_NEAREST;
+       
+       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 = ;*/
+               /*sampler.max_lod = ;*/
+               /*sampler.border_color[i] = ;*/
+               /*sampler.max_anisotropy = ;*/
+               context->states.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_A8L8_UNORM;
+       template.last_level = 0;
+       template.width[0] = 8;
+       template.height[0] = 8 * 4;
+       template.depth[0] = 1;
+       template.compressed = 0;
+       template.cpp = 2;
+       context->states.mc.textures[0] = pipe->screen->texture_create(pipe->screen, &template);
+       
+       if (context->video_format == VL_FORMAT_YCBCR_420)
+               template.height[0] = 8;
+       else if (context->video_format == VL_FORMAT_YCBCR_422)
+               template.height[0] = 8 * 2;
+       else if (context->video_format == VL_FORMAT_YCBCR_444)
+               template.height[0] = 8 * 4;
+       else
+               assert(0);
+               
+       context->states.mc.textures[1] = pipe->screen->texture_create(pipe->screen, &template);
+       context->states.mc.textures[2] = pipe->screen->texture_create(pipe->screen, &template);
+       
+       /* textures[3] & textures[4] are assigned from VL_SURFACEs for P and B macroblocks at render time */
+       
+       vlCreateVertexShaderIMC(context);
+       vlCreateFragmentShaderIMC(context);
+       vlCreateVertexShaderPMC(context);
+       vlCreateFragmentShaderPMC(context);
+       vlCreateVertexShaderBMC(context);
+       vlCreateFragmentShaderBMC(context);
+       vlCreateDataBufsMC(context);
+       
+       return 0;
+}
+
+static int vlDestroyMC(struct VL_CONTEXT *context)
+{
+       unsigned int i;
+       
+       assert(context);
+       
+       for (i = 0; i < 5; ++i)
+       {
+               context->pipe->delete_sampler_state(context->pipe, context->states.mc.samplers[i]);
+               context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vertex_bufs[i].buffer);
+       }
+       
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vertex_bufs[5].buffer);
+       
+       /* Textures 3 & 4 are not created directly, no need to release them here */
+       for (i = 0; i < 3; ++i)
+               pipe_texture_release(&context->states.mc.textures[i]);
+       
+       context->pipe->delete_vs_state(context->pipe, context->states.mc.i_vs);
+       context->pipe->delete_fs_state(context->pipe, context->states.mc.i_fs);
+       context->pipe->delete_vs_state(context->pipe, context->states.mc.p_vs);
+       context->pipe->delete_fs_state(context->pipe, context->states.mc.p_fs);
+       context->pipe->delete_vs_state(context->pipe, context->states.mc.b_vs);
+       context->pipe->delete_fs_state(context->pipe, context->states.mc.b_fs);
+       
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vs_const_buf.buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderCSC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       const unsigned int              num_attribs = 2;
+       const unsigned int              semantic_names[2] = {TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC};
+       const unsigned int              semantic_indexes[2] = {0, 1};
+       const unsigned int              proc_type = TGSI_PROCESSOR_VERTEX;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare inputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_INPUT;
+
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* Declare outputs (pos, texcoords) */
+       for (i = 0; i < num_attribs; i++)
+       {
+               decl = tgsi_default_full_declaration();
+               decl.Declaration.File = TGSI_FILE_OUTPUT;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.SemanticName = semantic_names[i];
+               decl.Semantic.SemanticIndex = semantic_indexes[i];
+               decl.u.DeclarationRange.First = i;
+               decl.u.DeclarationRange.Last = i;
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* MOV instructions */
+       /* mov o0, i0
+          mov o1, i1 */
+       for (i = 0; i < num_attribs; i++)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = i;
+               inst.Instruction.NumSrcRegs = 1;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+               inst.FullSrcRegisters[0].SrcRegister.Index = i;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* END instruction */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       vs.tokens = tokens;
+       
+       context->states.csc.vertex_shader = pipe->create_vs_state(pipe, &vs);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderCSC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       const unsigned int              proc_type = TGSI_PROCESSOR_FRAGMENT;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       struct tgsi_processor           *processor;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+
+       /* Processor */
+       processor = (struct tgsi_processor*)&tokens[2];
+       *processor = tgsi_build_processor(proc_type, header);
+
+       ti = 3;
+
+       /* Declare TEX[0] input */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_INPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 1;
+       decl.Declaration.Interpolate = 1;
+       decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 0;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* Declare constant input */
+       /* Constants include bias vector, 4x4 csc matrix, total 5 vectors */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 4;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       /* Declare output */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_OUTPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR;
+       decl.Semantic.SemanticIndex = 0;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 0;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* Declare sampler */
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_SAMPLER;
+       decl.u.DeclarationRange.First = 0;
+       decl.u.DeclarationRange.Last = 0;
+       ti += tgsi_build_full_declaration
+       (
+               &decl,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* TEX instruction */
+       /* tex2d t0, i0, s0 */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* SUB instruction */
+       /* sub t0, t0, c0 */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_SUB;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullDstRegisters[0].DstRegister.Index = 0;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+       inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+       inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+       inst.FullSrcRegisters[1].SrcRegister.Index = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+       
+       /* DP4 instruction */
+       /* dp4 o0.x, t0, c1
+          dp4 o0.y, t0, c2
+          dp4 o0.z, t0, c3
+          dp4 o0.w, t0, c4 */
+       for (i = 0; i < 4; ++i)
+       {
+               inst = tgsi_default_full_instruction();
+               inst.Instruction.Opcode = TGSI_OPCODE_DP4;
+               inst.Instruction.NumDstRegs = 1;
+               inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+               inst.FullDstRegisters[0].DstRegister.Index = 0;
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.Instruction.NumSrcRegs = 2;
+               inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
+               inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+               inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_CONSTANT;
+               inst.FullSrcRegisters[1].SrcRegister.Index = i + 1;
+               ti += tgsi_build_full_instruction
+               (
+                       &inst,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+
+       /* END instruction */
+       inst = tgsi_default_full_instruction();
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       ti += tgsi_build_full_instruction
+       (
+               &inst,
+               &tokens[ti],
+               header,
+               max_tokens - ti
+       );
+
+       fs.tokens = tokens;
+       
+       context->states.csc.fragment_shader = pipe->create_fs_state(pipe, &fs);
+       
+       return 0;
+}
+
+static int vlCreateDataBufsCSC(struct VL_CONTEXT *context)
+{
+       struct pipe_context *pipe;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /*
+       Create our vertex buffer and vertex buffer element
+       VB contains 4 vertices that render a quad covering the entire window
+       to display a rendered surface
+       Quad is rendered as a tri strip
+       */
+       context->states.csc.vertex_bufs[0].pitch = sizeof(struct VL_VERTEX2F);
+       context->states.csc.vertex_bufs[0].max_index = 3;
+       context->states.csc.vertex_bufs[0].buffer_offset = 0;
+       context->states.csc.vertex_bufs[0].buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_VERTEX,
+               sizeof(struct VL_VERTEX2F) * 4
+       );
+       
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.csc.vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_surface_vertex_positions,
+               sizeof(struct VL_VERTEX2F) * 4
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.vertex_bufs[0].buffer);
+       
+       context->states.csc.vertex_buf_elems[0].src_offset = 0;
+       context->states.csc.vertex_buf_elems[0].vertex_buffer_index = 0;
+       context->states.csc.vertex_buf_elems[0].nr_components = 2;
+       context->states.csc.vertex_buf_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       
+       /*
+       Create our texcoord buffer and texcoord buffer element
+       Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices
+       */
+       context->states.csc.vertex_bufs[1].pitch = sizeof(struct VL_TEXCOORD2F);
+       context->states.csc.vertex_bufs[1].max_index = 3;
+       context->states.csc.vertex_bufs[1].buffer_offset = 0;
+       context->states.csc.vertex_bufs[1].buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_VERTEX,
+               sizeof(struct VL_TEXCOORD2F) * 4
+       );
+       
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.csc.vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_surface_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 4
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.vertex_bufs[1].buffer);
+       
+       context->states.csc.vertex_buf_elems[1].src_offset = 0;
+       context->states.csc.vertex_buf_elems[1].vertex_buffer_index = 1;
+       context->states.csc.vertex_buf_elems[1].nr_components = 2;
+       context->states.csc.vertex_buf_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       
+       /*
+       Create our fragment shader's constant buffer
+       Const buffer contains the color conversion matrix and bias vectors
+       */
+       context->states.csc.fs_const_buf.size = sizeof(struct VL_CSC_FS_CONSTS);
+       context->states.csc.fs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.csc.fs_const_buf.size
+       );
+       
+       /*
+       TODO: Refactor this into a seperate function,
+       allow changing the csc matrix at runtime to switch between regular & full versions
+       */
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.csc.fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               &vl_csc_fs_consts_601,
+               sizeof(struct VL_CSC_FS_CONSTS)
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlInitCSC(struct VL_CONTEXT *context)
+{      
+       struct pipe_context             *pipe;
+       struct pipe_sampler_state       sampler;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* Delay creating the FB until vlPutSurface() so we know window size */
+       context->states.csc.framebuffer.num_cbufs = 1;
+       context->states.csc.framebuffer.cbufs[0] = NULL;
+       context->states.csc.framebuffer.zsbuf = NULL;
+
+       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+       sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+       sampler.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 = ;*/
+       /*sampler.max_lod = ;*/
+       /*sampler.border_color[i] = ;*/
+       /*sampler.max_anisotropy = ;*/
+       context->states.csc.sampler = pipe->create_sampler_state(pipe, &sampler);
+       
+       vlCreateVertexShaderCSC(context);
+       vlCreateFragmentShaderCSC(context);
+       vlCreateDataBufsCSC(context);
+       
+       return 0;
+}
+
+static int vlDestroyCSC(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       /*
+       Since we create the final FB when we display our first surface,
+       it may not be created if vlPutSurface() is never called
+       */
+       if (context->states.csc.framebuffer.cbufs[0])
+               context->pipe->winsys->surface_release(context->pipe->winsys, &context->states.csc.framebuffer.cbufs[0]);
+       context->pipe->delete_sampler_state(context->pipe, context->states.csc.sampler);
+       context->pipe->delete_vs_state(context->pipe, context->states.csc.vertex_shader);
+       context->pipe->delete_fs_state(context->pipe, context->states.csc.fragment_shader);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vertex_bufs[0].buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vertex_bufs[1].buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlInitCommon(struct VL_CONTEXT *context)
+{
+       struct pipe_context                     *pipe;
+       struct pipe_rasterizer_state            rast;
+       struct pipe_blend_state                 blend;
+       struct pipe_depth_stencil_alpha_state   dsa;
+       unsigned int                            i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       rast.flatshade = 1;
+       rast.light_twoside = 0;
+       rast.front_winding = PIPE_WINDING_CCW;
+       rast.cull_mode = PIPE_WINDING_CW;
+       rast.fill_cw = PIPE_POLYGON_MODE_FILL;
+       rast.fill_ccw = PIPE_POLYGON_MODE_FILL;
+       rast.offset_cw = 0;
+       rast.offset_ccw = 0;
+       rast.scissor = 0;
+       rast.poly_smooth = 0;
+       rast.point_sprite = 0;
+       rast.point_size_per_vertex = 0;
+       rast.multisample = 0;
+       rast.line_smooth = 0;
+       rast.line_stipple_enable = 0;
+       rast.line_stipple_factor = 0;
+       rast.line_stipple_pattern = 0;
+       rast.line_last_pixel = 0;
+       /* Don't need clipping, but viewport mapping done here */
+       rast.bypass_clipping = 0;
+       rast.bypass_vs = 0;
+       rast.origin_lower_left = 0;
+       rast.line_width = 1;
+       rast.point_size = 1;
+       rast.offset_units = 1;
+       rast.offset_scale = 1;
+       /*rast.sprite_coord_mode[i] = ;*/
+       context->states.common.raster = pipe->create_rasterizer_state(pipe, &rast);
+       pipe->bind_rasterizer_state(pipe, context->states.common.raster);
+       
+       blend.blend_enable = 0;
+       blend.rgb_func = PIPE_BLEND_ADD;
+       blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+       blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+       blend.alpha_func = PIPE_BLEND_ADD;
+       blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+       blend.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.colormask = PIPE_MASK_RGBA;
+       blend.dither = 0;
+       context->states.common.blend = pipe->create_blend_state(pipe, &blend);
+       pipe->bind_blend_state(pipe, context->states.common.blend);
+       
+       dsa.depth.enabled = 0;
+       dsa.depth.writemask = 0;
+       dsa.depth.func = PIPE_FUNC_ALWAYS;
+       dsa.depth.occlusion_count = 0;
+       for (i = 0; i < 2; ++i)
+       {
+               dsa.stencil[i].enabled = 0;
+               dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
+               dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
+               dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
+               dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
+               dsa.stencil[i].ref_value = 0;
+               dsa.stencil[i].value_mask = 0;
+               dsa.stencil[i].write_mask = 0;
+       }
+       dsa.alpha.enabled = 0;
+       dsa.alpha.func = PIPE_FUNC_ALWAYS;
+       dsa.alpha.ref = 0;
+       context->states.common.dsa = pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+       pipe->bind_depth_stencil_alpha_state(pipe, context->states.common.dsa);
+       
+       return 0;
+}
+
+static int vlDestroyCommon(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       context->pipe->delete_blend_state(context->pipe, context->states.common.blend);
+       context->pipe->delete_rasterizer_state(context->pipe, context->states.common.raster);
+       context->pipe->delete_depth_stencil_alpha_state(context->pipe, context->states.common.dsa);
+       
+       return 0;
+}
+
+static int vlInit(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       vlInitCommon(context);
+       vlInitCSC(context);
+       vlInitMC(context);
+       vlInitIDCT(context);
+       
+       return 0;
+}
+
+static int vlDestroy(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       /* Must unbind shaders before we can delete them for some reason */
+       context->pipe->bind_vs_state(context->pipe, NULL);
+       context->pipe->bind_fs_state(context->pipe, NULL);
+       
+       vlDestroyCommon(context);
+       vlDestroyCSC(context);
+       vlDestroyMC(context);
+       vlDestroyIDCT(context);
+       
+       return 0;
+}
+
+int vlCreateContext
+(
+       Display *display,
+       struct pipe_context *pipe,
+       unsigned int video_width,
+       unsigned int video_height,
+       enum VL_FORMAT video_format,
+       struct VL_CONTEXT **context
+)
+{
+       struct VL_CONTEXT *ctx;
+       
+       assert(display);
+       assert(pipe);
+       assert(context);
+       
+       ctx = calloc(1, sizeof(struct VL_CONTEXT));
+       
+       ctx->display = display;
+       ctx->pipe = pipe;
+       ctx->video_width = video_width;
+       ctx->video_height = video_height;
+       ctx->video_format = video_format;
+       
+       vlInit(ctx);
+       
+       /* Since we only change states in vlPutSurface() we need to start in render mode */
+       vlBeginRender(ctx);
+       
+       *context = ctx;
+       
+       return 0;
+}
+
+int vlDestroyContext(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       vlDestroy(context);
+       
+       free(context);
+       
+       return 0;
+}
+
+int vlBeginRender(struct VL_CONTEXT *context)
+{
+       struct pipe_context     *pipe;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* Frame buffer set in vlRender*Macroblock() */
+       /* Shaders, samplers, textures, VBs, VB elements set in vlRender*Macroblock() */
+       pipe->set_viewport_state(pipe, &context->states.mc.viewport);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->states.mc.vs_const_buf);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->states.mc.fs_const_buf);
+       
+       return 0;
+}
+
+int vlEndRender(struct VL_CONTEXT *context)
+{
+       struct pipe_context *pipe;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       pipe->set_framebuffer_state(pipe, &context->states.csc.framebuffer);
+       pipe->set_viewport_state(pipe, &context->states.csc.viewport);
+       pipe->bind_sampler_states(pipe, 1, (void**)&context->states.csc.sampler);
+       /* Source texture set in vlPutSurface() */
+       pipe->bind_vs_state(pipe, context->states.csc.vertex_shader);
+       pipe->bind_fs_state(pipe, context->states.csc.fragment_shader);
+       pipe->set_vertex_buffers(pipe, 2, context->states.csc.vertex_bufs);
+       pipe->set_vertex_elements(pipe, 2, context->states.csc.vertex_buf_elems);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->states.csc.fs_const_buf);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.h b/src/gallium/state_trackers/g3dvl/vl_context.h
new file mode 100644 (file)
index 0000000..0aeba18
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef vl_context_h
+#define vl_context_h
+
+#include <X11/Xlib.h>
+#include <pipe/p_state.h>
+#include "vl_types.h"
+
+struct pipe_context;
+
+struct VL_CONTEXT
+{
+       Display                 *display;
+       struct pipe_context     *pipe;
+       unsigned int            video_width;
+       unsigned int            video_height;
+       enum VL_FORMAT          video_format;
+       
+       struct
+       {
+               struct
+               {
+                       struct pipe_rasterizer_state            *raster;
+                       struct pipe_depth_stencil_alpha_state   *dsa;
+                       struct pipe_blend_state                 *blend;
+               } common;
+               
+               struct
+               {
+               } idct;
+               
+               struct
+               {
+                       struct pipe_viewport_state              viewport;
+                       struct pipe_framebuffer_state           render_target;
+                       struct pipe_sampler_state               *samplers[5];
+                       struct pipe_texture                     *textures[5];
+                       struct pipe_shader_state                *i_vs, *p_vs, *b_vs;
+                       struct pipe_shader_state                *i_fs, *p_fs, *b_fs;
+                       struct pipe_vertex_buffer               vertex_bufs[6];
+                       struct pipe_vertex_element              vertex_buf_elems[6];
+                       struct pipe_constant_buffer             vs_const_buf, fs_const_buf;
+               } mc;
+               
+               struct
+               {
+                       struct pipe_viewport_state              viewport;
+                       struct pipe_framebuffer_state           framebuffer;
+                       struct pipe_sampler_state               *sampler;
+                       struct pipe_shader_state                *vertex_shader, *fragment_shader;
+                       struct pipe_vertex_buffer               vertex_bufs[2];
+                       struct pipe_vertex_element              vertex_buf_elems[2];
+                       struct pipe_constant_buffer             fs_const_buf;
+               } csc;
+       } states;
+};
+
+int vlCreateContext
+(
+       Display *display,
+       struct pipe_context *pipe,
+       unsigned int video_width,
+       unsigned int video_height,
+       enum VL_FORMAT video_format,
+       struct VL_CONTEXT **context
+);
+
+int vlDestroyContext(struct VL_CONTEXT *context);
+
+int vlBeginRender(struct VL_CONTEXT *context);
+int vlEndRender(struct VL_CONTEXT *context);
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_data.c b/src/gallium/state_trackers/g3dvl/vl_data.c
new file mode 100644 (file)
index 0000000..c041632
--- /dev/null
@@ -0,0 +1,188 @@
+#include "vl_data.h"
+
+/*
+ * Represents 8 triangles (4 quads, 1 per block) in noormalized coords
+ * that render a macroblock.
+ * Need to be scaled to cover mbW*mbH macroblock pixels and translated into
+ * position on target surface.
+ */
+const struct VL_VERTEX2F vl_mb_vertex_positions[24] =
+{
+       {0.0f, 0.0f}, {0.0f, 0.5f}, {0.5f, 0.0f},
+       {0.5f, 0.0f}, {0.0f, 0.5f}, {0.5f, 0.5f},
+       
+       {0.5f, 0.0f}, {0.5f, 0.5f}, {1.0f, 0.0f},
+       {1.0f, 0.0f}, {0.5f, 0.5f}, {1.0f, 0.5f},
+       
+       {0.0f, 0.5f}, {0.0f, 1.0f}, {0.5f, 0.5f},
+       {0.5f, 0.5f}, {0.0f, 1.0f}, {0.5f, 1.0f},
+       
+       {0.5f, 0.5f}, {0.5f, 1.0f}, {1.0f, 0.5f},
+       {1.0f, 0.5f}, {0.5f, 1.0f}, {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above for rendering 4 luma blocks arranged
+ * in a bW*(bH*4) texture. First luma block located at 0,0->bW,bH; second at
+ * 0,bH->bW,2bH; third at 0,2bH->bW,3bH; fourth at 0,3bH->bW,4bH.
+ */
+const struct VL_TEXCOORD2F vl_luma_texcoords[24] =
+{
+       {0.0f, 0.0f}, {0.0f, 0.25f}, {1.0f, 0.0f},
+       {1.0f, 0.0f}, {0.0f, 0.25f}, {1.0f, 0.25f},
+       
+       {0.0f, 0.25f}, {0.0f, 0.5f}, {1.0f, 0.25f},
+       {1.0f, 0.25f}, {0.0f, 0.5f}, {1.0f, 0.5f},
+       
+       {0.0f, 0.5f}, {0.0f, 0.75f}, {1.0f, 0.5f},
+       {1.0f, 0.5f}, {0.0f, 0.75f}, {1.0f, 0.75f},
+       
+       {0.0f, 0.75f}, {0.0f, 1.0f}, {1.0f, 0.75f},
+       {1.0f, 0.75f}, {0.0f, 1.0f}, {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above for rendering 1 chroma block.
+ * Straight forward 0,0->1,1 mapping so we can reuse the MB pos vectors.
+ */
+const struct VL_TEXCOORD2F *vl_chroma_420_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions;
+
+/*
+ * Represents texcoords for the above for rendering 2 chroma blocks arranged
+ * in a bW*(bH*2) texture. First chroma block located at 0,0->bW,bH; second at
+ * 0,bH->bW,2bH. We can render this with 0,0->1,1 mapping.
+ * Straight forward 0,0->1,1 mapping so we can reuse MB pos vectors.
+ */
+const struct VL_TEXCOORD2F *vl_chroma_422_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions;
+
+/*
+ * Represents texcoords for the above for rendering 4 chroma blocks.
+ * Same case as 4 luma blocks.
+ */
+const struct VL_TEXCOORD2F *vl_chroma_444_texcoords = vl_luma_texcoords;
+
+/*
+ * Represents texcoords for the above for rendering a predicted macroblock.
+ * Straight forward 0,0->1,1 mapping so we can reuse MB pos vectors.
+ * Texcoords need to be translated to cover source macroblock on the
+ * past/future surface.
+ */
+ const struct VL_TEXCOORD2F *vl_ref_surface_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions;
+
+/*
+ * Represents 2 triangles in a strip in normalized coords.
+ * Used to render the surface onto the frame buffer.
+ */
+const struct VL_VERTEX2F vl_surface_vertex_positions[4] =
+{
+       {0.0f, 0.0f},
+       {0.0f, 1.0f},
+       {1.0f, 0.0f},
+       {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above. We can use the position values directly.
+ */
+const struct VL_TEXCOORD2F *vl_surface_texcoords = (const struct VL_TEXCOORD2F*)vl_surface_vertex_positions;
+
+/*
+ * Used when rendering P and B macroblocks, multiplier is applied to the A channel,
+ * which is then added to the L channel, then the bias is subtracted from that to
+ * get back the differential. The differential is then added to the samples from the
+ * reference surface(s).
+ */
+const struct VL_MC_FS_CONSTS vl_mc_fs_consts =
+{
+       {256.0f, 256.0f, 256.0f, 0.0f},
+       {256.0f / 255.0f, 256.0f / 255.0f, 256.0f / 255.0f, 0.0f}
+};
+
+/*
+ * Identity color conversion constants, for debugging
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_identity =
+{
+       {
+               0.0f, 0.0f, 0.0f, 0.0f
+       },
+       {
+               1.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 1.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 1.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601 =
+{
+       {
+               0.0f,           0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.0f,           0.0f,           1.371f,         0.0f,
+               1.0f,           -0.336f,        -0.698f,        0.0f,
+               1.0f,           1.732f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601_full =
+{
+       {
+               0.062745098f,   0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.164f,         0.0f,           1.596f,         0.0f,
+               1.164f,         -0.391f,        -0.813f,        0.0f,
+               1.164f,         2.018f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709 =
+{
+       {
+               0.0f,           0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.0f,           0.0f,           1.540f,         0.0f,
+               1.0f,           -0.183f,        -0.459f,        0.0f,
+               1.0f,           1.816f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709_full =
+{
+       {
+               0.062745098f,   0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.164f,         0.0f,           1.793f,         0.0f,
+               1.164f,         -0.213f,        -0.534f,        0.0f,
+               1.164f,         2.115f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_data.h b/src/gallium/state_trackers/g3dvl/vl_data.h
new file mode 100644 (file)
index 0000000..67a0a74
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef vl_data_h
+#define vl_data_h
+
+#include "vl_types.h"
+
+extern const struct VL_VERTEX2F vl_mb_vertex_positions[24];
+extern const struct VL_TEXCOORD2F vl_luma_texcoords[24];
+extern const struct VL_TEXCOORD2F *vl_chroma_420_texcoords;
+extern const struct VL_TEXCOORD2F *vl_chroma_422_texcoords;
+extern const struct VL_TEXCOORD2F *vl_chroma_444_texcoords;
+extern const struct VL_TEXCOORD2F *vl_ref_surface_texcoords;
+
+extern const struct VL_VERTEX2F vl_surface_vertex_positions[4];
+extern const struct VL_TEXCOORD2F *vl_surface_texcoords;
+
+extern const struct VL_MC_FS_CONSTS vl_mc_fs_consts;
+
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_identity;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601_full;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709_full;
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_defs.h b/src/gallium/state_trackers/g3dvl/vl_defs.h
new file mode 100644 (file)
index 0000000..e668a7a
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef vl_defs_h
+#define vl_defs_h
+
+#define VL_BLOCK_WIDTH         8
+#define VL_BLOCK_HEIGHT                8
+#define VL_BLOCK_SIZE          (VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT)
+#define VL_MACROBLOCK_WIDTH    16
+#define VL_MACROBLOCK_HEIGHT   16
+#define VL_MACROBLOCK_SIZE     (VL_MACROBLOCK_WIDTH * VL_MACROBLOCK_HEIGHT)
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c
new file mode 100644 (file)
index 0000000..e58e434
--- /dev/null
@@ -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;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h
new file mode 100644 (file)
index 0000000..9f56b77
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef vl_surface_h
+#define vl_surface_h
+
+#include <X11/Xlib.h>
+#include "vl_types.h"
+
+struct pipe_texture;
+
+struct VL_SURFACE
+{
+       struct VL_CONTEXT       *context;
+       unsigned int            width;
+       unsigned int            height;
+       enum VL_FORMAT          format;
+       struct pipe_texture     *texture;
+};
+
+int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface);
+
+int vlDestroySurface(struct VL_SURFACE *surface);
+
+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
+);
+
+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
+);
+
+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
+);
+
+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
+);
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_types.h b/src/gallium/state_trackers/g3dvl/vl_types.h
new file mode 100644 (file)
index 0000000..7040b74
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef vl_types_h
+#define vl_types_h
+
+enum VL_FORMAT
+{
+       VL_FORMAT_YCBCR_420,
+       VL_FORMAT_YCBCR_422,
+       VL_FORMAT_YCBCR_444
+};
+
+enum VL_PICTURE
+{
+       VL_TOP_FIELD,
+       VL_BOTTOM_FIELD,
+       VL_FRAME_PICTURE
+};
+
+enum VL_FIELD_ORDER
+{
+       VL_FIELD_FIRST,
+       VL_FIELD_SECOND
+};
+
+enum VL_DCT_TYPE
+{
+       VL_DCT_FIELD_CODED,
+       VL_DCT_FRAME_CODED
+};
+
+enum VL_SAMPLE_TYPE
+{
+       VL_FULL_SAMPLE,
+       VL_DIFFERENCE_SAMPLE
+};
+
+enum VL_MC_TYPE
+{
+       VL_FIELD_MC,
+       VL_FRAME_MC
+};
+
+struct VL_VERTEX4F
+{
+       float x, y, z, w;
+};
+
+struct VL_VERTEX2F
+{
+       float x, y;
+};
+
+struct VL_TEXCOORD2F
+{
+       float s, t;
+};
+
+struct VL_MC_VS_CONSTS
+{
+       struct VL_VERTEX4F      scale;
+       struct VL_VERTEX4F      mb_pos_trans;
+       struct VL_VERTEX4F      mb_tc_trans[2];
+};
+
+struct VL_MC_FS_CONSTS
+{
+       struct VL_VERTEX4F      multiplier;
+       struct VL_VERTEX4F      bias;
+};
+
+struct VL_CSC_FS_CONSTS
+{
+       struct VL_VERTEX4F      bias;
+       float                   matrix[16];
+};
+
+struct VL_MOTION_VECTOR
+{
+       struct
+       {
+               int x, y;
+       } top_field, bottom_field;
+};
+
+struct VL_CONTEXT;
+struct VL_SURFACE;
+
+#endif
+
diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.c b/src/gallium/winsys/g3dvl/xsp_winsys.c
new file mode 100644 (file)
index 0000000..eb4c908
--- /dev/null
@@ -0,0 +1,256 @@
+#include "xsp_winsys.h"
+#include <X11/Xutil.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_state.h>
+#include <pipe/p_util.h>
+#include <pipe/p_inlines.h>
+#include <softpipe/sp_winsys.h>
+
+/* pipe_winsys implementation */
+
+struct xsp_pipe_winsys
+{
+       struct pipe_winsys      base;
+       Display                 *display;
+       XImage                  fbimage;
+};
+
+struct xsp_buffer
+{
+       struct pipe_buffer      base;
+       boolean                 is_user_buffer;
+       void                    *data;
+       void                    *mapped_data;
+};
+
+static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size)
+{
+       struct xsp_buffer *buffer;
+       
+       assert(pws);
+       
+       buffer = calloc(1, sizeof(struct xsp_buffer));
+       buffer->base.refcount = 1;
+       buffer->base.alignment = alignment;
+       buffer->base.usage = usage;
+       buffer->base.size = size;
+       buffer->data = align_malloc(size, alignment);
+       
+       return (struct pipe_buffer*)buffer;
+}
+
+static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size)
+{
+       struct xsp_buffer *buffer;
+       
+       assert(pws);
+       
+       buffer = calloc(1, sizeof(struct xsp_buffer));
+       buffer->base.refcount = 1;
+       buffer->base.size = size;
+       buffer->is_user_buffer = TRUE;
+       buffer->data = data;
+       
+       return (struct pipe_buffer*)buffer;
+}
+
+static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags)
+{
+       struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+       
+       assert(pws);
+       assert(buffer);
+       
+       xsp_buf->mapped_data = xsp_buf->data;
+       return xsp_buf->mapped_data;
+}
+
+static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer)
+{
+       struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+       
+       assert(pws);
+       assert(buffer);
+       
+       xsp_buf->mapped_data = NULL;
+}
+
+static void xsp_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buffer)
+{
+       struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+       
+       assert(pws);
+       assert(buffer);
+       
+       if (!xsp_buf->is_user_buffer)
+               align_free(xsp_buf->data);
+       
+       free(xsp_buf);
+}
+
+static struct pipe_surface* xsp_surface_alloc(struct pipe_winsys *pws)
+{
+       struct pipe_surface *surface;
+       
+       assert(pws);
+       
+       surface = calloc(1, sizeof(struct pipe_surface));
+       surface->refcount = 1;
+       surface->winsys = pws;
+       
+       return surface;
+}
+
+static int xsp_surface_alloc_storage
+(
+       struct pipe_winsys *pws,
+       struct pipe_surface *surface,
+       unsigned width,
+       unsigned height,
+       enum pipe_format format,
+       unsigned flags,
+       unsigned tex_usage
+)
+{
+       const unsigned int ALIGNMENT = 1;
+       
+       assert(pws);
+       assert(surface);
+       
+       surface->width = width;
+       surface->height = height;
+       surface->format = format;
+       surface->cpp = pf_get_size(format);
+       surface->pitch = width;
+       surface->usage = flags;
+       surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->pitch * surface->cpp * height);
+       
+       return 0;
+}
+
+static void xsp_surface_release(struct pipe_winsys *pws, struct pipe_surface **surface)
+{
+       struct pipe_surface *s;
+       
+       assert(pws);
+       assert(surface);
+       assert(*surface);
+       
+       s = *surface;
+       
+       s->refcount--;
+       
+       if (s->refcount == 0)
+       {
+               pipe_buffer_reference(pws, &s->buffer, NULL);
+               free(s);
+       }
+       
+       *surface = NULL;
+}
+
+static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
+{      
+       struct xsp_pipe_winsys *xsp_winsys;
+       
+       assert(pws);
+       assert(surface);
+       assert(context_private);
+       
+       xsp_winsys = (struct xsp_pipe_winsys*)pws;
+       
+       xsp_winsys->fbimage.width = surface->width;
+       xsp_winsys->fbimage.height = surface->height;
+       xsp_winsys->fbimage.bytes_per_line = surface->width * (xsp_winsys->fbimage.bits_per_pixel >> 3);
+       xsp_winsys->fbimage.data = pipe_surface_map(surface, 0);
+       
+       XPutImage
+       (
+               xsp_winsys->display,
+               *(Drawable*)context_private,
+               XDefaultGC(xsp_winsys->display, XDefaultScreen(xsp_winsys->display)),
+               &xsp_winsys->fbimage,
+               0,
+               0,
+               0,
+               0,
+               surface->width,
+               surface->height
+       );
+       XFlush(xsp_winsys->display);
+       pipe_surface_unmap(surface);
+}
+
+static const char* xsp_get_name(struct pipe_winsys *pws)
+{
+       assert(pws);
+       return "X11 SoftPipe";
+}
+
+/* softpipe_winsys implementation */
+
+static boolean xsp_is_format_supported(struct softpipe_winsys *spws, enum pipe_format format)
+{
+       assert(spws);
+       
+       /* TODO: Test that 'format' is equal to our output window's format */
+       return TRUE;
+}
+
+/* Show starts here */
+
+struct pipe_context* create_pipe_context(Display *display)
+{
+       struct xsp_pipe_winsys  *xsp_winsys;
+       struct softpipe_winsys  *sp_winsys;
+       struct pipe_screen      *p_screen;
+       struct pipe_context     *p_context;
+       
+       assert(display);
+       
+       xsp_winsys = calloc(1, sizeof(struct xsp_pipe_winsys));
+       xsp_winsys->base.buffer_create = xsp_buffer_create;
+       xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
+       xsp_winsys->base.buffer_map = xsp_buffer_map;
+       xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
+       xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
+       xsp_winsys->base.surface_alloc = xsp_surface_alloc;
+       xsp_winsys->base.surface_alloc_storage = xsp_surface_alloc_storage;
+       xsp_winsys->base.surface_release = xsp_surface_release;
+       xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
+       xsp_winsys->base.get_name = xsp_get_name;
+       xsp_winsys->display = display;
+       
+       {
+               /* XXX: Can't use the returned XImage* directly,
+               since we don't have control over winsys destruction
+               and we wouldn't be able to free it */
+               XImage *template = XCreateImage
+               (
+                       display,
+                       XDefaultVisual(display, XDefaultScreen(display)),
+                       XDefaultDepth(display, XDefaultScreen(display)),
+                       ZPixmap,
+                       0,
+                       NULL,
+                       0,      /* Don't know the width and height until flush_frontbuffer */
+                       0,
+                       32,
+                       0
+               );
+               
+               memcpy(&xsp_winsys->fbimage, template, sizeof(XImage));
+               XInitImage(&xsp_winsys->fbimage);
+               
+               XDestroyImage(template);
+       }
+
+       sp_winsys = calloc(1, sizeof(struct softpipe_winsys));
+       sp_winsys->is_format_supported = xsp_is_format_supported;
+       
+       p_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys);
+       p_context = softpipe_create(p_screen, (struct pipe_winsys*)xsp_winsys, sp_winsys);
+       
+       return p_context;
+}
+
diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.h b/src/gallium/winsys/g3dvl/xsp_winsys.h
new file mode 100644 (file)
index 0000000..47a6ac6
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef xsp_winsys_h
+#define xsp_winsys_h
+
+#include <X11/Xlib.h>
+
+struct pipe_context;
+
+struct pipe_context* create_pipe_context(Display *display);
+
+#endif
+
diff --git a/src/libXvMC/Makefile b/src/libXvMC/Makefile
new file mode 100644 (file)
index 0000000..b2f41e1
--- /dev/null
@@ -0,0 +1,33 @@
+TARGET         = libXvMCg3dvl.so
+SONAME         = libXvMCg3dvl.so.1
+GALLIUMDIR     = ../gallium
+OBJECTS                = block.o surface.o context.o subpicture.o attributes.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+
+CFLAGS += -g -fPIC -Wall -Werror                       \
+          -I${GALLIUMDIR}/state_trackers/g3dvl         \
+          -I${GALLIUMDIR}/winsys/g3dvl                 \
+          -I${GALLIUMDIR}/include                      \
+          -I${GALLIUMDIR}/auxiliary                    \
+          -I${GALLIUMDIR}/drivers
+LDFLAGS        += -L${GALLIUMDIR}/state_trackers/g3dvl         \
+          -L${GALLIUMDIR}/drivers/softpipe             \
+          -L${GALLIUMDIR}/auxiliary/tgsi               \
+          -L${GALLIUMDIR}/auxiliary/draw               \
+          -L${GALLIUMDIR}/auxiliary/translate          \
+          -L${GALLIUMDIR}/auxiliary/cso_cache          \
+          -L${GALLIUMDIR}/auxiliary/util               \
+          -L${GALLIUMDIR}/auxiliary/rtasm
+LIBS   += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+       $(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ $^ ${LIBS}
+
+clean:
+       rm -rf ${OBJECTS} ${TARGET}
+
diff --git a/src/libXvMC/attributes.c b/src/libXvMC/attributes.c
new file mode 100644 (file)
index 0000000..674524b
--- /dev/null
@@ -0,0 +1,20 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+
+XvAttribute* XvMCQueryAttributes(Display *display, XvMCContext *context, int *number)
+{
+       return NULL;
+}
+
+Status XvMCSetAttribute(Display *display, XvMCContext *context, Atom attribute, int value)
+{
+       return BadImplementation;
+}
+
+Status XvMCGetAttribute(Display *display, XvMCContext *context, Atom attribute, int *value)
+{
+       return BadImplementation;
+}
+
diff --git a/src/libXvMC/block.c b/src/libXvMC/block.c
new file mode 100644 (file)
index 0000000..b56348d
--- /dev/null
@@ -0,0 +1,85 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_context.h>
+
+/*
+ * XvMC defines 64 element blocks (8x8 elements).
+ * Elements are 8 bits when they represent color values,
+ * 9 bits when they reprecent DCT coefficients, we
+ * store them in 2 bytes in either case. DCT coefficients
+ * can be signed or unsigned, at our option.
+ */
+#define BLOCK_SIZE (64 * 2)
+
+Status XvMCCreateBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
+{
+       struct vl_context *vl_ctx;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (num_blocks == 0)
+               return BadValue;
+       
+       assert(blocks);
+       
+       vl_ctx = context->privData;
+       assert(display == vl_ctx->display);
+
+       blocks->context_id = context->context_id;
+       blocks->num_blocks = num_blocks;
+       blocks->blocks = malloc(BLOCK_SIZE * num_blocks);
+       /* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
+       blocks->privData = display;
+       
+       return Success;
+}
+
+Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *blocks)
+{      
+       assert(display);
+       assert(blocks);
+       assert(display == blocks->privData);
+       free(blocks->blocks);
+       
+       return Success;
+}
+
+Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
+{
+       struct vl_context *vl_ctx;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (num_blocks == 0)
+               return BadValue;
+       
+       assert(blocks);
+       
+       vl_ctx = context->privData;
+       assert(display == vl_ctx->display);
+       
+       blocks->context_id = context->context_id;
+       blocks->num_blocks = num_blocks;
+       blocks->macro_blocks = malloc(sizeof(XvMCMacroBlock) * num_blocks);
+       /* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
+       blocks->privData = display;
+       
+       return Success;
+}
+
+Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *blocks)
+{      
+       assert(display);
+       assert(blocks);
+       assert(display == blocks->privData);
+       free(blocks->macro_blocks);
+       
+       return Success;
+}
+
diff --git a/src/libXvMC/context.c b/src/libXvMC/context.c
new file mode 100644 (file)
index 0000000..c835a6a
--- /dev/null
@@ -0,0 +1,154 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <vl_context.h>
+#include <xsp_winsys.h>
+
+static Status Validate(Display *display, XvPortID port, int surface_type_id, unsigned int width, unsigned int height, int flags, int *chroma_format)
+{
+       unsigned int    found_port = 0;
+       unsigned int    found_surface = 0;
+       XvAdaptorInfo   *adaptor_info;
+       unsigned int    num_adaptors;
+       int             num_types;
+       unsigned int    max_width, max_height;
+       Status          ret;
+       unsigned int    i, j, k;
+       
+       assert(display && chroma_format);
+       
+       ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info);
+       if (ret != Success)
+               return ret;
+       
+       /* Scan through all adaptors looking for this port and surface */
+       for (i = 0; i < num_adaptors && !found_port; ++i)
+       {
+               /* Scan through all ports of this adaptor looking for our port */
+               for (j = 0; j < adaptor_info[i].num_ports && !found_port; ++j)
+               {
+                       /* If this is our port, scan through all its surfaces looking for our surface */
+                       if (adaptor_info[i].base_id + j == port)
+                       {
+                               XvMCSurfaceInfo *surface_info;
+                               
+                               found_port = 1;
+                               surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+                               
+                               if (surface_info)
+                               {
+                                       for (k = 0; k < num_types && !found_surface; ++k)
+                                       {
+                                               if (surface_info[k].surface_type_id == surface_type_id)
+                                               {
+                                                       found_surface = 1;
+                                                       max_width = surface_info[k].max_width;
+                                                       max_height = surface_info[k].max_height;
+                                                       *chroma_format = surface_info[k].chroma_format;
+                                               }
+                                       }
+                                       
+                                       XFree(surface_info);
+                               }
+                               else
+                               {
+                                       XvFreeAdaptorInfo(adaptor_info);
+                                       return BadAlloc;
+                               }
+                       }
+               }
+       }
+       
+       XvFreeAdaptorInfo(adaptor_info);
+       
+       if (!found_port)
+               return XvBadPort;
+       if (!found_surface)
+               return BadMatch;
+       if (width > max_width || height > max_height)
+               return BadValue;
+       if (flags != XVMC_DIRECT && flags != 0)
+               return BadValue;
+       
+       return Success;
+}
+
+static enum VL_FORMAT FormatToVL(int xvmc_format)
+{
+       enum VL_FORMAT vl_format;
+       
+       switch (xvmc_format)
+       {
+               case XVMC_CHROMA_FORMAT_420:
+               {
+                       vl_format = VL_FORMAT_YCBCR_420;
+                       break;
+               }
+               case XVMC_CHROMA_FORMAT_422:
+               {
+                       vl_format = VL_FORMAT_YCBCR_422;
+                       break;
+               }
+               case XVMC_CHROMA_FORMAT_444:
+               {
+                       vl_format = VL_FORMAT_YCBCR_444;
+                       break;
+               }
+               default:
+                       assert(0);
+       }
+       
+       return vl_format;
+}
+
+Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
+{
+       int                     chroma_format;
+       Status                  ret;
+       struct VL_CONTEXT       *vl_ctx;
+       struct pipe_context     *pipe;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       
+       ret = Validate(display, port, surface_type_id, width, height, flags, &chroma_format);
+       if (ret != Success)
+               return ret;
+       
+       pipe = create_pipe_context(display);
+       
+       assert(pipe);
+       
+       vlCreateContext(display, pipe, width, height, FormatToVL(chroma_format), &vl_ctx);
+       
+       context->context_id = XAllocID(display);
+       context->surface_type_id = surface_type_id;
+       context->width = width;
+       context->height = height;
+       context->flags = flags;
+       context->port = port;
+       context->privData = vl_ctx;
+       
+       return Success;
+}
+
+Status XvMCDestroyContext(Display *display, XvMCContext *context)
+{
+       struct VL_CONTEXT *vl_ctx;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       
+       vl_ctx = context->privData;
+       
+       assert(display == vl_ctx->display);
+       
+       vlDestroyContext(vl_ctx);
+       
+       return Success;
+}
+
diff --git a/src/libXvMC/subpicture.c b/src/libXvMC/subpicture.c
new file mode 100644 (file)
index 0000000..38d9343
--- /dev/null
@@ -0,0 +1,110 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+
+Status XvMCCreateSubpicture
+(
+       Display *display,
+       XvMCContext *context,
+       XvMCSubpicture *subpicture,
+       unsigned short width,
+       unsigned short height,
+       int xvimage_id
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCClearSubpicture
+(
+       Display *display,
+       XvMCSubpicture *subpicture,
+       short x,
+       short y,
+       unsigned short width,
+       unsigned short height,
+       unsigned int color
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCCompositeSubpicture
+(
+       Display *display,
+       XvMCSubpicture *subpicture,
+       XvImage *image,
+       short srcx,
+       short srcy,
+       unsigned short width,
+       unsigned short height,
+       short dstx,
+       short dsty
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+       return BadImplementation;
+}
+
+Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, unsigned char *palette)
+{
+       return BadImplementation;
+}
+
+Status XvMCBlendSubpicture
+(
+       Display *display,
+       XvMCSurface *target_surface,
+       XvMCSubpicture *subpicture,
+       short subx,
+       short suby,
+       unsigned short subw,
+       unsigned short subh,
+       short surfx,
+       short surfy,
+       unsigned short surfw,
+       unsigned short surfh
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCBlendSubpicture2
+(
+       Display *display,
+       XvMCSurface *source_surface,
+       XvMCSurface *target_surface,
+       XvMCSubpicture *subpicture,
+       short subx,
+       short suby,
+       unsigned short subw,
+       unsigned short subh,
+       short surfx,
+       short surfy,
+       unsigned short surfw,
+       unsigned short surfh
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+       return BadImplementation;
+}
+
+Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+       return BadImplementation;
+}
+
+Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, int *status)
+{
+       return BadImplementation;
+}
+
diff --git a/src/libXvMC/surface.c b/src/libXvMC/surface.c
new file mode 100644 (file)
index 0000000..e4602d8
--- /dev/null
@@ -0,0 +1,373 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+
+static enum VL_PICTURE PictureToVL(int xvmc_pic)
+{
+       enum VL_PICTURE vl_pic;
+       
+       switch (xvmc_pic)
+       {
+               case XVMC_TOP_FIELD:
+               {
+                       vl_pic = VL_TOP_FIELD;
+                       break;
+               }
+               case XVMC_BOTTOM_FIELD:
+               {
+                       vl_pic = VL_BOTTOM_FIELD;
+                       break;
+               }
+               case XVMC_FRAME_PICTURE:
+               {
+                       vl_pic = VL_FRAME_PICTURE;
+                       break;
+               }
+               default:
+                       assert(0);
+       }
+       
+       return vl_pic;
+}
+
+Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (!surface)
+               return XvMCBadSurface;
+       
+       vl_ctx = context->privData;
+       
+       assert(display == vl_ctx->display);
+       
+       vlCreateSurface(vl_ctx, &vl_sfc);
+       
+       surface->surface_id = XAllocID(display);
+       surface->context_id = context->context_id;
+       surface->surface_type_id = context->surface_type_id;
+       surface->width = context->width;
+       surface->height = context->height;
+       surface->privData = vl_sfc;
+       
+       return Success;
+}
+
+Status XvMCRenderSurface
+(
+       Display *display,
+       XvMCContext *context,
+       unsigned int picture_structure,
+       XvMCSurface *target_surface,
+       XvMCSurface *past_surface,
+       XvMCSurface *future_surface,
+       unsigned int flags,
+       unsigned int num_macroblocks,
+       unsigned int first_macroblock,
+       XvMCMacroBlockArray *macroblocks,
+       XvMCBlockArray *blocks
+)
+{
+       struct VL_CONTEXT       *vl_ctx;
+       struct VL_SURFACE       *target_vl_surface;
+       struct VL_SURFACE       *past_vl_surface;
+       struct VL_SURFACE       *future_vl_surface;
+       unsigned int            i;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (!target_surface)
+               return XvMCBadSurface;
+       
+       if
+       (
+               picture_structure != XVMC_TOP_FIELD &&
+               picture_structure != XVMC_BOTTOM_FIELD &&
+               picture_structure != XVMC_FRAME_PICTURE
+       )
+               return BadValue;
+       if (future_surface && !past_surface)
+               return BadMatch;
+       
+       vl_ctx = context->privData;
+       
+       assert(display == vl_ctx->display);
+       
+       target_vl_surface = target_surface->privData;
+       past_vl_surface = past_surface ? past_surface->privData : NULL;
+       future_vl_surface = future_surface ? future_surface->privData : NULL;
+       
+       assert(vl_ctx == target_vl_surface->context);
+       assert(!past_vl_surface || vl_ctx == past_vl_surface->context);
+       assert(!future_vl_surface || vl_ctx == future_vl_surface->context);
+       
+       assert(macroblocks);
+       assert(blocks);
+       
+       assert(macroblocks->context_id == context->context_id);
+       assert(blocks->context_id == context->context_id);
+       
+       assert(flags == 0 || flags == XVMC_SECOND_FIELD);
+       
+       for (i = first_macroblock; i < first_macroblock + num_macroblocks; ++i)
+               if (macroblocks->macro_blocks[i].macroblock_type & XVMC_MB_TYPE_INTRA)
+                       vlRenderIMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               target_vl_surface
+                       );
+               else if
+               (
+                       (macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+                       == XVMC_MB_TYPE_MOTION_FORWARD
+               )
+               {
+                       struct VL_MOTION_VECTOR motion_vector =
+                       {
+                               {
+                                       macroblocks->macro_blocks[i].PMV[0][0][0],
+                                       macroblocks->macro_blocks[i].PMV[0][0][1],
+                               },
+                               {
+                                       macroblocks->macro_blocks[i].PMV[1][0][0],
+                                       macroblocks->macro_blocks[i].PMV[1][0][1],
+                               }
+                       };
+                                               
+                       vlRenderPMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               macroblocks->macro_blocks[i].motion_type == XVMC_PREDICTION_FRAME ? VL_FIELD_MC : VL_FRAME_MC,
+                               &motion_vector,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               past_vl_surface,
+                               target_vl_surface
+                       );
+               }
+               else if
+               (
+                       (macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+                       == XVMC_MB_TYPE_MOTION_BACKWARD
+               )
+               {
+                       struct VL_MOTION_VECTOR motion_vector =
+                       {
+                               {
+                                       macroblocks->macro_blocks[i].PMV[0][1][0],
+                                       macroblocks->macro_blocks[i].PMV[0][1][1],
+                               },
+                               {
+                                       macroblocks->macro_blocks[i].PMV[1][1][0],
+                                       macroblocks->macro_blocks[i].PMV[1][1][1],
+                               }
+                       };
+                       
+                       vlRenderPMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               macroblocks->macro_blocks[i].motion_type == XVMC_PREDICTION_FRAME ? VL_FIELD_MC : VL_FRAME_MC,
+                               &motion_vector,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               future_vl_surface,
+                               target_vl_surface
+                       );
+               }
+               else if
+               (
+                       (macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+                       == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)
+               )
+               {
+                       struct VL_MOTION_VECTOR motion_vector[2] =
+                       {
+                               {
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[0][0][0],
+                                               macroblocks->macro_blocks[i].PMV[0][0][1],
+                                       },
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[1][0][0],
+                                               macroblocks->macro_blocks[i].PMV[1][0][1],
+                                       }
+                               },
+                               {
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[0][1][0],
+                                               macroblocks->macro_blocks[i].PMV[0][1][1],
+                                       },
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[1][1][0],
+                                               macroblocks->macro_blocks[i].PMV[1][1][1],
+                                       }
+                               }
+                       };
+                       
+                       vlRenderBMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               macroblocks->macro_blocks[i].motion_type == XVMC_PREDICTION_FRAME ? VL_FIELD_MC : VL_FRAME_MC,
+                               motion_vector,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               past_vl_surface,
+                               future_vl_surface,
+                               target_vl_surface
+                       );
+               }
+               else
+                       fprintf(stderr, "Unrecognized macroblock\n");
+       
+       return Success;
+}
+
+Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
+{
+       /* TODO: Check display & surface match */
+       return BadImplementation;
+}
+
+Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
+{
+       /* TODO: Check display & surface match */
+       return BadImplementation;
+}
+
+Status XvMCPutSurface
+(
+       Display *display,
+       XvMCSurface *surface,
+       Drawable drawable,
+       short srcx,
+       short srcy,
+       unsigned short srcw,
+       unsigned short srch,
+       short destx,
+       short desty,
+       unsigned short destw,
+       unsigned short desth,
+       int flags
+)
+{
+       Window                  root;
+       int                     x, y;
+       unsigned int            width, height;
+       unsigned int            border_width;
+       unsigned int            depth;
+       struct VL_SURFACE       *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+               
+       if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+               return BadDrawable;
+       
+       assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
+       
+       /* TODO: Correct for negative srcx,srcy & destx,desty by clipping */
+       
+       assert(srcx + srcw - 1 < surface->width);
+       assert(srcy + srch - 1 < surface->height);
+       assert(destx + destw - 1 < width);
+       assert(desty + desth - 1 < height);
+       
+       vl_sfc = surface->privData;
+       
+       vlPutSurface(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, PictureToVL(flags));
+       
+       return Success;
+}
+
+Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+               
+       assert(status);
+       
+       vl_sfc = surface->privData;
+       vl_ctx = vl_sfc->context;
+       
+       assert(display == vl_ctx->display);
+       
+       /* TODO */
+       *status = 0;
+       
+       return BadImplementation;
+}
+
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+       
+       vl_sfc = surface->privData;
+       vl_ctx = vl_sfc->context;
+       
+       assert(display == vl_ctx->display);
+       
+       vlDestroySurface(vl_sfc);
+       
+       return Success;
+}
+
+Status XvMCHideSurface(Display *display, XvMCSurface *surface)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+       
+       vl_sfc = surface->privData;
+       vl_ctx = vl_sfc->context;
+       
+       assert(display == vl_ctx->display);
+       
+       /* No op, only for overlaid rendering */
+       
+       return Success;
+}
+
diff --git a/src/libXvMC/tests/.gitignore b/src/libXvMC/tests/.gitignore
new file mode 100644 (file)
index 0000000..eb1ef8a
--- /dev/null
@@ -0,0 +1,5 @@
+test_context
+test_surface
+test_blocks
+test_rendering
+
diff --git a/src/libXvMC/tests/Makefile b/src/libXvMC/tests/Makefile
new file mode 100644 (file)
index 0000000..2cbc97e
--- /dev/null
@@ -0,0 +1,25 @@
+CFLAGS += -g -Wall -Werror
+LDFLAGS        +=
+LIBS   += -lXvMCW -lXvMC -lXv
+
+#############################################
+
+.PHONY = all clean
+
+all: test_context test_surface test_blocks test_rendering
+
+test_context: test_context.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_surface: test_surface.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_blocks: test_blocks.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_rendering: test_rendering.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+clean:
+       rm -rf *.o test_context test_surface test_blocks test_rendering
+
diff --git a/src/libXvMC/tests/test_blocks.c b/src/libXvMC/tests/test_blocks.c
new file mode 100644 (file)
index 0000000..0b895ee
--- /dev/null
@@ -0,0 +1,95 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      min_required_blocks = 1, min_required_macroblocks = 1;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          blocks = {0};
+       XvMCMacroBlockArray     macroblocks = {0};
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       
+       /* Test NULL context */
+       assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
+       /* Test 0 blocks */
+       assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
+       /* Test too many blocks */
+       /*assert(XvMCCreateBlocks(display, &context, 16384, &blocks) == BadAlloc);*/
+       
+       /* Note: No XvMCBadBlock(s) error in spec */
+       
+       /* Test valid params */
+       assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
+       /* Test context id assigned and correct */
+       assert(blocks.context_id == context.context_id);
+       /* Test number of blocks assigned and correct */
+       assert(blocks.num_blocks == min_required_blocks);
+       /* Test block pointer valid */
+       assert(blocks.blocks != NULL);
+       /* Test NULL context */
+       assert(XvMCCreateMacroBlocks(display, NULL, 1, &macroblocks) == XvMCBadContext);
+       /* Test 0 macroblocks */
+       assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
+       /* Test too many macroblocks */
+       /*assert(XvMCCreateMacroBlocks(display, &context, 16384, &macroblocks) == BadAlloc);*/
+
+       /* Note: No XvMCBadMacroBlock(s) error in spec */
+
+       /* Test valid params */
+       assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == Success);
+       /* Test context id assigned and correct */
+       assert(macroblocks.context_id == context.context_id);
+       /* Test macroblock pointer valid */
+       assert(macroblocks.macro_blocks != NULL);
+       /* Test valid params */
+       assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+       /* Test valid params */
+       assert(XvMCDestroyBlocks(display, &blocks) == Success);
+       
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/test_context.c b/src/libXvMC/tests/test_context.c
new file mode 100644 (file)
index 0000000..22afb7a
--- /dev/null
@@ -0,0 +1,94 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context = {0};
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       /* Note: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
+       /* Note: Nvidia binary driver segfaults on NULL context, halts with debug output on bad port */
+       
+       /* Test NULL context */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
+       /* Test invalid port */
+       assert(XvMCCreateContext(display, port_num + 1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
+       /* Test invalid surface */
+       assert(XvMCCreateContext(display, port_num, surface_type_id + 1, width, height, XVMC_DIRECT, &context) == BadMatch);
+       /* Test invalid flags */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue);
+       /* Test huge width */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue);
+       /* Test huge height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue);
+       /* Test huge width & height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue);
+       /* Test valid params */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       /* Test context id assigned */
+       assert(context.context_id != 0);
+       /* Test surface type id assigned and correct */
+       assert(context.surface_type_id == surface_type_id);
+       /* Test width & height assigned and correct */
+       assert(context.width == width && context.height == height);
+       /* Test port assigned and correct */
+       assert(context.port == port_num);
+       /* Test flags assigned and correct */
+       assert(context.flags == XVMC_DIRECT);
+       /* Test NULL context */
+       assert(XvMCDestroyContext(display, NULL) == XvMCBadContext);
+       /* Test valid params */
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid width */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success);
+       assert(context.width >= width + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success);
+       assert(context.height >= height + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid width & height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success);
+       assert(context.width >= width + 1 && context.height >= height + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/test_rendering.c b/src/libXvMC/tests/test_rendering.c
new file mode 100644 (file)
index 0000000..1914b1f
--- /dev/null
@@ -0,0 +1,153 @@
+#include <assert.h>
+#include <stdio.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 32, height = 32;
+       const unsigned int      mwidth = width / 16, mheight = height / 16;
+       const unsigned int      num_macroblocks = mwidth * mheight;
+       const unsigned int      num_blocks = num_macroblocks * 6;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          blocks;
+       XvMCMacroBlockArray     macroblocks;
+       unsigned int            b, x, y;
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, colorkey);
+       framebuffer = XCreatePixmap(display, root, width, height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       assert(XvMCCreateBlocks(display, &context, num_blocks, &blocks) == Success);
+       assert(XvMCCreateMacroBlocks(display, &context, num_macroblocks, &macroblocks) == Success);
+       
+       for (b = 0; b < 6; ++b)
+       {
+               for (y = 0; y < 8; ++y)
+               {
+                       for (x = 0; x < 8; ++x)
+                       {
+                               blocks.blocks[b * 64 + y * 8 + x] = 0xFFFF;
+                       }
+               }
+       }
+       
+       for (y = 0; y < mheight; ++y)
+       {
+               for (x = 0; x < mwidth; ++x)
+               {
+                       macroblocks.macro_blocks[y * mwidth + x].x = x;
+                       macroblocks.macro_blocks[y * mwidth + x].y = y;
+                       macroblocks.macro_blocks[y * mwidth + x].index = (y * mwidth + x) * 6;
+                       macroblocks.macro_blocks[y * mwidth + x].macroblock_type = XVMC_MB_TYPE_INTRA;
+                       macroblocks.macro_blocks[y * mwidth + x].coded_block_pattern = 0x3F;
+                       macroblocks.macro_blocks[y * mwidth + x].dct_type = XVMC_DCT_TYPE_FRAME;
+               }
+       }
+       
+       /* Test NULL context */
+       assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, 1, 0, &macroblocks, &blocks) == XvMCBadContext);
+       /* Test NULL surface */
+       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, 1, 0, &macroblocks, &blocks) == XvMCBadSurface);
+       /* Test bad picture structure */
+       assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, 1, 0, &macroblocks, &blocks) == BadValue);
+       /* Test valid params */
+       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, num_macroblocks, 0, &macroblocks, &blocks) == Success);
+       
+       /* Test NULL surface */
+       assert(XvMCPutSurface(display, NULL, window, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
+       /* Test bad window */
+       /* X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
+       /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
+       /* Test valid params */
+       assert(XvMCPutSurface(display, &surface, framebuffer, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == Success);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       width,
+                                       height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       assert(XvMCDestroyBlocks(display, &blocks) == Success);
+       assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+       assert(XvMCDestroySurface(display, &surface) == Success);       
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XFreePixmap(display, framebuffer);
+       XvUngrabPort(display, port_num, CurrentTime);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/test_surface.c b/src/libXvMC/tests/test_surface.c
new file mode 100644 (file)
index 0000000..25ebdcc
--- /dev/null
@@ -0,0 +1,72 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface = {0};
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       
+       /* Test NULL context */
+       assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext);
+       /* Test NULL surface */
+       assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface);
+       /* Test valid params */
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       /* Test surface id assigned */
+       assert(surface.surface_id != 0);
+       /* Test context id assigned and correct */
+       assert(surface.context_id == context.context_id);
+       /* Test surface type id assigned and correct */
+       assert(surface.surface_type_id == surface_type_id);
+       /* Test width & height assigned and correct */
+       assert(surface.width == width && surface.height == height);
+       /* Test valid params */
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       /* Test NULL surface */
+       assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface);
+       
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/testlib.c b/src/libXvMC/tests/testlib.c
new file mode 100644 (file)
index 0000000..8672aa9
--- /dev/null
@@ -0,0 +1,87 @@
+#include "testlib.h"
+#include <stdio.h>
+
+/*
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line)
+{
+       fputs(doc_string, stderr);
+       if (!pred)
+               fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line);
+       else
+               fputs(" PASS!\n", stderr);
+}
+*/
+
+int GetPort
+(
+       Display *display,
+       unsigned int width,
+       unsigned int height,
+       unsigned int chroma_format,
+       const unsigned int *mc_types,
+       unsigned int num_mc_types,
+       XvPortID *port_id,
+       int *surface_type_id,
+       unsigned int *is_overlay,
+       unsigned int *intra_unsigned
+)
+{
+       unsigned int    found_port = 0;
+       XvAdaptorInfo   *adaptor_info;
+       unsigned int    num_adaptors;
+       int             num_types;
+       int             ev_base, err_base;
+       unsigned int    i, j, k, l;
+       
+       if (!XvMCQueryExtension(display, &ev_base, &err_base))
+               return 0;
+       if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success)
+               return 0;
+       
+       for (i = 0; i < num_adaptors && !found_port; ++i)
+       {
+               if (adaptor_info[i].type & XvImageMask)
+               {
+                       XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+                       
+                       if (surface_info)
+                       {
+                               for (j = 0; j < num_types && !found_port; ++j)
+                               {
+                                       if
+                                       (
+                                               surface_info[j].chroma_format == chroma_format &&
+                                               surface_info[j].max_width >= width &&
+                                               surface_info[j].max_height >= height
+                                       )
+                                       {
+                                               for (k = 0; k < num_mc_types && !found_port; ++k)
+                                               {
+                                                       if (surface_info[j].mc_type == mc_types[k])
+                                                       {
+                                                               for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l)
+                                                               {
+                                                                       if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success)
+                                                                       {
+                                                                               *port_id = adaptor_info[i].base_id + l;
+                                                                               *surface_type_id = surface_info[j].surface_type_id;
+                                                                               *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE;
+                                                                               *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED;
+                                                                               found_port = 1;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               
+                               XFree(surface_info);
+                       }
+               }
+       }
+       
+       XvFreeAdaptorInfo(adaptor_info);
+       
+       return found_port;
+}
+
diff --git a/src/libXvMC/tests/testlib.h b/src/libXvMC/tests/testlib.h
new file mode 100644 (file)
index 0000000..c738458
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef testlib_h
+#define testlib_h
+
+/*
+#define TEST(pred, doc)        test(pred, #pred, doc, __FILE__, __LINE__)
+
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line);
+*/
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+/*
+ * display: IN                 A valid X display
+ * width, height: IN           Surface size that the port must display
+ * chroma_format: IN           Chroma format that the port must display
+ * mc_types, num_mc_types: IN  List of MC types that the port must support, first port that matches the first mc_type will be returned
+ * port_id: OUT                        Your port's ID
+ * surface_type_id: OUT                Your port's surface ID
+ * is_overlay: OUT             If 1, port uses overlay surfaces, you need to set a colorkey
+ * intra_unsigned: OUT         If 1, port uses unsigned values for intra-coded blocks
+ */
+int GetPort
+(
+       Display *display,
+       unsigned int width,
+       unsigned int height,
+       unsigned int chroma_format,
+       const unsigned int *mc_types,
+       unsigned int num_mc_types,
+       XvPortID *port_id,
+       int *surface_type_id,
+       unsigned int *is_overlay,
+       unsigned int *intra_unsigned
+);
+
+#endif
+