tests/graw: Add a bunch of tests.
authorJosé Fonseca <jfonseca@vmware.com>
Wed, 22 Feb 2012 15:22:31 +0000 (15:22 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Wed, 22 Feb 2012 15:22:31 +0000 (15:22 +0000)
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.

src/gallium/tests/graw/SConscript
src/gallium/tests/graw/fs-fragcoord.c [new file with mode: 0644]
src/gallium/tests/graw/fs-frontface.c [new file with mode: 0644]
src/gallium/tests/graw/fs-write-z.c [new file with mode: 0644]
src/gallium/tests/graw/graw_util.h [new file with mode: 0644]
src/gallium/tests/graw/occlusion-query.c [new file with mode: 0644]
src/gallium/tests/graw/quad-tex.c
src/gallium/tests/graw/tex-srgb.c [new file with mode: 0644]
src/gallium/tests/graw/tex-swizzle.c [new file with mode: 0644]
src/gallium/tests/graw/tri.c

index ad44d54c855d0cfa869cab7d116c38686be93491..1fd2b532f403685411d50389b8ed1adfb3573f5c 100644 (file)
@@ -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 (file)
index 0000000..471acbb
--- /dev/null
@@ -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;
+}
diff --git a/src/gallium/tests/graw/fs-frontface.c b/src/gallium/tests/graw/fs-frontface.c
new file mode 100644 (file)
index 0000000..e725255
--- /dev/null
@@ -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;
+}
diff --git a/src/gallium/tests/graw/fs-write-z.c b/src/gallium/tests/graw/fs-write-z.c
new file mode 100644 (file)
index 0000000..186e3ec
--- /dev/null
@@ -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;
+}
diff --git a/src/gallium/tests/graw/graw_util.h b/src/gallium/tests/graw/graw_util.h
new file mode 100644 (file)
index 0000000..9250f0b
--- /dev/null
@@ -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 (file)
index 0000000..5c4bc8c
--- /dev/null
@@ -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;
+}
index 96c6f3fdc8e31cb29f6f79c2c4666306c7d8664d..9f81ad593ae06a7194e5acb0f5eca41732cdc0bb 100644 (file)
@@ -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;
diff --git a/src/gallium/tests/graw/tex-srgb.c b/src/gallium/tests/graw/tex-srgb.c
new file mode 100644 (file)
index 0000000..8eaf0bd
--- /dev/null
@@ -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 (file)
index 0000000..80a9608
--- /dev/null
@@ -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;
+}
index fc5d66ad18fda694a6b499e00ffd9fceeaba70b1..75fa88cae9e5c98f0748c26655df9a34b1d9e3f9 100644 (file)
@@ -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);
    }
 }