summaryrefslogtreecommitdiffstats
path: root/src/gallium/tests
diff options
context:
space:
mode:
authorThomas Balling Sørensen <tball@tball-laptop.(none)>2010-10-05 12:04:08 +0200
committerThomas Balling Sørensen <tball@tball-laptop.(none)>2010-10-05 12:04:08 +0200
commit1218430e1200a08cd64b6555d3fd1fd0274ad9e5 (patch)
treee060fb27b8388a4bd237ca39fc20f1675c5e367c /src/gallium/tests
parent63b1525cf0a50e3d31328c3b56355a86056e4c05 (diff)
parentbf21b7006c63c3dc47045c22d4f372dfe6c7ce67 (diff)
Merge branch 'master' into pipe-video
Conflicts: configs/linux-dri configure.ac src/gallium/drivers/nvfx/Makefile src/gallium/include/pipe/p_defines.h src/gallium/include/pipe/p_screen.h src/gallium/include/state_tracker/dri1_api.h src/gallium/include/state_tracker/drm_api.h src/gallium/tests/python/samples/tri.py src/gallium/tests/trivial/Makefile src/gallium/tests/unit/Makefile src/gallium/tests/unit/SConscript src/gallium/tests/unit/u_format_test.c src/gallium/winsys/nouveau/drm/nouveau_drm_api.c
Diffstat (limited to 'src/gallium/tests')
-rw-r--r--src/gallium/tests/graw/SConscript37
-rw-r--r--src/gallium/tests/graw/clear.c (renamed from src/gallium/tests/raw/clear.c)80
l---------src/gallium/tests/graw/fragment-shader1
-rw-r--r--src/gallium/tests/graw/fs-test.c556
-rw-r--r--src/gallium/tests/graw/geometry-shader/add-mix.txt23
-rw-r--r--src/gallium/tests/graw/geometry-shader/add.txt23
-rw-r--r--src/gallium/tests/graw/geometry-shader/line.txt28
-rw-r--r--src/gallium/tests/graw/geometry-shader/mov-cb-2d.txt24
-rw-r--r--src/gallium/tests/graw/geometry-shader/mov.txt23
-rw-r--r--src/gallium/tests/graw/geometry-shader/multi-line.txt42
-rw-r--r--src/gallium/tests/graw/gs-test.c624
-rw-r--r--src/gallium/tests/graw/quad-tex.c403
-rw-r--r--src/gallium/tests/graw/shader-leak.c266
-rw-r--r--src/gallium/tests/graw/tri-gs.c268
-rw-r--r--src/gallium/tests/graw/tri-instanced.c345
-rw-r--r--src/gallium/tests/graw/tri.c263
l---------src/gallium/tests/graw/vertex-shader1
-rw-r--r--src/gallium/tests/graw/vs-test.c508
-rwxr-xr-xsrc/gallium/tests/python/retrace/interpreter.py60
-rw-r--r--src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-2d.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/fragment-shader/frag-kil.sh18
-rw-r--r--src/gallium/tests/python/tests/regress/fragment-shader/frag-mad-immx.sh10
-rw-r--r--src/gallium/tests/python/tests/regress/fragment-shader/frag-tempx.sh14
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-abs.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-add.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-arl.sh2
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-arr.sh2
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-1d.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-2d.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-dp3.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-dp4.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-dst.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-ex2.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-flr.sh2
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-frc.sh2
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-lg2.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-lit.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-lrp.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-mad.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-max.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-min.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-mov.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-mul.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-rcp.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-rsq.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-sge.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-slt.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-abs.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-neg.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-swz.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-sub.sh4
-rw-r--r--src/gallium/tests/python/tests/regress/vertex-shader/vert-xpd.sh4
-rwxr-xr-xsrc/gallium/tests/python/tests/surface_copy.py7
-rwxr-xr-xsrc/gallium/tests/python/tests/texture_blit.py20
-rwxr-xr-xsrc/gallium/tests/python/tests/texture_transfer.py7
-rw-r--r--src/gallium/tests/raw/SConscript17
-rw-r--r--src/gallium/tests/trivial/quad-tex.c27
-rw-r--r--src/gallium/tests/trivial/tri.c25
-rw-r--r--src/gallium/tests/unit/translate_test.c310
-rw-r--r--src/gallium/tests/unit/u_format_compatible_test.c76
61 files changed, 4039 insertions, 183 deletions
diff --git a/src/gallium/tests/graw/SConscript b/src/gallium/tests/graw/SConscript
new file mode 100644
index 00000000000..ffde61965b4
--- /dev/null
+++ b/src/gallium/tests/graw/SConscript
@@ -0,0 +1,37 @@
+Import('*')
+
+try:
+ graw
+except NameError:
+ print 'warning: graw library not avaiable: skipping build of graw test'
+ Return()
+
+env = env.Clone()
+
+env.Prepend(LIBPATH = [graw.dir])
+env.Prepend(LIBS = ['graw'] + gallium)
+
+if platform in ('freebsd8', 'sunos5'):
+ env.Append(LIBS = ['m'])
+
+if platform == 'freebsd8':
+ env.Append(LIBS = ['pthread'])
+
+progs = [
+ 'clear',
+ 'tri',
+ 'tri-instanced',
+ 'quad-tex',
+ 'fs-test',
+ 'vs-test',
+ 'gs-test',
+ 'shader-leak',
+ 'tri-gs',
+]
+
+for prog in progs:
+ env.Program(
+ target = prog,
+ source = prog + '.c',
+ )
+
diff --git a/src/gallium/tests/raw/clear.c b/src/gallium/tests/graw/clear.c
index 706e3be3728..ce52a93aa1b 100644
--- a/src/gallium/tests/raw/clear.c
+++ b/src/gallium/tests/graw/clear.c
@@ -7,7 +7,6 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
-#include <unistd.h> /* for sleep() */
#include "util/u_debug.h" /* debug_dump_surface_bmp() */
@@ -20,33 +19,58 @@ enum pipe_format formats[] = {
static const int WIDTH = 300;
static const int HEIGHT = 300;
-int main( int argc, char *argv[] )
+struct pipe_screen *screen;
+struct pipe_context *ctx;
+struct pipe_surface *surf;
+static void *window = NULL;
+
+static void draw( void )
{
- struct pipe_screen *screen;
- struct pipe_context *pipe;
- struct pipe_surface *surf;
- struct pipe_framebuffer_state fb;
- struct pipe_texture *tex, templat;
- void *window = NULL;
float clear_color[4] = {1,0,1,1};
- int i;
- screen = graw_init();
- if (screen == NULL)
- exit(1);
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource *tex, templat;
+ 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;
window == NULL && formats[i] != PIPE_FORMAT_NONE;
i++) {
- window = graw_create_window(0,0,300,300, formats[i]);
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
}
-
if (window == NULL)
exit(2);
- pipe = screen->context_create(screen, NULL);
- if (pipe == NULL)
+ ctx = screen->context_create(screen, NULL);
+ if (ctx == NULL)
exit(3);
templat.target = PIPE_TEXTURE_2D;
@@ -57,10 +81,10 @@ int main( int argc, char *argv[] )
templat.last_level = 0;
templat.nr_samples = 1;
templat.bind = (PIPE_BIND_RENDER_TARGET |
- PIPE_BIND_DISPLAY_TARGET);
+ PIPE_BIND_DISPLAY_TARGET);
tex = screen->resource_create(screen,
- &templat);
+ &templat);
if (tex == NULL)
exit(4);
@@ -76,20 +100,16 @@ int main( int argc, char *argv[] )
fb.height = HEIGHT;
fb.cbufs[0] = surf;
- pipe->set_framebuffer_state(pipe, &fb);
- pipe->clear(pipe, PIPE_CLEAR_COLOR, clear_color, 0, 0);
- pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+ ctx->set_framebuffer_state(ctx, &fb);
+}
- /* At the moment, libgraw includes/makes available all 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.
- */
- if (0)
- debug_dump_surface_bmp(pipe, "result.bmp", surf);
- screen->flush_frontbuffer(screen, surf, window);
- sleep(100);
+int main( int argc, char *argv[] )
+{
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
return 0;
}
diff --git a/src/gallium/tests/graw/fragment-shader b/src/gallium/tests/graw/fragment-shader
new file mode 120000
index 00000000000..c7dd0b7c6b2
--- /dev/null
+++ b/src/gallium/tests/graw/fragment-shader
@@ -0,0 +1 @@
+../python/tests/regress/fragment-shader \ No newline at end of file
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
new file mode 100644
index 00000000000..53fbb744d86
--- /dev/null
+++ b/src/gallium/tests/graw/fs-test.c
@@ -0,0 +1,556 @@
+/* Display a cleared blue window. This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#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 <stdio.h> /* for fread(), etc */
+
+#include "util/u_debug.h" /* debug_dump_surface_bmp() */
+#include "util/u_inlines.h"
+#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
+#include "util/u_box.h"
+
+static const char *filename = NULL;
+unsigned show_fps = 0;
+
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
+#ifndef WIN32
+ fprintf(stderr, "\n" );
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " -fps show frames per second\n");
+#endif
+}
+
+
+enum pipe_format formats[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_NONE
+};
+
+static const int WIDTH = 250;
+static const int HEIGHT = 250;
+
+static struct pipe_screen *screen = NULL;
+static struct pipe_context *ctx = NULL;
+static struct pipe_resource *rttex = NULL;
+static struct pipe_resource *constbuf1 = NULL;
+static struct pipe_resource *constbuf2 = NULL;
+static struct pipe_surface *surf = NULL;
+static struct pipe_sampler_view *sv = NULL;
+static void *sampler = NULL;
+static void *window = NULL;
+static struct pipe_resource *samptex = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+ float texcoord[4];
+};
+
+/* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension
+ * so that the final images are the same.
+ */
+static struct vertex vertices[] =
+{
+ { { 0.9, 0.9, 0.0, 1.0 },
+ { 0, 0, 1, 1 },
+ { 1, 1, 0, 1 } },
+
+ { { 0.9, -0.9, 0.0, 1.0 },
+ { 1, 0, 0, 1 },
+ { 1, -1, 0, 1 } },
+
+ { {-0.9, 0.0, 0.0, 1.0 },
+ { 0, 1, 0, 1 },
+ { -1, 0, 0, 1 } },
+};
+
+static float constants1[] =
+{ 0.4, 0, 0, 1,
+ 1, 1, 1, 1,
+ 2, 2, 2, 2,
+ 4, 8, 16, 32,
+
+ 3, 0, 0, 0,
+ 0, .5, 0, 0,
+ 1, 0, 0, 1,
+ 0, 0, 0, 1,
+
+ 1, 0, 0, 0.5,
+ 0, 1, 0, 0.5,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+};
+
+
+static float constants2[] =
+{ 1, 0, 0, 1,
+ 0, 1, 0, 1,
+ 0, 0, 1, 1,
+ 0, 0, 0, 0,
+
+ 1, 1, 0, 1,
+ 1, .5, 0, 1,
+ 1, 0, 0, 1,
+ 0, 0, 0, 1,
+
+ 1, 0, 0, 0.5,
+ 0, 1, 0, 0.5,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+};
+
+static void init_fs_constbuf( void )
+{
+ struct pipe_resource templat;
+ struct pipe_box box;
+
+ templat.target = PIPE_BUFFER;
+ templat.format = PIPE_FORMAT_R8_UNORM;
+ templat.width0 = sizeof(constants1);
+ templat.height0 = 1;
+ templat.depth0 = 1;
+ templat.last_level = 0;
+ templat.nr_samples = 1;
+ templat.bind = PIPE_BIND_CONSTANT_BUFFER;
+
+ constbuf1 = screen->resource_create(screen,
+ &templat);
+ if (constbuf1 == NULL)
+ exit(4);
+
+ constbuf2 = screen->resource_create(screen,
+ &templat);
+ if (constbuf2 == NULL)
+ exit(4);
+
+
+ {
+ u_box_2d(0,0,sizeof(constants1),1, &box);
+
+ ctx->transfer_inline_write(ctx,
+ constbuf1,
+ u_subresource(0,0),
+ PIPE_TRANSFER_WRITE,
+ &box,
+ constants1,
+ sizeof constants1,
+ sizeof constants1);
+
+
+ ctx->set_constant_buffer(ctx,
+ PIPE_SHADER_FRAGMENT, 0,
+ constbuf1);
+ }
+ {
+ u_box_2d(0,0,sizeof(constants2),1, &box);
+
+ ctx->transfer_inline_write(ctx,
+ constbuf2,
+ u_subresource(0,0),
+ PIPE_TRANSFER_WRITE,
+ &box,
+ constants2,
+ sizeof constants2,
+ sizeof constants2);
+
+
+ ctx->set_constant_buffer(ctx,
+ PIPE_SHADER_FRAGMENT, 1,
+ constbuf2);
+ }
+}
+
+
+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[3];
+ 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;
+ ve[2].src_offset = Offset(struct vertex, texcoord);
+ ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+
+ handle = ctx->create_vertex_elements_state(ctx, 3, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(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 IN[2]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], COLOR[0]\n"
+ "DCL OUT[2], GENERIC[0]\n"
+ " MOV OUT[0], IN[0]\n"
+ " MOV OUT[1], IN[1]\n"
+ " MOV OUT[2], IN[2]\n"
+ " END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( const char *filename )
+{
+ FILE *f;
+ char buf[50000];
+ void *handle;
+ int sz;
+
+ if ((f = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Couldn't open %s\n", filename);
+ exit(1);
+ }
+
+ sz = fread(buf, 1, sizeof(buf), f);
+ if (!feof(f)) {
+ printf("file too long\n");
+ exit(1);
+ }
+ printf("%.*s\n", sz, buf);
+ buf[sz] = 0;
+
+ handle = graw_parse_fragment_shader(ctx, buf);
+ ctx->bind_fs_state(ctx, handle);
+ fclose(f);
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {.1,.3,.5,0};
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+#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;
+
+#if (SIZE != 2)
+ for (s = 0; s < SIZE; s++) {
+ for (t = 0; t < SIZE; t++) {
+ if (0) {
+ int x = (s ^ t) & 1;
+ tex2d[t][s][0] = (x) ? 0 : 63;
+ tex2d[t][s][1] = (x) ? 0 : 128;
+ tex2d[t][s][2] = 0;
+ tex2d[t][s][3] = 0xff;
+ }
+ else {
+ int x = ((s ^ t) >> 2) & 1;
+ tex2d[t][s][0] = s*255/(SIZE-1);
+ tex2d[t][s][1] = t*255/(SIZE-1);
+ tex2d[t][s][2] = (x) ? 0 : 128;
+ tex2d[t][s][3] = 0xff;
+ }
+ }
+ }
+#else
+ tex2d[0][0][0] = 0;
+ tex2d[0][0][1] = 255;
+ tex2d[0][0][2] = 255;
+ tex2d[0][0][3] = 0;
+
+ tex2d[0][1][0] = 0;
+ tex2d[0][1][1] = 0;
+ tex2d[0][1][2] = 255;
+ tex2d[0][1][3] = 255;
+
+ tex2d[1][0][0] = 255;
+ tex2d[1][0][1] = 255;
+ tex2d[1][0][2] = 0;
+ tex2d[1][0][3] = 255;
+
+ tex2d[1][1][0] = 255;
+ tex2d[1][1][1] = 0;
+ tex2d[1][1][2] = 0;
+ 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.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,
+ u_subresource(0,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, 0, /* face, level, zslice */
+ 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);
+
+ ctx->transfer_destroy(ctx, t);
+ }
+
+ memset(&sv_template, 0, sizeof sv_template);
+ sv_template.format = samptex->format;
+ sv_template.texture = samptex;
+ sv_template.first_level = 0;
+ sv_template.last_level = 0;
+ 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);
+
+}
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,WIDTH,HEIGHT,
+ formats[i],
+ &window);
+ }
+
+ 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.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 = screen->get_tex_surface(screen, rttex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+
+ init_tex();
+ init_fs_constbuf();
+
+ set_vertices();
+ set_vertex_shader();
+ set_fragment_shader(filename);
+}
+
+static void args(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-fps") == 0) {
+ show_fps = 1;
+ }
+ else if (i == argc - 1) {
+ filename = argv[i];
+ }
+ else {
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ if (!filename) {
+ usage(argv[0]);
+ exit(1);
+ }
+}
+
+int main( int argc, char *argv[] )
+{
+ args(argc,argv);
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
+ return 0;
+}
diff --git a/src/gallium/tests/graw/geometry-shader/add-mix.txt b/src/gallium/tests/graw/geometry-shader/add-mix.txt
new file mode 100644
index 00000000000..63e689a5158
--- /dev/null
+++ b/src/gallium/tests/graw/geometry-shader/add-mix.txt
@@ -0,0 +1,23 @@
+GEOM
+PROPERTY GS_INPUT_PRIMITIVE TRIANGLES
+PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP
+DCL IN[][0], POSITION, CONSTANT
+DCL IN[][1], COLOR, CONSTANT
+DCL OUT[0], POSITION, CONSTANT
+DCL OUT[1], COLOR, CONSTANT
+
+MOV OUT[0], IN[0][0]
+ADD OUT[1], IN[0][1], IN[1][1]
+EMIT
+
+MOV OUT[0], IN[1][0]
+ADD OUT[1], IN[1][1], IN[2][1]
+EMIT
+
+MOV OUT[0], IN[2][0]
+ADD OUT[1], IN[2][1], IN[0][1]
+EMIT
+
+ENDPRIM
+
+END
diff --git a/src/gallium/tests/graw/geometry-shader/add.txt b/src/gallium/tests/graw/geometry-shader/add.txt
new file mode 100644
index 00000000000..d8c7c41e9bd
--- /dev/null
+++ b/src/gallium/tests/graw/geometry-shader/add.txt
@@ -0,0 +1,23 @@
+GEOM
+PROPERTY GS_INPUT_PRIMITIVE TRIANGLES
+PROPERTY GS_OUTPUT_PRIMITIVE LINE_STRIP
+DCL IN[][0], POSITION, CONSTANT
+DCL IN[][1], COLOR, CONSTANT
+DCL OUT[0], POSITION, CONSTANT
+DCL OUT[1], COLOR, CONSTANT
+
+MOV OUT[0], IN[0][0]
+ADD OUT[1], IN[0][1], IN[0][1]
+EMIT
+
+MOV OUT[0], IN[1][0]
+ADD OUT[1], IN[1][1], IN[1][1]
+EMIT
+
+MOV OUT[0], IN[2][0]
+ADD OUT[1], IN[2][1], IN[2][1]
+EMIT
+
+ENDPRIM
+
+END
diff --git a/src/gallium/tests/graw/geometry-shader/line.txt b/src/gallium/tests/graw/geometry-shader/line.txt
new file mode 100644
index 00000000000..8be3f7fd985
--- /dev/null
+++ b/src/gallium/tests/graw/geometry-shader/line.txt
@@ -0,0 +1,28 @@
+GEOM
+PROPERTY GS_INPUT_PRIMITIVE TRIANGLES
+PROPERTY GS_OUTPUT_PRIMITIVE LINE_STRIP
+PROPERTY GS_MAX_OUTPUT_VERTICES 4
+DCL IN[][0], POSITION, CONSTANT
+DCL IN[][1], COLOR, CONSTANT
+DCL OUT[0], POSITION, CONSTANT
+DCL OUT[1], COLOR, CONSTANT
+
+MOV OUT[0], IN[0][0]
+MOV OUT[1], IN[0][1]
+EMIT
+
+MOV OUT[0], IN[1][0]
+MOV OUT[1], IN[0][1]
+EMIT
+
+MOV OUT[0], IN[2][0]
+MOV OUT[1], IN[2][1]
+EMIT
+
+MOV OUT[0], IN[0][0]
+MOV OUT[1], IN[0][1]
+EMIT
+
+ENDPRIM
+
+END
diff --git a/src/gallium/tests/graw/geometry-shader/mov-cb-2d.txt b/src/gallium/tests/graw/geometry-shader/mov-cb-2d.txt
new file mode 100644
index 00000000000..058acfbcb5a
--- /dev/null
+++ b/src/gallium/tests/graw/geometry-shader/mov-cb-2d.txt
@@ -0,0 +1,24 @@
+GEOM
+PROPERTY GS_INPUT_PRIMITIVE TRIANGLES
+PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP
+DCL IN[][0], POSITION, CONSTANT
+DCL IN[][1], COLOR, CONSTANT
+DCL OUT[0], POSITION, CONSTANT
+DCL OUT[1], COLOR, CONSTANT
+DCL CONST[1][0..6]
+
+MOV OUT[0], IN[0][0]
+MOV OUT[1], CONST[1][0]
+EMIT
+
+MOV OUT[0], IN[1][0]
+MOV OUT[1], CONST[1][1]
+EMIT
+
+MOV OUT[0], IN[2][0]
+MOV OUT[1], CONST[1][4]
+EMIT
+
+ENDPRIM
+
+END
diff --git a/src/gallium/tests/graw/geometry-shader/mov.txt b/src/gallium/tests/graw/geometry-shader/mov.txt
new file mode 100644
index 00000000000..97150a5da45
--- /dev/null
+++ b/src/gallium/tests/graw/geometry-shader/mov.txt
@@ -0,0 +1,23 @@
+GEOM
+PROPERTY GS_INPUT_PRIMITIVE TRIANGLES
+PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP
+DCL IN[][0], POSITION, CONSTANT
+DCL IN[][1], COLOR, CONSTANT
+DCL OUT[0], POSITION, CONSTANT
+DCL OUT[1], COLOR, CONSTANT
+
+MOV OUT[0], IN[0][0]
+MOV OUT[1], IN[0][1]
+EMIT
+
+MOV OUT[0], IN[1][0]
+MOV OUT[1], IN[1][1]
+EMIT
+
+MOV OUT[0], IN[2][0]
+MOV OUT[1], IN[2][1]
+EMIT
+
+ENDPRIM
+
+END
diff --git a/src/gallium/tests/graw/geometry-shader/multi-line.txt b/src/gallium/tests/graw/geometry-shader/multi-line.txt
new file mode 100644
index 00000000000..0762d19cdd9
--- /dev/null
+++ b/src/gallium/tests/graw/geometry-shader/multi-line.txt
@@ -0,0 +1,42 @@
+GEOM
+PROPERTY GS_INPUT_PRIMITIVE TRIANGLES
+PROPERTY GS_OUTPUT_PRIMITIVE LINE_STRIP
+PROPERTY GS_MAX_OUTPUT_VERTICES 8
+DCL IN[][0], POSITION, CONSTANT
+DCL IN[][1], COLOR, CONSTANT
+DCL OUT[0], POSITION, CONSTANT
+DCL OUT[1], COLOR, CONSTANT
+DCL TEMP[0]
+
+MOV TEMP[0], IN[0][0]
+ADD TEMP[0].y, IN[0][0], IN[1][0]
+
+MOV OUT[0], TEMP[0]
+MOV OUT[1], IN[0][1]
+EMIT
+MOV OUT[0], IN[2][0]
+MOV OUT[1], IN[0][1]
+EMIT
+MOV OUT[0], IN[0][0]
+MOV OUT[1], IN[2][1]
+EMIT
+MOV OUT[0], TEMP[0]
+MOV OUT[1], IN[0][1]
+EMIT
+ENDPRIM
+
+MOV OUT[0], TEMP[0]
+MOV OUT[1], IN[0][1]
+EMIT
+MOV OUT[0], IN[2][0]
+MOV OUT[1], IN[0][1]
+EMIT
+MOV OUT[0], IN[1][0]
+MOV OUT[1], IN[2][1]
+EMIT
+MOV OUT[0], TEMP[0]
+MOV OUT[1], IN[0][1]
+EMIT
+ENDPRIM
+
+END
diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c
new file mode 100644
index 00000000000..62714900bd9
--- /dev/null
+++ b/src/gallium/tests/graw/gs-test.c
@@ -0,0 +1,624 @@
+/* Display a cleared blue window. This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#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 <stdio.h> /* for fread(), etc */
+
+#include "util/u_debug.h" /* debug_dump_surface_bmp() */
+#include "util/u_inlines.h"
+#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
+#include "util/u_box.h"
+
+static const char *filename = NULL;
+unsigned show_fps = 0;
+unsigned draw_strip = 0;
+
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
+#ifndef WIN32
+ fprintf(stderr, "\n" );
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " -fps show frames per second\n");
+ fprintf(stderr, " -strip renders a triangle strip\n");
+#endif
+}
+
+
+enum pipe_format formats[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_NONE
+};
+
+static const int WIDTH = 250;
+static const int HEIGHT = 250;
+
+static struct pipe_screen *screen = NULL;
+static struct pipe_context *ctx = NULL;
+static struct pipe_resource *rttex = NULL;
+static struct pipe_resource *constbuf1 = NULL;
+static struct pipe_resource *constbuf2 = NULL;
+static struct pipe_surface *surf = NULL;
+static struct pipe_sampler_view *sv = NULL;
+static void *sampler = NULL;
+static void *window = NULL;
+static struct pipe_resource *samptex = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+ float texcoord[4];
+ float generic[4];
+};
+
+/* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension
+ * so that the final images are the same.
+ */
+static struct vertex vertices[] =
+{
+ { { 0.9, 0.9, 0.0, 1.0 },
+ { 0, 0, 1, 1 },
+ { 1, 1, 0, 1 },
+ { 1, 0, 1, 0 }
+ },
+
+ { { 0.9, -0.9, 0.0, 1.0 },
+ { 1, 0, 0, 1 },
+ { 1, -1, 0, 1 },
+ { 0, 1, 0, 1 }
+ },
+
+ { {-0.9, 0.0, 0.0, 1.0 },
+ { 0, 1, 0, 1 },
+ { -1, 0, 0, 1 },
+ { 0, 0, 1, 1 }
+ },
+};
+
+static struct vertex vertices_strip[] =
+{
+ { { 0.9, 0.9, 0.0, 1.0 },
+ { 0, 0, 1, 1 },
+ { 1, 1, 0, 1 },
+ { 1, 0, 0, 1 }
+ },
+
+ { { 0.9, -0.9, 0.0, 1.0 },
+ { 1, 0, 0, 1 },
+ { 1, -1, 0, 1 },
+ { 0, 1, 0, 1 }
+ },
+
+ { {-0.9, 0.9, 0.0, 1.0 },
+ { 0, 1, 0, 1 },
+ { -1, 1, 0, 1 },
+ { 0, 0, 1, 1 }
+ },
+
+ { {-0.9, -0.9, 0.0, 1.0 },
+ { 1, 1, 0, 1 },
+ { -1, -1, 0, 1 },
+ { 1, 1, 0, 1 }
+ },
+};
+
+static float constants1[] =
+{ 0.4, 0, 0, 1,
+ 1, 1, 1, 1,
+ 2, 2, 2, 2,
+ 4, 8, 16, 32,
+
+ 3, 0, 0, 0,
+ 0, .5, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+
+ 1, 0, 0, 0.5,
+ 0, 1, 0, 0.5,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+};
+
+
+static float constants2[] =
+{ 1, 0, 0, 1,
+ 0, 1, 0, 1,
+ 0, 0, 1, 1,
+ 0, 0, 0, 1,
+
+ 1, 1, 0, 1,
+ 1, .5, 0, 1,
+ 0, 1, 1, 1,
+ 1, 0, 1, 1,
+
+ 1, 0, 0, 0.5,
+ 0, 1, 0, 0.5,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+};
+
+
+static void init_fs_constbuf( void )
+{
+ struct pipe_resource templat;
+ struct pipe_box box;
+
+ templat.target = PIPE_BUFFER;
+ templat.format = PIPE_FORMAT_R8_UNORM;
+ templat.width0 = sizeof(constants1);
+ templat.height0 = 1;
+ templat.depth0 = 1;
+ templat.last_level = 0;
+ templat.nr_samples = 1;
+ templat.bind = PIPE_BIND_CONSTANT_BUFFER;
+
+ constbuf1 = screen->resource_create(screen, &templat);
+ if (constbuf1 == NULL)
+ exit(4);
+ constbuf2 = screen->resource_create(screen, &templat);
+ if (constbuf2 == NULL)
+ exit(4);
+
+ {
+ u_box_2d(0,0,sizeof(constants1),1, &box);
+
+ ctx->transfer_inline_write(ctx,
+ constbuf1,
+ u_subresource(0,0),
+ PIPE_TRANSFER_WRITE,
+ &box,
+ constants1,
+ sizeof constants1,
+ sizeof constants1);
+
+
+ ctx->set_constant_buffer(ctx,
+ PIPE_SHADER_GEOMETRY, 0,
+ constbuf1);
+ }
+ {
+ u_box_2d(0,0,sizeof(constants2),1, &box);
+
+ ctx->transfer_inline_write(ctx,
+ constbuf2,
+ u_subresource(0,0),
+ PIPE_TRANSFER_WRITE,
+ &box,
+ constants2,
+ sizeof constants2,
+ sizeof constants2);
+
+
+ ctx->set_constant_buffer(ctx,
+ PIPE_SHADER_GEOMETRY, 1,
+ constbuf2);
+ }
+}
+
+
+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[4];
+ 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;
+ ve[2].src_offset = Offset(struct vertex, texcoord);
+ ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ ve[3].src_offset = Offset(struct vertex, generic);
+ ve[3].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+
+ handle = ctx->create_vertex_elements_state(ctx, 4, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.buffer_offset = 0;
+ if (draw_strip) {
+ vbuf.max_index = sizeof(vertices_strip) / vbuf.stride;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices_strip,
+ sizeof(vertices_strip),
+ PIPE_BIND_VERTEX_BUFFER);
+ } else {
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+ }
+
+ ctx->set_vertex_buffers(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 IN[2]\n"
+ "DCL IN[3]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], COLOR[0]\n"
+ "DCL OUT[2], GENERIC[0]\n"
+ "DCL OUT[3], GENERIC[1]\n"
+ " MOV OUT[0], IN[0]\n"
+ " MOV OUT[1], IN[1]\n"
+ " MOV OUT[2], IN[2]\n"
+ " MOV OUT[3], IN[3]\n"
+ " END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], COLOR, LINEAR\n"
+ "DCL OUT[0], COLOR\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void set_geometry_shader( void )
+{
+ FILE *f;
+ char buf[50000];
+ void *handle;
+ int sz;
+
+ if ((f = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Couldn't open %s\n", filename);
+ exit(1);
+ }
+
+ sz = fread(buf, 1, sizeof(buf), f);
+ if (!feof(f)) {
+ printf("file too long\n");
+ exit(1);
+ }
+ printf("%.*s\n", sz, buf);
+ buf[sz] = 0;
+
+ handle = graw_parse_geometry_shader(ctx, buf);
+ ctx->bind_gs_state(ctx, handle);
+ fclose(f);
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {.1,.3,.5,0};
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ if (draw_strip)
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+ else
+ util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
+
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+#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;
+
+#if (SIZE != 2)
+ for (s = 0; s < SIZE; s++) {
+ for (t = 0; t < SIZE; t++) {
+ if (0) {
+ int x = (s ^ t) & 1;
+ tex2d[t][s][0] = (x) ? 0 : 63;
+ tex2d[t][s][1] = (x) ? 0 : 128;
+ tex2d[t][s][2] = 0;
+ tex2d[t][s][3] = 0xff;
+ }
+ else {
+ int x = ((s ^ t) >> 2) & 1;
+ tex2d[t][s][0] = s*255/(SIZE-1);
+ tex2d[t][s][1] = t*255/(SIZE-1);
+ tex2d[t][s][2] = (x) ? 0 : 128;
+ tex2d[t][s][3] = 0xff;
+ }
+ }
+ }
+#else
+ tex2d[0][0][0] = 0;
+ tex2d[0][0][1] = 255;
+ tex2d[0][0][2] = 255;
+ tex2d[0][0][3] = 0;
+
+ tex2d[0][1][0] = 0;
+ tex2d[0][1][1] = 0;
+ tex2d[0][1][2] = 255;
+ tex2d[0][1][3] = 255;
+
+ tex2d[1][0][0] = 255;
+ tex2d[1][0][1] = 255;
+ tex2d[1][0][2] = 0;
+ tex2d[1][0][3] = 255;
+
+ tex2d[1][1][0] = 255;
+ tex2d[1][1][1] = 0;
+ tex2d[1][1][2] = 0;
+ 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.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,
+ u_subresource(0,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, 0, /* face, level, zslice */
+ 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);
+
+ ctx->transfer_destroy(ctx, t);
+ }
+
+ memset(&sv_template, 0, sizeof sv_template);
+ sv_template.format = samptex->format;
+ sv_template.texture = samptex;
+ sv_template.first_level = 0;
+ sv_template.last_level = 0;
+ 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);
+
+}
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,WIDTH,HEIGHT,
+ formats[i],
+ &window);
+ }
+
+ 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.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 = screen->get_tex_surface(screen, rttex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+
+ init_tex();
+ init_fs_constbuf();
+
+ set_vertices();
+ set_vertex_shader();
+ set_fragment_shader();
+ set_geometry_shader();
+}
+
+static void args(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-fps") == 0) {
+ show_fps = 1;
+ }
+ else if (strcmp(argv[i], "-strip") == 0) {
+ draw_strip = 1;
+ }
+ else if (i == argc - 1) {
+ filename = argv[i];
+ }
+ else {
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ if (!filename) {
+ usage(argv[0]);
+ exit(1);
+ }
+}
+
+int main( int argc, char *argv[] )
+{
+ args(argc,argv);
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
+ return 0;
+}
diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c
new file mode 100644
index 00000000000..c50ef12ab5a
--- /dev/null
+++ b/src/gallium/tests/graw/quad-tex.c
@@ -0,0 +1,403 @@
+/* Display a cleared blue window. This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#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_debug.h" /* debug_dump_surface_bmp() */
+#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
+};
+
+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 pipe_sampler_view *sv = NULL;
+static void *sampler = NULL;
+static void *window = NULL;
+
+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_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];
+ 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 = ctx->create_vertex_elements_state(ctx, 2, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(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(ctx, text);
+ ctx->bind_vs_state(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(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {.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, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+#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;
+
+#if (SIZE != 2)
+ for (s = 0; s < SIZE; s++) {
+ for (t = 0; t < SIZE; t++) {
+ if (0) {
+ int x = (s ^ t) & 1;
+ tex2d[t][s][0] = (x) ? 0 : 63;
+ tex2d[t][s][1] = (x) ? 0 : 128;
+ tex2d[t][s][2] = 0;
+ tex2d[t][s][3] = 0xff;
+ }
+ else {
+ int x = ((s ^ t) >> 2) & 1;
+ tex2d[t][s][0] = s*255/(SIZE-1);
+ tex2d[t][s][1] = t*255/(SIZE-1);
+ tex2d[t][s][2] = (x) ? 0 : 128;
+ tex2d[t][s][3] = 0xff;
+ }
+ }
+ }
+#else
+ tex2d[0][0][0] = 0;
+ tex2d[0][0][1] = 255;
+ tex2d[0][0][2] = 255;
+ tex2d[0][0][3] = 0;
+
+ tex2d[0][1][0] = 0;
+ tex2d[0][1][1] = 0;
+ tex2d[0][1][2] = 255;
+ tex2d[0][1][3] = 255;
+
+ tex2d[1][0][0] = 255;
+ tex2d[1][0][1] = 255;
+ tex2d[1][0][2] = 0;
+ tex2d[1][0][3] = 255;
+
+ tex2d[1][1][0] = 255;
+ tex2d[1][1][1] = 0;
+ tex2d[1][1][2] = 0;
+ 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.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,
+ u_subresource(0,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, 0, /* face, level, zslice */
+ 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);
+
+ ctx->transfer_destroy(ctx, t);
+ }
+
+ memset(&sv_template, 0, sizeof sv_template);
+ sv_template.format = samptex->format;
+ sv_template.texture = samptex;
+ sv_template.first_level = 0;
+ sv_template.last_level = 0;
+ 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);
+
+}
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
+ }
+
+ 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.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 = screen->get_tex_surface(screen, rttex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+
+ init_tex();
+
+ set_vertices();
+ 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/shader-leak.c b/src/gallium/tests/graw/shader-leak.c
new file mode 100644
index 00000000000..ec30871e82c
--- /dev/null
+++ b/src/gallium/tests/graw/shader-leak.c
@@ -0,0 +1,266 @@
+/**
+ * Create shaders in a loop to test memory usage.
+ */
+
+#include <stdio.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_debug.h" /* debug_dump_surface_bmp() */
+#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
+
+
+static int num_iters = 100;
+
+
+enum pipe_format formats[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_NONE
+};
+
+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 void *window = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+};
+
+static struct vertex vertices[1] =
+{
+ {
+ { 0.0f, -0.9f, 0.0f, 1.0f },
+ { 1.0f, 0.0f, 0.0f, 1.0f }
+ }
+};
+
+
+
+
+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];
+ 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 = ctx->create_vertex_elements_state(ctx, 2, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ vbuf.stride = sizeof(struct vertex);
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(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], COLOR\n"
+ " 0: MOV OUT[1], IN[1]\n"
+ " 1: MOV OUT[0], IN[0]\n"
+ " 2: END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+
+
+static void *
+set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], COLOR, LINEAR\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL TEMP[0..1]\n"
+ " 0: MUL TEMP[0], IN[0], IN[0]\n"
+ " 1: ADD TEMP[1], IN[0], IN[0]\n"
+ " 2: SUB OUT[0], TEMP[0], TEMP[1]\n"
+ " 3: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ return handle;
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {0, 0, 0, 1};
+ int i;
+
+ printf("Creating %d shaders\n", num_iters);
+
+ for (i = 0; i < num_iters; i++) {
+ void *fs = set_fragment_shader();
+
+ ctx->bind_fs_state(ctx, fs);
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ util_draw_arrays(ctx, PIPE_PRIM_POINTS, 0, 1);
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ ctx->bind_fs_state(ctx, NULL);
+ ctx->delete_fs_state(ctx, fs);
+ }
+
+ screen->flush_frontbuffer(screen, surf, window);
+ ctx->destroy(ctx);
+
+ exit(0);
+}
+
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource *tex, templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
+ }
+
+ 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.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 = screen->get_tex_surface(screen, tex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+ set_vertices();
+ set_vertex_shader();
+ if (0)
+ set_fragment_shader();
+}
+
+
+int main( int argc, char *argv[] )
+{
+ if (argc > 1)
+ num_iters = atoi(argv[1]);
+
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
+ return 0;
+}
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
new file mode 100644
index 00000000000..152ae408eb0
--- /dev/null
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -0,0 +1,268 @@
+/* Display a cleared blue window. This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#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_debug.h" /* debug_dump_surface_bmp() */
+#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 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 void *window = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+};
+
+static struct vertex vertices[4] =
+{
+ { { 0.0f, -0.9f, 0.0f, 1.0f },
+ { 1.0f, 0.0f, 0.0f, 1.0f }
+ },
+ { { -0.9f, 0.9f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f }
+ },
+ { { 0.9f, 0.9f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f }
+ }
+};
+
+
+
+
+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];
+ 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 = ctx->create_vertex_elements_state(ctx, 2, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(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], COLOR\n"
+ " 0: MOV OUT[1], IN[1]\n"
+ " 1: MOV OUT[0], IN[0]\n"
+ " 2: END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], COLOR, LINEAR\n"
+ "DCL OUT[0], COLOR\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void set_geometry_shader( void )
+{
+ void *handle;
+ const char *text =
+ "GEOM\n"
+ "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
+ "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
+ "DCL IN[][0], POSITION, CONSTANT\n"
+ "DCL IN[][1], COLOR, CONSTANT\n"
+ "DCL OUT[0], POSITION, CONSTANT\n"
+ "DCL OUT[1], COLOR, CONSTANT\n"
+ "0:MOV OUT[0], IN[0][0]\n"
+ "1:MOV OUT[1], IN[0][1]\n"
+ "2:EMIT\n"
+ "3:MOV OUT[0], IN[1][0]\n"
+ "4:MOV OUT[1], IN[0][1]\n" /* copy color from input vertex 0 */
+ "5:EMIT\n"
+ "6:MOV OUT[0], IN[2][0]\n"
+ "7:MOV OUT[1], IN[2][1]\n"
+ "8:EMIT\n"
+ "9:ENDPRIM\n"
+ "10:END\n";
+
+ handle = graw_parse_geometry_shader(ctx, text);
+ ctx->bind_gs_state(ctx, handle);
+}
+
+static void draw( void )
+{
+ float clear_color[4] = {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, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource *tex, templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
+ }
+
+ 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.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)
+ exit(4);
+
+ surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+ set_vertices();
+ set_vertex_shader();
+ set_fragment_shader();
+ set_geometry_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/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
new file mode 100644
index 00000000000..8859f745fdb
--- /dev/null
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -0,0 +1,345 @@
+/*
+ * Test draw instancing.
+ */
+
+#include <stdio.h>
+#include <string.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_debug.h" /* debug_dump_surface_bmp() */
+#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 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 void *window = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+};
+
+
+static int draw_elements = 0;
+
+
+/**
+ * Vertex data.
+ * Each vertex has three attributes: position, color and translation.
+ * The translation attribute is a per-instance attribute. See
+ * "instance_divisor" below.
+ */
+static struct vertex vertices[4] =
+{
+ {
+ { 0.0f, -0.3f, 0.0f, 1.0f }, /* pos */
+ { 1.0f, 0.0f, 0.0f, 1.0f } /* color */
+ },
+ {
+ { -0.2f, 0.3f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f }
+ },
+ {
+ { 0.2f, 0.3f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f }
+ }
+};
+
+
+#define NUM_INST 5
+
+static float inst_data[NUM_INST][4] =
+{
+ { -0.50f, 0.4f, 0.0f, 0.0f },
+ { -0.25f, 0.1f, 0.0f, 0.0f },
+ { 0.00f, 0.2f, 0.0f, 0.0f },
+ { 0.25f, 0.1f, 0.0f, 0.0f },
+ { 0.50f, 0.3f, 0.0f, 0.0f }
+};
+
+
+static ushort indices[3] = { 0, 2, 1 };
+
+
+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[3];
+ struct pipe_vertex_buffer vbuf[2];
+ struct pipe_index_buffer ibuf;
+ void *handle;
+
+ memset(ve, 0, sizeof ve);
+
+ /* pos */
+ ve[0].src_offset = Offset(struct vertex, position);
+ ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ ve[0].vertex_buffer_index = 0;
+
+ /* color */
+ ve[1].src_offset = Offset(struct vertex, color);
+ ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ ve[1].vertex_buffer_index = 0;
+
+ /* per-instance info */
+ ve[2].src_offset = 0;
+ ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ ve[2].vertex_buffer_index = 1;
+ ve[2].instance_divisor = 1;
+
+ handle = ctx->create_vertex_elements_state(ctx, 3, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ /* vertex data */
+ vbuf[0].stride = sizeof( struct vertex );
+ vbuf[0].max_index = sizeof(vertices) / vbuf[0].stride;
+ vbuf[0].buffer_offset = 0;
+ vbuf[0].buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ /* instance data */
+ vbuf[1].stride = sizeof( inst_data[0] );
+ vbuf[1].max_index = sizeof(inst_data) / vbuf[1].stride;
+ vbuf[1].buffer_offset = 0;
+ vbuf[1].buffer = screen->user_buffer_create(screen,
+ inst_data,
+ sizeof(inst_data),
+ PIPE_BIND_VERTEX_BUFFER);
+
+
+ ctx->set_vertex_buffers(ctx, 2, vbuf);
+
+ /* index data */
+ ibuf.buffer = screen->user_buffer_create(screen,
+ indices,
+ sizeof(indices),
+ PIPE_BIND_VERTEX_BUFFER);
+ ibuf.offset = 0;
+ ibuf.index_size = 2;
+
+ ctx->set_index_buffer(ctx, &ibuf);
+
+}
+
+static void set_vertex_shader( void )
+{
+ void *handle;
+ const char *text =
+ "VERT\n"
+ "DCL IN[0]\n"
+ "DCL IN[1]\n"
+ "DCL IN[2]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], COLOR\n"
+ " 0: MOV OUT[1], IN[1]\n"
+ " 1: ADD OUT[0], IN[0], IN[2]\n" /* add instance pos to vertex pos */
+ " 2: END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], COLOR, LINEAR\n"
+ "DCL OUT[0], COLOR\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {1,0,1,1};
+ struct pipe_draw_info info;
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+
+ util_draw_init_info(&info);
+ info.indexed = (draw_elements != 0);
+ info.mode = PIPE_PRIM_TRIANGLES;
+ info.start = 0;
+ info.count = 3;
+ /* draw NUM_INST triangles */
+ info.instance_count = NUM_INST;
+
+ ctx->draw_vbo(ctx, &info);
+
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource *tex, templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
+ }
+
+ 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.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)
+ exit(4);
+
+ surf = screen->get_tex_surface(screen, tex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+ set_vertices();
+ set_vertex_shader();
+ set_fragment_shader();
+}
+
+
+static void options(int argc, char *argv[])
+{
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-e") == 0)
+ draw_elements = 1;
+ }
+ if (draw_elements)
+ printf("Using pipe_context::draw_elements_instanced()\n");
+ else
+ printf("Using pipe_context::draw_arrays_instanced()\n");
+}
+
+
+int main( int argc, char *argv[] )
+{
+ options(argc, argv);
+
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
+ return 0;
+}
diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c
new file mode 100644
index 00000000000..f7e39588a4d
--- /dev/null
+++ b/src/gallium/tests/graw/tri.c
@@ -0,0 +1,263 @@
+/* Display a cleared blue window. This demo has no dependencies on
+ * 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_state.h"
+#include "pipe/p_defines.h"
+
+#include "util/u_debug.h" /* debug_dump_surface_bmp() */
+#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 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 void *window = NULL;
+
+struct vertex {
+ float position[4];
+ float color[4];
+};
+
+static struct vertex vertices[3] =
+{
+ {
+ { 0.0f, -0.9f, 0.0f, 1.0f },
+ { 1.0f, 0.0f, 0.0f, 1.0f }
+ },
+ {
+ { -0.9f, 0.9f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f }
+ },
+ {
+ { 0.9f, 0.9f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f }
+ }
+};
+
+
+
+
+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];
+ 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 = ctx->create_vertex_elements_state(ctx, 2, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(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], COLOR\n"
+ " 0: MOV OUT[1], IN[1]\n"
+ " 1: MOV OUT[0], IN[0]\n"
+ " 2: END\n";
+
+ handle = graw_parse_vertex_shader(ctx, text);
+ ctx->bind_vs_state(ctx, handle);
+}
+
+static void set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], COLOR, LINEAR\n"
+ "DCL OUT[0], COLOR\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+static void draw( void )
+{
+ float clear_color[4] = {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, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource *tex, templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,300,300,
+ formats[i],
+ &window);
+ }
+
+ 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.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 = screen->get_tex_surface(screen, tex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ if (surf == NULL) {
+ fprintf(stderr, "Unable to get 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+ set_vertices();
+ 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/vertex-shader b/src/gallium/tests/graw/vertex-shader
new file mode 120000
index 00000000000..7b216e8ca08
--- /dev/null
+++ b/src/gallium/tests/graw/vertex-shader
@@ -0,0 +1 @@
+../python/tests/regress/vertex-shader \ No newline at end of file
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
new file mode 100644
index 00000000000..e1cd814bf72
--- /dev/null
+++ b/src/gallium/tests/graw/vs-test.c
@@ -0,0 +1,508 @@
+/* Display a cleared blue window. This demo has no dependencies on
+ * any utility code, just the graw interface and gallium.
+ */
+
+#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 <stdio.h> /* for fread(), etc */
+
+#include "util/u_debug.h" /* debug_dump_surface_bmp() */
+#include "util/u_inlines.h"
+#include "util/u_memory.h" /* Offset() */
+#include "util/u_draw_quad.h"
+#include "util/u_box.h"
+
+static const char *filename = NULL;
+unsigned show_fps = 0;
+
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
+#ifndef WIN32
+ fprintf(stderr, "\n" );
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " -fps show frames per second\n");
+#endif
+}
+
+
+enum pipe_format formats[] = {
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_NONE
+};
+
+static const int WIDTH = 250;
+static const int HEIGHT = 250;
+
+static struct pipe_screen *screen = NULL;
+static struct pipe_context *ctx = NULL;
+static struct pipe_resource *rttex = NULL;
+static struct pipe_resource *constbuf = NULL;
+static struct pipe_surface *surf = NULL;
+static struct pipe_sampler_view *sv = NULL;
+static void *sampler = NULL;
+static void *window = NULL;
+static struct pipe_resource *samptex = NULL;
+
+struct vertex {
+ float position[4];
+ float color[3];
+};
+
+/* Draw a regular mesh
+ */
+#define MESH_SZ 16
+static struct vertex vertices[MESH_SZ * MESH_SZ];
+
+static float constants[] =
+{ 0.4, 0, 0, 1,
+ 1, 1, 1, 1,
+ 2, 2, 2, 2,
+ 4, 8, 16, 32,
+
+ 3, 0, 0, 0,
+ 0, .5, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+
+ 1, 0, 0, 0.5,
+ 0, 1, 0, 0.5,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+};
+
+static void init_fs_constbuf( void )
+{
+ struct pipe_resource templat;
+ struct pipe_box box;
+
+ templat.target = PIPE_BUFFER;
+ templat.format = PIPE_FORMAT_R8_UNORM;
+ templat.width0 = sizeof(constants);
+ templat.height0 = 1;
+ templat.depth0 = 1;
+ templat.last_level = 0;
+ templat.nr_samples = 1;
+ templat.bind = PIPE_BIND_CONSTANT_BUFFER;
+
+ constbuf = screen->resource_create(screen,
+ &templat);
+ if (constbuf == NULL)
+ exit(4);
+
+
+ u_box_2d(0,0,sizeof(constants),1, &box);
+
+ ctx->transfer_inline_write(ctx,
+ constbuf,
+ u_subresource(0,0),
+ PIPE_TRANSFER_WRITE,
+ &box,
+ constants,
+ sizeof constants,
+ sizeof constants);
+
+
+ ctx->set_constant_buffer(ctx,
+ PIPE_SHADER_FRAGMENT, 0,
+ constbuf);
+}
+
+
+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];
+ struct pipe_vertex_buffer vbuf;
+ void *handle;
+ int x,y;
+
+ 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 = ctx->create_vertex_elements_state(ctx, 2, ve);
+ ctx->bind_vertex_elements_state(ctx, handle);
+
+ for (x = 0; x < MESH_SZ; x++) {
+ for (y = 0; y < MESH_SZ; y++) {
+ int i = y * MESH_SZ + x;
+ vertices[i].position[0] = ((float)x)/MESH_SZ * 2.0 - 1.0;
+ vertices[i].position[1] = ((float)y)/MESH_SZ * 2.0 - 1.0;
+ vertices[i].position[2] = 0;
+ vertices[i].position[3] = 1.0;
+
+ vertices[i].color[0] = .5;
+ vertices[i].color[1] = (float)x / (float)MESH_SZ;
+ vertices[i].color[2] = (float)y / (float)MESH_SZ;
+ }
+ }
+
+ vbuf.stride = sizeof( struct vertex );
+ vbuf.max_index = sizeof(vertices) / vbuf.stride;
+ vbuf.buffer_offset = 0;
+ vbuf.buffer = screen->user_buffer_create(screen,
+ vertices,
+ sizeof(vertices),
+ PIPE_BIND_VERTEX_BUFFER);
+
+ ctx->set_vertex_buffers(ctx, 1, &vbuf);
+}
+
+static void set_vertex_shader( void )
+{
+ FILE *f;
+ char buf[50000];
+ void *handle;
+ int sz;
+
+ if ((f = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Couldn't open %s\n", filename);
+ exit(1);
+ }
+
+ sz = fread(buf, 1, sizeof(buf), f);
+ if (!feof(f)) {
+ printf("file too long\n");
+ exit(1);
+ }
+ printf("%.*s\n", sz, buf);
+ buf[sz] = 0;
+
+ handle = graw_parse_vertex_shader(ctx, buf);
+ ctx->bind_vs_state(ctx, handle);
+ fclose(f);
+}
+
+static void set_fragment_shader( void )
+{
+ void *handle;
+ const char *text =
+ "FRAG\n"
+ "DCL IN[0], COLOR, LINEAR\n"
+ "DCL OUT[0], COLOR\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: END\n";
+
+ handle = graw_parse_fragment_shader(ctx, text);
+ ctx->bind_fs_state(ctx, handle);
+}
+
+
+
+static void draw( void )
+{
+ float clear_color[4] = {.1,.3,.5,0};
+
+ ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
+ util_draw_arrays(ctx, PIPE_PRIM_POINTS, 0, Elements(vertices));
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, 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(ctx, "result.bmp", surf);
+#endif
+
+ screen->flush_frontbuffer(screen, surf, window);
+}
+
+#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;
+
+#if (SIZE != 2)
+ for (s = 0; s < SIZE; s++) {
+ for (t = 0; t < SIZE; t++) {
+ if (0) {
+ int x = (s ^ t) & 1;
+ tex2d[t][s][0] = (x) ? 0 : 63;
+ tex2d[t][s][1] = (x) ? 0 : 128;
+ tex2d[t][s][2] = 0;
+ tex2d[t][s][3] = 0xff;
+ }
+ else {
+ int x = ((s ^ t) >> 2) & 1;
+ tex2d[t][s][0] = s*255/(SIZE-1);
+ tex2d[t][s][1] = t*255/(SIZE-1);
+ tex2d[t][s][2] = (x) ? 0 : 128;
+ tex2d[t][s][3] = 0xff;
+ }
+ }
+ }
+#else
+ tex2d[0][0][0] = 0;
+ tex2d[0][0][1] = 255;
+ tex2d[0][0][2] = 255;
+ tex2d[0][0][3] = 0;
+
+ tex2d[0][1][0] = 0;
+ tex2d[0][1][1] = 0;
+ tex2d[0][1][2] = 255;
+ tex2d[0][1][3] = 255;
+
+ tex2d[1][0][0] = 255;
+ tex2d[1][0][1] = 255;
+ tex2d[1][0][2] = 0;
+ tex2d[1][0][3] = 255;
+
+ tex2d[1][1][0] = 255;
+ tex2d[1][1][1] = 0;
+ tex2d[1][1][2] = 0;
+ 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.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,
+ u_subresource(0,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, 0, /* face, level, zslice */
+ 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);
+
+ ctx->transfer_destroy(ctx, t);
+ }
+
+ memset(&sv_template, 0, sizeof sv_template);
+ sv_template.format = samptex->format;
+ sv_template.texture = samptex;
+ sv_template.first_level = 0;
+ sv_template.last_level = 0;
+ 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);
+
+}
+
+static void init( void )
+{
+ struct pipe_framebuffer_state fb;
+ struct pipe_resource templat;
+ 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;
+ window == NULL && formats[i] != PIPE_FORMAT_NONE;
+ i++) {
+
+ screen = graw_create_window_and_screen(0,0,WIDTH,HEIGHT,
+ formats[i],
+ &window);
+ }
+
+ 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.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 = screen->get_tex_surface(screen, rttex, 0, 0, 0,
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DISPLAY_TARGET);
+ 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);
+ }
+
+ {
+ struct pipe_rasterizer_state rasterizer;
+ void *handle;
+ memset(&rasterizer, 0, sizeof rasterizer);
+ rasterizer.cull_face = PIPE_FACE_NONE;
+ rasterizer.point_size = 8.0;
+ rasterizer.gl_rasterization_rules = 1;
+ handle = ctx->create_rasterizer_state(ctx, &rasterizer);
+ ctx->bind_rasterizer_state(ctx, handle);
+ }
+
+ set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
+
+ init_tex();
+ init_fs_constbuf();
+
+ set_vertices();
+ set_vertex_shader();
+ set_fragment_shader();
+}
+
+static void args(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-fps") == 0) {
+ show_fps = 1;
+ }
+ else if (i == argc - 1) {
+ filename = argv[i];
+ }
+ else {
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ if (!filename) {
+ usage(argv[0]);
+ exit(1);
+ }
+}
+
+int main( int argc, char *argv[] )
+{
+ args(argc,argv);
+ init();
+
+ graw_set_display_func( draw );
+ graw_main_loop();
+ return 0;
+}
diff --git a/src/gallium/tests/python/retrace/interpreter.py b/src/gallium/tests/python/retrace/interpreter.py
index 7118ff85ed8..16132abb06d 100755
--- a/src/gallium/tests/python/retrace/interpreter.py
+++ b/src/gallium/tests/python/retrace/interpreter.py
@@ -111,6 +111,7 @@ struct_factories = {
#"pipe_texture": gallium.Texture,
'pipe_subresource': gallium.pipe_subresource,
'pipe_box': gallium.pipe_box,
+ 'pipe_draw_info': gallium.pipe_draw_info,
}
@@ -230,8 +231,8 @@ class Screen(Object):
context = self.real.context_create()
return Context(self.interpreter, context)
- def is_format_supported(self, format, target, bind, geom_flags):
- return self.real.is_format_supported(format, target, bind, geom_flags)
+ def is_format_supported(self, format, target, sample_count, bind, geom_flags):
+ return self.real.is_format_supported(format, target, sample_count, bind, geom_flags)
def resource_create(self, templat):
return self.real.resource_create(
@@ -432,6 +433,9 @@ class Context(Object):
swizzle_b = templ.swizzle_g,
swizzle_a = templ.swizzle_a)
+ def sampler_view_destroy(self, view):
+ pass
+
def set_fragment_sampler_views(self, num, views):
for i in range(num):
self.real.set_fragment_sampler_view(i, views[i])
@@ -456,6 +460,10 @@ class Context(Object):
return elements[0:num_elements]
def bind_vertex_elements_state(self, state):
+ if state is None:
+ self.real.set_vertex_elements(0)
+ return
+
elements = state
num_elements = len(elements)
self.velems = elements
@@ -526,43 +534,31 @@ class Context(Object):
return minindex + ibias, maxindex + ibias
- def draw_arrays(self, mode, start, count):
- self.dump_vertices(start, count)
-
- self.real.draw_arrays(mode, start, count)
- self._set_dirty()
-
- def draw_elements(self, indexBuffer, indexSize, indexBias, mode, start, count):
- if self.interpreter.verbosity(2):
- minindex, maxindex = self.dump_indices(indexBuffer, indexSize, indexBias, start, count)
- self.dump_vertices(minindex, maxindex - minindex)
+ def set_index_buffer(self, ib):
+ if ib:
+ self.real.set_index_buffer(ib.index_size, ib.offset, ib.buffer)
+ else:
+ self.real.set_index_buffer(0, 0, None)
- self.real.draw_elements(indexBuffer, indexSize, indexBias, mode, start, count)
- self._set_dirty()
-
- def draw_range_elements(self, indexBuffer, indexSize, indexBias, minIndex, maxIndex, mode, start, count):
+ def draw_vbo(self, info):
if self.interpreter.verbosity(2):
- minindex, maxindex = self.dump_indices(indexBuffer, indexSize, indexBias, start, count)
- minindex = min(minindex, minIndex)
- maxindex = min(maxindex, maxIndex)
- self.dump_vertices(minindex, maxindex - minindex)
+ if 0:
+ minindex, maxindex = self.dump_indices(indexBuffer, indexSize, indexBias, start, count)
+
+ self.dump_vertices(info.minindex, info.maxindex + 1 - info.minindex)
- self.real.draw_range_elements(indexBuffer, indexSize, indexBias, minIndex, maxIndex, mode, start, count)
+ self.real.draw_vbo(info)
self._set_dirty()
-
- def surface_copy(self, dest, destx, desty, src, srcx, srcy, width, height):
- if dest is not None and src is not None:
+
+ def resource_copy_region(self, dst, subdst, dstx, dsty, dstz, src, subsrc, srcx, srcy, srcz, width, height):
+ if dst is not None and src is not None:
if self.interpreter.options.all:
- self.interpreter.present(self.real, src, 'surface_copy_src', srcx, srcy, width, height)
- self.real.surface_copy(dest, destx, desty, src, srcx, srcy, width, height)
- if dest in self.cbufs:
- self._set_dirty()
- flags = gallium.PIPE_FLUSH_FRAME
- else:
- flags = 0
+ self.interpreter.present(self.real, src, 'resource_copy_src', srcx, srcy, width, height)
+ self.real.resource_copy_region(dst, subdst, dstx, dsty, dstx, src, subsrc, srcx, srcy, srcz, width, height)
+ flags = 0
self.flush(flags)
if self.interpreter.options.all:
- self.interpreter.present(self.real, dest, 'surface_copy_dest', destx, desty, width, height)
+ self.interpreter.present(self.real, dst, 'resource_copy_dst', dstx, dsty, width, height)
def is_resource_referenced(self, texture, face, level):
#return self.real.is_resource_referenced(format, texture, face, level)
diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-2d.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-2d.sh
index f70a5146f4e..bbc3a10f9b5 100644
--- a/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-2d.sh
+++ b/src/gallium/tests/python/tests/regress/fragment-shader/frag-cb-2d.sh
@@ -2,8 +2,8 @@ FRAG
DCL IN[0], COLOR, LINEAR
DCL OUT[0], COLOR
-DCL CONST[1][1..2]
+DCL CONST[1][6]
-MAD OUT[0], IN[0], CONST[1][2], CONST[1][1]
+MOV OUT[0], CONST[1][6]
END
diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-kil.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-kil.sh
new file mode 100644
index 00000000000..583b0ca4a4a
--- /dev/null
+++ b/src/gallium/tests/python/tests/regress/fragment-shader/frag-kil.sh
@@ -0,0 +1,18 @@
+FRAG
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.6, 0.0 }
+IMM FLT32 { 0.01, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+
+SLT TEMP[0], IN[0], IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+MOV OUT[0].w, IMM[2].xxxx
+SUB TEMP[0], TEMP[0], IMM[1].xxxy
+KIL TEMP[0]
+
+END
diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-mad-immx.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-mad-immx.sh
new file mode 100644
index 00000000000..6b034915769
--- /dev/null
+++ b/src/gallium/tests/python/tests/regress/fragment-shader/frag-mad-immx.sh
@@ -0,0 +1,10 @@
+FRAG
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+DCL IMMX[0..1] {{ 0.5, 0.4, 0.6, 1.0 },
+ { 0.5, 0.4, 0.6, 0.0 }}
+
+MAD OUT[0], IN[0], IMMX[0], IMMX[1]
+
+END
diff --git a/src/gallium/tests/python/tests/regress/fragment-shader/frag-tempx.sh b/src/gallium/tests/python/tests/regress/fragment-shader/frag-tempx.sh
new file mode 100644
index 00000000000..81bcad2d65c
--- /dev/null
+++ b/src/gallium/tests/python/tests/regress/fragment-shader/frag-tempx.sh
@@ -0,0 +1,14 @@
+FRAG
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMPX[0][0..1]
+
+IMM FLT32 { -0.5, -0.4, -0.6, 0.0 }
+
+ADD TEMPX[0][0], IN[0], IMM[0]
+ADD TEMPX[0][1], IN[0], IMM[0]
+ABS OUT[0], TEMPX[0][1]
+
+END
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-abs.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-abs.sh
index 79c9ca69fb1..062a48b531e 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-abs.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-abs.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL TEMP[0]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-add.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-add.sh
index ca97ad05df0..188931ebc8d 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-add.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-add.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-arl.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-arl.sh
index 321140e89e8..0039597f6f0 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-arl.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-arl.sh
@@ -1,6 +1,6 @@
VERT
-DCL IN[0], POSITION
+DCL IN[0]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-arr.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-arr.sh
index d60ea46b367..fdde4f9ad12 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-arr.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-arr.sh
@@ -1,6 +1,6 @@
VERT
-DCL IN[0], POSITION
+DCL IN[0]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-1d.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-1d.sh
index b41fe5dd38f..e227917fd3b 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-1d.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-1d.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL CONST[1]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-2d.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-2d.sh
index 45f5e6b7299..39768d2dda9 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-2d.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-cb-2d.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL CONST[1][1..2]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp3.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp3.sh
index caff622fe61..357e224f696 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp3.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp3.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL TEMP[0]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp4.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp4.sh
index 3dd2fd1c2f7..14f61066014 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp4.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-dp4.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL TEMP[0]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-dst.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-dst.sh
index da9cc18dfc0..2d59bd1a0c3 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-dst.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-dst.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-ex2.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-ex2.sh
index 4637227e5c4..e2383a6b5bd 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-ex2.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-ex2.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-flr.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-flr.sh
index aa80d6e394c..fa24806663b 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-flr.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-flr.sh
@@ -1,6 +1,6 @@
VERT
-DCL IN[0], POSITION
+DCL IN[0]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-frc.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-frc.sh
index 64d1a494e13..ff09bfafd0c 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-frc.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-frc.sh
@@ -1,6 +1,6 @@
VERT
-DCL IN[0], POSITION
+DCL IN[0]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-lg2.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-lg2.sh
index 5cf16fd1aa8..876b7ab6608 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-lg2.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-lg2.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-lit.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-lit.sh
index a4a752d4d23..a2235ff6119 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-lit.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-lit.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-lrp.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-lrp.sh
index 4bb5f3ec3f4..a26ca3b0ec0 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-lrp.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-lrp.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-mad.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-mad.sh
index daaa941f15f..caf83a91e48 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-mad.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-mad.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-max.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-max.sh
index af279ec7f4a..db84a499214 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-max.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-max.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-min.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-min.sh
index 46d886c55b8..63a8c2cf3cd 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-min.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-min.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-mov.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-mov.sh
index 0ef91637e03..4c23e3eaadb 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-mov.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-mov.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-mul.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-mul.sh
index d34f6cd6e3c..a409cd4b21e 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-mul.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-mul.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-rcp.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-rcp.sh
index cfb3ec37dc2..d440e35d9a3 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-rcp.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-rcp.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-rsq.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-rsq.sh
index faf1e6e7d41..6fbd53ae0ac 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-rsq.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-rsq.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-sge.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-sge.sh
index 6de1d071ef4..e32a21b6109 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-sge.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-sge.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-slt.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-slt.sh
index 9a524229845..2af61062922 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-slt.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-slt.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-abs.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
index dc87ce4ae70..e768d95049d 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL TEMP[0]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
index d82eb08fd30..40ca5d60def 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
DCL TEMP[0]
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-neg.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
index e39bebcd9f1..297bc1ee3ed 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-swz.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
index 6f20552f212..528f164b9ee 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-sub.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-sub.sh
index 0f9678b8a3e..90249abdd38 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-sub.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-sub.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/regress/vertex-shader/vert-xpd.sh b/src/gallium/tests/python/tests/regress/vertex-shader/vert-xpd.sh
index 39d42ae2a0d..72b048676fb 100644
--- a/src/gallium/tests/python/tests/regress/vertex-shader/vert-xpd.sh
+++ b/src/gallium/tests/python/tests/regress/vertex-shader/vert-xpd.sh
@@ -1,7 +1,7 @@
VERT
-DCL IN[0], POSITION
-DCL IN[1], COLOR
+DCL IN[0]
+DCL IN[1]
DCL OUT[0], POSITION
DCL OUT[1], COLOR
diff --git a/src/gallium/tests/python/tests/surface_copy.py b/src/gallium/tests/python/tests/surface_copy.py
index 8d841644035..7a6ede38044 100755
--- a/src/gallium/tests/python/tests/surface_copy.py
+++ b/src/gallium/tests/python/tests/surface_copy.py
@@ -70,13 +70,14 @@ class TextureTest(TestCase):
face = self.face
level = self.level
zslice = self.zslice
-
+
bind = PIPE_BIND_SAMPLER_VIEW
geom_flags = 0
- if not dev.is_format_supported(format, target, bind, geom_flags):
+ sample_count = 0
+ if not dev.is_format_supported(format, target, sample_count, bind, geom_flags):
raise TestSkip
- if not dev.is_format_supported(format, target, bind, geom_flags):
+ if not dev.is_format_supported(format, target, sample_count, bind, geom_flags):
raise TestSkip
# textures
diff --git a/src/gallium/tests/python/tests/texture_blit.py b/src/gallium/tests/python/tests/texture_blit.py
index 77f006ea04e..089d05c6237 100755
--- a/src/gallium/tests/python/tests/texture_blit.py
+++ b/src/gallium/tests/python/tests/texture_blit.py
@@ -55,7 +55,7 @@ def tex_coords(texture, face, level, zslice):
[0.0, 1.0],
]
- if texture.target == PIPE_TEXTURE_2D:
+ if texture.target == PIPE_TEXTURE_2D or texture.target == PIPE_TEXTURE_RECT:
return [[s, t, 0.0] for s, t in st]
elif texture.target == PIPE_TEXTURE_3D:
depth = texture.get_depth(level)
@@ -130,17 +130,18 @@ class TextureColorSampleTest(TestCase):
zslice = self.zslice
minz = 0.0
maxz = 1.0
-
+
bind = PIPE_BIND_SAMPLER_VIEW
geom_flags = 0
+ sample_count = 0
if width != height:
geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
if not is_pot(width) or not is_pot(height) or not is_pot(depth):
geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
-
- if not dev.is_format_supported(format, target, bind, geom_flags):
+
+ if not dev.is_format_supported(format, target, sample_count, bind, geom_flags):
raise TestSkip
-
+
# disabled blending/masking
blend = Blend()
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE
@@ -348,17 +349,18 @@ class TextureDepthSampleTest(TestCase):
zslice = self.zslice
minz = 0.0
maxz = 1.0
-
+
bind = PIPE_BIND_SAMPLER_VIEW
geom_flags = 0
+ sample_count = 0
if width != height:
geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE
if not is_pot(width) or not is_pot(height) or not is_pot(depth):
geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO
-
- if not dev.is_format_supported(format, target, bind, geom_flags):
+
+ if not dev.is_format_supported(format, target, sample_count, bind, geom_flags):
raise TestSkip
-
+
# disabled blending/masking
blend = Blend()
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE
diff --git a/src/gallium/tests/python/tests/texture_transfer.py b/src/gallium/tests/python/tests/texture_transfer.py
index 4aa3d6c709b..65c919bc64d 100755
--- a/src/gallium/tests/python/tests/texture_transfer.py
+++ b/src/gallium/tests/python/tests/texture_transfer.py
@@ -71,12 +71,13 @@ class TextureTest(TestCase):
face = self.face
level = self.level
zslice = self.zslice
-
+
bind = PIPE_BIND_SAMPLER_VIEW
geom_flags = 0
- if not dev.is_format_supported(format, target, bind, geom_flags):
+ sample_count = 0
+ if not dev.is_format_supported(format, target, sample_count, bind, geom_flags):
raise TestSkip
-
+
# textures
texture = dev.resource_create(
target = target,
diff --git a/src/gallium/tests/raw/SConscript b/src/gallium/tests/raw/SConscript
deleted file mode 100644
index 073b97951e7..00000000000
--- a/src/gallium/tests/raw/SConscript
+++ /dev/null
@@ -1,17 +0,0 @@
-Import('*')
-
-env = env.Clone()
-
-env.Prepend(LIBPATH = [graw.dir])
-env.Prepend(LIBS = [graw.name])
-
-progs = [
- 'clear'
-]
-
-for prog in progs:
- env.Program(
- target = prog,
- source = prog + '.c',
- )
-
diff --git a/src/gallium/tests/trivial/quad-tex.c b/src/gallium/tests/trivial/quad-tex.c
index 522ff3cb42d..cf88edcdc56 100644
--- a/src/gallium/tests/trivial/quad-tex.c
+++ b/src/gallium/tests/trivial/quad-tex.c
@@ -58,18 +58,13 @@
/* util_make_[fragment|vertex]_passthrough_shader */
#include "util/u_simple_shaders.h"
-/* softpipe software driver */
-#include "softpipe/sp_public.h"
-
+/* sw_screen_create: to get a software pipe driver */
+#include "target-helpers/inline_sw_helper.h"
+/* debug_screen_wrap: to wrap with debug pipe drivers */
+#include "target-helpers/inline_debug_helper.h"
/* null software winsys */
#include "sw/null/null_sw_winsys.h"
-/* traceing support see src/gallium/drivers/trace/README for more info. */
-#if USE_TRACE
-#include "trace/tr_screen.h"
-#include "trace/tr_context.h"
-#endif
-
struct program
{
struct pipe_screen *screen;
@@ -98,10 +93,11 @@ struct program
static void init_prog(struct program *p)
{
/* create the software rasterizer */
- p->screen = softpipe_create_screen(null_sw_create());
-#if USE_TRACE
- p->screen = trace_screen_create(p->screen);
-#endif
+ p->screen = sw_screen_create(null_sw_create());
+ /* wrap the screen with any debugger */
+ p->screen = debug_screen_wrap(p->screen);
+
+ /* create the pipe driver context and cso context */
p->pipe = p->screen->context_create(p->screen, NULL);
p->cso = cso_create_context(p->pipe);
@@ -201,8 +197,7 @@ static void init_prog(struct program *p)
/* rasterizer */
memset(&p->rasterizer, 0, sizeof(p->rasterizer));
- p->rasterizer.front_winding = PIPE_WINDING_CW;
- p->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ p->rasterizer.cull_face = PIPE_FACE_NONE;
p->rasterizer.gl_rasterization_rules = 1;
/* sampler */
@@ -272,7 +267,7 @@ static void init_prog(struct program *p)
}
/* fragment shader */
- p->fs = util_make_fragment_tex_shader(p->pipe, TGSI_TEXTURE_2D);
+ p->fs = util_make_fragment_tex_shader(p->pipe, TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
}
static void close_prog(struct program *p)
diff --git a/src/gallium/tests/trivial/tri.c b/src/gallium/tests/trivial/tri.c
index 48305240a4b..667a27b28ab 100644
--- a/src/gallium/tests/trivial/tri.c
+++ b/src/gallium/tests/trivial/tri.c
@@ -56,18 +56,13 @@
/* util_make_[fragment|vertex]_passthrough_shader */
#include "util/u_simple_shaders.h"
-/* softpipe software driver */
-#include "softpipe/sp_public.h"
-
+/* sw_screen_create: to get a software pipe driver */
+#include "target-helpers/inline_sw_helper.h"
+/* debug_screen_wrap: to wrap with debug pipe drivers */
+#include "target-helpers/inline_debug_helper.h"
/* null software winsys */
#include "sw/null/null_sw_winsys.h"
-/* traceing support see src/gallium/drivers/trace/README for more info. */
-#if USE_TRACE
-#include "trace/tr_screen.h"
-#include "trace/tr_context.h"
-#endif
-
struct program
{
struct pipe_screen *screen;
@@ -93,10 +88,11 @@ struct program
static void init_prog(struct program *p)
{
/* create the software rasterizer */
- p->screen = softpipe_create_screen(null_sw_create());
-#if USE_TRACE
- p->screen = trace_screen_create(p->screen);
-#endif
+ p->screen = sw_screen_create(null_sw_create());
+ /* wrap the screen with any debugger */
+ p->screen = debug_screen_wrap(p->screen);
+
+ /* create the pipe driver context and cso context */
p->pipe = p->screen->context_create(p->screen, NULL);
p->cso = cso_create_context(p->pipe);
@@ -151,8 +147,7 @@ static void init_prog(struct program *p)
/* rasterizer */
memset(&p->rasterizer, 0, sizeof(p->rasterizer));
- p->rasterizer.front_winding = PIPE_WINDING_CW;
- p->rasterizer.cull_mode = PIPE_WINDING_NONE;
+ p->rasterizer.cull_face = PIPE_FACE_NONE;
p->rasterizer.gl_rasterization_rules = 1;
/* drawing destination */
diff --git a/src/gallium/tests/unit/translate_test.c b/src/gallium/tests/unit/translate_test.c
new file mode 100644
index 00000000000..d0946a91a26
--- /dev/null
+++ b/src/gallium/tests/unit/translate_test.c
@@ -0,0 +1,310 @@
+/**************************************************************************
+ *
+ * Copyright © 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+#include <translate/translate.h>
+#include <util/u_memory.h>
+#include <util/u_format.h>
+#include <util/u_cpu_detect.h>
+#include <rtasm/rtasm_cpu.h>
+
+/* don't use this for serious use */
+static double rand_double()
+{
+ const double rm = (double)RAND_MAX + 1;
+ double div = 1;
+ double v = 0;
+ unsigned i;
+ for(i = 0; i < 4; ++i)
+ {
+ div *= rm;
+ v += (double)rand() / div;
+ }
+ return v;
+}
+
+int main(int argc, char** argv)
+{
+ struct translate *(*create_fn)(const struct translate_key *key) = 0;
+
+ struct translate_key key;
+ unsigned output_format;
+ unsigned input_format;
+ unsigned buffer_size = 4096;
+ unsigned char* buffer[5];
+ unsigned char* byte_buffer;
+ float* float_buffer;
+ double* double_buffer;
+ unsigned count = 4;
+ unsigned i, j, k;
+ unsigned passed = 0;
+ unsigned total = 0;
+ const float error = 0.03125;
+
+ create_fn = 0;
+
+ util_cpu_detect();
+
+ if(argc <= 1)
+ {}
+ else if (!strcmp(argv[1], "generic"))
+ create_fn = translate_generic_create;
+ else if (!strcmp(argv[1], "x86"))
+ create_fn = translate_sse2_create;
+ else if (!strcmp(argv[1], "nosse"))
+ {
+ util_cpu_caps.has_sse = 0;
+ util_cpu_caps.has_sse2 = 0;
+ util_cpu_caps.has_sse3 = 0;
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse"))
+ {
+ if(!util_cpu_caps.has_sse || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE (test with qemu)\n");
+ return 2;
+ }
+ util_cpu_caps.has_sse2 = 0;
+ util_cpu_caps.has_sse3 = 0;
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse2"))
+ {
+ if(!util_cpu_caps.has_sse2 || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE2 (test with qemu)\n");
+ return 2;
+ }
+ util_cpu_caps.has_sse3 = 0;
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse3"))
+ {
+ if(!util_cpu_caps.has_sse3 || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE3 (test with qemu)\n");
+ return 2;
+ }
+ util_cpu_caps.has_sse4_1 = 0;
+ create_fn = translate_sse2_create;
+ }
+ else if (!strcmp(argv[1], "sse4.1"))
+ {
+ if(!util_cpu_caps.has_sse4_1 || !rtasm_cpu_has_sse())
+ {
+ printf("Error: CPU doesn't support SSE4.1 (test with qemu)\n");
+ return 2;
+ }
+ create_fn = translate_sse2_create;
+ }
+
+ if (!create_fn)
+ {
+ printf("Usage: ./translate_test [generic|x86|nosse|sse|sse2|sse3|sse4.1]\n");
+ return 2;
+ }
+
+ for (i = 1; i < Elements(buffer); ++i)
+ buffer[i] = align_malloc(buffer_size, 4096);
+
+ byte_buffer = align_malloc(buffer_size, 4096);
+ float_buffer = align_malloc(buffer_size, 4096);
+ double_buffer = align_malloc(buffer_size, 4096);
+
+ key.nr_elements = 1;
+ key.element[0].input_buffer = 0;
+ key.element[0].input_offset = 0;
+ key.element[0].output_offset = 0;
+ key.element[0].type = TRANSLATE_ELEMENT_NORMAL;
+ key.element[0].instance_divisor = 0;
+
+ srand(4359025);
+
+ /* avoid negative values that work badly when converted to unsigned format*/
+ for (i = 0; i < buffer_size; ++i)
+ byte_buffer[i] = rand() & 0x7f7f7f7f;
+
+ for (i = 0; i < buffer_size / sizeof(float); ++i)
+ float_buffer[i] = (float)rand_double();
+
+ for (i = 0; i < buffer_size / sizeof(double); ++i)
+ double_buffer[i] = rand_double();
+
+ for (output_format = 1; output_format < PIPE_FORMAT_COUNT; ++output_format)
+ {
+ const struct util_format_description* output_format_desc = util_format_description(output_format);
+ unsigned output_format_size;
+ unsigned output_normalized = 0;
+
+ if (!output_format_desc
+ || !output_format_desc->fetch_rgba_float
+ || !output_format_desc->pack_rgba_float
+ || output_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB
+ || output_format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN
+ || !translate_is_output_format_supported(output_format))
+ continue;
+
+ for(i = 0; i < output_format_desc->nr_channels; ++i)
+ {
+ if(output_format_desc->channel[i].type != UTIL_FORMAT_TYPE_FLOAT)
+ output_normalized |= (1 << output_format_desc->channel[i].normalized);
+ }
+
+ output_format_size = util_format_get_stride(output_format, 1);
+
+ for (input_format = 1; input_format < PIPE_FORMAT_COUNT; ++input_format)
+ {
+ const struct util_format_description* input_format_desc = util_format_description(input_format);
+ unsigned input_format_size;
+ struct translate* translate[2];
+ unsigned fail = 0;
+ unsigned used_generic = 0;
+ unsigned input_normalized = 0;
+ boolean input_is_float = FALSE;
+
+ if (!input_format_desc
+ || !input_format_desc->fetch_rgba_float
+ || !input_format_desc->pack_rgba_float
+ || input_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB
+ || input_format_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN
+ || !translate_is_output_format_supported(input_format))
+ continue;
+
+ input_format_size = util_format_get_stride(input_format, 1);
+
+ for(i = 0; i < input_format_desc->nr_channels; ++i)
+ {
+ if(input_format_desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
+ {
+ input_is_float = 1;
+ input_normalized |= 1 << 1;
+ }
+ else
+ input_normalized |= (1 << input_format_desc->channel[i].normalized);
+ }
+
+ if(((input_normalized | output_normalized) == 3)
+ || ((input_normalized & 1) && (output_normalized & 1)
+ && input_format_size * output_format_desc->nr_channels > output_format_size * input_format_desc->nr_channels))
+ continue;
+
+ key.element[0].input_format = input_format;
+ key.element[0].output_format = output_format;
+ key.output_stride = output_format_size;
+ translate[0] = create_fn(&key);
+ if (!translate[0])
+ continue;
+
+ key.element[0].input_format = output_format;
+ key.element[0].output_format = input_format;
+ key.output_stride = input_format_size;
+ translate[1] = create_fn(&key);
+ if(!translate[1])
+ {
+ used_generic = 1;
+ translate[1] = translate_generic_create(&key);
+ if(!translate[1])
+ continue;
+ }
+
+ for(i = 1; i < 5; ++i)
+ memset(buffer[i], 0xcd - (0x22 * i), 4096);
+
+ if(input_is_float && input_format_desc->channel[0].size == 32)
+ buffer[0] = (unsigned char*)float_buffer;
+ else if(input_is_float && input_format_desc->channel[0].size == 64)
+ buffer[0] = (unsigned char*)double_buffer;
+ else if(input_is_float)
+ abort();
+ else
+ buffer[0] = byte_buffer;
+
+ translate[0]->set_buffer(translate[0], 0, buffer[0], input_format_size, ~0);
+ translate[0]->run(translate[0], 0, count, 0, buffer[1]);
+ translate[1]->set_buffer(translate[1], 0, buffer[1], output_format_size, ~0);
+ translate[1]->run(translate[1], 0, count, 0, buffer[2]);
+ translate[0]->set_buffer(translate[0], 0, buffer[2], input_format_size, ~0);
+ translate[0]->run(translate[0], 0, count, 0, buffer[3]);
+ translate[1]->set_buffer(translate[1], 0, buffer[3], output_format_size, ~0);
+ translate[1]->run(translate[1], 0, count, 0, buffer[4]);
+
+ for (i = 0; i < count; ++i)
+ {
+ float a[4];
+ float b[4];
+ input_format_desc->fetch_rgba_float(a, buffer[2] + i * input_format_size, 0, 0);
+ input_format_desc->fetch_rgba_float(b, buffer[4] + i * input_format_size, 0, 0);
+
+ for (j = 0; j < count; ++j)
+ {
+ float d = a[j] - b[j];
+ if (d > error || d < -error)
+ {
+ fail = 1;
+ break;
+ }
+ }
+ }
+
+ printf("%s%s: %s -> %s -> %s -> %s -> %s\n",
+ fail ? "FAIL" : "PASS",
+ used_generic ? "[GENERIC]" : "",
+ input_format_desc->name, output_format_desc->name, input_format_desc->name, output_format_desc->name, input_format_desc->name);
+
+ if (1)
+ {
+ for (i = 0; i < Elements(buffer); ++i)
+ {
+ unsigned format_size = (i & 1) ? output_format_size : input_format_size;
+ printf("%c ", (i == 2 || i == 4) ? '*' : ' ');
+ for (j = 0; j < count; ++j)
+ {
+ for (k = 0; k < format_size; ++k)
+ {
+ printf("%02x", buffer[i][j * format_size + k]);
+ }
+ printf(" ");
+ }
+ printf("\n");
+ }
+ }
+
+ if (!fail)
+ ++passed;
+ ++total;
+
+ if(translate[1])
+ translate[1]->release(translate[1]);
+ translate[0]->release(translate[0]);
+ }
+ }
+
+ printf("%u/%u tests passed for translate_%s\n", passed, total, argv[1]);
+ return passed != total;
+}
diff --git a/src/gallium/tests/unit/u_format_compatible_test.c b/src/gallium/tests/unit/u_format_compatible_test.c
new file mode 100644
index 00000000000..c655c35f20a
--- /dev/null
+++ b/src/gallium/tests/unit/u_format_compatible_test.c
@@ -0,0 +1,76 @@
+/**************************************************************************
+ *
+ * Copyright 2009-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "util/u_format.h"
+
+
+static boolean
+test_all(void)
+{
+ enum pipe_format src_format;
+ enum pipe_format dst_format;
+
+ for (src_format = 1; src_format < PIPE_FORMAT_COUNT; ++src_format) {
+ const struct util_format_description *src_format_desc;
+ src_format_desc = util_format_description(src_format);
+ if (!src_format_desc) {
+ continue;
+ }
+
+ for (dst_format = 1; dst_format < PIPE_FORMAT_COUNT; ++dst_format) {
+ const struct util_format_description *dst_format_desc;
+ dst_format_desc = util_format_description(dst_format);
+ if (!dst_format_desc) {
+ continue;
+ }
+
+ if (dst_format == src_format) {
+ continue;
+ }
+
+ if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
+ debug_printf("%s -> %s\n", src_format_desc->short_name, dst_format_desc->short_name);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+int main(int argc, char **argv)
+{
+ boolean success;
+
+ success = test_all();
+
+ return success ? 0 : 1;
+}