From: José Fonseca Date: Wed, 22 Feb 2012 15:22:31 +0000 (+0000) Subject: tests/graw: Add a bunch of tests. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d35d3d612acef1612aaab9a923b8814d4dbb4d9c;p=mesa.git tests/graw: Add a bunch of tests. These were rotting in an internal branch, but contain nothing confidential, and would be much more useful if kept up-to-date with latest gallium interface changes. Several authors including Keith Whitwell, Zack Rusin, and Brian Paul. --- diff --git a/src/gallium/tests/graw/SConscript b/src/gallium/tests/graw/SConscript index ad44d54c855..1fd2b532f40 100644 --- a/src/gallium/tests/graw/SConscript +++ b/src/gallium/tests/graw/SConscript @@ -16,15 +16,21 @@ if env['platform'] == 'freebsd8': progs = [ 'clear', - 'tri', - 'tri-instanced', - 'quad-tex', + 'fs-fragcoord', + 'fs-frontface', 'fs-test', - 'vs-test', + 'fs-write-z', 'gs-test', + 'occlusion-query', + 'quad-sample', + 'quad-tex', 'shader-leak', + 'tex-srgb', + 'tex-swizzle', + 'tri', 'tri-gs', - 'quad-sample', + 'tri-instanced', + 'vs-test', ] for name in progs: diff --git a/src/gallium/tests/graw/fs-fragcoord.c b/src/gallium/tests/graw/fs-fragcoord.c new file mode 100644 index 00000000000..471acbb3639 --- /dev/null +++ b/src/gallium/tests/graw/fs-fragcoord.c @@ -0,0 +1,259 @@ +/* Test the TGSI_SEMANTIC_POSITION fragment shader input. + * Plus properties for upper-left vs. lower-left origin and + * center integer vs. half-integer; + */ + +#include + +#include "graw_util.h" + + +static int width = 300; +static int height = 300; + +static struct graw_info info; + +struct vertex { + float position[4]; + float color[4]; +}; + +/* Note: the upper-left vertex is pushed to the left a bit to + * make sure we can spot upside-down rendering. + */ +static struct vertex vertices[] = +{ + { + {-0.95, -0.95, 0.5, 1.0 }, + { 0, 0, 0, 1 } + }, + + { + { 0.85, -0.95, 0.5, 1.0 }, + { 0, 0, 0, 1 } + }, + + { + { 0.95, 0.95, 0.5, 1.0 }, + { 0, 0, 0, 1 } + }, + + { + {-0.95, 0.95, 0.5, 1.0 }, + { 0, 0, 0, 1 } + } +}; + +#define NUM_VERTS (sizeof(vertices) / sizeof(vertices[0])) + + +static void +set_vertices(void) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); + + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = info.screen->user_buffer_create(info.screen, + vertices, + sizeof(vertices), + PIPE_BIND_VERTEX_BUFFER); + + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); +} + + +static void +set_vertex_shader(void) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: MOV OUT[1], IN[1]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); +} + + +static void +set_fragment_shader(int mode) +{ + void *handle; + + const char *origin_upper_left_text = + "FRAG\n" + "PROPERTY FS_COORD_ORIGIN UPPER_LEFT\n" /* upper-left = black corner */ + "DCL IN[0], POSITION, LINEAR\n" + "DCL OUT[0], COLOR\n" + "DCL TEMP[0]\n" + "IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 }\n" + "IMM FLT32 { 0.0, 300.0, 0.0, 0.0 }\n" + " 0: MOV TEMP[0], IN[0] \n" + " 1: MOV TEMP[0].zw, IMM[1].xxxx \n" + " 2: MUL OUT[0], TEMP[0], IMM[0] \n" + " 3: END\n"; + + const char *origin_lower_left_text = + "FRAG\n" + "PROPERTY FS_COORD_ORIGIN LOWER_LEFT\n" /* lower-left = black corner */ + "DCL IN[0], POSITION, LINEAR\n" + "DCL OUT[0], COLOR\n" + "DCL TEMP[0]\n" + "IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 }\n" + "IMM FLT32 { 0.0, 300.0, 0.0, 0.0 }\n" + " 0: MOV TEMP[0], IN[0] \n" + " 1: MOV TEMP[0].zw, IMM[1].xxxx \n" + " 2: MUL OUT[0], TEMP[0], IMM[0] \n" + " 3: END\n"; + + /* Test fragcoord center integer vs. half integer */ + const char *center_integer_text = + "FRAG\n" + "PROPERTY FS_COORD_PIXEL_CENTER INTEGER \n" /* pixels are black */ + "DCL IN[0], POSITION, LINEAR \n" + "DCL OUT[0], COLOR \n" + "DCL TEMP[0] \n" + "IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 } \n" + "IMM FLT32 { 0.0, 300.0, 0.0, 0.0 } \n" + "0: FRC TEMP[0], IN[0] \n" + "1: MOV TEMP[0].zw, IMM[1].xxxx \n" + "2: MOV OUT[0], TEMP[0] \n" + "3: END \n"; + + const char *center_half_integer_text = + "FRAG\n" + "PROPERTY FS_COORD_PIXEL_CENTER HALF_INTEGER \n" /* pixels are olive colored */ + "DCL IN[0], POSITION, LINEAR \n" + "DCL OUT[0], COLOR \n" + "DCL TEMP[0] \n" + "IMM FLT32 { 0.003333, 0.003333, 1.0, 1.0 } \n" + "IMM FLT32 { 0.0, 300.0, 0.0, 0.0 } \n" + "0: FRC TEMP[0], IN[0] \n" + "1: MOV TEMP[0].zw, IMM[1].xxxx \n" + "2: MOV OUT[0], TEMP[0] \n" + "3: END \n"; + + const char *text; + + if (mode == 0) + text = origin_upper_left_text; + else if (mode == 1) + text = origin_lower_left_text; + else if (mode == 2) + text = center_integer_text; + else + text = center_half_integer_text; + + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); +} + + +static void +draw(void) +{ + union pipe_color_union clear_color; + + clear_color.f[0] = 0.25; + clear_color.f[1] = 0.25; + clear_color.f[2] = 0.25; + clear_color.f[3] = 1.0; + + info.ctx->clear(info.ctx, + PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, + &clear_color, 1.0, 0); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS); + info.ctx->flush(info.ctx, NULL); + +#if 0 + /* At the moment, libgraw leaks out/makes available some of the + * symbols from gallium/auxiliary, including these debug helpers. + * Will eventually want to bless some of these paths, and lock the + * others down so they aren't accessible from test programs. + * + * This currently just happens to work on debug builds - a release + * build will probably fail to link here: + */ + debug_dump_surface_bmp(info.ctx, "result.bmp", surf); +#endif + + graw_util_flush_front(&info); +} + + +#if 0 +static void +resize(int w, int h) +{ + width = w; + height = h; + + set_viewport(0, 0, width, height, 30, 1000); +} +#endif + + +static void +init(int mode) +{ + if (!graw_util_create_window(&info, width, height, 1, TRUE)) + exit(1); + + graw_util_default_state(&info, TRUE); + + graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0); + + set_vertices(); + set_vertex_shader(); + set_fragment_shader(mode); +} + + +int +main(int argc, char *argv[]) +{ + int mode = argc > 1 ? atoi(argv[1]) : 0; + + switch (mode) { + default: + case 0: + printf("frag coord origin upper-left (lower-left = black)\n"); + break; + case 1: + printf("frag coord origin lower-left (upper-left = black)\n"); + break; + case 2: + printf("frag coord center integer (all pixels black)\n"); + break; + case 3: + printf("frag coord center half-integer (all pixels olive color)\n"); + break; + } + + init(mode); + + graw_set_display_func(draw); + /*graw_set_reshape_func(resize);*/ + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/fs-frontface.c b/src/gallium/tests/graw/fs-frontface.c new file mode 100644 index 00000000000..e7252551815 --- /dev/null +++ b/src/gallium/tests/graw/fs-frontface.c @@ -0,0 +1,206 @@ +/* Test the TGSI_SEMANTIC_FACE fragment shader input. + */ + +#include + +#include "graw_util.h" + + +static int width = 300; +static int height = 300; + +static struct graw_info info; + +struct vertex { + float position[4]; + float color[4]; +}; + +#define z0 0.2 +#define z01 0.5 +#define z1 0.4 + +static struct vertex vertices[] = +{ + /* left quad: clock-wise, front-facing, red */ + { + {-0.8, -0.9, z0, 1.0 }, + { 0, 0, 0, 1 } + }, + + { + { -0.2, -0.9, z0, 1.0 }, + { 0, 0, 0, 1 } + }, + + { + { 0.2, 0.9, z01, 1.0 }, + { 0, 0, 0, 1 } + }, + + { + {-0.9, 0.9, z01, 1.0 }, + { 0, 0, 0, 1 } + }, + + /* right quad : counter-clock-wise, back-facing, green */ + { + { 0.2, -0.9, z1, 1.0 }, + { 1, 1, 1, -1 } + }, + + { + { -0.2, 0.8, z1, 1.0 }, + { 1, 1, 1, -1 } + }, + + { + { 0.9, 0.8, z1, 1.0 }, + { 1, 1, 1, -1 } + }, + + { + { 0.8, -0.9, z1, 1.0 }, + { 1, 1, 1, -1 } + }, +}; + +#define NUM_VERTS (sizeof(vertices) / sizeof(vertices[0])) + + + +static void +set_vertices(void) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); + + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = info.screen->user_buffer_create(info.screen, + vertices, + sizeof(vertices), + PIPE_BIND_VERTEX_BUFFER); + + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); +} + + +static void +set_vertex_shader(void) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: MOV OUT[1], IN[1]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); +} + + +static void +set_fragment_shader(void) +{ + void *handle; + const char *text = + "FRAG\n" + "DCL IN[0], FACE, CONSTANT\n" + "DCL IN[1], GENERIC, CONSTANT\n" + "DCL OUT[0], COLOR\n" + "DCL TEMP[0]\n" + "IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }\n" + "IMM FLT32 { 0.0, 1.0, 0.0, 0.0 }\n" + "IMM FLT32 { 0.5, 0.6, 0.0, 0.0 }\n" + " 0: SGT TEMP[0].x, IN[0].xxxx, IMM[1].xxxx\n" /* TMP[0].x = IN[0].x > 0.0 */ + " 1: IF TEMP[0].xxxx :4\n" + " 2: MOV OUT[0], IMM[0]\n" /* front-facing: red */ + " 3: ELSE :5\n" + " 4: MOV OUT[0], IMM[1]\n" /* back-facing: green */ + " 5: ENDIF\n" + " 6: END\n"; + + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); +} + + +static void +draw(void) +{ + union pipe_color_union clear_color; + + clear_color.f[0] = 0.25; + clear_color.f[1] = 0.25; + clear_color.f[2] = 0.25; + clear_color.f[3] = 1.00; + + info.ctx->clear(info.ctx, + PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, + &clear_color, 1.0, 0); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS); + info.ctx->flush(info.ctx, NULL); + + graw_util_flush_front(&info); +} + + +#if 0 +static void +resize(int w, int h) +{ + width = w; + height = h; + + set_viewport(0, 0, width, height, 30, 1000); +} +#endif + + +static void +init(void) +{ + if (!graw_util_create_window(&info, width, height, 1, TRUE)) + exit(1); + + graw_util_default_state(&info, TRUE); + + graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0); + + set_vertices(); + set_vertex_shader(); + set_fragment_shader(); +} + + +int +main(int argc, char *argv[]) +{ + init(); + + printf("Left quad: clock-wise, front-facing, red\n"); + printf("Right quad: counter clock-wise, back-facing, green\n"); + + graw_set_display_func(draw); + /*graw_set_reshape_func(resize);*/ + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/fs-write-z.c b/src/gallium/tests/graw/fs-write-z.c new file mode 100644 index 00000000000..186e3ec5034 --- /dev/null +++ b/src/gallium/tests/graw/fs-write-z.c @@ -0,0 +1,222 @@ +/* Test the writing Z in fragment shader. + * The red quad should be entirely in front of the blue quad even + * though the overlap and intersect in Z. + */ + +#include + +#include "graw_util.h" + + +static int width = 300; +static int height = 300; + +static struct graw_info info; + + +struct vertex { + float position[4]; + float color[4]; +}; + +#define z0 0.2 +#define z01 0.5 +#define z1 0.4 + + +static struct vertex vertices[] = +{ + /* left quad: clock-wise, front-facing, red */ + { + {-0.8, -0.9, z0, 1.0 }, + { 1, 0, 0, 1 } + }, + + { + { -0.2, -0.9, z0, 1.0 }, + { 1, 0, 0, 1 } + }, + + { + { 0.2, 0.9, z01, 1.0 }, + { 1, 0, 0, 1 } + }, + + { + {-0.9, 0.9, z01, 1.0 }, + { 1, 0, 0, 1 } + }, + + /* right quad : counter-clock-wise, back-facing, green */ + { + { 0.2, -0.9, z1, 1.0 }, + { 0, 0, 1, -1 } + }, + + { + { -0.2, 0.8, z1, 1.0 }, + { 0, 0, 1, -1 } + }, + + { + { 0.9, 0.8, z1, 1.0 }, + { 0, 0, 1, -1 } + }, + + { + { 0.8, -0.9, z1, 1.0 }, + { 0, 0, 1, -1 } + }, +}; + +#define NUM_VERTS (sizeof(vertices) / sizeof(vertices[0])) + + + +static void +set_vertices(void) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); + + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = info.screen->user_buffer_create(info.screen, + vertices, + sizeof(vertices), + PIPE_BIND_VERTEX_BUFFER); + + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); +} + + +static void +set_vertex_shader(void) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: MOV OUT[1], IN[1]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); +} + + +static void +set_fragment_shader(void) +{ + void *handle; + const char *text = + "FRAG\n" + "DCL IN[0], GENERIC, CONSTANT\n" + "DCL OUT[0], COLOR\n" + "DCL OUT[1], POSITION\n" + "DCL TEMP[0]\n" + "IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }\n" + "IMM FLT32 { 0.0, 1.0, 0.0, 0.0 }\n" + "IMM FLT32 { 0.5, 0.4, 0.0, 0.0 }\n" + " 0: MOV OUT[0], IN[0]\n" /* front-facing: red */ + " 1: IF IN[0].xxxx :3\n" + " 2: MOV OUT[1].z, IMM[2].yyyy\n" /* red: Z = 0.4 */ + " 3: ELSE :5\n" + " 4: MOV OUT[1].z, IMM[2].xxxx\n" /* blue: Z = 0.5 */ + " 5: ENDIF\n" + " 6: END\n"; + + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); +} + + + +static void +draw(void) +{ + union pipe_color_union clear_color; + + clear_color.f[0] = 0.25; + clear_color.f[1] = 0.25; + clear_color.f[2] = 0.25; + clear_color.f[3] = 1.00; + + info.ctx->clear(info.ctx, + PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, + &clear_color, 1.0, 0); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS); + info.ctx->flush(info.ctx, NULL); + +#if 0 + /* At the moment, libgraw leaks out/makes available some of the + * symbols from gallium/auxiliary, including these debug helpers. + * Will eventually want to bless some of these paths, and lock the + * others down so they aren't accessible from test programs. + * + * This currently just happens to work on debug builds - a release + * build will probably fail to link here: + */ + debug_dump_surface_bmp(info.ctx, "result.bmp", surf); +#endif + + graw_util_flush_front(&info); +} + + +#if 0 +static void +resize(int w, int h) +{ + width = w; + height = h; + + graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0); +} +#endif + + +static void +init(void) +{ + if (!graw_util_create_window(&info, width, height, 1, TRUE)) + exit(1); + + graw_util_default_state(&info, TRUE); + + graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0); + + set_vertices(); + set_vertex_shader(); + set_fragment_shader(); +} + + +int +main(int argc, char *argv[]) +{ + init(); + + printf("The red quad should be entirely in front of the blue quad.\n"); + + graw_set_display_func(draw); + /*graw_set_reshape_func(resize);*/ + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/graw_util.h b/src/gallium/tests/graw/graw_util.h new file mode 100644 index 00000000000..9250f0b66bb --- /dev/null +++ b/src/gallium/tests/graw/graw_util.h @@ -0,0 +1,329 @@ + +#include "state_tracker/graw.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" + +#include "util/u_box.h" +#include "util/u_debug.h" +#include "util/u_draw_quad.h" +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" + + +struct graw_info +{ + struct pipe_screen *screen; + struct pipe_context *ctx; + struct pipe_resource *color_buf[PIPE_MAX_COLOR_BUFS], *zs_buf; + struct pipe_surface *color_surf[PIPE_MAX_COLOR_BUFS], *zs_surf; + void *window; +}; + + + +static INLINE boolean +graw_util_create_window(struct graw_info *info, + int width, int height, + int num_cbufs, bool zstencil_buf) +{ + static const enum pipe_format formats[] = { + PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_NONE + }; + enum pipe_format format; + struct pipe_resource resource_temp; + struct pipe_surface surface_temp; + int i; + + memset(info, 0, sizeof(*info)); + + /* It's hard to say whether window or screen should be created + * first. Different environments would prefer one or the other. + * + * Also, no easy way of querying supported formats if the screen + * cannot be created first. + */ + for (i = 0; info->window == NULL && formats[i] != PIPE_FORMAT_NONE; i++) { + info->screen = graw_create_window_and_screen(0, 0, width, height, + formats[i], + &info->window); + format = formats[i]; + } + if (!info->screen || !info->window) { + debug_printf("graw: Failed to create screen/window\n"); + return FALSE; + } + + info->ctx = info->screen->context_create(info->screen, NULL); + if (info->ctx == NULL) { + debug_printf("graw: Failed to create context\n"); + return FALSE; + } + + for (i = 0; i < num_cbufs; i++) { + /* create color texture */ + resource_temp.target = PIPE_TEXTURE_2D; + resource_temp.format = format; + resource_temp.width0 = width; + resource_temp.height0 = height; + resource_temp.depth0 = 1; + resource_temp.array_size = 1; + resource_temp.last_level = 0; + resource_temp.nr_samples = 1; + resource_temp.bind = (PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET); + info->color_buf[i] = info->screen->resource_create(info->screen, + &resource_temp); + if (info->color_buf[i] == NULL) { + debug_printf("graw: Failed to create color texture\n"); + return FALSE; + } + + /* create color surface */ + surface_temp.format = resource_temp.format; + surface_temp.usage = PIPE_BIND_RENDER_TARGET; + surface_temp.u.tex.level = 0; + surface_temp.u.tex.first_layer = 0; + surface_temp.u.tex.last_layer = 0; + info->color_surf[i] = info->ctx->create_surface(info->ctx, + info->color_buf[i], + &surface_temp); + if (info->color_surf[i] == NULL) { + debug_printf("graw: Failed to get color surface\n"); + return FALSE; + } + } + + /* create Z texture (XXX try other Z/S formats if needed) */ + resource_temp.target = PIPE_TEXTURE_2D; + resource_temp.format = PIPE_FORMAT_S8_UINT_Z24_UNORM; + resource_temp.width0 = width; + resource_temp.height0 = height; + resource_temp.depth0 = 1; + resource_temp.array_size = 1; + resource_temp.last_level = 0; + resource_temp.nr_samples = 1; + resource_temp.bind = PIPE_BIND_DEPTH_STENCIL; + info->zs_buf = info->screen->resource_create(info->screen, &resource_temp); + if (!info->zs_buf) { + debug_printf("graw: Failed to create Z texture\n"); + return FALSE; + } + + /* create z surface */ + surface_temp.format = resource_temp.format; + surface_temp.usage = PIPE_BIND_DEPTH_STENCIL; + surface_temp.u.tex.level = 0; + surface_temp.u.tex.first_layer = 0; + surface_temp.u.tex.last_layer = 0; + info->zs_surf = info->ctx->create_surface(info->ctx, + info->zs_buf, + &surface_temp); + if (info->zs_surf == NULL) { + debug_printf("graw: Failed to get Z surface\n"); + return FALSE; + } + + { + struct pipe_framebuffer_state fb; + memset(&fb, 0, sizeof fb); + fb.nr_cbufs = num_cbufs; + fb.width = width; + fb.height = height; + for (i = 0; i < num_cbufs; i++) + fb.cbufs[i] = info->color_surf[i]; + fb.zsbuf = info->zs_surf; + info->ctx->set_framebuffer_state(info->ctx, &fb); + } + + return TRUE; +} + + +static INLINE void +graw_util_default_state(struct graw_info *info, boolean depth_test) +{ + { + struct pipe_blend_state blend; + void *handle; + memset(&blend, 0, sizeof blend); + blend.rt[0].colormask = PIPE_MASK_RGBA; + handle = info->ctx->create_blend_state(info->ctx, &blend); + info->ctx->bind_blend_state(info->ctx, handle); + } + + { + struct pipe_depth_stencil_alpha_state depthStencilAlpha; + void *handle; + memset(&depthStencilAlpha, 0, sizeof depthStencilAlpha); + depthStencilAlpha.depth.enabled = depth_test; + depthStencilAlpha.depth.writemask = 1; + depthStencilAlpha.depth.func = PIPE_FUNC_LESS; + handle = info->ctx->create_depth_stencil_alpha_state(info->ctx, + &depthStencilAlpha); + info->ctx->bind_depth_stencil_alpha_state(info->ctx, handle); + } + + { + struct pipe_rasterizer_state rasterizer; + void *handle; + memset(&rasterizer, 0, sizeof rasterizer); + rasterizer.cull_face = PIPE_FACE_NONE; + rasterizer.gl_rasterization_rules = 1; + handle = info->ctx->create_rasterizer_state(info->ctx, &rasterizer); + info->ctx->bind_rasterizer_state(info->ctx, handle); + } +} + + +static INLINE void +graw_util_viewport(struct graw_info *info, + float x, float y, + float width, float height, + float near, float far) +{ + float z = near; + float half_width = width / 2.0f; + float half_height = height / 2.0f; + float half_depth = (far - near) / 2.0f; + struct pipe_viewport_state vp; + + vp.scale[0] = half_width; + vp.scale[1] = half_height; + vp.scale[2] = half_depth; + vp.scale[3] = 1.0f; + + vp.translate[0] = half_width + x; + vp.translate[1] = half_height + y; + vp.translate[2] = half_depth + z; + vp.translate[3] = 0.0f; + + info->ctx->set_viewport_state(info->ctx, &vp); +} + + +static INLINE void +graw_util_flush_front(const struct graw_info *info) +{ + info->screen->flush_frontbuffer(info->screen, info->color_buf[0], + 0, 0, info->window); +} + + +static INLINE struct pipe_resource * +graw_util_create_tex2d(const struct graw_info *info, + int width, int height, enum pipe_format format, + const void *data) +{ + const int row_stride = width * util_format_get_blocksize(format); + const int image_bytes = row_stride * height; + struct pipe_resource temp, *tex; + struct pipe_box box; + + temp.target = PIPE_TEXTURE_2D; + temp.format = PIPE_FORMAT_B8G8R8A8_UNORM; + temp.width0 = width; + temp.height0 = height; + temp.depth0 = 1; + temp.last_level = 0; + temp.array_size = 1; + temp.nr_samples = 1; + temp.bind = PIPE_BIND_SAMPLER_VIEW; + + tex = info->screen->resource_create(info->screen, &temp); + if (!tex) { + debug_printf("graw: failed to create texture\n"); + return NULL; + } + + u_box_2d(0, 0, width, height, &box); + + info->ctx->transfer_inline_write(info->ctx, + tex, + 0, + PIPE_TRANSFER_WRITE, + &box, + data, + row_stride, + image_bytes); + + /* Possibly read back & compare against original data: + */ +#if 0 + { + struct pipe_transfer *t; + uint32_t *ptr; + t = pipe_get_transfer(info->ctx, samptex, + 0, 0, /* level, layer */ + PIPE_TRANSFER_READ, + 0, 0, SIZE, SIZE); /* x, y, width, height */ + + ptr = info->ctx->transfer_map(info->ctx, t); + + if (memcmp(ptr, tex2d, sizeof tex2d) != 0) { + assert(0); + exit(9); + } + + info->ctx->transfer_unmap(info->ctx, t); + + info->ctx->transfer_destroy(info->ctx, t); + } +#endif + + return tex; +} + + +static INLINE void * +graw_util_create_simple_sampler(const struct graw_info *info, + unsigned wrap_mode, + unsigned img_filter) +{ + struct pipe_sampler_state sampler_desc; + void *sampler; + + memset(&sampler_desc, 0, sizeof sampler_desc); + sampler_desc.wrap_s = + sampler_desc.wrap_t = + sampler_desc.wrap_r = wrap_mode; + sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler_desc.min_img_filter = + sampler_desc.mag_img_filter = img_filter; + sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler_desc.compare_func = 0; + sampler_desc.normalized_coords = 1; + sampler_desc.max_anisotropy = 0; + + sampler = info->ctx->create_sampler_state(info->ctx, &sampler_desc); + + return sampler; +} + + +static INLINE struct pipe_sampler_view * +graw_util_create_simple_sampler_view(const struct graw_info *info, + struct pipe_resource *texture) +{ + struct pipe_sampler_view sv_temp; + struct pipe_sampler_view *sv; + + memset(&sv_temp, 0, sizeof(sv_temp)); + sv_temp.format = texture->format; + sv_temp.texture = texture; + sv_temp.swizzle_r = PIPE_SWIZZLE_RED; + sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN; + sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE; + sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA; + + sv = info->ctx->create_sampler_view(info->ctx, texture, &sv_temp); + + return sv; +} + diff --git a/src/gallium/tests/graw/occlusion-query.c b/src/gallium/tests/graw/occlusion-query.c new file mode 100644 index 00000000000..5c4bc8cf479 --- /dev/null +++ b/src/gallium/tests/graw/occlusion-query.c @@ -0,0 +1,242 @@ +/* Test gallium occlusion queries. + */ + +#include + +#include "graw_util.h" + + +static int width = 300; +static int height = 300; + +/* expected results of occlusion test (depndsd on window size) */ +static int expected1 = (int) ((300 * 0.9) * (300 * 0.9)); +static int expected2 = 420; + + +static struct graw_info info; + +struct vertex { + float position[4]; + float color[4]; +}; + +#define z0 0.2 +#define z1 0.6 + +static struct vertex obj1_vertices[4] = +{ + { + {-0.9, -0.9, z0, 1.0 }, + { 1, 0, 0, 1 } + }, + + { + { 0.9, -0.9, z0, 1.0 }, + { 1, 0, 0, 1 } + }, + + { + { 0.9, 0.9, z0, 1.0 }, + { 1, 0, 0, 1 } + }, + + { + {-0.9, 0.9, z0, 1.0 }, + { 1, 0, 0, 1 } + } +}; + +static struct vertex obj2_vertices[4] = +{ + { + { -0.2, -0.2, z1, 1.0 }, + { 0, 0, 1, 1 } + }, + + { + { 0.95, -0.2, z1, 1.0 }, + { 0, 0, 1, 1 } + }, + + { + { 0.95, 0.2, z1, 1.0 }, + { 0, 0, 1, 1 } + }, + + { + { -0.2, 0.2, z1, 1.0 }, + { 0, 0, 1, 1 } + }, +}; + +#define NUM_VERTS 4 + + + +static void +set_vertices(struct vertex *vertices, unsigned bytes) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); + + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = info.screen->user_buffer_create(info.screen, + vertices, + bytes, + PIPE_BIND_VERTEX_BUFFER); + + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); +} + + +static void +set_vertex_shader(struct graw_info *info) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: MOV OUT[1], IN[1]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(info->ctx, text); + if (!handle) { + debug_printf("Failed to parse vertex shader\n"); + return; + } + info->ctx->bind_vs_state(info->ctx, handle); +} + + +static void +set_fragment_shader(struct graw_info *info) +{ + void *handle; + const char *text = + "FRAG\n" + "DCL IN[0], GENERIC, LINEAR\n" + "DCL OUT[0], COLOR\n" + " 0: MOV OUT[0], IN[0]\n" + " 1: END\n"; + + handle = graw_parse_fragment_shader(info->ctx, text); + if (!handle) { + debug_printf("Failed to parse fragment shader\n"); + return; + } + info->ctx->bind_fs_state(info->ctx, handle); +} + + +static void +draw(void) +{ + int expected1_min = (int) (expected1 * 0.95); + int expected1_max = (int) (expected1 * 1.05); + int expected2_min = (int) (expected2 * 0.95); + int expected2_max = (int) (expected2 * 1.05); + + union pipe_color_union clear_color; + + struct pipe_query *q1, *q2; + uint64_t res1, res2; + + clear_color.f[0] = 0.25; + clear_color.f[1] = 0.25; + clear_color.f[2] = 0.25; + clear_color.f[3] = 1.00; + + info.ctx->clear(info.ctx, + PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, + &clear_color, 1.0, 0); + + q1 = info.ctx->create_query(info.ctx, PIPE_QUERY_OCCLUSION_COUNTER); + q2 = info.ctx->create_query(info.ctx, PIPE_QUERY_OCCLUSION_COUNTER); + + /* draw first, large object */ + set_vertices(obj1_vertices, sizeof(obj1_vertices)); + info.ctx->begin_query(info.ctx, q1); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS); + info.ctx->end_query(info.ctx, q1); + + /* draw second, small object behind first object */ + set_vertices(obj2_vertices, sizeof(obj2_vertices)); + info.ctx->begin_query(info.ctx, q2); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS); + info.ctx->end_query(info.ctx, q2); + + info.ctx->get_query_result(info.ctx, q1, TRUE, &res1); + info.ctx->get_query_result(info.ctx, q2, TRUE, &res2); + + printf("result1 = %lu result2 = %lu\n", res1, res2); + if (res1 < expected1_min || res1 > expected1_max) + printf(" Failure: result1 should be near %d\n", expected1); + if (res2 < expected2_min || res2 > expected2_max) + printf(" Failure: result2 should be near %d\n", expected2); + + info.ctx->flush(info.ctx, NULL); + + graw_util_flush_front(&info); + + info.ctx->destroy_query(info.ctx, q1); + info.ctx->destroy_query(info.ctx, q2); +} + + +#if 0 +static void +resize(int w, int h) +{ + width = w; + height = h; + + graw_util_viewport(&info, 0, 0, width, height, 30, 1000); +} +#endif + + +static void +init(void) +{ + if (!graw_util_create_window(&info, width, height, 1, TRUE)) + exit(1); + + graw_util_default_state(&info, TRUE); + + graw_util_viewport(&info, 0, 0, width, height, -1.0, 1.0); + + set_vertex_shader(&info); + set_fragment_shader(&info); +} + + +int +main(int argc, char *argv[]) +{ + init(); + + printf("The red quad should mostly occlude the blue quad.\n"); + + graw_set_display_func(draw); + /*graw_set_reshape_func(resize);*/ + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c index 96c6f3fdc8e..9f81ad593ae 100644 --- a/src/gallium/tests/graw/quad-tex.c +++ b/src/gallium/tests/graw/quad-tex.c @@ -2,36 +2,17 @@ * any utility code, just the graw interface and gallium. */ -#include -#include "state_tracker/graw.h" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_shader_tokens.h" -#include "pipe/p_state.h" -#include "pipe/p_defines.h" - -#include "util/u_inlines.h" -#include "util/u_memory.h" /* Offset() */ -#include "util/u_draw_quad.h" -#include "util/u_box.h" - -enum pipe_format formats[] = { - PIPE_FORMAT_R8G8B8A8_UNORM, - PIPE_FORMAT_B8G8R8A8_UNORM, - PIPE_FORMAT_NONE -}; +#include "graw_util.h" static const int WIDTH = 300; static const int HEIGHT = 300; -static struct pipe_screen *screen = NULL; -static struct pipe_context *ctx = NULL; -static struct pipe_resource *rttex = NULL; -static struct pipe_resource *samptex = NULL; -static struct pipe_surface *surf = NULL; +static struct graw_info info; + + +static struct pipe_resource *texture = NULL; static struct pipe_sampler_view *sv = NULL; static void *sampler = NULL; -static void *window = NULL; struct vertex { float position[4]; @@ -56,29 +37,6 @@ static struct vertex vertices[] = -static void set_viewport( float x, float y, - float width, float height, - float near, float far) -{ - float z = far; - float half_width = (float)width / 2.0f; - float half_height = (float)height / 2.0f; - float half_depth = ((float)far - (float)near) / 2.0f; - struct pipe_viewport_state vp; - - vp.scale[0] = half_width; - vp.scale[1] = half_height; - vp.scale[2] = half_depth; - vp.scale[3] = 1.0f; - - vp.translate[0] = half_width + x; - vp.translate[1] = half_height + y; - vp.translate[2] = half_depth + z; - vp.translate[3] = 0.0f; - - ctx->set_viewport_state( ctx, &vp ); -} - static void set_vertices( void ) { struct pipe_vertex_element ve[2]; @@ -92,18 +50,18 @@ static void set_vertices( void ) ve[1].src_offset = Offset(struct vertex, color); ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - handle = ctx->create_vertex_elements_state(ctx, 2, ve); - ctx->bind_vertex_elements_state(ctx, handle); + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); vbuf.stride = sizeof( struct vertex ); vbuf.buffer_offset = 0; - vbuf.buffer = screen->user_buffer_create(screen, + vbuf.buffer = info.screen->user_buffer_create(info.screen, vertices, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER); - ctx->set_vertex_buffers(ctx, 1, &vbuf); + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); } static void set_vertex_shader( void ) @@ -119,8 +77,8 @@ static void set_vertex_shader( void ) " 1: MOV OUT[0], IN[0]\n" " 2: END\n"; - handle = graw_parse_vertex_shader(ctx, text); - ctx->bind_vs_state(ctx, handle); + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); } static void set_fragment_shader( void ) @@ -136,8 +94,8 @@ static void set_fragment_shader( void ) " 1: MOV OUT[0], TEMP[0]\n" " 2: END\n"; - handle = graw_parse_fragment_shader(ctx, text); - ctx->bind_fs_state(ctx, handle); + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); } @@ -145,23 +103,20 @@ static void draw( void ) { union pipe_color_union clear_color = { {.5,.5,.5,1} }; - ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); - util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4); - ctx->flush(ctx, NULL); + info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4); + info.ctx->flush(info.ctx, NULL); - graw_save_surface_to_file(ctx, surf, NULL); + graw_save_surface_to_file(info.ctx, info.color_surf[0], NULL); - screen->flush_frontbuffer(screen, rttex, 0, 0, window); + graw_util_flush_front(&info); } + #define SIZE 16 static void init_tex( void ) { - struct pipe_sampler_view sv_template; - struct pipe_sampler_state sampler_desc; - struct pipe_resource templat; - struct pipe_box box; ubyte tex2d[SIZE][SIZE][4]; int s, t; @@ -206,168 +161,25 @@ static void init_tex( void ) tex2d[1][1][3] = 255; #endif - templat.target = PIPE_TEXTURE_2D; - templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; - templat.width0 = SIZE; - templat.height0 = SIZE; - templat.depth0 = 1; - templat.array_size = 1; - templat.last_level = 0; - templat.nr_samples = 1; - templat.bind = PIPE_BIND_SAMPLER_VIEW; - - - samptex = screen->resource_create(screen, - &templat); - if (samptex == NULL) - exit(4); - - u_box_2d(0,0,SIZE,SIZE, &box); - - ctx->transfer_inline_write(ctx, - samptex, - 0, - PIPE_TRANSFER_WRITE, - &box, - tex2d, - sizeof tex2d[0], - sizeof tex2d); - - /* Possibly read back & compare against original data: - */ - if (0) - { - struct pipe_transfer *t; - uint32_t *ptr; - t = pipe_get_transfer(ctx, samptex, - 0, 0, /* level, layer */ - PIPE_TRANSFER_READ, - 0, 0, SIZE, SIZE); /* x, y, width, height */ - - ptr = ctx->transfer_map(ctx, t); - - if (memcmp(ptr, tex2d, sizeof tex2d) != 0) { - assert(0); - exit(9); - } - - ctx->transfer_unmap(ctx, t); + texture = graw_util_create_tex2d(&info, SIZE, SIZE, + PIPE_FORMAT_B8G8R8A8_UNORM, tex2d); - ctx->transfer_destroy(ctx, t); - } + sv = graw_util_create_simple_sampler_view(&info, texture); + info.ctx->set_fragment_sampler_views(info.ctx, 1, &sv); - memset(&sv_template, 0, sizeof sv_template); - sv_template.format = samptex->format; - sv_template.texture = samptex; - sv_template.swizzle_r = 0; - sv_template.swizzle_g = 1; - sv_template.swizzle_b = 2; - sv_template.swizzle_a = 3; - sv = ctx->create_sampler_view(ctx, samptex, &sv_template); - if (sv == NULL) - exit(5); - - ctx->set_fragment_sampler_views(ctx, 1, &sv); - - - memset(&sampler_desc, 0, sizeof sampler_desc); - sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT; - sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT; - sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT; - sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST; - sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE; - sampler_desc.compare_func = 0; - sampler_desc.normalized_coords = 1; - sampler_desc.max_anisotropy = 0; - - sampler = ctx->create_sampler_state(ctx, &sampler_desc); - if (sampler == NULL) - exit(6); - - ctx->bind_fragment_sampler_states(ctx, 1, &sampler); - + sampler = graw_util_create_simple_sampler(&info, + PIPE_TEX_WRAP_REPEAT, + PIPE_TEX_FILTER_NEAREST); + info.ctx->bind_fragment_sampler_states(info.ctx, 1, &sampler); } + static void init( void ) { - struct pipe_framebuffer_state fb; - struct pipe_resource templat; - struct pipe_surface surf_tmpl; - int i; - - /* It's hard to say whether window or screen should be created - * first. Different environments would prefer one or the other. - * - * Also, no easy way of querying supported formats if the screen - * cannot be created first. - */ - for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { - screen = graw_create_window_and_screen(0, 0, 300, 300, - formats[i], - &window); - if (window && screen) - break; - } - if (!screen || !window) { - fprintf(stderr, "Unable to create window\n"); + if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE)) exit(1); - } - - ctx = screen->context_create(screen, NULL); - if (ctx == NULL) - exit(3); - - templat.target = PIPE_TEXTURE_2D; - templat.format = formats[i]; - templat.width0 = WIDTH; - templat.height0 = HEIGHT; - templat.depth0 = 1; - templat.array_size = 1; - templat.last_level = 0; - templat.nr_samples = 1; - templat.bind = (PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET); - - rttex = screen->resource_create(screen, - &templat); - if (rttex == NULL) - exit(4); - - surf_tmpl.format = templat.format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; - surf_tmpl.u.tex.level = 0; - surf_tmpl.u.tex.first_layer = 0; - surf_tmpl.u.tex.last_layer = 0; - surf = ctx->create_surface(ctx, rttex, &surf_tmpl); - if (surf == NULL) - exit(5); - - memset(&fb, 0, sizeof fb); - fb.nr_cbufs = 1; - fb.width = WIDTH; - fb.height = HEIGHT; - fb.cbufs[0] = surf; - - ctx->set_framebuffer_state(ctx, &fb); - - { - struct pipe_blend_state blend; - void *handle; - memset(&blend, 0, sizeof blend); - blend.rt[0].colormask = PIPE_MASK_RGBA; - handle = ctx->create_blend_state(ctx, &blend); - ctx->bind_blend_state(ctx, handle); - } - { - struct pipe_depth_stencil_alpha_state depthstencil; - void *handle; - memset(&depthstencil, 0, sizeof depthstencil); - handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); - ctx->bind_depth_stencil_alpha_state(ctx, handle); - } + graw_util_default_state(&info, FALSE); { struct pipe_rasterizer_state rasterizer; @@ -376,11 +188,11 @@ static void init( void ) rasterizer.cull_face = PIPE_FACE_NONE; rasterizer.gl_rasterization_rules = 1; rasterizer.depth_clip = 1; - handle = ctx->create_rasterizer_state(ctx, &rasterizer); - ctx->bind_rasterizer_state(ctx, handle); + handle = info.ctx->create_rasterizer_state(info.ctx, &rasterizer); + info.ctx->bind_rasterizer_state(info.ctx, handle); } - set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); + graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 1000); init_tex(); @@ -389,6 +201,7 @@ static void init( void ) set_fragment_shader(); } + static void args(int argc, char *argv[]) { int i; diff --git a/src/gallium/tests/graw/tex-srgb.c b/src/gallium/tests/graw/tex-srgb.c new file mode 100644 index 00000000000..8eaf0bd1ec7 --- /dev/null +++ b/src/gallium/tests/graw/tex-srgb.c @@ -0,0 +1,224 @@ +/* Test sRGB texturing. + */ + +#include "graw_util.h" + + +static const int WIDTH = 600; +static const int HEIGHT = 300; + +static struct graw_info info; + +static struct pipe_resource *texture; +static struct pipe_sampler_view *linear_sv, *srgb_sv; + + +struct vertex { + float position[4]; + float color[4]; +}; + +static struct vertex vertices1[] = +{ + { { -0.1, -0.9, 0.0, 1.0 }, + { 1, 1, 0, 1 } }, + + { { -0.1, 0.9, 0.0, 1.0 }, + { 1, 0, 0, 1 } }, + + { {-0.9, 0.9, 0.0, 1.0 }, + { 0, 0, 0, 1 } }, + + { {-0.9, -0.9, 0.0, 1.0 }, + { 0, 1, 0, 1 } }, +}; + + +static struct vertex vertices2[] = +{ + { { 0.9, -0.9, 0.0, 1.0 }, + { 1, 1, 0, 1 } }, + + { { 0.9, 0.9, 0.0, 1.0 }, + { 1, 0, 0, 1 } }, + + { { 0.1, 0.9, 0.0, 1.0 }, + { 0, 0, 0, 1 } }, + + { { 0.1, -0.9, 0.0, 1.0 }, + { 0, 1, 0, 1 } }, +}; + + + + +static void +set_vertices(struct vertex *verts, unsigned num_verts) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); + + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = info.screen->user_buffer_create(info.screen, + verts, + num_verts *sizeof(struct vertex), + PIPE_BIND_VERTEX_BUFFER); + + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); +} + +static void set_vertex_shader( void ) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[1], IN[1]\n" + " 1: MOV OUT[0], IN[0]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); +} + +static void set_fragment_shader( void ) +{ + void *handle; + const char *text = + "FRAG\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR\n" + "DCL TEMP[0]\n" + "DCL SAMP[0]\n" + " 0: TXP TEMP[0], IN[0], SAMP[0], 2D\n" + " 1: MOV OUT[0], TEMP[0]\n" + " 2: END\n"; + + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); +} + + +static void draw( void ) +{ + union pipe_color_union clear_color; + + clear_color.f[0] = 0.5; + clear_color.f[1] = 0.5; + clear_color.f[2] = 0.5; + clear_color.f[3] = 1.0; + + info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); + + info.ctx->set_fragment_sampler_views(info.ctx, 1, &linear_sv); + set_vertices(vertices1, 4); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4); + + info.ctx->set_fragment_sampler_views(info.ctx, 1, &srgb_sv); + set_vertices(vertices2, 4); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4); + + info.ctx->flush(info.ctx, NULL); + + graw_util_flush_front(&info); +} + + +static void init_tex( void ) +{ +#define SIZE 64 + ubyte tex2d[SIZE][SIZE][4]; + int s, t; + + for (s = 0; s < SIZE; s++) { + for (t = 0; t < SIZE; t++) { + tex2d[t][s][0] = 0; + tex2d[t][s][1] = s * 255 / SIZE; + tex2d[t][s][2] = t * 255 / SIZE; + tex2d[t][s][3] = 255; + } + } + + texture = graw_util_create_tex2d(&info, SIZE, SIZE, + PIPE_FORMAT_B8G8R8A8_UNORM, tex2d); + + { + void *sampler; + sampler = graw_util_create_simple_sampler(&info, + PIPE_TEX_WRAP_REPEAT, + PIPE_TEX_FILTER_NEAREST); + info.ctx->bind_fragment_sampler_states(info.ctx, 1, &sampler); + } + + /* linear sampler view */ + { + struct pipe_sampler_view sv_temp; + memset(&sv_temp, 0, sizeof sv_temp); + sv_temp.format = PIPE_FORMAT_B8G8R8A8_UNORM; + sv_temp.texture = texture; + sv_temp.swizzle_r = PIPE_SWIZZLE_RED; + sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN; + sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE; + sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA; + linear_sv = info.ctx->create_sampler_view(info.ctx, texture, &sv_temp); + if (linear_sv == NULL) + exit(0); + } + + /* srgb sampler view */ + { + struct pipe_sampler_view sv_temp; + memset(&sv_temp, 0, sizeof sv_temp); + sv_temp.format = PIPE_FORMAT_B8G8R8A8_SRGB; + sv_temp.texture = texture; + sv_temp.swizzle_r = PIPE_SWIZZLE_RED; + sv_temp.swizzle_g = PIPE_SWIZZLE_GREEN; + sv_temp.swizzle_b = PIPE_SWIZZLE_BLUE; + sv_temp.swizzle_a = PIPE_SWIZZLE_ALPHA; + srgb_sv = info.ctx->create_sampler_view(info.ctx, texture, &sv_temp); + if (srgb_sv == NULL) + exit(0); + } +#undef SIZE +} + +static void init( void ) +{ + if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE)) + exit(1); + + graw_util_default_state(&info, FALSE); + + graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 10000); + + init_tex(); + + set_vertex_shader(); + set_fragment_shader(); +} + + +int main( int argc, char *argv[] ) +{ + init(); + + graw_set_display_func( draw ); + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/tex-swizzle.c b/src/gallium/tests/graw/tex-swizzle.c new file mode 100644 index 00000000000..80a96087e78 --- /dev/null +++ b/src/gallium/tests/graw/tex-swizzle.c @@ -0,0 +1,226 @@ +/* Test texture swizzles */ + +#include + +#include "graw_util.h" + + +static struct graw_info info; + +static struct pipe_resource *texture = NULL; +static struct pipe_sampler_view *sv = NULL; +static void *sampler = NULL; + +static const int WIDTH = 300; +static const int HEIGHT = 300; + +struct vertex { + float position[4]; + float color[4]; +}; + +static struct vertex vertices[] = +{ + { { 0.9, -0.9, 0.0, 1.0 }, + { 1, 0, 0, 1 } }, + + { { 0.9, 0.9, 0.0, 1.0 }, + { 1, 1, 0, 1 } }, + + { {-0.9, 0.9, 0.0, 1.0 }, + { 0, 1, 0, 1 } }, + + { {-0.9, -0.9, 0.0, 1.0 }, + { 0, 0, 0, 1 } }, +}; + + +static void set_vertices(void) +{ + struct pipe_vertex_element ve[2]; + struct pipe_vertex_buffer vbuf; + void *handle; + + memset(ve, 0, sizeof ve); + + ve[0].src_offset = Offset(struct vertex, position); + ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + ve[1].src_offset = Offset(struct vertex, color); + ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); + + + vbuf.stride = sizeof(struct vertex); + vbuf.buffer_offset = 0; + vbuf.buffer = info.screen->user_buffer_create(info.screen, + vertices, + sizeof(vertices), + PIPE_BIND_VERTEX_BUFFER); + + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); +} + +static void set_vertex_shader(void) +{ + void *handle; + const char *text = + "VERT\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC[0]\n" + " 0: MOV OUT[1], IN[1]\n" + " 1: MOV OUT[0], IN[0]\n" + " 2: END\n"; + + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); +} + +static void set_fragment_shader(void) +{ + void *handle; + const char *text = + "FRAG\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR\n" + "DCL SAMP[0]\n" + " 0: TXP OUT[0], IN[0], SAMP[0], 2D\n" + " 2: END\n"; + + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); +} + + +static void draw(void) +{ + union pipe_color_union clear_color; + + clear_color.f[0] = 0.5; + clear_color.f[1] = 0.5; + clear_color.f[2] = 0.5; + clear_color.f[3] = 1.0; + + info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); + util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4); + info.ctx->flush(info.ctx, NULL); + + graw_util_flush_front(&info); +} + + + +static void +init_tex(const unsigned swizzle[4]) +{ +#define SIZE 256 + struct pipe_sampler_view sv_template; + ubyte tex2d[SIZE][SIZE][4]; + int s, t; + + for (s = 0; s < SIZE; s++) { + for (t = 0; t < SIZE; t++) { + tex2d[t][s][0] = 0; /*B*/ + tex2d[t][s][1] = t; /*G*/ + tex2d[t][s][2] = s; /*R*/ + tex2d[t][s][3] = 1; /*A*/ + } + } + + texture = graw_util_create_tex2d(&info, SIZE, SIZE, + PIPE_FORMAT_B8G8R8A8_UNORM, tex2d); + + memset(&sv_template, 0, sizeof sv_template); + sv_template.format = texture->format; + sv_template.texture = texture; + sv_template.swizzle_r = swizzle[0]; + sv_template.swizzle_g = swizzle[1]; + sv_template.swizzle_b = swizzle[2]; + sv_template.swizzle_a = swizzle[3]; + sv = info.ctx->create_sampler_view(info.ctx, texture, &sv_template); + if (sv == NULL) + exit(5); + + info.ctx->set_fragment_sampler_views(info.ctx, 1, &sv); + + sampler = graw_util_create_simple_sampler(&info, + PIPE_TEX_WRAP_REPEAT, + PIPE_TEX_FILTER_NEAREST); + + info.ctx->bind_fragment_sampler_states(info.ctx, 1, &sampler); +#undef SIZE +} + + +static void +init(const unsigned swizzle[4]) +{ + if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE)) + exit(1); + + graw_util_default_state(&info, FALSE); + + graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 10000); + + init_tex(swizzle); + + set_vertices(); + set_vertex_shader(); + set_fragment_shader(); +} + + +static unsigned +char_to_swizzle(char c) +{ + switch (c) { + case 'r': + return PIPE_SWIZZLE_RED; + case 'g': + return PIPE_SWIZZLE_GREEN; + case 'b': + return PIPE_SWIZZLE_BLUE; + case 'a': + return PIPE_SWIZZLE_ALPHA; + case '0': + return PIPE_SWIZZLE_ZERO; + case '1': + return PIPE_SWIZZLE_ONE; + default: + return PIPE_SWIZZLE_RED; + } +} + + +int main(int argc, char *argv[]) +{ + const char swizzle_names[] = "rgba01"; + uint swizzle[4]; + int i; + + swizzle[0] = PIPE_SWIZZLE_RED; + swizzle[1] = PIPE_SWIZZLE_GREEN; + swizzle[2] = PIPE_SWIZZLE_BLUE; + swizzle[3] = PIPE_SWIZZLE_ALPHA; + + for (i = 1; i < argc; i++) { + swizzle[i-1] = char_to_swizzle(argv[i][0]); + } + + printf("Example:\n"); + printf(" tex-swizzle r 0 g 1\n"); + printf("Current swizzle = "); + for (i = 0; i < 4; i++) { + printf("%c", swizzle_names[swizzle[i]]); + } + printf("\n"); + + init(swizzle); + + graw_set_display_func(draw); + graw_main_loop(); + return 0; +} diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c index fc5d66ad18f..75fa88cae9e 100644 --- a/src/gallium/tests/graw/tri.c +++ b/src/gallium/tests/graw/tri.c @@ -3,36 +3,22 @@ */ #include +#include "graw_util.h" -#include "state_tracker/graw.h" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "pipe/p_defines.h" - -#include "util/u_memory.h" /* Offset() */ -#include "util/u_draw_quad.h" - -enum pipe_format formats[] = { - PIPE_FORMAT_R8G8B8A8_UNORM, - PIPE_FORMAT_B8G8R8A8_UNORM, - PIPE_FORMAT_NONE -}; +static struct graw_info info; static const int WIDTH = 300; static const int HEIGHT = 300; -static struct pipe_screen *screen = NULL; -static struct pipe_context *ctx = NULL; -static struct pipe_surface *surf = NULL; -static struct pipe_resource *tex = NULL; -static void *window = NULL; struct vertex { float position[4]; float color[4]; }; +static boolean FlatShade = FALSE; + + static struct vertex vertices[3] = { { @@ -50,31 +36,6 @@ static struct vertex vertices[3] = }; - - -static void set_viewport( float x, float y, - float width, float height, - float near, float far) -{ - float z = far; - float half_width = (float)width / 2.0f; - float half_height = (float)height / 2.0f; - float half_depth = ((float)far - (float)near) / 2.0f; - struct pipe_viewport_state vp; - - vp.scale[0] = half_width; - vp.scale[1] = half_height; - vp.scale[2] = half_depth; - vp.scale[3] = 1.0f; - - vp.translate[0] = half_width + x; - vp.translate[1] = half_height + y; - vp.translate[2] = half_depth + z; - vp.translate[3] = 0.0f; - - ctx->set_viewport_state( ctx, &vp ); -} - static void set_vertices( void ) { struct pipe_vertex_element ve[2]; @@ -88,20 +49,21 @@ static void set_vertices( void ) ve[1].src_offset = Offset(struct vertex, color); ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - handle = ctx->create_vertex_elements_state(ctx, 2, ve); - ctx->bind_vertex_elements_state(ctx, handle); + handle = info.ctx->create_vertex_elements_state(info.ctx, 2, ve); + info.ctx->bind_vertex_elements_state(info.ctx, handle); vbuf.stride = sizeof( struct vertex ); vbuf.buffer_offset = 0; - vbuf.buffer = screen->user_buffer_create(screen, - vertices, - sizeof(vertices), - PIPE_BIND_VERTEX_BUFFER); + vbuf.buffer = info.screen->user_buffer_create(info.screen, + vertices, + sizeof(vertices), + PIPE_BIND_VERTEX_BUFFER); - ctx->set_vertex_buffers(ctx, 1, &vbuf); + info.ctx->set_vertex_buffers(info.ctx, 1, &vbuf); } + static void set_vertex_shader( void ) { void *handle; @@ -115,10 +77,11 @@ static void set_vertex_shader( void ) " 1: MOV OUT[0], IN[0]\n" " 2: END\n"; - handle = graw_parse_vertex_shader(ctx, text); - ctx->bind_vs_state(ctx, handle); + handle = graw_parse_vertex_shader(info.ctx, text); + info.ctx->bind_vs_state(info.ctx, handle); } + static void set_fragment_shader( void ) { void *handle; @@ -129,8 +92,8 @@ static void set_fragment_shader( void ) " 0: MOV OUT[0], IN[0]\n" " 1: END\n"; - handle = graw_parse_fragment_shader(ctx, text); - ctx->bind_fs_state(ctx, handle); + handle = graw_parse_fragment_shader(info.ctx, text); + info.ctx->bind_fs_state(info.ctx, handle); } @@ -138,100 +101,22 @@ static void draw( void ) { union pipe_color_union clear_color = { {1,0,1,1} }; - ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); - util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3); - ctx->flush(ctx, NULL); + info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); + util_draw_arrays(info.ctx, PIPE_PRIM_TRIANGLES, 0, 3); + info.ctx->flush(info.ctx, NULL); - graw_save_surface_to_file(ctx, surf, NULL); + graw_save_surface_to_file(info.ctx, info.color_surf[0], NULL); - screen->flush_frontbuffer(screen, tex, 0, 0, window); + graw_util_flush_front(&info); } static void init( void ) { - struct pipe_framebuffer_state fb; - struct pipe_resource templat; - struct pipe_surface surf_tmpl; - int i; - - /* It's hard to say whether window or screen should be created - * first. Different environments would prefer one or the other. - * - * Also, no easy way of querying supported formats if the screen - * cannot be created first. - */ - for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { - screen = graw_create_window_and_screen(0, 0, 300, 300, - formats[i], - &window); - if (window && screen) - break; - } - if (!screen || !window) { - fprintf(stderr, "Unable to create window\n"); + if (!graw_util_create_window(&info, WIDTH, HEIGHT, 1, FALSE)) exit(1); - } - - ctx = screen->context_create(screen, NULL); - if (ctx == NULL) { - fprintf(stderr, "Unable to create context!\n"); - exit(3); - } - templat.target = PIPE_TEXTURE_2D; - templat.format = formats[i]; - templat.width0 = WIDTH; - templat.height0 = HEIGHT; - templat.depth0 = 1; - templat.array_size = 1; - templat.last_level = 0; - templat.nr_samples = 1; - templat.bind = (PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET); - - tex = screen->resource_create(screen, - &templat); - if (tex == NULL) { - fprintf(stderr, "Unable to create screen texture!\n"); - exit(4); - } - - surf_tmpl.format = templat.format; - surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; - surf_tmpl.u.tex.level = 0; - surf_tmpl.u.tex.first_layer = 0; - surf_tmpl.u.tex.last_layer = 0; - surf = ctx->create_surface(ctx, tex, &surf_tmpl); - if (surf == NULL) { - fprintf(stderr, "Unable to create tex surface!\n"); - exit(5); - } - - memset(&fb, 0, sizeof fb); - fb.nr_cbufs = 1; - fb.width = WIDTH; - fb.height = HEIGHT; - fb.cbufs[0] = surf; - - ctx->set_framebuffer_state(ctx, &fb); - - { - struct pipe_blend_state blend; - void *handle; - memset(&blend, 0, sizeof blend); - blend.rt[0].colormask = PIPE_MASK_RGBA; - handle = ctx->create_blend_state(ctx, &blend); - ctx->bind_blend_state(ctx, handle); - } - - { - struct pipe_depth_stencil_alpha_state depthstencil; - void *handle; - memset(&depthstencil, 0, sizeof depthstencil); - handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); - ctx->bind_depth_stencil_alpha_state(ctx, handle); - } + graw_util_default_state(&info, FALSE); { struct pipe_rasterizer_state rasterizer; @@ -239,12 +124,15 @@ static void init( void ) memset(&rasterizer, 0, sizeof rasterizer); rasterizer.cull_face = PIPE_FACE_NONE; rasterizer.gl_rasterization_rules = 1; + rasterizer.flatshade = FlatShade; rasterizer.depth_clip = 1; - handle = ctx->create_rasterizer_state(ctx, &rasterizer); - ctx->bind_rasterizer_state(ctx, handle); + handle = info.ctx->create_rasterizer_state(info.ctx, &rasterizer); + info.ctx->bind_rasterizer_state(info.ctx, handle); } - set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); + + graw_util_viewport(&info, 0, 0, WIDTH, HEIGHT, 30, 1000); + set_vertices(); set_vertex_shader(); set_fragment_shader(); @@ -254,11 +142,18 @@ static void args(int argc, char *argv[]) { int i; - for (i = 1; i < argc;) { + for (i = 1; i < argc; ) { if (graw_parse_args(&i, argc, argv)) { - continue; + /* ok */ + } + else if (strcmp(argv[i], "-f") == 0) { + FlatShade = TRUE; + i++; + } + else { + printf("Invalid arg %s\n", argv[i]); + exit(1); } - exit(1); } }