summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/python
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/python')
-rw-r--r--src/gallium/state_trackers/python/README43
-rw-r--r--src/gallium/state_trackers/python/SConscript47
-rw-r--r--src/gallium/state_trackers/python/gallium.i103
-rw-r--r--src/gallium/state_trackers/python/p_compiler.i29
-rw-r--r--src/gallium/state_trackers/python/p_context.i319
-rw-r--r--src/gallium/state_trackers/python/p_device.i130
-rw-r--r--src/gallium/state_trackers/python/p_format.i162
-rw-r--r--src/gallium/state_trackers/python/p_state.i137
-rw-r--r--src/gallium/state_trackers/python/p_texture.i450
-rw-r--r--src/gallium/state_trackers/python/retrace/README17
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/format.py173
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/interpreter.py748
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/model.py213
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/parse.py392
-rwxr-xr-xsrc/gallium/state_trackers/python/retrace/parser.py34
-rw-r--r--src/gallium/state_trackers/python/samples/tri.py232
-rw-r--r--src/gallium/state_trackers/python/st_device.c305
-rw-r--r--src/gallium/state_trackers/python/st_device.h106
-rw-r--r--src/gallium/state_trackers/python/st_hardpipe_winsys.c237
-rw-r--r--src/gallium/state_trackers/python/st_sample.c570
-rw-r--r--src/gallium/state_trackers/python/st_sample.h47
-rw-r--r--src/gallium/state_trackers/python/st_softpipe_winsys.c270
-rw-r--r--src/gallium/state_trackers/python/st_winsys.h52
-rw-r--r--src/gallium/state_trackers/python/tests/.gitignore3
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/base.py344
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh10
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh10
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh10
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh8
-rw-r--r--src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py218
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh23
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh23
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh23
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh14
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh14
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh18
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh15
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh16
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh12
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh13
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh11
-rw-r--r--src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py247
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/surface_copy.py199
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/texture_render.py320
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/texture_sample.py591
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/texture_transfer.py179
-rwxr-xr-xsrc/gallium/state_trackers/python/tests/tree.py23
86 files changed, 7652 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/python/README b/src/gallium/state_trackers/python/README
new file mode 100644
index 0000000000..e03d546830
--- /dev/null
+++ b/src/gallium/state_trackers/python/README
@@ -0,0 +1,43 @@
+This directory contains Python bindings to Gallium3D. It looks like a state
+tracker from the pipe driver perspective, and it looks like a pipe driver from
+the python script perspective.
+
+
+To build you'll need:
+* Python (with development packages)
+* SCons
+* SWIG, http://www.swig.org/download.html
+* Python Imaging Library with TK support, http://www.pythonware.com/products/pil/,
+ for the samples
+
+On a debian-based distro you can simply do:
+
+ aptitude install python-dev scons swig python-imaging python-imaging-tk
+
+On a Windows machine ensure the swig command is in your PATH.
+
+Invoke scons on the top dir as
+
+ scons debug=yes statetrackers=python drivers=softpipe,trace winsys=none
+
+To use it set PYTHONPATH appropriately, e.g, in Linux do:
+
+ export PYTHONPATH=$PWD/build/linux-x86-debug/gallium/state_trackers/python
+
+or (in Windows)
+
+ set PYTHONPATH=%CD%\build\windows-x86-debug\gallium\state_trackers\python
+
+and then try running
+
+ python src/gallium/state_trackers/python/samples/tri.py
+
+which should show a triangle.
+
+
+This is still work in progress:
+- errors are not handled properly and almost always result in crash
+- state atoms with array members are awkward to set
+
+--
+Jose Fonseca <jfonseca@vmware.com>
diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript
new file mode 100644
index 0000000000..ec385e7c44
--- /dev/null
+++ b/src/gallium/state_trackers/python/SConscript
@@ -0,0 +1,47 @@
+import sys
+import os.path
+
+Import('*')
+
+if 'python' in env['statetrackers']:
+
+ env = env.Clone()
+
+ env.Tool('python')
+
+ env.Tool('swig')
+ env.Append(SWIGPATH = ['#src/gallium/include', '#src/gallium/include/pipe'])
+ env.Append(SWIGFLAGS = ['-python', '-keyword'])
+
+ env.Append(CPPPATH = '.')
+
+ if env['platform'] == 'windows':
+ env.Append(LIBS = [
+ 'opengl32',
+ 'gdi32',
+ 'user32',
+ 'kernel32',
+ ])
+ else:
+ env.Append(LIBS = [
+ 'GL',
+ 'X11',
+ ])
+
+ pyst = env.ConvenienceLibrary(
+ target = 'pyst',
+ source = [
+ 'gallium.i',
+ 'st_device.c',
+ 'st_sample.c',
+ 'st_softpipe_winsys.c',
+ ],
+ )
+
+ env.SharedLibrary(
+ target = '_gallium',
+ source = [
+ 'st_hardpipe_winsys.c',
+ ],
+ LIBS = [pyst, softpipe, trace] + auxiliaries + env['LIBS'],
+ )
diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i
new file mode 100644
index 0000000000..3f79cc1a3d
--- /dev/null
+++ b/src/gallium/state_trackers/python/gallium.i
@@ -0,0 +1,103 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+%module gallium;
+
+%{
+
+#include <stdio.h>
+
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_shader_tokens.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_draw_quad.h"
+#include "util/u_tile.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_text.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "st_device.h"
+#include "st_sample.h"
+
+%}
+
+%include "typemaps.i"
+%include "exception.i"
+%include "cstring.i"
+
+%include "carrays.i"
+%array_class(unsigned char, ByteArray);
+%array_class(int, IntArray);
+%array_class(unsigned, UnsignedArray);
+%array_class(float, FloatArray);
+
+
+%rename(Device) st_device;
+%rename(Context) st_context;
+%rename(Texture) pipe_texture;
+%rename(Surface) st_surface;
+%rename(Buffer) pipe_buffer;
+
+%rename(BlendColor) pipe_blend_color;
+%rename(Blend) pipe_blend_state;
+%rename(Clip) pipe_clip_state;
+%rename(ConstantBuffer) pipe_constant_buffer;
+%rename(Depth) pipe_depth_state;
+%rename(Stencil) pipe_stencil_state;
+%rename(Alpha) pipe_alpha_state;
+%rename(DepthStencilAlpha) pipe_depth_stencil_alpha_state;
+%rename(FormatBlock) pipe_format_block;
+%rename(Framebuffer) pipe_framebuffer_state;
+%rename(PolyStipple) pipe_poly_stipple;
+%rename(Rasterizer) pipe_rasterizer_state;
+%rename(Sampler) pipe_sampler_state;
+%rename(Scissor) pipe_scissor_state;
+%rename(Shader) pipe_shader_state;
+%rename(VertexBuffer) pipe_vertex_buffer;
+%rename(VertexElement) pipe_vertex_element;
+%rename(Viewport) pipe_viewport_state;
+
+
+%include "p_compiler.i"
+%include "p_defines.h";
+%include "p_format.i"
+
+%include "p_device.i"
+%include "p_context.i"
+%include "p_texture.i"
+%include "p_state.i"
+
diff --git a/src/gallium/state_trackers/python/p_compiler.i b/src/gallium/state_trackers/python/p_compiler.i
new file mode 100644
index 0000000000..15f6ba5b9d
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_compiler.i
@@ -0,0 +1,29 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+
+typedef unsigned char ubyte;
diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i
new file mode 100644
index 0000000000..a40aa1e518
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_context.i
@@ -0,0 +1,319 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+%nodefaultctor st_context;
+%nodefaultdtor st_context;
+
+struct st_context {
+};
+
+%extend st_context {
+
+ ~st_context() {
+ st_context_destroy($self);
+ }
+
+ /*
+ * State functions (create/bind/destroy state objects)
+ */
+
+ void set_blend( const struct pipe_blend_state *state ) {
+ cso_set_blend($self->cso, state);
+ }
+
+ void set_sampler( unsigned index, const struct pipe_sampler_state *state ) {
+ cso_single_sampler($self->cso, index, state);
+ cso_single_sampler_done($self->cso);
+ }
+
+ void set_rasterizer( const struct pipe_rasterizer_state *state ) {
+ cso_set_rasterizer($self->cso, state);
+ }
+
+ void set_depth_stencil_alpha(const struct pipe_depth_stencil_alpha_state *state) {
+ cso_set_depth_stencil_alpha($self->cso, state);
+ }
+
+ void set_fragment_shader( const struct pipe_shader_state *state ) {
+ void *fs;
+
+ if(!state) {
+ cso_set_fragment_shader_handle($self->cso, NULL);
+ return;
+ }
+
+ fs = $self->pipe->create_fs_state($self->pipe, state);
+ if(!fs)
+ return;
+
+ if(cso_set_fragment_shader_handle($self->cso, fs) != PIPE_OK)
+ return;
+
+ cso_delete_fragment_shader($self->cso, $self->fs);
+ $self->fs = fs;
+ }
+
+ void set_vertex_shader( const struct pipe_shader_state *state ) {
+ void *vs;
+
+ if(!state) {
+ cso_set_vertex_shader_handle($self->cso, NULL);
+ return;
+ }
+
+ vs = $self->pipe->create_vs_state($self->pipe, state);
+ if(!vs)
+ return;
+
+ if(cso_set_vertex_shader_handle($self->cso, vs) != PIPE_OK)
+ return;
+
+ cso_delete_vertex_shader($self->cso, $self->vs);
+ $self->vs = vs;
+ }
+
+ /*
+ * Parameter-like state (or properties)
+ */
+
+ void set_blend_color(const struct pipe_blend_color *state ) {
+ cso_set_blend_color($self->cso, state);
+ }
+
+ void set_clip(const struct pipe_clip_state *state ) {
+ $self->pipe->set_clip_state($self->pipe, state);
+ }
+
+ void set_constant_buffer(unsigned shader, unsigned index,
+ struct pipe_buffer *buffer )
+ {
+ struct pipe_constant_buffer state;
+ memset(&state, 0, sizeof(state));
+ state.buffer = buffer;
+ $self->pipe->set_constant_buffer($self->pipe, shader, index, &state);
+ }
+
+ void set_framebuffer(const struct pipe_framebuffer_state *state )
+ {
+ memcpy(&$self->framebuffer, state, sizeof *state);
+ cso_set_framebuffer($self->cso, state);
+ }
+
+ void set_polygon_stipple(const struct pipe_poly_stipple *state ) {
+ $self->pipe->set_polygon_stipple($self->pipe, state);
+ }
+
+ void set_scissor(const struct pipe_scissor_state *state ) {
+ $self->pipe->set_scissor_state($self->pipe, state);
+ }
+
+ void set_viewport(const struct pipe_viewport_state *state) {
+ cso_set_viewport($self->cso, state);
+ }
+
+ void set_sampler_texture(unsigned index,
+ struct pipe_texture *texture) {
+ if(!texture)
+ texture = $self->default_texture;
+ pipe_texture_reference(&$self->sampler_textures[index], texture);
+ $self->pipe->set_sampler_textures($self->pipe,
+ PIPE_MAX_SAMPLERS,
+ $self->sampler_textures);
+ }
+
+ void set_vertex_buffer(unsigned index,
+ unsigned stride,
+ unsigned max_index,
+ unsigned buffer_offset,
+ struct pipe_buffer *buffer)
+ {
+ unsigned i;
+ struct pipe_vertex_buffer state;
+
+ memset(&state, 0, sizeof(state));
+ state.stride = stride;
+ state.max_index = max_index;
+ state.buffer_offset = buffer_offset;
+ state.buffer = buffer;
+
+ memcpy(&$self->vertex_buffers[index], &state, sizeof(state));
+
+ for(i = 0; i < PIPE_MAX_ATTRIBS; ++i)
+ if(self->vertex_buffers[i].buffer)
+ $self->num_vertex_buffers = i + 1;
+
+ $self->pipe->set_vertex_buffers($self->pipe,
+ $self->num_vertex_buffers,
+ $self->vertex_buffers);
+ }
+
+ void set_vertex_element(unsigned index,
+ const struct pipe_vertex_element *element)
+ {
+ memcpy(&$self->vertex_elements[index], element, sizeof(*element));
+ }
+
+ void set_vertex_elements(unsigned num)
+ {
+ $self->num_vertex_elements = num;
+ $self->pipe->set_vertex_elements($self->pipe,
+ $self->num_vertex_elements,
+ $self->vertex_elements);
+ }
+
+ /*
+ * Draw functions
+ */
+
+ void draw_arrays(unsigned mode, unsigned start, unsigned count) {
+ $self->pipe->draw_arrays($self->pipe, mode, start, count);
+ }
+
+ void draw_elements( struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+ {
+ $self->pipe->draw_elements($self->pipe,
+ indexBuffer,
+ indexSize,
+ mode, start, count);
+ }
+
+ void draw_range_elements( struct pipe_buffer *indexBuffer,
+ unsigned indexSize, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count)
+ {
+ $self->pipe->draw_range_elements($self->pipe,
+ indexBuffer,
+ indexSize, minIndex, maxIndex,
+ mode, start, count);
+ }
+
+ void draw_vertices(unsigned prim,
+ unsigned num_verts,
+ unsigned num_attribs,
+ const float *vertices)
+ {
+ struct pipe_context *pipe = $self->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_buffer *vbuf;
+ float *map;
+ unsigned size;
+
+ size = num_verts * num_attribs * 4 * sizeof(float);
+
+ vbuf = pipe_buffer_create(screen,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ size);
+ if(!vbuf)
+ goto error1;
+
+ map = pipe_buffer_map(screen, vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
+ if (!map)
+ goto error2;
+ memcpy(map, vertices, size);
+ pipe_buffer_unmap(screen, vbuf);
+
+ util_draw_vertex_buffer(pipe, vbuf, 0, prim, num_verts, num_attribs);
+
+error2:
+ pipe_buffer_reference(&vbuf, NULL);
+error1:
+ ;
+ }
+
+ void
+ flush(unsigned flags = 0) {
+ struct pipe_fence_handle *fence = NULL;
+ $self->pipe->flush($self->pipe, flags | PIPE_FLUSH_RENDER_CACHE, &fence);
+ if(fence) {
+ /* TODO: allow asynchronous operation */
+ $self->pipe->screen->fence_finish( $self->pipe->screen, fence, 0 );
+ $self->pipe->screen->fence_reference( $self->pipe->screen, &fence, NULL );
+ }
+ }
+
+ /*
+ * Surface functions
+ */
+
+ void surface_copy(struct st_surface *dst,
+ unsigned destx, unsigned desty,
+ struct st_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+ {
+ struct pipe_surface *_dst = NULL;
+ struct pipe_surface *_src = NULL;
+
+ _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_dst)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
+
+ _src = st_pipe_surface(src, PIPE_BUFFER_USAGE_GPU_READ);
+ if(!_src)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire source surface for reading");
+
+ $self->pipe->surface_copy($self->pipe, _dst, destx, desty, _src, srcx, srcy, width, height);
+
+ fail:
+ pipe_surface_reference(&_src, NULL);
+ pipe_surface_reference(&_dst, NULL);
+ }
+
+ void surface_fill(struct st_surface *dst,
+ unsigned x, unsigned y,
+ unsigned width, unsigned height,
+ unsigned value)
+ {
+ struct pipe_surface *_dst = NULL;
+
+ _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_dst)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
+
+ $self->pipe->surface_fill($self->pipe, _dst, x, y, width, height, value);
+
+ fail:
+ pipe_surface_reference(&_dst, NULL);
+ }
+
+ void clear(unsigned buffers, const float *rgba, double depth = 0.0f,
+ unsigned stencil = 0)
+ {
+ $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil);
+ }
+
+};
diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i
new file mode 100644
index 0000000000..f16fe5b0ff
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_device.i
@@ -0,0 +1,130 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+%nodefaultctor st_device;
+%nodefaultdtor st_device;
+
+
+struct st_device {
+};
+
+%newobject st_device::texture_create;
+%newobject st_device::context_create;
+%newobject st_device::buffer_create;
+
+%extend st_device {
+
+ st_device(int hardware = 1) {
+ return st_device_create(hardware ? TRUE : FALSE);
+ }
+
+ ~st_device() {
+ st_device_destroy($self);
+ }
+
+ const char * get_name( void ) {
+ return $self->screen->get_name($self->screen);
+ }
+
+ const char * get_vendor( void ) {
+ return $self->screen->get_vendor($self->screen);
+ }
+
+ /**
+ * Query an integer-valued capability/parameter/limit
+ * \param param one of PIPE_CAP_x
+ */
+ int get_param( int param ) {
+ return $self->screen->get_param($self->screen, param);
+ }
+
+ /**
+ * Query a float-valued capability/parameter/limit
+ * \param param one of PIPE_CAP_x
+ */
+ float get_paramf( int param ) {
+ return $self->screen->get_paramf($self->screen, param);
+ }
+
+ /**
+ * Check if the given pipe_format is supported as a texture or
+ * drawing surface.
+ * \param type one of PIPE_TEXTURE, PIPE_SURFACE
+ */
+ int is_format_supported( enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage,
+ unsigned geom_flags ) {
+ return $self->screen->is_format_supported( $self->screen,
+ format,
+ target,
+ tex_usage,
+ geom_flags );
+ }
+
+ struct st_context *
+ context_create(void) {
+ return st_context_create($self);
+ }
+
+ struct pipe_texture *
+ texture_create(
+ enum pipe_format format,
+ unsigned width,
+ unsigned height,
+ unsigned depth = 1,
+ unsigned last_level = 0,
+ enum pipe_texture_target target = PIPE_TEXTURE_2D,
+ unsigned tex_usage = 0
+ ) {
+ struct pipe_texture templat;
+ memset(&templat, 0, sizeof(templat));
+ templat.format = format;
+ pf_get_block(templat.format, &templat.block);
+ templat.width[0] = width;
+ templat.height[0] = height;
+ templat.depth[0] = depth;
+ templat.last_level = last_level;
+ templat.target = target;
+ templat.tex_usage = tex_usage;
+ return $self->screen->texture_create($self->screen, &templat);
+ }
+
+ struct pipe_buffer *
+ buffer_create(unsigned size, unsigned alignment = 0, unsigned usage = 0) {
+ return pipe_buffer_create($self->screen, alignment, usage, size);
+ }
+
+};
diff --git a/src/gallium/state_trackers/python/p_format.i b/src/gallium/state_trackers/python/p_format.i
new file mode 100644
index 0000000000..26fb12b387
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_format.i
@@ -0,0 +1,162 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2008 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/*
+ * XXX: SWIG can't parse p_format.h, so we need to duplicate the relevant
+ * declarations here
+ */
+
+%{
+#include "pipe/p_format.h"
+%}
+
+enum pipe_format {
+ PIPE_FORMAT_NONE,
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_FORMAT_B8G8R8A8_UNORM,
+ PIPE_FORMAT_B8G8R8X8_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A2B10G10R10_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_I8_UNORM,
+ PIPE_FORMAT_A8L8_UNORM,
+ PIPE_FORMAT_L16_UNORM,
+ PIPE_FORMAT_YCBCR,
+ PIPE_FORMAT_YCBCR_REV,
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z32_FLOAT,
+ PIPE_FORMAT_S8Z24_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_X8Z24_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_R64_FLOAT,
+ PIPE_FORMAT_R64G64_FLOAT,
+ PIPE_FORMAT_R64G64B64_FLOAT,
+ PIPE_FORMAT_R64G64B64A64_FLOAT,
+ PIPE_FORMAT_R32_FLOAT,
+ PIPE_FORMAT_R32G32_FLOAT,
+ PIPE_FORMAT_R32G32B32_FLOAT,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_FORMAT_R32_UNORM,
+ PIPE_FORMAT_R32G32_UNORM,
+ PIPE_FORMAT_R32G32B32_UNORM,
+ PIPE_FORMAT_R32G32B32A32_UNORM,
+ PIPE_FORMAT_R32_USCALED,
+ PIPE_FORMAT_R32G32_USCALED,
+ PIPE_FORMAT_R32G32B32_USCALED,
+ PIPE_FORMAT_R32G32B32A32_USCALED,
+ PIPE_FORMAT_R32_SNORM,
+ PIPE_FORMAT_R32G32_SNORM,
+ PIPE_FORMAT_R32G32B32_SNORM,
+ PIPE_FORMAT_R32G32B32A32_SNORM,
+ PIPE_FORMAT_R32_SSCALED,
+ PIPE_FORMAT_R32G32_SSCALED,
+ PIPE_FORMAT_R32G32B32_SSCALED,
+ PIPE_FORMAT_R32G32B32A32_SSCALED,
+ PIPE_FORMAT_R16_UNORM,
+ PIPE_FORMAT_R16G16_UNORM,
+ PIPE_FORMAT_R16G16B16_UNORM,
+ PIPE_FORMAT_R16G16B16A16_UNORM,
+ PIPE_FORMAT_R16_USCALED,
+ PIPE_FORMAT_R16G16_USCALED,
+ PIPE_FORMAT_R16G16B16_USCALED,
+ PIPE_FORMAT_R16G16B16A16_USCALED,
+ PIPE_FORMAT_R16_SNORM,
+ PIPE_FORMAT_R16G16_SNORM,
+ PIPE_FORMAT_R16G16B16_SNORM,
+ PIPE_FORMAT_R16G16B16A16_SNORM,
+ PIPE_FORMAT_R16_SSCALED,
+ PIPE_FORMAT_R16G16_SSCALED,
+ PIPE_FORMAT_R16G16B16_SSCALED,
+ PIPE_FORMAT_R16G16B16A16_SSCALED,
+ PIPE_FORMAT_R8_UNORM,
+ PIPE_FORMAT_R8G8_UNORM,
+ PIPE_FORMAT_R8G8B8_UNORM,
+ PIPE_FORMAT_R8G8B8A8_UNORM,
+ PIPE_FORMAT_R8G8B8X8_UNORM,
+ PIPE_FORMAT_R8_USCALED,
+ PIPE_FORMAT_R8G8_USCALED,
+ PIPE_FORMAT_R8G8B8_USCALED,
+ PIPE_FORMAT_R8G8B8A8_USCALED,
+ PIPE_FORMAT_R8G8B8X8_USCALED,
+ PIPE_FORMAT_R8_SNORM,
+ PIPE_FORMAT_R8G8_SNORM,
+ PIPE_FORMAT_R8G8B8_SNORM,
+ PIPE_FORMAT_R8G8B8A8_SNORM,
+ PIPE_FORMAT_R8G8B8X8_SNORM,
+ PIPE_FORMAT_B6G5R5_SNORM,
+ PIPE_FORMAT_A8B8G8R8_SNORM,
+ PIPE_FORMAT_X8B8G8R8_SNORM,
+ PIPE_FORMAT_R8_SSCALED,
+ PIPE_FORMAT_R8G8_SSCALED,
+ PIPE_FORMAT_R8G8B8_SSCALED,
+ PIPE_FORMAT_R8G8B8A8_SSCALED,
+ PIPE_FORMAT_R8G8B8X8_SSCALED,
+ PIPE_FORMAT_R32_FIXED,
+ PIPE_FORMAT_R32G32_FIXED,
+ PIPE_FORMAT_R32G32B32_FIXED,
+ PIPE_FORMAT_R32G32B32A32_FIXED,
+
+ PIPE_FORMAT_L8_SRGB,
+ PIPE_FORMAT_A8L8_SRGB,
+ PIPE_FORMAT_R8G8B8_SRGB,
+ PIPE_FORMAT_R8G8B8A8_SRGB,
+ PIPE_FORMAT_R8G8B8X8_SRGB,
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_X8R8G8B8_SRGB,
+ PIPE_FORMAT_B8G8R8A8_SRGB,
+ PIPE_FORMAT_B8G8R8X8_SRGB,
+
+ PIPE_FORMAT_X8UB8UG8SR8S_NORM,
+ PIPE_FORMAT_B6UG5SR5S_NORM,
+
+ PIPE_FORMAT_DXT1_RGB,
+ PIPE_FORMAT_DXT1_RGBA,
+ PIPE_FORMAT_DXT3_RGBA,
+ PIPE_FORMAT_DXT5_RGBA,
+
+ PIPE_FORMAT_DXT1_SRGB,
+ PIPE_FORMAT_DXT1_SRGBA,
+ PIPE_FORMAT_DXT3_SRGBA,
+ PIPE_FORMAT_DXT5_SRGBA,
+};
+
+
+struct pipe_format_block
+{
+ unsigned size;
+ unsigned width;
+ unsigned height;
+};
+
diff --git a/src/gallium/state_trackers/python/p_state.i b/src/gallium/state_trackers/python/p_state.i
new file mode 100644
index 0000000000..90f157e0ab
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_state.i
@@ -0,0 +1,137 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+%module gallium;
+
+%ignore winsys;
+%ignore pipe_vertex_buffer::buffer;
+
+%include "pipe/p_compiler.h";
+%include "pipe/p_state.h";
+
+
+%array_class(struct pipe_stencil_state, StencilArray);
+
+
+%extend pipe_framebuffer_state {
+
+ pipe_framebuffer_state(void) {
+ return CALLOC_STRUCT(pipe_framebuffer_state);
+ }
+
+ ~pipe_framebuffer_state() {
+ unsigned index;
+ for(index = 0; index < PIPE_MAX_COLOR_BUFS; ++index)
+ pipe_surface_reference(&$self->cbufs[index], NULL);
+ pipe_surface_reference(&$self->zsbuf, NULL);
+ FREE($self);
+ }
+
+ void
+ set_cbuf(unsigned index, struct st_surface *surface)
+ {
+ struct pipe_surface *_surface = NULL;
+
+ if(index >= PIPE_MAX_COLOR_BUFS)
+ SWIG_exception(SWIG_ValueError, "index out of bounds");
+
+ if(surface) {
+ _surface = st_pipe_surface(surface, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_surface)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing");
+ }
+
+ pipe_surface_reference(&$self->cbufs[index], _surface);
+
+ fail:
+ return;
+ }
+
+ void
+ set_zsbuf(struct st_surface *surface)
+ {
+ struct pipe_surface *_surface = NULL;
+
+ if(surface) {
+ _surface = st_pipe_surface(surface, PIPE_BUFFER_USAGE_GPU_WRITE);
+ if(!_surface)
+ SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing");
+ }
+
+ pipe_surface_reference(&$self->zsbuf, _surface);
+
+ fail:
+ return;
+ }
+
+};
+
+
+%extend pipe_shader_state {
+
+ pipe_shader_state(const char *text, unsigned num_tokens = 1024) {
+ struct tgsi_token *tokens;
+ struct pipe_shader_state *shader;
+
+ tokens = MALLOC(num_tokens * sizeof(struct tgsi_token));
+ if(!tokens)
+ goto error1;
+
+ if(tgsi_text_translate(text, tokens, num_tokens ) != TRUE)
+ goto error2;
+
+ shader = CALLOC_STRUCT(pipe_shader_state);
+ if(!shader)
+ goto error3;
+
+ shader->tokens = tokens;
+
+ return shader;
+
+error3:
+error2:
+ FREE(tokens);
+error1:
+ return NULL;
+ }
+
+ ~pipe_shader_state() {
+ FREE((void*)$self->tokens);
+ FREE($self);
+ }
+
+ void dump(unsigned flags = 0) {
+ tgsi_dump($self->tokens, flags);
+ }
+}
diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i
new file mode 100644
index 0000000000..1d513abf3c
--- /dev/null
+++ b/src/gallium/state_trackers/python/p_texture.i
@@ -0,0 +1,450 @@
+ /**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * SWIG interface definion for Gallium types.
+ *
+ * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
+ */
+
+
+%nodefaultctor pipe_texture;
+%nodefaultctor st_surface;
+%nodefaultctor pipe_buffer;
+
+%nodefaultdtor pipe_texture;
+%nodefaultdtor st_surface;
+%nodefaultdtor pipe_buffer;
+
+%ignore pipe_texture::screen;
+
+%immutable st_surface::texture;
+%immutable st_surface::face;
+%immutable st_surface::level;
+%immutable st_surface::zslice;
+
+%newobject pipe_texture::get_surface;
+
+
+%extend pipe_texture {
+
+ ~pipe_texture() {
+ struct pipe_texture *ptr = $self;
+ pipe_texture_reference(&ptr, NULL);
+ }
+
+ unsigned get_width(unsigned level=0) {
+ return $self->width[level];
+ }
+
+ unsigned get_height(unsigned level=0) {
+ return $self->height[level];
+ }
+
+ unsigned get_depth(unsigned level=0) {
+ return $self->depth[level];
+ }
+
+ unsigned get_nblocksx(unsigned level=0) {
+ return $self->nblocksx[level];
+ }
+
+ unsigned get_nblocksy(unsigned level=0) {
+ return $self->nblocksy[level];
+ }
+
+ /** Get a surface which is a "view" into a texture */
+ struct st_surface *
+ get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0)
+ {
+ struct st_surface *surface;
+
+ if(face >= ($self->target == PIPE_TEXTURE_CUBE ? 6U : 1U))
+ SWIG_exception(SWIG_ValueError, "face out of bounds");
+ if(level > $self->last_level)
+ SWIG_exception(SWIG_ValueError, "level out of bounds");
+ if(zslice >= $self->depth[level])
+ SWIG_exception(SWIG_ValueError, "zslice out of bounds");
+
+ surface = CALLOC_STRUCT(st_surface);
+ if(!surface)
+ return NULL;
+
+ pipe_texture_reference(&surface->texture, $self);
+ surface->face = face;
+ surface->level = level;
+ surface->zslice = zslice;
+
+ return surface;
+
+ fail:
+ return NULL;
+ }
+
+};
+
+struct st_surface
+{
+ %immutable;
+
+ struct pipe_texture *texture;
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+
+};
+
+%extend st_surface {
+
+ %immutable;
+
+ unsigned format;
+ unsigned width;
+ unsigned height;
+ unsigned nblocksx;
+ unsigned nblocksy;
+
+ ~st_surface() {
+ pipe_texture_reference(&$self->texture, NULL);
+ FREE($self);
+ }
+
+ %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
+ void get_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH)
+ {
+ struct pipe_texture *texture = $self->texture;
+ struct pipe_screen *screen = texture->screen;
+ struct pipe_transfer *transfer;
+ unsigned stride;
+
+ stride = pf_get_nblocksx(&texture->block, w) * texture->block.size;
+ *LENGTH = pf_get_nblocksy(&texture->block, h) * stride;
+ *STRING = (char *) malloc(*LENGTH);
+ if(!*STRING)
+ return;
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(transfer) {
+ pipe_get_tile_raw(transfer, 0, 0, w, h, *STRING, stride);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ %cstring_input_binary(const char *STRING, unsigned LENGTH);
+ void put_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, const char *STRING, unsigned LENGTH, unsigned stride = 0)
+ {
+ struct pipe_texture *texture = $self->texture;
+ struct pipe_screen *screen = texture->screen;
+ struct pipe_transfer *transfer;
+
+ if(stride == 0)
+ stride = pf_get_nblocksx(&texture->block, w) * texture->block.size;
+
+ if(LENGTH < pf_get_nblocksy(&texture->block, h) * stride)
+ SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_WRITE,
+ x, y, w, h);
+ if(!transfer)
+ SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer");
+
+ pipe_put_tile_raw(transfer, 0, 0, w, h, STRING, stride);
+ screen->tex_transfer_destroy(transfer);
+
+ fail:
+ return;
+ }
+
+ void
+ get_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, float *rgba)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(transfer) {
+ pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ void
+ put_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_WRITE,
+ x, y, w, h);
+ if(transfer) {
+ pipe_put_tile_rgba(transfer, 0, 0, w, h, rgba);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
+ void
+ get_tile_rgba8(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ float *rgba;
+ unsigned char *rgba8;
+ unsigned i, j, k;
+
+ *LENGTH = 0;
+ *STRING = NULL;
+
+ if (!$self)
+ return;
+
+ *LENGTH = h*w*4;
+ *STRING = (char *) malloc(*LENGTH);
+ if(!*STRING)
+ return;
+
+ rgba = malloc(h*w*4*sizeof(float));
+ if(!rgba)
+ return;
+
+ rgba8 = (unsigned char *) *STRING;
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y,
+ w, h);
+ if(transfer) {
+ pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba);
+ for(j = 0; j < h; ++j) {
+ for(i = 0; i < w; ++i)
+ for(k = 0; k <4; ++k)
+ rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]);
+ }
+ screen->tex_transfer_destroy(transfer);
+ }
+
+ free(rgba);
+ }
+
+ void
+ get_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, unsigned *z)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(transfer) {
+ pipe_get_tile_z(transfer, 0, 0, w, h, z);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ void
+ put_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, const unsigned *z)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_WRITE,
+ x, y, w, h);
+ if(transfer) {
+ pipe_put_tile_z(transfer, 0, 0, w, h, z);
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ void
+ sample_rgba(float *rgba) {
+ st_sample_surface($self, rgba);
+ }
+
+ unsigned
+ compare_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba, float tol = 0.0)
+ {
+ struct pipe_screen *screen = $self->texture->screen;
+ struct pipe_transfer *transfer;
+ float *rgba2;
+ const float *p1;
+ const float *p2;
+ unsigned i, j, n;
+
+ rgba2 = MALLOC(h*w*4*sizeof(float));
+ if(!rgba2)
+ return ~0;
+
+ transfer = screen->get_tex_transfer(screen,
+ $self->texture,
+ $self->face,
+ $self->level,
+ $self->zslice,
+ PIPE_TRANSFER_READ,
+ x, y, w, h);
+ if(!transfer) {
+ FREE(rgba2);
+ return ~0;
+ }
+
+ pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba2);
+ screen->tex_transfer_destroy(transfer);
+
+ p1 = rgba;
+ p2 = rgba2;
+ n = 0;
+ for(i = h*w; i; --i) {
+ unsigned differs = 0;
+ for(j = 4; j; --j) {
+ float delta = *p2++ - *p1++;
+ if (delta < -tol || delta > tol)
+ differs = 1;
+ }
+ n += differs;
+ }
+
+ FREE(rgba2);
+
+ return n;
+ }
+
+};
+
+%{
+ static enum pipe_format
+ st_surface_format_get(struct st_surface *surface)
+ {
+ return surface->texture->format;
+ }
+
+ static unsigned
+ st_surface_width_get(struct st_surface *surface)
+ {
+ return surface->texture->width[surface->level];
+ }
+
+ static unsigned
+ st_surface_height_get(struct st_surface *surface)
+ {
+ return surface->texture->height[surface->level];
+ }
+
+ static unsigned
+ st_surface_nblocksx_get(struct st_surface *surface)
+ {
+ return surface->texture->nblocksx[surface->level];
+ }
+
+ static unsigned
+ st_surface_nblocksy_get(struct st_surface *surface)
+ {
+ return surface->texture->nblocksy[surface->level];
+ }
+%}
+
+/* Avoid naming conflict with p_inlines.h's pipe_buffer_read/write */
+%rename(read) read_;
+%rename(write) write_;
+
+%extend pipe_buffer {
+
+ ~pipe_buffer() {
+ struct pipe_buffer *ptr = $self;
+ pipe_buffer_reference(&ptr, NULL);
+ }
+
+ unsigned __len__(void)
+ {
+ assert(p_atomic_read(&$self->reference.count) > 0);
+ return $self->size;
+ }
+
+ %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
+ void read_(char **STRING, int *LENGTH)
+ {
+ struct pipe_screen *screen = $self->screen;
+
+ assert(p_atomic_read(&$self->reference.count) > 0);
+
+ *LENGTH = $self->size;
+ *STRING = (char *) malloc($self->size);
+ if(!*STRING)
+ return;
+
+ pipe_buffer_read(screen, $self, 0, $self->size, *STRING);
+ }
+
+ %cstring_input_binary(const char *STRING, unsigned LENGTH);
+ void write_(const char *STRING, unsigned LENGTH, unsigned offset = 0)
+ {
+ struct pipe_screen *screen = $self->screen;
+
+ assert(p_atomic_read(&$self->reference.count) > 0);
+
+ if(offset > $self->size)
+ SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
+
+ if(offset + LENGTH > $self->size)
+ SWIG_exception(SWIG_ValueError, "data length must fit inside the buffer");
+
+ pipe_buffer_write(screen, $self, offset, LENGTH, STRING);
+
+fail:
+ return;
+ }
+};
diff --git a/src/gallium/state_trackers/python/retrace/README b/src/gallium/state_trackers/python/retrace/README
new file mode 100644
index 0000000000..822cd11404
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/README
@@ -0,0 +1,17 @@
+This is an application written in python to replay the traces captured by the
+ trace pipe driver.
+
+
+To use it follow the instructions in src/gallium/drivers/trace/README and
+src/gallium/state_trackers/python/README, and then do
+
+ python src/gallium/state_trackers/python/samples/retrace/interpreter.py filename.trace
+
+
+This is still work in progress:
+- not everything is captured/replayed
+ - surface/textures contents
+- any tiny error will result in a crash
+
+--
+Jose Fonseca <jrfonseca@tungstengraphics.com>
diff --git a/src/gallium/state_trackers/python/retrace/format.py b/src/gallium/state_trackers/python/retrace/format.py
new file mode 100755
index 0000000000..a4285bfe07
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/format.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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 TUNGSTEN GRAPHICS 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.
+#
+##########################################################################
+
+
+import sys
+
+
+class Formatter:
+ '''Plain formatter'''
+
+ def __init__(self, stream):
+ self.stream = stream
+
+ def text(self, text):
+ self.stream.write(text)
+
+ def newline(self):
+ self.text('\n')
+
+ def function(self, name):
+ self.text(name)
+
+ def variable(self, name):
+ self.text(name)
+
+ def literal(self, value):
+ self.text(str(value))
+
+ def address(self, addr):
+ self.text(str(addr))
+
+
+class AnsiFormatter(Formatter):
+ '''Formatter for plain-text files which outputs ANSI escape codes. See
+ http://en.wikipedia.org/wiki/ANSI_escape_code for more information
+ concerning ANSI escape codes.
+ '''
+
+ _csi = '\33['
+
+ _normal = '0m'
+ _bold = '1m'
+ _italic = '3m'
+ _red = '31m'
+ _green = '32m'
+ _blue = '34m'
+
+ def _escape(self, code):
+ self.text(self._csi + code)
+
+ def function(self, name):
+ self._escape(self._bold)
+ Formatter.function(self, name)
+ self._escape(self._normal)
+
+ def variable(self, name):
+ self._escape(self._italic)
+ Formatter.variable(self, name)
+ self._escape(self._normal)
+
+ def literal(self, value):
+ self._escape(self._blue)
+ Formatter.literal(self, value)
+ self._escape(self._normal)
+
+ def address(self, value):
+ self._escape(self._green)
+ Formatter.address(self, value)
+ self._escape(self._normal)
+
+
+class WindowsConsoleFormatter(Formatter):
+ '''Formatter for the Windows Console. See
+ http://code.activestate.com/recipes/496901/ for more information.
+ '''
+
+ STD_INPUT_HANDLE = -10
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+
+ FOREGROUND_BLUE = 0x01
+ FOREGROUND_GREEN = 0x02
+ FOREGROUND_RED = 0x04
+ FOREGROUND_INTENSITY = 0x08
+ BACKGROUND_BLUE = 0x10
+ BACKGROUND_GREEN = 0x20
+ BACKGROUND_RED = 0x40
+ BACKGROUND_INTENSITY = 0x80
+
+ _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+ _bold = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
+ _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
+ _red = FOREGROUND_RED | FOREGROUND_INTENSITY
+ _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY
+ _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY
+
+ def __init__(self, stream):
+ Formatter.__init__(self, stream)
+
+ if stream is sys.stdin:
+ nStdHandle = self.STD_INPUT_HANDLE
+ elif stream is sys.stdout:
+ nStdHandle = self.STD_OUTPUT_HANDLE
+ elif stream is sys.stderr:
+ nStdHandle = self.STD_ERROR_HANDLE
+ else:
+ nStdHandle = None
+
+ if nStdHandle:
+ import ctypes
+ self.handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle)
+ else:
+ self.handle = None
+
+ def _attribute(self, attr):
+ if self.handle:
+ import ctypes
+ ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, attr)
+
+ def function(self, name):
+ self._attribute(self._bold)
+ Formatter.function(self, name)
+ self._attribute(self._normal)
+
+ def variable(self, name):
+ self._attribute(self._italic)
+ Formatter.variable(self, name)
+ self._attribute(self._normal)
+
+ def literal(self, value):
+ self._attribute(self._blue)
+ Formatter.literal(self, value)
+ self._attribute(self._normal)
+
+ def address(self, value):
+ self._attribute(self._green)
+ Formatter.address(self, value)
+ self._attribute(self._normal)
+
+
+def DefaultFormatter(stream):
+ if sys.platform in ('linux2', 'cygwin'):
+ return AnsiFormatter(stream)
+ elif sys.platform in ('win32',):
+ return WindowsConsoleFormatter(stream)
+ else:
+ return Formatter(stream)
+
diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py
new file mode 100755
index 0000000000..6f0bd6ae52
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/interpreter.py
@@ -0,0 +1,748 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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 TUNGSTEN GRAPHICS 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.
+#
+##########################################################################
+
+
+import sys
+import struct
+
+import gallium
+import model
+import parse as parser
+
+
+try:
+ from struct import unpack_from
+except ImportError:
+ def unpack_from(fmt, buf, offset=0):
+ size = struct.calcsize(fmt)
+ return struct.unpack(fmt, buf[offset:offset + size])
+
+
+def make_image(surface, x=None, y=None, w=None, h=None):
+ if x is None:
+ x = 0
+ if y is None:
+ y = 0
+ if w is None:
+ w = surface.width - x
+ if h is None:
+ h = surface.height - y
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface, x=None, y=None, w=None, h=None):
+ outimage = make_image(surface, x, y, w, h)
+ outimage.save(filename, "PNG")
+
+def show_image(surface, title, x=None, y=None, w=None, h=None):
+ outimage = make_image(surface, x, y, w, h)
+
+ import Tkinter as tk
+ from PIL import Image, ImageTk
+ root = tk.Tk()
+
+ root.title(title)
+
+ image1 = ImageTk.PhotoImage(outimage)
+ w = image1.width()
+ h = image1.height()
+ x = 100
+ y = 100
+ root.geometry("%dx%d+%d+%d" % (w, h, x, y))
+ panel1 = tk.Label(root, image=image1)
+ panel1.pack(side='top', fill='both', expand='yes')
+ panel1.image = image1
+ root.mainloop()
+
+
+class Struct:
+ """C-like struct"""
+
+ # A basic Python class can pass as a C-like structure
+ pass
+
+
+struct_factories = {
+ "pipe_blend_color": gallium.BlendColor,
+ "pipe_blend_state": gallium.Blend,
+ #"pipe_clip_state": gallium.Clip,
+ #"pipe_constant_buffer": gallium.ConstantBuffer,
+ "pipe_depth_state": gallium.Depth,
+ "pipe_stencil_state": gallium.Stencil,
+ "pipe_alpha_state": gallium.Alpha,
+ "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha,
+ "pipe_format_block": gallium.FormatBlock,
+ #"pipe_framebuffer_state": gallium.Framebuffer,
+ "pipe_poly_stipple": gallium.PolyStipple,
+ "pipe_rasterizer_state": gallium.Rasterizer,
+ "pipe_sampler_state": gallium.Sampler,
+ "pipe_scissor_state": gallium.Scissor,
+ #"pipe_shader_state": gallium.Shader,
+ #"pipe_vertex_buffer": gallium.VertexBuffer,
+ "pipe_vertex_element": gallium.VertexElement,
+ "pipe_viewport_state": gallium.Viewport,
+ #"pipe_texture": gallium.Texture,
+}
+
+
+member_array_factories = {
+ "pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray},
+ "pipe_poly_stipple": {"stipple": gallium.UnsignedArray},
+ "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray},
+ #"pipe_clip_state": {"ucp": gallium.FloatArray},
+ "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray},
+ "pipe_blend_color": {"color": gallium.FloatArray},
+ "pipe_sampler_state": {"border_color": gallium.FloatArray},
+}
+
+
+class Translator(model.Visitor):
+ """Translate model arguments into regular Python objects"""
+
+ def __init__(self, interpreter):
+ self.interpreter = interpreter
+ self.result = None
+
+ def visit(self, node):
+ self.result = None
+ node.visit(self)
+ return self.result
+
+ def visit_literal(self, node):
+ self.result = node.value
+
+ def visit_named_constant(self, node):
+ # lookup the named constant in the gallium module
+ self.result = getattr(gallium, node.name)
+
+ def visit_array(self, node):
+ array = []
+ for element in node.elements:
+ array.append(self.visit(element))
+ self.result = array
+
+ def visit_struct(self, node):
+ struct_factory = struct_factories.get(node.name, Struct)
+ struct = struct_factory()
+ for member_name, member_node in node.members:
+ member_value = self.visit(member_node)
+ try:
+ array_factory = member_array_factories[node.name][member_name]
+ except KeyError:
+ pass
+ else:
+ assert isinstance(member_value, list)
+ array = array_factory(len(member_value))
+ for i in range(len(member_value)):
+ array[i] = member_value[i]
+ member_value = array
+ #print node.name, member_name, member_value
+ assert isinstance(struct, Struct) or hasattr(struct, member_name)
+ setattr(struct, member_name, member_value)
+ self.result = struct
+
+ def visit_pointer(self, node):
+ self.result = self.interpreter.lookup_object(node.address)
+
+
+class Object:
+
+ def __init__(self, interpreter, real):
+ self.interpreter = interpreter
+ self.real = real
+
+
+class Global(Object):
+
+ def __init__(self, interpreter, real):
+ self.interpreter = interpreter
+ self.real = real
+
+ def pipe_winsys_create(self):
+ return Winsys(self.interpreter, gallium.Device())
+
+ def pipe_screen_create(self, winsys=None):
+ if winsys is None:
+ real = gallium.Device()
+ else:
+ real = winsys.real
+ return Screen(self.interpreter, real)
+
+ def pipe_context_create(self, screen):
+ context = screen.real.context_create()
+ return Context(self.interpreter, context)
+
+
+class Winsys(Object):
+
+ def __init__(self, interpreter, real):
+ self.interpreter = interpreter
+ self.real = real
+
+ def get_name(self):
+ pass
+
+ def user_buffer_create(self, data, size):
+ # We don't really care to distinguish between user and regular buffers
+ buffer = self.real.buffer_create(size,
+ 4,
+ gallium.PIPE_BUFFER_USAGE_CPU_READ |
+ gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
+ assert size == len(data)
+ buffer.write(data)
+ return buffer
+
+ def buffer_create(self, alignment, usage, size):
+ return self.real.buffer_create(size, alignment, usage)
+
+ def buffer_destroy(self, buffer):
+ pass
+
+ def buffer_write(self, buffer, data, size):
+ assert size == len(data)
+ buffer.write(data)
+
+ def fence_finish(self, fence, flags):
+ pass
+
+ def fence_reference(self, dst, src):
+ pass
+
+ def flush_frontbuffer(self, surface):
+ pass
+
+ def surface_alloc(self):
+ return None
+
+ def surface_release(self, surface):
+ pass
+
+
+class Transfer:
+
+ def __init__(self, surface, x, y, w, h):
+ self.surface = surface
+ self.x = x
+ self.y = y
+ self.w = w
+ self.h = h
+
+
+class Screen(Object):
+
+ def destroy(self):
+ pass
+
+ def get_name(self):
+ pass
+
+ def get_vendor(self):
+ pass
+
+ def get_param(self, param):
+ pass
+
+ def get_paramf(self, param):
+ pass
+
+ def is_format_supported(self, format, target, tex_usage, geom_flags):
+ return self.real.is_format_supported(format, target, tex_usage, geom_flags)
+
+ def texture_create(self, templat):
+ return self.real.texture_create(
+ format = templat.format,
+ width = templat.width[0],
+ height = templat.height[0],
+ depth = templat.depth[0],
+ last_level = templat.last_level,
+ target = templat.target,
+ tex_usage = templat.tex_usage,
+ )
+
+ def texture_destroy(self, texture):
+ self.interpreter.unregister_object(texture)
+
+ def texture_release(self, surface):
+ pass
+
+ def get_tex_surface(self, texture, face, level, zslice, usage):
+ if texture is None:
+ return None
+ return texture.get_surface(face, level, zslice)
+
+ def tex_surface_destroy(self, surface):
+ self.interpreter.unregister_object(surface)
+
+ def tex_surface_release(self, surface):
+ pass
+
+ def surface_write(self, surface, data, stride, size):
+ if surface is None:
+ return
+ assert surface.nblocksy * stride == size
+ surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride)
+
+ def get_tex_transfer(self, texture, face, level, zslice, usage, x, y, w, h):
+ if texture is None:
+ return None
+ transfer = Transfer(texture.get_surface(face, level, zslice), x, y, w, h)
+ if transfer and usage != gallium.PIPE_TRANSFER_WRITE:
+ if self.interpreter.options.all:
+ self.interpreter.present(transfer.surface, 'transf_read', x, y, w, h)
+ return transfer
+
+ def tex_transfer_destroy(self, transfer):
+ self.interpreter.unregister_object(transfer)
+
+ def transfer_write(self, transfer, stride, data, size):
+ if transfer is None:
+ return
+ transfer.surface.put_tile_raw(transfer.x, transfer.y, transfer.w, transfer.h, data, stride)
+ if self.interpreter.options.all:
+ self.interpreter.present(transfer.surface, 'transf_write', transfer.x, transfer.y, transfer.w, transfer.h)
+
+ def user_buffer_create(self, data, size):
+ # We don't really care to distinguish between user and regular buffers
+ buffer = self.real.buffer_create(size,
+ 4,
+ gallium.PIPE_BUFFER_USAGE_CPU_READ |
+ gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
+ assert size == len(data)
+ buffer.write(data)
+ return buffer
+
+ def buffer_create(self, alignment, usage, size):
+ return self.real.buffer_create(size, alignment, usage)
+
+ def buffer_destroy(self, buffer):
+ pass
+
+ def buffer_write(self, buffer, data, size, offset=0):
+ assert size == len(data)
+ buffer.write(data)
+
+ def fence_finish(self, fence, flags):
+ pass
+
+ def fence_reference(self, dst, src):
+ pass
+
+ def flush_frontbuffer(self, surface):
+ pass
+
+
+class Context(Object):
+
+ def __init__(self, interpreter, real):
+ Object.__init__(self, interpreter, real)
+ self.cbufs = []
+ self.zsbuf = None
+ self.vbufs = []
+ self.velems = []
+ self.dirty = False
+
+ def destroy(self):
+ pass
+
+ def create_blend_state(self, state):
+ return state
+
+ def bind_blend_state(self, state):
+ if state is not None:
+ self.real.set_blend(state)
+
+ def delete_blend_state(self, state):
+ pass
+
+ def create_sampler_state(self, state):
+ return state
+
+ def delete_sampler_state(self, state):
+ pass
+
+ def bind_sampler_states(self, num_states, states):
+ for i in range(num_states):
+ self.real.set_sampler(i, states[i])
+
+ def create_rasterizer_state(self, state):
+ return state
+
+ def bind_rasterizer_state(self, state):
+ if state is not None:
+ self.real.set_rasterizer(state)
+
+ def delete_rasterizer_state(self, state):
+ pass
+
+ def create_depth_stencil_alpha_state(self, state):
+ return state
+
+ def bind_depth_stencil_alpha_state(self, state):
+ if state is not None:
+ self.real.set_depth_stencil_alpha(state)
+
+ def delete_depth_stencil_alpha_state(self, state):
+ pass
+
+ def create_fs_state(self, state):
+ tokens = str(state.tokens)
+ shader = gallium.Shader(tokens)
+ return shader
+
+ create_vs_state = create_fs_state
+
+ def bind_fs_state(self, state):
+ self.real.set_fragment_shader(state)
+
+ def bind_vs_state(self, state):
+ self.real.set_vertex_shader(state)
+
+ def delete_fs_state(self, state):
+ pass
+
+ delete_vs_state = delete_fs_state
+
+ def set_blend_color(self, state):
+ self.real.set_blend_color(state)
+
+ def set_clip_state(self, state):
+ _state = gallium.Clip()
+ _state.nr = state.nr
+ if state.nr:
+ # FIXME
+ ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4)
+ for i in range(len(state.ucp)):
+ for j in range(len(state.ucp[i])):
+ ucp[i*4 + j] = state.ucp[i][j]
+ _state.ucp = ucp
+ self.real.set_clip(_state)
+
+ def dump_constant_buffer(self, buffer):
+ if not self.interpreter.verbosity(2):
+ return
+
+ data = buffer.read()
+ format = '4f'
+ index = 0
+ for offset in range(0, len(data), struct.calcsize(format)):
+ x, y, z, w = unpack_from(format, data, offset)
+ sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
+ index += 1
+ sys.stdout.flush()
+
+ def set_constant_buffer(self, shader, index, buffer):
+ if buffer is not None:
+ self.real.set_constant_buffer(shader, index, buffer.buffer)
+
+ self.dump_constant_buffer(buffer.buffer)
+
+ def set_framebuffer_state(self, state):
+ _state = gallium.Framebuffer()
+ _state.width = state.width
+ _state.height = state.height
+ _state.nr_cbufs = state.nr_cbufs
+ for i in range(len(state.cbufs)):
+ _state.set_cbuf(i, state.cbufs[i])
+ _state.set_zsbuf(state.zsbuf)
+ self.real.set_framebuffer(_state)
+
+ self.cbufs = state.cbufs
+ self.zsbuf = state.zsbuf
+
+ def set_polygon_stipple(self, state):
+ self.real.set_polygon_stipple(state)
+
+ def set_scissor_state(self, state):
+ self.real.set_scissor(state)
+
+ def set_viewport_state(self, state):
+ self.real.set_viewport(state)
+
+ def set_sampler_textures(self, num_textures, textures):
+ for i in range(num_textures):
+ self.real.set_sampler_texture(i, textures[i])
+
+ def set_vertex_buffers(self, num_buffers, buffers):
+ self.vbufs = buffers[0:num_buffers]
+ for i in range(num_buffers):
+ vbuf = buffers[i]
+ self.real.set_vertex_buffer(
+ i,
+ stride = vbuf.stride,
+ max_index = vbuf.max_index,
+ buffer_offset = vbuf.buffer_offset,
+ buffer = vbuf.buffer,
+ )
+
+ def set_vertex_elements(self, num_elements, elements):
+ self.velems = elements[0:num_elements]
+ for i in range(num_elements):
+ self.real.set_vertex_element(i, elements[i])
+ self.real.set_vertex_elements(num_elements)
+
+ def set_edgeflags(self, bitfield):
+ # FIXME
+ pass
+
+ def dump_vertices(self, start, count):
+ if not self.interpreter.verbosity(2):
+ return
+
+ for index in range(start, start + count):
+ if index >= start + 16:
+ sys.stdout.write('\t...\n')
+ break
+ sys.stdout.write('\t{\n')
+ for velem in self.velems:
+ vbuf = self.vbufs[velem.vertex_buffer_index]
+
+ offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
+ format = {
+ gallium.PIPE_FORMAT_R32_FLOAT: 'f',
+ gallium.PIPE_FORMAT_R32G32_FLOAT: '2f',
+ gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f',
+ gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f',
+ gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B',
+ }[velem.src_format]
+
+ data = vbuf.buffer.read()
+ values = unpack_from(format, data, offset)
+ sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n')
+ assert len(values) == velem.nr_components
+ sys.stdout.write('\t},\n')
+ sys.stdout.flush()
+
+ def dump_indices(self, ibuf, isize, start, count):
+ if not self.interpreter.verbosity(2):
+ return
+
+ format = {
+ 1: 'B',
+ 2: 'H',
+ 4: 'I',
+ }[isize]
+
+ assert struct.calcsize(format) == isize
+
+ data = ibuf.read()
+ maxindex, minindex = 0, 0xffffffff
+
+ sys.stdout.write('\t{\n')
+ for i in range(start, start + count):
+ if i >= start + 16:
+ sys.stdout.write('\t...\n')
+ break
+ offset = i*isize
+ index, = unpack_from(format, data, offset)
+ sys.stdout.write('\t\t%u,\n' % index)
+ minindex = min(minindex, index)
+ maxindex = max(maxindex, index)
+ sys.stdout.write('\t},\n')
+ sys.stdout.flush()
+
+ return minindex, maxindex
+
+ 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, mode, start, count):
+ if self.interpreter.verbosity(2):
+ minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count)
+ self.dump_vertices(minindex, maxindex - minindex)
+
+ self.real.draw_elements(indexBuffer, indexSize, mode, start, count)
+ self._set_dirty()
+
+ def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count):
+ if self.interpreter.verbosity(2):
+ minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count)
+ minindex = min(minindex, minIndex)
+ maxindex = min(maxindex, maxIndex)
+ self.dump_vertices(minindex, maxindex - minindex)
+
+ self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count)
+ 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:
+ if self.interpreter.options.all:
+ self.interpreter.present(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.flush(flags)
+ if self.interpreter.options.all:
+ self.interpreter.present(dest, 'surface_copy_dest', destx, desty, width, height)
+
+ def is_texture_referenced(self, texture, face, level):
+ #return self.real.is_texture_referenced(format, texture, face, level)
+ pass
+
+ def is_buffer_referenced(self, buf):
+ #return self.real.is_buffer_referenced(format, buf)
+ pass
+
+ def _set_dirty(self):
+ if self.interpreter.options.step:
+ self._present()
+ else:
+ self.dirty = True
+
+ def flush(self, flags):
+ self.real.flush(flags)
+ if self.dirty:
+ if flags & gallium.PIPE_FLUSH_FRAME:
+ self._present()
+ self.dirty = False
+ return None
+
+ def clear(self, buffers, rgba, depth, stencil):
+ _rgba = gallium.FloatArray(4)
+ for i in range(4):
+ _rgba[i] = rgba[i]
+ self.real.clear(buffers, _rgba, depth, stencil)
+
+ def _present(self):
+ self.real.flush()
+
+ if self.cbufs and self.cbufs[0]:
+ self.interpreter.present(self.cbufs[0], "cbuf")
+ if self.zsbuf:
+ if self.interpreter.options.all:
+ self.interpreter.present(self.zsbuf, "zsbuf")
+
+
+class Interpreter(parser.TraceDumper):
+
+ ignore_calls = set((
+ ('pipe_screen', 'is_format_supported'),
+ ('pipe_screen', 'get_param'),
+ ('pipe_screen', 'get_paramf'),
+ ))
+
+ def __init__(self, stream, options):
+ parser.TraceDumper.__init__(self, stream)
+ self.options = options
+ self.objects = {}
+ self.result = None
+ self.globl = Global(self, None)
+ self.call_no = None
+
+ def register_object(self, address, object):
+ self.objects[address] = object
+
+ def unregister_object(self, object):
+ # FIXME:
+ pass
+
+ def lookup_object(self, address):
+ return self.objects[address]
+
+ def interpret(self, trace):
+ for call in trace.calls:
+ self.interpret_call(call)
+
+ def handle_call(self, call):
+ if self.options.stop and call.no > self.options.stop:
+ sys.exit(0)
+
+ if (call.klass, call.method) in self.ignore_calls:
+ return
+
+ self.call_no = call.no
+
+ if self.verbosity(1):
+ parser.TraceDumper.handle_call(self, call)
+ sys.stdout.flush()
+
+ args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args]
+
+ if call.klass:
+ name, obj = args[0]
+ args = args[1:]
+ else:
+ obj = self.globl
+
+ method = getattr(obj, call.method)
+ ret = method(**dict(args))
+
+ if call.ret and isinstance(call.ret, model.Pointer):
+ if ret is None:
+ sys.stderr.write('warning: NULL returned\n')
+ self.register_object(call.ret.address, ret)
+
+ self.call_no = None
+
+ def interpret_arg(self, node):
+ translator = Translator(self)
+ return translator.visit(node)
+
+ def verbosity(self, level):
+ return self.options.verbosity >= level
+
+ def present(self, surface, description, x=None, y=None, w=None, h=None):
+ if self.call_no < self.options.start:
+ return
+
+ if self.options.images:
+ filename = '%04u_%s.png' % (self.call_no, description)
+ save_image(filename, surface, x, y, w, h)
+ else:
+ title = '%u. %s' % (self.call_no, description)
+ show_image(surface, title, x, y, w, h)
+
+
+class Main(parser.Main):
+
+ def get_optparser(self):
+ optparser = parser.Main.get_optparser(self)
+ optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
+ optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level")
+ optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them")
+ optparser.add_option("-a", "--all", action="store_true", dest="all", default=False, help="show depth, stencil, and transfers")
+ optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw")
+ optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no")
+ optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no")
+ return optparser
+
+ def process_arg(self, stream, options):
+ parser = Interpreter(stream, options)
+ parser.parse()
+
+
+if __name__ == '__main__':
+ Main().main()
diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py
new file mode 100755
index 0000000000..d4a079fb1e
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/model.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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 TUNGSTEN GRAPHICS 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.
+#
+##########################################################################
+
+
+'''Trace data model.'''
+
+
+import sys
+import string
+import format
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+
+class Node:
+
+ def visit(self, visitor):
+ raise NotImplementedError
+
+ def __str__(self):
+ stream = StringIO()
+ formatter = format.DefaultFormatter(stream)
+ pretty_printer = PrettyPrinter(formatter)
+ self.visit(pretty_printer)
+ return stream.getvalue()
+
+
+class Literal(Node):
+
+ def __init__(self, value):
+ self.value = value
+
+ def visit(self, visitor):
+ visitor.visit_literal(self)
+
+
+class NamedConstant(Node):
+
+ def __init__(self, name):
+ self.name = name
+
+ def visit(self, visitor):
+ visitor.visit_named_constant(self)
+
+
+class Array(Node):
+
+ def __init__(self, elements):
+ self.elements = elements
+
+ def visit(self, visitor):
+ visitor.visit_array(self)
+
+
+class Struct(Node):
+
+ def __init__(self, name, members):
+ self.name = name
+ self.members = members
+
+ def visit(self, visitor):
+ visitor.visit_struct(self)
+
+
+class Pointer(Node):
+
+ def __init__(self, address):
+ self.address = address
+
+ def visit(self, visitor):
+ visitor.visit_pointer(self)
+
+
+class Call:
+
+ def __init__(self, no, klass, method, args, ret):
+ self.no = no
+ self.klass = klass
+ self.method = method
+ self.args = args
+ self.ret = ret
+
+ def visit(self, visitor):
+ visitor.visit_call(self)
+
+
+class Trace:
+
+ def __init__(self, calls):
+ self.calls = calls
+
+ def visit(self, visitor):
+ visitor.visit_trace(self)
+
+
+class Visitor:
+
+ def visit_literal(self, node):
+ raise NotImplementedError
+
+ def visit_named_constant(self, node):
+ raise NotImplementedError
+
+ def visit_array(self, node):
+ raise NotImplementedError
+
+ def visit_struct(self, node):
+ raise NotImplementedError
+
+ def visit_pointer(self, node):
+ raise NotImplementedError
+
+ def visit_call(self, node):
+ raise NotImplementedError
+
+ def visit_trace(self, node):
+ raise NotImplementedError
+
+
+class PrettyPrinter:
+
+ def __init__(self, formatter):
+ self.formatter = formatter
+
+ def visit_literal(self, node):
+ if isinstance(node.value, basestring):
+ if len(node.value) >= 4096 or node.value.strip(string.printable):
+ self.formatter.text('...')
+ return
+
+ self.formatter.literal('"' + node.value + '"')
+ return
+
+ self.formatter.literal(repr(node.value))
+
+ def visit_named_constant(self, node):
+ self.formatter.literal(node.name)
+
+ def visit_array(self, node):
+ self.formatter.text('{')
+ sep = ''
+ for value in node.elements:
+ self.formatter.text(sep)
+ value.visit(self)
+ sep = ', '
+ self.formatter.text('}')
+
+ def visit_struct(self, node):
+ self.formatter.text('{')
+ sep = ''
+ for name, value in node.members:
+ self.formatter.text(sep)
+ self.formatter.variable(name)
+ self.formatter.text(' = ')
+ value.visit(self)
+ sep = ', '
+ self.formatter.text('}')
+
+ def visit_pointer(self, node):
+ self.formatter.address(node.address)
+
+ def visit_call(self, node):
+ self.formatter.text('%s ' % node.no)
+ if node.klass is not None:
+ self.formatter.function(node.klass + '::' + node.method)
+ else:
+ self.formatter.function(node.method)
+ self.formatter.text('(')
+ sep = ''
+ for name, value in node.args:
+ self.formatter.text(sep)
+ self.formatter.variable(name)
+ self.formatter.text(' = ')
+ value.visit(self)
+ sep = ', '
+ self.formatter.text(')')
+ if node.ret is not None:
+ self.formatter.text(' = ')
+ node.ret.visit(self)
+
+ def visit_trace(self, node):
+ for call in node.calls:
+ call.visit(self)
+ self.formatter.newline()
+
diff --git a/src/gallium/state_trackers/python/retrace/parse.py b/src/gallium/state_trackers/python/retrace/parse.py
new file mode 100755
index 0000000000..b08d368671
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/parse.py
@@ -0,0 +1,392 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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 TUNGSTEN GRAPHICS 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.
+#
+##########################################################################
+
+
+import sys
+import xml.parsers.expat
+import binascii
+import optparse
+
+from model import *
+
+
+ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
+
+
+class XmlToken:
+
+ def __init__(self, type, name_or_data, attrs = None, line = None, column = None):
+ assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF)
+ self.type = type
+ self.name_or_data = name_or_data
+ self.attrs = attrs
+ self.line = line
+ self.column = column
+
+ def __str__(self):
+ if self.type == ELEMENT_START:
+ return '<' + self.name_or_data + ' ...>'
+ if self.type == ELEMENT_END:
+ return '</' + self.name_or_data + '>'
+ if self.type == CHARACTER_DATA:
+ return self.name_or_data
+ if self.type == EOF:
+ return 'end of file'
+ assert 0
+
+
+class XmlTokenizer:
+ """Expat based XML tokenizer."""
+
+ def __init__(self, fp, skip_ws = True):
+ self.fp = fp
+ self.tokens = []
+ self.index = 0
+ self.final = False
+ self.skip_ws = skip_ws
+
+ self.character_pos = 0, 0
+ self.character_data = ''
+
+ self.parser = xml.parsers.expat.ParserCreate()
+ self.parser.StartElementHandler = self.handle_element_start
+ self.parser.EndElementHandler = self.handle_element_end
+ self.parser.CharacterDataHandler = self.handle_character_data
+
+ def handle_element_start(self, name, attributes):
+ self.finish_character_data()
+ line, column = self.pos()
+ token = XmlToken(ELEMENT_START, name, attributes, line, column)
+ self.tokens.append(token)
+
+ def handle_element_end(self, name):
+ self.finish_character_data()
+ line, column = self.pos()
+ token = XmlToken(ELEMENT_END, name, None, line, column)
+ self.tokens.append(token)
+
+ def handle_character_data(self, data):
+ if not self.character_data:
+ self.character_pos = self.pos()
+ self.character_data += data
+
+ def finish_character_data(self):
+ if self.character_data:
+ if not self.skip_ws or not self.character_data.isspace():
+ line, column = self.character_pos
+ token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column)
+ self.tokens.append(token)
+ self.character_data = ''
+
+ def next(self):
+ size = 16*1024
+ while self.index >= len(self.tokens) and not self.final:
+ self.tokens = []
+ self.index = 0
+ data = self.fp.read(size)
+ self.final = len(data) < size
+ data = data.rstrip('\0')
+ try:
+ self.parser.Parse(data, self.final)
+ except xml.parsers.expat.ExpatError, e:
+ #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS:
+ if e.code == 3:
+ pass
+ else:
+ raise e
+ if self.index >= len(self.tokens):
+ line, column = self.pos()
+ token = XmlToken(EOF, None, None, line, column)
+ else:
+ token = self.tokens[self.index]
+ self.index += 1
+ return token
+
+ def pos(self):
+ return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber
+
+
+class TokenMismatch(Exception):
+
+ def __init__(self, expected, found):
+ self.expected = expected
+ self.found = found
+
+ def __str__(self):
+ return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found))
+
+
+
+class XmlParser:
+ """Base XML document parser."""
+
+ def __init__(self, fp):
+ self.tokenizer = XmlTokenizer(fp)
+ self.consume()
+
+ def consume(self):
+ self.token = self.tokenizer.next()
+
+ def match_element_start(self, name):
+ return self.token.type == ELEMENT_START and self.token.name_or_data == name
+
+ def match_element_end(self, name):
+ return self.token.type == ELEMENT_END and self.token.name_or_data == name
+
+ def element_start(self, name):
+ while self.token.type == CHARACTER_DATA:
+ self.consume()
+ if self.token.type != ELEMENT_START:
+ raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
+ if self.token.name_or_data != name:
+ raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token)
+ attrs = self.token.attrs
+ self.consume()
+ return attrs
+
+ def element_end(self, name):
+ while self.token.type == CHARACTER_DATA:
+ self.consume()
+ if self.token.type != ELEMENT_END:
+ raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
+ if self.token.name_or_data != name:
+ raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token)
+ self.consume()
+
+ def character_data(self, strip = True):
+ data = ''
+ while self.token.type == CHARACTER_DATA:
+ data += self.token.name_or_data
+ self.consume()
+ if strip:
+ data = data.strip()
+ return data
+
+
+class TraceParser(XmlParser):
+
+ def __init__(self, fp):
+ XmlParser.__init__(self, fp)
+ self.last_call_no = 0
+
+ def parse(self):
+ self.element_start('trace')
+ while self.token.type not in (ELEMENT_END, EOF):
+ call = self.parse_call()
+ self.handle_call(call)
+ if self.token.type != EOF:
+ self.element_end('trace')
+
+ def parse_call(self):
+ attrs = self.element_start('call')
+ try:
+ no = int(attrs['no'])
+ except KeyError:
+ self.last_call_no += 1
+ no = self.last_call_no
+ else:
+ self.last_call_no = no
+ klass = attrs['class']
+ method = attrs['method']
+ args = []
+ ret = None
+ while self.token.type == ELEMENT_START:
+ if self.token.name_or_data == 'arg':
+ arg = self.parse_arg()
+ args.append(arg)
+ elif self.token.name_or_data == 'ret':
+ ret = self.parse_ret()
+ elif self.token.name_or_data == 'call':
+ # ignore nested function calls
+ self.parse_call()
+ else:
+ raise TokenMismatch("<arg ...> or <ret ...>", self.token)
+ self.element_end('call')
+
+ return Call(no, klass, method, args, ret)
+
+ def parse_arg(self):
+ attrs = self.element_start('arg')
+ name = attrs['name']
+ value = self.parse_value()
+ self.element_end('arg')
+
+ return name, value
+
+ def parse_ret(self):
+ attrs = self.element_start('ret')
+ value = self.parse_value()
+ self.element_end('ret')
+
+ return value
+
+ def parse_value(self):
+ expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes')
+ if self.token.type == ELEMENT_START:
+ if self.token.name_or_data in expected_tokens:
+ method = getattr(self, 'parse_' + self.token.name_or_data)
+ return method()
+ raise TokenMismatch(" or " .join(expected_tokens), self.token)
+
+ def parse_null(self):
+ self.element_start('null')
+ self.element_end('null')
+ return Literal(None)
+
+ def parse_bool(self):
+ self.element_start('bool')
+ value = int(self.character_data())
+ self.element_end('bool')
+ return Literal(value)
+
+ def parse_int(self):
+ self.element_start('int')
+ value = int(self.character_data())
+ self.element_end('int')
+ return Literal(value)
+
+ def parse_uint(self):
+ self.element_start('uint')
+ value = int(self.character_data())
+ self.element_end('uint')
+ return Literal(value)
+
+ def parse_float(self):
+ self.element_start('float')
+ value = float(self.character_data())
+ self.element_end('float')
+ return Literal(value)
+
+ def parse_enum(self):
+ self.element_start('enum')
+ name = self.character_data()
+ self.element_end('enum')
+ return NamedConstant(name)
+
+ def parse_string(self):
+ self.element_start('string')
+ value = self.character_data()
+ self.element_end('string')
+ return Literal(value)
+
+ def parse_bytes(self):
+ self.element_start('bytes')
+ value = binascii.a2b_hex(self.character_data())
+ self.element_end('bytes')
+ return Literal(value)
+
+ def parse_array(self):
+ self.element_start('array')
+ elems = []
+ while self.token.type != ELEMENT_END:
+ elems.append(self.parse_elem())
+ self.element_end('array')
+ return Array(elems)
+
+ def parse_elem(self):
+ self.element_start('elem')
+ value = self.parse_value()
+ self.element_end('elem')
+ return value
+
+ def parse_struct(self):
+ attrs = self.element_start('struct')
+ name = attrs['name']
+ members = []
+ while self.token.type != ELEMENT_END:
+ members.append(self.parse_member())
+ self.element_end('struct')
+ return Struct(name, members)
+
+ def parse_member(self):
+ attrs = self.element_start('member')
+ name = attrs['name']
+ value = self.parse_value()
+ self.element_end('member')
+
+ return name, value
+
+ def parse_ptr(self):
+ self.element_start('ptr')
+ address = self.character_data()
+ self.element_end('ptr')
+
+ return Pointer(address)
+
+ def handle_call(self, call):
+ pass
+
+
+class TraceDumper(TraceParser):
+
+ def __init__(self, fp):
+ TraceParser.__init__(self, fp)
+ self.formatter = format.DefaultFormatter(sys.stdout)
+ self.pretty_printer = PrettyPrinter(self.formatter)
+
+ def handle_call(self, call):
+ call.visit(self.pretty_printer)
+ self.formatter.newline()
+
+
+class Main:
+ '''Common main class for all retrace command line utilities.'''
+
+ def __init__(self):
+ pass
+
+ def main(self):
+ optparser = self.get_optparser()
+ (options, args) = optparser.parse_args(sys.argv[1:])
+
+ if args:
+ for arg in args:
+ if arg.endswith('.gz'):
+ from gzip import GzipFile
+ stream = GzipFile(arg, 'rt')
+ elif arg.endswith('.bz2'):
+ from bz2 import BZ2File
+ stream = BZ2File(arg, 'rU')
+ else:
+ stream = open(arg, 'rt')
+ self.process_arg(stream, options)
+ else:
+ self.process_arg(stream, options)
+
+ def get_optparser(self):
+ optparser = optparse.OptionParser(
+ usage="\n\t%prog [options] [traces] ...")
+ return optparser
+
+ def process_arg(self, stream, options):
+ parser = TraceDumper(stream)
+ parser.parse()
+
+
+if __name__ == '__main__':
+ Main().main()
diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py
new file mode 100755
index 0000000000..bd47c9a6b0
--- /dev/null
+++ b/src/gallium/state_trackers/python/retrace/parser.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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 TUNGSTEN GRAPHICS 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.
+#
+##########################################################################
+
+
+from parse import *
+
+
+if __name__ == '__main__':
+ Main().main()
diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py
new file mode 100644
index 0000000000..b721e0b575
--- /dev/null
+++ b/src/gallium/state_trackers/python/samples/tri.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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 TUNGSTEN GRAPHICS 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.
+#
+##########################################################################
+
+
+from gallium import *
+
+
+def make_image(surface):
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface):
+ outimage = make_image(surface)
+ outimage.save(filename, "PNG")
+
+def show_image(surface):
+ outimage = make_image(surface)
+
+ import Tkinter as tk
+ from PIL import Image, ImageTk
+ root = tk.Tk()
+
+ root.title('background image')
+
+ image1 = ImageTk.PhotoImage(outimage)
+ w = image1.width()
+ h = image1.height()
+ x = 100
+ y = 100
+ root.geometry("%dx%d+%d+%d" % (w, h, x, y))
+ panel1 = tk.Label(root, image=image1)
+ panel1.pack(side='top', fill='both', expand='yes')
+ panel1.image = image1
+ root.mainloop()
+
+
+def test(dev):
+ ctx = dev.context_create()
+
+ width = 255
+ height = 255
+ minz = 0.0
+ maxz = 1.0
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 1
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.scissor = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # viewport
+ viewport = Viewport()
+ scale = FloatArray(4)
+ scale[0] = width / 2.0
+ scale[1] = -height / 2.0
+ scale[2] = (maxz - minz) / 2.0
+ scale[3] = 1.0
+ viewport.scale = scale
+ translate = FloatArray(4)
+ translate[0] = width / 2.0
+ translate[1] = height / 2.0
+ translate[2] = (maxz - minz) / 2.0
+ translate[3] = 0.0
+ viewport.translate = translate
+ ctx.set_viewport(viewport)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ ctx.set_sampler(0, sampler)
+
+ # scissor
+ scissor = Scissor()
+ scissor.minx = 0
+ scissor.miny = 0
+ scissor.maxx = width
+ scissor.maxy = height
+ ctx.set_scissor(scissor)
+
+ clip = Clip()
+ clip.nr = 0
+ ctx.set_clip(clip)
+
+ # framebuffer
+ cbuf = dev.texture_create(
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ ).get_surface()
+ zbuf = dev.texture_create(
+ PIPE_FORMAT_Z16_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DEPTH_STENCIL,
+ ).get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ fb.set_zsbuf(zbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.0
+ rgba[1] = 0.0
+ rgba[2] = 0.0
+ rgba[3] = 0.0
+ ctx.clear(PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0xff)
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], COLOR, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], COLOR, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], COLOR, LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:END
+ ''')
+ ctx.set_fragment_shader(fs)
+
+ nverts = 3
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ verts[ 0] = 0.0 # x1
+ verts[ 1] = 0.8 # y1
+ verts[ 2] = 0.2 # z1
+ verts[ 3] = 1.0 # w1
+ verts[ 4] = 1.0 # r1
+ verts[ 5] = 0.0 # g1
+ verts[ 6] = 0.0 # b1
+ verts[ 7] = 1.0 # a1
+ verts[ 8] = -0.8 # x2
+ verts[ 9] = -0.8 # y2
+ verts[10] = 0.5 # z2
+ verts[11] = 1.0 # w2
+ verts[12] = 0.0 # r2
+ verts[13] = 1.0 # g2
+ verts[14] = 0.0 # b2
+ verts[15] = 1.0 # a2
+ verts[16] = 0.8 # x3
+ verts[17] = -0.8 # y3
+ verts[18] = 0.8 # z3
+ verts[19] = 1.0 # w3
+ verts[20] = 0.0 # r3
+ verts[21] = 0.0 # g3
+ verts[22] = 1.0 # b3
+ verts[23] = 1.0 # a3
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLES,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ show_image(cbuf)
+ #show_image(zbuf)
+ #save_image('cbuf.png', cbuf)
+ #save_image('zbuf.png', zbuf)
+
+
+
+def main():
+ dev = Device()
+ test(dev)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c
new file mode 100644
index 0000000000..ea7d18738f
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_device.c
@@ -0,0 +1,305 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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 "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_inlines.h"
+#include "cso_cache/cso_context.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "util/u_simple_shaders.h"
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+
+#include "st_device.h"
+#include "st_winsys.h"
+
+
+static void
+st_device_really_destroy(struct st_device *st_dev)
+{
+ if(st_dev->screen) {
+ /* FIXME: Don't really destroy until we keep track of every single
+ * reference or we end up causing a segmentation fault every time
+ * python exits. */
+#if 0
+ st_dev->screen->destroy(st_dev->screen);
+#endif
+ }
+
+ FREE(st_dev);
+}
+
+
+static void
+st_device_reference(struct st_device **ptr, struct st_device *st_dev)
+{
+ struct st_device *old_dev = *ptr;
+
+ if (pipe_reference((struct pipe_reference **)ptr, &st_dev->reference))
+ st_device_really_destroy(old_dev);
+}
+
+
+void
+st_device_destroy(struct st_device *st_dev)
+{
+ st_device_reference(&st_dev, NULL);
+}
+
+
+static struct st_device *
+st_device_create_from_st_winsys(const struct st_winsys *st_ws)
+{
+ struct st_device *st_dev;
+
+ if(!st_ws->screen_create ||
+ !st_ws->context_create)
+ return NULL;
+
+ st_dev = CALLOC_STRUCT(st_device);
+ if(!st_dev)
+ return NULL;
+
+ pipe_reference_init(&st_dev->reference, 1);
+ st_dev->st_ws = st_ws;
+
+ st_dev->real_screen = st_ws->screen_create();
+ if(!st_dev->real_screen) {
+ st_device_destroy(st_dev);
+ return NULL;
+ }
+
+ st_dev->screen = trace_screen_create(st_dev->real_screen);
+ if(!st_dev->screen) {
+ st_device_destroy(st_dev);
+ return NULL;
+ }
+
+ return st_dev;
+}
+
+
+struct st_device *
+st_device_create(boolean hardware) {
+ if(hardware)
+ return st_device_create_from_st_winsys(&st_hardpipe_winsys);
+ else
+ return st_device_create_from_st_winsys(&st_softpipe_winsys);
+}
+
+
+void
+st_context_destroy(struct st_context *st_ctx)
+{
+ unsigned i;
+
+ if(st_ctx) {
+ struct st_device *st_dev = st_ctx->st_dev;
+
+ if(st_ctx->cso) {
+ cso_delete_vertex_shader(st_ctx->cso, st_ctx->vs);
+ cso_delete_fragment_shader(st_ctx->cso, st_ctx->fs);
+
+ cso_destroy_context(st_ctx->cso);
+ }
+
+ if(st_ctx->pipe)
+ st_ctx->pipe->destroy(st_ctx->pipe);
+
+ for(i = 0; i < PIPE_MAX_SAMPLERS; ++i)
+ pipe_texture_reference(&st_ctx->sampler_textures[i], NULL);
+ pipe_texture_reference(&st_ctx->default_texture, NULL);
+
+ FREE(st_ctx);
+
+ st_device_reference(&st_dev, NULL);
+ }
+}
+
+
+struct st_context *
+st_context_create(struct st_device *st_dev)
+{
+ struct st_context *st_ctx;
+
+ st_ctx = CALLOC_STRUCT(st_context);
+ if(!st_ctx)
+ return NULL;
+
+ st_device_reference(&st_ctx->st_dev, st_dev);
+
+ st_ctx->real_pipe = st_dev->st_ws->context_create(st_dev->real_screen);
+ if(!st_ctx->real_pipe) {
+ st_context_destroy(st_ctx);
+ return NULL;
+ }
+
+ st_ctx->pipe = trace_context_create(st_dev->screen, st_ctx->real_pipe);
+ if(!st_ctx->pipe) {
+ st_context_destroy(st_ctx);
+ return NULL;
+ }
+
+ st_ctx->cso = cso_create_context(st_ctx->pipe);
+ if(!st_ctx->cso) {
+ st_context_destroy(st_ctx);
+ return NULL;
+ }
+
+ /* disabled blending/masking */
+ {
+ struct pipe_blend_state blend;
+ memset(&blend, 0, sizeof(blend));
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.colormask = PIPE_MASK_RGBA;
+ cso_set_blend(st_ctx->cso, &blend);
+ }
+
+ /* no-op depth/stencil/alpha */
+ {
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ memset(&depthstencil, 0, sizeof(depthstencil));
+ cso_set_depth_stencil_alpha(st_ctx->cso, &depthstencil);
+ }
+
+ /* rasterizer */
+ {
+ struct pipe_rasterizer_state rasterizer;
+ memset(&rasterizer, 0, sizeof(rasterizer));
+ rasterizer.front_winding = PIPE_WINDING_CW;
+ rasterizer.cull_mode = PIPE_WINDING_NONE;
+ cso_set_rasterizer(st_ctx->cso, &rasterizer);
+ }
+
+ /* clip */
+ {
+ struct pipe_clip_state clip;
+ memset(&clip, 0, sizeof(clip));
+ st_ctx->pipe->set_clip_state(st_ctx->pipe, &clip);
+ }
+
+ /* identity viewport */
+ {
+ struct pipe_viewport_state viewport;
+ viewport.scale[0] = 1.0;
+ viewport.scale[1] = 1.0;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = 0.0;
+ viewport.translate[1] = 0.0;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+ cso_set_viewport(st_ctx->cso, &viewport);
+ }
+
+ /* samplers */
+ {
+ struct pipe_sampler_state sampler;
+ unsigned i;
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
+ sampler.normalized_coords = 1;
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ cso_single_sampler(st_ctx->cso, i, &sampler);
+ cso_single_sampler_done(st_ctx->cso);
+ }
+
+ /* default textures */
+ {
+ struct pipe_screen *screen = st_dev->screen;
+ struct pipe_texture templat;
+ struct pipe_transfer *transfer;
+ unsigned i;
+
+ memset( &templat, 0, sizeof( templat ) );
+ templat.target = PIPE_TEXTURE_2D;
+ templat.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+ templat.block.size = 4;
+ templat.block.width = 1;
+ templat.block.height = 1;
+ templat.width[0] = 1;
+ templat.height[0] = 1;
+ templat.depth[0] = 1;
+ templat.last_level = 0;
+
+ st_ctx->default_texture = screen->texture_create( screen, &templat );
+ if(st_ctx->default_texture) {
+ transfer = screen->get_tex_transfer(screen,
+ st_ctx->default_texture,
+ 0, 0, 0,
+ PIPE_TRANSFER_WRITE,
+ 0, 0,
+ st_ctx->default_texture->width[0],
+ st_ctx->default_texture->height[0]);
+ if (transfer) {
+ uint32_t *map;
+ map = (uint32_t *) screen->transfer_map(screen, transfer);
+ if(map) {
+ *map = 0x00000000;
+ screen->transfer_unmap(screen, transfer);
+ }
+ screen->tex_transfer_destroy(transfer);
+ }
+ }
+
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
+ pipe_texture_reference(&st_ctx->sampler_textures[i], st_ctx->default_texture);
+
+ cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->sampler_textures);
+ }
+
+ /* vertex shader */
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC };
+ const uint semantic_indexes[] = { 0, 0 };
+ st_ctx->vs = util_make_vertex_passthrough_shader(st_ctx->pipe,
+ 2,
+ semantic_names,
+ semantic_indexes);
+ cso_set_vertex_shader_handle(st_ctx->cso, st_ctx->vs);
+ }
+
+ /* fragment shader */
+ {
+ st_ctx->fs = util_make_fragment_passthrough_shader(st_ctx->pipe);
+ cso_set_fragment_shader_handle(st_ctx->cso, st_ctx->fs);
+ }
+
+ return st_ctx;
+}
diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h
new file mode 100644
index 0000000000..a246b6a1f2
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_device.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_DEVICE_H_
+#define ST_DEVICE_H_
+
+
+#include "pipe/p_state.h"
+
+struct cso_context;
+struct pipe_screen;
+struct pipe_context;
+struct st_winsys;
+
+
+struct st_surface
+{
+ struct pipe_texture *texture;
+ unsigned face;
+ unsigned level;
+ unsigned zslice;
+};
+
+
+struct st_context {
+ struct st_device *st_dev;
+
+ struct pipe_context *real_pipe;
+ struct pipe_context *pipe;
+
+ struct cso_context *cso;
+
+ void *vs;
+ void *fs;
+
+ struct pipe_texture *default_texture;
+ struct pipe_texture *sampler_textures[PIPE_MAX_SAMPLERS];
+
+ unsigned num_vertex_buffers;
+ struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
+
+ unsigned num_vertex_elements;
+ struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS];
+
+ struct pipe_framebuffer_state framebuffer;
+};
+
+
+struct st_device {
+ /* FIXME: we also need to refcount for textures and surfaces... */
+ struct pipe_reference reference;
+
+ const struct st_winsys *st_ws;
+
+ struct pipe_screen *real_screen;
+ struct pipe_screen *screen;
+};
+
+
+static INLINE struct pipe_surface *
+st_pipe_surface(struct st_surface *surface, unsigned usage)
+{
+ struct pipe_texture *texture = surface->texture;
+ struct pipe_screen *screen = texture->screen;
+ return screen->get_tex_surface(screen, texture, surface->face, surface->level, surface->zslice, usage);
+}
+
+struct st_context *
+st_context_create(struct st_device *st_dev);
+
+void
+st_context_destroy(struct st_context *st_ctx);
+
+struct st_device *
+st_device_create(boolean hardware);
+
+void
+st_device_destroy(struct st_device *st_dev);
+
+
+#endif /* ST_DEVICE_H_ */
diff --git a/src/gallium/state_trackers/python/st_hardpipe_winsys.c b/src/gallium/state_trackers/python/st_hardpipe_winsys.c
new file mode 100644
index 0000000000..43aaaabf2a
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_hardpipe_winsys.c
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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 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
+ * THE COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Get a hardware accelerated Gallium screen/context from the OpenGL driver.
+ */
+
+
+#include "pipe/p_compiler.h"
+
+#ifdef PIPE_OS_WINDOWS
+#include <windows.h>
+#include <GL/gl.h>
+#else
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#endif
+
+#include "st_winsys.h"
+
+
+typedef struct pipe_screen * (GLAPIENTRY *PFNGETGALLIUMSCREENMESAPROC) (void);
+typedef struct pipe_context * (GLAPIENTRY* PFNCREATEGALLIUMCONTEXTMESAPROC) (void);
+
+static PFNGETGALLIUMSCREENMESAPROC pfnGetGalliumScreenMESA = NULL;
+static PFNCREATEGALLIUMCONTEXTMESAPROC pfnCreateGalliumContextMESA = NULL;
+
+
+/* XXX: Force init_gallium symbol to be linked */
+extern void init_gallium(void);
+void (*force_init_gallium_linkage)(void) = &init_gallium;
+
+
+#ifdef PIPE_OS_WINDOWS
+
+static INLINE boolean
+st_hardpipe_load(void)
+{
+ WNDCLASS wc;
+ HWND hwnd;
+ HGLRC hglrc;
+ HDC hdc;
+ PIXELFORMATDESCRIPTOR pfd;
+ int iPixelFormat;
+
+ if(pfnGetGalliumScreenMESA && pfnCreateGalliumContextMESA)
+ return TRUE;
+
+ memset(&wc, 0, sizeof wc);
+ wc.lpfnWndProc = DefWindowProc;
+ wc.lpszClassName = "gallium";
+ wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ RegisterClass(&wc);
+
+ hwnd = CreateWindow(wc.lpszClassName, "gallium", 0, 0, 0, 0, 0, NULL, 0, wc.hInstance, NULL);
+ if (!hwnd)
+ return FALSE;
+
+ hdc = GetDC(hwnd);
+ if (!hdc)
+ return FALSE;
+
+ pfd.cColorBits = 3;
+ pfd.cRedBits = 1;
+ pfd.cGreenBits = 1;
+ pfd.cBlueBits = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+
+ iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+ if (!iPixelFormat) {
+ pfd.dwFlags |= PFD_DOUBLEBUFFER;
+ iPixelFormat = ChoosePixelFormat(hdc, &pfd);
+ }
+ if (!iPixelFormat)
+ return FALSE;
+
+ SetPixelFormat(hdc, iPixelFormat, &pfd);
+ hglrc = wglCreateContext(hdc);
+ if (!hglrc)
+ return FALSE;
+
+ if (!wglMakeCurrent(hdc, hglrc))
+ return FALSE;
+
+ pfnGetGalliumScreenMESA = (PFNGETGALLIUMSCREENMESAPROC)wglGetProcAddress("wglGetGalliumScreenMESA");
+ if(!pfnGetGalliumScreenMESA)
+ return FALSE;
+
+ pfnCreateGalliumContextMESA = (PFNCREATEGALLIUMCONTEXTMESAPROC)wglGetProcAddress("wglCreateGalliumContextMESA");
+ if(!pfnCreateGalliumContextMESA)
+ return FALSE;
+
+ DestroyWindow(hwnd);
+
+ return TRUE;
+}
+
+#else
+
+static INLINE boolean
+st_hardpipe_load(void)
+{
+ Display *dpy;
+ int scrnum;
+ Window root;
+ int attribSingle[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None };
+ int attribDouble[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+ XVisualInfo *visinfo;
+ GLXContext ctx = NULL;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ int width = 100, height = 100;
+ Window win;
+
+ dpy = XOpenDisplay(NULL);
+ if (!dpy)
+ return FALSE;
+
+ scrnum = 0;
+
+ root = RootWindow(dpy, scrnum);
+
+ visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
+ if (!visinfo)
+ visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
+ if (!visinfo)
+ return FALSE;
+
+ ctx = glXCreateContext( dpy, visinfo, NULL, True );
+
+ if (!ctx)
+ return FALSE;
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask;
+
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ win = XCreateWindow(dpy, root, 0, 0, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr);
+
+ if (!glXMakeCurrent(dpy, win, ctx))
+ return FALSE;
+
+ pfnGetGalliumScreenMESA = (PFNGETGALLIUMSCREENMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXGetGalliumScreenMESA");
+ if(!pfnGetGalliumScreenMESA)
+ return FALSE;
+
+ pfnCreateGalliumContextMESA = (PFNCREATEGALLIUMCONTEXTMESAPROC)glXGetProcAddressARB((const GLubyte *)"glXCreateGalliumContextMESA");
+ if(!pfnCreateGalliumContextMESA)
+ return FALSE;
+
+ glXDestroyContext(dpy, ctx);
+ XFree(visinfo);
+ XDestroyWindow(dpy, win);
+ XCloseDisplay(dpy);
+
+ return TRUE;
+}
+
+#endif
+
+
+static struct pipe_screen *
+st_hardpipe_screen_create(void)
+{
+ if(st_hardpipe_load())
+ return pfnGetGalliumScreenMESA();
+ else
+ return st_softpipe_winsys.screen_create();
+}
+
+
+static struct pipe_context *
+st_hardpipe_context_create(struct pipe_screen *screen)
+{
+ if(st_hardpipe_load()) {
+ if(screen == pfnGetGalliumScreenMESA())
+ return pfnCreateGalliumContextMESA();
+ else
+ return NULL;
+ }
+ else
+ return st_softpipe_winsys.context_create(screen);
+}
+
+
+const struct st_winsys st_hardpipe_winsys = {
+ &st_hardpipe_screen_create,
+ &st_hardpipe_context_create
+};
diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c
new file mode 100644
index 0000000000..53a01891e1
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_sample.c
@@ -0,0 +1,570 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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 "pipe/p_compiler.h"
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "st_device.h"
+#include "st_sample.h"
+
+
+/**
+ * Use our own pseudo random generator to ensure consistent runs among
+ * multiple runs and platforms.
+ *
+ * @sa http://en.wikipedia.org/wiki/Linear_congruential_generator
+ */
+static uint32_t st_random(void) {
+ static uint64_t seed = UINT64_C(0xbb9a063afb0a739d);
+
+ seed = UINT64_C(134775813) * seed + UINT64_C(1);
+
+ return (uint16_t)(seed >> 32);
+}
+
+
+/**
+ * We don't want to include the patent-encumbered DXT code here, so instead
+ * we store several uncompressed/compressed data pairs for hardware testing
+ * purposes.
+ */
+struct dxt_data
+{
+ uint8_t rgba[16*4];
+ uint8_t raw[16];
+};
+
+
+static const struct dxt_data
+dxt1_rgb_data[] = {
+ {
+ {
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0xd6, 0xff, 0x94, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0xd6, 0xff, 0x94, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff,
+ 0x21, 0x14, 0x84, 0xff,
+ 0x5d, 0x62, 0x89, 0xff,
+ 0x21, 0x14, 0x84, 0xff,
+ 0x21, 0x14, 0x84, 0xff,
+ 0x99, 0xb0, 0x8e, 0xff
+ },
+ {0xf2, 0xd7, 0xb0, 0x20, 0xae, 0x2c, 0x6f, 0x97}
+ },
+ {
+ {
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x21, 0x08, 0x6b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x52, 0x4a, 0x7b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x21, 0x08, 0x6b, 0xff,
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x52, 0x4a, 0x7b, 0xff,
+ 0xb5, 0xcf, 0x9c, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff,
+ 0x52, 0x4a, 0x7b, 0xff,
+ 0x83, 0x8c, 0x8b, 0xff
+ },
+ {0x73, 0xb6, 0x4d, 0x20, 0x98, 0x2b, 0xe1, 0xb8}
+ },
+ {
+ {
+ 0x00, 0x2c, 0xff, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0x4a, 0x5c, 0xbd, 0xff,
+ 0x4a, 0x5c, 0xbd, 0xff,
+ 0x4a, 0x5c, 0xbd, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0xde, 0xbe, 0x39, 0xff,
+ 0x94, 0x8d, 0x7b, 0xff
+ },
+ {0xe7, 0xdd, 0x7f, 0x01, 0xf9, 0xab, 0x08, 0x80}
+ },
+ {
+ {
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x9c, 0xa6, 0xd6, 0xff,
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x6b, 0x24, 0x21, 0xff,
+ 0x8b, 0x7a, 0x99, 0xff,
+ 0x7b, 0x4f, 0x5d, 0xff,
+ 0x9c, 0xa6, 0xd6, 0xff
+ },
+ {0x3a, 0x9d, 0x24, 0x69, 0xbd, 0x9f, 0xb4, 0x39}
+ }
+};
+
+
+static const struct dxt_data
+dxt1_rgba_data[] = {
+ {
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x29, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x73, 0x55, 0x21, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x4e, 0xaa, 0x90, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x4e, 0xaa, 0x90, 0xff
+ },
+ {0xff, 0x2f, 0xa4, 0x72, 0xeb, 0xb2, 0xbd, 0xbe}
+ },
+ {
+ {
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x6b, 0x24, 0x84, 0xff,
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x6b, 0x24, 0x84, 0xff,
+ 0x6b, 0x24, 0x84, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xb5, 0xe3, 0x63, 0xff,
+ 0x90, 0x83, 0x73, 0xff,
+ 0xb5, 0xe3, 0x63, 0xff
+ },
+ {0x30, 0x69, 0x0c, 0xb7, 0x4d, 0xf7, 0x0f, 0x67}
+ },
+ {
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0xc6, 0x86, 0x8c, 0xff,
+ 0xc6, 0x86, 0x8c, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x21, 0x65, 0x42, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x21, 0x65, 0x42, 0xff,
+ 0xc6, 0x86, 0x8c, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xc6, 0x86, 0x8c, 0xff
+ },
+ {0x28, 0x23, 0x31, 0xc4, 0x17, 0xc0, 0xd3, 0x7f}
+ },
+ {
+ {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xc6, 0xe3, 0x9c, 0xff,
+ 0x7b, 0x1c, 0x52, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x7b, 0x1c, 0x52, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x7b, 0x1c, 0x52, 0xff,
+ 0xa0, 0x7f, 0x77, 0xff,
+ 0xc6, 0xe3, 0x9c, 0xff,
+ 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x7f, 0x77, 0xff
+ },
+ {0xea, 0x78, 0x13, 0xc7, 0x7f, 0xfc, 0x33, 0xb6}
+ },
+};
+
+
+static const struct dxt_data
+dxt3_rgba_data[] = {
+ {
+ {
+ 0x6d, 0xc6, 0x96, 0x77,
+ 0x6d, 0xc6, 0x96, 0xee,
+ 0x6d, 0xc6, 0x96, 0xaa,
+ 0x8c, 0xff, 0xb5, 0x44,
+ 0x6d, 0xc6, 0x96, 0xff,
+ 0x6d, 0xc6, 0x96, 0x88,
+ 0x31, 0x55, 0x5a, 0x66,
+ 0x6d, 0xc6, 0x96, 0x99,
+ 0x31, 0x55, 0x5a, 0xbb,
+ 0x31, 0x55, 0x5a, 0x55,
+ 0x31, 0x55, 0x5a, 0x11,
+ 0x6d, 0xc6, 0x96, 0xcc,
+ 0x6d, 0xc6, 0x96, 0xcc,
+ 0x6d, 0xc6, 0x96, 0x11,
+ 0x31, 0x55, 0x5a, 0x44,
+ 0x31, 0x55, 0x5a, 0x88
+ },
+ {0xe7, 0x4a, 0x8f, 0x96, 0x5b, 0xc1, 0x1c, 0x84, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a}
+ },
+ {
+ {
+ 0xad, 0xeb, 0x73, 0x99,
+ 0x97, 0xaa, 0x86, 0x66,
+ 0x6b, 0x28, 0xad, 0x99,
+ 0xad, 0xeb, 0x73, 0x99,
+ 0x6b, 0x28, 0xad, 0x22,
+ 0xad, 0xeb, 0x73, 0xff,
+ 0x97, 0xaa, 0x86, 0x55,
+ 0x6b, 0x28, 0xad, 0x55,
+ 0x6b, 0x28, 0xad, 0x44,
+ 0xad, 0xeb, 0x73, 0x33,
+ 0x6b, 0x28, 0xad, 0xee,
+ 0x6b, 0x28, 0xad, 0x99,
+ 0x97, 0xaa, 0x86, 0x66,
+ 0xad, 0xeb, 0x73, 0xbb,
+ 0x97, 0xaa, 0x86, 0x99,
+ 0xad, 0xeb, 0x73, 0xbb
+ },
+ {0x69, 0x99, 0xf2, 0x55, 0x34, 0x9e, 0xb6, 0xb9, 0x4e, 0xaf, 0x55, 0x69, 0x18, 0x61, 0x51, 0x22}
+ },
+ {
+ {
+ 0x63, 0xd7, 0xd6, 0x00,
+ 0x57, 0x62, 0x5d, 0xdd,
+ 0x57, 0x62, 0x5d, 0xcc,
+ 0x57, 0x62, 0x5d, 0xbb,
+ 0x52, 0x28, 0x21, 0xaa,
+ 0x57, 0x62, 0x5d, 0xcc,
+ 0x57, 0x62, 0x5d, 0xcc,
+ 0x57, 0x62, 0x5d, 0x66,
+ 0x57, 0x62, 0x5d, 0x22,
+ 0x57, 0x62, 0x5d, 0xdd,
+ 0x63, 0xd7, 0xd6, 0xee,
+ 0x57, 0x62, 0x5d, 0x33,
+ 0x63, 0xd7, 0xd6, 0x55,
+ 0x52, 0x28, 0x21, 0x55,
+ 0x57, 0x62, 0x5d, 0x11,
+ 0x5d, 0x9c, 0x99, 0xee
+ },
+ {0xd0, 0xbc, 0xca, 0x6c, 0xd2, 0x3e, 0x55, 0xe1, 0xba, 0x66, 0x44, 0x51, 0xfc, 0xfd, 0xcf, 0xb4}
+ },
+ {
+ {
+ 0x94, 0x6f, 0x60, 0x22,
+ 0x94, 0x6f, 0x60, 0x22,
+ 0xc5, 0xab, 0x76, 0x11,
+ 0xc5, 0xab, 0x76, 0xee,
+ 0x63, 0x34, 0x4a, 0xdd,
+ 0x63, 0x34, 0x4a, 0x33,
+ 0x94, 0x6f, 0x60, 0x77,
+ 0xf7, 0xe7, 0x8c, 0x00,
+ 0x94, 0x6f, 0x60, 0x33,
+ 0x63, 0x34, 0x4a, 0xaa,
+ 0x94, 0x6f, 0x60, 0x77,
+ 0x63, 0x34, 0x4a, 0xcc,
+ 0x94, 0x6f, 0x60, 0xaa,
+ 0xf7, 0xe7, 0x8c, 0x99,
+ 0x63, 0x34, 0x4a, 0x44,
+ 0xc5, 0xab, 0x76, 0xaa
+ },
+ {0x22, 0xe1, 0x3d, 0x07, 0xa3, 0xc7, 0x9a, 0xa4, 0x31, 0xf7, 0xa9, 0x61, 0xaf, 0x35, 0x77, 0x93}
+ },
+};
+
+
+static const struct dxt_data
+dxt5_rgba_data[] = {
+ {
+ {
+ 0x6d, 0xc6, 0x96, 0x74,
+ 0x6d, 0xc6, 0x96, 0xf8,
+ 0x6d, 0xc6, 0x96, 0xb6,
+ 0x8c, 0xff, 0xb5, 0x53,
+ 0x6d, 0xc6, 0x96, 0xf8,
+ 0x6d, 0xc6, 0x96, 0x95,
+ 0x31, 0x55, 0x5a, 0x53,
+ 0x6d, 0xc6, 0x96, 0x95,
+ 0x31, 0x55, 0x5a, 0xb6,
+ 0x31, 0x55, 0x5a, 0x53,
+ 0x31, 0x55, 0x5a, 0x11,
+ 0x6d, 0xc6, 0x96, 0xd7,
+ 0x6d, 0xc6, 0x96, 0xb6,
+ 0x6d, 0xc6, 0x96, 0x11,
+ 0x31, 0x55, 0x5a, 0x32,
+ 0x31, 0x55, 0x5a, 0x95
+ },
+ {0xf8, 0x11, 0xc5, 0x0c, 0x9a, 0x73, 0xb4, 0x9c, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a}
+ },
+ {
+ {
+ 0xad, 0xeb, 0x73, 0xa1,
+ 0x97, 0xaa, 0x86, 0x65,
+ 0x6b, 0x28, 0xad, 0xa1,
+ 0xad, 0xeb, 0x73, 0xa1,
+ 0x6b, 0x28, 0xad, 0x2a,
+ 0xad, 0xeb, 0x73, 0xfb,
+ 0x97, 0xaa, 0x86, 0x47,
+ 0x6b, 0x28, 0xad, 0x65,
+ 0x6b, 0x28, 0xad, 0x47,
+ 0xad, 0xeb, 0x73, 0x47,
+ 0x6b, 0x28, 0xad, 0xdd,
+ 0x6b, 0x28, 0xad, 0xa1,
+ 0x97, 0xaa, 0x86, 0x65,
+ 0xad, 0xeb, 0x73, 0xbf,
+ 0x97, 0xaa, 0x86, 0xa1,
+ 0xad, 0xeb, 0x73, 0xbf
+ },
+ {0xfb, 0x2a, 0x34, 0x19, 0xdc, 0xbf, 0xe8, 0x71, 0x4e, 0xaf, 0x55, 0x69, 0x18, 0x61, 0x51, 0x22}
+ },
+ {
+ {
+ 0x63, 0xd7, 0xd6, 0x00,
+ 0x57, 0x62, 0x5d, 0xf5,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x57, 0x62, 0x5d, 0xaf,
+ 0x52, 0x28, 0x21, 0xaf,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x57, 0x62, 0x5d, 0x69,
+ 0x57, 0x62, 0x5d, 0x23,
+ 0x57, 0x62, 0x5d, 0xd2,
+ 0x63, 0xd7, 0xd6, 0xf5,
+ 0x57, 0x62, 0x5d, 0x46,
+ 0x63, 0xd7, 0xd6, 0x46,
+ 0x52, 0x28, 0x21, 0x69,
+ 0x57, 0x62, 0x5d, 0x23,
+ 0x5d, 0x9c, 0x99, 0xf5
+ },
+ {0xf5, 0x00, 0x81, 0x36, 0xa9, 0x17, 0xec, 0x1e, 0xba, 0x66, 0x44, 0x51, 0xfc, 0xfd, 0xcf, 0xb4}
+ },
+ {
+ {
+ 0x94, 0x6f, 0x60, 0x25,
+ 0x94, 0x6f, 0x60, 0x25,
+ 0xc5, 0xab, 0x76, 0x05,
+ 0xc5, 0xab, 0x76, 0xe8,
+ 0x63, 0x34, 0x4a, 0xe8,
+ 0x63, 0x34, 0x4a, 0x25,
+ 0x94, 0x6f, 0x60, 0x86,
+ 0xf7, 0xe7, 0x8c, 0x05,
+ 0x94, 0x6f, 0x60, 0x25,
+ 0x63, 0x34, 0x4a, 0xa7,
+ 0x94, 0x6f, 0x60, 0x66,
+ 0x63, 0x34, 0x4a, 0xc7,
+ 0x94, 0x6f, 0x60, 0xa7,
+ 0xf7, 0xe7, 0x8c, 0xa7,
+ 0x63, 0x34, 0x4a, 0x45,
+ 0xc5, 0xab, 0x76, 0xa7
+ },
+ {0xe8, 0x05, 0x7f, 0x80, 0x33, 0x5f, 0xb5, 0x79, 0x31, 0xf7, 0xa9, 0x61, 0xaf, 0x35, 0x77, 0x93}
+ },
+};
+
+
+static INLINE void
+st_sample_dxt_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ uint8_t *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h)
+{
+ const struct dxt_data *data;
+ unsigned n;
+ unsigned i;
+ unsigned x, y, ch;
+
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ data = dxt1_rgb_data;
+ n = sizeof(dxt1_rgb_data)/sizeof(dxt1_rgb_data[0]);
+ break;
+ case PIPE_FORMAT_DXT1_RGBA:
+ data = dxt1_rgba_data;
+ n = sizeof(dxt1_rgba_data)/sizeof(dxt1_rgba_data[0]);
+ break;
+ case PIPE_FORMAT_DXT3_RGBA:
+ data = dxt3_rgba_data;
+ n = sizeof(dxt3_rgba_data)/sizeof(dxt3_rgba_data[0]);
+ break;
+ case PIPE_FORMAT_DXT5_RGBA:
+ data = dxt5_rgba_data;
+ n = sizeof(dxt5_rgba_data)/sizeof(dxt5_rgba_data[0]);
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ i = st_random() % n;
+
+ for(y = 0; y < h; ++y)
+ for(x = 0; x < w; ++x)
+ for(ch = 0; ch < 4; ++ch)
+ rgba[y*rgba_stride + x*4 + ch] = (float)(data[i].rgba[y*4*4 + x*4 + ch])/255.0f;
+
+ memcpy(raw, data[i].raw, block->size);
+}
+
+
+static INLINE void
+st_sample_generic_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ uint8_t *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h)
+{
+ unsigned i;
+ unsigned x, y, ch;
+
+ for(i = 0; i < block->size; ++i)
+ raw[i] = (uint8_t)st_random();
+
+
+ pipe_tile_raw_to_rgba(format,
+ raw,
+ w, h,
+ rgba, rgba_stride);
+
+ if(format == PIPE_FORMAT_YCBCR || format == PIPE_FORMAT_YCBCR_REV) {
+ for(y = 0; y < h; ++y) {
+ for(x = 0; x < w; ++x) {
+ for(ch = 0; ch < 4; ++ch) {
+ unsigned offset = y*rgba_stride + x*4 + ch;
+ rgba[offset] = CLAMP(rgba[offset], 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Randomly sample pixels.
+ */
+void
+st_sample_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ void *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h)
+{
+ switch(format) {
+ case PIPE_FORMAT_DXT1_RGB:
+ case PIPE_FORMAT_DXT1_RGBA:
+ case PIPE_FORMAT_DXT3_RGBA:
+ case PIPE_FORMAT_DXT5_RGBA:
+ st_sample_dxt_pixel_block(format, block, raw, rgba, rgba_stride, w, h);
+ break;
+
+ default:
+ st_sample_generic_pixel_block(format, block, raw, rgba, rgba_stride, w, h);
+ break;
+ }
+}
+
+
+void
+st_sample_surface(struct st_surface *surface, float *rgba)
+{
+ struct pipe_texture *texture = surface->texture;
+ struct pipe_screen *screen = texture->screen;
+ unsigned width = texture->width[surface->level];
+ unsigned height = texture->height[surface->level];
+ uint rgba_stride = width * 4;
+ struct pipe_transfer *transfer;
+ void *raw;
+
+ transfer = screen->get_tex_transfer(screen,
+ surface->texture,
+ surface->face,
+ surface->level,
+ surface->zslice,
+ PIPE_TRANSFER_WRITE,
+ 0, 0,
+ width,
+ height);
+ if (!transfer)
+ return;
+
+ raw = screen->transfer_map(screen, transfer);
+ if (raw) {
+ const struct pipe_format_block *block = &texture->block;
+ uint x, y;
+
+ for (y = 0; y < transfer->nblocksy; ++y) {
+ for (x = 0; x < transfer->nblocksx; ++x) {
+ st_sample_pixel_block(texture->format,
+ block,
+ (uint8_t *) raw + y * transfer->stride + x * block->size,
+ rgba + y * block->height * rgba_stride + x * block->width * 4,
+ rgba_stride,
+ MIN2(block->width, width - x*block->width),
+ MIN2(block->height, height - y*block->height));
+ }
+ }
+
+ screen->transfer_unmap(screen, transfer);
+ }
+
+ screen->tex_transfer_destroy(transfer);
+}
diff --git a/src/gallium/state_trackers/python/st_sample.h b/src/gallium/state_trackers/python/st_sample.h
new file mode 100644
index 0000000000..0a27083549
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_sample.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_SAMPLE_H_
+#define ST_SAMPLE_H_
+
+
+#include "pipe/p_format.h"
+
+
+void
+st_sample_pixel_block(enum pipe_format format,
+ const struct pipe_format_block *block,
+ void *raw,
+ float *rgba, unsigned rgba_stride,
+ unsigned w, unsigned h);
+
+void
+st_sample_surface(struct st_surface *surface, float *rgba);
+
+
+#endif /* ST_SAMPLE_H_ */
diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c
new file mode 100644
index 0000000000..f0a4826a00
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c
@@ -0,0 +1,270 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * 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 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
+ * THE COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Softpipe support.
+ *
+ * @author Keith Whitwell
+ * @author Brian Paul
+ * @author Jose Fonseca
+ */
+
+
+#include "pipe/internal/p_winsys_screen.h"/* port to just p_screen */
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+#include "softpipe/sp_winsys.h"
+#include "st_winsys.h"
+
+
+struct st_softpipe_buffer
+{
+ struct pipe_buffer base;
+ boolean userBuffer; /** Is this a user-space buffer? */
+ void *data;
+ void *mapped;
+};
+
+
+/** Cast wrapper */
+static INLINE struct st_softpipe_buffer *
+st_softpipe_buffer( struct pipe_buffer *buf )
+{
+ return (struct st_softpipe_buffer *)buf;
+}
+
+
+static void *
+st_softpipe_buffer_map(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf,
+ unsigned flags)
+{
+ struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf);
+ st_softpipe_buf->mapped = st_softpipe_buf->data;
+ return st_softpipe_buf->mapped;
+}
+
+
+static void
+st_softpipe_buffer_unmap(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf);
+ st_softpipe_buf->mapped = NULL;
+}
+
+
+static void
+st_softpipe_buffer_destroy(struct pipe_buffer *buf)
+{
+ struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf);
+
+ if (oldBuf->data) {
+ if (!oldBuf->userBuffer)
+ align_free(oldBuf->data);
+
+ oldBuf->data = NULL;
+ }
+
+ FREE(oldBuf);
+}
+
+
+static void
+st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+}
+
+
+
+static const char *
+st_softpipe_get_name(struct pipe_winsys *winsys)
+{
+ return "softpipe";
+}
+
+
+static struct pipe_buffer *
+st_softpipe_buffer_create(struct pipe_winsys *winsys,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size)
+{
+ struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer);
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+ buffer->data = align_malloc(size, alignment);
+
+ return &buffer->base;
+}
+
+
+/**
+ * Create buffer which wraps user-space data.
+ */
+static struct pipe_buffer *
+st_softpipe_user_buffer_create(struct pipe_winsys *winsys,
+ void *ptr,
+ unsigned bytes)
+{
+ struct st_softpipe_buffer *buffer;
+
+ buffer = CALLOC_STRUCT(st_softpipe_buffer);
+ if(!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.size = bytes;
+ buffer->userBuffer = TRUE;
+ buffer->data = ptr;
+
+ return &buffer->base;
+}
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+static struct pipe_buffer *
+st_softpipe_surface_buffer_create(struct pipe_winsys *winsys,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned usage,
+ unsigned *stride)
+{
+ const unsigned alignment = 64;
+ struct pipe_format_block block;
+ unsigned nblocksx, nblocksy;
+
+ pf_get_block(format, &block);
+ nblocksx = pf_get_nblocksx(&block, width);
+ nblocksy = pf_get_nblocksy(&block, height);
+ *stride = round_up(nblocksx * block.size, alignment);
+
+ return winsys->buffer_create(winsys, alignment,
+ usage,
+ *stride * nblocksy);
+}
+
+
+static void
+st_softpipe_fence_reference(struct pipe_winsys *winsys,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+}
+
+
+static int
+st_softpipe_fence_signalled(struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static int
+st_softpipe_fence_finish(struct pipe_winsys *winsys,
+ struct pipe_fence_handle *fence,
+ unsigned flag)
+{
+ return 0;
+}
+
+
+static void
+st_softpipe_destroy(struct pipe_winsys *winsys)
+{
+ FREE(winsys);
+}
+
+
+static struct pipe_screen *
+st_softpipe_screen_create(void)
+{
+ static struct pipe_winsys *winsys;
+ struct pipe_screen *screen;
+
+ winsys = CALLOC_STRUCT(pipe_winsys);
+ if(!winsys)
+ return NULL;
+
+ winsys->destroy = st_softpipe_destroy;
+
+ winsys->buffer_create = st_softpipe_buffer_create;
+ winsys->user_buffer_create = st_softpipe_user_buffer_create;
+ winsys->buffer_map = st_softpipe_buffer_map;
+ winsys->buffer_unmap = st_softpipe_buffer_unmap;
+ winsys->buffer_destroy = st_softpipe_buffer_destroy;
+
+ winsys->surface_buffer_create = st_softpipe_surface_buffer_create;
+
+ winsys->fence_reference = st_softpipe_fence_reference;
+ winsys->fence_signalled = st_softpipe_fence_signalled;
+ winsys->fence_finish = st_softpipe_fence_finish;
+
+ winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer;
+ winsys->get_name = st_softpipe_get_name;
+
+ screen = softpipe_create_screen(winsys);
+ if(!screen)
+ st_softpipe_destroy(winsys);
+
+ return screen;
+}
+
+
+static struct pipe_context *
+st_softpipe_context_create(struct pipe_screen *screen)
+{
+ return softpipe_create(screen);
+}
+
+
+const struct st_winsys st_softpipe_winsys = {
+ &st_softpipe_screen_create,
+ &st_softpipe_context_create,
+};
diff --git a/src/gallium/state_trackers/python/st_winsys.h b/src/gallium/state_trackers/python/st_winsys.h
new file mode 100644
index 0000000000..b8cb612d86
--- /dev/null
+++ b/src/gallium/state_trackers/python/st_winsys.h
@@ -0,0 +1,52 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 TUNGSTEN GRAPHICS 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.
+ *
+ **************************************************************************/
+
+
+#ifndef ST_WINSYS_H_
+#define ST_WINSYS_H_
+
+
+struct pipe_screen;
+struct pipe_context;
+
+
+struct st_winsys
+{
+ struct pipe_screen *
+ (*screen_create)(void);
+
+ struct pipe_context *
+ (*context_create)(struct pipe_screen *screen);
+};
+
+
+extern const struct st_winsys st_softpipe_winsys;
+
+extern const struct st_winsys st_hardpipe_winsys;
+
+
+#endif /* ST_WINSYS_H_ */
diff --git a/src/gallium/state_trackers/python/tests/.gitignore b/src/gallium/state_trackers/python/tests/.gitignore
new file mode 100644
index 0000000000..0dbbaeea16
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+*.tsv
+*.dot
diff --git a/src/gallium/state_trackers/python/tests/base.py b/src/gallium/state_trackers/python/tests/base.py
new file mode 100755
index 0000000000..202ccfc350
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/base.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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.
+#
+##########################################################################
+
+
+"""Base classes for tests.
+
+Loosely inspired on Python's unittest module.
+"""
+
+
+import os.path
+import sys
+
+from gallium import *
+
+
+# Enumerate all pixel formats
+formats = {}
+for name, value in globals().items():
+ if name.startswith("PIPE_FORMAT_") and isinstance(value, int):
+ formats[value] = name
+
+def is_depth_stencil_format(format):
+ # FIXME: make and use binding to pf_is_depth_stencil
+ return format in (
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ )
+
+def make_image(width, height, rgba):
+ import Image
+ outimage = Image.new(
+ mode='RGB',
+ size=(width, height),
+ color=(0,0,0))
+ outpixels = outimage.load()
+ for y in range(0, height):
+ for x in range(0, width):
+ offset = (y*width + x)*4
+ r, g, b, a = [int(min(max(rgba[offset + ch], 0.0), 1.0)*255) for ch in range(4)]
+ outpixels[x, y] = r, g, b
+ return outimage
+
+def save_image(width, height, rgba, filename):
+ outimage = make_image(width, height, rgba)
+ outimage.save(filename, "PNG")
+
+def show_image(width, height, **rgbas):
+ import Tkinter as tk
+ from PIL import Image, ImageTk
+
+ root = tk.Tk()
+
+ x = 64
+ y = 64
+
+ labels = rgbas.keys()
+ labels.sort()
+ for i in range(len(labels)):
+ label = labels[i]
+ outimage = make_image(width, height, rgbas[label])
+
+ if i:
+ window = tk.Toplevel(root)
+ else:
+ window = root
+ window.title(label)
+ image1 = ImageTk.PhotoImage(outimage)
+ w = image1.width()
+ h = image1.height()
+ window.geometry("%dx%d+%d+%d" % (w, h, x, y))
+ panel1 = tk.Label(window, image=image1)
+ panel1.pack(side='top', fill='both', expand='yes')
+ panel1.image = image1
+ x += w + 2
+
+ root.mainloop()
+
+
+class TestFailure(Exception):
+
+ pass
+
+class TestSkip(Exception):
+
+ pass
+
+
+class Test:
+
+ def __init__(self):
+ pass
+
+ def _run(self, result):
+ raise NotImplementedError
+
+ def run(self):
+ result = TestResult()
+ self._run(result)
+ result.summary()
+
+ def assert_rgba(self, surface, x, y, w, h, expected_rgba, pixel_tol=4.0/256, surface_tol=0.85):
+ total = h*w
+ different = surface.compare_tile_rgba(x, y, w, h, expected_rgba, tol=pixel_tol)
+ if different:
+ sys.stderr.write("%u out of %u pixels differ\n" % (different, total))
+
+ if float(total - different)/float(total) < surface_tol:
+ if 0:
+ rgba = FloatArray(h*w*4)
+ surface.get_tile_rgba(x, y, w, h, rgba)
+ show_image(w, h, Result=rgba, Expected=expected_rgba)
+ save_image(w, h, rgba, "result.png")
+ save_image(w, h, expected_rgba, "expected.png")
+ #sys.exit(0)
+
+ raise TestFailure
+
+
+class TestCase(Test):
+
+ tags = ()
+
+ def __init__(self, dev, **kargs):
+ Test.__init__(self)
+ self.dev = dev
+ self.__dict__.update(kargs)
+
+ def description(self):
+ descriptions = []
+ for tag in self.tags:
+ value = self.get(tag)
+ if value is not None and value != '':
+ descriptions.append(tag + '=' + str(value))
+ return ' '.join(descriptions)
+
+ def get(self, tag):
+ try:
+ method = getattr(self, '_get_' + tag)
+ except AttributeError:
+ return getattr(self, tag, None)
+ else:
+ return method()
+
+ def _get_target(self):
+ return {
+ PIPE_TEXTURE_1D: "1d",
+ PIPE_TEXTURE_2D: "2d",
+ PIPE_TEXTURE_3D: "3d",
+ PIPE_TEXTURE_CUBE: "cube",
+ }[self.target]
+
+ def _get_format(self):
+ name = formats[self.format]
+ if name.startswith('PIPE_FORMAT_'):
+ name = name[12:]
+ name = name.lower()
+ return name
+
+ def _get_face(self):
+ if self.target == PIPE_TEXTURE_CUBE:
+ return {
+ PIPE_TEX_FACE_POS_X: "+x",
+ PIPE_TEX_FACE_NEG_X: "-x",
+ PIPE_TEX_FACE_POS_Y: "+y",
+ PIPE_TEX_FACE_NEG_Y: "-y",
+ PIPE_TEX_FACE_POS_Z: "+z",
+ PIPE_TEX_FACE_NEG_Z: "-z",
+ }[self.face]
+ else:
+ return ''
+
+ def test(self):
+ raise NotImplementedError
+
+ def _run(self, result):
+ result.test_start(self)
+ try:
+ self.test()
+ except KeyboardInterrupt:
+ raise
+ except TestSkip:
+ result.test_skipped(self)
+ except TestFailure:
+ result.test_failed(self)
+ else:
+ result.test_passed(self)
+
+
+class TestSuite(Test):
+
+ def __init__(self, tests = None):
+ Test.__init__(self)
+ if tests is None:
+ self.tests = []
+ else:
+ self.tests = tests
+
+ def add_test(self, test):
+ self.tests.append(test)
+
+ def _run(self, result):
+ for test in self.tests:
+ test._run(result)
+
+
+class TestResult:
+
+ def __init__(self):
+ self.tests = 0
+ self.passed = 0
+ self.skipped = 0
+ self.failed = 0
+
+ self.names = ['result']
+ self.types = ['pass skip fail']
+ self.rows = []
+
+ def test_start(self, test):
+ sys.stdout.write("Running %s...\n" % test.description())
+ sys.stdout.flush()
+ self.tests += 1
+
+ def test_passed(self, test):
+ sys.stdout.write("PASS\n")
+ sys.stdout.flush()
+ self.passed += 1
+ self.log_result(test, 'pass')
+
+ def test_skipped(self, test):
+ sys.stdout.write("SKIP\n")
+ sys.stdout.flush()
+ self.skipped += 1
+ #self.log_result(test, 'skip')
+
+ def test_failed(self, test):
+ sys.stdout.write("FAIL\n")
+ sys.stdout.flush()
+ self.failed += 1
+ self.log_result(test, 'fail')
+
+ def log_result(self, test, result):
+ row = ['']*len(self.names)
+
+ # add result
+ assert self.names[0] == 'result'
+ assert result in ('pass', 'skip', 'fail')
+ row[0] = result
+
+ # add tags
+ for tag in test.tags:
+ value = test.get(tag)
+
+ # infer type
+ if value is None:
+ continue
+ elif isinstance(value, (int, float)):
+ value = str(value)
+ type = 'c' # continous
+ elif isinstance(value, basestring):
+ type = 'd' # discrete
+ else:
+ assert False
+ value = str(value)
+ type = 'd' # discrete
+
+ # insert value
+ try:
+ col = self.names.index(tag, 1)
+ except ValueError:
+ self.names.append(tag)
+ self.types.append(type)
+ row.append(value)
+ else:
+ row[col] = value
+ assert self.types[col] == type
+
+ self.rows.append(row)
+
+ def summary(self):
+ sys.stdout.write("%u tests, %u passed, %u skipped, %u failed\n\n" % (self.tests, self.passed, self.skipped, self.failed))
+ sys.stdout.flush()
+
+ name, ext = os.path.splitext(os.path.basename(sys.argv[0]))
+ filename = name + '.tsv'
+ stream = file(filename, 'wt')
+
+ # header
+ stream.write('\t'.join(self.names) + '\n')
+ stream.write('\t'.join(self.types) + '\n')
+ stream.write('class\n')
+
+ # rows
+ for row in self.rows:
+ row += ['']*(len(self.names) - len(row))
+ stream.write('\t'.join(row) + '\n')
+
+ stream.close()
+
+ # See http://www.ailab.si/orange/doc/ofb/c_otherclass.htm
+ try:
+ import orange
+ import orngTree
+ except ImportError:
+ sys.stderr.write('Install Orange from http://www.ailab.si/orange/ for a classification tree.\n')
+ return
+
+ data = orange.ExampleTable(filename)
+
+ tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2)
+
+ orngTree.printTxt(tree, maxDepth=4)
+
+ file(name+'.txt', 'wt').write(orngTree.dumpTree(tree))
+
+ orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box')
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh
new file mode 100644
index 0000000000..7a0006bf66
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.5, -0.4, -0.6, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+ABS OUT[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh
new file mode 100644
index 0000000000..f7836c85dd
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-add.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+ADD OUT[0], IN[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh
new file mode 100644
index 0000000000..c89cd748a8
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp3.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DP3 OUT[0], IN[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh
new file mode 100644
index 0000000000..6517e3c494
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dp4.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DP4 OUT[0], IN[0].xyzx, IN[0].xyzx
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh
new file mode 100644
index 0000000000..464880ba68
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-dst.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DST OUT[0], IN[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh
new file mode 100644
index 0000000000..2684076f1d
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-ex2.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+EX2 TEMP[0], IN[0].xxxx
+MUL OUT[0], TEMP[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh
new file mode 100644
index 0000000000..ad11e28918
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-flr.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 2.5, 4.0, 2.0, 1.0 }
+IMM FLT32 { 0.4, 0.25, 0.5, 1.0 }
+
+MUL TEMP[0], IN[0], IMM[0]
+FLR TEMP[0], TEMP[0]
+MUL OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh
new file mode 100644
index 0000000000..4f3aa30d66
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-frc.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 2.7, 3.1, 4.5, 1.0 }
+
+MUL TEMP[0], IN[0], IMM[0]
+FRC OUT[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh
new file mode 100644
index 0000000000..54c7c64459
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lg2.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 0.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+LG2 TEMP[0].x, TEMP[0].xxxx
+ADD OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh
new file mode 100644
index 0000000000..0e78ef86b5
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lit.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+LIT OUT[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh
new file mode 100644
index 0000000000..e9ee0f8147
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-lrp.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+ABS TEMP[0], IN[0]
+LRP OUT[0], TEMP[0], IN[0].xxxx, IN[0].yyyy
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh
new file mode 100644
index 0000000000..439acd5bbd
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mad.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.5, 0.4, 0.6, 1.0 }
+IMM FLT32 { 0.5, 0.4, 0.6, 0.0 }
+
+MAD OUT[0], IN[0], IMM[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh
new file mode 100644
index 0000000000..ab21b245dd
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-max.sh
@@ -0,0 +1,10 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.4, 0.4, 0.4, 0.0 }
+
+MAX OUT[0], IN[0], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh
new file mode 100644
index 0000000000..969ae73d98
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-min.sh
@@ -0,0 +1,10 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.6, 0.6, 0.6, 1.0 }
+
+MIN OUT[0], IN[0], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh
new file mode 100644
index 0000000000..612975e057
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mov.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+MOV OUT[0], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh
new file mode 100644
index 0000000000..ed158b0fc6
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-mul.sh
@@ -0,0 +1,10 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+IMM FLT32 { 0.5, 0.6, 0.7, 1.0 }
+
+MUL OUT[0], IN[0], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh
new file mode 100644
index 0000000000..cc9feef07e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rcp.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RCP TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh
new file mode 100644
index 0000000000..695621fdc9
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-rsq.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RSQ TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh
new file mode 100644
index 0000000000..9505bc3c3e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sge.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.6, 0.0 }
+
+SGE TEMP[0], IN[0], IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh
new file mode 100644
index 0000000000..f2a1521cbf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-slt.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.6, 0.0 }
+
+SLT TEMP[0], IN[0], IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh
new file mode 100644
index 0000000000..9cd4b68295
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-abs.sh
@@ -0,0 +1,13 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.3, -0.5, -0.4, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV OUT[0], |TEMP[0]|
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh
new file mode 100644
index 0000000000..acd6aa750d
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-absneg.sh
@@ -0,0 +1,15 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.2, -0.3, -0.4, 0.0 }
+IMM FLT32 { -1.0, -1.0, -1.0, -1.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV TEMP[0], -|TEMP[0]|
+MUL OUT[0], TEMP[0], IMM[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh
new file mode 100644
index 0000000000..ba1b61503b
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-neg.sh
@@ -0,0 +1,11 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+DCL TEMP[0]
+
+SUB TEMP[0], IN[0], IN[0].yzxw
+MOV OUT[0], -TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh
new file mode 100644
index 0000000000..192aa7bb26
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-srcmod-swz.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+MOV OUT[0], IN[0].yxzw
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh
new file mode 100644
index 0000000000..83441fa820
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-sub.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+SUB OUT[0], IN[0], IN[0].yzxw
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh
new file mode 100644
index 0000000000..d6f66c4927
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-xpd.sh
@@ -0,0 +1,8 @@
+FRAG1.1
+
+DCL IN[0], COLOR, LINEAR
+DCL OUT[0], COLOR
+
+XPD OUT[0], IN[0], IN[0].yzxw
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py b/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py
new file mode 100644
index 0000000000..d60fb38d1a
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/fragment-shader.py
@@ -0,0 +1,218 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 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.
+#
+##########################################################################
+
+
+from gallium import *
+
+def make_image(surface):
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface):
+ outimage = make_image(surface)
+ outimage.save(filename, "PNG")
+
+def test(dev, name):
+ ctx = dev.context_create()
+
+ width = 320
+ height = 320
+ minz = 0.0
+ maxz = 1.0
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 0
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.scissor = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # viewport
+ viewport = Viewport()
+ scale = FloatArray(4)
+ scale[0] = width / 2.0
+ scale[1] = -height / 2.0
+ scale[2] = (maxz - minz) / 2.0
+ scale[3] = 1.0
+ viewport.scale = scale
+ translate = FloatArray(4)
+ translate[0] = width / 2.0
+ translate[1] = height / 2.0
+ translate[2] = (maxz - minz) / 2.0
+ translate[3] = 0.0
+ viewport.translate = translate
+ ctx.set_viewport(viewport)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ ctx.set_sampler(0, sampler)
+
+ # scissor
+ scissor = Scissor()
+ scissor.minx = 0
+ scissor.miny = 0
+ scissor.maxx = width
+ scissor.maxy = height
+ ctx.set_scissor(scissor)
+
+ clip = Clip()
+ clip.nr = 0
+ ctx.set_clip(clip)
+
+ # framebuffer
+ cbuf = dev.texture_create(
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ ).get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION
+ DCL IN[1], COLOR
+ DCL OUT[0], POSITION
+ DCL OUT[1], COLOR
+ MOV OUT[0], IN[0]
+ MOV OUT[1], IN[1]
+ END
+ ''')
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader(file('frag-' + name + '.sh', 'rt').read())
+ ctx.set_fragment_shader(fs)
+
+ xy = [
+ -0.8, -0.8,
+ 0.8, -0.8,
+ 0.0, 0.8,
+ ]
+ color = [
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0,
+ ]
+
+ nverts = 3
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ for i in range(0, nverts):
+ verts[i * nattrs * 4 + 0] = xy[i * 2 + 0] # x
+ verts[i * nattrs * 4 + 1] = xy[i * 2 + 1] # y
+ verts[i * nattrs * 4 + 2] = 0.5 # z
+ verts[i * nattrs * 4 + 3] = 1.0 # w
+ verts[i * nattrs * 4 + 4] = color[i * 3 + 0] # r
+ verts[i * nattrs * 4 + 5] = color[i * 3 + 1] # g
+ verts[i * nattrs * 4 + 6] = color[i * 3 + 2] # b
+ verts[i * nattrs * 4 + 7] = 1.0 # a
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLES,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ save_image('frag-' + name + '.png', cbuf)
+
+def main():
+ tests = [
+ 'abs',
+ 'add',
+ 'dp3',
+ 'dp4',
+ 'dst',
+ 'ex2',
+ 'flr',
+ 'frc',
+ 'lg2',
+ 'lit',
+ 'lrp',
+ 'mad',
+ 'max',
+ 'min',
+ 'mov',
+ 'mul',
+ 'rcp',
+ 'rsq',
+ 'sge',
+ 'slt',
+ 'srcmod-abs',
+ 'srcmod-absneg',
+ 'srcmod-neg',
+ 'srcmod-swz',
+ 'sub',
+ 'xpd',
+ ]
+
+ dev = Device()
+ for t in tests:
+ test(dev, t)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh
new file mode 100644
index 0000000000..f0d0d5de17
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-abs.sh
@@ -0,0 +1,15 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.2, 0.2, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+ABS OUT[0], TEMP[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh
new file mode 100644
index 0000000000..936c851c9d
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-add.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.2, -0.1, 0.0, 0.0 }
+
+ADD OUT[0], IN[0], IMM[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh
new file mode 100644
index 0000000000..7638e96346
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arl.sh
@@ -0,0 +1,23 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+DCL ADDR[0]
+
+IMM FLT32 { 3.0, 1.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 1.0, 1.0 }
+
+MOV OUT[0], IN[0]
+MUL TEMP[0], IN[0], IMM[0]
+ARL ADDR[0].x, TEMP[0]
+MOV OUT[1], IMM[ADDR[0].x + 3]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh
new file mode 100644
index 0000000000..28ce6f9a0c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-arr.sh
@@ -0,0 +1,23 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+DCL ADDR[0]
+
+IMM FLT32 { 3.0, 1.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 1.0, 1.0 }
+
+MOV OUT[0], IN[0]
+MUL TEMP[0], IN[0], IMM[0]
+ARR ADDR[0].x, TEMP[0]
+MOV OUT[1], IMM[ADDR[0].x + 3]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh
new file mode 100644
index 0000000000..b57d68520f
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp3.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+
+DP3 TEMP[0].xy, IN[0], IN[0]
+MOV TEMP[0].zw, IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh
new file mode 100644
index 0000000000..0eb31719c5
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dp4.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+
+DP4 TEMP[0].xy, IN[0], IN[0]
+MOV TEMP[0].zw, IMM[0]
+MUL OUT[0], IN[0], TEMP[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh
new file mode 100644
index 0000000000..dc5e0eb92e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-dst.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+DST OUT[1], IN[1], IN[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh
new file mode 100644
index 0000000000..34057af4e6
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-ex2.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0..1]
+
+IMM FLT32 { 0.3, 0.3, 0.3, 1.0 }
+
+EX2 TEMP[0], IN[0]
+EX2 TEMP[1], IN[1].yyyy
+MUL TEMP[0], TEMP[0], IMM[0]
+MOV OUT[0], IN[0]
+MUL OUT[1], TEMP[0], TEMP[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh
new file mode 100644
index 0000000000..44ad708119
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-flr.sh
@@ -0,0 +1,23 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+DCL ADDR[0]
+
+IMM FLT32 { 3.0, 1.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 0.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 0.0, 1.0, 1.0 }
+IMM FLT32 { 1.0, 1.0, 0.0, 1.0 }
+IMM FLT32 { 0.0, 1.0, 1.0, 1.0 }
+
+MOV OUT[0], IN[0]
+MUL TEMP[0], IN[0], IMM[0]
+FLR ADDR[0].x, TEMP[0]
+MOV OUT[1], IMM[ADDR[0].x + 3]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh
new file mode 100644
index 0000000000..d179749de8
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-frc.sh
@@ -0,0 +1,15 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 2.7, 3.1, 4.5, 1.0 }
+
+MUL TEMP[0], IN[0].xyxw, IMM[0]
+MOV OUT[0], IN[0]
+FRC OUT[1], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh
new file mode 100644
index 0000000000..f6e08d087c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lg2.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 0.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+LG2 TEMP[0].x, TEMP[0].xxxx
+ADD OUT[0], TEMP[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh
new file mode 100644
index 0000000000..da98f30928
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lit.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+LIT OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh
new file mode 100644
index 0000000000..8c262580e2
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-lrp.sh
@@ -0,0 +1,14 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+ABS TEMP[0], IN[0]
+MOV OUT[0], IN[0]
+LRP OUT[1], TEMP[0], IN[1].xxxx, IN[1].yyyy
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh
new file mode 100644
index 0000000000..eb07a3bd56
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mad.sh
@@ -0,0 +1,14 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.5, 1.0, 1.0, 1.0 }
+IMM FLT32 { 0.5, 0.0, 0.0, 0.0 }
+
+MAD OUT[0], IN[0], IMM[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh
new file mode 100644
index 0000000000..2d8b1fe3bf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-max.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.5, 0.5, 0.5, 0.0 }
+
+MOV OUT[0], IN[0]
+MAX OUT[1], IN[1], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh
new file mode 100644
index 0000000000..84af0e2905
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-min.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.5, 0.5, 0.5, 0.0 }
+
+MOV OUT[0], IN[0]
+MIN OUT[1], IN[1], IMM[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh
new file mode 100644
index 0000000000..bcdec07c20
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mov.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh
new file mode 100644
index 0000000000..f3b57c3038
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-mul.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.6, 0.6, 1.0, 1.0 }
+
+MUL OUT[0], IN[0], IMM[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh
new file mode 100644
index 0000000000..78af589b5c
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rcp.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RCP TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh
new file mode 100644
index 0000000000..1675c7d5ff
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-rsq.sh
@@ -0,0 +1,18 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 1.0, 0.0, 0.0, 0.0 }
+IMM FLT32 { 1.5, 0.0, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+RSQ TEMP[0].x, TEMP[0].xxxx
+SUB OUT[0], TEMP[0], IMM[1]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh
new file mode 100644
index 0000000000..3d92cd5aae
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sge.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { -0.1, -0.1, 1.0, 0.0 }
+
+SGE TEMP[0], IN[0], IMM[0]
+MOV OUT[0], IN[0]
+MUL OUT[1], IN[1], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh
new file mode 100644
index 0000000000..85c60ff4ec
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-slt.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+DCL TEMP[0]
+
+IMM FLT32 { 0.6, 0.6, 0.0, 0.0 }
+
+SLT TEMP[0], IN[0], IMM[0]
+MOV OUT[0], IN[0]
+MUL OUT[1], IN[1], TEMP[0]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
new file mode 100644
index 0000000000..6db417a62e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-abs.sh
@@ -0,0 +1,15 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { 0.1, 0.1, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV OUT[0], |TEMP[0]|
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
new file mode 100644
index 0000000000..fc83238052
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-absneg.sh
@@ -0,0 +1,16 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+DCL TEMP[0]
+
+IMM FLT32 { -0.2, -0.2, 0.0, 0.0 }
+
+ADD TEMP[0], IN[0], IMM[0]
+MOV OUT[0].xy, -|TEMP[0]|
+MOV OUT[0].zw, IN[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
new file mode 100644
index 0000000000..ce4e90b5e1
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-neg.sh
@@ -0,0 +1,12 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0].xy, -IN[0]
+MOV OUT[0].zw, IN[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
new file mode 100644
index 0000000000..c03de4c674
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-srcmod-swz.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0].yxzw
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh
new file mode 100644
index 0000000000..a583b95828
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-sub.sh
@@ -0,0 +1,13 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+IMM FLT32 { 0.1, 0.1, 0.0, 0.0 }
+
+SUB OUT[0], IN[0], IMM[0]
+MOV OUT[1], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh
new file mode 100644
index 0000000000..8def8943b0
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vert-xpd.sh
@@ -0,0 +1,11 @@
+VERT1.1
+
+DCL IN[0], POSITION
+DCL IN[1], COLOR
+DCL OUT[0], POSITION
+DCL OUT[1], COLOR
+
+MOV OUT[0], IN[0]
+XPD OUT[1], IN[0], IN[1]
+
+END
diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py
new file mode 100644
index 0000000000..472769f259
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 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.
+#
+##########################################################################
+
+
+from gallium import *
+
+def make_image(surface):
+ data = surface.get_tile_rgba8(0, 0, surface.width, surface.height)
+
+ import Image
+ outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1)
+ return outimage
+
+def save_image(filename, surface):
+ outimage = make_image(surface)
+ outimage.save(filename, "PNG")
+
+def test(dev, name):
+ ctx = dev.context_create()
+
+ width = 320
+ height = 320
+ minz = 0.0
+ maxz = 1.0
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 0
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.scissor = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # viewport
+ viewport = Viewport()
+ scale = FloatArray(4)
+ scale[0] = width / 2.0
+ scale[1] = -height / 2.0
+ scale[2] = (maxz - minz) / 2.0
+ scale[3] = 1.0
+ viewport.scale = scale
+ translate = FloatArray(4)
+ translate[0] = width / 2.0
+ translate[1] = height / 2.0
+ translate[2] = (maxz - minz) / 2.0
+ translate[3] = 0.0
+ viewport.translate = translate
+ ctx.set_viewport(viewport)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ ctx.set_sampler(0, sampler)
+
+ # scissor
+ scissor = Scissor()
+ scissor.minx = 0
+ scissor.miny = 0
+ scissor.maxx = width
+ scissor.maxy = height
+ ctx.set_scissor(scissor)
+
+ clip = Clip()
+ clip.nr = 0
+ ctx.set_clip(clip)
+
+ # framebuffer
+ cbuf = dev.texture_create(
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ width, height,
+ tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET,
+ ).get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+
+ # vertex shader
+ vs = Shader(file('vert-' + name + '.sh', 'rt').read())
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], COLOR, LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:END
+ ''')
+ ctx.set_fragment_shader(fs)
+
+ xy = [
+ 0.0, 0.8,
+ -0.2, 0.4,
+ 0.2, 0.4,
+ -0.4, 0.0,
+ 0.0, 0.0,
+ 0.4, 0.0,
+ -0.6, -0.4,
+ -0.2, -0.4,
+ 0.2, -0.4,
+ 0.6, -0.4,
+ -0.8, -0.8,
+ -0.4, -0.8,
+ 0.0, -0.8,
+ 0.4, -0.8,
+ 0.8, -0.8,
+ ]
+ color = [
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0,
+ ]
+ tri = [
+ 1, 2, 0,
+ 3, 4, 1,
+ 4, 2, 1,
+ 4, 5, 2,
+ 6, 7, 3,
+ 7, 4, 3,
+ 7, 8, 4,
+ 8, 5, 4,
+ 8, 9, 5,
+ 10, 11, 6,
+ 11, 7, 6,
+ 11, 12, 7,
+ 12, 8, 7,
+ 12, 13, 8,
+ 13, 9, 8,
+ 13, 14, 9,
+ ]
+
+ nverts = 16 * 3
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ for i in range(0, nverts):
+ verts[i * nattrs * 4 + 0] = xy[tri[i] * 2 + 0] # x
+ verts[i * nattrs * 4 + 1] = xy[tri[i] * 2 + 1] # y
+ verts[i * nattrs * 4 + 2] = 0.5 # z
+ verts[i * nattrs * 4 + 3] = 1.0 # w
+ verts[i * nattrs * 4 + 4] = color[(i % 3) * 3 + 0] # r
+ verts[i * nattrs * 4 + 5] = color[(i % 3) * 3 + 1] # g
+ verts[i * nattrs * 4 + 6] = color[(i % 3) * 3 + 2] # b
+ verts[i * nattrs * 4 + 7] = 1.0 # a
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLES,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ save_image('vert-' + name + '.png', cbuf)
+
+def main():
+ tests = [
+ 'abs',
+ 'add',
+ 'arl',
+ 'arr',
+ 'dp3',
+ 'dp4',
+ 'dst',
+ 'ex2',
+ 'flr',
+ 'frc',
+ 'lg2',
+ 'lit',
+ 'lrp',
+ 'mad',
+ 'max',
+ 'min',
+ 'mov',
+ 'mul',
+ 'rcp',
+ 'rsq',
+ 'sge',
+ 'slt',
+ 'srcmod-abs',
+ 'srcmod-absneg',
+ 'srcmod-neg',
+ 'srcmod-swz',
+ 'sub',
+ 'xpd',
+ ]
+
+ dev = Device()
+ for t in tests:
+ test(dev, t)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/surface_copy.py b/src/gallium/state_trackers/python/tests/surface_copy.py
new file mode 100755
index 0000000000..3ceecbbd3a
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/surface_copy.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 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.
+#
+##########################################################################
+
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+class TextureTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ # textures
+ dst_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+ if dst_texture is None:
+ raise TestSkip
+
+ dst_surface = dst_texture.get_surface(face = face, level = level, zslice = zslice)
+
+ src_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = dst_surface.width,
+ height = dst_surface.height,
+ depth = 1,
+ last_level = 0,
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER,
+ )
+
+ src_surface = src_texture.get_surface()
+
+ x = 0
+ y = 0
+ w = dst_surface.width
+ h = dst_surface.height
+
+ stride = dst_surface.nblocksx * dst_texture.block.size
+ size = dst_surface.nblocksy * stride
+ src_raw = os.urandom(size)
+
+ src_surface.put_tile_raw(0, 0, w, h, src_raw, stride)
+
+ ctx = self.dev.context_create()
+
+ ctx.surface_copy(dst_surface, 0, 0,
+ src_surface, 0, 0, w, h)
+
+ ctx.flush()
+
+ dst_raw = dst_surface.get_tile_raw(0, 0, w, h)
+
+ if dst_raw != src_raw:
+ raise TestFailure
+
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ #PIPE_TEXTURE_3D,
+ ]
+
+ formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_DXT1_RGB,
+ PIPE_FORMAT_DXT1_RGBA,
+ PIPE_FORMAT_DXT3_RGBA,
+ PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for target in targets:
+ for format in formats:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/texture_render.py b/src/gallium/state_trackers/python/tests/texture_render.py
new file mode 100755
index 0000000000..0b76932b6e
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/texture_render.py
@@ -0,0 +1,320 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 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.
+#
+##########################################################################
+
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+class TextureTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ # textures
+ dst_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+ if dst_texture is None:
+ raise TestSkip
+
+ dst_surface = dst_texture.get_surface(face = face, level = level, zslice = zslice)
+
+ ref_texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = dst_surface.width,
+ height = dst_surface.height,
+ depth = 1,
+ last_level = 0,
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER,
+ )
+
+ ref_surface = ref_texture.get_surface()
+
+ src_texture = dev.texture_create(
+ target = target,
+ format = PIPE_FORMAT_A8R8G8B8_UNORM,
+ width = dst_surface.width,
+ height = dst_surface.height,
+ depth = 1,
+ last_level = 0,
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER,
+ )
+
+ src_surface = src_texture.get_surface()
+
+ expected_rgba = FloatArray(height*width*4)
+ ref_surface.sample_rgba(expected_rgba)
+
+ src_surface.put_tile_rgba(0, 0, src_surface.width, src_surface.height, expected_rgba)
+
+ ctx = self.dev.context_create()
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # no-op depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.bypass_vs_clip_and_viewport = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ sampler.min_lod = 0
+ sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
+ ctx.set_sampler(0, sampler)
+ ctx.set_sampler_texture(0, src_texture)
+
+ # framebuffer
+ cbuf_tex = dev.texture_create(
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ fb = Framebuffer()
+ fb.width = dst_surface.width
+ fb.height = dst_surface.height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, dst_surface)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.0
+ rgba[1] = 0.0
+ rgba[2] = 0.0
+ rgba[3] = 0.0
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+ del fb
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], GENERIC, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], GENERIC, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ #vs.dump()
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], GENERIC[0], LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ DCL SAMP[0], CONSTANT
+ 0:TEX OUT[0], IN[0], SAMP[0], 2D
+ 1:END
+ ''')
+ #fs.dump()
+ ctx.set_fragment_shader(fs)
+
+ nverts = 4
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ x = 0
+ y = 0
+ w = dst_surface.width
+ h = dst_surface.height
+
+ pos = [
+ [x, y],
+ [x+w, y],
+ [x+w, y+h],
+ [x, y+h],
+ ]
+
+ tex = [
+ [0.0, 0.0],
+ [1.0, 0.0],
+ [1.0, 1.0],
+ [0.0, 1.0],
+ ]
+
+ for i in range(0, 4):
+ j = 8*i
+ verts[j + 0] = pos[i][0] # x
+ verts[j + 1] = pos[i][1] # y
+ verts[j + 2] = 0.0 # z
+ verts[j + 3] = 1.0 # w
+ verts[j + 4] = tex[i][0] # s
+ verts[j + 5] = tex[i][1] # r
+ verts[j + 6] = 0.0
+ verts[j + 7] = 1.0
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ self.assert_rgba(dst_surface, x, y, w, h, expected_rgba, 4.0/256, 0.85)
+
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ #PIPE_TEXTURE_3D,
+ ]
+
+ formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ #PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ #PIPE_FORMAT_Z32_UNORM,
+ #PIPE_FORMAT_Z24S8_UNORM,
+ #PIPE_FORMAT_Z24X8_UNORM,
+ #PIPE_FORMAT_Z16_UNORM,
+ #PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ #PIPE_FORMAT_DXT1_RGB,
+ #PIPE_FORMAT_DXT1_RGBA,
+ #PIPE_FORMAT_DXT3_RGBA,
+ #PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for target in targets:
+ for format in formats:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/texture_sample.py b/src/gallium/state_trackers/python/tests/texture_sample.py
new file mode 100755
index 0000000000..c7b78abbbe
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/texture_sample.py
@@ -0,0 +1,591 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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.
+#
+##########################################################################
+
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+def minify(dims, level = 1):
+ return [max(dim>>level, 1) for dim in dims]
+
+
+def tex_coords(texture, face, level, zslice):
+ st = [
+ [0.0, 0.0],
+ [1.0, 0.0],
+ [1.0, 1.0],
+ [0.0, 1.0],
+ ]
+
+ if texture.target == PIPE_TEXTURE_2D:
+ return [[s, t, 0.0] for s, t in st]
+ elif texture.target == PIPE_TEXTURE_3D:
+ depth = texture.get_depth(level)
+ if depth > 1:
+ r = float(zslice)/float(depth - 1)
+ else:
+ r = 0.0
+ return [[s, t, r] for s, t in st]
+ elif texture.target == PIPE_TEXTURE_CUBE:
+ result = []
+ for s, t in st:
+ # See http://developer.nvidia.com/object/cube_map_ogl_tutorial.html
+ sc = 2.0*s - 1.0
+ tc = 2.0*t - 1.0
+ if face == PIPE_TEX_FACE_POS_X:
+ rx = 1.0
+ ry = -tc
+ rz = -sc
+ if face == PIPE_TEX_FACE_NEG_X:
+ rx = -1.0
+ ry = -tc
+ rz = sc
+ if face == PIPE_TEX_FACE_POS_Y:
+ rx = sc
+ ry = 1.0
+ rz = tc
+ if face == PIPE_TEX_FACE_NEG_Y:
+ rx = sc
+ ry = -1.0
+ rz = -tc
+ if face == PIPE_TEX_FACE_POS_Z:
+ rx = sc
+ ry = -tc
+ rz = 1.0
+ if face == PIPE_TEX_FACE_NEG_Z:
+ rx = -sc
+ ry = -tc
+ rz = -1.0
+ result.append([rx, ry, rz])
+ return result
+
+def is_pot(n):
+ return n & (n - 1) == 0
+
+
+class TextureColorSampleTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER
+ geom_flags = 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, tex_usage, geom_flags):
+ raise TestSkip
+
+ ctx = self.dev.context_create()
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # no-op depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.bypass_vs_clip_and_viewport = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ sampler.min_lod = 0
+ sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
+ ctx.set_sampler(0, sampler)
+
+ # texture
+ texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = tex_usage,
+ )
+
+ expected_rgba = FloatArray(height*width*4)
+ texture.get_surface(
+ face = face,
+ level = level,
+ zslice = zslice,
+ ).sample_rgba(expected_rgba)
+
+ ctx.set_sampler_texture(0, texture)
+
+ # framebuffer
+ cbuf_tex = dev.texture_create(
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ cbuf = cbuf_tex.get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0)
+ del fb
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], GENERIC, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], GENERIC, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ #vs.dump()
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ op = {
+ PIPE_TEXTURE_1D: "1D",
+ PIPE_TEXTURE_2D: "2D",
+ PIPE_TEXTURE_3D: "3D",
+ PIPE_TEXTURE_CUBE: "CUBE",
+ }[target]
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], GENERIC[0], LINEAR
+ DCL OUT[0], COLOR, CONSTANT
+ DCL SAMP[0], CONSTANT
+ 0:TEX OUT[0], IN[0], SAMP[0], %s
+ 1:END
+ ''' % op)
+ #fs.dump()
+ ctx.set_fragment_shader(fs)
+
+ nverts = 4
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ x = 0
+ y = 0
+ w, h = minify((width, height), level)
+
+ pos = [
+ [x, y],
+ [x+w, y],
+ [x+w, y+h],
+ [x, y+h],
+ ]
+
+ tex = tex_coords(texture, face, level, zslice)
+
+ for i in range(0, 4):
+ j = 8*i
+ verts[j + 0] = pos[i][0] # x
+ verts[j + 1] = pos[i][1] # y
+ verts[j + 2] = 0.0 # z
+ verts[j + 3] = 1.0 # w
+ verts[j + 4] = tex[i][0] # s
+ verts[j + 5] = tex[i][1] # r
+ verts[j + 6] = tex[i][2] # q
+ verts[j + 7] = 1.0
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ cbuf = cbuf_tex.get_surface()
+
+ self.assert_rgba(cbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
+
+
+class TextureDepthSampleTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ tex_usage = PIPE_TEXTURE_USAGE_SAMPLER
+ geom_flags = 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, tex_usage, geom_flags):
+ raise TestSkip
+
+ ctx = self.dev.context_create()
+
+ # disabled blending/masking
+ blend = Blend()
+ blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE
+ blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO
+ blend.colormask = PIPE_MASK_RGBA
+ ctx.set_blend(blend)
+
+ # depth/stencil/alpha
+ depth_stencil_alpha = DepthStencilAlpha()
+ depth_stencil_alpha.depth.enabled = 1
+ depth_stencil_alpha.depth.writemask = 1
+ depth_stencil_alpha.depth.func = PIPE_FUNC_LESS
+ ctx.set_depth_stencil_alpha(depth_stencil_alpha)
+
+ # rasterizer
+ rasterizer = Rasterizer()
+ rasterizer.front_winding = PIPE_WINDING_CW
+ rasterizer.cull_mode = PIPE_WINDING_NONE
+ rasterizer.bypass_vs_clip_and_viewport = 1
+ ctx.set_rasterizer(rasterizer)
+
+ # samplers
+ sampler = Sampler()
+ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST
+ sampler.normalized_coords = 1
+ sampler.min_lod = 0
+ sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1
+ ctx.set_sampler(0, sampler)
+
+ # texture
+ texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = tex_usage,
+ )
+
+ expected_rgba = FloatArray(height*width*4)
+ texture.get_surface(
+ face = face,
+ level = level,
+ zslice = zslice,
+ ).sample_rgba(expected_rgba)
+
+ ctx.set_sampler_texture(0, texture)
+
+ # framebuffer
+ cbuf_tex = dev.texture_create(
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ zsbuf_tex = dev.texture_create(
+ PIPE_FORMAT_Z24X8_UNORM,
+ width,
+ height,
+ tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET,
+ )
+
+ cbuf = cbuf_tex.get_surface()
+ zsbuf = zsbuf_tex.get_surface()
+ fb = Framebuffer()
+ fb.width = width
+ fb.height = height
+ fb.nr_cbufs = 1
+ fb.set_cbuf(0, cbuf)
+ fb.set_zsbuf(zsbuf)
+ ctx.set_framebuffer(fb)
+ rgba = FloatArray(4);
+ rgba[0] = 0.5
+ rgba[1] = 0.5
+ rgba[2] = 0.5
+ rgba[3] = 0.5
+ ctx.clear(PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0)
+ del fb
+
+ # vertex shader
+ vs = Shader('''
+ VERT1.1
+ DCL IN[0], POSITION, CONSTANT
+ DCL IN[1], GENERIC, CONSTANT
+ DCL OUT[0], POSITION, CONSTANT
+ DCL OUT[1], GENERIC, CONSTANT
+ 0:MOV OUT[0], IN[0]
+ 1:MOV OUT[1], IN[1]
+ 2:END
+ ''')
+ #vs.dump()
+ ctx.set_vertex_shader(vs)
+
+ # fragment shader
+ op = {
+ PIPE_TEXTURE_1D: "1D",
+ PIPE_TEXTURE_2D: "2D",
+ PIPE_TEXTURE_3D: "3D",
+ PIPE_TEXTURE_CUBE: "CUBE",
+ }[target]
+ fs = Shader('''
+ FRAG1.1
+ DCL IN[0], GENERIC[0], LINEAR
+ DCL SAMP[0], CONSTANT
+ DCL OUT[0].z, POSITION
+ 0:TEX OUT[0].z, IN[0], SAMP[0], %s
+ 1:END
+ ''' % op)
+ #fs.dump()
+ ctx.set_fragment_shader(fs)
+
+ nverts = 4
+ nattrs = 2
+ verts = FloatArray(nverts * nattrs * 4)
+
+ x = 0
+ y = 0
+ w, h = minify((width, height), level)
+
+ pos = [
+ [x, y],
+ [x+w, y],
+ [x+w, y+h],
+ [x, y+h],
+ ]
+
+ tex = tex_coords(texture, face, level, zslice)
+
+ for i in range(0, 4):
+ j = 8*i
+ verts[j + 0] = pos[i][0] # x
+ verts[j + 1] = pos[i][1] # y
+ verts[j + 2] = 0.0 # z
+ verts[j + 3] = 1.0 # w
+ verts[j + 4] = tex[i][0] # s
+ verts[j + 5] = tex[i][1] # r
+ verts[j + 6] = tex[i][2] # q
+ verts[j + 7] = 1.0
+
+ ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN,
+ nverts,
+ nattrs,
+ verts)
+
+ ctx.flush()
+
+ zsbuf = zsbuf_tex.get_surface()
+
+ self.assert_rgba(zsbuf, x, y, w, h, expected_rgba, 4.0/256, 0.85)
+
+
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ PIPE_TEXTURE_3D,
+ ]
+
+ color_formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ #PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_YCBCR,
+ PIPE_FORMAT_DXT1_RGB,
+ #PIPE_FORMAT_DXT1_RGBA,
+ #PIPE_FORMAT_DXT3_RGBA,
+ #PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ depth_formats = [
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for format in color_formats:
+ for target in targets:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureColorSampleTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ for format in depth_formats:
+ target = PIPE_TEXTURE_2D
+ depth = 1
+ face = 0
+ last_level = 0
+ level = 0
+ zslice = 0
+ for size in sizes:
+ test = TextureDepthSampleTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/texture_transfer.py b/src/gallium/state_trackers/python/tests/texture_transfer.py
new file mode 100755
index 0000000000..e65b425adf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/texture_transfer.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2009 VMware, Inc.
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# 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.
+#
+##########################################################################
+
+
+import os
+
+from gallium import *
+from base import *
+
+
+def lods(*dims):
+ size = max(dims)
+ lods = 0
+ while size:
+ lods += 1
+ size >>= 1
+ return lods
+
+
+class TextureTest(TestCase):
+
+ tags = (
+ 'target',
+ 'format',
+ 'width',
+ 'height',
+ 'depth',
+ 'last_level',
+ 'face',
+ 'level',
+ 'zslice',
+ )
+
+ def test(self):
+ dev = self.dev
+
+ target = self.target
+ format = self.format
+ width = self.width
+ height = self.height
+ depth = self.depth
+ last_level = self.last_level
+ face = self.face
+ level = self.level
+ zslice = self.zslice
+
+ tex_usage = 0
+
+ texture = dev.texture_create(
+ target = target,
+ format = format,
+ width = width,
+ height = height,
+ depth = depth,
+ last_level = last_level,
+ tex_usage = tex_usage,
+ )
+ if texture is None:
+ raise TestSkip
+
+ surface = texture.get_surface(face, level, zslice)
+
+ stride = surface.nblocksx * texture.block.size
+ size = surface.nblocksy * stride
+
+ in_raw = os.urandom(size)
+
+ surface.put_tile_raw(0, 0, surface.width, surface.height, in_raw, stride)
+
+ out_raw = surface.get_tile_raw(0, 0, surface.width, surface.height)
+
+ if in_raw != out_raw:
+ raise TestFailure
+
+
+def main():
+ dev = Device()
+ suite = TestSuite()
+
+ targets = [
+ PIPE_TEXTURE_2D,
+ PIPE_TEXTURE_CUBE,
+ PIPE_TEXTURE_3D,
+ ]
+
+ formats = [
+ PIPE_FORMAT_A8R8G8B8_UNORM,
+ PIPE_FORMAT_X8R8G8B8_UNORM,
+ PIPE_FORMAT_A8R8G8B8_SRGB,
+ PIPE_FORMAT_R5G6B5_UNORM,
+ PIPE_FORMAT_A1R5G5B5_UNORM,
+ PIPE_FORMAT_A4R4G4B4_UNORM,
+ PIPE_FORMAT_Z32_UNORM,
+ PIPE_FORMAT_Z24S8_UNORM,
+ PIPE_FORMAT_Z24X8_UNORM,
+ PIPE_FORMAT_Z16_UNORM,
+ PIPE_FORMAT_S8_UNORM,
+ PIPE_FORMAT_A8_UNORM,
+ PIPE_FORMAT_L8_UNORM,
+ PIPE_FORMAT_DXT1_RGB,
+ PIPE_FORMAT_DXT1_RGBA,
+ PIPE_FORMAT_DXT3_RGBA,
+ PIPE_FORMAT_DXT5_RGBA,
+ ]
+
+ sizes = [64, 32, 16, 8, 4, 2, 1]
+ #sizes = [1020, 508, 252, 62, 30, 14, 6, 3]
+ #sizes = [64]
+ #sizes = [63]
+
+ faces = [
+ PIPE_TEX_FACE_POS_X,
+ PIPE_TEX_FACE_NEG_X,
+ PIPE_TEX_FACE_POS_Y,
+ PIPE_TEX_FACE_NEG_Y,
+ PIPE_TEX_FACE_POS_Z,
+ PIPE_TEX_FACE_NEG_Z,
+ ]
+
+ for target in targets:
+ for format in formats:
+ for size in sizes:
+ if target == PIPE_TEXTURE_3D:
+ depth = size
+ else:
+ depth = 1
+ for face in faces:
+ if target != PIPE_TEXTURE_CUBE and face:
+ continue
+ levels = lods(size)
+ for last_level in range(levels):
+ for level in range(0, last_level + 1):
+ zslice = 0
+ while zslice < depth >> level:
+ test = TextureTest(
+ dev = dev,
+ target = target,
+ format = format,
+ width = size,
+ height = size,
+ depth = depth,
+ last_level = last_level,
+ face = face,
+ level = level,
+ zslice = zslice,
+ )
+ suite.add_test(test)
+ zslice = (zslice + 1)*2 - 1
+ suite.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/gallium/state_trackers/python/tests/tree.py b/src/gallium/state_trackers/python/tests/tree.py
new file mode 100755
index 0000000000..0c1bcda4cf
--- /dev/null
+++ b/src/gallium/state_trackers/python/tests/tree.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+#
+# See also:
+# http://www.ailab.si/orange/doc/ofb/c_otherclass.htm
+
+import os.path
+import sys
+
+import orange
+import orngTree
+
+for arg in sys.argv[1:]:
+ name, ext = os.path.splitext(arg)
+
+ data = orange.ExampleTable(arg)
+
+ tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2)
+
+ orngTree.printTxt(tree)
+
+ file(name+'.txt', 'wt').write(orngTree.dumpTree(tree) + '\n')
+
+ orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box')