diff options
author | Younes Manton <[email protected]> | 2008-06-08 03:04:14 -0400 |
---|---|---|
committer | Younes Manton <[email protected]> | 2008-06-08 03:04:14 -0400 |
commit | c11a7ec821d41b91a3825c5abfb4687c98b5bf98 (patch) | |
tree | cca76bb6d30d3da0b6bd49a9dd1c61ea6feb3cf2 /src/gallium | |
parent | 996b549fdbfe772ee56a51858e81e93bccaae5c5 (diff) |
Initial commit for g3dvl.
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
Diffstat (limited to 'src/gallium')
18 files changed, 4257 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/g3dvl/Makefile b/src/gallium/state_trackers/g3dvl/Makefile new file mode 100644 index 00000000000..a0d85fbcc8f --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/Makefile @@ -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 index 00000000000..939666da9ab --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/.gitignore @@ -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 index 00000000000..8f983593c3a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/Makefile @@ -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 index 00000000000..b78cc851ae4 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c @@ -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 index 00000000000..2002977ee24 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_context.c @@ -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 index 00000000000..1f964711308 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c @@ -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 index 00000000000..2203349784f --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c @@ -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 index 00000000000..4d1946396af --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/tests/test_surface.c @@ -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 index 00000000000..7193f7cceaf --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_context.c @@ -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 index 00000000000..0aeba184ccb --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_context.h @@ -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 index 00000000000..c04163276d8 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_data.c @@ -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 index 00000000000..67a0a749909 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_data.h @@ -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 index 00000000000..e668a7a10e0 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_defs.h @@ -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 index 00000000000..e58e434dab1 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_surface.c @@ -0,0 +1,539 @@ +#include "vl_surface.h" +#include <assert.h> +#include <stdlib.h> +#include <pipe/p_context.h> +#include <pipe/p_state.h> +#include <pipe/p_format.h> +#include <pipe/p_inlines.h> +#include "vl_context.h" +#include "vl_defs.h" + +static int vlGrabBlocks +( + struct VL_CONTEXT *context, + unsigned int coded_block_pattern, + enum VL_DCT_TYPE dct_type, + enum VL_SAMPLE_TYPE sample_type, + short *blocks +) +{ + struct pipe_surface *tex_surface; + short *texels; + unsigned int b, x, y, y2; + + assert(context); + assert(blocks); + + tex_surface = context->pipe->screen->get_tex_surface + ( + context->pipe->screen, + context->states.mc.textures[0], + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE + ); + + texels = pipe_surface_map(tex_surface, 0); + + for (b = 0; b < 4; ++b) + { + if ((coded_block_pattern >> b) & 1) + { + if (dct_type == VL_DCT_FRAME_CODED) + { + if (sample_type == VL_FULL_SAMPLE) + { + for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y) + memcpy + ( + texels + y * tex_surface->pitch, + blocks + y * VL_BLOCK_WIDTH, + VL_BLOCK_WIDTH * 2 + ); + } + else + { + for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y) + for (x = 0; x < VL_BLOCK_WIDTH; ++x) + texels[y * tex_surface->pitch + x] = + blocks[y * VL_BLOCK_WIDTH + x] + 0x100; + } + } + else + { + if (sample_type == VL_FULL_SAMPLE) + { + for + ( + y = VL_BLOCK_HEIGHT * (b % 2), y2 = VL_BLOCK_HEIGHT * b; + y < VL_BLOCK_HEIGHT * ((b % 2) + 1); + y += 2, ++y2 + ) + memcpy + ( + texels + y * tex_surface->pitch, + blocks + y2 * VL_BLOCK_WIDTH, + VL_BLOCK_WIDTH * 2 + ); + for + ( + y = VL_BLOCK_HEIGHT * ((b % 2) + 2); + y < VL_BLOCK_HEIGHT * (((b % 2) + 2) + 1); + y += 2, ++y2 + ) + memcpy + ( + texels + y * tex_surface->pitch, + blocks + y2 * VL_BLOCK_WIDTH, + VL_BLOCK_WIDTH * 2 + ); + } + else + { + for + ( + y = VL_BLOCK_HEIGHT * (b % 2), y2 = VL_BLOCK_HEIGHT * b; + y < VL_BLOCK_HEIGHT * ((b % 2) + 1); + y += 2, ++y2 + ) + for (x = 0; x < VL_BLOCK_WIDTH; ++x) + texels[y * tex_surface->pitch + x] = + blocks[y2 * VL_BLOCK_WIDTH + x] + 0x100; + for + ( + y = VL_BLOCK_HEIGHT * ((b % 2) + 2); + y < VL_BLOCK_HEIGHT * (((b % 2) + 2) + 1); + y += 2, ++y2 + ) + for (x = 0; x < VL_BLOCK_WIDTH; ++x) + texels[y * tex_surface->pitch + x] = + blocks[y2 * VL_BLOCK_WIDTH + x] + 0x100; + } + } + } + else + { + for (y = VL_BLOCK_HEIGHT * b; y < VL_BLOCK_HEIGHT * (b + 1); ++y) + { + for (x = 0; x < VL_BLOCK_WIDTH; ++x) + texels[y * tex_surface->pitch + x] = 0x100; + } + } + } + + pipe_surface_unmap(tex_surface); + + /* TODO: Implement 422, 444 */ + for (b = 0; b < 2; ++b) + { + tex_surface = context->pipe->screen->get_tex_surface + ( + context->pipe->screen, + context->states.mc.textures[b + 1], + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE + ); + + texels = pipe_surface_map(tex_surface, 0); + + if ((coded_block_pattern >> (b + 4)) & 1) + { + if (sample_type == VL_FULL_SAMPLE) + { + for (y = 0; y < tex_surface->height; ++y) + memcpy + ( + texels + y * tex_surface->pitch, + blocks + VL_BLOCK_SIZE * (b + 4) + y * VL_BLOCK_WIDTH, + VL_BLOCK_WIDTH * 2 + ); + } + else + { + for (y = 0; y < tex_surface->height; ++y) + for (x = 0; x < VL_BLOCK_WIDTH; ++x) + texels[y * tex_surface->pitch + x] = + blocks[VL_BLOCK_SIZE * (b + 4) + y * VL_BLOCK_WIDTH + x] + 0x100; + } + } + else + { + for (y = 0; y < tex_surface->height; ++y) + { + for (x = 0; x < VL_BLOCK_WIDTH; ++x) + texels[y * tex_surface->pitch + x] = 0x100; + } + } + + pipe_surface_unmap(tex_surface); + } + + return 0; +} + +int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface) +{ + struct pipe_context *pipe; + struct pipe_texture template; + struct VL_SURFACE *sfc; + + assert(context); + assert(surface); + + pipe = context->pipe; + + sfc = calloc(1, sizeof(struct VL_SURFACE)); + + sfc->context = context; + sfc->width = context->video_width; + sfc->height = context->video_height; + sfc->format = context->video_format; + + memset(&template, 0, sizeof(struct pipe_texture)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_A8R8G8B8_UNORM; + template.last_level = 0; + template.width[0] = sfc->width; + template.height[0] = sfc->height; + template.depth[0] = 1; + template.compressed = 0; + template.cpp = 4; + + sfc->texture = pipe->screen->texture_create(pipe->screen, &template); + + *surface = sfc; + + return 0; +} + +int vlDestroySurface(struct VL_SURFACE *surface) +{ + assert(surface); + pipe_texture_release(&surface->texture); + free(surface); + + return 0; +} + +int vlRenderIMacroBlock +( + enum VL_PICTURE picture_type, + enum VL_FIELD_ORDER field_order, + unsigned int mbx, + unsigned int mby, + unsigned int coded_block_pattern, + enum VL_DCT_TYPE dct_type, + short *blocks, + struct VL_SURFACE *surface +) +{ + struct pipe_context *pipe; + struct VL_MC_VS_CONSTS *vscbdata; + + assert(blocks); + assert(surface); + + /* TODO: Implement interlaced rendering */ + /*assert(picture_type == VL_FRAME_PICTURE);*/ + if (picture_type != VL_FRAME_PICTURE) + { + /*fprintf(stderr, "field picture (I) unimplemented, ignoring\n");*/ + return 0; + } + + pipe = surface->context->pipe; + + vscbdata = pipe->winsys->buffer_map + ( + pipe->winsys, + surface->context->states.mc.vs_const_buf.buffer, + PIPE_BUFFER_USAGE_CPU_WRITE + ); + + vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width; + vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height; + vscbdata->scale.z = 1.0f; + vscbdata->scale.w = 1.0f; + vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width; + vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height; + vscbdata->mb_pos_trans.z = 0.0f; + vscbdata->mb_pos_trans.w = 0.0f; + + pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer); + + vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_FULL_SAMPLE, blocks); + + surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface + ( + pipe->screen, + surface->texture, + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE + ); + pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target); + pipe->set_sampler_textures(pipe, 3, surface->context->states.mc.textures); + pipe->bind_sampler_states(pipe, 3, (void**)surface->context->states.mc.samplers); + pipe->set_vertex_buffers(pipe, 4, surface->context->states.mc.vertex_bufs); + pipe->set_vertex_elements(pipe, 4, surface->context->states.mc.vertex_buf_elems); + pipe->bind_vs_state(pipe, surface->context->states.mc.i_vs); + pipe->bind_fs_state(pipe, surface->context->states.mc.i_fs); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24); + + return 0; +} + +int vlRenderPMacroBlock +( + enum VL_PICTURE picture_type, + enum VL_FIELD_ORDER field_order, + unsigned int mbx, + unsigned int mby, + enum VL_MC_TYPE mc_type, + struct VL_MOTION_VECTOR *motion_vector, + unsigned int coded_block_pattern, + enum VL_DCT_TYPE dct_type, + short *blocks, + struct VL_SURFACE *ref_surface, + struct VL_SURFACE *surface +) +{ + struct pipe_context *pipe; + struct VL_MC_VS_CONSTS *vscbdata; + + assert(motion_vectors); + assert(blocks); + assert(ref_surface); + assert(surface); + + /* TODO: Implement interlaced rendering */ + /*assert(picture_type == VL_FRAME_PICTURE);*/ + if (picture_type != VL_FRAME_PICTURE) + { + /*fprintf(stderr, "field picture (P) unimplemented, ignoring\n");*/ + return 0; + } + /* TODO: Implement field based motion compensation */ + /*assert(mc_type == VL_FRAME_MC);*/ + if (mc_type != VL_FRAME_MC) + { + /*fprintf(stderr, "field MC (P) unimplemented, ignoring\n");*/ + return 0; + } + + pipe = surface->context->pipe; + + vscbdata = pipe->winsys->buffer_map + ( + pipe->winsys, + surface->context->states.mc.vs_const_buf.buffer, + PIPE_BUFFER_USAGE_CPU_WRITE + ); + + vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width; + vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height; + vscbdata->scale.z = 1.0f; + vscbdata->scale.w = 1.0f; + vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width; + vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height; + vscbdata->mb_pos_trans.z = 0.0f; + vscbdata->mb_pos_trans.w = 0.0f; + vscbdata->mb_tc_trans[0].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->top_field.x * 0.5f) / (float)surface->width; + vscbdata->mb_tc_trans[0].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->top_field.y * 0.5f) / (float)surface->height; + vscbdata->mb_tc_trans[0].z = 0.0f; + vscbdata->mb_tc_trans[0].w = 0.0f; + + pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer); + + vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks); + + surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface + ( + pipe->screen, + surface->texture, + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE + ); + pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target); + + surface->context->states.mc.textures[3] = ref_surface->texture; + pipe->set_sampler_textures(pipe, 4, surface->context->states.mc.textures); + pipe->bind_sampler_states(pipe, 4, (void**)surface->context->states.mc.samplers); + pipe->set_vertex_buffers(pipe, 5, surface->context->states.mc.vertex_bufs); + pipe->set_vertex_elements(pipe, 5, surface->context->states.mc.vertex_buf_elems); + pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs); + pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24); + + return 0; +} + +int vlRenderBMacroBlock +( + enum VL_PICTURE picture_type, + enum VL_FIELD_ORDER field_order, + unsigned int mbx, + unsigned int mby, + enum VL_MC_TYPE mc_type, + struct VL_MOTION_VECTOR *motion_vector, + unsigned int coded_block_pattern, + enum VL_DCT_TYPE dct_type, + short *blocks, + struct VL_SURFACE *past_surface, + struct VL_SURFACE *future_surface, + struct VL_SURFACE *surface +) +{ + struct pipe_context *pipe; + struct VL_MC_VS_CONSTS *vscbdata; + + assert(motion_vectors); + assert(blocks); + assert(ref_surface); + assert(surface); + + /* TODO: Implement interlaced rendering */ + /*assert(picture_type == VL_FRAME_PICTURE);*/ + if (picture_type != VL_FRAME_PICTURE) + { + /*fprintf(stderr, "field picture (B) unimplemented, ignoring\n");*/ + return 0; + } + /* TODO: Implement field based motion compensation */ + /*assert(mc_type == VL_FRAME_MC);*/ + if (mc_type != VL_FRAME_MC) + { + /*fprintf(stderr, "field MC (B) unimplemented, ignoring\n");*/ + return 0; + } + + pipe = surface->context->pipe; + + vscbdata = pipe->winsys->buffer_map + ( + pipe->winsys, + surface->context->states.mc.vs_const_buf.buffer, + PIPE_BUFFER_USAGE_CPU_WRITE + ); + + vscbdata->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width; + vscbdata->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height; + vscbdata->scale.z = 1.0f; + vscbdata->scale.w = 1.0f; + vscbdata->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width; + vscbdata->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height; + vscbdata->mb_pos_trans.z = 0.0f; + vscbdata->mb_pos_trans.w = 0.0f; + vscbdata->mb_tc_trans[0].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].top_field.x * 0.5f) / (float)surface->width; + vscbdata->mb_tc_trans[0].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].top_field.y * 0.5f) / (float)surface->height; + vscbdata->mb_tc_trans[0].z = 0.0f; + vscbdata->mb_tc_trans[0].w = 0.0f; + vscbdata->mb_tc_trans[1].x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].top_field.x * 0.5f) / (float)surface->width; + vscbdata->mb_tc_trans[1].y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].top_field.y * 0.5f) / (float)surface->height; + vscbdata->mb_tc_trans[1].z = 0.0f; + vscbdata->mb_tc_trans[1].w = 0.0f; + + pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer); + + vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks); + + surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface + ( + pipe->screen, + surface->texture, + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE + ); + pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target); + + surface->context->states.mc.textures[3] = past_surface->texture; + surface->context->states.mc.textures[4] = future_surface->texture; + pipe->set_sampler_textures(pipe, 5, surface->context->states.mc.textures); + pipe->bind_sampler_states(pipe, 5, (void**)surface->context->states.mc.samplers); + pipe->set_vertex_buffers(pipe, 6, surface->context->states.mc.vertex_bufs); + pipe->set_vertex_elements(pipe, 6, surface->context->states.mc.vertex_buf_elems); + pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs); + pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24); + + return 0; +} + +int vlPutSurface +( + struct VL_SURFACE *surface, + Drawable drawable, + unsigned int srcx, + unsigned int srcy, + unsigned int srcw, + unsigned int srch, + unsigned int destx, + unsigned int desty, + unsigned int destw, + unsigned int desth, + enum VL_PICTURE picture_type +) +{ + unsigned int create_fb = 0; + struct pipe_context *pipe; + + assert(surface); + + pipe = surface->context->pipe; + + if (!surface->context->states.csc.framebuffer.cbufs[0]) + create_fb = 1; + else if + ( + surface->context->states.csc.framebuffer.width != destw || + surface->context->states.csc.framebuffer.height != desth + ) + { + pipe->winsys->surface_release + ( + pipe->winsys, + &surface->context->states.csc.framebuffer.cbufs[0] + ); + + create_fb = 1; + } + + if (create_fb) + { + surface->context->states.csc.viewport.scale[0] = destw; + surface->context->states.csc.viewport.scale[1] = desth; + surface->context->states.csc.viewport.scale[2] = 1; + surface->context->states.csc.viewport.scale[3] = 1; + surface->context->states.csc.viewport.translate[0] = 0; + surface->context->states.csc.viewport.translate[1] = 0; + surface->context->states.csc.viewport.translate[2] = 0; + surface->context->states.csc.viewport.translate[3] = 0; + + surface->context->states.csc.framebuffer.width = destw; + surface->context->states.csc.framebuffer.height = desth; + surface->context->states.csc.framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys); + pipe->winsys->surface_alloc_storage + ( + pipe->winsys, + surface->context->states.csc.framebuffer.cbufs[0], + destw, + desth, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE, + 0 + ); + } + + vlEndRender(surface->context); + + pipe->set_sampler_textures(pipe, 1, &surface->texture); + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + pipe->winsys->flush_frontbuffer + ( + pipe->winsys, + surface->context->states.csc.framebuffer.cbufs[0], + &drawable + ); + + vlBeginRender(surface->context); + + return 0; +} + diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h new file mode 100644 index 00000000000..9f56b77e1e7 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_surface.h @@ -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 index 00000000000..7040b745036 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_types.h @@ -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 index 00000000000..eb4c9085d6d --- /dev/null +++ b/src/gallium/winsys/g3dvl/xsp_winsys.c @@ -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 index 00000000000..47a6ac6e251 --- /dev/null +++ b/src/gallium/winsys/g3dvl/xsp_winsys.h @@ -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 + |