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.tags/i965-primitive-restart-v2
| @@ -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: | |||
| @@ -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 <stdio.h> | |||
| #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; | |||
| } | |||
| @@ -0,0 +1,206 @@ | |||
| /* Test the TGSI_SEMANTIC_FACE fragment shader input. | |||
| */ | |||
| #include <stdio.h> | |||
| #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; | |||
| } | |||
| @@ -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 <stdio.h> | |||
| #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; | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -0,0 +1,242 @@ | |||
| /* Test gallium occlusion queries. | |||
| */ | |||
| #include <stdio.h> | |||
| #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; | |||
| } | |||
| @@ -2,36 +2,17 @@ | |||
| * any utility code, just the graw interface and gallium. | |||
| */ | |||
| #include <stdio.h> | |||
| #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; | |||
| @@ -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; | |||
| } | |||
| @@ -0,0 +1,226 @@ | |||
| /* Test texture swizzles */ | |||
| #include <stdio.h> | |||
| #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; | |||
| } | |||
| @@ -3,36 +3,22 @@ | |||
| */ | |||
| #include <stdio.h> | |||
| #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); | |||
| } | |||
| } | |||