Merge branch 'master' of git+ssh://michal@git.freedesktop.org/git/mesa/mesa into...
authormichal <michal@michal-laptop.(none)>
Fri, 27 Jul 2007 08:05:40 +0000 (10:05 +0200)
committermichal <michal@michal-laptop.(none)>
Fri, 27 Jul 2007 08:05:40 +0000 (10:05 +0200)
168 files changed:
configs/linux-dri
progs/samples/prim.c
progs/trivial/Makefile
progs/trivial/clear.c
progs/trivial/dlist-dangling.c
progs/trivial/dlist-edgeflag-dangling.c
progs/trivial/dlist-edgeflag.c
progs/trivial/fs-tri.c [new file with mode: 0644]
progs/trivial/line-clip.c
progs/trivial/line-cull.c
progs/trivial/line-userclip-clip.c
progs/trivial/line-userclip-nop-clip.c
progs/trivial/line-userclip-nop.c
progs/trivial/line-userclip.c
progs/trivial/line.c
progs/trivial/lineloop-clip.c
progs/trivial/lineloop.c
progs/trivial/point-clip.c
progs/trivial/point-param.c
progs/trivial/point-wide.c
progs/trivial/point.c
progs/trivial/poly-flat.c
progs/trivial/poly-unfilled.c
progs/trivial/poly.c
progs/trivial/quad-clip-all-vertices.c
progs/trivial/quad-clip-nearplane.c
progs/trivial/quad-clip.c
progs/trivial/quad-degenerate.c
progs/trivial/quad-flat.c
progs/trivial/quad-offset-factor.c
progs/trivial/quad-offset-unfilled.c
progs/trivial/quad-offset-units.c
progs/trivial/quad-tex-3d.c
progs/trivial/quad-unfilled.c
progs/trivial/quads.c
progs/trivial/quadstrip-flat.c
progs/trivial/quadstrip.c
progs/trivial/tri-blend.c
progs/trivial/tri-clip.c
progs/trivial/tri-cull.c
progs/trivial/tri-dlist.c
progs/trivial/tri-edgeflag.c
progs/trivial/tri-flat-clip.c
progs/trivial/tri-flat.c
progs/trivial/tri-tex-3d.c
progs/trivial/tri-unfilled-clip.c
progs/trivial/tri-unfilled-smooth.c
progs/trivial/tri-unfilled-userclip.c
progs/trivial/tri-unfilled.c
progs/trivial/tri-userclip.c
progs/trivial/tri-z.c [new file with mode: 0644]
progs/trivial/tri.c
progs/trivial/tristrip.c
src/mesa/drivers/dri/Makefile.template
src/mesa/drivers/dri/i915tex/i915_vtbl.c
src/mesa/drivers/dri/i915tex/intel_blit.c
src/mesa/drivers/dri/i915tex/intel_buffers.c
src/mesa/drivers/dri/i915tex/intel_context.c
src/mesa/drivers/dri/i915tex/intel_context.h
src/mesa/drivers/dri/i915tex/intel_fbo.c
src/mesa/drivers/dri/i915tex/intel_screen.c
src/mesa/drivers/dri/i915tex/intel_screen.h
src/mesa/drivers/dri/i915tex/intel_state.c
src/mesa/drivers/x11/Makefile [new file with mode: 0644]
src/mesa/drivers/x11/xm_api.c
src/mesa/drivers/x11/xm_dd.c
src/mesa/drivers/x11/xm_span.c
src/mesa/drivers/x11/xm_surface.c [new file with mode: 0644]
src/mesa/drivers/x11/xm_tri.c
src/mesa/drivers/x11/xmesaP.h
src/mesa/main/mtypes.h
src/mesa/main/queryobj.c
src/mesa/pipe/Makefile [new file with mode: 0644]
src/mesa/pipe/draw/draw_clip.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_context.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_context.h [new file with mode: 0644]
src/mesa/pipe/draw/draw_cull.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_flatshade.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_offset.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_private.h [new file with mode: 0644]
src/mesa/pipe/draw/draw_twoside.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_unfilled.c [new file with mode: 0644]
src/mesa/pipe/draw/draw_vb.c [new file with mode: 0644]
src/mesa/pipe/p_context.h [new file with mode: 0644]
src/mesa/pipe/p_defines.h [new file with mode: 0644]
src/mesa/pipe/p_state.h [new file with mode: 0644]
src/mesa/pipe/softpipe/Makefile [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_clear.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_clear.h [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_context.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_context.h [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_headers.h [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_prim_setup.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_prim_setup.h [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad.h [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_alpha_test.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_blend.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_bufloop.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_colormask.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_coverage.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_depth_test.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_fs.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_occlusion.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_output.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_stencil.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_quad_stipple.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state.h [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_blend.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_clip.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_derived.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_fs.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_sampler.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_setup.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_state_surface.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_surface.c [new file with mode: 0644]
src/mesa/pipe/softpipe/sp_surface.h [new file with mode: 0644]
src/mesa/pipe/tgsi/Makefile [new file with mode: 0644]
src/mesa/pipe/tgsi/core/Makefile [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_build.c [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_build.h [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_core.h [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_dump.c [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_dump.h [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_exec.c [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_exec.h [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_parse.c [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_parse.h [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_token.h [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_util.c [new file with mode: 0644]
src/mesa/pipe/tgsi/core/tgsi_util.h [new file with mode: 0644]
src/mesa/pipe/tgsi/mesa/Makefile [new file with mode: 0644]
src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c [new file with mode: 0644]
src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.h [new file with mode: 0644]
src/mesa/pipe/tgsi/mesa/tgsi_mesa.h [new file with mode: 0644]
src/mesa/pipe/tgsi/tgsi_platform.h [new file with mode: 0644]
src/mesa/sources
src/mesa/state_tracker/Makefile [new file with mode: 0644]
src/mesa/state_tracker/st_atom.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom.h [new file with mode: 0644]
src/mesa/state_tracker/st_atom_alphatest.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_blend.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_cbuf.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_clear_color.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_clip.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_depth.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_framebuffer.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_fs.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_sampler.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_scissor.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_setup.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_stencil.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_stipple.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_viewport.c [new file with mode: 0644]
src/mesa/state_tracker/st_atom_vs.c [new file with mode: 0644]
src/mesa/state_tracker/st_cb_program.c [new file with mode: 0644]
src/mesa/state_tracker/st_context.c [new file with mode: 0644]
src/mesa/state_tracker/st_context.h [new file with mode: 0644]
src/mesa/state_tracker/st_draw.c [new file with mode: 0644]
src/mesa/state_tracker/st_draw.h [new file with mode: 0644]
src/mesa/state_tracker/st_program.h [new file with mode: 0644]
src/mesa/state_tracker/st_public.h [new file with mode: 0644]
src/mesa/state_tracker/st_texobj.c [new file with mode: 0644]
src/mesa/state_tracker/st_texobj.h [new file with mode: 0644]
src/mesa/vf/vf.c [new file with mode: 0644]
src/mesa/vf/vf.h [new file with mode: 0644]
src/mesa/vf/vf_generic.c [new file with mode: 0644]
src/mesa/vf/vf_sse.c [new file with mode: 0644]

index 5f945a73f1a4c5df4725a2eacd8098bcb49b289b..4af8c25f66f869b0c85cdc6b5db45eefc0b40be2 100644 (file)
@@ -66,5 +66,4 @@ WINDOW_SYSTEM=dri
 
 # gamma are missing because they have not been converted to use the new
 # interface.
-DRI_DIRS = i810 i915tex i915 i965 mach64 mga r128 r200 r300 radeon s3v \
-       savage sis tdfx trident unichrome ffb
+DRI_DIRS = i915tex 
index 388e0153b4f2007b4e0ab34f422735df937062e3..f47c60faefd160bc6ebbfc275479a8d86e6f4c91 100644 (file)
@@ -466,7 +466,7 @@ static void Draw(void)
     } else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     }
-
+#if 01
     Viewport(0, 0); Point();
     Viewport(0, 1); Lines();
     Viewport(0, 2); LineStrip();
@@ -479,10 +479,12 @@ static void Draw(void)
     Viewport(1, 3); TriangleStrip();
 
     Viewport(2, 0); Rect();
+#endif
     Viewport(2, 1); PolygonFunc();
+#if 01
     Viewport(2, 2); Quads();
     Viewport(2, 3); QuadStrip();
-
+#endif
     glFlush();
 
     if (doubleBuffer) {
index 341c115c07d86e80c2cbee13c6fbaac5462c7695..2edf0ae0084b8d0dd99406dddfe64a44ca2a8582 100644 (file)
@@ -12,6 +12,7 @@ LIBS = $(APP_LIB_DEPS)
 
 SOURCES = \
        clear.c \
+       fs-tri.c \
        line-clip.c \
        line-cull.c \
        line-userclip-clip.c \
@@ -63,6 +64,7 @@ SOURCES = \
        tri-unfilled.c \
        tri-userclip.c \
        tri-dlist.c \
+       tri-z.c \
        tri.c \
        tristrip-clip.c \
        tristrip.c \
@@ -137,6 +139,11 @@ readtex.c: $(TOP)/progs/util/readtex.c
        ln -s $(TOP)/progs/util/readtex.c .
 
 
+fs-tri: fs-tri.c extfuncs.h
+
+
+extfuncs.h:  $(TOP)/progs/util/extfuncs.h
+       cp $< .
 
 
 # Emacs tags
index 7e7ca588c312db86953d865cdd5ae1692ff2e88f..69931b58182027d73beb79c7351343a8608bb8ac 100644 (file)
@@ -108,7 +108,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 97f878e96b9115a33122ae437bcd42fdae4b7d41..00a75078444eaa4518499d1b786692d9ac60aecd 100644 (file)
@@ -131,7 +131,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 31300efd842bf7536eb21f37eae40bdbbdc93657..b993946320ff521d2f7a45ca80f425ff946392cb 100644 (file)
@@ -134,7 +134,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index fa97f041035f77242d4e0e848facb0702c1b48cb..9e190db7001fe7a556b95b5a2f94d68e25df4aa0 100644 (file)
@@ -138,7 +138,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
diff --git a/progs/trivial/fs-tri.c b/progs/trivial/fs-tri.c
new file mode 100644 (file)
index 0000000..3be4d42
--- /dev/null
@@ -0,0 +1,212 @@
+/* Test fragment shader */
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include <GL/glut.h>
+#include <GL/glext.h>
+#include "extfuncs.h"
+
+
+static GLuint fragShader;
+static GLuint vertShader;
+static GLuint program;
+static GLint win = 0;
+static GLfloat xpos = 0, ypos = 0;
+
+
+static void
+Redisplay(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glPushMatrix();
+   glTranslatef(xpos, ypos, 0);
+
+   glBegin(GL_TRIANGLES);
+   glColor3f(1, 0, 0);
+   glVertex2f(-0.9, -0.9);
+   glColor3f(0, 1, 0);
+   glVertex2f( 0.9, -0.9);
+   glColor3f(0, 0, 1);
+   glVertex2f( 0,  0.9);
+   glEnd();
+
+   glPopMatrix();
+
+   glutSwapBuffers();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(-1, 1, -1, 1, -1, 1);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+}
+
+
+static void
+CleanUp(void)
+{
+   glDeleteShader_func(fragShader);
+   glDeleteShader_func(vertShader);
+   glDeleteProgram_func(program);
+   glutDestroyWindow(win);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+  (void) x;
+  (void) y;
+
+   switch(key) {
+   case 27:
+      CleanUp();
+      exit(0);
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+SpecialKey(int key, int x, int y)
+{
+   const GLfloat step = 0.1;
+
+  (void) x;
+  (void) y;
+
+   switch(key) {
+   case GLUT_KEY_UP:
+      ypos += step;
+      break;
+   case GLUT_KEY_DOWN:
+      ypos -= step;
+      break;
+   case GLUT_KEY_LEFT:
+      xpos -= step;
+      break;
+   case GLUT_KEY_RIGHT:
+      xpos += step;
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+LoadAndCompileShader(GLuint shader, const char *text)
+{
+   GLint stat;
+
+   glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
+
+   glCompileShader_func(shader);
+
+   glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      glGetShaderInfoLog_func(shader, 1000, &len, log);
+      fprintf(stderr, "fslight: problem compiling shader:\n%s\n", log);
+      exit(1);
+   }
+}
+
+
+static void
+CheckLink(GLuint prog)
+{
+   GLint stat;
+   glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      glGetProgramInfoLog_func(prog, 1000, &len, log);
+      fprintf(stderr, "Linker error:\n%s\n", log);
+   }
+}
+
+
+static void
+Init(void)
+{
+   /* fragment color is a function of fragment position: */
+   static const char *fragShaderText =
+      "void main() {\n"
+      "   gl_FragColor = gl_FragCoord * vec4(0.005); \n"
+      "   //gl_FragColor = gl_Color; \n"
+      "   //gl_FragColor = vec4(1, 0, 0.5, 0); \n"
+      "}\n";
+#if 0
+   static const char *vertShaderText =
+      "varying vec3 normal;\n"
+      "void main() {\n"
+      "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+      "   normal = gl_NormalMatrix * gl_Normal;\n"
+      "}\n";
+#endif
+   const char *version;
+
+   version = (const char *) glGetString(GL_VERSION);
+   if (version[0] != '2' || version[1] != '.') {
+      printf("This program requires OpenGL 2.x, found %s\n", version);
+      exit(1);
+   }
+
+   GetExtensionFuncs();
+
+   fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
+   LoadAndCompileShader(fragShader, fragShaderText);
+
+#if 0
+   vertShader = glCreateShader_func(GL_VERTEX_SHADER);
+   LoadAndCompileShader(vertShader, vertShaderText);
+#endif
+
+   program = glCreateProgram_func();
+   glAttachShader_func(program, fragShader);
+#if 0
+   glAttachShader_func(program, vertShader);
+#endif
+   glLinkProgram_func(program);
+   CheckLink(program);
+   glUseProgram_func(program);
+
+   assert(glGetError() == 0);
+
+   glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
+
+   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   glutInit(&argc, argv);
+   glutInitWindowPosition( 0, 0);
+   glutInitWindowSize(200, 200);
+   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+   win = glutCreateWindow(argv[0]);
+   glutReshapeFunc(Reshape);
+   glutKeyboardFunc(Key);
+   glutSpecialFunc(SpecialKey);
+   glutDisplayFunc(Redisplay);
+   Init();
+   glutMainLoop();
+   return 0;
+}
+
+
index 9acd12acc7b1652dd1ec65c9841af5f34b4d5591..fd79d049c4f0fc1ff74b280fe0d98c08f95023fb 100644 (file)
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 8999a8f0b1c6c32a61ae5747d28b56d3f3eee946..038004b4c4aae2d028ef626698bef877f68670fb 100644 (file)
@@ -118,7 +118,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index b24d8452bcdd49fdf319393db6340779c993339a..5c9c1b3b291e2cd2b93da6ecea2f9ab14e1c2401 100644 (file)
@@ -124,7 +124,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index e2e0b85a522eac4ab1db26375cc8220cb598118f..a6ee44fbd0f5600ea5bbde3ad03fcb3f02272233 100644 (file)
@@ -124,7 +124,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index eacee069789853d0acd558b26a949d1d7708e735..cebea5f4812a374f0816a0d6b55aaea5ac6d8342 100644 (file)
@@ -124,7 +124,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 6af91431d0852eee6921e55e81b980c3ba579d46..ecfd28cac7106c9650ec38f49c62ea77f5eba96b 100644 (file)
@@ -124,7 +124,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 58bad91b05aa274c0949dc5c37ce25b9855c02e5..b435a2689a09b5ef34715966f5c8a98544496e30 100644 (file)
@@ -40,7 +40,7 @@ static void Init(void)
    fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
    fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
 
-    glClearColor(0.0, 0.0, 1.0, 0.0);
+    glClearColor(0.3, 0.3, 0.3, 0.0);
 }
 
 static void Reshape(int width, int height)
index d8645ee34778e0fe2c3891edbf2981aaeba456eb..211056720fee893ea42ffafeb526dc54560fce22 100644 (file)
@@ -118,7 +118,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 7500c54fc2650e00db08f750770f7cba4adebf59..fab7d1ea0226661267e428073e380a51eea48587 100644 (file)
@@ -118,7 +118,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 32792047c64e7be1843647da6333d4a00eac331c..7fec54e1db93f3440744645c9e21aeba4bdb59fc 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index c5424682b853b4251f0eda6d28426fec7592a194..c50b7cb103422b43f5ec16cbec94c8cef61076ad 100644 (file)
@@ -127,7 +127,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 473ca043f1d2e081073267e1498694b32a5ca077..d1038ecfa15e06119c1feac8789ba5dc54dfd308 100644 (file)
@@ -33,6 +33,8 @@
 
 
 GLenum doubleBuffer;
+static GLboolean smooth = GL_FALSE;
+
 
 static void Init(void)
 {
@@ -58,6 +60,9 @@ static void Key(unsigned char key, int x, int y)
 {
 
     switch (key) {
+     case 's':
+        smooth = !smooth;
+        break;
       case 27:
        exit(1);
       default:
@@ -73,6 +78,16 @@ static void Draw(void)
 
    glPointSize(8.0);
 
+   if (smooth) {
+      glEnable(GL_POINT_SMOOTH);
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+   }
+   else {
+      glDisable(GL_POINT_SMOOTH);
+      glDisable(GL_BLEND);
+   }
+
    glBegin(GL_POINTS);
    glColor3f(1,0,0); 
    glVertex3f( 0.9, -0.9, -30.0);
@@ -122,7 +137,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 87465bfb2c1b8c835f78aa2801bbb46e9aae9823..8dabfb6ca64eb6809577aee17332164aec805ffc 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 747b24dc0ce32ca13a2bf03b3643d355ab59b6ab..a847d6828a7d59724a5e137d640c3c79e79dd80d 100644 (file)
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index e0ae463b083a69f27a7ad9fccac22940a7fc6ed0..ae092a830ab2e61289c230274a4cd696da25ae76 100644 (file)
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index bdb9e27aa91101ace21b4ed71970ffe4e60a14f6..2f254de48158fa881811bc661bcf6a187df4effb 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 019ef0c479a57efda5377e3ed547d2371c7c923f..3e0f3d949483df11f8199901064b27a69bea00e8 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 7e12e58a196b0355fcc7fb5655b4171171e57ce0..e76eb29f890b4729ec252e8706f87946738c2885 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 9f3a45caec3608b98a01f85e7071adda5f60d7ea..504fef3dc593ff770a0144c27f499804f9d924e4 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index b14b0f1d879f425ce42bc213a5455c604efee6cf..83047408573f19320a4ff5f3843426b4876b64f4 100644 (file)
@@ -125,7 +125,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index d6e9f02120653e000aa68b091a6350794c494509..bd8be7c43e3088f1696dd6dc44464b512261f838 100644 (file)
@@ -130,7 +130,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 861d3461c041722ec620f42e750bf16f481d73de..90943d908ff377f7c765cfaa8dffa032f22fd05b 100644 (file)
 #include <stdlib.h>
 #include <GL/glut.h>
 
-
-#define CI_OFFSET_1 16
-#define CI_OFFSET_2 32
-
-
 GLenum doubleBuffer;
 
 static void Init(void)
@@ -45,7 +40,6 @@ static void Init(void)
 
 static void Reshape(int width, int height)
 {
-
     glViewport(0, 0, (GLint)width, (GLint)height);
 
     glMatrixMode(GL_PROJECTION);
@@ -56,7 +50,6 @@ static void Reshape(int width, int height)
 
 static void Key(unsigned char key, int x, int y)
 {
-
     switch (key) {
       case 27:
        exit(1);
@@ -75,7 +68,6 @@ static void quad( float half )
    glVertex3f(-half/9.0,  half/9.0, -25.0 - half);
    glVertex3f(-half/9.0, -half/9.0, -25.0 - half);
    glEnd();
-
 }
 
 static void Draw(void)
@@ -83,27 +75,24 @@ static void Draw(void)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glEnable(GL_DEPTH_TEST);
 
-
-
+   /* red: offset back */
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1, 0);
-
    glColor3f(1,0,0); 
    quad(9);
 
+   /* green: no offset */
    glDisable(GL_POLYGON_OFFSET_FILL); 
    glColor3f(0,1,0); 
    quad(6);
 
-
+   /* black: offset zero, should not be visible because of z test */
    glEnable(GL_POLYGON_OFFSET_FILL); 
    glPolygonOffset(0, 0); 
-
-   /* Black - should not be visible
-    */
    glColor3f(0,0,0); 
    quad(6);
 
+   /* blue: offset forward */
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(-1, 0);
    glColor3f(0,0,1); 
@@ -149,7 +138,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB | GLUT_DEPTH;
+    type = GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
@@ -163,5 +152,5 @@ int main(int argc, char **argv)
     glutKeyboardFunc(Key);
     glutDisplayFunc(Draw);
     glutMainLoop();
-       return 0;
+    return 0;
 }
index 1cecf3c1cefa9a1640ee49034dd5162410a5f259..32b2129727bf00d896d30dad32d39ae8d44da133 100644 (file)
@@ -149,7 +149,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB | GLUT_DEPTH;
+    type = GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 5c41be308ee17d417fd3953096f8e475880f71a5..d5db21469e61dacee1f759df01cc4dae762c9db6 100644 (file)
 #include <stdlib.h>
 #include <GL/glut.h>
 
-
-#define CI_OFFSET_1 16
-#define CI_OFFSET_2 32
-
-
 GLenum doubleBuffer;
 
 static void Init(void)
@@ -45,7 +40,6 @@ static void Init(void)
 
 static void Reshape(int width, int height)
 {
-
     glViewport(0, 0, (GLint)width, (GLint)height);
 
     glMatrixMode(GL_PROJECTION);
@@ -56,7 +50,6 @@ static void Reshape(int width, int height)
 
 static void Key(unsigned char key, int x, int y)
 {
-
     switch (key) {
       case 27:
        exit(1);
@@ -75,7 +68,6 @@ static void quad( float half )
    glVertex3f(-half/9.0,  half/9.0, -25.0 - half);
    glVertex3f(-half/9.0, -half/9.0, -25.0 - half);
    glEnd();
-
 }
 
 static void Draw(void)
@@ -83,27 +75,26 @@ static void Draw(void)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glEnable(GL_DEPTH_TEST);
 
-
-
+   /* red: offset back */
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(0, 4);
-
    glColor3f(1,0,0); 
    quad(9);
 
+   /* black: no offset */
    glDisable(GL_POLYGON_OFFSET_FILL); 
    glColor3f(0,0,0); 
    quad(6);
 
+   /* green: offset 0 (this should obscure the black quad) */
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(0, 0);
-
    glDepthFunc( GL_EQUAL );
    glColor3f(0,1,0); 
    quad(6);
-   glDepthFunc( GL_LESS );
-
 
+   /* blue: offset forward */
+   glDepthFunc( GL_LESS );
    glPolygonOffset(0, -4);
    glColor3f(0,0,1); 
    quad(3);
@@ -148,7 +139,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB | GLUT_DEPTH;
+    type = GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
@@ -162,5 +153,5 @@ int main(int argc, char **argv)
     glutKeyboardFunc(Key);
     glutDisplayFunc(Draw);
     glutMainLoop();
-       return 0;
+    return 0;
 }
index 0b2dcc08a5f0fa0a6286ed13e3ffdf340381a03c..fd02d9d6adc3427e1c1f0e5566ae9641ad5f875c 100644 (file)
@@ -159,7 +159,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 9d63d2dfb95016e6bd12d0f352660b6644a26eb6..9d0087ce08d12a6d21dcf71cdf008a32555ea381 100644 (file)
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 1ca82cd9f8bbea4f3d3d419cfbd1bd60200aa115..307a9e0720999cf1daae66d818f5f503a9fc7d7d 100644 (file)
@@ -138,7 +138,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 061a0e409e4e2a20e89bdaffaa3c3b19ba6b5b8c..d02135f702a603ae3ba81027654aeb1d518579e1 100644 (file)
@@ -132,7 +132,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 342463f1a24ac8d64faf1c3e0eef920366502853..ff8644be09eecbb212fb8b9f8847b836f6b88104 100644 (file)
@@ -126,7 +126,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 284d15fd3c9878db7795c5f133750ab3ad06e164..58c451c976935966ca4198db56c1a256e8c03df3 100644 (file)
@@ -132,7 +132,7 @@ void keyboard(unsigned char key, int x, int y)
 int main(int argc, char** argv)
 {
    glutInit(&argc, argv);
-   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
+   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_ALPHA);
    glutInitWindowSize (200, 200);
    glutCreateWindow (argv[0]);
    init();
index bf48533adcced0e7405beb7f58964eab1c18b7e2..f30445cdba1c751da2c878f9946363c407199f6d 100644 (file)
 #include <GL/glut.h>
 
 
-#define CI_OFFSET_1 16
-#define CI_OFFSET_2 32
+static GLenum doubleBuffer;
+static GLfloat Xpos = 0, Ypos = 0;
 
 
-GLenum doubleBuffer;
-
 static void Init(void)
 {
    fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
    fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
    fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
-
-    glClearColor(0.0, 0.0, 1.0, 0.0);
+   glClearColor(0.0, 0.0, 1.0, 0.0);
 }
 
 static void Reshape(int width, int height)
 {
-
     glViewport(0, 0, (GLint)width, (GLint)height);
-
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
@@ -56,21 +51,45 @@ static void Reshape(int width, int height)
 
 static void Key(unsigned char key, int x, int y)
 {
-
     switch (key) {
       case 27:
        exit(1);
       default:
        return;
     }
-
     glutPostRedisplay();
 }
 
+static void
+SpecialKey(int key, int x, int y)
+{
+   const GLfloat step = 0.25;
+   (void) x;
+   (void) y;
+   switch (key) {
+      case GLUT_KEY_UP:
+         Ypos += step;
+         break;
+      case GLUT_KEY_DOWN:
+         Ypos -= step;
+         break;
+      case GLUT_KEY_LEFT:
+         Xpos -= step;
+         break;
+      case GLUT_KEY_RIGHT:
+         Xpos += step;
+         break;
+   }
+   glutPostRedisplay();
+}
+
 static void Draw(void)
 {
    glClear(GL_COLOR_BUFFER_BIT); 
 
+   glPushMatrix();
+   glTranslatef(Xpos, Ypos, 0);
+
    glBegin(GL_TRIANGLES);
    glColor3f(0,0,.7); 
    glVertex3f( 0.9, -0.9, -30.0);
@@ -80,12 +99,13 @@ static void Draw(void)
    glVertex3f(-1.9,  0.0, -30.0);
    glEnd();
 
+   glPopMatrix();
+
    glFlush();
 
    if (doubleBuffer) {
       glutSwapBuffers();
    }
-
 }
 
 static GLenum Args(int argc, char **argv)
@@ -131,7 +151,8 @@ int main(int argc, char **argv)
 
     glutReshapeFunc(Reshape);
     glutKeyboardFunc(Key);
+    glutSpecialFunc(SpecialKey);
     glutDisplayFunc(Draw);
     glutMainLoop();
-       return 0;
+    return 0;
 }
index 20aeaf1d7cddfb8f8ff838a4950744778a3b28ba..2eead8411558e15bcaeaf1318f4fc88adec79fd5 100644 (file)
 #include <stdlib.h>
 #include <GL/glut.h>
 
+static GLenum doubleBuffer;
+static GLint cullmode = 0;
+static GLenum front = GL_CCW; /* GL default */
 
-#define CI_OFFSET_1 16
-#define CI_OFFSET_2 32
-
-
-GLenum doubleBuffer;
+static void cull(void)
+{
+   cullmode = (cullmode + 1) % 4;
+   if (cullmode == 0) {
+      glCullFace(GL_FRONT);
+      glEnable(GL_CULL_FACE);
+      printf("cull GL_FRONT\n");
+   }
+   else if (cullmode == 1) {
+      glCullFace(GL_BACK);
+      glEnable(GL_CULL_FACE);
+      printf("cull GL_BACK\n");
+   }
+   else if (cullmode == 2) {
+      glCullFace(GL_FRONT_AND_BACK);
+      glEnable(GL_CULL_FACE);
+      printf("cull GL_FRONT_AND_BACK\n");
+   }
+   else {
+      glDisable(GL_CULL_FACE);
+      printf("cull none\n");
+   }
+}
 
 static void Init(void)
 {
    fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
    fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
    fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
-
-    glClearColor(0.0, 0.0, 1.0, 0.0);
+   glClearColor(0.0, 0.0, 1.0, 0.0);
+   cull();
 }
 
 static void Reshape(int width, int height)
 {
-
     glViewport(0, 0, (GLint)width, (GLint)height);
 
     glMatrixMode(GL_PROJECTION);
@@ -56,15 +76,21 @@ static void Reshape(int width, int height)
 
 static void Key(unsigned char key, int x, int y)
 {
-
-    switch (key) {
-      case 27:
-       exit(1);
-      default:
-       return;
-    }
-
-    glutPostRedisplay();
+   switch (key) {
+   case 27:
+      exit(1);
+   case 'c':
+      cull();
+      break;
+   case 'f':
+      front = ((front == GL_CCW) ? GL_CW : GL_CCW);
+      glFrontFace(front);
+      printf("front face = %s\n", front == GL_CCW ? "GL_CCW" : "GL_CW");
+      break;
+   default:
+      return;
+   }
+   glutPostRedisplay();
 }
 
 static void Draw(void)
@@ -72,12 +98,22 @@ static void Draw(void)
    glClear(GL_COLOR_BUFFER_BIT); 
 
    glBegin(GL_TRIANGLES);
-   glColor3f(0,0,1); 
-   glVertex3f( -1.5, 0.5, -30.0);
-   glColor3f(1,0,0); 
-   glVertex3f( 0,  2.0, -30.0);
-   glColor3f(0,1,0); 
-   glVertex3f(-1.5, 2.0, -30.0);
+   /* CCW / front-facing */
+   glColor3f(0,0,.7); 
+   glVertex3f(-0.1, -0.9, -30.0);
+   glColor3f(.8,0,0); 
+   glVertex3f(-0.1,  0.9, -30.0);
+   glColor3f(0,.9,0); 
+   glVertex3f(-0.9,  0.0, -30.0);
+
+   /* CW / back-facing */
+   glColor3f(0,0,.7); 
+   glVertex3f( 0.1, -0.9, -30.0);
+   glColor3f(.8,0,0); 
+   glVertex3f( 0.1,  0.9, -30.0);
+   glColor3f(0,.9,0); 
+   glVertex3f( 0.9,  0.0, -30.0);
+
    glEnd();
 
    glFlush();
@@ -118,7 +154,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
@@ -132,5 +168,5 @@ int main(int argc, char **argv)
     glutKeyboardFunc(Key);
     glutDisplayFunc(Draw);
     glutMainLoop();
-       return 0;
+    return 0;
 }
index e0ab285eff4f6c13a4724aa1d2ece2423f38c6cf..c21c4714adf15067dda859cb7484295bb85f3583 100644 (file)
@@ -132,7 +132,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index bdc0eaa253a8b0861e85fd9f9dbbdbb05a55903e..41899c2eb4f869226a6ac78435fd86336db48e81 100644 (file)
 #include <stdlib.h>
 #include <GL/glut.h>
 
-
-#define CI_OFFSET_1 16
-#define CI_OFFSET_2 32
-
-
-GLenum doubleBuffer;
+static GLenum doubleBuffer;
+static GLenum frontface = GL_CCW;
 
 static void Init(void)
 {
    fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
    fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
    fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
-
-    glClearColor(0.0, 0.0, 1.0, 0.0);
 }
 
 static void Reshape(int width, int height)
 {
-
     glViewport(0, 0, (GLint)width, (GLint)height);
 
     glMatrixMode(GL_PROJECTION);
@@ -56,13 +49,16 @@ static void Reshape(int width, int height)
 
 static void Key(unsigned char key, int x, int y)
 {
-
-    switch (key) {
-      case 27:
-       exit(1);
-      default:
-       return;
-    }
+   switch (key) {
+   case 'f':
+      frontface = (frontface == GL_CCW) ? GL_CW : GL_CCW;
+      glFrontFace(frontface);
+      break;
+   case 27:
+      exit(1);
+   default:
+      return;
+   }
 
     glutPostRedisplay();
 }
@@ -75,7 +71,7 @@ static void Draw(void)
 
    glBegin(GL_TRIANGLES);
    glEdgeFlag(1);
-   glColor3f(0,0,.7); 
+   glColor3f(0.3,0.3,.9); 
    glVertex3f( 0.9, -0.9, -0.0);
    glEdgeFlag(0);
    glColor3f(.8,0,0); 
@@ -123,7 +119,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
@@ -137,5 +133,5 @@ int main(int argc, char **argv)
     glutKeyboardFunc(Key);
     glutDisplayFunc(Draw);
     glutMainLoop();
-       return 0;
+    return 0;
 }
index fafa64914d4e3893cf46cd9b3235431ed259b152..155b0c4f8d40fb85ebc3a28dfc2f6043ebb43824 100644 (file)
@@ -119,7 +119,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index fb2cdbd7bba80c2eb21a306718052fb2b83edfc6..0583a2a99a1160cb0bd8e986fe07dc16b907028f 100644 (file)
@@ -119,7 +119,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 6a9d1d1bf6d4f17feeacd89c54be5387b81f3b5d..613803fd1b1920eaf5c13b5678ef3997d1dc8ba3 100644 (file)
@@ -152,7 +152,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index d486af23655f28fb2024bcdd0e71c6168c5ea7f2..df161df3fb82928140a2be94690c7de5448c9d50 100644 (file)
@@ -119,7 +119,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index e41903a3d50f6eaf4c354463982343dc7cc63286..f70c1cd9d4dac0a89cd90300b061999b764811e9 100644 (file)
@@ -132,7 +132,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index dc93a8f1abf9da589c83956f5db4ca59e1dcc5f0..9201f9d433cefc5c69cac6bba1813450e3a0f833 100644 (file)
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 73961bc93a61e5433150de55d33a7e5e23e3f636..1e44823db5a7433a96a988f70e6f8550a24bb9b6 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index cde9662ace92e7be56992f52673f6a37994a68af..ccf631dff80c5f1a564f1f11a148043d93c7ef6e 100644 (file)
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
diff --git a/progs/trivial/tri-z.c b/progs/trivial/tri-z.c
new file mode 100644 (file)
index 0000000..ae25900
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1993-1997, Silicon Graphics, Inc.
+ * ALL RIGHTS RESERVED 
+ * Permission to use, copy, modify, and distribute this software for 
+ * any purpose and without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies and that both the copyright notice
+ * and this permission notice appear in supporting documentation, and that 
+ * the name of Silicon Graphics, Inc. not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. 
+ *
+ * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
+ * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
+ * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
+ * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
+ * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
+ * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
+ * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
+ * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
+ * 
+ * US Government Users Restricted Rights 
+ * Use, duplication, or disclosure by the Government is subject to
+ * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+ * (c)(1)(ii) of the Rights in Technical Data and Computer Software
+ * clause at DFARS 252.227-7013 and/or in similar or successor
+ * clauses in the FAR or the DOD or NASA FAR Supplement.
+ * Unpublished-- rights reserved under the copyright laws of the
+ * United States.  Contractor/manufacturer is Silicon Graphics,
+ * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
+ *
+ * OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
+ */
+
+#include <GL/glut.h>
+#include <stdlib.h>
+
+static int leftFirst = GL_TRUE;
+
+static void init(void)
+{
+   glEnable(GL_DEPTH_TEST);
+   glClearColor (1.0, 0.0, 0.0, 0.0);
+}
+
+static void drawLeftTriangle(void)
+{
+   /* draw yellow triangle on LHS of screen */
+   glBegin (GL_TRIANGLES);
+      glColor4f(1.0, 1.0, 0.0, 0.75);
+      glVertex3f(0.1, 0.9, -1.0); 
+      glVertex3f(0.1, 0.1, -1.0); 
+      glVertex3f(0.8, 0.5,  1.0); 
+   glEnd();
+}
+
+static void drawRightTriangle(void)
+{
+   /* draw cyan triangle on RHS of screen */
+   glBegin (GL_TRIANGLES);
+      glColor4f(0.0, 1.0, 1.0, 0.75);
+      glVertex3f(0.9, 0.9, 0.0); 
+      glVertex3f(0.2, 0.5, 0.0); 
+      glVertex3f(0.9, 0.1, 0.0); 
+   glEnd();
+}
+
+void display(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   if (leftFirst) {
+      drawLeftTriangle();
+      drawRightTriangle();
+   }
+   else {
+      drawRightTriangle();
+      drawLeftTriangle();
+   }
+
+   glFlush();
+}
+
+void reshape(int w, int h)
+{
+   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   if (w <= h) 
+      gluOrtho2D (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w);
+   else 
+      gluOrtho2D (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0);
+}
+
+/* ARGSUSED1 */
+void keyboard(unsigned char key, int x, int y)
+{
+   switch (key) {
+      case 't':
+      case 'T':
+         leftFirst = !leftFirst;
+         glutPostRedisplay();  
+         break;
+      case 27:  /*  Escape key  */
+         exit(0);
+         break;
+      default:
+         break;
+   }
+}
+
+/*  Main Loop
+ *  Open window with initial window size, title bar, 
+ *  RGBA display mode, and handle input events.
+ */
+int main(int argc, char** argv)
+{
+   glutInit(&argc, argv);
+   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
+   glutInitWindowSize (200, 200);
+   glutCreateWindow (argv[0]);
+   init();
+   glutReshapeFunc (reshape);
+   glutKeyboardFunc (keyboard);
+   glutDisplayFunc (display);
+   glutMainLoop();
+   return 0;
+}
index 58a650b559fef8cd7343222099fa0d8b5f9d9f26..51395f0a418a641d45fec863e0438e6f32f088a7 100644 (file)
@@ -32,7 +32,7 @@
 #define CI_OFFSET_2 32
 
 
-GLenum doubleBuffer;
+GLenum doubleBuffer = 1;
 
 static void Init(void)
 {
@@ -40,7 +40,7 @@ static void Init(void)
    fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
    fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
 
-    glClearColor(0.0, 0.0, 1.0, 0.0);
+    glClearColor(0.3, 0.1, 0.3, 0.0);
 }
 
 static void Reshape(int width, int height)
@@ -91,8 +91,6 @@ static GLenum Args(int argc, char **argv)
 {
     GLint i;
 
-    doubleBuffer = GL_FALSE;
-
     for (i = 1; i < argc; i++) {
         if (strcmp(argv[i], "-sb") == 0) {
            doubleBuffer = GL_FALSE;
@@ -118,7 +116,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index fa82a737112ce73393c15c8ee2a5e8a6b0b3e49c..51ea4f23251818eab61a1eef94e2cdd20c6b7e67 100644 (file)
@@ -120,7 +120,7 @@ int main(int argc, char **argv)
 
     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
 
-    type = GLUT_RGB;
+    type = GLUT_RGB | GLUT_ALPHA;
     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
     glutInitDisplayMode(type);
 
index 6f2314ee8cb7ee6ed10727bc2d505d5e3b25093a..43c0e912bf25540f98cf79f094b1c0e81ebe1de2 100644 (file)
@@ -85,7 +85,7 @@ $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
 depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
        touch depend
        $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
-               $(ASM_SOURCES) 2>&1 /dev/null
+               $(ASM_SOURCES) 2> /dev/null
 
 
 # Emacs tags
index ad333b490b78ef4b808a6e36884fb8ab6aba2849..0e7ca9586e81be91b701a2e233ddb4d23c5de2cd 100644 (file)
@@ -464,6 +464,7 @@ i915_state_draw_region(struct intel_context *intel,
     * Set stride/cpp values
     */
    if (color_region) {
+//      fprintf(stderr, "color pitch %d\n", color_region->pitch);
       state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
       state->Buffer[I915_DESTREG_CBUFADDR1] =
          (BUF_3D_ID_COLOR_BACK |
@@ -472,6 +473,7 @@ i915_state_draw_region(struct intel_context *intel,
    }
 
    if (depth_region) {
+//      fprintf(stderr, "depth pitch %d\n", depth_region->pitch);
       state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
       state->Buffer[I915_DESTREG_DBUFADDR1] =
          (BUF_3D_ID_DEPTH |
index dbe4ba2ac5ef3e678d9401fbb9022b1db3a98cb7..c755eac6b2c43d5f8001e10d6752d3ef26c815b2 100644 (file)
@@ -79,15 +79,25 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
     */
    LOCK_HARDWARE(intel);
 
+      if (intel->revalidateDrawable) {
+        __DRIscreenPrivate *sPriv = intel->driScreen;
+        if (dPriv) {
+           DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+        }
+      }
+
    if (dPriv && dPriv->numClipRects) {
       struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
       const struct intel_region *frontRegion
-        = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT);
+        = intelScreen->front_region;
       const struct intel_region *backRegion
-        = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
+        = intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ?
+          intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) :
+          intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
       const int nbox = dPriv->numClipRects;
       const drm_clip_rect_t *pbox = dPriv->pClipRects;
       const int pitch = frontRegion->pitch;
+      const int srcpitch = backRegion->pitch;
       const int cpp = frontRegion->cpp;
       int BR13, CMD;
       int i;
@@ -96,9 +106,12 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
       ASSERT(intel_fb->Base.Name == 0);    /* Not a user-created FBO */
       ASSERT(frontRegion);
       ASSERT(backRegion);
-      ASSERT(frontRegion->pitch == backRegion->pitch);
+//      ASSERT(frontRegion->pitch == backRegion->pitch);
       ASSERT(frontRegion->cpp == backRegion->cpp);
 
+      DBG("front pitch %d back pitch %d\n",
+        frontRegion->pitch, backRegion->pitch);
+
       if (cpp == 2) {
         BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
         CMD = XY_SRC_COPY_BLT_CMD;
@@ -111,6 +124,7 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
 
       for (i = 0; i < nbox; i++, pbox++) {
         drm_clip_rect_t box;
+        drm_clip_rect_t sbox;
 
         if (pbox->x1 > pbox->x2 ||
             pbox->y1 > pbox->y2 ||
@@ -133,6 +147,14 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
               continue;
         }
 
+        DBG("box x1 x2 y1 y2 %d %d %d %d\n",
+             box.x1, box.x2, box.y1, box.y2);
+
+        /* XXX should make sure only the minimum area based on
+           old draw buffer and new front clip rects is copied */
+        sbox.x1 = box.x1 - dPriv->x;
+        sbox.y1 = box.y1 - dPriv->y;
+
         BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
         OUT_BATCH(CMD);
         OUT_BATCH(BR13);
@@ -141,8 +163,8 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
 
         OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
                   DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
-        OUT_BATCH((pbox->y1 << 16) | pbox->x1);
-        OUT_BATCH(BR13 & 0xffff);
+        OUT_BATCH((sbox.y1 << 16) | sbox.x1);
+        OUT_BATCH((srcpitch * cpp) & 0xffff);
         OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
                   DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
 
@@ -156,6 +178,12 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
    }
 
    UNLOCK_HARDWARE(intel);
+
+   if (intel->revalidateDrawable) {
+      intel->revalidateDrawable = GL_FALSE;
+      intelWindowMoved(intel);
+   }
+
 }
 
 
@@ -409,9 +437,8 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)
             b = *box;
          }
 
-         if (0)
-            _mesa_printf("clear %d,%d..%d,%d, mask %x\n",
-                         b.x1, b.y1, b.x2, b.y2, mask);
+         DBG("clear %d,%d..%d,%d, mask %x\n",
+                      b.x1, b.y1, b.x2, b.y2, mask);
 
          /* Loop over all renderbuffers */
          for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
index 15d02f8e2cf0771619309c5c6ab4b68ea9d4524c..17b4feadf854f1d4c84b41c2018d41c06a1afd9d 100644 (file)
@@ -146,57 +146,30 @@ intelSetRenderbufferClipRects(struct intel_context *intel)
    intel->drawY = 0;
 }
 
-
 /**
- * As above, but for rendering to front buffer of a window.
- * \sa intelSetRenderbufferClipRects
+ * As above, but for rendering private front/back buffer of a window.
+ * \sa intelSetPrivbufClipRects
  */
-static void
-intelSetFrontClipRects(struct intel_context *intel)
-{
-   __DRIdrawablePrivate *dPriv = intel->driDrawable;
-
-   if (!dPriv)
-      return;
-
-   intel->numClipRects = dPriv->numClipRects;
-   intel->pClipRects = dPriv->pClipRects;
-   intel->drawX = dPriv->x;
-   intel->drawY = dPriv->y;
-}
 
-
-/**
- * As above, but for rendering to back buffer of a window.
- */
 static void
-intelSetBackClipRects(struct intel_context *intel)
+intelSetPrivbufClipRects(struct intel_context *intel)
 {
    __DRIdrawablePrivate *dPriv = intel->driDrawable;
-   struct intel_framebuffer *intel_fb;
-
    if (!dPriv)
       return;
 
-   intel_fb = dPriv->driverPrivate;
-
-   if (intel_fb->pf_active || dPriv->numBackClipRects == 0) {
-      /* use the front clip rects */
-      intel->numClipRects = dPriv->numClipRects;
-      intel->pClipRects = dPriv->pClipRects;
-      intel->drawX = dPriv->x;
-      intel->drawY = dPriv->y;
-   }
-   else {
-      /* use the back clip rects */
-      intel->numClipRects = dPriv->numBackClipRects;
-      intel->pClipRects = dPriv->pBackClipRects;
-      intel->drawX = dPriv->backX;
-      intel->drawY = dPriv->backY;
-   }
+   intel->fakeClipRect.x1 = 0;
+   intel->fakeClipRect.y1 = 0;
+   intel->fakeClipRect.x2 = dPriv->w;
+   intel->fakeClipRect.y2 = dPriv->h;
+   intel->numClipRects = 1;
+   intel->pClipRects = &intel->fakeClipRect;
+   intel->drawX = 0;
+   intel->drawY = 0;
 }
 
 
+
 /**
  * This will be called whenever the currently bound window is moved/resized.
  * XXX: actually, it seems to NOT be called when the window is only moved (BP).
@@ -210,27 +183,10 @@ intelWindowMoved(struct intel_context *intel)
 
    if (!intel->ctx.DrawBuffer) {
       /* when would this happen? -BP */
-      intelSetFrontClipRects(intel);
-   }
-   else if (intel->ctx.DrawBuffer->Name != 0) {
-      /* drawing to user-created FBO - do nothing */
-      /* Cliprects would be set from intelDrawBuffer() */
-   }
-   else {
-      /* drawing to a window */
-      switch (intel_fb->Base._ColorDrawBufferMask[0]) {
-      case BUFFER_BIT_FRONT_LEFT:
-         intelSetFrontClipRects(intel);
-         break;
-      case BUFFER_BIT_BACK_LEFT:
-         intelSetBackClipRects(intel);
-         break;
-      default:
-         /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
-         intelSetFrontClipRects(intel);
-      }
+      intel->numClipRects = 0;
    }
 
+
    if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) {
       drmI830Sarea *sarea = intel->sarea;
       drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
@@ -482,6 +438,7 @@ void
 intelRotateWindow(struct intel_context *intel,
                   __DRIdrawablePrivate * dPriv, GLuint srcBuf)
 {
+
    intelScreenPrivate *screen = intel->intelScreen;
    drm_clip_rect_t fullRect;
    struct intel_framebuffer *intel_fb;
@@ -913,7 +870,7 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv)
         GLboolean missed_target;
         struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
         int64_t ust;
-         
+
         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
 
          if (screen->current_rotation != 0 ||
@@ -957,10 +914,17 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
 
       if (ctx->Visual.doubleBufferMode) {
          drm_clip_rect_t rect;
+#if 1
          rect.x1 = x + dPriv->x;
          rect.y1 = (dPriv->h - y - h) + dPriv->y;
          rect.x2 = rect.x1 + w;
          rect.y2 = rect.y1 + h;
+#else
+         rect.x1 = x;
+         rect.y1 = dPriv->h - y;
+         rect.x2 = rect.x1 + w;
+         rect.y2 = rect.y1 + h;
+#endif
          _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
          intelCopyBuffer(dPriv, &rect);
       }
@@ -995,7 +959,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
       return;
    }
 
-   /* Do this here, note core Mesa, since this function is called from
+   /* Do this here, not core Mesa, since this function is called from
     * many places within the driver.
     */
    if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
@@ -1019,12 +983,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
    /*
     * How many color buffers are we drawing into?
     */
-   if (fb->_NumColorDrawBuffers[0] != 1
-#if 0
-       /* XXX FBO temporary - always use software rendering */
-       || 1
-#endif
-      ) {
+   if (fb->_NumColorDrawBuffers[0] != 1) {
       /* writing to 0 or 2 or 4 color buffers */
       /*_mesa_debug(ctx, "Software rendering\n");*/
       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
@@ -1044,13 +1003,12 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
     * And set up cliprects.
     */
    if (fb->Name == 0) {
+      intelSetPrivbufClipRects(intel);
       /* drawing to window system buffer */
       if (front) {
-         intelSetFrontClipRects(intel);
          colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
       }
       else {
-         intelSetBackClipRects(intel);
          colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
       }
    }
index 40ea7564126712310578c6929d2fba98b9303f6e..61842da29d9827adc3a36804eef8bd0f6d821833 100644 (file)
 #include "intel_buffer_objects.h"
 #include "intel_fbo.h"
 
+#include "pipe/softpipe/sp_context.h"
+#include "state_tracker/st_public.h"
+
+
 #include "drirenderbuffer.h"
 #include "vblank.h"
 #include "utils.h"
@@ -256,6 +260,9 @@ intelInvalidateState(GLcontext * ctx, GLuint new_state)
    _vbo_InvalidateState(ctx, new_state);
    _tnl_InvalidateState(ctx, new_state);
    _tnl_invalidate_vertex_state(ctx, new_state);
+
+   st_invalidate_state( ctx, new_state );
+
    intel_context(ctx)->NewGLState |= new_state;
 }
 
@@ -282,18 +289,22 @@ intelFlush(GLcontext * ctx)
  * Check if we need to rotate/warp the front color buffer to the
  * rotated screen.  We generally need to do this when we get a glFlush
  * or glFinish after drawing to the front color buffer.
+ * If no rotation, just copy the private fake front buffer to the real one.
  */
 static void
-intelCheckFrontRotate(GLcontext * ctx)
+intelCheckFrontUpdate(GLcontext * ctx)
 {
    struct intel_context *intel = intel_context(ctx);
    if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] ==
        BUFFER_BIT_FRONT_LEFT) {
       intelScreenPrivate *screen = intel->intelScreen;
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
       if (screen->current_rotation != 0) {
-         __DRIdrawablePrivate *dPriv = intel->driDrawable;
          intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
       }
+      else {
+         intelCopyBuffer(dPriv, NULL);
+      }
    }
 }
 
@@ -305,7 +316,7 @@ static void
 intelglFlush(GLcontext * ctx)
 {
    intelFlush(ctx);
-   intelCheckFrontRotate(ctx);
+   intelCheckFrontUpdate(ctx);
 }
 
 void
@@ -319,7 +330,7 @@ intelFinish(GLcontext * ctx)
       driFenceUnReference(intel->batch->last_fence);
       intel->batch->last_fence = NULL;
    }
-   intelCheckFrontRotate(ctx);
+   intelCheckFrontUpdate(ctx);
 }
 
 
@@ -505,6 +516,11 @@ intelInitContext(struct intel_context *intel,
       FALLBACK(intel, INTEL_FALLBACK_USER, 1);
    }
 
+
+   st_create_context( &intel->ctx,
+                     softpipe_create() );
+   
+
    return GL_TRUE;
 }
 
@@ -569,6 +585,13 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
                  __DRIdrawablePrivate * driReadPriv)
 {
 
+#if 0
+   if (driDrawPriv) {
+      fprintf(stderr, "x %d, y %d, width %d, height %d\n",
+             driDrawPriv->x, driDrawPriv->y, driDrawPriv->w, driDrawPriv->h);
+   }
+#endif
+
    if (driContextPriv) {
       struct intel_context *intel =
          (struct intel_context *) driContextPriv->driverPrivate;
@@ -576,6 +599,9 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
         (struct intel_framebuffer *) driDrawPriv->driverPrivate;
       GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate;
 
+      /* this is a hack so we have a valid context when the region allocation
+         is done. Need a per-screen context? */
+      intel->intelScreen->dummyctxptr = intel;
 
       /* XXX FBO temporary fix-ups! */
       /* if the renderbuffers don't have regions, init them from the context */
@@ -613,6 +639,7 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
       }
 
       _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb);
+      intel->intelScreen->dummyctxptr = &intel->ctx;
 
       /* The drawbuffer won't always be updated by _mesa_make_current: 
        */
@@ -669,7 +696,8 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
     * checking must be done *after* this call:
     */
    if (dPriv)
-      DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+      intel->revalidateDrawable = GL_TRUE;
+//      DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
 
    if (sarea->width != intelScreen->width ||
        sarea->height != intelScreen->height ||
@@ -678,6 +706,7 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
       intelUpdateScreenRotation(sPriv, sarea);
    }
 
+#if 0
    if (sarea->width != intel->width ||
        sarea->height != intel->height ||
        sarea->rotation != intel->current_rotation) {
@@ -710,13 +739,7 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
       intel->height = sarea->height;
       intel->current_rotation = sarea->rotation;
    }
-
-   /* Drawable changed?
-    */
-   if (dPriv && intel->lastStamp != dPriv->lastStamp) {
-      intelWindowMoved(intel);
-      intel->lastStamp = dPriv->lastStamp;
-   }
+#endif
 }
 
 
index 9d060eb866f7e70be411f13626ba6b790e268294..7b97c564a3eddf12a8f4c67126cbe41036e01c33 100644 (file)
@@ -254,6 +254,7 @@ struct intel_context
    GLuint numClipRects;         /**< cliprects for drawing */
    drm_clip_rect_t *pClipRects;
    drm_clip_rect_t fboRect;     /**< cliprect for FBO rendering */
+   drm_clip_rect_t fakeClipRect;     /**< cliprect for priv back/fake front buffers rendering */
 
    int perf_boxes;
 
@@ -272,6 +273,7 @@ struct intel_context
    drmI830Sarea *sarea;
 
    GLuint lastStamp;
+   GLuint revalidateDrawable;
 
    /**
     * Configuration cache
@@ -353,7 +355,7 @@ __memcpy(void *to, const void *from, size_t n)
 /* ================================================================
  * Debugging:
  */
-#define DO_DEBUG               0
+#define DO_DEBUG               1
 #if DO_DEBUG
 extern int INTEL_DEBUG;
 #else
index 6f99f401c7cb9476986f9fafa305f69f33706408..a09db46163d51dc36bde5dc2aa648a81a21480a2 100644 (file)
@@ -176,7 +176,7 @@ intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
 
 /**
  * Called via glRenderbufferStorageEXT() to set the format and allocate
- * storage for a user-created renderbuffer.
+ * storage for a user-created (or priv buffer) renderbuffer.
  */
 static GLboolean
 intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
@@ -188,8 +188,6 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
    GLboolean softwareBuffer = GL_FALSE;
    int cpp;
 
-   ASSERT(rb->Name != 0);
-
    switch (internalFormat) {
    case GL_R3_G3_B2:
    case GL_RGB4:
@@ -257,7 +255,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
       break;
    default:
       _mesa_problem(ctx,
-                    "Unexpected format in intel_alloc_renderbuffer_storage");
+                    "Unexpected format (%x) in intel_alloc_renderbuffer_storage", internalFormat);
       return GL_FALSE;
    }
 
@@ -453,6 +451,29 @@ intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
    return irb;
 }
 
+struct gl_renderbuffer *
+intel_new_renderbuffer_fb(GLcontext * ctx, GLuint intFormat)
+{
+   struct intel_renderbuffer *irb;
+
+   irb = CALLOC_STRUCT(intel_renderbuffer);
+   if (!irb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
+      return NULL;
+   }
+
+   _mesa_init_renderbuffer(&irb->Base, 0);
+   irb->Base.ClassID = INTEL_RB_CLASS;
+   irb->Base.InternalFormat = intFormat;
+
+   /* intel-specific methods */
+   irb->Base.Delete = intel_delete_renderbuffer;
+   irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
+   irb->Base.GetPointer = intel_get_pointer;
+   /* span routines set in alloc_storage function */
+
+   return &irb->Base;
+}
 
 /**
  * Create a new renderbuffer object.
index 2acdead63d5d02207c820a2499add5b1e3d0a559..08057a6600623095626fe694c92e60d775af144a 100644 (file)
@@ -88,6 +88,7 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv)
       _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
    }
 
+#if 0
    if (0)
       _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
    if (drmMap(sPriv->fd,
@@ -119,6 +120,7 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv)
       intelUnmapScreenRegions(intelScreen);
       return GL_FALSE;
    }
+#endif
 
 #if 0
    _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
@@ -156,7 +158,7 @@ intel_recreate_static(intelScreenPrivate *intelScreen,
   }
   return region;
 }
-    
+
 
 /* Create intel_region structs to describe the static front,back,depth
  * buffers created by the xserver. 
@@ -172,6 +174,7 @@ intel_recreate_static(intelScreenPrivate *intelScreen,
 static void
 intel_recreate_static_regions(intelScreenPrivate *intelScreen)
 {
+/* this is the real front buffer which is only used for blitting to */
    intelScreen->front_region =
       intel_recreate_static(intelScreen,
                            intelScreen->front_region,
@@ -192,7 +195,7 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen)
                            intelScreen->rotated.pitch /
                            intelScreen->cpp, intelScreen->height);
 
-
+#if 0
    intelScreen->back_region =
       intel_recreate_static(intelScreen,
                            intelScreen->back_region,
@@ -226,6 +229,7 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen)
                            intelScreen->cpp,
                            intelScreen->depth.pitch / intelScreen->cpp,
                            intelScreen->height);
+#endif
 }
 
 /**
@@ -382,7 +386,7 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
    intelScreen->rotatedWidth = sarea->virtualX;
    intelScreen->rotatedHeight = sarea->virtualY;
 
-   if (0)
+   if (1)
       intelPrintSAREA(sarea);
 }
 
@@ -600,6 +604,7 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
 
       _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);
 
+#if 0
       /* setup the hardware-based renderbuffers */
       {
          intel_fb->color_rb[0]
@@ -640,7 +645,6 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
            _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
         }
       }
-
       if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
          /* combined depth/stencil buffer */
          struct intel_renderbuffer *depthStencilRb
@@ -670,6 +674,50 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
          _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
       }
 
+#else
+      {
+        /* fake frontbuffer */
+        /* XXX allocation should only happen in the unusual case
+            it's actually needed */
+         intel_fb->color_rb[0]
+            = intel_new_renderbuffer_fb(NULL, rgbFormat);
+         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
+                               &intel_fb->color_rb[0]->Base);
+      }
+
+      if (mesaVis->doubleBufferMode) {
+         intel_fb->color_rb[1]
+            = intel_new_renderbuffer_fb(NULL, rgbFormat);
+         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
+                               &intel_fb->color_rb[1]->Base);
+
+        if (screen->third.handle) {
+           struct gl_renderbuffer *tmp_rb = NULL;
+
+           intel_fb->color_rb[2]
+              = intel_new_renderbuffer_fb(NULL, rgbFormat);
+           _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base);
+        }
+      }
+      if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
+         /* combined depth/stencil buffer */
+         struct intel_renderbuffer *depthStencilRb
+            = intel_new_renderbuffer_fb(NULL, GL_DEPTH24_STENCIL8_EXT);
+         /* note: bind RB to two attachment points */
+         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH,
+                               &depthStencilRb->Base);
+         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL,
+                               &depthStencilRb->Base);
+      }
+      else if (mesaVis->depthBits == 16) {
+         /* just 16-bit depth buffer, no hw stencil */
+         struct intel_renderbuffer *depthRb
+            = intel_new_renderbuffer_fb(NULL, GL_DEPTH_COMPONENT16);
+         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);
+      }
+
+#endif
+
       /* now add any/all software-based renderbuffers we may need */
       _mesa_add_soft_renderbuffers(&intel_fb->Base,
                                    GL_FALSE, /* never sw color */
@@ -939,11 +987,18 @@ struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
    * context at screen creation. For now just use the current context.
    */
 
-  GET_CURRENT_CONTEXT(ctx);
+/*  GET_CURRENT_CONTEXT(ctx);
   if (ctx == NULL) {
      _mesa_problem(NULL, "No current context in intelScreenContext\n");
      return NULL;
   }
   return intel_context(ctx);
+*/
+  if (intelScreen->dummyctxptr == NULL) {
+     _mesa_problem(NULL, "No current context in intelScreenContext\n");
+     return NULL;
+  }
+  return intelScreen->dummyctxptr;
+
 }
 
index bac43aadddf0015096d6100f72b5f0f88acf1b16..783ee35524bdc48e133f72c18f51067a2aa7f066 100644 (file)
@@ -96,6 +96,7 @@ typedef struct
    struct _DriBufferPool *staticPool;
    unsigned int maxBatchSize;
    GLboolean havePools;
+   struct intel_context *dummyctxptr;
 } intelScreenPrivate;
 
 
index 271511037e975e75a053aaade24aef2050ddeb57..b2773990e4b15d7240c56e874a1f3abd0b6d1511 100644 (file)
@@ -205,25 +205,17 @@ intelCalcViewport(GLcontext * ctx)
    GLfloat *m = intel->ViewportMatrix.m;
    GLfloat yScale, yBias;
 
-   if (ctx->DrawBuffer->Name) {
-      /* User created FBO */
-      struct intel_renderbuffer *irb
+   struct intel_renderbuffer *irb
          = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
-      if (irb && !irb->RenderToTexture) {
-         /* y=0=top */
-         yScale = -1.0;
-         yBias = irb->Base.Height;
-      }
-      else {
-         /* y=0=bottom */
-         yScale = 1.0;
-         yBias = 0.0;
-      }
+   if (irb && !irb->RenderToTexture) {
+      /* y=0=top */
+      yScale = -1.0;
+      yBias = irb->Base.Height;
    }
    else {
-      /* window buffer, y=0=top */
-      yScale = -1.0;
-      yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
+      /* y=0=bottom */
+      yScale = 1.0;
+      yBias = 0.0;
    }
 
    m[MAT_SX] = v[MAT_SX];
diff --git a/src/mesa/drivers/x11/Makefile b/src/mesa/drivers/x11/Makefile
new file mode 100644 (file)
index 0000000..0ab1dc6
--- /dev/null
@@ -0,0 +1,2 @@
+default:
+       cd ../.. ; make
\ No newline at end of file
index eaa277db4ad1c7e1f289d42d368fc50ae86c251c..f20e8104fb3930c0b9e4d70dfb68f6df0a91707a 100644 (file)
@@ -81,6 +81,9 @@
 #include "tnl/t_pipeline.h"
 #include "drivers/common/driverfuncs.h"
 
+#include "state_tracker/st_public.h"
+#include "pipe/softpipe/sp_context.h"
+
 /**
  * Global X driver lock
  */
@@ -1566,6 +1569,10 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
    xmesa_register_swrast_functions( mesaCtx );
    _swsetup_Wakeup(mesaCtx);
 
+
+   st_create_context( mesaCtx,
+                     softpipe_create() );
+   
    return c;
 }
 
index c8546236fbf3644b222a96e16149e7ddab152265..57254148561a6950ae880d3a395825315139f83a 100644 (file)
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 
+#include "pipe/softpipe/sp_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_draw.h"
 
 
 /*
@@ -391,6 +395,7 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers)
 
       /* we can't handle color or index masking */
       if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+#if 0
          if (buffers & BUFFER_BIT_FRONT_LEFT) {
             /* clear front color buffer */
             struct gl_renderbuffer *frontRb
@@ -414,6 +419,15 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers)
                buffers &= ~BUFFER_BIT_BACK_LEFT;
             }
          }
+#else
+         /* Clear with state-tracker/pipe interface */
+         struct st_context *st = st_context(ctx);
+         GLboolean color = (buffers & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) ? 1: 0;
+         GLboolean depth = (buffers & BUFFER_BIT_DEPTH) ? 1 : 0;
+         GLboolean stencil = (buffers & BUFFER_BIT_STENCIL) ? 1 : 0;
+         GLboolean accum = (buffers & BUFFER_BIT_ACCUM) ? 1 : 0;
+         st_clear(st, color, depth, stencil, accum);
+#endif
       }
    }
    if (buffers)
@@ -828,6 +842,9 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state )
    _vbo_InvalidateState( ctx, new_state );
    _swsetup_InvalidateState( ctx, new_state );
 
+   st_invalidate_state( ctx, new_state );
+
+
    if (ctx->DrawBuffer->Name != 0)
       return;
 
index a24966b3aeb41ec5f4d645f349855b2ccfaad751..3776891e2eca5c7d44ac50d80c18f1e1fffd0280 100644 (file)
@@ -1303,6 +1303,17 @@ static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS )
 }
 
 
+
+static void *get_pointer_4_ximage( GLcontext *ctx, 
+                                  struct gl_renderbuffer *rb, 
+                                  GLint x, GLint y )
+{
+   GET_XRB(xrb);
+   return PIXEL_ADDR4(xrb, x, y);
+}
+
+
+
 /*
  * Write a span of PF_8A8B8G8R-format pixels to an ximage.
  */
@@ -4593,6 +4604,7 @@ xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb,
          xrb->Base.PutMonoRow    = put_mono_row_8A8B8G8R_ximage;
          xrb->Base.PutValues     = put_values_8A8B8G8R_ximage;
          xrb->Base.PutMonoValues = put_mono_values_8A8B8G8R_ximage;
+        xrb->Base.GetPointer    = get_pointer_4_ximage;
       }
       break;
    case PF_8A8R8G8B:
@@ -4609,6 +4621,7 @@ xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb,
          xrb->Base.PutMonoRow    = put_mono_row_8A8R8G8B_ximage;
          xrb->Base.PutValues     = put_values_8A8R8G8B_ximage;
          xrb->Base.PutMonoValues = put_mono_values_8A8R8G8B_ximage;
+        xrb->Base.GetPointer    = get_pointer_4_ximage;
       }
       break;
    case PF_8R8G8B:
diff --git a/src/mesa/drivers/x11/xm_surface.c b/src/mesa/drivers/x11/xm_surface.c
new file mode 100644 (file)
index 0000000..58081a3
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.1
+ *
+ * Copyright (C) 1999-2007  Brian Paul   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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL 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 xm_surface.h
+ * Code to allow the softpipe code to write to X windows/buffers.
+ * This is a bit of a hack for now.  We've basically got two different
+ * abstractions for color buffers: gl_renderbuffer and softpipe_surface.
+ * They'll need to get merged someday...
+ * For now, they're separate things that point to each other.
+ */
+
+
+#include "glxheader.h"
+#include "GL/xmesa.h"
+#include "xmesaP.h"
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/softpipe/sp_context.h"
+#include "pipe/softpipe/sp_surface.h"
+
+
+/**
+ * An xm_surface is derived from a softpipe_surface
+ */
+struct xmesa_surface
+{
+   struct softpipe_surface sps;
+   struct xmesa_renderbuffer *xrb;  /** ptr back to matching xmesa_renderbuffer */
+   struct gl_renderbuffer *rb; /* ptr to matching gl_renderbuffer */
+};
+
+
+/**
+ * Cast wrapper
+ */
+static INLINE struct xmesa_surface *
+xmesa_surface(struct softpipe_surface *sps)
+{
+   return (struct xmesa_surface *) sps;
+}
+
+
+/**
+ * quad reading/writing
+ * These functions are just wrappers around the existing renderbuffer
+ * functions.
+ */
+
+static void
+read_quad_f(struct softpipe_surface *gs, GLint x, GLint y,
+            GLfloat (*rgba)[NUM_CHANNELS])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GLubyte temp[16];
+   GLfloat *dst = (GLfloat *) rgba;
+   GLuint i;
+   GET_CURRENT_CONTEXT(ctx);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y,     temp);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8);
+   for (i = 0; i < 16; i++) {
+      dst[i] = UBYTE_TO_FLOAT(temp[i]);
+   }
+}
+
+static void
+read_quad_f_swz(struct softpipe_surface *gs, GLint x, GLint y,
+                GLfloat (*rrrr)[QUAD_SIZE])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GLubyte temp[16];
+   GLfloat *dst = (GLfloat *) rrrr;
+   GLuint i, j;
+   GET_CURRENT_CONTEXT(ctx);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y,     temp);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8);
+   for (i = 0; i < 4; i++) {
+      for (j = 0; j < 4; j++) {
+         dst[j * 4 + i] = UBYTE_TO_FLOAT(temp[i * 4 + j]);
+      }
+   }
+}
+
+static void
+write_quad_f(struct softpipe_surface *gs, GLint x, GLint y,
+             GLfloat (*rgba)[NUM_CHANNELS])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GLubyte temp[16];
+   const GLfloat *src = (const GLfloat *) rgba;
+   GLuint i;
+   GET_CURRENT_CONTEXT(ctx);
+   for (i = 0; i < 16; i++) {
+      UNCLAMPED_FLOAT_TO_UBYTE(temp[i], src[i]);
+   }
+   xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y,     temp,     NULL);
+   xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8, NULL);
+}
+
+static void
+write_quad_f_swz(struct softpipe_surface *gs, GLint x, GLint y,
+                 GLfloat (*rrrr)[QUAD_SIZE])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GLubyte temp[16];
+   const GLfloat *src = (const GLfloat *) rrrr;
+   GLuint i, j;
+   GET_CURRENT_CONTEXT(ctx);
+   for (i = 0; i < 4; i++) {
+      for (j = 0; j < 4; j++) {
+         UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + i], src[i * 4 + j]);
+      }
+   }
+   xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y,     temp,     NULL);
+   xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8, NULL);
+}
+
+static void
+read_quad_ub(struct softpipe_surface *gs, GLint x, GLint y,
+             GLubyte (*rgba)[NUM_CHANNELS])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GET_CURRENT_CONTEXT(ctx);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y,     rgba);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, rgba + 2);
+}
+
+static void
+write_quad_ub(struct softpipe_surface *gs, GLint x, GLint y,
+              GLubyte (*rgba)[NUM_CHANNELS])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GET_CURRENT_CONTEXT(ctx);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y,     rgba);
+   xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, rgba + 2);
+}
+
+static void
+write_mono_row_ub(struct softpipe_surface *gs, GLuint count, GLint x, GLint y,
+                  GLubyte rgba[NUM_CHANNELS])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(gs);
+   struct xmesa_renderbuffer *xrb = xmsurf->xrb;
+   GET_CURRENT_CONTEXT(ctx);
+   xrb->Base.PutMonoRow(ctx, &xrb->Base, count, x, y, rgba, NULL);
+}
+
+
+static struct xmesa_surface *
+create_surface(XMesaContext xmctx, struct xmesa_renderbuffer *xrb)
+{
+   struct xmesa_surface *xmsurf;
+
+   xmsurf = CALLOC_STRUCT(xmesa_surface);
+   if (xmsurf) {
+      xmsurf->xrb = xrb;
+      xmsurf->sps.surface.width = xrb->Base.Width;
+      xmsurf->sps.surface.height = xrb->Base.Height;
+
+      xmsurf->sps.read_quad_f = read_quad_f;
+      xmsurf->sps.read_quad_f_swz = read_quad_f_swz;
+      xmsurf->sps.read_quad_ub = read_quad_ub;
+      xmsurf->sps.write_quad_f = write_quad_f;
+      xmsurf->sps.write_quad_f_swz = write_quad_f_swz;
+      xmsurf->sps.write_quad_ub = write_quad_ub;
+      xmsurf->sps.write_mono_row_ub = write_mono_row_ub;
+
+#if 0
+      if (xrb->ximage) {
+         xmsurf->sps.surface.ptr = (GLubyte *) xrb->ximage->data;
+         xmsurf->sps.surface.stride = xrb->ximage->bytes_per_line;
+         xmsurf->sps.surface.cpp = xrb->ximage->depth;
+
+      }
+#endif
+   }
+   return xmsurf;
+}
+
+
+static void
+free_surface(struct softpipe_surface *sps)
+{
+   /* XXX may need to do more in the future */
+   free(sps);
+}
+
+
+/**
+ * Return generic surface pointer corresponding to the current color buffer.
+ */
+struct pipe_surface *
+xmesa_get_color_surface(GLcontext *ctx, GLuint buf)
+{
+   XMesaContext xmctx = XMESA_CONTEXT(ctx);
+   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][buf];   
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
+   struct softpipe_surface *sps = (struct softpipe_surface *) xrb->pSurface;
+
+   if (!sps) {
+      xrb->pSurface = create_surface(xmctx, xrb);
+   }
+   else if (sps->surface.width != rb->Width ||
+            sps->surface.height != rb->Height) {
+      free_surface(sps);
+      xrb->pSurface = create_surface(xmctx, xrb);
+   }
+
+   return (struct pipe_surface *) xrb->pSurface;
+}
+
+
+
+
+static void
+read_quad_z(struct softpipe_surface *sps,
+            GLint x, GLint y, GLuint zzzz[QUAD_SIZE])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(sps);
+   struct gl_renderbuffer *rb = xmsurf->rb;
+   GLushort temp[4];
+   GLuint i;
+   GET_CURRENT_CONTEXT(ctx);
+   rb->GetRow(ctx, rb, 2, x, y,     temp);
+   rb->GetRow(ctx, rb, 2, x, y + 1, temp + 2);
+   /* convert from GLushort to GLuint */
+   for (i = 0; i < 4; i++) {
+      zzzz[i] = temp[i];
+   }
+}
+
+static void
+write_quad_z(struct softpipe_surface *sps,
+             GLint x, GLint y, const GLuint zzzz[QUAD_SIZE])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(sps);
+   struct gl_renderbuffer *rb = xmsurf->rb;
+   GLushort temp[4];
+   GLuint i;
+   GET_CURRENT_CONTEXT(ctx);
+   /* convert from GLuint to GLushort */
+   for (i = 0; i < 4; i++) {
+      temp[i] = zzzz[i];
+   }
+   rb->PutRow(ctx, rb, 2, x, y,     temp,     NULL);
+   rb->PutRow(ctx, rb, 2, x, y + 1, temp + 2, NULL);
+}
+
+
+static struct xmesa_surface *
+create_z_surface(XMesaContext xmctx, struct gl_renderbuffer *rb)
+{
+   struct xmesa_surface *xmsurf;
+
+   xmsurf = CALLOC_STRUCT(xmesa_surface);
+   if (xmsurf) {
+      xmsurf->sps.surface.format = PIPE_FORMAT_U_Z16;
+      xmsurf->sps.surface.width = rb->Width;
+      xmsurf->sps.surface.height = rb->Height;
+      xmsurf->sps.read_quad_z = read_quad_z;
+      xmsurf->sps.write_quad_z = write_quad_z;
+      xmsurf->rb = rb;
+   }
+   return xmsurf;
+}
+
+
+
+
+static void
+read_quad_stencil(struct softpipe_surface *sps,
+                  GLint x, GLint y, GLubyte ssss[QUAD_SIZE])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(sps);
+   struct gl_renderbuffer *rb = xmsurf->rb;
+   GET_CURRENT_CONTEXT(ctx);
+   rb->GetRow(ctx, rb, 2, x, y,     ssss);
+   rb->GetRow(ctx, rb, 2, x, y + 1, ssss + 2);
+}
+
+static void
+write_quad_stencil(struct softpipe_surface *sps,
+                   GLint x, GLint y, const GLubyte ssss[QUAD_SIZE])
+{
+   struct xmesa_surface *xmsurf = xmesa_surface(sps);
+   struct gl_renderbuffer *rb = xmsurf->rb;
+   GET_CURRENT_CONTEXT(ctx);
+   rb->PutRow(ctx, rb, 2, x, y,     ssss,     NULL);
+   rb->PutRow(ctx, rb, 2, x, y + 1, ssss + 2, NULL);
+}
+
+static struct xmesa_surface *
+create_stencil_surface(XMesaContext xmctx, struct gl_renderbuffer *rb)
+{
+   struct xmesa_surface *xmsurf;
+
+   xmsurf = CALLOC_STRUCT(xmesa_surface);
+   if (xmsurf) {
+      xmsurf->sps.surface.format = PIPE_FORMAT_U_S8;
+      xmsurf->sps.surface.width = rb->Width;
+      xmsurf->sps.surface.height = rb->Height;
+      xmsurf->sps.read_quad_stencil = read_quad_stencil;
+      xmsurf->sps.write_quad_stencil = write_quad_stencil;
+      xmsurf->rb = rb;
+   }
+   return xmsurf;
+}
+
+
+
+
+/**
+ * Return a pipe_surface that wraps the current Z/depth buffer.
+ * XXX this is pretty much a total hack until gl_renderbuffers and
+ * pipe_surfaces are merged...
+ */
+struct pipe_surface *
+xmesa_get_z_surface(GLcontext *ctx)
+{
+   XMesaContext xmctx = XMESA_CONTEXT(ctx);
+   struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
+   static struct xmesa_surface *xms = NULL;
+
+   if (!rb)
+      return NULL;
+
+   if (!xms) {
+      xms = create_z_surface(xmctx, rb);
+   }
+   else if (xms->sps.surface.width != rb->Width ||
+            xms->sps.surface.height != rb->Height) {
+      free_surface(&xms->sps);
+      xms = create_z_surface(xmctx, rb);
+   }
+
+   return (struct pipe_surface *) &xms->sps.surface;
+}
+
+
+struct pipe_surface *
+xmesa_get_stencil_surface(GLcontext *ctx)
+{
+   XMesaContext xmctx = XMESA_CONTEXT(ctx);
+   struct gl_renderbuffer *rb = ctx->DrawBuffer->_StencilBuffer;
+   static struct xmesa_surface *xms = NULL;
+
+   if (!rb)
+      return NULL;
+
+   if (!xms) {
+      xms = create_stencil_surface(xmctx, rb);
+   }
+   else if (xms->sps.surface.width != rb->Width ||
+            xms->sps.surface.height != rb->Height) {
+      free_surface(&xms->sps);
+      xms = create_stencil_surface(xmctx, rb);
+   }
+
+   return (struct pipe_surface *) &xms->sps.surface;
+}
+
index 95c6d7c1d20a80faa234d4d2f64485c953771001..9f17083f90124d972072053cbea9dc5dfa371e4b 100644 (file)
@@ -1443,6 +1443,46 @@ do {                                   \
 #endif
 
 
+#if 0
+GLboolean xmesa_get_cbuf_details( GLcontext *ctx,
+                                 void **ptr,
+                                 GLuint *cpp,
+                                 GLint *stride,
+                                 GLuint *format )
+{
+   XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+   struct gl_renderbuffer *crb = fb->_ColorDrawBuffers[0][0];
+   struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(crb->Wrapped);
+
+   *ptr = crb->GetPointer(ctx, crb, 0, 0);
+   *stride = ((GLubyte *)crb->GetPointer(ctx, crb, 0, 1) - 
+             (GLubyte *)crb->GetPointer(ctx, crb, 0, 0));
+
+   if (!ptr) 
+      goto bad;
+
+   switch (xmesa->pixelformat) {
+   case PF_8A8B8G8R:
+   case PF_8A8R8G8B:
+      *format = 1;             /* whatever */
+      *cpp = 4;
+      break;
+   default:
+      goto bad;
+   }
+
+   return GL_TRUE;
+
+ bad:
+   *ptr = NULL;
+   *stride = 0;
+   *format = 0;
+   return GL_FALSE;   
+}
+#endif
+
+
 /**
  * Return pointer to line drawing function, or NULL if we should use a
  * swrast fallback.
index e3d7cf381f7c52d2d43faa955ca8ac30df10099e..8648b19939982c753f0b9a2ee035aa847dbcbeba 100644 (file)
@@ -196,6 +196,8 @@ struct xmesa_renderbuffer
    GLint bottom;       /* used for FLIP macro, equals height - 1 */
 
    ClearFunc clearFunc;
+
+   void *pSurface;      /** pipe surface */
 };
 
 
@@ -583,4 +585,23 @@ extern void xmesa_register_swrast_functions( GLcontext *ctx );
 #define ENABLE_EXT_timer_query 0 /* may not have 64-bit GLuint64EXT */
 #endif
 
+#if 0
+GLboolean xmesa_get_cbuf_details( GLcontext *ctx,
+                                 void **ptr,
+                                 GLuint *cpp,
+                                 GLint *stride,
+                                 GLuint *format );
+#endif
+
+struct pipe_surface;
+struct pipe_surface *
+xmesa_get_color_surface(GLcontext *ctx, GLuint buf);
+
+struct pipe_surface *
+xmesa_get_z_surface(GLcontext *ctx);
+
+struct pipe_surface *
+xmesa_get_stencil_surface(GLcontext *ctx);
+
+
 #endif
index 3e4c49249a001e4fe816171fac88e32818fb0b6e..52448ee04eb6b81754cd243c8ad60b6eacb9439b 100644 (file)
@@ -126,6 +126,7 @@ struct gl_pixelstore_attrib;
 struct gl_texture_format;
 struct gl_texture_image;
 struct gl_texture_object;
+struct st_context;
 typedef struct __GLcontextRec GLcontext;
 typedef struct __GLcontextModesRec GLvisual;
 typedef struct gl_framebuffer GLframebuffer;
@@ -3102,7 +3103,7 @@ struct __GLcontextRec
    void *swsetup_context;
    void *swtnl_context;
    void *swtnl_im;
-   void *acache_context;
+   struct st_context *st;
    void *aelt_context;
    /*@}*/
 };
index 0e59ba615a783bd597f1ffe49d78efa616d5b9c4..fc04dde3f49a2ccf1544f697365be3ea303634f0 100644 (file)
 #include "queryobj.h"
 #include "mtypes.h"
 
+#if 1 /*PIPE*/
+#include "pipe/p_context.h"
+#include "state_tracker/st_context.h"
+#endif
+
 
 /**
  * Allocate a new query object.  This is a fallback routine called via
@@ -220,6 +225,10 @@ _mesa_BeginQueryARB(GLenum target, GLuint id)
    q->Result = 0;
    q->Ready = GL_FALSE;
 
+#if 1 /*PIPE*/
+   ctx->st->pipe->reset_occlusion_counter(ctx->st->pipe);
+#endif
+
    if (target == GL_SAMPLES_PASSED_ARB) {
       ctx->Query.CurrentOcclusionObject = q;
    }
@@ -282,6 +291,12 @@ _mesa_EndQueryARB(GLenum target)
       /* if we're using software rendering/querying */
       q->Ready = GL_TRUE;
    }
+
+#if 1 /*PIPE*/
+   if (target == GL_SAMPLES_PASSED_ARB) {
+      q->Result = ctx->st->pipe->get_occlusion_counter(ctx->st->pipe);
+   }
+#endif
 }
 
 
diff --git a/src/mesa/pipe/Makefile b/src/mesa/pipe/Makefile
new file mode 100644 (file)
index 0000000..451911a
--- /dev/null
@@ -0,0 +1,2 @@
+default:
+       cd .. ; make
diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c
new file mode 100644 (file)
index 0000000..f8bacf8
--- /dev/null
@@ -0,0 +1,463 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  Clipping stage
+ *
+ * \author  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/macros.h"
+#include "draw_private.h"
+
+
+struct clipper {
+   struct draw_stage stage;      /**< base class */
+
+   GLuint active_user_planes;
+   GLfloat (*plane)[4];
+};
+
+
+/* This is a bit confusing:
+ */
+static INLINE struct clipper *clipper_stage( struct draw_stage *stage )
+{
+   return (struct clipper *)stage;
+}
+
+
+#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT)))
+
+
+/* All attributes are float[4], so this is easy:
+ */
+static void interp_attr( GLfloat *fdst,
+                        GLfloat t,
+                        const GLfloat *fin,
+                        const GLfloat *fout )
+{  
+   fdst[0] = LINTERP( t, fout[0], fin[0] );
+   fdst[1] = LINTERP( t, fout[1], fin[1] );
+   fdst[2] = LINTERP( t, fout[2], fin[2] );
+   fdst[3] = LINTERP( t, fout[3], fin[3] );
+}
+
+
+
+
+/* Interpolate between two vertices to produce a third.  
+ */
+static void interp( const struct clipper *clip,
+                   struct vertex_header *dst,
+                   GLfloat t,
+                   const struct vertex_header *out, 
+                   const struct vertex_header *in )
+{
+   const GLuint nr_attrs = clip->stage.draw->nr_attrs;
+   GLuint j;
+
+   /* Vertex header.
+    */
+   {
+      dst->clipmask = 0;
+      dst->edgeflag = 0;
+      dst->pad = 0;
+   }
+
+   /* Clip coordinates:  interpolate normally
+    */
+   {
+      interp_attr(dst->clip, t, in->clip, out->clip);
+   }
+
+   /* Do the projective divide and insert window coordinates:
+    */
+   {
+      const GLfloat *pos = dst->clip;
+      const GLfloat *scale = clip->stage.draw->viewport.scale;
+      const GLfloat *trans = clip->stage.draw->viewport.translate;
+      const GLfloat oow = 1.0 / pos[3];
+
+      dst->data[0][0] = pos[0] * oow * scale[0] + trans[0];
+      dst->data[0][1] = pos[1] * oow * scale[1] + trans[1];
+      dst->data[0][2] = pos[2] * oow * scale[2] + trans[2];
+      dst->data[0][3] = oow;
+   }
+
+   /* Other attributes
+    * Note: start at 1 to skip winpos (data[0]) since we just computed
+    * it above.
+    * Subtract two from nr_attrs since the first two attribs (always 
+    * VF_ATTRIB_VERTEX_HEADER and VF_ATTRIB_CLIP_POS, see
+    * draw_set_vertex_attributes()) are in the vertex_header struct,
+    * not in the data[] array.
+    */
+   for (j = 1; j < nr_attrs - 2; j++) {
+      interp_attr(dst->data[j], t, in->data[j], out->data[j]);
+   }
+}
+
+
+#define CLIP_USER_BIT    0x40
+#define CLIP_CULL_BIT    0x80
+
+
+static INLINE GLfloat dot4( const GLfloat *a,
+                           const GLfloat *b )
+{
+   GLfloat result = (a[0]*b[0] +
+                    a[1]*b[1] +
+                    a[2]*b[2] +
+                    a[3]*b[3]);
+
+   return result;
+}
+
+
+#if 0   
+static INLINE void do_tri( struct draw_stage *next,
+                          struct prim_header *header )
+{
+   GLuint i;
+   for (i = 0; i < 3; i++) {
+      GLfloat *ndc = header->v[i]->data[0];
+      _mesa_printf("ndc %f %f %f\n", ndc[0], ndc[1], ndc[2]);
+      assert(ndc[0] >= -1 && ndc[0] <= 641);
+      assert(ndc[1] >= 30 && ndc[1] <= 481);
+   }
+   _mesa_printf("\n");
+   next->tri(next, header);
+}
+#endif
+
+
+static void emit_poly( struct draw_stage *stage,
+                      struct vertex_header **inlist,
+                      GLuint n )
+{
+   struct prim_header header;
+   GLuint i;
+
+   for (i = 2; i < n; i++) {
+      header.v[0] = inlist[0];
+      header.v[1] = inlist[i-1];
+      header.v[2] = inlist[i];
+       
+      {
+        GLuint tmp0 = header.v[0]->edgeflag;
+        GLuint tmp2 = header.v[2]->edgeflag;
+
+        if (i != 2)   header.v[0]->edgeflag = 0;
+        if (i != n-1) header.v[2]->edgeflag = 0;
+
+        stage->next->tri( stage->next, &header );
+
+        header.v[0]->edgeflag = tmp0;
+        header.v[2]->edgeflag = tmp2;
+      }
+   }
+}
+
+
+#if 0
+static void emit_poly( struct draw_stage *stage )
+{
+   GLuint i;
+
+   for (i = 2; i < n; i++) {
+      header->v[0] = inlist[0];
+      header->v[1] = inlist[i-1];
+      header->v[2] = inlist[i];
+        
+      stage->next->tri( stage->next, header );
+   }
+}
+#endif
+
+
+/* Clip a triangle against the viewport and user clip planes.
+ */
+static void
+do_clip_tri( struct draw_stage *stage, 
+            struct prim_header *header,
+            GLuint clipmask )
+{
+   struct clipper *clipper = clipper_stage( stage );
+   struct vertex_header *a[MAX_CLIPPED_VERTICES];
+   struct vertex_header *b[MAX_CLIPPED_VERTICES];
+   struct vertex_header **inlist = a;
+   struct vertex_header **outlist = b;
+   GLuint tmpnr = 0;
+   GLuint n = 3;
+   GLuint i;
+
+   inlist[0] = header->v[0];
+   inlist[1] = header->v[1];
+   inlist[2] = header->v[2];
+
+   /* XXX: Note stupid hack to deal with tnl's 8-bit clipmask.  Remove
+    * this once we correctly use 16bit masks for userclip planes.
+    */
+   clipmask &= ~CLIP_CULL_BIT;
+   if (clipmask & CLIP_USER_BIT) {
+      clipmask &= ~CLIP_USER_BIT;
+      clipmask |= clipper->active_user_planes;
+   }
+
+   while (clipmask && n >= 3) {
+      GLuint plane_idx = ffs(clipmask)-1;
+      const GLfloat *plane = clipper->plane[plane_idx];
+      struct vertex_header *vert_prev = inlist[0];
+      GLfloat dp_prev = dot4( vert_prev->clip, plane );
+      GLuint outcount = 0;
+
+      clipmask &= ~(1<<plane_idx);
+
+      inlist[n] = inlist[0]; /* prevent rotation of vertices */
+
+      for (i = 1; i <= n; i++) {
+        struct vertex_header *vert = inlist[i];
+
+        GLfloat dp = dot4( vert->clip, plane );
+
+        if (!IS_NEGATIVE(dp_prev)) {
+           outlist[outcount++] = vert_prev;
+        }
+
+        if (DIFFERENT_SIGNS(dp, dp_prev)) {
+           struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++];
+           outlist[outcount++] = new_vert;
+
+           if (IS_NEGATIVE(dp)) {
+              /* Going out of bounds.  Avoid division by zero as we
+               * know dp != dp_prev from DIFFERENT_SIGNS, above.
+               */
+              GLfloat t = dp / (dp - dp_prev);
+              interp( clipper, new_vert, t, vert, vert_prev );
+              
+              /* Force edgeflag true in this case:
+               */
+              new_vert->edgeflag = 1;
+           } else {
+              /* Coming back in.
+               */
+              GLfloat t = dp_prev / (dp_prev - dp);
+              interp( clipper, new_vert, t, vert_prev, vert );
+
+              /* Copy starting vert's edgeflag:
+               */
+              new_vert->edgeflag = vert_prev->edgeflag;
+           }
+        }
+
+        vert_prev = vert;
+        dp_prev = dp;
+      }
+
+      {
+        struct vertex_header **tmp = inlist;
+        inlist = outlist;
+        outlist = tmp;
+        n = outcount;
+      }
+   }
+
+   /* Emit the polygon as triangles to the setup stage:
+    */
+   if (n >= 3)
+      emit_poly( stage, inlist, n );
+}
+
+
+/* Clip a line against the viewport and user clip planes.
+ */
+static void
+do_clip_line( struct draw_stage *stage,
+             struct prim_header *header,
+             GLuint clipmask )
+{
+   const struct clipper *clipper = clipper_stage( stage );
+   struct vertex_header *v0 = header->v[0];
+   struct vertex_header *v1 = header->v[1];
+   const GLfloat *pos0 = v0->clip;
+   const GLfloat *pos1 = v1->clip;
+   GLfloat t0 = 0;
+   GLfloat t1 = 0;
+   struct prim_header newprim;
+
+   /* XXX: Note stupid hack to deal with tnl's 8-bit clipmask.  Remove
+    * this once we correctly use 16bit masks for userclip planes.
+    */
+   clipmask &= ~CLIP_CULL_BIT;
+   if (clipmask & CLIP_USER_BIT) {
+      clipmask &= ~CLIP_USER_BIT;
+      clipmask |= clipper->active_user_planes;
+   }
+
+   while (clipmask) {
+      const GLuint plane_idx = ffs(clipmask)-1;
+      const GLfloat *plane = clipper->plane[plane_idx];
+      const GLfloat dp0 = dot4( pos0, plane );
+      const GLfloat dp1 = dot4( pos1, plane );
+
+      if (dp1 < 0) {
+        GLfloat t = dp1 / (dp1 - dp0);
+         t1 = MAX2(t1, t);
+      } 
+
+      if (dp0 < 0) {
+        GLfloat t = dp0 / (dp0 - dp1);
+         t0 = MAX2(t0, t);
+      }
+
+      if (t0 + t1 >= 1.0)
+        return; /* discard */
+
+      clipmask &= ~(1 << plane_idx);  /* turn off this plane's bit */
+   }
+
+   if (v0->clipmask) {
+      interp( clipper, stage->tmp[0], t0, v0, v1 );
+      newprim.v[0] = stage->tmp[0];
+   }
+   else {
+      newprim.v[0] = v0;
+   }
+
+   if (v1->clipmask) {
+      interp( clipper, stage->tmp[1], t1, v1, v0 );
+      newprim.v[1] = stage->tmp[1];
+   }
+   else {
+      newprim.v[1] = v1;
+   }
+
+   stage->next->line( stage->next, &newprim );
+}
+
+
+static void clip_begin( struct draw_stage *stage )
+{
+   struct clipper *clipper = clipper_stage(stage);
+   GLuint nr = stage->draw->nr_planes;
+
+   /* sanity checks.  If these fail, review the clip/interp code! */
+   assert(stage->draw->nr_attrs >= 3);
+   assert(stage->draw->attrs[0].attrib == VF_ATTRIB_VERTEX_HEADER);
+   assert(stage->draw->attrs[1].attrib == VF_ATTRIB_CLIP_POS);
+
+   /* Hacky bitmask to use when we hit CLIP_USER_BIT:
+    */   
+   clipper->active_user_planes = ((1<<nr)-1) & ~((1<<6)-1);
+
+   stage->next->begin( stage->next );
+}
+
+
+static void
+clip_point( struct draw_stage *stage, 
+           struct prim_header *header )
+{
+   if (header->v[0]->clipmask == 0) 
+      stage->next->point( stage->next, header );
+}
+
+
+static void
+clip_line( struct draw_stage *stage,
+          struct prim_header *header )
+{
+   GLuint clipmask = (header->v[0]->clipmask | 
+                     header->v[1]->clipmask);
+   
+   if (clipmask == 0) {
+      /* no clipping needed */
+      stage->next->line( stage->next, header );
+   }
+   else if ((header->v[0]->clipmask & 
+            header->v[1]->clipmask) == 0) {
+      do_clip_line(stage, header, clipmask);
+   }
+}
+
+
+static void
+clip_tri( struct draw_stage *stage,
+         struct prim_header *header )
+{
+   GLuint clipmask = (header->v[0]->clipmask | 
+                     header->v[1]->clipmask | 
+                     header->v[2]->clipmask);
+   
+   if (clipmask == 0) {
+      /* no clipping needed */
+      stage->next->tri( stage->next, header );
+   }
+   else if ((header->v[0]->clipmask & 
+            header->v[1]->clipmask & 
+            header->v[2]->clipmask) == 0) {
+      do_clip_tri(stage, header, clipmask);
+   }
+}
+
+
+static void clip_end( struct draw_stage *stage )
+{
+   stage->next->end( stage->next );
+}
+
+
+static void clip_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
+/**
+ * Allocate a new clipper stage.
+ * \return pointer to new stage object
+ */
+struct draw_stage *draw_clip_stage( struct draw_context *draw )
+{
+   struct clipper *clipper = CALLOC_STRUCT(clipper);
+
+   draw_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES );
+
+   clipper->stage.draw = draw;
+   clipper->stage.begin = clip_begin;
+   clipper->stage.point = clip_point;
+   clipper->stage.line = clip_line;
+   clipper->stage.tri = clip_tri;
+   clipper->stage.end = clip_end;
+   clipper->stage.reset_stipple_counter = clip_reset_stipple_counter;
+
+   clipper->plane = draw->plane;
+
+   return &clipper->stage;
+}
diff --git a/src/mesa/pipe/draw/draw_context.c b/src/mesa/pipe/draw/draw_context.c
new file mode 100644 (file)
index 0000000..a97f488
--- /dev/null
@@ -0,0 +1,183 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "imports.h"
+#include "macros.h"
+
+#include "draw_context.h"
+#include "draw_private.h"
+
+
+struct draw_context *draw_create( void )
+{
+   struct draw_context *draw = CALLOC_STRUCT( draw_context );
+
+   /* create pipeline stages */
+   draw->pipeline.unfilled  = draw_unfilled_stage( draw );
+   draw->pipeline.twoside   = draw_twoside_stage( draw );
+   draw->pipeline.offset    = draw_offset_stage( draw );
+   draw->pipeline.clip      = draw_clip_stage( draw );
+   draw->pipeline.flatshade = draw_flatshade_stage( draw );
+   draw->pipeline.cull      = draw_cull_stage( draw );
+
+   ASSIGN_4V( draw->plane[0], -1,  0,  0, 1 );
+   ASSIGN_4V( draw->plane[1],  1,  0,  0, 1 );
+   ASSIGN_4V( draw->plane[2],  0, -1,  0, 1 );
+   ASSIGN_4V( draw->plane[3],  0,  1,  0, 1 );
+   ASSIGN_4V( draw->plane[4],  0,  0,  1, 1 ); /* yes these are correct */
+   ASSIGN_4V( draw->plane[5],  0,  0, -1, 1 ); /* mesa's a bit wonky */
+   draw->nr_planes = 6;
+
+   draw->vf = vf_create( GL_TRUE );
+
+   return draw;
+}
+
+
+void draw_destroy( struct draw_context *draw )
+{
+   if (draw->header.storage)
+      ALIGN_FREE( draw->header.storage );
+
+   vf_destroy( draw->vf );
+
+   FREE( draw );
+}
+
+
+/**
+ * Rebuild the rendering pipeline.
+ */
+static void validate_pipeline( struct draw_context *draw )
+{
+   struct draw_stage *next = draw->pipeline.setup;
+
+   /*
+    * NOTE: we build up the pipeline in end-to-start order.
+    *
+    * TODO: make the current primitive part of the state and build
+    * shorter pipelines for lines & points.
+    */
+
+   if (draw->setup.fill_cw != PIPE_POLYGON_MODE_FILL ||
+       draw->setup.fill_ccw != PIPE_POLYGON_MODE_FILL) {
+      draw->pipeline.unfilled->next = next;
+      next = draw->pipeline.unfilled;
+   }
+        
+   if (draw->setup.offset_cw ||
+       draw->setup.offset_ccw) {
+      draw->pipeline.offset->next = next;
+      next = draw->pipeline.offset;
+   }
+
+   if (draw->setup.light_twoside) {
+      draw->pipeline.twoside->next = next;
+      next = draw->pipeline.twoside;
+   }
+
+   /* Always run the cull stage as we calculate determinant there
+    * also.  Fix this..
+    */
+   {
+      draw->pipeline.cull->next = next;
+      next = draw->pipeline.cull;
+   }
+
+   /* Clip stage
+    */
+   {
+      draw->pipeline.clip->next = next;
+      next = draw->pipeline.clip;
+   }
+
+   /* Do software flatshading prior to clipping.  XXX: should only do
+    * this for clipped primitives, ie it is a part of the clip
+    * routine.
+    */
+   if (draw->setup.flatshade) {
+      draw->pipeline.flatshade->next = next;
+      next = draw->pipeline.flatshade;
+   }
+   
+   draw->pipeline.first = next;
+}
+
+
+/**
+ * Register new primitive setup/rendering state.
+ * This causes the drawing pipeline to be rebuilt.
+ */
+void draw_set_setup_state( struct draw_context *draw,
+                           const struct pipe_setup_state *setup )
+{
+   memcpy( &draw->setup, setup, sizeof(*setup) );
+   validate_pipeline( draw );
+}
+
+
+/** 
+ * Plug in the primitive rendering/rasterization stage.
+ * This is provided by the device driver.
+ */
+void draw_set_setup_stage( struct draw_context *draw,
+                           struct draw_stage *stage )
+{
+   draw->pipeline.setup = stage;
+}
+
+
+/**
+ * Set the draw module's clipping state.
+ */
+void draw_set_clip_state( struct draw_context *draw,
+                          const struct pipe_clip_state *clip )
+{
+   memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
+   draw->nr_planes = 6 + clip->nr;
+}
+
+
+/**
+ * Set the draw module's viewport state.
+ */
+void draw_set_viewport_state( struct draw_context *draw,
+                              const struct pipe_viewport_state *viewport )
+{
+   draw->viewport = *viewport; /* struct copy */
+
+   vf_set_vp_scale_translate( draw->vf, viewport->scale, viewport->translate );
+
+   /* Using tnl/ and vf/ modules is temporary while getting started.
+    * Full pipe will have vertex shader, vertex fetch of its own.
+    */
+}
diff --git a/src/mesa/pipe/draw/draw_context.h b/src/mesa/pipe/draw/draw_context.h
new file mode 100644 (file)
index 0000000..c298d4f
--- /dev/null
@@ -0,0 +1,74 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  Public interface into the drawing module.
+ */
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef DRAW_CONTEXT_H
+#define DRAW_CONTEXT_H
+
+
+#include "glheader.h"
+#include "pipe/p_state.h"
+
+
+struct vertex_buffer;
+struct draw_context;
+struct draw_stage;
+
+
+struct draw_context *draw_create( void );
+
+void draw_destroy( struct draw_context *draw );
+
+void draw_set_viewport_state( struct draw_context *draw,
+                              const struct pipe_viewport_state *viewport );
+
+void draw_set_clip_state( struct draw_context *pipe,
+                          const struct pipe_clip_state *clip );
+
+void draw_set_setup_state( struct draw_context *draw,
+                           const struct pipe_setup_state *setup );
+
+void draw_set_setup_stage( struct draw_context *draw,
+                           struct draw_stage *stage );
+
+void draw_set_vertex_attributes( struct draw_context *draw,
+                                const GLuint *attrs,
+                                GLuint nr_attrs );
+
+void draw_vb(struct draw_context *draw,
+            struct vertex_buffer *VB );
+
+
+#endif /* DRAW_CONTEXT_H */
diff --git a/src/mesa/pipe/draw/draw_cull.c b/src/mesa/pipe/draw/draw_cull.c
new file mode 100644 (file)
index 0000000..8b2ac5e
--- /dev/null
@@ -0,0 +1,138 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  Drawing stage for polygon culling
+ */
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "draw_private.h"
+
+
+struct cull_stage {
+   struct draw_stage stage;
+   GLuint winding;  /**< which winding(s) to cull (one of PIPE_WINDING_x) */
+};
+
+
+static INLINE struct cull_stage *cull_stage( struct draw_stage *stage )
+{
+   return (struct cull_stage *)stage;
+}
+
+
+static void cull_begin( struct draw_stage *stage )
+{
+   struct cull_stage *cull = cull_stage(stage);
+
+   cull->winding = stage->draw->setup.cull_mode;
+
+   stage->next->begin( stage->next );
+}
+
+
+static void cull_tri( struct draw_stage *stage,
+                     struct prim_header *header )
+{
+   /* Window coords: */
+   const GLfloat *v0 = header->v[0]->data[0];
+   const GLfloat *v1 = header->v[1]->data[0];
+   const GLfloat *v2 = header->v[2]->data[0];
+
+   /* edge vectors e = v0 - v2, f = v1 - v2 */
+   GLfloat ex = v0[0] - v2[0];
+   GLfloat ey = v0[1] - v2[1];
+   GLfloat fx = v1[0] - v2[0];
+   GLfloat fy = v1[1] - v2[1];
+   
+   /* det = cross(e,f).z */
+   header->det = ex * fy - ey * fx;
+
+   if (header->det != 0) {
+      /* if (det > 0 then Z points toward camera and triangle is 
+       * counter-clockwise winding.
+       */
+      GLuint winding = (header->det > 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW;
+
+      if ((winding & cull_stage(stage)->winding) == 0) {
+         /* triangle is not culled, pass to next stage */
+        stage->next->tri( stage->next, header );
+      }
+   }
+}
+
+
+static void cull_line( struct draw_stage *stage,
+                      struct prim_header *header )
+{
+   stage->next->line( stage->next, header );
+}
+
+
+static void cull_point( struct draw_stage *stage,
+                       struct prim_header *header )
+{
+   stage->next->point( stage->next, header );
+}
+
+
+static void cull_end( struct draw_stage *stage )
+{
+   stage->next->end( stage->next );
+}
+
+
+static void cull_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+/**
+ * Create a new polygon culling stage.
+ */
+struct draw_stage *draw_cull_stage( struct draw_context *draw )
+{
+   struct cull_stage *cull = CALLOC_STRUCT(cull_stage);
+
+   draw_alloc_tmps( &cull->stage, 0 );
+
+   cull->stage.draw = draw;
+   cull->stage.next = NULL;
+   cull->stage.begin = cull_begin;
+   cull->stage.point = cull_point;
+   cull->stage.line = cull_line;
+   cull->stage.tri = cull_tri;
+   cull->stage.end = cull_end;
+   cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
+
+   return &cull->stage;
+}
diff --git a/src/mesa/pipe/draw/draw_flatshade.c b/src/mesa/pipe/draw/draw_flatshade.c
new file mode 100644 (file)
index 0000000..cf5e762
--- /dev/null
@@ -0,0 +1,162 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "draw_private.h"
+
+
+struct flatshade_stage {
+   struct draw_stage stage;
+
+   const GLuint *lookup;
+};
+
+
+
+static INLINE struct flatshade_stage *flatshade_stage( struct draw_stage *stage )
+{
+   return (struct flatshade_stage *)stage;
+}
+
+
+static void flatshade_begin( struct draw_stage *stage )
+{
+   stage->next->begin( stage->next );
+}
+
+
+
+static INLINE void copy_attr( GLuint attr,
+                             struct vertex_header *dst, 
+                             const struct vertex_header *src )
+{
+   if (attr) {
+      memcpy( dst->data[attr],
+             src->data[attr],
+             sizeof(src->data[0]) );
+   }
+}
+
+
+static INLINE void copy_colors( struct draw_stage *stage, 
+                                struct vertex_header *dst, 
+                                const struct vertex_header *src )
+{
+   const struct flatshade_stage *flatshade = flatshade_stage(stage);
+   const GLuint *lookup = flatshade->lookup;
+
+   copy_attr( lookup[VF_ATTRIB_COLOR0], dst, src );
+   copy_attr( lookup[VF_ATTRIB_COLOR1], dst, src );
+   copy_attr( lookup[VF_ATTRIB_BFC0], dst, src );
+   copy_attr( lookup[VF_ATTRIB_BFC1], dst, src );
+}
+
+
+/**
+ * Flatshade tri.  Required for clipping and when unfilled tris are
+ * active, otherwise handled by hardware.
+ */
+static void flatshade_tri( struct draw_stage *stage,
+                          struct prim_header *header )
+{
+   struct prim_header tmp;
+
+   tmp.det = header->det;
+   tmp.v[0] = dup_vert(stage, header->v[0], 0);
+   tmp.v[1] = dup_vert(stage, header->v[1], 1);
+   tmp.v[2] = header->v[2];
+
+   copy_colors(stage, tmp.v[0], tmp.v[2]);
+   copy_colors(stage, tmp.v[1], tmp.v[2]);
+   
+   stage->next->tri( stage->next, &tmp );
+}
+
+
+/**
+ * Flatshade line.  Required for clipping.
+ */
+static void flatshade_line( struct draw_stage *stage,
+                           struct prim_header *header )
+{
+   struct prim_header tmp;
+
+   tmp.v[0] = dup_vert(stage, header->v[0], 0);
+   tmp.v[1] = header->v[1];
+
+   copy_colors(stage, tmp.v[0], tmp.v[1]);
+   
+   stage->next->line( stage->next, &tmp );
+}
+
+
+static void flatshade_point( struct draw_stage *stage,
+                             struct prim_header *header )
+{
+   stage->next->point( stage->next, header );
+}
+
+
+static void flatshade_end( struct draw_stage *stage )
+{
+   stage->next->end( stage->next );
+}
+
+
+static void flatshade_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
+/**
+ * Create flatshading drawing stage.
+ */
+struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
+{
+   struct flatshade_stage *flatshade = CALLOC_STRUCT(flatshade_stage);
+
+   draw_alloc_tmps( &flatshade->stage, 2 );
+
+   flatshade->stage.draw = draw;
+   flatshade->stage.next = NULL;
+   flatshade->stage.begin = flatshade_begin;
+   flatshade->stage.point = flatshade_point;
+   flatshade->stage.line = flatshade_line;
+   flatshade->stage.tri = flatshade_tri;
+   flatshade->stage.end = flatshade_end;
+   flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
+
+   flatshade->lookup = draw->vf_attr_to_slot;
+
+   return &flatshade->stage;
+}
+
+
diff --git a/src/mesa/pipe/draw/draw_offset.c b/src/mesa/pipe/draw/draw_offset.c
new file mode 100644 (file)
index 0000000..9f66566
--- /dev/null
@@ -0,0 +1,173 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  polygon offset state
+ *
+ * \author  Keith Whitwell <keith@tungstengraphics.com>
+ * \author  Brian Paul
+ */
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "draw_private.h"
+
+
+
+struct offset_stage {
+   struct draw_stage stage;
+
+   GLfloat scale;
+   GLfloat units;
+};
+
+
+
+static INLINE struct offset_stage *offset_stage( struct draw_stage *stage )
+{
+   return (struct offset_stage *) stage;
+}
+
+
+static void offset_begin( struct draw_stage *stage )
+{
+   struct offset_stage *offset = offset_stage(stage);
+   GLfloat mrd = 1.0 / 65535.0; /* XXX this depends on depthbuffer bits! */
+
+   offset->units = stage->draw->setup.offset_units * mrd;
+   offset->scale = stage->draw->setup.offset_scale;
+
+   stage->next->begin( stage->next );
+}
+
+
+/**
+ * Offset tri Z.  Some hardware can handle this, but not usually when
+ * doing unfilled rendering.
+ */
+static void do_offset_tri( struct draw_stage *stage,
+                          struct prim_header *header )
+{
+   struct offset_stage *offset = offset_stage(stage);   
+   GLfloat inv_det = 1.0 / header->det;
+
+   /* Window coords:
+    */
+   GLfloat *v0 = header->v[0]->data[0];
+   GLfloat *v1 = header->v[1]->data[0];
+   GLfloat *v2 = header->v[2]->data[0];
+
+   /* edge vectors e = v0 - v2, f = v1 - v2 */
+   GLfloat ex = v0[0] - v2[0];
+   GLfloat ey = v0[1] - v2[1];
+   GLfloat ez = v0[2] - v2[2];
+   GLfloat fx = v1[0] - v2[0];
+   GLfloat fy = v1[1] - v2[1];
+   GLfloat fz = v1[2] - v2[2];
+
+   /* (a,b) = cross(e,f).xy */
+   GLfloat a = ey*fz - ez*fy;
+   GLfloat b = ez*fx - ex*fz;
+
+   GLfloat dzdx = FABSF(a * inv_det);
+   GLfloat dzdy = FABSF(b * inv_det);
+
+   GLfloat zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale;
+
+   /*
+    * Note: we're applying the offset and clamping per-vertex.
+    * Ideally, the offset is applied per-fragment prior to fragment shading.
+    */
+   v0[2] = CLAMP(v0[2] + zoffset, 0.0, 1.0);
+   v1[2] = CLAMP(v1[2] + zoffset, 0.0, 1.0);
+   v2[2] = CLAMP(v2[2] + zoffset, 0.0, 1.0);
+
+   stage->next->tri( stage->next, header );
+}
+
+
+static void offset_tri( struct draw_stage *stage,
+                       struct prim_header *header )
+{
+   struct prim_header tmp;
+
+   tmp.det = header->det;
+   tmp.v[0] = dup_vert(stage, header->v[0], 0);
+   tmp.v[1] = dup_vert(stage, header->v[1], 1);
+   tmp.v[2] = dup_vert(stage, header->v[2], 2);
+
+   do_offset_tri( stage, &tmp );
+}
+
+
+
+static void offset_line( struct draw_stage *stage,
+                      struct prim_header *header )
+{
+   stage->next->line( stage->next, header );
+}
+
+
+static void offset_point( struct draw_stage *stage,
+                       struct prim_header *header )
+{
+   stage->next->point( stage->next, header );
+}
+
+
+static void offset_end( struct draw_stage *stage )
+{
+   stage->next->end( stage->next );
+}
+
+
+static void offset_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
+/**
+ * Create polygon offset drawing stage.
+ */
+struct draw_stage *draw_offset_stage( struct draw_context *draw )
+{
+   struct offset_stage *offset = CALLOC_STRUCT(offset_stage);
+
+   draw_alloc_tmps( &offset->stage, 3 );
+
+   offset->stage.draw = draw;
+   offset->stage.next = NULL;
+   offset->stage.begin = offset_begin;
+   offset->stage.point = offset_point;
+   offset->stage.line = offset_line;
+   offset->stage.tri = offset_tri;
+   offset->stage.end = offset_end;
+   offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
+
+   return &offset->stage;
+}
diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h
new file mode 100644 (file)
index 0000000..3dfaa05
--- /dev/null
@@ -0,0 +1,184 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * Private data structures, etc for the draw module.
+ */
+
+
+/**
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Brian Paul
+ */
+
+
+#ifndef DRAW_PRIVATE_H
+#define DRAW_PRIVATE_H
+
+
+#include "main/glheader.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "vf/vf.h"
+
+
+/**
+ * Basic vertex info.
+ * Carry some useful information around with the vertices in the prim pipe.  
+ */
+struct vertex_header {
+   GLuint clipmask:12;
+   GLuint edgeflag:1;
+   GLuint pad:19;
+
+   GLfloat clip[4];
+
+   GLfloat data[][4];          /* Note variable size */
+};
+
+
+/**
+ * Basic info for a point/line/triangle primitive.
+ */
+struct prim_header {
+   GLfloat det;                 /**< front/back face determinant */
+   struct vertex_header *v[3];  /**< 1 to 3 vertex pointers */
+};
+
+
+
+struct draw_context;
+
+/**
+ * Base class for all primitive drawing stages.
+ */
+struct draw_stage
+{
+   struct draw_context *draw;   /**< parent context */
+
+   struct draw_stage *next;     /**< next stage in pipeline */
+
+   struct vertex_header **tmp;
+   GLuint nr_tmps;
+
+   void (*begin)( struct draw_stage * );
+
+   void (*point)( struct draw_stage *,
+                 struct prim_header * );
+
+   void (*line)( struct draw_stage *,
+                struct prim_header * );
+
+   void (*tri)( struct draw_stage *,
+               struct prim_header * );
+   
+   void (*end)( struct draw_stage * );
+
+   void (*reset_stipple_counter)( struct draw_stage * );
+};
+
+
+/**
+ * Private context for the drawing module.
+ */
+struct draw_context
+{
+   struct {
+      struct draw_stage *first;  /**< one of the following */
+
+      /* stages (in logical order) */
+      struct draw_stage *flatshade;
+      struct draw_stage *clip;
+      struct draw_stage *cull;
+      struct draw_stage *twoside;
+      struct draw_stage *offset;
+      struct draw_stage *unfilled;
+      struct draw_stage *setup;  /* aka render/rasterize */
+   } pipeline;
+
+   /* pipe state that we need: */
+   struct pipe_setup_state setup;
+   struct pipe_viewport_state viewport;
+
+   /* Clip derived state:
+    */
+   GLfloat plane[12][4];
+   GLuint nr_planes;
+
+   GLuint vf_attr_to_slot[PIPE_ATTRIB_MAX];
+
+   struct vf_attr_map attrs[VF_ATTRIB_MAX];
+   GLuint nr_attrs;
+   GLuint vertex_size;       /**< in bytes */
+   struct vertex_fetch *vf;
+
+   GLubyte *verts;
+   GLuint nr_vertices;
+   GLboolean in_vb;
+
+   GLenum prim;   /**< GL_POINTS, GL_LINE_STRIP, GL_QUADS, etc */
+
+   /* Helper for tnl:
+    */
+   GLvector4f header;   
+};
+
+
+
+extern struct draw_stage *draw_unfilled_stage( struct draw_context *context );
+extern struct draw_stage *draw_twoside_stage( struct draw_context *context );
+extern struct draw_stage *draw_offset_stage( struct draw_context *context );
+extern struct draw_stage *draw_clip_stage( struct draw_context *context );
+extern struct draw_stage *draw_flatshade_stage( struct draw_context *context );
+extern struct draw_stage *draw_cull_stage( struct draw_context *context );
+
+
+extern void draw_free_tmps( struct draw_stage *stage );
+extern void draw_alloc_tmps( struct draw_stage *stage, GLuint nr );
+
+
+
+/**
+ * Get a writeable copy of a vertex.
+ * \param stage  drawing stage info
+ * \param vert  the vertex to copy (source)
+ * \param idx  index into stage's tmp[] array to put the copy (dest)
+ * \return  pointer to the copied vertex
+ */
+static INLINE struct vertex_header *
+dup_vert( struct draw_stage *stage,
+         const struct vertex_header *vert,
+         GLuint idx )
+{   
+   struct vertex_header *tmp = stage->tmp[idx];
+   memcpy(tmp, vert, stage->draw->vertex_size );
+   return tmp;
+}
+
+
+#endif /* DRAW_PRIVATE_H */
diff --git a/src/mesa/pipe/draw/draw_twoside.c b/src/mesa/pipe/draw/draw_twoside.c
new file mode 100644 (file)
index 0000000..fdda6b3
--- /dev/null
@@ -0,0 +1,169 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "draw_private.h"
+
+
+struct twoside_stage {
+   struct draw_stage stage;
+   GLfloat sign;         /**< +1 or -1 */
+   const GLuint *lookup;
+};
+
+
+static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage )
+{
+   return (struct twoside_stage *)stage;
+}
+
+
+static void twoside_begin( struct draw_stage *stage )
+{
+   struct twoside_stage *twoside = twoside_stage(stage);
+
+   /*
+    * We'll multiply the primitive's determinant by this sign to determine
+    * if the triangle is back-facing (negative).
+    * sign = 1 for CCW, -1 for CW
+    */
+   twoside->sign = (stage->draw->setup.front_winding == PIPE_WINDING_CCW) ? 1 : -1;
+
+   stage->next->begin( stage->next );
+}
+
+
+static INLINE void copy_color( GLuint attr_dst,
+                              GLuint attr_src,
+                              struct vertex_header *v )
+{
+   if (attr_dst && attr_src) {
+      memcpy( v->data[attr_dst],
+             v->data[attr_src],
+             sizeof(v->data[0]) );
+   }
+}
+
+
+static struct vertex_header *copy_bfc( struct twoside_stage *twoside, 
+                                      const struct vertex_header *v,
+                                      GLuint idx )
+{   
+   struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
+   
+   copy_color( twoside->lookup[VF_ATTRIB_COLOR0], 
+              twoside->lookup[VF_ATTRIB_BFC0],
+              tmp );
+
+   copy_color( twoside->lookup[VF_ATTRIB_COLOR1], 
+              twoside->lookup[VF_ATTRIB_BFC1],
+              tmp );
+
+   return tmp;
+}
+
+
+/* Twoside tri:
+ */
+static void twoside_tri( struct draw_stage *stage,
+                        struct prim_header *header )
+{
+   struct twoside_stage *twoside = twoside_stage(stage);
+
+   if (header->det * twoside->sign < 0.0) {
+      /* this is a back-facing triangle */
+      struct prim_header tmp;
+
+      tmp.det = header->det;
+      /* copy back colors to front color slots */
+      tmp.v[0] = copy_bfc(twoside, header->v[0], 0);
+      tmp.v[1] = copy_bfc(twoside, header->v[1], 1);
+      tmp.v[2] = copy_bfc(twoside, header->v[2], 2);
+
+      stage->next->tri( stage->next, &tmp );
+   }
+   else {
+      stage->next->tri( stage->next, header );
+   }
+}
+
+
+static void twoside_line( struct draw_stage *stage,
+                      struct prim_header *header )
+{
+   /* pass-through */
+   stage->next->line( stage->next, header );
+}
+
+
+static void twoside_point( struct draw_stage *stage,
+                       struct prim_header *header )
+{
+   /* pass-through */
+   stage->next->point( stage->next, header );
+}
+
+
+static void twoside_end( struct draw_stage *stage )
+{
+   /* pass-through */
+   stage->next->end( stage->next );
+}
+
+
+static void twoside_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
+/**
+ * Create twoside pipeline stage.
+ */
+struct draw_stage *draw_twoside_stage( struct draw_context *draw )
+{
+   struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage);
+
+   draw_alloc_tmps( &twoside->stage, 3 );
+
+   twoside->stage.draw = draw;
+   twoside->stage.next = NULL;
+   twoside->stage.begin = twoside_begin;
+   twoside->stage.point = twoside_point;
+   twoside->stage.line = twoside_line;
+   twoside->stage.tri = twoside_tri;
+   twoside->stage.end = twoside_end;
+   twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
+
+   twoside->lookup = draw->vf_attr_to_slot;
+
+   return &twoside->stage;
+}
diff --git a/src/mesa/pipe/draw/draw_unfilled.c b/src/mesa/pipe/draw/draw_unfilled.c
new file mode 100644 (file)
index 0000000..82e8775
--- /dev/null
@@ -0,0 +1,185 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  Drawing stage for handling glPolygonMode(line/point).
+ * Convert triangles to points or lines as needed.
+ */
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "draw_private.h"
+
+
+struct unfilled_stage {
+   struct draw_stage stage;
+
+   /** [0] = front face, [1] = back face.
+    * legal values:  PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE,
+    * and PIPE_POLYGON_MODE_POINT,
+    */
+   GLuint mode[2];
+};
+
+
+static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage )
+{
+   return (struct unfilled_stage *)stage;
+}
+
+
+static void unfilled_begin( struct draw_stage *stage )
+{
+   struct unfilled_stage *unfilled = unfilled_stage(stage);
+
+   unfilled->mode[0] = stage->draw->setup.fill_ccw; /* front */
+   unfilled->mode[1] = stage->draw->setup.fill_cw;  /* back */
+
+   stage->next->begin( stage->next );
+}
+
+static void point( struct draw_stage *stage,
+                  struct vertex_header *v0 )
+{
+   struct prim_header tmp;
+   tmp.v[0] = v0;
+   stage->next->point( stage->next, &tmp );
+}
+
+static void line( struct draw_stage *stage,
+                 struct vertex_header *v0,
+                 struct vertex_header *v1 )
+{
+   struct prim_header tmp;
+   tmp.v[0] = v0;
+   tmp.v[1] = v1;
+   stage->next->line( stage->next, &tmp );
+}
+
+
+static void points( struct draw_stage *stage,
+                   struct prim_header *header )
+{
+   struct vertex_header *v0 = header->v[0];
+   struct vertex_header *v1 = header->v[1];
+   struct vertex_header *v2 = header->v[2];
+
+   if (v0->edgeflag) point( stage, v0 );
+   if (v1->edgeflag) point( stage, v1 );
+   if (v2->edgeflag) point( stage, v2 );
+}
+
+
+static void lines( struct draw_stage *stage,
+                  struct prim_header *header )
+{
+   struct vertex_header *v0 = header->v[0];
+   struct vertex_header *v1 = header->v[1];
+   struct vertex_header *v2 = header->v[2];
+
+   if (v0->edgeflag) line( stage, v0, v1 );
+   if (v1->edgeflag) line( stage, v1, v2 );
+   if (v2->edgeflag) line( stage, v2, v0 );
+}
+
+
+/* Unfilled tri:  
+ *
+ * Note edgeflags in the vertex struct is not sufficient as we will
+ * need to manipulate them when decomposing primitives???
+ */
+static void unfilled_tri( struct draw_stage *stage,
+                         struct prim_header *header )
+{
+   struct unfilled_stage *unfilled = unfilled_stage(stage);
+   GLuint mode = unfilled->mode[header->det > 0.0];
+  
+   switch (mode) {
+   case PIPE_POLYGON_MODE_FILL:
+      stage->next->tri( stage->next, header );
+      break;
+   case PIPE_POLYGON_MODE_LINE:
+      lines( stage, header );
+      break;
+   case PIPE_POLYGON_MODE_POINT:
+      points( stage, header );
+      break;
+   default:
+      abort();
+   }   
+}
+
+static void unfilled_line( struct draw_stage *stage,
+                           struct prim_header *header )
+{
+   stage->next->line( stage->next, header );
+}
+
+
+static void unfilled_point( struct draw_stage *stage,
+                            struct prim_header *header )
+{
+   stage->next->point( stage->next, header );
+}
+
+
+static void unfilled_end( struct draw_stage *stage )
+{
+   stage->next->end( stage->next );
+}
+
+
+static void unfilled_reset_stipple_counter( struct draw_stage *stage )
+{
+   stage->next->reset_stipple_counter( stage->next );
+}
+
+
+/**
+ * Create unfilled triangle stage.
+ */
+struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
+{
+   struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage);
+
+   draw_alloc_tmps( &unfilled->stage, 0 );
+
+   unfilled->stage.draw = draw;
+   unfilled->stage.next = NULL;
+   unfilled->stage.tmp = NULL;
+   unfilled->stage.begin = unfilled_begin;
+   unfilled->stage.point = unfilled_point;
+   unfilled->stage.line = unfilled_line;
+   unfilled->stage.tri = unfilled_tri;
+   unfilled->stage.end = unfilled_end;
+   unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
+
+   return &unfilled->stage;
+}
diff --git a/src/mesa/pipe/draw/draw_vb.c b/src/mesa/pipe/draw/draw_vb.c
new file mode 100644 (file)
index 0000000..ac126c5
--- /dev/null
@@ -0,0 +1,728 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "imports.h"
+#include "macros.h"
+
+#include "tnl/t_context.h"
+#include "vf/vf.h"
+
+#include "draw_private.h"
+#include "draw_context.h"
+
+
+/* This file is a temporary set of hooks to allow us to use the tnl/
+ * and vf/ modules until we have replacements in pipe.
+ */
+
+
+static struct vertex_header *get_vertex( struct draw_context *pipe,
+                                              GLuint i )
+{
+   return (struct vertex_header *)(pipe->verts + i * pipe->vertex_size);
+}
+
+
+
+static void draw_allocate_vertices( struct draw_context *draw,
+                                   GLuint nr_vertices )
+{
+   draw->nr_vertices = nr_vertices;
+   draw->verts = MALLOC( nr_vertices * draw->vertex_size );
+
+   draw->pipeline.first->begin( draw->pipeline.first );
+}
+
+static void draw_set_prim( struct draw_context *draw,
+                          GLenum prim )
+{
+   draw->prim = prim;
+
+   /* Not done yet - need to force edgeflags to 1 in strip/fan
+    * primitives.
+    */
+#if 0
+   switch (prim) {
+   case GL_TRIANGLES:
+   case GL_POLYGON:
+   case GL_QUADS:
+   case GL_QUAD_STRIP:         /* yes, we need this */
+      respect_edgeflags( pipe, GL_TRUE );
+      break;
+
+   default:
+      respect_edgeflags( pipe, GL_FALSE );
+      break;
+   }
+#endif
+}
+                         
+
+
+static void do_quad( struct draw_stage *first,
+                    struct vertex_header *v0,
+                    struct vertex_header *v1,
+                    struct vertex_header *v2,
+                    struct vertex_header *v3 )
+{
+   struct prim_header prim;
+
+   {
+      GLuint tmp = v1->edgeflag;
+      v1->edgeflag = 0;
+
+      prim.v[0] = v0;
+      prim.v[1] = v1;
+      prim.v[2] = v3;
+      first->tri( first, &prim );
+
+      v1->edgeflag = tmp;
+   }
+
+   {
+      GLuint tmp = v3->edgeflag;
+      v3->edgeflag = 0;
+
+      prim.v[0] = v1;
+      prim.v[1] = v2;
+      prim.v[2] = v3;
+      first->tri( first, &prim );
+
+      v3->edgeflag = tmp;
+   }
+}
+
+
+
+
+static void draw_indexed_prim( struct draw_context *draw,
+                              const GLuint *elts,
+                              GLuint count )
+{
+   struct draw_stage * const first = draw->pipeline.first;
+   struct prim_header prim;
+   GLuint i;
+
+   prim.det = 0;               /* valid from cull stage onwards */
+   prim.v[0] = 0;
+   prim.v[1] = 0;
+   prim.v[2] = 0;
+
+   switch (draw->prim) {
+   case GL_POINTS:
+      for (i = 0; i < count; i ++) {
+        prim.v[0] = get_vertex( draw, elts[i] );
+
+        first->point( first, &prim );
+      }
+      break;
+
+   case GL_LINES:
+      for (i = 0; i+1 < count; i += 2) {
+        prim.v[0] = get_vertex( draw, elts[i + 0] );
+        prim.v[1] = get_vertex( draw, elts[i + 1] );
+      
+         first->reset_stipple_counter( first );
+        first->line( first, &prim );
+      }
+      break;
+
+   case GL_LINE_LOOP:  
+      if (count >= 2) {
+         first->reset_stipple_counter( first );
+        for (i = 1; i < count; i++) {
+           prim.v[0] = get_vertex( draw, elts[i-1] );
+           prim.v[1] = get_vertex( draw, elts[i] );        
+           first->line( first, &prim );
+        }
+
+        prim.v[0] = get_vertex( draw, elts[count-1] );
+        prim.v[1] = get_vertex( draw, elts[0] );           
+        first->line( first, &prim );
+      }
+      break;
+
+   case GL_LINE_STRIP:
+      /* I'm guessing it will be necessary to have something like a
+       * render->reset_line_stipple() method to properly support
+       * splitting strips into primitives like this.  Alternately we
+       * could just scan ahead to find individual clipped lines and
+       * otherwise leave the strip intact - that might be better, but
+       * require more complex code here.
+       */
+      if (count >= 2) {
+         first->reset_stipple_counter( first );
+        prim.v[0] = 0;
+        prim.v[1] = get_vertex( draw, elts[0] );
+        
+        for (i = 1; i < count; i++) {
+           prim.v[0] = prim.v[1];
+           prim.v[1] = get_vertex( draw, elts[i] );
+           
+           first->line( first, &prim );
+        }
+      }
+      break;
+
+   case GL_TRIANGLES:
+      for (i = 0; i+2 < count; i += 3) {
+        prim.v[0] = get_vertex( draw, elts[i + 0] );
+        prim.v[1] = get_vertex( draw, elts[i + 1] );
+        prim.v[2] = get_vertex( draw, elts[i + 2] );
+      
+        first->tri( first, &prim );
+      }
+      break;
+
+   case GL_TRIANGLE_STRIP:
+      for (i = 0; i+2 < count; i++) {
+        if (i & 1) {
+           prim.v[0] = get_vertex( draw, elts[i + 1] );
+           prim.v[1] = get_vertex( draw, elts[i + 0] );
+           prim.v[2] = get_vertex( draw, elts[i + 2] );
+        }
+        else {
+           prim.v[0] = get_vertex( draw, elts[i + 0] );
+           prim.v[1] = get_vertex( draw, elts[i + 1] );
+           prim.v[2] = get_vertex( draw, elts[i + 2] );
+        }
+        
+        first->tri( first, &prim );
+      }
+      break;
+
+   case GL_TRIANGLE_FAN:
+      if (count >= 3) {
+        prim.v[0] = get_vertex( draw, elts[0] );
+        prim.v[1] = 0;
+        prim.v[2] = get_vertex( draw, elts[1] );
+        
+        for (i = 0; i+2 < count; i++) {
+           prim.v[1] = prim.v[2];
+           prim.v[2] = get_vertex( draw, elts[i+2] );
+      
+           first->tri( first, &prim );
+        }
+      }
+      break;
+
+   case GL_QUADS:
+      for (i = 0; i+3 < count; i += 4) {
+        do_quad( first,
+                 get_vertex( draw, elts[i + 0] ),
+                 get_vertex( draw, elts[i + 1] ),
+                 get_vertex( draw, elts[i + 2] ),
+                 get_vertex( draw, elts[i + 3] ));
+      }
+      break;
+
+   case GL_QUAD_STRIP:
+      for (i = 0; i+3 < count; i += 2) {
+        do_quad( first,
+                 get_vertex( draw, elts[i + 2] ),
+                 get_vertex( draw, elts[i + 0] ),
+                 get_vertex( draw, elts[i + 1] ),
+                 get_vertex( draw, elts[i + 3] ));
+      }
+      break;
+
+
+   case GL_POLYGON:
+      if (count >= 3) {
+         int e1save, e2save;
+        prim.v[0] = 0;
+        prim.v[1] = get_vertex( draw, elts[1] );
+        prim.v[2] = get_vertex( draw, elts[0] );
+        e2save = prim.v[2]->edgeflag;
+        
+        for (i = 0; i+2 < count; i++) {
+           prim.v[0] = prim.v[1];
+           prim.v[1] = get_vertex( draw, elts[i+2] );
+      
+            /* save v1 edge flag, and clear if not last triangle */
+            e1save = prim.v[1]->edgeflag;
+            if (i + 3 < count)
+               prim.v[1]->edgeflag = 0;
+
+            /* draw */
+           first->tri( first, &prim );
+
+            prim.v[1]->edgeflag = e1save; /* restore */
+            prim.v[2]->edgeflag = 0; /* disable edge after 1st tri */
+        }
+         prim.v[2]->edgeflag = e2save;
+      }
+      break;
+
+   default:
+      assert(0);
+      break;
+   }
+}
+
+static void draw_prim( struct draw_context *draw,
+                      GLuint start,
+                      GLuint count )
+{
+   struct draw_stage * const first = draw->pipeline.first;
+   struct prim_header prim;
+   GLuint i;
+
+//   _mesa_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count );
+
+   prim.det = 0;               /* valid from cull stage onwards */
+   prim.v[0] = 0;
+   prim.v[1] = 0;
+   prim.v[2] = 0;
+
+   switch (draw->prim) {
+   case GL_POINTS:
+      for (i = 0; i < count; i ++) {
+        prim.v[0] = get_vertex( draw, start + i );
+        first->point( first, &prim );
+      }
+      break;
+
+   case GL_LINES:
+      for (i = 0; i+1 < count; i += 2) {
+        prim.v[0] = get_vertex( draw, start + i + 0 );
+        prim.v[1] = get_vertex( draw, start + i + 1 );
+
+         first->reset_stipple_counter( first );
+        first->line( first, &prim );
+      }
+      break;
+
+   case GL_LINE_LOOP:  
+      if (count >= 2) {
+         first->reset_stipple_counter( first );
+        for (i = 1; i < count; i++) {
+           prim.v[0] = get_vertex( draw, start + i - 1 );
+           prim.v[1] = get_vertex( draw, start + i );      
+           first->line( first, &prim );
+        }
+
+        prim.v[0] = get_vertex( draw, start + count - 1 );
+        prim.v[1] = get_vertex( draw, start + 0 );         
+        first->line( first, &prim );
+      }
+      break;
+
+   case GL_LINE_STRIP:
+      if (count >= 2) {
+         first->reset_stipple_counter( first );
+        prim.v[0] = 0;
+        prim.v[1] = get_vertex( draw, start + 0 );
+        
+        for (i = 1; i < count; i++) {
+           prim.v[0] = prim.v[1];
+           prim.v[1] = get_vertex( draw, start + i );
+           
+           first->line( first, &prim );
+        }
+      }
+      break;
+
+   case GL_TRIANGLES:
+      for (i = 0; i+2 < count; i += 3) {
+        prim.v[0] = get_vertex( draw, start + i + 0 );
+        prim.v[1] = get_vertex( draw, start + i + 1 );
+        prim.v[2] = get_vertex( draw, start + i + 2 );
+      
+        first->tri( first, &prim );
+      }
+      break;
+
+   case GL_TRIANGLE_STRIP:
+      for (i = 0; i+2 < count; i++) {
+        if (i & 1) {
+           prim.v[0] = get_vertex( draw, start + i + 1 );
+           prim.v[1] = get_vertex( draw, start + i + 0 );
+           prim.v[2] = get_vertex( draw, start + i + 2 );
+        }
+        else {
+           prim.v[0] = get_vertex( draw, start + i + 0 );
+           prim.v[1] = get_vertex( draw, start + i + 1 );
+           prim.v[2] = get_vertex( draw, start + i + 2 );
+        }
+        
+        first->tri( first, &prim );
+      }
+      break;
+
+   case GL_TRIANGLE_FAN:
+      if (count >= 3) {
+        prim.v[0] = get_vertex( draw, start + 0 );
+        prim.v[1] = 0;
+        prim.v[2] = get_vertex( draw, start + 1 );
+        
+        for (i = 0; i+2 < count; i++) {
+           prim.v[1] = prim.v[2];
+           prim.v[2] = get_vertex( draw, start + i + 2 );
+      
+           first->tri( first, &prim );
+        }
+      }
+      break;
+
+
+   case GL_QUADS:
+      for (i = 0; i+3 < count; i += 4) {
+        do_quad( first,
+                 get_vertex( draw, start + i + 0 ),
+                 get_vertex( draw, start + i + 1 ),
+                 get_vertex( draw, start + i + 2 ),
+                 get_vertex( draw, start + i + 3 ));
+      }
+      break;
+
+   case GL_QUAD_STRIP:
+      for (i = 0; i+3 < count; i += 2) {
+        do_quad( first,
+                 get_vertex( draw, start + i + 2 ),
+                 get_vertex( draw, start + i + 0 ),
+                 get_vertex( draw, start + i + 1 ),
+                 get_vertex( draw, start + i + 3 ));
+      }
+      break;
+
+   case GL_POLYGON:
+      if (count >= 3) {
+         int e1save, e2save;
+        prim.v[0] = 0;
+        prim.v[1] = get_vertex( draw, start + 1 );
+        prim.v[2] = get_vertex( draw, start + 0 );
+        e2save = prim.v[2]->edgeflag;
+
+        for (i = 0; i+2 < count; i++) {
+           prim.v[0] = prim.v[1];
+           prim.v[1] = get_vertex( draw, start + i + 2 );
+
+            /* save v1 edge flag, and clear if not last triangle */
+            e1save = prim.v[1]->edgeflag;
+            if (i + 3 < count)
+               prim.v[1]->edgeflag = 0;
+
+            /* draw */
+           first->tri( first, &prim );
+
+            prim.v[1]->edgeflag = e1save; /* restore */
+            prim.v[2]->edgeflag = 0; /* disable edge after 1st tri */
+        }
+         prim.v[2]->edgeflag = e2save;
+      }
+      break;
+
+   default:
+      assert(0);
+      break;
+   }
+}
+
+
+static void draw_release_vertices( struct draw_context *draw )
+{
+   draw->pipeline.first->end( draw->pipeline.first );
+
+   FREE(draw->verts);
+   draw->verts = NULL;
+}
+
+
+struct header_dword {
+   GLuint clipmask:12;
+   GLuint edgeflag:1;
+   GLuint pad:19;
+};
+
+
+static void 
+build_vertex_headers( struct draw_context *draw,
+                     struct vertex_buffer *VB )
+{
+   if (draw->header.storage == NULL) {
+      draw->header.stride = sizeof(GLfloat);
+      draw->header.size = 1;
+      draw->header.storage = ALIGN_MALLOC( VB->Size * sizeof(GLfloat), 32 );
+      draw->header.data = draw->header.storage;
+      draw->header.count = 0;
+      draw->header.flags = VEC_SIZE_1 | VEC_MALLOC;
+   }
+
+   /* Build vertex header attribute.
+    * 
+    */
+
+   {
+      GLuint i;
+      struct header_dword *header = (struct header_dword *)draw->header.storage;
+
+      /* yes its a hack
+       */
+      assert(sizeof(*header) == sizeof(GLfloat));
+
+      draw->header.count = VB->Count;
+
+      if (VB->EdgeFlag) {
+        for (i = 0; i < VB->Count; i++) {
+           header[i].clipmask = VB->ClipMask[i];
+           header[i].edgeflag = VB->EdgeFlag[i]; 
+           header[i].pad = 0;
+        }
+      }
+      else if (VB->ClipOrMask) {
+        for (i = 0; i < VB->Count; i++) {
+           header[i].clipmask = VB->ClipMask[i];
+           header[i].edgeflag = 0; 
+           header[i].pad = 0;
+        }
+      }
+      else {
+        for (i = 0; i < VB->Count; i++) {
+           header[i].clipmask = 0;
+           header[i].edgeflag = 0; 
+           header[i].pad = 0;
+        }
+      }
+   }
+
+   VB->AttribPtr[VF_ATTRIB_VERTEX_HEADER] = &draw->header;
+}
+
+
+
+
+
+static GLuint draw_prim_info(GLenum mode, GLuint *first, GLuint *incr)
+{
+   switch (mode) {
+   case GL_POINTS:
+      *first = 1;
+      *incr = 1;
+      return 0;
+   case GL_LINES:
+      *first = 2;
+      *incr = 2;
+      return 0;
+   case GL_LINE_STRIP:
+      *first = 2;
+      *incr = 1;
+      return 0;
+   case GL_LINE_LOOP:
+      *first = 2;
+      *incr = 1;
+      return 1;
+   case GL_TRIANGLES:
+      *first = 3;
+      *incr = 3;
+      return 0;
+   case GL_TRIANGLE_STRIP:
+      *first = 3;
+      *incr = 1;
+      return 0;
+   case GL_TRIANGLE_FAN:
+   case GL_POLYGON:
+      *first = 3;
+      *incr = 1;
+      return 1;
+   case GL_QUADS:
+      *first = 4;
+      *incr = 4;
+      return 0;
+   case GL_QUAD_STRIP:
+      *first = 4;
+      *incr = 2;
+      return 0;
+   default:
+      assert(0);
+      *first = 1;
+      *incr = 1;
+      return 0;
+   }
+}
+
+
+static GLuint trim( GLuint count, GLuint first, GLuint incr )
+{
+   if (count < first)
+      return 0;
+   else
+      return count - (count - first) % incr; 
+}
+
+
+/* This is a hack & will all go away.
+ */
+void draw_vb(struct draw_context *draw,
+            struct vertex_buffer *VB )
+{
+   GLuint i;
+
+   VB->AttribPtr[VF_ATTRIB_POS] = VB->NdcPtr;
+   VB->AttribPtr[VF_ATTRIB_BFC0] = VB->ColorPtr[1];
+   VB->AttribPtr[VF_ATTRIB_BFC1] = VB->SecondaryColorPtr[1];
+   VB->AttribPtr[VF_ATTRIB_CLIP_POS] = VB->ClipPtr;
+
+   /* Build vertex headers: 
+    */
+   build_vertex_headers( draw, VB );
+
+   draw->in_vb = 1;
+
+   /* Allocate the vertices:
+    */
+   draw_allocate_vertices( draw, VB->Count );
+
+   /* Bind the vb outputs:
+    */
+   vf_set_sources( draw->vf, VB->AttribPtr, 0 );
+
+   /* Build the hardware or prim-pipe vertices: 
+    */
+   vf_emit_vertices( draw->vf, VB->Count, draw->verts );
+
+
+   for (i = 0; i < VB->PrimitiveCount; i++) {
+
+      GLenum mode = VB->Primitive[i].mode;
+      GLuint start = VB->Primitive[i].start;
+      GLuint length, first, incr;
+
+      /* Trim the primitive down to a legal size.  
+       */
+      draw_prim_info( mode, &first, &incr );
+      length = trim( VB->Primitive[i].count, first, incr );
+
+      if (!length)
+        continue;
+
+      if (draw->prim != mode) 
+        draw_set_prim( draw, mode );
+
+      if (VB->Elts) {
+        draw_indexed_prim( draw, 
+                           VB->Elts + start,
+                           length );
+      }
+      else {
+        draw_prim( draw, 
+                   start,
+                   length );
+      }         
+   }
+
+   draw_release_vertices( draw );
+   draw->verts = NULL;
+   draw->in_vb = 0;
+}
+
+
+/**
+ * Accumulate another attribute's info.
+ * Note the "- 2" factor here.  We need this because the vertex->data[]
+ * array does not include the first two attributes we emit (VERTEX_HEADER
+ * and CLIP_POS).  So, the 3rd attribute actually winds up in the 1st
+ * position of the data[] array.
+ */
+#define EMIT_ATTR( VF_ATTR, STYLE )                            \
+do {                                                           \
+   if (draw->nr_attrs >= 2)                                    \
+      draw->vf_attr_to_slot[VF_ATTR] = draw->nr_attrs - 2;     \
+   draw->attrs[draw->nr_attrs].attrib = VF_ATTR;               \
+   draw->attrs[draw->nr_attrs].format = STYLE;                 \
+   draw->nr_attrs++;                                           \
+} while (0)
+
+
+/**
+ * Tell the draw module about the layout of attributes in the vertex.
+ * We need this in order to know which vertex slot has color0, etc.
+ *
+ * \param slot_to_vf_attr  an array which maps slot indexes to vertex
+ *                         format tokens (VF_*).
+ * \param nr_attrs  the size of the slot_to_vf_attr array
+ *                  (and number of attributes)
+ */
+void draw_set_vertex_attributes( struct draw_context *draw,
+                                const GLuint *slot_to_vf_attr,
+                                GLuint nr_attrs )
+{
+   GLuint i;
+
+   memset(draw->vf_attr_to_slot, 0, sizeof(draw->vf_attr_to_slot));
+   draw->nr_attrs = 0;
+
+   /*
+    * First three attribs are always the same: header, clip pos, winpos
+    */
+   EMIT_ATTR(VF_ATTRIB_VERTEX_HEADER, EMIT_1F);
+   EMIT_ATTR(VF_ATTRIB_CLIP_POS, EMIT_4F);
+
+   assert(slot_to_vf_attr[0] == VF_ATTRIB_POS);
+   EMIT_ATTR(slot_to_vf_attr[0], EMIT_4F_VIEWPORT);
+
+   /*
+    * Remaining attribs (color, texcoords, etc)
+    */
+   for (i = 1; i < nr_attrs; i++) 
+      EMIT_ATTR(slot_to_vf_attr[i], EMIT_4F);
+
+   /* tell the vertex format module how to construct vertices for us */
+   draw->vertex_size = vf_set_vertex_attributes( draw->vf, draw->attrs,
+                                                 draw->nr_attrs, 0 );
+}
+                           
+
+#define MAX_VERTEX_SIZE ((2 + FRAG_ATTRIB_MAX) * 4 * sizeof(GLfloat))
+
+void draw_alloc_tmps( struct draw_stage *stage, GLuint nr )
+{
+   stage->nr_tmps = nr;
+
+   if (nr) {
+      GLubyte *store = MALLOC(MAX_VERTEX_SIZE * nr);
+      GLuint i;
+
+      stage->tmp = MALLOC(sizeof(struct vertex_header *) * nr);
+      
+      for (i = 0; i < nr; i++)
+        stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE);
+   }
+}
+
+void draw_free_tmps( struct draw_stage *stage )
+{
+   if (stage->tmp) {
+      FREE(stage->tmp[0]);
+      FREE(stage->tmp);
+   }
+}
diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h
new file mode 100644 (file)
index 0000000..05a175c
--- /dev/null
@@ -0,0 +1,120 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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 PIPE_CONTEXT_H
+#define PIPE_CONTEXT_H
+
+#include "main/mtypes.h"
+#include "p_state.h"
+
+
+/* Kludge:
+ */
+extern struct pipe_context *softpipe_create( void );
+                                     
+/* Drawing currently kludged up via the existing tnl/ module.  
+ */
+struct vertex_buffer;
+
+
+/**
+ * Software pipeline rendering context.  Basically a collection of
+ * state setting functions, plus VBO drawing entrypoint.
+ */
+struct pipe_context {
+
+   void (*destroy)( struct pipe_context * );
+
+   /*
+    * Drawing
+    */
+   void (*draw_vb)( struct pipe_context *pipe,
+                   struct vertex_buffer *VB );
+
+   /** Clear framebuffer */
+   void (*clear)(struct pipe_context *pipe, GLboolean color, GLboolean depth,
+                 GLboolean stencil, GLboolean accum);
+
+   /** occlusion counting (XXX this may be temporary - we should probably
+    * have generic query objects with begin/end methods)
+    */
+   void (*reset_occlusion_counter)(struct pipe_context *pipe);
+   GLuint (*get_occlusion_counter)(struct pipe_context *pipe);
+
+   /*
+    * State functions
+    */
+   void (*set_alpha_test_state)( struct pipe_context *,
+                                 const struct pipe_alpha_test_state * );
+
+   void (*set_blend_state)( struct pipe_context *,
+                            const struct pipe_blend_state * );
+
+   void (*set_blend_color)( struct pipe_context *,
+                            const struct pipe_blend_color * );
+
+   void (*set_clip_state)( struct pipe_context *,
+                          const struct pipe_clip_state * );
+
+   void (*set_clear_color_state)( struct pipe_context *,
+                                  const struct pipe_clear_color_state * );
+
+   void (*set_depth_state)( struct pipe_context *,
+                              const struct pipe_depth_state * );
+
+   void (*set_framebuffer_state)( struct pipe_context *,
+                                  const struct pipe_framebuffer_state * );
+
+   void (*set_fs_state)( struct pipe_context *,
+                        const struct pipe_fs_state * );
+
+   void (*set_polygon_stipple)( struct pipe_context *,
+                               const struct pipe_poly_stipple * );
+
+   void (*set_setup_state)( struct pipe_context *,
+                           const struct pipe_setup_state * );
+
+   void (*set_scissor_state)( struct pipe_context *,
+                              const struct pipe_scissor_state * );
+
+   void (*set_stencil_state)( struct pipe_context *,
+                              const struct pipe_stencil_state * );
+
+   void (*set_sampler_state)( struct pipe_context *,
+                              GLuint unit,
+                              const struct pipe_sampler_state * );
+
+   void (*set_texture_state)( struct pipe_context *,
+                              GLuint unit,
+                              struct pipe_texture_object * );
+
+   void (*set_viewport_state)( struct pipe_context *,
+                               const struct pipe_viewport_state * );
+};
+
+
+#endif
diff --git a/src/mesa/pipe/p_defines.h b/src/mesa/pipe/p_defines.h
new file mode 100644 (file)
index 0000000..1b799f1
--- /dev/null
@@ -0,0 +1,165 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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 PIPE_DEFINES_H
+#define PIPE_DEFINES_H
+
+#define PIPE_BLENDFACTOR_ONE                 0x1
+#define PIPE_BLENDFACTOR_SRC_COLOR           0x2
+#define PIPE_BLENDFACTOR_SRC_ALPHA           0x3
+#define PIPE_BLENDFACTOR_DST_ALPHA           0x4
+#define PIPE_BLENDFACTOR_DST_COLOR           0x5
+#define PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE  0x6
+#define PIPE_BLENDFACTOR_CONST_COLOR         0x7
+#define PIPE_BLENDFACTOR_CONST_ALPHA         0x8
+#define PIPE_BLENDFACTOR_SRC1_COLOR          0x9
+#define PIPE_BLENDFACTOR_SRC1_ALPHA          0x0A
+#define PIPE_BLENDFACTOR_ZERO                0x11
+#define PIPE_BLENDFACTOR_INV_SRC_COLOR       0x12
+#define PIPE_BLENDFACTOR_INV_SRC_ALPHA       0x13
+#define PIPE_BLENDFACTOR_INV_DST_ALPHA       0x14
+#define PIPE_BLENDFACTOR_INV_DST_COLOR       0x15
+#define PIPE_BLENDFACTOR_INV_CONST_COLOR     0x17
+#define PIPE_BLENDFACTOR_INV_CONST_ALPHA     0x18
+#define PIPE_BLENDFACTOR_INV_SRC1_COLOR      0x19
+#define PIPE_BLENDFACTOR_INV_SRC1_ALPHA      0x1A
+
+#define PIPE_BLEND_ADD               0
+#define PIPE_BLEND_SUBTRACT          1
+#define PIPE_BLEND_REVERSE_SUBTRACT  2
+#define PIPE_BLEND_MIN               3
+#define PIPE_BLEND_MAX               4
+
+#define PIPE_LOGICOP_CLEAR            0
+#define PIPE_LOGICOP_NOR              1
+#define PIPE_LOGICOP_AND_INVERTED     2
+#define PIPE_LOGICOP_COPY_INVERTED    3
+#define PIPE_LOGICOP_AND_REVERSE      4
+#define PIPE_LOGICOP_INVERT           5
+#define PIPE_LOGICOP_XOR              6
+#define PIPE_LOGICOP_NAND             7
+#define PIPE_LOGICOP_AND              8
+#define PIPE_LOGICOP_EQUIV            9
+#define PIPE_LOGICOP_NOOP             10
+#define PIPE_LOGICOP_OR_INVERTED      11
+#define PIPE_LOGICOP_COPY             12
+#define PIPE_LOGICOP_OR_REVERSE       13
+#define PIPE_LOGICOP_OR               14
+#define PIPE_LOGICOP_SET              15  
+
+#define PIPE_MASK_R  0x1
+#define PIPE_MASK_G  0x2
+#define PIPE_MASK_B  0x4
+#define PIPE_MASK_A  0x8
+
+/**
+ * Inequality functions.  Used for depth test, stencil compare, alpha
+ * test, shadow compare, etc.
+ */
+#define PIPE_FUNC_NEVER    0
+#define PIPE_FUNC_LESS     1
+#define PIPE_FUNC_EQUAL    2
+#define PIPE_FUNC_LEQUAL   3
+#define PIPE_FUNC_GREATER  4
+#define PIPE_FUNC_NOTEQUAL 5
+#define PIPE_FUNC_GEQUAL   6
+#define PIPE_FUNC_ALWAYS   7
+
+/** Polygon fill mode */
+#define PIPE_POLYGON_MODE_FILL  0
+#define PIPE_POLYGON_MODE_LINE  1
+#define PIPE_POLYGON_MODE_POINT 2
+
+/** Polygon front/back window, also for culling */
+#define PIPE_WINDING_NONE 0
+#define PIPE_WINDING_CW   1
+#define PIPE_WINDING_CCW  2
+#define PIPE_WINDING_BOTH (PIPE_WINDING_CW | PIPE_WINDING_CCW)
+
+/** Stencil ops */
+#define PIPE_STENCIL_OP_KEEP       0
+#define PIPE_STENCIL_OP_ZERO       1
+#define PIPE_STENCIL_OP_REPLACE    2
+#define PIPE_STENCIL_OP_INCR       3
+#define PIPE_STENCIL_OP_DECR       4
+#define PIPE_STENCIL_OP_INCR_WRAP  5
+#define PIPE_STENCIL_OP_DECR_WRAP  6
+#define PIPE_STENCIL_OP_INVERT     7
+
+#define PIPE_TEX_WRAP_REPEAT                   0
+#define PIPE_TEX_WRAP_CLAMP                    1
+#define PIPE_TEX_WRAP_CLAMP_TO_EDGE            2
+#define PIPE_TEX_WRAP_CLAMP_TO_BORDER          3
+#define PIPE_TEX_WRAP_MIRROR_REPEAT            4
+#define PIPE_TEX_WRAP_MIRROR_CLAMP             5
+#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE     6
+#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER   7
+
+#define PIPE_TEX_FILTER_NEAREST                0
+#define PIPE_TEX_FILTER_LINEAR                 1
+#define PIPE_TEX_FILTER_NEAREST_MIPMAP_NEAREST 2
+#define PIPE_TEX_FILTER_NEAREST_MIPMAP_LINEAR  3
+#define PIPE_TEX_FILTER_LINEAR_MIPMAP_NEAREST  4
+#define PIPE_TEX_FILTER_LINEAR_MIPMAP_LINEAR   5
+
+#define PIPE_TEX_COMPARE_NONE          0
+#define PIPE_TEX_COMPARE_R_TO_TEXTURE  1
+
+/**
+ * Texture/surface image formats (preliminary)
+ */
+#define PIPE_FORMAT_U_R8_G8_B8_A8   0  /**< ubyte[4] RGBA */
+#define PIPE_FORMAT_U_A8_R8_G8_B8   1  /**< ubyte[4] ARGB */
+#define PIPE_FORMAT_U_R5_G6_B5      2  /**< 5/6/5 RGB */
+#define PIPE_FORMAT_U_L8            3  /**< ubyte luminance */
+#define PIPE_FORMAT_U_A8            4  /**< ubyte alpha */
+#define PIPE_FORMAT_U_I8            5  /**< ubyte intensity */
+#define PIPE_FORMAT_U_L8_A8         6  /**< ubyte luminance, alpha */
+#define PIPE_FORMAT_U_Z16           7  /**< ushort Z/depth */
+#define PIPE_FORMAT_F_Z32           8  /**< float Z/depth */
+#define PIPE_FORMAT_YCBCR           9
+#define PIPE_FORMAT_YCBCR_REV      10
+#define PIPE_FORMAT_U_S8           11  /**< 8-bit stencil */
+#define PIPE_FORMAT_Z24_S8         12  /**< 24-bit Z + 8-bit stencil */
+
+
+/**
+ * Texture typess
+ */
+#define PIPE_TEXTURE_1D   0
+#define PIPE_TEXTURE_2D   1
+#define PIPE_TEXTURE_3D   2
+#define PIPE_TEXTURE_CUBE 3
+
+/**
+ * Buffer mapping access modes
+ */
+#define PIPE_MAP_READ         1
+#define PIPE_MAP_WRITE        2
+#define PIPE_MAP_READ_WRITE   3
+
+#endif
diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h
new file mode 100644 (file)
index 0000000..4ae8928
--- /dev/null
@@ -0,0 +1,301 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+
+/**
+ * Abstract graphics pipe state objects.
+ *
+ * Basic notes:
+ *   1. Want compact representations, so we use bitfields.
+ *   2. Put bitfields before other (GLfloat) fields.
+ */
+
+
+#ifndef PIPE_STATE_H
+#define PIPE_STATE_H
+
+#include "mtypes.h"
+
+
+
+/**
+ * Implementation limits
+ */
+#define PIPE_MAX_SAMPLERS     8
+#define PIPE_MAX_CLIP_PLANES  6
+#define PIPE_MAX_CONSTANT    32
+#define PIPE_ATTRIB_MAX      32
+#define PIPE_MAX_COLOR_BUFS   8
+
+
+/* fwd decl */
+struct pipe_surface;
+
+
+/***
+ *** State objects
+ ***/
+
+
+/**
+ * Primitive (point/line/tri) setup info
+ */
+struct pipe_setup_state
+{
+   GLuint flatshade:1;
+   GLuint light_twoside:1;
+
+   GLuint front_winding:2;  /**< PIPE_WINDING_x */
+
+   GLuint cull_mode:2;      /**< PIPE_WINDING_x */
+
+   GLuint fill_cw:2;        /**< PIPE_POLYGON_MODE_x */
+   GLuint fill_ccw:2;       /**< PIPE_POLYGON_MODE_x */
+
+   GLuint offset_cw:1;
+   GLuint offset_ccw:1;
+
+   GLuint scissor:1;
+
+   GLuint poly_smooth:1;
+   GLuint poly_stipple_enable:1;
+
+   GLuint line_smooth:1;
+   GLuint line_stipple_enable:1;
+
+   GLuint point_smooth:1;
+
+   GLuint multisample:1;         /* XXX maybe more ms state in future */
+
+   GLubyte line_stipple_factor;  /**< [1..256] actually */
+   GLushort line_stipple_pattern;
+   GLfloat line_width;
+   GLfloat point_size;           /**< used when no per-vertex size */
+   GLfloat offset_units;
+   GLfloat offset_scale;
+};
+
+struct pipe_poly_stipple {
+   GLuint stipple[32];
+};
+
+
+struct pipe_viewport_state {
+   GLfloat scale[4];
+   GLfloat translate[4];
+};
+
+struct pipe_scissor_state {
+   GLshort minx;
+   GLshort miny;
+   GLshort maxx;
+   GLshort maxy;
+};
+
+struct pipe_clip_state {
+   GLfloat ucp[PIPE_MAX_CLIP_PLANES][4];
+   GLuint nr;
+};
+
+
+struct pipe_constant_buffer {
+   GLfloat constant[PIPE_MAX_CONSTANT][4];
+   GLuint nr_constants;
+};
+
+
+struct pipe_fs_state {
+   GLbitfield inputs_read;             /* FRAG_ATTRIB_* */
+   const struct tgsi_token *tokens;
+   struct pipe_constant_buffer *constants; /* XXX temporary? */
+};
+
+struct pipe_depth_state
+{
+   GLuint enabled:1;   /**< depth test enabled? */
+   GLuint writemask:1; /**< allow depth buffer writes? */
+   GLuint func:3;      /**< depth test func (PIPE_FUNC_x) */
+   GLuint occlusion_count:1; /**< XXX move this elsewhere? */
+   GLfloat clear;      /**< Clear value in [0,1] (XXX correct place?) */
+};
+
+struct pipe_alpha_test_state {
+   GLuint enabled:1;
+   GLuint func:3;    /**< PIPE_FUNC_x */
+   GLfloat ref;      /**< reference value */
+};
+
+struct pipe_blend_state {
+   GLuint blend_enable:1;
+
+   GLuint rgb_func:3;          /**< PIPE_BLEND_x */
+   GLuint rgb_src_factor:5;    /**< PIPE_BLENDFACTOR_x */
+   GLuint rgb_dst_factor:5;    /**< PIPE_BLENDFACTOR_x */
+
+   GLuint alpha_func:3;        /**< PIPE_BLEND_x */
+   GLuint alpha_src_factor:5;  /**< PIPE_BLENDFACTOR_x */
+   GLuint alpha_dst_factor:5;  /**< PIPE_BLENDFACTOR_x */
+
+   GLuint logicop_enable:1;
+   GLuint logicop_func:4;      /**< PIPE_LOGICOP_x */
+
+   GLuint colormask:4;         /**< bitmask of PIPE_MASK_R/G/B/A */
+   GLuint dither:1;
+};
+
+struct pipe_blend_color {
+   GLfloat color[4];
+};
+
+struct pipe_clear_color_state
+{
+   GLfloat color[4];
+};
+
+struct pipe_stencil_state {
+   GLuint front_enabled:1;
+   GLuint front_func:3;     /**< PIPE_FUNC_x */
+   GLuint front_fail_op:3;  /**< PIPE_STENCIL_OP_x */
+   GLuint front_zpass_op:3; /**< PIPE_STENCIL_OP_x */
+   GLuint front_zfail_op:3; /**< PIPE_STENCIL_OP_x */
+   GLuint back_enabled:1;
+   GLuint back_func:3;      /**< PIPE_FUNC_x */
+   GLuint back_fail_op:3;   /**< PIPE_STENCIL_OP_x */
+   GLuint back_zpass_op:3;  /**< PIPE_STENCIL_OP_x */
+   GLuint back_zfail_op:3;  /**< PIPE_STENCIL_OP_x */
+   GLubyte ref_value[2];    /**< [0] = front, [1] = back */
+   GLubyte value_mask[2];
+   GLubyte write_mask[2];
+   GLubyte clear_value;
+};
+
+
+struct pipe_framebuffer_state
+{
+   /** multiple colorbuffers for multiple render targets */
+   GLuint num_cbufs;
+   struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS];
+
+   struct pipe_surface *zbuf;      /**< Z buffer */
+   struct pipe_surface *sbuf;      /**< Stencil buffer */
+   struct pipe_surface *abuf;      /**< Accum buffer */
+};
+
+
+/**
+ * Texture sampler state.
+ */
+struct pipe_sampler_state
+{
+   GLuint wrap_s:3;        /**< PIPE_TEX_WRAP_x */
+   GLuint wrap_t:3;        /**< PIPE_TEX_WRAP_x */
+   GLuint wrap_r:3;        /**< PIPE_TEX_WRAP_x */
+   GLuint min_filter:3;    /**< PIPE_TEX_FILTER_x */
+   GLuint mag_filter:1;    /**< PIPE_TEX_FILTER_LINEAR or _NEAREST */
+   GLuint compare:1;       /**< shadow/depth compare enabled? */
+   GLenum compare_mode:1;  /**< PIPE_TEX_COMPARE_x */
+   GLenum compare_func:3;  /**< PIPE_FUNC_x */
+   GLfloat shadow_ambient; /**< shadow test fail color/intensity */
+   GLfloat min_lod;
+   GLfloat max_lod;
+   GLfloat lod_bias;
+#if 0 /* need these? */
+   GLint BaseLevel;     /**< min mipmap level, OpenGL 1.2 */
+   GLint MaxLevel;      /**< max mipmap level, OpenGL 1.2 */
+   GLfloat border_color[4];
+#endif
+   GLfloat max_anisotropy;
+};
+
+
+/***
+ *** Non-state Objects
+ ***/
+
+
+/**
+ * A mappable buffer (vertex data, pixel data, etc)
+ */
+struct pipe_buffer
+{
+   void (*buffer_data)(struct pipe_buffer *pb, GLuint size, const void *src);
+   void (*buffer_sub_data)(struct pipe_buffer *pb, GLuint offset, GLuint size,
+                           const void *src);
+   void *(*map)(struct pipe_buffer *pb, GLuint access_mode);
+   void (*unmap)(struct pipe_buffer *pb);
+   void *ptr;        /**< address, only valid while mapped */
+   GLuint mode;      /**< PIPE_MAP_x, only valid while mapped */
+};
+
+
+/**
+ * 2D surface.
+ * May be a renderbuffer, texture mipmap level, etc.
+ */
+struct pipe_surface
+{
+   struct pipe_buffer buffer;  /**< surfaces can be mapped */
+   GLuint format:5;            /**< PIPE_FORMAT_x */
+   GLuint width, height;
+#if 0
+   GLubyte *ptr;
+   GLint stride;
+   GLuint cpp;
+   GLuint format;
+#endif
+};
+
+
+/**
+ * Texture object.
+ * Mipmap levels, cube faces, 3D slices can be accessed as surfaces.
+ */
+struct pipe_texture_object
+{
+   GLuint type:2;      /**< PIPE_TEXTURE_x */
+   GLuint format:5;    /**< PIPE_FORMAT_x */
+   GLuint width:13;    /**< 13 bits = 8K max size */
+   GLuint height:13;
+   GLuint depth:13;
+   GLuint mipmapped:1;
+
+   /** to access a 1D or 2D texture object as a surface */
+   struct pipe_surface *(*get_2d_surface)(struct pipe_texture_object *pto,
+                                          GLuint level);
+   /** to access a 3D texture object as a surface */
+   struct pipe_surface *(*get_3d_surface)(struct pipe_texture_object *pto,
+                                          GLuint level, GLuint slice);
+   /** to access a cube texture object as a surface */
+   struct pipe_surface *(*get_cube_surface)(struct pipe_texture_object *pto,
+                                            GLuint face, GLuint level);
+   /** when finished with surface: */
+   void (*release_surface)(struct pipe_texture_object *pto,
+                           struct pipe_surface *ps);
+};
+
+
+#endif
diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile
new file mode 100644 (file)
index 0000000..12a8bd0
--- /dev/null
@@ -0,0 +1,3 @@
+default:
+       cd ../.. ; make
+
diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c
new file mode 100644 (file)
index 0000000..e83bc05
--- /dev/null
@@ -0,0 +1,71 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Author:
+ *    Brian Paul
+ */
+
+
+#include "sp_clear.h"
+#include "sp_context.h"
+#include "sp_surface.h"
+#include "colormac.h"
+
+
+void
+softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth,
+               GLboolean stencil, GLboolean accum)
+{
+   const struct softpipe_context *softpipe = softpipe_context(pipe);
+   const GLint x = softpipe->scissor.minx;
+   const GLint y = softpipe->scissor.miny;
+   const GLint w = softpipe->scissor.maxx - x;
+   const GLint h = softpipe->scissor.maxy - y;
+
+   if (color) {
+      GLuint i;
+      GLubyte clr[4];
+
+      UNCLAMPED_FLOAT_TO_UBYTE(clr[0], softpipe->clear_color.color[0]);
+      UNCLAMPED_FLOAT_TO_UBYTE(clr[1], softpipe->clear_color.color[1]);
+      UNCLAMPED_FLOAT_TO_UBYTE(clr[2], softpipe->clear_color.color[2]);
+      UNCLAMPED_FLOAT_TO_UBYTE(clr[3], softpipe->clear_color.color[3]);
+
+      for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) {
+         struct pipe_surface *ps = softpipe->framebuffer.cbufs[i];
+         struct softpipe_surface *sps = softpipe_surface(ps);
+         GLint j;
+         for (j = 0; j < h; j++) {
+            sps->write_mono_row_ub(sps, w, x, y + j, clr);
+         }
+      }
+   }
+
+   if (depth) {
+   }
+
+}
diff --git a/src/mesa/pipe/softpipe/sp_clear.h b/src/mesa/pipe/softpipe/sp_clear.h
new file mode 100644 (file)
index 0000000..f9db99d
--- /dev/null
@@ -0,0 +1,43 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Author:
+ *    Brian Paul
+ */
+
+#ifndef SP_CLEAR_H
+#define SP_CLEAR_H
+
+#include "pipe/p_state.h"
+struct pipe_context;
+
+extern void
+softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth,
+               GLboolean stencil, GLboolean accum);
+
+
+#endif /* SP_CLEAR_H */
diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c
new file mode 100644 (file)
index 0000000..3bb04a6
--- /dev/null
@@ -0,0 +1,126 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Author:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/imports.h"
+#include "main/macros.h"
+#include "pipe/draw/draw_context.h"
+#include "sp_context.h"
+#include "sp_clear.h"
+#include "sp_state.h"
+#include "sp_prim_setup.h"
+
+
+static void softpipe_destroy( struct pipe_context *pipe )
+{
+   struct softpipe_context *softpipe = softpipe_context( pipe );
+
+   draw_destroy( softpipe->draw );
+
+   free( softpipe );
+}
+
+
+static void softpipe_draw_vb( struct pipe_context *pipe,
+                            struct vertex_buffer *VB )
+{
+   struct softpipe_context *softpipe = softpipe_context( pipe );
+
+   if (softpipe->dirty)
+      softpipe_update_derived( softpipe );
+
+   draw_vb( softpipe->draw, VB );
+}
+
+
+static void softpipe_reset_occlusion_counter(struct pipe_context *pipe)
+{
+   struct softpipe_context *softpipe = softpipe_context( pipe );
+   softpipe->occlusion_counter = 0;
+}
+
+/* XXX pipe param should be const */
+static GLuint softpipe_get_occlusion_counter(struct pipe_context *pipe)
+{
+   struct softpipe_context *softpipe = softpipe_context( pipe );
+   return softpipe->occlusion_counter;
+}
+
+
+struct pipe_context *softpipe_create( void )
+{
+   struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
+
+   softpipe->pipe.destroy = softpipe_destroy;
+   softpipe->pipe.set_alpha_test_state = softpipe_set_alpha_test_state;
+   softpipe->pipe.set_blend_color = softpipe_set_blend_color;
+   softpipe->pipe.set_blend_state = softpipe_set_blend_state;
+   softpipe->pipe.set_clip_state = softpipe_set_clip_state;
+   softpipe->pipe.set_clear_color_state = softpipe_set_clear_color_state;
+   softpipe->pipe.set_depth_state = softpipe_set_depth_test_state;
+   softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
+   softpipe->pipe.set_fs_state = softpipe_set_fs_state;
+   softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple;
+   softpipe->pipe.set_sampler_state = softpipe_set_sampler_state;
+   softpipe->pipe.set_scissor_state = softpipe_set_scissor_state;
+   softpipe->pipe.set_setup_state = softpipe_set_setup_state;
+   softpipe->pipe.set_stencil_state = softpipe_set_stencil_state;
+   softpipe->pipe.set_texture_state = softpipe_set_texture_state;
+   softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
+   softpipe->pipe.draw_vb = softpipe_draw_vb;
+   softpipe->pipe.clear = softpipe_clear;
+   softpipe->pipe.reset_occlusion_counter = softpipe_reset_occlusion_counter;
+   softpipe->pipe.get_occlusion_counter = softpipe_get_occlusion_counter;
+
+   softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe);
+   softpipe->quad.shade = sp_quad_shade_stage(softpipe);
+   softpipe->quad.alpha_test = sp_quad_alpha_test_stage(softpipe);
+   softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
+   softpipe->quad.stencil_test = sp_quad_stencil_test_stage(softpipe);
+   softpipe->quad.occlusion = sp_quad_occlusion_stage(softpipe);
+   softpipe->quad.coverage = sp_quad_coverage_stage(softpipe);
+   softpipe->quad.bufloop = sp_quad_bufloop_stage(softpipe);
+   softpipe->quad.blend = sp_quad_blend_stage(softpipe);
+   softpipe->quad.colormask = sp_quad_colormask_stage(softpipe);
+   softpipe->quad.output = sp_quad_output_stage(softpipe);
+
+   /*
+    * Create drawing context and plug our rendering stage into it.
+    */
+   softpipe->draw = draw_create();
+   draw_set_setup_stage(softpipe->draw, sp_draw_render_stage(softpipe));
+
+   /*
+    * XXX we could plug GL selection/feedback into the drawing pipeline
+    * by specifying a different setup/render stage.
+    */
+
+   return &softpipe->pipe;
+}
diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h
new file mode 100644 (file)
index 0000000..8871b45
--- /dev/null
@@ -0,0 +1,157 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_CONTEXT_H
+#define SP_CONTEXT_H
+
+#include "glheader.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+
+#include "sp_quad.h"
+
+
+struct softpipe_surface;
+struct draw_context;
+struct draw_stage;
+
+
+enum interp_mode {
+   INTERP_CONSTANT, 
+   INTERP_LINEAR, 
+   INTERP_PERSPECTIVE
+};
+
+
+#define SP_NEW_VIEWPORT      0x1
+#define SP_NEW_SETUP         0x2
+#define SP_NEW_FS            0x4
+#define SP_NEW_BLEND         0x8
+#define SP_NEW_CLIP         0x10
+#define SP_NEW_SCISSOR      0x20
+#define SP_NEW_STIPPLE      0x40
+#define SP_NEW_FRAMEBUFFER  0x80
+#define SP_NEW_ALPHA_TEST  0x100
+#define SP_NEW_DEPTH_TEST  0x200
+#define SP_NEW_SAMPLER     0x400
+#define SP_NEW_TEXTURE     0x800
+#define SP_NEW_STENCIL    0x1000
+
+
+struct softpipe_context {     
+   struct pipe_context pipe;  /**< base class */
+
+   /* The most recent drawing state as set by the driver:
+    */
+   struct pipe_alpha_test_state alpha_test;
+   struct pipe_blend_state blend;
+   struct pipe_blend_color blend_color;
+   struct pipe_clear_color_state clear_color;
+   struct pipe_clip_state clip;
+   struct pipe_depth_state depth_test;
+   struct pipe_framebuffer_state framebuffer;
+   struct pipe_fs_state fs;
+   struct pipe_poly_stipple poly_stipple;
+   struct pipe_scissor_state scissor;
+   struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
+   struct pipe_setup_state setup;
+   struct pipe_stencil_state stencil;
+   struct pipe_texture_object *texture[PIPE_MAX_SAMPLERS];
+   struct pipe_viewport_state viewport;
+   GLuint dirty;
+
+   /* Setup derived state.  TODO: this should be passed in the program
+    * tokens as parameters to DECL instructions.
+    * 
+    * For now we just set colors to CONST on flatshade, textures to
+    * perspective always and everything else to linear.
+    */
+   enum interp_mode interp[PIPE_ATTRIB_MAX];
+
+
+   /* FS + setup derived state:
+    */
+
+   /** Map fragment program attribute to quad/coef array slot */
+   GLuint fp_attr_to_slot[PIPE_ATTRIB_MAX];
+   /** Map vertex format attribute to a vertex attribute slot */
+   GLuint vf_attr_to_slot[PIPE_ATTRIB_MAX];
+   GLuint nr_attrs;
+   GLuint nr_frag_attrs;  /**< number of active fragment attribs */
+   GLbitfield attr_mask;  /**< bitfield of VF_ATTRIB_ indexes/bits */
+
+   GLboolean need_z;  /**< produce quad/fragment Z values? */
+   GLboolean need_w;  /**< produce quad/fragment W values? */
+
+#if 0
+   /* Stipple derived state:
+    */
+   GLubyte stipple_masks[16][16];
+#endif
+
+   GLuint occlusion_counter;
+
+   GLuint line_stipple_counter;
+
+   /** Software quad rendering pipeline */
+   struct {
+      struct quad_stage *polygon_stipple;
+      struct quad_stage *shade;
+      struct quad_stage *alpha_test;
+      struct quad_stage *stencil_test;
+      struct quad_stage *depth_test;
+      struct quad_stage *occlusion;
+      struct quad_stage *coverage;
+      struct quad_stage *bufloop;
+      struct quad_stage *blend;
+      struct quad_stage *colormask;
+      struct quad_stage *output;
+
+      struct quad_stage *first; /**< points to one of the above stages */
+   } quad;
+
+   /** The primitive drawing context */
+   struct draw_context *draw;
+
+   struct pipe_surface *cbuf;      /**< current color buffer (one of cbufs) */
+};
+
+
+
+
+static INLINE struct softpipe_context *
+softpipe_context( struct pipe_context *pipe )
+{
+   return (struct softpipe_context *)pipe;
+}
+
+
+#endif /* SP_CONTEXT_H */
diff --git a/src/mesa/pipe/softpipe/sp_headers.h b/src/mesa/pipe/softpipe/sp_headers.h
new file mode 100644 (file)
index 0000000..68a8462
--- /dev/null
@@ -0,0 +1,95 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_HEADERS_H
+#define SP_HEADERS_H
+
+
+#define PRIM_POINT 1
+#define PRIM_LINE  2
+#define PRIM_TRI   3
+
+
+/* The rasterizer generates 2x2 quads of fragment and feeds them to
+ * the current fp_machine (see below).  
+ */
+#define QUAD_BOTTOM_LEFT  0
+#define QUAD_BOTTOM_RIGHT 1
+#define QUAD_TOP_LEFT     2
+#define QUAD_TOP_RIGHT    3
+#define QUAD_SIZE        (2*2)
+
+#define MASK_BOTTOM_LEFT  0x1
+#define MASK_BOTTOM_RIGHT 0x2
+#define MASK_TOP_LEFT     0x4
+#define MASK_TOP_RIGHT    0x8
+#define MASK_ALL          0xf
+
+
+#define NUM_CHANNELS   4       /* avoid confusion between 4 pixels and 4 channels */
+
+
+struct setup_coefficient {
+   GLfloat a0[NUM_CHANNELS];   /* in an xyzw layout */
+   GLfloat dadx[NUM_CHANNELS];
+   GLfloat dady[NUM_CHANNELS];
+};
+
+
+
+/**
+ * Encodes everything we need to know about a 2x2 pixel block.  Uses
+ * "Channel-Serial" or "SoA" layout.  
+ */
+struct quad_header {
+   GLint x0;
+   GLint y0;
+   GLuint mask:4;
+   GLuint facing:1;   /**< Front (0) or back (1) facing? */
+   GLuint prim:2;     /**< PRIM_POINT, LINE, TRI */
+
+   struct {
+      GLfloat color[4][QUAD_SIZE];     /* rrrr, gggg, bbbb, aaaa */
+      GLfloat depth[QUAD_SIZE];
+   } outputs;
+
+   GLfloat coverage[QUAD_SIZE];    /** fragment coverage for antialiasing */
+
+   const struct setup_coefficient *coef;
+
+   const enum interp_mode *interp; /* XXX: this information should be
+                                   * encoded in fragment program DECL
+                                   * statements. */
+
+   GLuint nr_attrs;
+};
+
+
+#endif /* SP_HEADERS_H */
diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c
new file mode 100644 (file)
index 0000000..091a234
--- /dev/null
@@ -0,0 +1,1039 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  Primitive rasterization/rendering (points, lines, triangles)
+ *
+ * \author  Keith Whitwell <keith@tungstengraphics.com>
+ * \author  Brian Paul
+ */
+
+
+#include "imports.h"
+#include "macros.h"
+
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "pipe/draw/draw_private.h"
+#include "sp_quad.h"
+#include "sp_prim_setup.h"
+
+
+
+/**
+ * Emit/render a quad.
+ * This passes the quad to the first stage of per-fragment operations.
+ */
+static INLINE void
+quad_emit(struct softpipe_context *sp, struct quad_header *quad)
+{
+   sp->quad.first->run(sp->quad.first, quad);
+}
+
+
+/**
+ * Triangle edge info
+ */
+struct edge {
+   GLfloat dx;                 /* X(v1) - X(v0), used only during setup */
+   GLfloat dy;                 /* Y(v1) - Y(v0), used only during setup */
+   GLfloat dxdy;               /* dx/dy */
+   GLfloat sx;                 /* first sample point x coord */
+   GLfloat sy;
+   GLint lines;                        /* number of lines  on this edge */
+};
+
+
+/**
+ * Triangle setup info (derived from draw_stage).
+ * Also used for line drawing (taking some liberties).
+ */
+struct setup_stage {
+   struct draw_stage stage; /**< This must be first (base class) */
+
+   /*XXX NEW */
+   struct softpipe_context *softpipe;
+
+   /* Vertices are just an array of floats making up each attribute in
+    * turn.  Currently fixed at 4 floats, but should change in time.
+    * Codegen will help cope with this.
+    */
+   const struct vertex_header *vmax;
+   const struct vertex_header *vmid;
+   const struct vertex_header *vmin;
+   const struct vertex_header *vprovoke;
+
+   struct edge ebot;
+   struct edge etop;
+   struct edge emaj;
+
+   GLfloat oneoverarea;
+
+   struct setup_coefficient coef[FRAG_ATTRIB_MAX];
+   struct quad_header quad; 
+
+   struct {
+      GLint left[2];   /**< [0] = row0, [1] = row1 */
+      GLint right[2];
+      GLint y;
+      GLuint y_flags;
+      GLuint mask;     /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
+   } span;
+};
+
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static inline struct setup_stage *setup_stage( struct draw_stage *stage )
+{
+   return (struct setup_stage *)stage;
+}
+
+
+/**
+ * Given an X or Y coordinate, return the block/quad coordinate that it
+ * belongs to.
+ */
+static inline GLint block( GLint x )
+{
+   return x & ~1;
+}
+
+
+
+/**
+ * Run shader on a quad/block.
+ */
+static void run_shader_block( struct setup_stage *setup, 
+                             GLint x, GLint y, GLuint mask )
+{
+   setup->quad.x0 = x;
+   setup->quad.y0 = y;
+   setup->quad.mask = mask;
+
+   quad_emit(setup->softpipe, &setup->quad);
+}
+
+
+/**
+ * Compute mask which indicates which pixels in the 2x2 quad are actually inside
+ * the triangle's bounds.
+ *
+ * this is pretty nasty...  may need to rework flush_spans again to
+ * fix it, if possible.
+ */
+static GLuint calculate_mask( struct setup_stage *setup,
+                           GLint x )
+{
+   GLuint mask = 0;
+
+   if (x >= setup->span.left[0] && x < setup->span.right[0]) 
+      mask |= MASK_BOTTOM_LEFT;
+
+   if (x >= setup->span.left[1] && x < setup->span.right[1]) 
+      mask |= MASK_TOP_LEFT;
+      
+   if (x+1 >= setup->span.left[0] && x+1 < setup->span.right[0]) 
+      mask |= MASK_BOTTOM_RIGHT;
+
+   if (x+1 >= setup->span.left[1] && x+1 < setup->span.right[1]) 
+      mask |= MASK_TOP_RIGHT;
+
+   return mask;
+}
+
+
+/**
+ * Render a horizontal span of quads
+ */
+static void flush_spans( struct setup_stage *setup )
+{
+   GLint minleft, maxright;
+   GLint x;
+
+   switch (setup->span.y_flags) {      
+   case 3:
+      minleft = MIN2(setup->span.left[0], setup->span.left[1]);
+      maxright = MAX2(setup->span.right[0], setup->span.right[1]);
+      break;
+
+   case 1:
+      minleft = setup->span.left[0];
+      maxright = setup->span.right[0];
+      break;
+
+   case 2:
+      minleft = setup->span.left[1];
+      maxright = setup->span.right[1];
+      break;
+
+   default:
+      return;
+   }
+
+
+   for (x = block(minleft); x <= block(maxright); )
+   {
+      run_shader_block( setup, x,
+                       setup->span.y, 
+                       calculate_mask( setup, x ) );
+      x += 2;
+   }
+
+   setup->span.y = 0;
+   setup->span.y_flags = 0;
+   setup->span.right[0] = 0;
+   setup->span.right[1] = 0;
+}
+
+
+static GLboolean setup_sort_vertices( struct setup_stage *setup,
+                                     const struct prim_header *prim )
+{
+   const struct vertex_header *v0 = prim->v[0];
+   const struct vertex_header *v1 = prim->v[1];
+   const struct vertex_header *v2 = prim->v[2];
+
+   setup->vprovoke = v2;
+
+   /* determine bottom to top order of vertices */
+   {
+      GLfloat y0 = v0->data[0][1];
+      GLfloat y1 = v1->data[0][1];
+      GLfloat y2 = v2->data[0][1];
+      if (y0 <= y1) {
+        if (y1 <= y2) {
+           /* y0<=y1<=y2 */
+           setup->vmin = v0;   
+           setup->vmid = v1;   
+           setup->vmax = v2;
+        }
+        else if (y2 <= y0) {
+           /* y2<=y0<=y1 */
+           setup->vmin = v2;   
+           setup->vmid = v0;   
+           setup->vmax = v1;   
+        }
+        else {
+           /* y0<=y2<=y1 */
+           setup->vmin = v0;   
+           setup->vmid = v2;   
+           setup->vmax = v1;  
+        }
+      }
+      else {
+        if (y0 <= y2) {
+           /* y1<=y0<=y2 */
+           setup->vmin = v1;   
+           setup->vmid = v0;   
+           setup->vmax = v2;  
+        }
+        else if (y2 <= y1) {
+           /* y2<=y1<=y0 */
+           setup->vmin = v2;   
+           setup->vmid = v1;   
+           setup->vmax = v0;  
+        }
+        else {
+           /* y1<=y2<=y0 */
+           setup->vmin = v1;   
+           setup->vmid = v2;   
+           setup->vmax = v0;
+        }
+      }
+   }
+
+   setup->ebot.dx = setup->vmid->data[0][0] - setup->vmin->data[0][0];
+   setup->ebot.dy = setup->vmid->data[0][1] - setup->vmin->data[0][1];
+   setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
+   setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
+   setup->etop.dx = setup->vmax->data[0][0] - setup->vmid->data[0][0];
+   setup->etop.dy = setup->vmax->data[0][1] - setup->vmid->data[0][1];
+
+   /*
+    * Compute triangle's area.  Use 1/area to compute partial
+    * derivatives of attributes later.
+    *
+    * The area will be the same as prim->det, but the sign may be
+    * different depending on how the vertices get sorted above.
+    *
+    * To determine whether the primitive is front or back facing we
+    * use the prim->det value because its sign is correct.
+    */
+   {
+      const GLfloat area = (setup->emaj.dx * setup->ebot.dy - 
+                           setup->ebot.dx * setup->emaj.dy);
+
+      setup->oneoverarea = 1.0 / area;
+      /*
+      _mesa_printf("%s one-over-area %f  area %f  det %f\n",
+                   __FUNCTION__, setup->oneoverarea, area, prim->det );
+      */
+   }
+
+   /* We need to know if this is a front or back-facing triangle for:
+    *  - the GLSL gl_FrontFacing fragment attribute (bool)
+    *  - two-sided stencil test
+    */
+   setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->setup.front_winding == PIPE_WINDING_CW);
+
+   return GL_TRUE;
+}
+
+
+/**
+ * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
+ * The value value comes from vertex->data[slot][i].
+ * The result will be put into setup->coef[slot].a0[i].
+ * \param slot  which attribute slot 
+ * \param i  which component of the slot (0..3)
+ */
+static void const_coeff( struct setup_stage *setup,
+                        GLuint slot,
+                        GLuint i )
+{
+   assert(slot < FRAG_ATTRIB_MAX);
+   assert(i <= 3);
+
+   setup->coef[slot].dadx[i] = 0;
+   setup->coef[slot].dady[i] = 0;
+
+   /* need provoking vertex info!
+    */
+   setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i];
+}
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a triangle.
+ */
+static void tri_linear_coeff( struct setup_stage *setup,
+                              GLuint slot,
+                              GLuint i)
+{
+   GLfloat botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
+   GLfloat majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
+   GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+   GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+   
+   assert(slot < FRAG_ATTRIB_MAX);
+   assert(i <= 3);
+
+   setup->coef[slot].dadx[i] = a * setup->oneoverarea;
+   setup->coef[slot].dady[i] = b * setup->oneoverarea;
+
+   /* calculate a0 as the value which would be sampled for the
+    * fragment at (0,0), taking into account that we want to sample at
+    * pixel centers, in other words (0.5, 0.5).
+    *
+    * this is neat but unfortunately not a good way to do things for
+    * triangles with very large values of dadx or dady as it will
+    * result in the subtraction and re-addition from a0 of a very
+    * large number, which means we'll end up loosing a lot of the
+    * fractional bits and precision from a0.  the way to fix this is
+    * to define a0 as the sample at a pixel center somewhere near vmin
+    * instead - i'll switch to this later.
+    */
+   setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] - 
+                           (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) + 
+                            setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
+
+   /*
+   _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
+               slot, "xyzw"[i], 
+               setup->coef[slot].a0[i],
+               setup->coef[slot].dadx[i],
+               setup->coef[slot].dady[i]);
+   */
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a triangle.
+ */
+static void tri_persp_coeff( struct setup_stage *setup,
+                             GLuint slot,
+                             GLuint i )
+{
+   /* premultiply by 1/w:
+    */
+   GLfloat mina = setup->vmin->data[slot][i] * setup->vmin->data[0][3];
+   GLfloat mida = setup->vmid->data[slot][i] * setup->vmid->data[0][3];
+   GLfloat maxa = setup->vmax->data[slot][i] * setup->vmax->data[0][3];
+
+   GLfloat botda = mida - mina;
+   GLfloat majda = maxa - mina;
+   GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+   GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+      
+   assert(slot < FRAG_ATTRIB_MAX);
+   assert(i <= 3);
+
+   setup->coef[slot].dadx[i] = a * setup->oneoverarea;
+   setup->coef[slot].dady[i] = b * setup->oneoverarea;
+   setup->coef[slot].a0[i] = (mina - 
+                           (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) + 
+                            setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
+}
+
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
+ */
+static void setup_tri_coefficients( struct setup_stage *setup )
+{
+   const enum interp_mode *interp = setup->softpipe->interp;
+   GLuint slot, j;
+
+   /* z and w are done by linear interpolation:
+    */
+   tri_linear_coeff(setup, 0, 2);
+   tri_linear_coeff(setup, 0, 3);
+
+   /* setup interpolation for all the remaining attributes:
+    */
+   for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
+      switch (interp[slot]) {
+      case INTERP_CONSTANT:
+        for (j = 0; j < NUM_CHANNELS; j++)
+           const_coeff(setup, slot, j);
+        break;
+      
+      case INTERP_LINEAR:
+        for (j = 0; j < NUM_CHANNELS; j++)
+           tri_linear_coeff(setup, slot, j);
+        break;
+
+      case INTERP_PERSPECTIVE:
+        for (j = 0; j < NUM_CHANNELS; j++)
+           tri_persp_coeff(setup, slot, j);
+        break;
+      }
+   }
+}
+
+
+
+static void setup_tri_edges( struct setup_stage *setup )
+{
+   GLfloat vmin_x = setup->vmin->data[0][0] + 0.5;
+   GLfloat vmid_x = setup->vmid->data[0][0] + 0.5;
+
+   GLfloat vmin_y = setup->vmin->data[0][1] - 0.5;
+   GLfloat vmid_y = setup->vmid->data[0][1] - 0.5;
+   GLfloat vmax_y = setup->vmax->data[0][1] - 0.5;
+
+   setup->emaj.sy = ceilf(vmin_y);
+   setup->emaj.lines = (GLint) ceilf(vmax_y - setup->emaj.sy);
+   setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy;
+   setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
+
+   setup->etop.sy = ceilf(vmid_y);
+   setup->etop.lines = (GLint) ceilf(vmax_y - setup->etop.sy);
+   setup->etop.dxdy = setup->etop.dx / setup->etop.dy;
+   setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
+
+   setup->ebot.sy = ceilf(vmin_y);
+   setup->ebot.lines = (GLint) ceilf(vmid_y - setup->ebot.sy);
+   setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy;
+   setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
+}
+
+
+/**
+ * Render the upper or lower half of a triangle.
+ * Scissoring is applied here too.
+ */
+static void subtriangle( struct setup_stage *setup,
+                        struct edge *eleft,
+                        struct edge *eright,
+                        GLuint lines )
+{
+   GLint y, start_y, finish_y;
+   GLint sy = (GLint)eleft->sy;
+
+   assert((GLint)eleft->sy == (GLint) eright->sy);
+   assert((GLint)eleft->sy >= 0);      /* catch bug in x64? */
+
+   /* scissor y:
+    */
+   if (setup->softpipe->setup.scissor) {
+      start_y = sy;
+      finish_y = start_y + lines;
+
+      if (start_y < setup->softpipe->scissor.miny) 
+        start_y = setup->softpipe->scissor.miny;
+
+      if (finish_y > setup->softpipe->scissor.maxy) 
+        finish_y = setup->softpipe->scissor.maxy;
+
+      start_y -= sy;
+      finish_y -= sy;
+   }
+   else {
+      start_y = 0;
+      finish_y = lines;
+   }
+
+   /*
+   _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);  
+   */
+
+   for (y = start_y; y < finish_y; y++) {
+
+      /* avoid accumulating adds as floats don't have the precision to
+       * accurately iterate large triangle edges that way.  luckily we
+       * can just multiply these days.
+       *
+       * this is all drowned out by the attribute interpolation anyway.
+       */
+      GLint left = (GLint)(eleft->sx + y * eleft->dxdy);
+      GLint right = (GLint)(eright->sx + y * eright->dxdy);
+
+      /* scissor x: 
+       */
+      if (setup->softpipe->setup.scissor) {
+        if (left  < setup->softpipe->scissor.minx) 
+           left  = setup->softpipe->scissor.minx;
+
+        if (right > setup->softpipe->scissor.maxx) 
+           right = setup->softpipe->scissor.maxx;
+      }
+
+      if (left < right) {
+        GLint _y = sy+y;
+        if (block(_y) != setup->span.y) {
+           flush_spans(setup);
+           setup->span.y = block(_y);
+        }
+   
+        setup->span.left[_y&1] = left;
+        setup->span.right[_y&1] = right;
+        setup->span.y_flags |= 1<<(_y&1);
+      }
+   } 
+
+
+   /* save the values so that emaj can be restarted:
+    */
+   eleft->sx += lines * eleft->dxdy;
+   eright->sx += lines * eright->dxdy;
+   eleft->sy += lines;
+   eright->sy += lines;
+}
+
+
+/**
+ * Do setup for triangle rasterization, then render the triangle.
+ */
+static void setup_tri( struct draw_stage *stage,
+                      struct prim_header *prim )
+{
+   struct setup_stage *setup = setup_stage( stage );
+
+   /*
+   _mesa_printf("%s\n", __FUNCTION__ );
+   */
+
+   setup_sort_vertices( setup, prim );
+   setup_tri_coefficients( setup );
+   setup_tri_edges( setup );
+
+   setup->quad.prim = PRIM_TRI;
+
+   setup->span.y = 0;
+   setup->span.y_flags = 0;
+   setup->span.right[0] = 0;
+   setup->span.right[1] = 0;
+   /*   setup->span.z_mode = tri_z_mode( setup->ctx ); */
+
+   /*   init_constant_attribs( setup ); */
+      
+   if (setup->oneoverarea < 0.0) {
+      /* emaj on left:
+       */
+      subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
+      subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
+   }
+   else {
+      /* emaj on right:
+       */
+      subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
+      subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
+   }
+
+   flush_spans( setup );
+}
+
+
+
+/**
+ * Compute a0, dadx and dady for a linearly interpolated coefficient,
+ * for a line.
+ */
+static void
+line_linear_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
+{
+   const GLfloat dz = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
+   const GLfloat dadx = dz * setup->emaj.dx * setup->oneoverarea;
+   const GLfloat dady = dz * setup->emaj.dy * setup->oneoverarea;
+   setup->coef[slot].dadx[i] = dadx;
+   setup->coef[slot].dady[i] = dady;
+   setup->coef[slot].a0[i]
+      = (setup->vmin->data[slot][i] - 
+         (dadx * (setup->vmin->data[0][0] - 0.5) + 
+          dady * (setup->vmin->data[0][1] - 0.5)));
+}
+
+
+/**
+ * Compute a0, dadx and dady for a perspective-corrected interpolant,
+ * for a line.
+ */
+static void
+line_persp_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
+{
+   /* XXX to do */
+   line_linear_coeff(setup, slot, i); /* XXX temporary */
+}
+
+
+/**
+ * Compute the setup->coef[] array dadx, dady, a0 values.
+ * Must be called after setup->vmin,vmax are initialized.
+ */
+static INLINE void
+setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
+{
+   const enum interp_mode *interp = setup->softpipe->interp;
+   GLuint slot, j;
+
+   /* use setup->vmin, vmax to point to vertices */
+   setup->vprovoke = prim->v[1];
+   setup->vmin = prim->v[0];
+   setup->vmax = prim->v[1];
+
+   setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
+   setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
+   /* NOTE: this is not really 1/area */
+   setup->oneoverarea = 1.0 / (setup->emaj.dx * setup->emaj.dx +
+                               setup->emaj.dy * setup->emaj.dy);
+
+   /* z and w are done by linear interpolation:
+    */
+   line_linear_coeff(setup, 0, 2);
+   line_linear_coeff(setup, 0, 3);
+
+   /* setup interpolation for all the remaining attributes:
+    */
+   for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
+      switch (interp[slot]) {
+      case INTERP_CONSTANT:
+        for (j = 0; j < NUM_CHANNELS; j++)
+           const_coeff(setup, slot, j);
+        break;
+      
+      case INTERP_LINEAR:
+        for (j = 0; j < NUM_CHANNELS; j++)
+           line_linear_coeff(setup, slot, j);
+        break;
+
+      case INTERP_PERSPECTIVE:
+        for (j = 0; j < NUM_CHANNELS; j++)
+           line_persp_coeff(setup, slot, j);
+        break;
+      }
+   }
+}
+
+
+/**
+ * Plot a pixel in a line segment.
+ */
+static INLINE void
+plot(struct setup_stage *setup, GLint x, GLint y)
+{
+   const GLint iy = y & 1;
+   const GLint ix = x & 1;
+   const GLint quadX = x - ix;
+   const GLint quadY = y - iy;
+   const GLint mask = (1 << ix) << (2 * iy);
+
+   if (quadX != setup->quad.x0 || 
+       quadY != setup->quad.y0) 
+   {
+      /* flush prev quad, start new quad */
+
+      if (setup->quad.x0 != -1) 
+        quad_emit(setup->softpipe, &setup->quad);
+
+      setup->quad.x0 = quadX;
+      setup->quad.y0 = quadY;
+      setup->quad.mask = 0x0;
+   }
+
+   setup->quad.mask |= mask;
+}
+
+
+/**
+ * Determine whether or not to emit a line fragment by checking
+ * line stipple pattern.
+ */
+static INLINE GLuint
+stipple_test(GLint counter, GLushort pattern, GLint factor)
+{
+   GLint b = (counter / factor) & 0xf;
+   return (1 << b) & pattern;
+}
+
+
+/**
+ * Do setup for line rasterization, then render the line.
+ * XXX single-pixel width, no stipple, etc
+ * XXX no scissoring yet.
+ */
+static void
+setup_line(struct draw_stage *stage, struct prim_header *prim)
+{
+   const struct vertex_header *v0 = prim->v[0];
+   const struct vertex_header *v1 = prim->v[1];
+   struct setup_stage *setup = setup_stage( stage );
+   struct softpipe_context *sp = setup->softpipe;
+
+   GLint x0 = (GLint) v0->data[0][0];
+   GLint x1 = (GLint) v1->data[0][0];
+   GLint y0 = (GLint) v0->data[0][1];
+   GLint y1 = (GLint) v1->data[0][1];
+   GLint dx = x1 - x0;
+   GLint dy = y1 - y0;
+   GLint xstep, ystep;
+
+   if (dx == 0 && dy == 0)
+      return;
+
+   setup_line_coefficients(setup, prim);
+
+   if (dx < 0) {
+      dx = -dx;   /* make positive */
+      xstep = -1;
+   }
+   else {
+      xstep = 1;
+   }
+
+   if (dy < 0) {
+      dy = -dy;   /* make positive */
+      ystep = -1;
+   }
+   else {
+      ystep = 1;
+   }
+
+   assert(dx >= 0);
+   assert(dy >= 0);
+
+   setup->quad.x0 = setup->quad.y0 = -1;
+   setup->quad.mask = 0x0;
+   setup->quad.prim = PRIM_LINE;
+
+   if (dx > dy) {
+      /*** X-major line ***/
+      GLint i;
+      const GLint errorInc = dy + dy;
+      GLint error = errorInc - dx;
+      const GLint errorDec = error - dx;
+
+      for (i = 0; i < dx; i++) {
+         if (!sp->setup.line_stipple_enable ||
+             stipple_test(sp->line_stipple_counter,
+                          sp->setup.line_stipple_pattern,
+                          sp->setup.line_stipple_factor + 1)) {
+             plot(setup, x0, y0);
+         }
+
+         x0 += xstep;
+         if (error < 0) {
+            error += errorInc;
+         }
+         else {
+            error += errorDec;
+            y0 += ystep;
+         }
+
+         sp->line_stipple_counter++;
+      }
+   }
+   else {
+      /*** Y-major line ***/
+      GLint i;
+      const GLint errorInc = dx + dx;
+      GLint error = errorInc - dy;
+      const GLint errorDec = error - dy;
+
+      for (i = 0; i < dy; i++) {
+         if (!sp->setup.line_stipple_enable ||
+             stipple_test(sp->line_stipple_counter,
+                          sp->setup.line_stipple_pattern,
+                          sp->setup.line_stipple_factor + 1)) {
+            plot(setup, x0, y0);
+         }
+
+         y0 += ystep;
+
+         if (error < 0) {
+            error += errorInc;
+         }
+         else {
+            error += errorDec;
+            x0 += xstep;
+         }
+
+         sp->line_stipple_counter++;
+      }
+   }
+
+   /* draw final quad */
+   if (setup->quad.mask) {
+      quad_emit(setup->softpipe, &setup->quad);
+   }
+}
+
+
+/**
+ * Do setup for point rasterization, then render the point.
+ * Round or square points...
+ * XXX could optimize a lot for 1-pixel points.
+ */
+static void
+setup_point(struct draw_stage *stage, struct prim_header *prim)
+{
+   struct setup_stage *setup = setup_stage( stage );
+   /*XXX this should be a vertex attrib! */
+   GLfloat halfSize = 0.5 * setup->softpipe->setup.point_size;
+   GLboolean round = setup->softpipe->setup.point_smooth;
+   const struct vertex_header *v0 = prim->v[0];
+   const GLfloat x = v0->data[FRAG_ATTRIB_WPOS][0];
+   const GLfloat y = v0->data[FRAG_ATTRIB_WPOS][1];
+   GLuint slot, j;
+
+   /* For points, all interpolants are constant-valued.
+    * However, for point sprites, we'll need to setup texcoords appropriately.
+    * XXX: which coefficients are the texcoords???
+    * We may do point sprites as textured quads...
+    *
+    * KW: We don't know which coefficients are texcoords - ultimately
+    * the choice of what interpolation mode to use for each attribute
+    * should be determined by the fragment program, using
+    * per-attribute declaration statements that include interpolation
+    * mode as a parameter.  So either the fragment program will have
+    * to be adjusted for pointsprite vs normal point behaviour, or
+    * otherwise a special interpolation mode will have to be defined
+    * which matches the required behaviour for point sprites.  But -
+    * the latter is not a feature of normal hardware, and as such
+    * probably should be ruled out on that basis.
+    */
+   setup->vprovoke = prim->v[0];
+   const_coeff(setup, 0, 2);
+   const_coeff(setup, 0, 3);
+   for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
+      for (j = 0; j < NUM_CHANNELS; j++)
+         const_coeff(setup, slot, j);
+   }
+
+   setup->quad.prim = PRIM_POINT;
+
+   /* XXX need to clip against scissor bounds too */
+
+   if (halfSize <= 0.5 && !round) {
+      /* special case for 1-pixel points */
+      const GLint ix = ((GLint) x) & 1;
+      const GLint iy = ((GLint) y) & 1;
+      setup->quad.x0 = x - ix;
+      setup->quad.y0 = y - iy;
+      setup->quad.mask = (1 << ix) << (2 * iy);
+      quad_emit(setup->softpipe, &setup->quad);
+   }
+   else {
+      const GLint ixmin = block((GLint) (x - halfSize));
+      const GLint ixmax = block((GLint) (x + halfSize));
+      const GLint iymin = block((GLint) (y - halfSize));
+      const GLint iymax = block((GLint) (y + halfSize));
+      GLint ix, iy;
+
+      if (round) {
+         /* rounded points */
+         const GLfloat rmin = halfSize - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
+         const GLfloat rmax = halfSize + 0.7071F;
+         const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
+         const GLfloat rmax2 = rmax * rmax;
+         const GLfloat cscale = 1.0F / (rmax2 - rmin2);
+
+         for (iy = iymin; iy <= iymax; iy += 2) {
+            for (ix = ixmin; ix <= ixmax; ix += 2) {
+               GLfloat dx, dy, dist2, cover;
+
+               setup->quad.mask = 0x0;
+
+               dx = (ix + 0.5) - x;
+               dy = (iy + 0.5) - y;
+               dist2 = dx * dx + dy * dy;
+               if (dist2 <= rmax2) {
+                  cover = 1.0F - (dist2 - rmin2) * cscale;
+                  setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0);
+                  setup->quad.mask |= MASK_BOTTOM_LEFT;
+               }
+
+               dx = (ix + 1.5) - x;
+               dy = (iy + 0.5) - y;
+               dist2 = dx * dx + dy * dy;
+               if (dist2 <= rmax2) {
+                  cover = 1.0F - (dist2 - rmin2) * cscale;
+                  setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0);
+                  setup->quad.mask |= MASK_BOTTOM_RIGHT;
+               }
+
+               dx = (ix + 0.5) - x;
+               dy = (iy + 1.5) - y;
+               dist2 = dx * dx + dy * dy;
+               if (dist2 <= rmax2) {
+                  cover = 1.0F - (dist2 - rmin2) * cscale;
+                  setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0);
+                  setup->quad.mask |= MASK_TOP_LEFT;
+               }
+
+               dx = (ix + 1.5) - x;
+               dy = (iy + 1.5) - y;
+               dist2 = dx * dx + dy * dy;
+               if (dist2 <= rmax2) {
+                  cover = 1.0F - (dist2 - rmin2) * cscale;
+                  setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0);
+                  setup->quad.mask |= MASK_TOP_RIGHT;
+               }
+
+               if (setup->quad.mask) {
+                  setup->quad.x0 = ix;
+                  setup->quad.y0 = iy;
+                  quad_emit( setup->softpipe, &setup->quad );
+               }
+            }
+         }
+      }
+      else {
+         /* square points */
+         for (iy = iymin; iy <= iymax; iy += 2) {
+            for (ix = ixmin; ix <= ixmax; ix += 2) {
+               setup->quad.mask = 0xf;
+
+               if (ix + 0.5 < x - halfSize) {
+                  /* fragment is past left edge of point, turn off left bits */
+                  setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
+               }
+
+               if (ix + 1.5 > x + halfSize) {
+                  /* past the right edge */
+                  setup->quad.mask &= ~(MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
+               }
+
+               if (iy + 0.5 < y - halfSize) {
+                  /* below the bottom edge */
+                  setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
+               }
+
+               if (iy + 1.5 > y + halfSize) {
+                  /* above the top edge */
+                  setup->quad.mask &= ~(MASK_TOP_LEFT | MASK_TOP_RIGHT);
+               }
+
+               if (setup->quad.mask) {
+                  setup->quad.x0 = ix;
+                  setup->quad.y0 = iy;
+                  quad_emit( setup->softpipe, &setup->quad );
+               }
+            }
+         }
+      }
+   }
+}
+
+
+
+static void setup_begin( struct draw_stage *stage )
+{
+   struct setup_stage *setup = setup_stage(stage);
+
+   setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs;
+
+   /*
+    * XXX this is where we might map() the renderbuffers to begin
+    * s/w rendering.
+    */
+}
+
+
+static void setup_end( struct draw_stage *stage )
+{
+   /*
+    * XXX this is where we might unmap() the renderbuffers after
+    * s/w rendering.
+    */
+}
+
+
+static void reset_stipple_counter( struct draw_stage *stage )
+{
+   struct setup_stage *setup = setup_stage(stage);
+   setup->softpipe->line_stipple_counter = 0;
+}
+
+
+/**
+ * Create a new primitive setup/render stage.
+ */
+struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe )
+{
+   struct setup_stage *setup = CALLOC_STRUCT(setup_stage);
+
+   setup->softpipe = softpipe;
+   setup->stage.draw = softpipe->draw;
+   setup->stage.begin = setup_begin;
+   setup->stage.point = setup_point;
+   setup->stage.line = setup_line;
+   setup->stage.tri = setup_tri;
+   setup->stage.end = setup_end;
+   setup->stage.reset_stipple_counter = reset_stipple_counter;
+
+   setup->quad.coef = setup->coef;
+
+   return &setup->stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.h b/src/mesa/pipe/softpipe/sp_prim_setup.h
new file mode 100644 (file)
index 0000000..e5abefc
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  Brian Paul   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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL 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 SP_PRIM_SETUP_H
+#define SP_PRIM_SETUP_H
+
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed.  We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#if 0
+#include "s_tri_public.h"
+#endif
+#include "s_context.h"
+
+
+extern struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe );
+
+
+#if 0 /* UNUSED? */
+struct tri_context;
+struct fp_context;
+struct be_context;
+
+/* Note the rasterizer does not take a GLcontext argument.  This is
+ * deliberate.
+ */
+struct tri_context *tri_create_context( GLcontext *ctx );
+
+void tri_destroy_context( struct tri_context *tri );
+
+void tri_set_fp_context( struct tri_context *tri,
+                        struct fp_context *fp,
+                        void (*fp_run)( struct fp_context *fp,
+                                        const struct fp_inputs *,
+                                        struct fp_outputs * ));
+
+
+void tri_set_be_context( struct tri_context *tri,
+                        struct be_context *be,
+                        void (*be_run)( struct be_context *be,
+                                        const struct fp_outputs * ));
+
+void tri_set_attribs( struct tri_context *tri,
+                     const struct attr_info *info,
+                     GLuint nr_attrib );
+
+void tri_set_backface( struct tri_context *tri,
+                      GLfloat backface );
+                                              
+void tri_set_scissor( struct tri_context *tri,
+                     GLint x,
+                     GLint y,
+                     GLuint width,
+                     GLuint height,
+                     GLboolean enabled );
+
+void tri_set_stipple( struct tri_context *tri,
+                     const GLuint *pattern,
+                     GLboolean enabled );
+
+/* Unfilled triangles will be handled elsewhere (higher in the
+ * pipeline), as will things like stipple (lower in the pipeline).
+ */
+
+void tri_triangle( struct tri_context *tri,
+                  const struct vertex *v0,
+                  const struct vertex *v1,
+                  const struct vertex *v2 );
+
+/* TODO: rasterize_line, rasterize_point?? 
+ * How will linestipple work?
+ */
+
+
+#ifdef SETUP_PRIVATE
+
+GLboolean tri_setup( struct tri_context *tri,
+                      const struct vertex *v0,
+                      const struct vertex *v1,
+                      const struct vertex *v2 );
+
+void tri_rasterize( struct tri_context *tri );
+void tri_rasterize_spans( struct tri_context *tri );
+
+#endif
+
+
+#endif
+
+#endif /* SP_PRIM_SETUP_H */
diff --git a/src/mesa/pipe/softpipe/sp_quad.c b/src/mesa/pipe/softpipe/sp_quad.c
new file mode 100644 (file)
index 0000000..0053b16
--- /dev/null
@@ -0,0 +1,71 @@
+
+
+#include "sp_context.h"
+
+
+
+void
+sp_build_quad_pipeline(struct softpipe_context *sp)
+{
+   /* build up the pipeline in reverse order... */
+
+   sp->quad.first = sp->quad.output;
+
+   if (sp->blend.colormask != 0xf) {
+      sp->quad.colormask->next = sp->quad.first;
+      sp->quad.first = sp->quad.colormask;
+   }
+
+   if (sp->blend.blend_enable) {
+      sp->quad.blend->next = sp->quad.first;
+      sp->quad.first = sp->quad.blend;
+   }
+
+   if (sp->framebuffer.num_cbufs == 1) {
+      /* the usual case: write to exactly one colorbuf */
+      sp->cbuf = sp->framebuffer.cbufs[0];
+   }
+   else {
+      /* insert bufloop stage */
+      sp->quad.bufloop->next = sp->quad.first;
+      sp->quad.first = sp->quad.bufloop;
+   }
+
+   if (sp->depth_test.occlusion_count) {
+      sp->quad.occlusion->next = sp->quad.first;
+      sp->quad.first = sp->quad.occlusion;
+   }
+
+   if (sp->setup.poly_smooth ||
+       sp->setup.line_smooth ||
+       sp->setup.point_smooth) {
+      sp->quad.coverage->next = sp->quad.first;
+      sp->quad.first = sp->quad.coverage;
+   }
+
+   if (   sp->stencil.front_enabled
+       || sp->stencil.front_enabled) {
+      sp->quad.stencil_test->next = sp->quad.first;
+      sp->quad.first = sp->quad.stencil_test;
+   }
+   else if (sp->depth_test.enabled) {
+      sp->quad.depth_test->next = sp->quad.first;
+      sp->quad.first = sp->quad.depth_test;
+   }
+
+   if (sp->alpha_test.enabled) {
+      sp->quad.alpha_test->next = sp->quad.first;
+      sp->quad.first = sp->quad.alpha_test;
+   }
+
+   /* XXX always enable shader? */
+   if (1) {
+      sp->quad.shade->next = sp->quad.first;
+      sp->quad.first = sp->quad.shade;
+   }
+
+   if (sp->setup.poly_stipple_enable) {
+      sp->quad.polygon_stipple->next = sp->quad.first;
+      sp->quad.first = sp->quad.polygon_stipple;
+   }
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad.h b/src/mesa/pipe/softpipe/sp_quad.h
new file mode 100644 (file)
index 0000000..2ee53bd
--- /dev/null
@@ -0,0 +1,65 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_TILE_H
+#define SP_TILE_H
+
+
+struct softpipe_context;
+struct quad_header;
+
+
+struct quad_stage {
+   struct softpipe_context *softpipe;
+
+   struct quad_stage *next;
+
+   /** the stage action */
+   void (*run)(struct quad_stage *qs, struct quad_header *quad);
+};
+
+
+struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe );
+struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe );
+
+void sp_build_quad_pipeline(struct softpipe_context *sp);
+
+void sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
+
+#endif /* SP_TILE_H */
diff --git a/src/mesa/pipe/softpipe/sp_quad_alpha_test.c b/src/mesa/pipe/softpipe/sp_quad_alpha_test.c
new file mode 100644 (file)
index 0000000..8c28a82
--- /dev/null
@@ -0,0 +1,94 @@
+
+/**
+ * quad alpha test
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+#include "pipe/p_defines.h"
+
+
+static void
+alpha_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   const GLfloat ref = softpipe->alpha_test.ref;
+   GLuint passMask = 0x0, j;
+
+   switch (softpipe->alpha_test.func) {
+   case PIPE_FUNC_NEVER:
+      quad->mask = 0x0;
+      break;
+   case PIPE_FUNC_LESS:
+      /*
+       * If mask were an array [4] we could do this SIMD-style:
+       * passMask = (quad->outputs.color[3] <= vec4(ref));
+       */
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (quad->outputs.color[3][j] < ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_EQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (quad->outputs.color[3][j] == ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_LEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (quad->outputs.color[3][j] <= ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_GREATER:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (quad->outputs.color[3][j] > ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_NOTEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (quad->outputs.color[3][j] != ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_GEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (quad->outputs.color[3][j] >= ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_ALWAYS:
+      passMask = MASK_ALL;
+      break;
+   default:
+      abort();
+   }
+
+   quad->mask &= passMask;
+
+   if (quad->mask)
+      qs->next->run(qs->next, quad);
+}
+
+
+struct quad_stage *
+sp_quad_alpha_test_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = alpha_test_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_blend.c b/src/mesa/pipe/softpipe/sp_quad_blend.c
new file mode 100644 (file)
index 0000000..3d097ae
--- /dev/null
@@ -0,0 +1,395 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * quad blending
+ * \author Brian Paul
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "macros.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+#define VEC4_COPY(DST, SRC) \
+do { \
+    DST[0] = SRC[0]; \
+    DST[1] = SRC[1]; \
+    DST[2] = SRC[2]; \
+    DST[3] = SRC[3]; \
+} while(0)
+
+#define VEC4_SCALAR(DST, SRC) \
+do { \
+    DST[0] = SRC; \
+    DST[1] = SRC; \
+    DST[2] = SRC; \
+    DST[3] = SRC; \
+} while(0)
+
+#define VEC4_ADD(SUM, A, B) \
+do { \
+   SUM[0] = A[0] + B[0]; \
+   SUM[1] = A[1] + B[1]; \
+   SUM[2] = A[2] + B[2]; \
+   SUM[3] = A[3] + B[3]; \
+} while (0)
+
+#define VEC4_SUB(SUM, A, B) \
+do { \
+   SUM[0] = A[0] - B[0]; \
+   SUM[1] = A[1] - B[1]; \
+   SUM[2] = A[2] - B[2]; \
+   SUM[3] = A[3] - B[3]; \
+} while (0)
+
+#define VEC4_MUL(SUM, A, B) \
+do { \
+   SUM[0] = A[0] * B[0]; \
+   SUM[1] = A[1] * B[1]; \
+   SUM[2] = A[2] * B[2]; \
+   SUM[3] = A[3] * B[3]; \
+} while (0)
+
+#define VEC4_MIN(SUM, A, B) \
+do { \
+   SUM[0] = (A[0] < B[0]) ? A[0] : B[0]; \
+   SUM[1] = (A[1] < B[1]) ? A[1] : B[1]; \
+   SUM[2] = (A[2] < B[2]) ? A[2] : B[2]; \
+   SUM[3] = (A[3] < B[3]) ? A[3] : B[3]; \
+} while (0)
+
+#define VEC4_MAX(SUM, A, B) \
+do { \
+   SUM[0] = (A[0] > B[0]) ? A[0] : B[0]; \
+   SUM[1] = (A[1] > B[1]) ? A[1] : B[1]; \
+   SUM[2] = (A[2] > B[2]) ? A[2] : B[2]; \
+   SUM[3] = (A[3] > B[3]) ? A[3] : B[3]; \
+} while (0)
+
+
+
+static void
+blend_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   static const GLfloat zero[4] = { 0, 0, 0, 0 };
+   static const GLfloat one[4] = { 1, 1, 1, 1 };
+   struct softpipe_context *softpipe = qs->softpipe;
+   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
+   GLfloat source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
+   
+   /* get colors from framebuffer */
+   sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest);
+
+   /*
+    * Compute src/first term RGB
+    */
+   switch (softpipe->blend.rgb_src_factor) {
+   case PIPE_BLENDFACTOR_ONE:
+      VEC4_COPY(source[0], quad->outputs.color[0]); /* R */
+      VEC4_COPY(source[1], quad->outputs.color[1]); /* G */
+      VEC4_COPY(source[2], quad->outputs.color[2]); /* B */
+      break;
+   case PIPE_BLENDFACTOR_SRC_COLOR:
+      VEC4_MUL(source[0], quad->outputs.color[0], quad->outputs.color[0]); /* R */
+      VEC4_MUL(source[1], quad->outputs.color[1], quad->outputs.color[1]); /* G */
+      VEC4_MUL(source[2], quad->outputs.color[2], quad->outputs.color[2]); /* B */
+      break;
+   case PIPE_BLENDFACTOR_SRC_ALPHA:
+      {
+         const GLfloat *alpha = quad->outputs.color[3];
+         VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */
+         VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */
+         VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_DST_COLOR:
+      VEC4_MUL(source[0], quad->outputs.color[0], dest[0]); /* R */
+      VEC4_MUL(source[1], quad->outputs.color[1], dest[1]); /* G */
+      VEC4_MUL(source[2], quad->outputs.color[2], dest[2]); /* B */
+      break;
+   case PIPE_BLENDFACTOR_DST_ALPHA:
+      {
+         const GLfloat *alpha = dest[3];
+         VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */
+         VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */
+         VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+      assert(0); /* to do */
+      break;
+   case PIPE_BLENDFACTOR_CONST_COLOR:
+      {
+         GLfloat comp[4];
+         VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
+         VEC4_MUL(source[0], quad->outputs.color[0], comp); /* R */
+         VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
+         VEC4_MUL(source[1], quad->outputs.color[1], comp); /* G */
+         VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
+         VEC4_MUL(source[2], quad->outputs.color[2], comp); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_CONST_ALPHA:
+      {
+         GLfloat alpha[4];
+         VEC4_SCALAR(alpha, softpipe->blend_color.color[3]);
+         VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */
+         VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */
+         VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_SRC1_COLOR:
+      assert(0); /* to do */
+      break;
+   case PIPE_BLENDFACTOR_SRC1_ALPHA:
+      assert(0); /* to do */
+      break;
+   case PIPE_BLENDFACTOR_ZERO:
+      VEC4_COPY(source[0], zero); /* R */
+      VEC4_COPY(source[1], zero); /* G */
+      VEC4_COPY(source[2], zero); /* B */
+      break;
+   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+      {
+         GLfloat inv_comp[4];
+         VEC4_SUB(inv_comp, one, quad->outputs.color[0]); /* R */
+         VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); /* R */
+         VEC4_SUB(inv_comp, one, quad->outputs.color[1]); /* G */
+         VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); /* G */
+         VEC4_SUB(inv_comp, one, quad->outputs.color[2]); /* B */
+         VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+      {
+         GLfloat inv_alpha[4];
+         VEC4_SUB(inv_alpha, one, quad->outputs.color[3]);
+         VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */
+         VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */
+         VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+      {
+         GLfloat inv_alpha[4];
+         VEC4_SUB(inv_alpha, one, dest[3]);
+         VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */
+         VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */
+         VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_INV_DST_COLOR:
+      {
+         GLfloat inv_comp[4];
+         VEC4_SUB(inv_comp, one, dest[0]); /* R */
+         VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); /* R */
+         VEC4_SUB(inv_comp, one, dest[1]); /* G */
+         VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); /* G */
+         VEC4_SUB(inv_comp, one, dest[2]); /* B */
+         VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+      {
+         GLfloat inv_comp[4];
+         /* R */
+         VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[0]);
+         VEC4_MUL(source[0], quad->outputs.color[0], inv_comp);
+         /* G */
+         VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[1]);
+         VEC4_MUL(source[1], quad->outputs.color[1], inv_comp);
+         /* B */
+         VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[2]);
+         VEC4_MUL(source[2], quad->outputs.color[2], inv_comp);
+      }
+      break;
+   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+      {
+         GLfloat alpha[4], inv_alpha[4];
+         VEC4_SCALAR(alpha, 1.0 - softpipe->blend_color.color[3]);
+         VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */
+         VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */
+         VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+      assert(0); /* to do */
+      break;
+   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+      assert(0); /* to do */
+      break;
+   default:
+      abort();
+   }
+   
+   /*
+    * Compute src/first term A
+    */
+   switch (softpipe->blend.alpha_src_factor) {
+   case PIPE_BLENDFACTOR_ONE:
+      VEC4_COPY(source[3], quad->outputs.color[3]); /* A */
+      break;
+   case PIPE_BLENDFACTOR_SRC_ALPHA:
+      {
+         const GLfloat *alpha = quad->outputs.color[3];
+         VEC4_MUL(source[3], quad->outputs.color[3], alpha); /* A */
+      }
+      break;
+   case PIPE_BLENDFACTOR_ZERO:
+      VEC4_COPY(source[3], zero); /* A */
+      break;
+      /* XXX fill in remaining terms */
+   default:
+      abort();
+   }
+   
+   
+   /*
+    * Compute dest/second term RGB
+    */
+   switch (softpipe->blend.rgb_dst_factor) {
+   case PIPE_BLENDFACTOR_ONE:
+      /* dest = dest * 1   NO-OP, leave dest as-is */
+      break;
+   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+      {
+         GLfloat one_minus_alpha[QUAD_SIZE];
+         VEC4_SUB(one_minus_alpha, one, quad->outputs.color[3]);
+         VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
+         VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
+         VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
+      }
+      break;
+   case PIPE_BLENDFACTOR_ZERO:
+      VEC4_COPY(dest[0], zero); /* R */
+      VEC4_COPY(dest[1], zero); /* G */
+      VEC4_COPY(dest[2], zero); /* B */
+      break;
+      /* XXX fill in remaining terms */
+   default:
+      abort();
+   }
+   
+   /*
+    * Compute dest/second term A
+    */
+   switch (softpipe->blend.alpha_dst_factor) {
+   case PIPE_BLENDFACTOR_ONE:
+      /* dest = dest * 1   NO-OP, leave dest as-is */
+      break;
+   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+      {
+         GLfloat one_minus_alpha[QUAD_SIZE];
+         VEC4_SUB(one_minus_alpha, one, quad->outputs.color[3]);
+         VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
+      }
+      break;
+   case PIPE_BLENDFACTOR_ZERO:
+      VEC4_COPY(dest[3], zero); /* A */
+      break;
+      /* XXX fill in remaining terms */
+   default:
+      abort();
+   }
+   
+   /*
+    * Combine RGB terms
+    */
+   switch (softpipe->blend.rgb_func) {
+   case PIPE_BLEND_ADD:
+      VEC4_ADD(quad->outputs.color[0], source[0], dest[0]); /* R */
+      VEC4_ADD(quad->outputs.color[1], source[1], dest[1]); /* G */
+      VEC4_ADD(quad->outputs.color[2], source[2], dest[2]); /* B */
+      break;
+   case PIPE_BLEND_SUBTRACT:
+      VEC4_SUB(quad->outputs.color[0], source[0], dest[0]); /* R */
+      VEC4_SUB(quad->outputs.color[1], source[1], dest[1]); /* G */
+      VEC4_SUB(quad->outputs.color[2], source[2], dest[2]); /* B */
+      break;
+   case PIPE_BLEND_REVERSE_SUBTRACT:
+      VEC4_SUB(quad->outputs.color[0], dest[0], source[0]); /* R */
+      VEC4_SUB(quad->outputs.color[1], dest[1], source[1]); /* G */
+      VEC4_SUB(quad->outputs.color[2], dest[2], source[2]); /* B */
+      break;
+   case PIPE_BLEND_MIN:
+      VEC4_MIN(quad->outputs.color[0], source[0], dest[0]); /* R */
+      VEC4_MIN(quad->outputs.color[1], source[1], dest[1]); /* G */
+      VEC4_MIN(quad->outputs.color[2], source[2], dest[2]); /* B */
+      break;
+   case PIPE_BLEND_MAX:
+      VEC4_MAX(quad->outputs.color[0], source[0], dest[0]); /* R */
+      VEC4_MAX(quad->outputs.color[1], source[1], dest[1]); /* G */
+      VEC4_MAX(quad->outputs.color[2], source[2], dest[2]); /* B */
+      break;
+   default:
+      abort();
+   }
+   
+   /*
+    * Combine A terms
+    */
+   switch (softpipe->blend.alpha_func) {
+   case PIPE_BLEND_ADD:
+      VEC4_ADD(quad->outputs.color[3], source[3], dest[3]); /* A */
+      break;
+   case PIPE_BLEND_SUBTRACT:
+      VEC4_SUB(quad->outputs.color[3], source[3], dest[3]); /* A */
+      break;
+   case PIPE_BLEND_REVERSE_SUBTRACT:
+      VEC4_SUB(quad->outputs.color[3], dest[3], source[3]); /* A */
+      break;
+   case PIPE_BLEND_MIN:
+      VEC4_MIN(quad->outputs.color[3], source[3], dest[3]); /* A */
+      break;
+   case PIPE_BLEND_MAX:
+      VEC4_MAX(quad->outputs.color[3], source[3], dest[3]); /* A */
+   default:
+      abort();
+   }
+   
+   /* pass blended quad to next stage */
+   qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = blend_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_bufloop.c b/src/mesa/pipe/softpipe/sp_quad_bufloop.c
new file mode 100644 (file)
index 0000000..be32d02
--- /dev/null
@@ -0,0 +1,62 @@
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+/**
+ * Loop over colorbuffers, passing quad to next stage each time.
+ */
+static void
+cbuf_loop_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   GLfloat tmp[4][QUAD_SIZE];
+   GLuint i;
+
+   assert(sizeof(quad->outputs.color) == sizeof(tmp));
+   assert(softpipe->framebuffer.num_cbufs <= PIPE_MAX_COLOR_BUFS);
+
+   /* make copy of original colors since they can get modified
+    * by blending and masking.
+    * XXX we won't have to do this if the fragment program actually emits
+    * N separate colors and we're drawing to N color buffers (MRT).
+    * But if we emitted one color and glDrawBuffer(GL_FRONT_AND_BACK) is
+    * in effect, we need to save/restore colors like this.
+    */
+   memcpy(tmp, quad->outputs.color, sizeof(tmp));
+
+   for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) {
+      /* set current cbuffer */
+      softpipe->cbuf = softpipe->framebuffer.cbufs[i];
+
+      /* pass blended quad to next stage */
+      qs->next->run(qs->next, quad);
+
+      /* restore quad's colors for next buffer */
+      memcpy(quad->outputs.color, tmp, sizeof(tmp));
+   }
+
+   softpipe->cbuf = NULL; /* prevent accidental use */
+}
+
+
+/**
+ * Create the colorbuffer loop stage.
+ * This is used to implement multiple render targets and GL_FRONT_AND_BACK
+ * rendering.
+ */
+struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = cbuf_loop_quad;
+
+   return stage;
+}
+
diff --git a/src/mesa/pipe/softpipe/sp_quad_colormask.c b/src/mesa/pipe/softpipe/sp_quad_colormask.c
new file mode 100644 (file)
index 0000000..fff6efa
--- /dev/null
@@ -0,0 +1,84 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/**
+ * \brief  quad colormask stage
+ * \author Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/macros.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+
+static void
+colormask_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
+   GLfloat dest[4][QUAD_SIZE];
+   
+   sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest);
+
+   /* R */
+   if (!(softpipe->blend.colormask & PIPE_MASK_R))
+       COPY_4FV(quad->outputs.color[0], dest[0]);
+
+   /* G */
+   if (!(softpipe->blend.colormask & PIPE_MASK_G))
+       COPY_4FV(quad->outputs.color[1], dest[1]);
+
+   /* B */
+   if (!(softpipe->blend.colormask & PIPE_MASK_B))
+       COPY_4FV(quad->outputs.color[2], dest[2]);
+
+   /* A */
+   if (!(softpipe->blend.colormask & PIPE_MASK_A))
+       COPY_4FV(quad->outputs.color[3], dest[3]);
+
+   /* pass quad to next stage */
+   qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = colormask_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_coverage.c b/src/mesa/pipe/softpipe/sp_quad_coverage.c
new file mode 100644 (file)
index 0000000..cdd8890
--- /dev/null
@@ -0,0 +1,74 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+
+/**
+ * \brief  Apply AA coverage to quad alpha valus
+ * \author  Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+
+
+/**
+ * Multiply quad's alpha values by the fragment coverage.
+ */
+static void
+coverage_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+
+   if ((softpipe->setup.poly_smooth && quad->prim == PRIM_TRI) ||
+       (softpipe->setup.line_smooth && quad->prim == PRIM_LINE) ||
+       (softpipe->setup.point_smooth && quad->prim == PRIM_POINT)) {
+      GLuint j;
+      for (j = 0; j < QUAD_SIZE; j++) {
+         assert(quad->coverage[j] >= 0.0);
+         assert(quad->coverage[j] <= 1.0);
+         quad->outputs.color[3][j] *= quad->coverage[j];
+      }
+   }
+
+   qs->next->run(qs->next, quad);
+}
+
+
+struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = coverage_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_depth_test.c b/src/mesa/pipe/softpipe/sp_quad_depth_test.c
new file mode 100644 (file)
index 0000000..d47c4c4
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  Brian Paul   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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ */
+
+/**
+ * \brief  Quad depth testing
+ */
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+/**
+ * Do depth testing for a quad.
+ * Not static since it's used by the stencil code.
+ */
+void
+sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf);
+   GLuint bzzzz[QUAD_SIZE];  /**< Z values fetched from depth buffer */
+   GLuint qzzzz[QUAD_SIZE];  /**< Z values from the quad */
+   GLuint zmask = 0;
+   GLuint j;
+   GLfloat scale;
+
+   assert(sps); /* shouldn't get here if there's no zbuffer */
+
+   /*
+    * To increase efficiency, we should probably have multiple versions
+    * of this function that are specifically for Z16, Z32 and FP Z buffers.
+    * Try to effectively do that with codegen...
+    */
+   if (sps->surface.format == PIPE_FORMAT_U_Z16)
+      scale = 65535.0;
+   else
+      assert(0);  /* XXX fix this someday */
+
+   /*
+    * Convert quad's float depth values to int depth values.
+    * If the Z buffer stores integer values, we _have_ to do the depth
+    * compares with integers (not floats).  Otherwise, the float->int->float
+    * conversion of Z values (which isn't an identity function) will cause
+    * Z-fighting errors.
+    */
+   for (j = 0; j < QUAD_SIZE; j++) {
+      qzzzz[j] = (GLuint) (quad->outputs.depth[j] * scale);
+   }
+
+   /* get zquad from zbuffer */
+   sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz);
+
+   switch (softpipe->depth_test.func) {
+   case PIPE_FUNC_NEVER:
+      /* zmask = 0 */
+      break;
+   case PIPE_FUNC_LESS:
+      /* Note this is pretty much a single sse or cell instruction.  
+       * Like this:  quad->mask &= (quad->outputs.depth < zzzz);
+       */
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (qzzzz[j] < bzzzz[j]) 
+           zmask |= 1 << j;
+      }
+      break;
+   case PIPE_FUNC_EQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (qzzzz[j] == bzzzz[j]) 
+           zmask |= 1 << j;
+      }
+      break;
+   case PIPE_FUNC_LEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (qzzzz[j] <= bzzzz[j]) 
+           zmask |= (1 << j);
+      }
+      break;
+   case PIPE_FUNC_GREATER:
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (qzzzz[j] > bzzzz[j]) 
+           zmask |= (1 << j);
+      }
+      break;
+   case PIPE_FUNC_NOTEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (qzzzz[j] != bzzzz[j]) 
+           zmask |= (1 << j);
+      }
+      break;
+   case PIPE_FUNC_GEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (qzzzz[j] >= bzzzz[j]) 
+           zmask |= (1 << j);
+      }
+      break;
+   case PIPE_FUNC_ALWAYS:
+      zmask = MASK_ALL;
+      break;
+   default:
+      abort();
+   }
+
+   quad->mask &= zmask;
+
+   if (softpipe->depth_test.writemask) {
+      
+      /* This is also efficient with sse / spe instructions: 
+       */
+      for (j = 0; j < QUAD_SIZE; j++) {
+        if (quad->mask & (1 << j)) {
+           bzzzz[j] = qzzzz[j];
+        }
+      }
+
+      /* write updated zquad to zbuffer */
+      sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz);
+   }
+}
+
+
+static void
+depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   sp_depth_test_quad(qs, quad);
+
+   if (quad->mask)
+      qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = depth_test_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_fs.c b/src/mesa/pipe/softpipe/sp_quad_fs.c
new file mode 100644 (file)
index 0000000..301bd13
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  Brian Paul   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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ */
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed.  We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+#include "core/tgsi_core.h"
+
+struct exec_machine {
+   const struct setup_coefficient *coef; /**< will point to quad->coef */
+
+   GLfloat attr[FRAG_ATTRIB_MAX][4][QUAD_SIZE];
+};
+
+
+/**
+ * Compute quad's attributes values, as constants (GL_FLAT shading).
+ */
+static INLINE void cinterp( struct exec_machine *exec,
+                           GLuint attrib,
+                           GLuint i )
+{
+   GLuint j;
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      exec->attr[attrib][i][j] = exec->coef[attrib].a0[i];
+   }
+}
+
+
+/**
+ * Compute quad's attribute values by linear interpolation.
+ *
+ * Push into the fp:
+ * 
+ *   INPUT[attr] = MAD COEF_A0[attr], COEF_DADX[attr], INPUT_WPOS.xxxx
+ *   INPUT[attr] = MAD INPUT[attr],   COEF_DADY[attr], INPUT_WPOS.yyyy
+ */
+static INLINE void linterp( struct exec_machine *exec,
+                           GLuint attrib,
+                           GLuint i )
+{
+   GLuint j;
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const GLfloat x = exec->attr[FRAG_ATTRIB_WPOS][0][j];
+      const GLfloat y = exec->attr[FRAG_ATTRIB_WPOS][1][j];
+      exec->attr[attrib][i][j] = (exec->coef[attrib].a0[i] +
+                                 exec->coef[attrib].dadx[i] * x + 
+                                 exec->coef[attrib].dady[i] * y);
+   }
+}
+
+
+/**
+ * Compute quad's attribute values by linear interpolation with
+ * perspective correction.
+ *
+ * Push into the fp:
+ * 
+ *   INPUT[attr] = MAD COEF_DADX[attr], INPUT_WPOS.xxxx, COEF_A0[attr]
+ *   INPUT[attr] = MAD COEF_DADY[attr], INPUT_WPOS.yyyy, INPUT[attr]
+ *   TMP         = RCP INPUT_WPOS.w
+ *   INPUT[attr] = MUL INPUT[attr], TMP.xxxx
+ *
+ */
+static INLINE void pinterp( struct exec_machine *exec,
+                           GLuint attrib,
+                           GLuint i )
+{
+   GLuint j;
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      const GLfloat x = exec->attr[FRAG_ATTRIB_WPOS][0][j];
+      const GLfloat y = exec->attr[FRAG_ATTRIB_WPOS][1][j];
+      /* FRAG_ATTRIB_WPOS.w here is really 1/w */
+      const GLfloat w = 1.0 / exec->attr[FRAG_ATTRIB_WPOS][3][j];
+      exec->attr[attrib][i][j] = ((exec->coef[attrib].a0[i] +
+                                  exec->coef[attrib].dadx[i] * x + 
+                                  exec->coef[attrib].dady[i] * y) * w);
+   }
+}
+
+
+
+/* This should be done by the fragment shader execution unit (code
+ * generated from the decl instructions).  Do it here for now.
+ */
+static void
+shade_quad( struct quad_stage *qs, struct quad_header *quad )
+{
+   const struct softpipe_context *softpipe = qs->softpipe;
+   struct exec_machine exec;
+   const GLfloat fx = quad->x0;
+   const GLfloat fy = quad->y0;
+   GLuint attr, i;
+
+   exec.coef = quad->coef;
+
+   /* Position:
+    */
+   exec.attr[FRAG_ATTRIB_WPOS][0][0] = fx;
+   exec.attr[FRAG_ATTRIB_WPOS][0][1] = fx + 1.0;
+   exec.attr[FRAG_ATTRIB_WPOS][0][2] = fx;
+   exec.attr[FRAG_ATTRIB_WPOS][0][3] = fx + 1.0;
+
+   exec.attr[FRAG_ATTRIB_WPOS][1][0] = fy;
+   exec.attr[FRAG_ATTRIB_WPOS][1][1] = fy;
+   exec.attr[FRAG_ATTRIB_WPOS][1][2] = fy + 1.0;
+   exec.attr[FRAG_ATTRIB_WPOS][1][3] = fy + 1.0;
+
+   /* Z and W are done by linear interpolation */
+   if (softpipe->need_z) {
+      linterp(&exec, 0, 2);   /* attr[0].z */
+   }
+
+   if (softpipe->need_w) {
+      linterp(&exec, 0, 3);  /* attr[0].w */
+      /*invert(&exec, 0, 3);*/
+   }
+
+   /* Interpolate all the remaining attributes.  This will get pushed
+    * into the fragment program's responsibilities at some point.
+    * Start at 1 to skip fragment position attribute (computed above).
+    */
+   for (attr = 1; attr < quad->nr_attrs; attr++) {
+      switch (softpipe->interp[attr]) {
+      case INTERP_CONSTANT:
+        for (i = 0; i < NUM_CHANNELS; i++)
+           cinterp(&exec, attr, i);
+        break;
+      
+      case INTERP_LINEAR:
+        for (i = 0; i < NUM_CHANNELS; i++)
+           linterp(&exec, attr, i);
+        break;
+
+      case INTERP_PERSPECTIVE:
+        for (i = 0; i < NUM_CHANNELS; i++)
+           pinterp(&exec, attr, i);
+        break;
+      }
+   }
+
+#if 1
+   /*softpipe->run_fs( tri->fp, quad, &tri->outputs );*/
+
+   {
+      struct tgsi_exec_machine machine;
+      struct tgsi_exec_vector inputs[FRAG_ATTRIB_MAX + 1];
+      struct tgsi_exec_vector outputs[FRAG_ATTRIB_MAX + 1];
+      struct tgsi_exec_vector *ainputs;
+      struct tgsi_exec_vector *aoutputs;
+      GLuint i /*, total*/;
+
+#ifdef DEBUG
+      memset(&machine, 0, sizeof(machine));
+#endif
+
+      ainputs = (struct tgsi_exec_vector *) tgsi_align_128bit( inputs );
+      aoutputs = (struct tgsi_exec_vector *) tgsi_align_128bit( outputs );
+
+#if 0
+      for( i = total = 0; i < PIPE_ATTRIB_MAX; i++ ) {
+         GLuint attr;
+
+         attr = softpipe->fp_attr_to_slot[i];
+         if( attr || total == 0) {
+            assert( total < FRAG_ATTRIB_MAX );
+            assert( attr < FRAG_ATTRIB_MAX );
+            assert( sizeof( ainputs[0] ) == sizeof( exec.attr[0] ) );
+
+            memcpy(
+               &ainputs[total],
+               exec.attr[attr],
+               sizeof( ainputs[0] ) );
+            total++;
+         }
+      }
+#else
+      /* load input registers */
+      /* XXX simpler than above, but might not be right... */
+      for (i = 0; i < softpipe->nr_attrs; i++) {
+         memcpy(
+                &ainputs[i],
+                exec.attr[i],
+                sizeof( ainputs[0] ) );
+      }
+#endif
+
+      /* init machine state */
+      tgsi_exec_machine_init(
+         &machine,
+         softpipe->fs.tokens );
+
+      machine.Inputs = ainputs;
+      machine.Outputs = aoutputs;
+      machine.Consts = softpipe->fs.constants->constant; /* XXX alignment? */
+
+      /* run shader */
+      tgsi_exec_machine_run( &machine );
+
+      /* store result color */
+      memcpy(quad->outputs.color,
+             &aoutputs[FRAG_ATTRIB_COL0].xyzw[0].f[0],
+             sizeof(quad->outputs.color));
+      if (softpipe->need_z) {
+         /* XXX temporary */
+         quad->outputs.depth[0] = exec.attr[0][2][0];
+         quad->outputs.depth[1] = exec.attr[0][2][1];
+         quad->outputs.depth[2] = exec.attr[0][2][2];
+         quad->outputs.depth[3] = exec.attr[0][2][3];
+      }
+   }
+#else
+   {
+      GLuint attr = softpipe->fp_attr_to_slot[FRAG_ATTRIB_COL0];
+      assert(attr);
+
+      memcpy(quad->outputs.color, 
+            exec.attr[attr], 
+            sizeof(quad->outputs.color));
+
+      if (softpipe->need_z) {
+         quad->outputs.depth[0] = exec.attr[0][2][0];
+         quad->outputs.depth[1] = exec.attr[0][2][1];
+         quad->outputs.depth[2] = exec.attr[0][2][2];
+         quad->outputs.depth[3] = exec.attr[0][2][3];
+      }
+   }
+#endif
+
+   /* shader may cull fragments */
+   if (quad->mask)
+      qs->next->run(qs->next, quad);
+}
+
+
+
+struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = shade_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_occlusion.c b/src/mesa/pipe/softpipe/sp_quad_occlusion.c
new file mode 100644 (file)
index 0000000..843c462
--- /dev/null
@@ -0,0 +1,67 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+
+/**
+ * \brief  Quad occlusion counter stage
+ * \author  Brian Paul
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "pipe/p_defines.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+static void
+occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+
+   softpipe->occlusion_counter += (quad->mask     ) & 1;
+   softpipe->occlusion_counter += (quad->mask >> 1) & 1;
+   softpipe->occlusion_counter += (quad->mask >> 2) & 1;
+   softpipe->occlusion_counter += (quad->mask >> 3) & 1;
+
+   if (quad->mask)
+      qs->next->run(qs->next, quad);
+}
+
+
+struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = occlusion_count_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_output.c b/src/mesa/pipe/softpipe/sp_quad_output.c
new file mode 100644 (file)
index 0000000..12ab1ec
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 1999-2005  Brian Paul   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, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL 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.
+ */
+
+/* Vertices are just an array of floats, with all the attributes
+ * packed.  We currently assume a layout like:
+ *
+ * attr[0][0..3] - window position
+ * attr[1..n][0..3] - remaining attributes.
+ *
+ * Attributes are assumed to be 4 floats wide but are packed so that
+ * all the enabled attributes run contiguously.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+
+
+static void mask_copy( GLfloat (*dest)[4],
+                      GLfloat (*src)[4],
+                      GLuint mask )
+{
+   GLuint i, j;
+
+   for (i = 0; i < 4; i++) {
+      if (mask & (1<<i)) {
+        for (j = 0; j < 4; j++) {
+           dest[j][i] = src[j][i];
+        }
+      }
+   }
+}
+
+
+/**
+ * Write quad to framebuffer, taking mask into account.
+ *
+ * Note that surfaces support only full quad reads and writes.
+ */
+static void
+output_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
+
+   if (quad->mask != MASK_ALL) {
+      GLfloat tmp[4][QUAD_SIZE];
+
+      /* XXX probably add a masked-write function someday */
+
+      sps->read_quad_f_swz(sps, quad->x0, quad->y0, tmp);
+
+      mask_copy( tmp, quad->outputs.color, quad->mask );
+
+      sps->write_quad_f_swz(sps, quad->x0, quad->y0, tmp);
+   }
+   else if (quad->mask) {
+      sps->write_quad_f_swz(sps, quad->x0, quad->y0, quad->outputs.color);
+   }
+}
+
+
+struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = output_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_stencil.c b/src/mesa/pipe/softpipe/sp_quad_stencil.c
new file mode 100644 (file)
index 0000000..0b37474
--- /dev/null
@@ -0,0 +1,288 @@
+
+/**
+ * \brief Quad stencil testing
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_surface.h"
+#include "sp_quad.h"
+#include "pipe/p_defines.h"
+
+
+/** Only 8-bit stencil supported */
+#define STENCIL_MAX 0xff
+
+
+/**
+ * Do the basic stencil test (compare stencil buffer values against the
+ * reference value.
+ *
+ * \param stencilVals  the stencil values from the stencil buffer
+ * \param func  the stencil func (PIPE_FUNC_x)
+ * \param ref  the stencil reference value
+ * \param valMask  the stencil value mask indicating which bits of the stencil
+ *                 values and ref value are to be used.
+ * \return mask indicating which pixels passed the stencil test
+ */
+static GLbitfield
+do_stencil_test(const GLubyte stencilVals[QUAD_SIZE], GLuint func,
+                GLbitfield ref, GLbitfield valMask)
+{
+   GLbitfield passMask = 0x0;
+   GLuint j;
+
+   ref &= valMask;
+
+   switch (func) {
+   case PIPE_FUNC_NEVER:
+      /* passMask = 0x0 */
+      break;
+   case PIPE_FUNC_LESS:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if ((stencilVals[j] & valMask) < ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_EQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if ((stencilVals[j] & valMask) == ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_LEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if ((stencilVals[j] & valMask) <= ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_GREATER:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if ((stencilVals[j] & valMask) > ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_NOTEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if ((stencilVals[j] & valMask) != ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_GEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if ((stencilVals[j] & valMask) >= ref) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_ALWAYS:
+      passMask = MASK_ALL;
+      break;
+   default:
+      assert(0);
+   }
+
+   return passMask;
+}
+
+
+/**
+ * Apply the stencil operator to stencil values.
+ *
+ * \param stencilVals  the stencil buffer values (read and written)
+ * \param mask  indicates which pixels to update
+ * \param op  the stencil operator (PIPE_STENCIL_OP_x)
+ * \param ref  the stencil reference value
+ * \param wrtMask  writemask controlling which bits are changed in the
+ *                 stencil values
+ */
+static void
+apply_stencil_op(GLubyte stencilVals[QUAD_SIZE],
+                 GLbitfield mask, GLuint op, GLubyte ref, GLubyte wrtMask)
+{
+   GLuint j;
+   GLubyte newstencil[QUAD_SIZE];
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      newstencil[j] = stencilVals[j];
+   }
+
+   switch (op) {
+   case PIPE_STENCIL_OP_KEEP:
+      /* no-op */
+      break;
+   case PIPE_STENCIL_OP_ZERO:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = 0;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_REPLACE:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = ref;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_INCR:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            if (stencilVals[j] < STENCIL_MAX) {
+               newstencil[j] = stencilVals[j] + 1;
+            }
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_DECR:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            if (stencilVals[j] > 0) {
+               newstencil[j] = stencilVals[j] - 1;
+            }
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_INCR_WRAP:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = stencilVals[j] + 1;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_DECR_WRAP:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = stencilVals[j] - 1;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_INVERT:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = ~stencilVals[j];
+         }
+      }
+      break;
+   default:
+      assert(0);
+   }
+
+   /*
+    * update the stencil values
+    */
+   if (wrtMask != STENCIL_MAX) {
+      /* apply bit-wise stencil buffer writemask */
+      for (j = 0; j < QUAD_SIZE; j++) {
+         stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]);
+      }
+   }
+   else {
+      for (j = 0; j < QUAD_SIZE; j++) {
+         stencilVals[j] = newstencil[j];
+      }
+   }
+}
+
+
+/**
+ * Do stencil (and depth) testing.  Stenciling depends on the outcome of
+ * depth testing.
+ */
+static void
+stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   struct softpipe_surface *s_surf = softpipe_surface(softpipe->framebuffer.sbuf);
+   GLuint func, zFailOp, zPassOp, failOp;
+   GLubyte ref, wrtMask, valMask;
+   GLubyte stencilVals[QUAD_SIZE];
+
+   /* choose front or back face function, operator, etc */
+   /* XXX we could do these initializations once per primitive */
+   if (softpipe->stencil.back_enabled && quad->facing) {
+      func = softpipe->stencil.back_func;
+      failOp = softpipe->stencil.back_fail_op;
+      zFailOp = softpipe->stencil.back_zfail_op;
+      zPassOp = softpipe->stencil.back_zpass_op;
+      ref = softpipe->stencil.ref_value[1];
+      wrtMask = softpipe->stencil.write_mask[1];
+      valMask = softpipe->stencil.value_mask[1];
+   }
+   else {
+      func = softpipe->stencil.front_func;
+      failOp = softpipe->stencil.front_fail_op;
+      zFailOp = softpipe->stencil.front_zfail_op;
+      zPassOp = softpipe->stencil.front_zpass_op;
+      ref = softpipe->stencil.ref_value[0];
+      wrtMask = softpipe->stencil.write_mask[0];
+      valMask = softpipe->stencil.value_mask[0];
+   }
+
+   assert(s_surf); /* shouldn't get here if there's no stencil buffer */
+   s_surf->read_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals);
+
+   /* do the stencil test first */
+   {
+      GLbitfield passMask, failMask;
+      passMask = do_stencil_test(stencilVals, func, ref, valMask);
+      failMask = quad->mask & ~passMask;
+      quad->mask &= passMask;
+
+      if (failOp != PIPE_STENCIL_OP_KEEP) {
+         apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
+      }
+   }
+
+   if (quad->mask) {
+
+      /* now the pixels that passed the stencil test are depth tested */
+      if (softpipe->depth_test.enabled) {
+         const GLbitfield origMask = quad->mask;
+
+         sp_depth_test_quad(qs, quad);  /* quad->mask is updated */
+
+         /* update stencil buffer values according to z pass/fail result */
+         if (zFailOp != PIPE_STENCIL_OP_KEEP) {
+            const GLbitfield failMask = origMask & ~quad->mask;
+            apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
+         }
+
+         if (zPassOp != PIPE_STENCIL_OP_KEEP) {
+            const GLbitfield passMask = origMask & quad->mask;
+            apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
+         }
+      }
+      else {
+         /* no depth test, apply Zpass operator to stencil buffer values */
+         apply_stencil_op(stencilVals, quad->mask, zPassOp, ref, wrtMask);
+      }
+
+   }
+
+   s_surf->write_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals);
+
+   if (quad->mask)
+      qs->next->run(qs->next, quad);
+}
+
+
+
+
+struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = stencil_test_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_quad_stipple.c b/src/mesa/pipe/softpipe/sp_quad_stipple.c
new file mode 100644 (file)
index 0000000..cad1a14
--- /dev/null
@@ -0,0 +1,48 @@
+
+/**
+ * quad polygon stipple stage
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "sp_context.h"
+#include "sp_headers.h"
+#include "sp_quad.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Apply polygon stipple to quads produced by triangle rasterization
+ */
+static void
+stipple_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   if (quad->prim == PRIM_TRI) {
+      struct softpipe_context *softpipe = qs->softpipe;
+      const GLint col0 = quad->x0 % 32;
+      const GLint row0 = quad->y0 % 32;
+      const GLuint stipple0 = softpipe->poly_stipple.stipple[row0];
+      const GLuint stipple1 = softpipe->poly_stipple.stipple[row0 + 1];
+
+      /* XXX there may be a better way to lay out the stored stipple
+       * values to further simplify this computation.
+       */
+      quad->mask &= (((stipple0 >> col0) & 0x3) | 
+                     (((stipple1 >> col0) & 0x3) << 2));
+
+      if (quad->mask)
+         qs->next->run(qs->next, quad);
+   }
+}
+
+
+struct quad_stage *
+sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe )
+{
+   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
+
+   stage->softpipe = softpipe;
+   stage->run = stipple_quad;
+
+   return stage;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h
new file mode 100644 (file)
index 0000000..71c1a2d
--- /dev/null
@@ -0,0 +1,87 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_STATE_H
+#define SP_STATE_H
+
+#include "glheader.h"
+#include "pipe/p_state.h"
+
+
+void softpipe_set_framebuffer_state( struct pipe_context *,
+                            const struct pipe_framebuffer_state * );
+
+void softpipe_set_alpha_test_state( struct pipe_context *,
+                                    const struct pipe_alpha_test_state * );
+
+void softpipe_set_blend_state( struct pipe_context *,
+                               const struct pipe_blend_state * );
+
+void softpipe_set_blend_color( struct pipe_context *pipe,
+                               const struct pipe_blend_color *blend_color );
+
+void softpipe_set_clear_color_state( struct pipe_context *,
+                                     const struct pipe_clear_color_state * );
+
+void softpipe_set_clip_state( struct pipe_context *,
+                            const struct pipe_clip_state * );
+
+void softpipe_set_depth_test_state( struct pipe_context *,
+                                    const struct pipe_depth_state * );
+
+void softpipe_set_fs_state( struct pipe_context *,
+                          const struct pipe_fs_state * );
+
+void softpipe_set_polygon_stipple( struct pipe_context *,
+                                 const struct pipe_poly_stipple * );
+
+void softpipe_set_scissor_state( struct pipe_context *,
+                                 const struct pipe_scissor_state * );
+
+void softpipe_set_setup_state( struct pipe_context *,
+                             const struct pipe_setup_state * );
+
+void softpipe_set_sampler_state( struct pipe_context *,
+                                 GLuint unit,
+                                 const struct pipe_sampler_state * );
+
+void softpipe_set_stencil_state( struct pipe_context *,
+                                 const struct pipe_stencil_state * );
+
+void softpipe_set_texture_state( struct pipe_context *,
+                                 GLuint unit,
+                                 struct pipe_texture_object * );
+
+void softpipe_set_viewport_state( struct pipe_context *,
+                                  const struct pipe_viewport_state * );
+
+void softpipe_update_derived( struct softpipe_context *softpipe );
+
+#endif
diff --git a/src/mesa/pipe/softpipe/sp_state_blend.c b/src/mesa/pipe/softpipe/sp_state_blend.c
new file mode 100644 (file)
index 0000000..8bc22b0
--- /dev/null
@@ -0,0 +1,93 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+void softpipe_set_blend_state( struct pipe_context *pipe,
+                            const struct pipe_blend_state *blend )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->blend = *blend;
+
+   softpipe->dirty |= SP_NEW_BLEND;
+}
+
+
+void softpipe_set_blend_color( struct pipe_context *pipe,
+                            const struct pipe_blend_color *blend_color )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->blend_color = *blend_color;
+
+   softpipe->dirty |= SP_NEW_BLEND;
+}
+
+
+/** XXX move someday?  Or consolidate all these simple state setters
+ * into one file.
+ */
+void
+softpipe_set_depth_test_state(struct pipe_context *pipe,
+                              const struct pipe_depth_state *depth)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->depth_test = *depth;
+
+   softpipe->dirty |= SP_NEW_DEPTH_TEST;
+}
+
+void
+softpipe_set_alpha_test_state(struct pipe_context *pipe,
+                              const struct pipe_alpha_test_state *alpha)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->alpha_test = *alpha;
+
+   softpipe->dirty |= SP_NEW_ALPHA_TEST;
+}
+
+void
+softpipe_set_stencil_state(struct pipe_context *pipe,
+                           const struct pipe_stencil_state *stencil)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->stencil = *stencil;
+
+   softpipe->dirty |= SP_NEW_STENCIL;
+}
+
diff --git a/src/mesa/pipe/softpipe/sp_state_clip.c b/src/mesa/pipe/softpipe/sp_state_clip.c
new file mode 100644 (file)
index 0000000..8cf4383
--- /dev/null
@@ -0,0 +1,85 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "pipe/draw/draw_context.h"
+
+
+void softpipe_set_clip_state( struct pipe_context *pipe,
+                            const struct pipe_clip_state *clip )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   /* pass the clip state to the draw module */
+   draw_set_clip_state(softpipe->draw, clip);
+}
+
+
+
+/* Called when driver state tracker notices changes to the viewport
+ * matrix:
+ */
+void softpipe_set_viewport_state( struct pipe_context *pipe,
+                                  const struct pipe_viewport_state *viewport )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->viewport = *viewport; /* struct copy */
+   softpipe->dirty |= SP_NEW_VIEWPORT;
+
+   /* pass the viewport info to the draw module */
+   draw_set_viewport_state(softpipe->draw, viewport);
+
+   /* Using tnl/ and vf/ modules is temporary while getting started.
+    * Full pipe will have vertex shader, vertex fetch of its own.
+    */
+}
+
+
+void softpipe_set_scissor_state( struct pipe_context *pipe,
+                                 const struct pipe_scissor_state *scissor )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   memcpy( &softpipe->scissor, scissor, sizeof(*scissor) );
+   softpipe->dirty |= SP_NEW_SCISSOR;
+}
+
+
+void softpipe_set_polygon_stipple( struct pipe_context *pipe,
+                                   const struct pipe_poly_stipple *stipple )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   memcpy( &softpipe->poly_stipple, stipple, sizeof(*stipple) );
+   softpipe->dirty |= SP_NEW_STIPPLE;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state_derived.c b/src/mesa/pipe/softpipe/sp_state_derived.c
new file mode 100644 (file)
index 0000000..26083c2
--- /dev/null
@@ -0,0 +1,184 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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 "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+
+#include "vf/vf.h"
+#include "pipe/draw/draw_context.h"
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+#define EMIT_ATTR( VF_ATTR, FRAG_ATTR, INTERP )                        \
+do {                                                           \
+   slot_to_vf_attr[softpipe->nr_attrs] = VF_ATTR;              \
+   softpipe->vf_attr_to_slot[VF_ATTR] = softpipe->nr_attrs;    \
+   softpipe->fp_attr_to_slot[FRAG_ATTR] = softpipe->nr_attrs;  \
+   softpipe->interp[softpipe->nr_attrs] = INTERP;              \
+   softpipe->nr_attrs++;                                       \
+   attr_mask |= (1 << (VF_ATTR));                              \
+} while (0)
+
+
+static const GLuint frag_to_vf[FRAG_ATTRIB_MAX] = 
+{
+   VF_ATTRIB_POS,
+   VF_ATTRIB_COLOR0,
+   VF_ATTRIB_COLOR1,
+   VF_ATTRIB_FOG,
+   VF_ATTRIB_TEX0,
+   VF_ATTRIB_TEX1,
+   VF_ATTRIB_TEX2,
+   VF_ATTRIB_TEX3,
+   VF_ATTRIB_TEX4,
+   VF_ATTRIB_TEX5,
+   VF_ATTRIB_TEX6,
+   VF_ATTRIB_TEX7,
+   VF_ATTRIB_VAR0,
+   VF_ATTRIB_VAR1,
+   VF_ATTRIB_VAR2,
+   VF_ATTRIB_VAR3,
+   VF_ATTRIB_VAR4,
+   VF_ATTRIB_VAR5,
+   VF_ATTRIB_VAR6,
+   VF_ATTRIB_VAR7,
+};
+
+
+/**
+ * Determine which post-transform / pre-rasterization vertex attributes
+ * we need.
+ * Derived from:  fs, setup states.
+ */
+static void calculate_vertex_layout( struct softpipe_context *softpipe )
+{
+   const GLbitfield inputsRead = softpipe->fs.inputs_read;
+   GLuint slot_to_vf_attr[VF_ATTRIB_MAX];
+   GLbitfield attr_mask = 0x0;
+   GLuint i;
+
+   /* Need Z if depth test is enabled or the fragment program uses the
+    * fragment position (XYZW).
+    */
+   if (softpipe->depth_test.enabled ||
+       (inputsRead & FRAG_ATTRIB_WPOS))
+      softpipe->need_z = GL_TRUE;
+   else
+      softpipe->need_z = GL_FALSE;
+
+   /* Need W if we do any perspective-corrected interpolation or the
+    * fragment program uses the fragment position.
+    */
+   if (inputsRead & FRAG_ATTRIB_WPOS)
+      softpipe->need_w = GL_TRUE;
+   else
+      softpipe->need_w = GL_FALSE;
+
+
+   softpipe->nr_attrs = 0;
+   memset(slot_to_vf_attr, 0, sizeof(slot_to_vf_attr));
+
+   memset(softpipe->fp_attr_to_slot, 0, sizeof(softpipe->fp_attr_to_slot));
+   memset(softpipe->vf_attr_to_slot, 0, sizeof(softpipe->vf_attr_to_slot));
+
+   /* TODO - Figure out if we need to do perspective divide, etc.
+    */
+   EMIT_ATTR(VF_ATTRIB_POS, FRAG_ATTRIB_WPOS, INTERP_LINEAR);
+      
+   /* Pull in the rest of the attributes.  They are all in float4
+    * format.  Future optimizations could be to keep some attributes
+    * as fixed point or ubyte format.
+    */
+   for (i = 1; i < FRAG_ATTRIB_TEX0; i++) {
+      if (inputsRead & (1 << i)) {
+         assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0]));
+         if (softpipe->setup.flatshade
+             && (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1))
+            EMIT_ATTR(frag_to_vf[i], i, INTERP_CONSTANT);
+         else
+            EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR);
+      }
+   }
+
+   for (i = FRAG_ATTRIB_TEX0; i < FRAG_ATTRIB_MAX; i++) {
+      if (inputsRead & (1 << i)) {
+         assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0]));
+         EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE);
+         softpipe->need_w = GL_TRUE;
+      }
+   }
+
+   softpipe->nr_frag_attrs = softpipe->nr_attrs;
+
+   /* Additional attributes required for setup: Just twosided
+    * lighting.  Edgeflag is dealt with specially by setting bits in
+    * the vertex header.
+    */
+   if (softpipe->setup.light_twoside) {
+      if (inputsRead & FRAG_BIT_COL0) {
+        EMIT_ATTR(VF_ATTRIB_BFC0, FRAG_ATTRIB_MAX, 0); /* XXX: mark as discarded after setup */
+      }
+           
+      if (inputsRead & FRAG_BIT_COL1) {
+        EMIT_ATTR(VF_ATTRIB_BFC1, FRAG_ATTRIB_MAX, 0); /* XXX: discard after setup */
+      }
+   }
+
+   /* If the attributes have changed, tell the draw module (which in turn
+    * tells the vf module) about the new vertex layout.
+    */
+   if (attr_mask != softpipe->attr_mask) {
+      softpipe->attr_mask = attr_mask;
+
+      draw_set_vertex_attributes( softpipe->draw,
+                                 slot_to_vf_attr,
+                                 softpipe->nr_attrs );
+   }
+}
+
+
+/* Hopefully this will remain quite simple, otherwise need to pull in
+ * something like the state tracker mechanism.
+ */
+void softpipe_update_derived( struct softpipe_context *softpipe )
+{
+   if (softpipe->dirty & (SP_NEW_SETUP | SP_NEW_FS))
+      calculate_vertex_layout( softpipe );
+
+   if (softpipe->dirty & (SP_NEW_BLEND |
+                          SP_NEW_DEPTH_TEST |
+                          SP_NEW_ALPHA_TEST |
+                          SP_NEW_FRAMEBUFFER |
+                          SP_NEW_STENCIL |
+                          SP_NEW_SETUP |
+                          SP_NEW_FS))
+      sp_build_quad_pipeline(softpipe);
+
+   softpipe->dirty = 0;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state_fs.c b/src/mesa/pipe/softpipe/sp_state_fs.c
new file mode 100644 (file)
index 0000000..c7ef1f1
--- /dev/null
@@ -0,0 +1,50 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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 "sp_context.h"
+#include "sp_state.h"
+
+
+
+void softpipe_set_fs_state( struct pipe_context *pipe,
+                          const struct pipe_fs_state *fs )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   memcpy(&softpipe->fs, fs, sizeof(*fs));
+
+   softpipe->dirty |= SP_NEW_FS;
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/mesa/pipe/softpipe/sp_state_sampler.c b/src/mesa/pipe/softpipe/sp_state_sampler.c
new file mode 100644 (file)
index 0000000..9ef71f7
--- /dev/null
@@ -0,0 +1,64 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:
+ *  Brian Paul
+ */
+
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+
+
+
+void
+softpipe_set_sampler_state(struct pipe_context *pipe,
+                           GLuint unit,
+                           const struct pipe_sampler_state *sampler)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   assert(unit < PIPE_MAX_SAMPLERS);
+   softpipe->sampler[unit] = *sampler;
+
+   softpipe->dirty |= SP_NEW_SAMPLER;
+}
+
+
+void
+softpipe_set_texture_state(struct pipe_context *pipe,
+                           GLuint unit,
+                           struct pipe_texture_object *texture)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   assert(unit < PIPE_MAX_SAMPLERS);
+   softpipe->texture[unit] = texture;  /* ptr, not struct */
+
+   softpipe->dirty |= SP_NEW_TEXTURE;
+}
diff --git a/src/mesa/pipe/softpipe/sp_state_setup.c b/src/mesa/pipe/softpipe/sp_state_setup.c
new file mode 100644 (file)
index 0000000..4715a26
--- /dev/null
@@ -0,0 +1,47 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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_defines.h"
+#include "sp_context.h"
+#include "sp_state.h"
+#include "pipe/draw/draw_context.h"
+
+
+void softpipe_set_setup_state( struct pipe_context *pipe,
+                             const struct pipe_setup_state *setup )
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   /* pass-through to draw module */
+   draw_set_setup_state(softpipe->draw, setup);
+
+   memcpy( &softpipe->setup, setup, sizeof(*setup) );
+
+   softpipe->dirty |= SP_NEW_SETUP;
+}
+
+
diff --git a/src/mesa/pipe/softpipe/sp_state_surface.c b/src/mesa/pipe/softpipe/sp_state_surface.c
new file mode 100644 (file)
index 0000000..8ce81eb
--- /dev/null
@@ -0,0 +1,61 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "imports.h"
+
+#include "sp_context.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+
+
+/*
+ * XXX this might get moved someday
+ */
+void
+softpipe_set_framebuffer_state(struct pipe_context *pipe,
+                               const struct pipe_framebuffer_state *fb)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->framebuffer = *fb; /* struct copy */
+
+   softpipe->dirty |= SP_NEW_FRAMEBUFFER;
+}
+
+
+
+
+void
+softpipe_set_clear_color_state(struct pipe_context *pipe,
+                               const struct pipe_clear_color_state *clear)
+{
+   struct softpipe_context *softpipe = softpipe_context(pipe);
+
+   softpipe->clear_color = *clear; /* struct copy */
+}
diff --git a/src/mesa/pipe/softpipe/sp_surface.c b/src/mesa/pipe/softpipe/sp_surface.c
new file mode 100644 (file)
index 0000000..16bbacb
--- /dev/null
@@ -0,0 +1,153 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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 "sp_context.h"
+#include "sp_state.h"
+#include "sp_surface.h"
+#include "sp_headers.h"
+
+static void rgba8_read_quad_f( struct softpipe_surface *gs,
+                              GLint x, GLint y,
+                              GLfloat (*rgba)[NUM_CHANNELS] )
+{
+   GLuint i, j, k = 0;
+
+   for (i = 0; i < 2; i++) {
+      for (j = 0; j < 2; j++, k++) {
+        GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+        rgba[k][0] = ptr[0] * (1.0 / 255.0);
+        rgba[k][1] = ptr[1] * (1.0 / 255.0);
+        rgba[k][2] = ptr[2] * (1.0 / 255.0);
+        rgba[k][3] = ptr[3] * (1.0 / 255.0);
+      }
+   }
+}
+
+static void rgba8_read_quad_f_swz( struct softpipe_surface *gs,
+                                  GLint x, GLint y,
+                                  GLfloat (*rrrr)[QUAD_SIZE] )
+{
+   GLuint i, j, k = 0;
+
+   for (i = 0; i < 2; i++) {
+      for (j = 0; j < 2; j++, k++) {
+        GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+        rrrr[0][k] = ptr[0] * (1.0 / 255.0);
+        rrrr[1][k] = ptr[1] * (1.0 / 255.0);
+        rrrr[2][k] = ptr[2] * (1.0 / 255.0);
+        rrrr[3][k] = ptr[3] * (1.0 / 255.0);
+      }
+   }
+}
+
+static void rgba8_write_quad_f( struct softpipe_surface *gs,
+                               GLint x, GLint y,
+                               GLfloat (*rgba)[NUM_CHANNELS] )
+{
+   GLuint i, j, k = 0;
+
+   for (i = 0; i < 2; i++) {
+      for (j = 0; j < 2; j++, k++) {
+        GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+        ptr[0] = rgba[k][0] * 255.0;
+        ptr[1] = rgba[k][1] * 255.0;
+        ptr[2] = rgba[k][2] * 255.0;
+        ptr[3] = rgba[k][3] * 255.0;
+      }
+   }
+}
+
+static void rgba8_write_quad_f_swz( struct softpipe_surface *gs,
+                                   GLint x, GLint y,
+                                   GLfloat (*rrrr)[QUAD_SIZE] )
+{
+   GLuint i, j, k = 0;
+
+   for (i = 0; i < 2; i++) {
+      for (j = 0; j < 2; j++, k++) {
+        GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+        ptr[0] = rrrr[0][k] * 255.0;
+        ptr[1] = rrrr[1][k] * 255.0;
+        ptr[2] = rrrr[2][k] * 255.0;
+        ptr[3] = rrrr[3][k] * 255.0;
+      }
+   }
+}
+
+
+
+
+static void rgba8_read_quad_ub( struct softpipe_surface *gs,
+                               GLint x, GLint y,
+                               GLubyte (*rgba)[NUM_CHANNELS] )
+{
+   GLuint i, j, k = 0;
+
+   for (i = 0; i < 2; i++) {
+      for (j = 0; j < 2; j++, k++) {
+        GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+        rgba[k][0] = ptr[0];
+        rgba[k][1] = ptr[1];
+        rgba[k][2] = ptr[2];
+        rgba[k][3] = ptr[3];
+      }
+   }
+}
+
+
+static void rgba8_write_quad_ub( struct softpipe_surface *gs,
+                                GLint x, GLint y,
+                                GLubyte (*rgba)[NUM_CHANNELS] )
+{
+   GLuint i, j, k = 0;
+
+   for (i = 0; i < 2; i++) {
+      for (j = 0; j < 2; j++, k++) {
+        GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4;
+        ptr[0] = rgba[k][0];
+        ptr[1] = rgba[k][1];
+        ptr[2] = rgba[k][2];
+        ptr[3] = rgba[k][3];
+      }
+   }
+}
+
+
+
+
+struct softpipe_surface_type gs_rgba8 = {
+   G_SURFACE_RGBA_8888,
+   rgba8_read_quad_f,
+   rgba8_read_quad_f_swz,
+   rgba8_read_quad_ub,
+   rgba8_write_quad_f,
+   rgba8_write_quad_f_swz,
+   rgba8_write_quad_ub,
+};
+
+
+
diff --git a/src/mesa/pipe/softpipe/sp_surface.h b/src/mesa/pipe/softpipe/sp_surface.h
new file mode 100644 (file)
index 0000000..3ba732c
--- /dev/null
@@ -0,0 +1,101 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef SP_SURFACE_H
+#define SP_SURFACE_H
+
+#include "glheader.h"
+#include "sp_headers.h"
+
+struct softpipe_surface;
+
+#define G_SURFACE_RGBA_8888  0x1
+
+
+/**
+ * Softpipe surface is derived from pipe_surface.
+ */
+struct softpipe_surface {
+   struct pipe_surface surface;
+
+   /**
+    * Functions for read/writing surface data
+    */
+   void (*read_quad_f)( struct softpipe_surface *,
+                       GLint x, GLint y,
+                       GLfloat (*rgba)[NUM_CHANNELS] );
+
+   void (*read_quad_f_swz)( struct softpipe_surface *,
+                           GLint x, GLint y,
+                           GLfloat (*rrrr)[QUAD_SIZE] );
+
+   void (*read_quad_ub)( struct softpipe_surface *,
+                        GLint x, GLint y,
+                        GLubyte (*rgba)[NUM_CHANNELS] );
+
+
+   void (*write_quad_f)( struct softpipe_surface *,
+                        GLint x, GLint y,
+                        GLfloat (*rgba)[NUM_CHANNELS] );
+
+   void (*write_quad_f_swz)( struct softpipe_surface *,
+                            GLint x, GLint y,
+                            GLfloat (*rrrr)[QUAD_SIZE] );
+
+
+   void (*write_quad_ub)( struct softpipe_surface *,
+                         GLint x, GLint y,
+                         GLubyte (*rgba)[NUM_CHANNELS] );
+
+   void (*write_mono_row_ub)( struct softpipe_surface *,
+                              GLuint count, GLint x, GLint y,
+                              GLubyte rgba[NUM_CHANNELS] );
+
+   void (*read_quad_z)(struct softpipe_surface *,
+                       GLint x, GLint y, GLuint zzzz[QUAD_SIZE]);
+   void (*write_quad_z)(struct softpipe_surface *,
+                        GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]);
+
+   void (*read_quad_stencil)(struct softpipe_surface *,
+                             GLint x, GLint y, GLubyte ssss[QUAD_SIZE]);
+   void (*write_quad_stencil)(struct softpipe_surface *,
+                              GLint x, GLint y, const GLubyte ssss[QUAD_SIZE]);
+};
+
+
+/** Cast wrapper */
+static INLINE struct softpipe_surface *
+softpipe_surface(struct pipe_surface *ps)
+{
+   return (struct softpipe_surface *) ps;
+}
+
+
+#endif /* SP_SURFACE_H */
diff --git a/src/mesa/pipe/tgsi/Makefile b/src/mesa/pipe/tgsi/Makefile
new file mode 100644 (file)
index 0000000..12a8bd0
--- /dev/null
@@ -0,0 +1,3 @@
+default:
+       cd ../.. ; make
+
diff --git a/src/mesa/pipe/tgsi/core/Makefile b/src/mesa/pipe/tgsi/core/Makefile
new file mode 100644 (file)
index 0000000..eb8b14e
--- /dev/null
@@ -0,0 +1,3 @@
+default:
+       cd ../../.. ; make
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_build.c b/src/mesa/pipe/tgsi/core/tgsi_build.c
new file mode 100644 (file)
index 0000000..2a482a7
--- /dev/null
@@ -0,0 +1,1315 @@
+#include "tgsi_platform.h"
+#include "tgsi_core.h"
+
+/*
+ * version
+ */
+
+struct tgsi_version
+tgsi_build_version( void )
+{
+   struct tgsi_version  version;
+
+   version.MajorVersion = 1;
+   version.MinorVersion = 1;
+   version.Padding = 0;
+
+   return version;
+}
+
+/*
+ * header
+ */
+
+struct tgsi_header
+tgsi_build_header( void )
+{
+   struct tgsi_header header;
+
+   header.HeaderSize = 1;
+   header.BodySize = 0;
+
+   return header;
+}
+
+static void
+header_headersize_grow( struct tgsi_header *header )
+{
+   assert (header->HeaderSize < 0xFF);
+   assert (header->BodySize == 0);
+
+   header->HeaderSize++;
+}
+
+static void
+header_bodysize_grow( struct tgsi_header *header )
+{
+   assert (header->BodySize < 0xFFFFFF);
+
+   header->BodySize++;
+}
+
+struct tgsi_processor
+tgsi_default_processor( void )
+{
+   struct tgsi_processor processor;
+
+   processor.Processor = TGSI_PROCESSOR_FRAGMENT;
+   processor.Padding = 0;
+
+   return processor;
+}
+
+struct tgsi_processor
+tgsi_build_processor(
+   GLuint type,
+   struct tgsi_header *header )
+{
+   struct tgsi_processor processor;
+
+   processor = tgsi_default_processor();
+   processor.Processor = type;
+
+   header_headersize_grow( header );
+
+   return processor;
+}
+
+/*
+ * declaration
+ */
+
+struct tgsi_declaration
+tgsi_default_declaration( void )
+{
+   struct tgsi_declaration declaration;
+
+   declaration.Type = TGSI_TOKEN_TYPE_DECLARATION;
+   declaration.Size = 1;
+   declaration.File = TGSI_FILE_NULL;
+   declaration.Declare = TGSI_DECLARE_RANGE;
+   declaration.Interpolate = 0;
+   declaration.Padding = 0;
+   declaration.Extended = 0;
+
+   return declaration;
+}
+
+struct tgsi_declaration
+tgsi_build_declaration(
+   GLuint file,
+   GLuint declare,
+   GLuint interpolate,
+   struct tgsi_header *header )
+{
+   struct tgsi_declaration declaration;
+
+   assert (file <= TGSI_FILE_IMMEDIATE);
+   assert (declare <= TGSI_DECLARE_MASK);
+
+   declaration = tgsi_default_declaration();
+   declaration.File = file;
+   declaration.Declare = declare;
+   declaration.Interpolate = interpolate;
+
+   header_bodysize_grow( header );
+
+   return declaration;
+}
+
+static void
+declaration_grow(
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header )
+{
+   assert (declaration->Size < 0xFF);
+
+   declaration->Size++;
+
+   header_bodysize_grow( header );
+}
+
+struct tgsi_full_declaration
+tgsi_default_full_declaration( void )
+{
+   struct tgsi_full_declaration  full_declaration;
+
+   full_declaration.Declaration  = tgsi_default_declaration();
+   full_declaration.Interpolation = tgsi_default_declaration_interpolation();
+
+   return full_declaration;
+}
+
+GLuint
+tgsi_build_full_declaration(
+   const struct   tgsi_full_declaration *full_decl,
+   struct tgsi_token *tokens,
+   struct tgsi_header *header,
+   GLuint maxsize )
+{
+   GLuint size = 0;
+   struct tgsi_declaration *declaration;
+
+   if( maxsize <= size )
+     return 0;
+   declaration = (struct tgsi_declaration *) &tokens[size];
+   size++;
+
+   *declaration = tgsi_build_declaration(
+      full_decl->Declaration.File,
+      full_decl->Declaration.Declare,
+      full_decl->Declaration.Interpolate,
+      header );
+
+   switch( full_decl->Declaration.Declare )  {
+   case  TGSI_DECLARE_RANGE:
+   {
+      struct tgsi_declaration_range *dr;
+
+      if( maxsize <=   size )
+         return 0;
+      dr = (struct tgsi_declaration_range *) &tokens[size];
+      size++;
+
+      *dr = tgsi_build_declaration_range(
+         full_decl->u.DeclarationRange.First,
+         full_decl->u.DeclarationRange.Last,
+         declaration,
+         header );
+      break;
+    }
+
+   case  TGSI_DECLARE_MASK:
+   {
+      struct  tgsi_declaration_mask *dm;
+
+      if( maxsize <=   size )
+         return 0;
+      dm = (struct tgsi_declaration_mask  *) &tokens[size];
+      size++;
+
+      *dm = tgsi_build_declaration_mask(
+         full_decl->u.DeclarationMask.Mask,
+         declaration,
+         header );
+      break;
+   }
+
+   default:
+      assert( 0 );
+   }
+
+   if( full_decl->Declaration.Interpolate ) {
+      struct tgsi_declaration_interpolation *di;
+
+      if( maxsize <= size )
+         return  0;
+      di = (struct tgsi_declaration_interpolation *) &tokens[size];
+      size++;
+
+      *di = tgsi_build_declaration_interpolation(
+         full_decl->Interpolation.Interpolate,
+         declaration,
+         header );
+   }
+
+   return size;
+}
+
+struct tgsi_declaration_range
+tgsi_build_declaration_range(
+   GLuint first,
+   GLuint last,
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header )
+{
+   struct tgsi_declaration_range declaration_range;
+
+   assert (last >=   first);
+   assert (last <=   0xFFFF);
+
+   declaration_range.First = first;
+   declaration_range.Last = last;
+
+   declaration_grow( declaration, header );
+
+   return declaration_range;
+}
+
+struct tgsi_declaration_mask
+tgsi_build_declaration_mask(
+   GLuint mask,
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header )
+{
+   struct tgsi_declaration_mask  declaration_mask;
+
+   declaration_mask.Mask = mask;
+
+   declaration_grow( declaration, header );
+
+   return declaration_mask;
+}
+
+struct tgsi_declaration_interpolation
+tgsi_default_declaration_interpolation( void )
+{
+   struct tgsi_declaration_interpolation di;
+
+   di.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+   di.Padding = 0;
+
+   return di;
+}
+
+struct tgsi_declaration_interpolation
+tgsi_build_declaration_interpolation(
+   GLuint interpolate,
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header )
+{
+   struct tgsi_declaration_interpolation di;
+
+   assert( interpolate <= TGSI_INTERPOLATE_PERSPECTIVE );
+
+   di = tgsi_default_declaration_interpolation();
+   di.Interpolate = interpolate;
+
+   declaration_grow( declaration, header );
+
+   return di;
+}
+
+/*
+ * immediate
+ */
+
+struct tgsi_immediate
+tgsi_default_immediate( void )
+{
+   struct tgsi_immediate immediate;
+
+   immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
+   immediate.Size = 1;
+   immediate.DataType = TGSI_IMM_FLOAT32;
+   immediate.Padding = 0;
+   immediate.Extended = 0;
+
+   return immediate;
+}
+
+struct tgsi_immediate
+tgsi_build_immediate(
+   struct tgsi_header *header )
+{
+   struct tgsi_immediate immediate;
+
+   immediate = tgsi_default_immediate();
+
+   header_bodysize_grow( header  );
+
+   return immediate;
+}
+
+struct tgsi_full_immediate
+tgsi_default_full_immediate( void )
+{
+   struct tgsi_full_immediate fullimm;
+
+   fullimm.Immediate = tgsi_default_immediate();
+   fullimm.u.Pointer = (void *) 0;
+
+   return fullimm;
+}
+
+static void
+immediate_grow(
+   struct tgsi_immediate *immediate,
+   struct tgsi_header *header )
+{
+   assert( immediate->Size < 0xFF );
+
+   immediate->Size++;
+
+   header_bodysize_grow( header );
+}
+
+struct tgsi_immediate_float32
+tgsi_build_immediate_float32(
+   GLfloat value,
+   struct tgsi_immediate *immediate,
+   struct tgsi_header *header )
+{
+   struct tgsi_immediate_float32 immediate_float32;
+
+   immediate_float32.Float = value;
+
+   immediate_grow( immediate, header );
+
+   return immediate_float32;
+}
+
+GLuint
+tgsi_build_full_immediate(
+   const struct tgsi_full_immediate *full_imm,
+   struct tgsi_token *tokens,
+   struct tgsi_header *header,
+   GLuint maxsize )
+{
+   GLuint size = 0,  i;
+   struct tgsi_immediate *immediate;
+
+   if( maxsize <= size )
+      return 0;
+   immediate = (struct tgsi_immediate *) &tokens[size];
+   size++;
+
+   *immediate = tgsi_build_immediate( header );
+
+   for( i = 0; i < full_imm->Immediate.Size - 1; i++ ) {
+      struct tgsi_immediate_float32 *if32;
+
+      if( maxsize <= size )
+         return  0;
+      if32 = (struct tgsi_immediate_float32 *) &tokens[size];
+      size++;
+
+      *if32  = tgsi_build_immediate_float32(
+         full_imm->u.ImmediateFloat32[i].Float,
+         immediate,
+         header );
+   }
+
+   return size;
+}
+
+/*
+ * instruction
+ */
+
+struct tgsi_instruction
+tgsi_default_instruction( void )
+{
+   struct tgsi_instruction instruction;
+
+   instruction.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
+   instruction.Size = 1;
+   instruction.Opcode = TGSI_OPCODE_MOV;
+   instruction.Saturate = TGSI_SAT_NONE;
+   instruction.NumDstRegs = 1;
+   instruction.NumSrcRegs = 1;
+   instruction.Padding  = 0;
+   instruction.Extended = 0;
+
+   return instruction;
+}
+
+struct tgsi_instruction
+tgsi_build_instruction(
+   GLuint opcode,
+   GLuint saturate,
+   GLuint num_dst_regs,
+   GLuint num_src_regs,
+   struct tgsi_header *header )
+{
+   struct tgsi_instruction instruction;
+
+   assert (opcode <= TGSI_OPCODE_LAST);
+   assert (saturate <= TGSI_SAT_MINUS_PLUS_ONE);
+   assert (num_dst_regs <= 3);
+   assert (num_src_regs <= 15);
+
+   instruction = tgsi_default_instruction();
+   instruction.Opcode = opcode;
+   instruction.Saturate = saturate;
+   instruction.NumDstRegs = num_dst_regs;
+   instruction.NumSrcRegs = num_src_regs;
+
+   header_bodysize_grow( header );
+
+   return instruction;
+}
+
+static void
+instruction_grow(
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   assert (instruction->Size <   0xFF);
+
+   instruction->Size++;
+
+   header_bodysize_grow( header );
+}
+
+struct tgsi_full_instruction
+tgsi_default_full_instruction( void )
+{
+   struct tgsi_full_instruction full_instruction;
+   GLuint i;
+
+   full_instruction.Instruction = tgsi_default_instruction();
+   full_instruction.InstructionExtNv = tgsi_default_instruction_ext_nv();
+   full_instruction.InstructionExtLabel = tgsi_default_instruction_ext_label();
+   full_instruction.InstructionExtTexture = tgsi_default_instruction_ext_texture();
+   for( i = 0;  i < TGSI_FULL_MAX_DST_REGISTERS; i++ ) {
+      full_instruction.FullDstRegisters[i] = tgsi_default_full_dst_register();
+   }
+   for( i = 0;  i < TGSI_FULL_MAX_SRC_REGISTERS; i++ ) {
+      full_instruction.FullSrcRegisters[i] = tgsi_default_full_src_register();
+   }
+
+   return full_instruction;
+}
+
+GLuint
+tgsi_build_full_instruction(
+   const struct tgsi_full_instruction *full_inst,
+   struct  tgsi_token *tokens,
+   struct  tgsi_header *header,
+   GLuint  maxsize )
+{
+   GLuint size = 0;
+   GLuint i;
+   struct tgsi_instruction *instruction;
+   struct tgsi_token *prev_token;
+
+   if( maxsize <= size )
+      return 0;
+   instruction = (struct tgsi_instruction *) &tokens[size];
+   size++;
+
+   *instruction = tgsi_build_instruction(
+      full_inst->Instruction.Opcode,
+      full_inst->Instruction.Saturate,
+      full_inst->Instruction.NumDstRegs,
+      full_inst->Instruction.NumSrcRegs,
+      header );
+   prev_token = (struct tgsi_token  *) instruction;
+
+   if( tgsi_compare_instruction_ext_nv(
+         full_inst->InstructionExtNv,
+         tgsi_default_instruction_ext_nv() ) ) {
+      struct tgsi_instruction_ext_nv *instruction_ext_nv;
+
+      if( maxsize <= size )
+         return 0;
+      instruction_ext_nv =
+         (struct  tgsi_instruction_ext_nv *) &tokens[size];
+      size++;
+
+      *instruction_ext_nv  = tgsi_build_instruction_ext_nv(
+         full_inst->InstructionExtNv.Precision,
+         full_inst->InstructionExtNv.CondDstIndex,
+         full_inst->InstructionExtNv.CondFlowIndex,
+         full_inst->InstructionExtNv.CondMask,
+         full_inst->InstructionExtNv.CondSwizzleX,
+         full_inst->InstructionExtNv.CondSwizzleY,
+         full_inst->InstructionExtNv.CondSwizzleZ,
+         full_inst->InstructionExtNv.CondSwizzleW,
+         full_inst->InstructionExtNv.CondDstUpdate,
+         full_inst->InstructionExtNv.CondFlowEnable,
+         prev_token,
+         instruction,
+         header );
+      prev_token = (struct tgsi_token  *) instruction_ext_nv;
+   }
+
+   if( tgsi_compare_instruction_ext_label(
+         full_inst->InstructionExtLabel,
+         tgsi_default_instruction_ext_label() ) ) {
+      struct tgsi_instruction_ext_label *instruction_ext_label;
+
+      if( maxsize <= size )
+         return 0;
+      instruction_ext_label =
+         (struct  tgsi_instruction_ext_label *) &tokens[size];
+      size++;
+
+      *instruction_ext_label = tgsi_build_instruction_ext_label(
+         full_inst->InstructionExtLabel.Label,
+         full_inst->InstructionExtLabel.Target,
+         prev_token,
+         instruction,
+         header );
+      prev_token = (struct tgsi_token  *) instruction_ext_label;
+   }
+
+   if( tgsi_compare_instruction_ext_texture(
+         full_inst->InstructionExtTexture,
+         tgsi_default_instruction_ext_texture() ) ) {
+      struct tgsi_instruction_ext_texture *instruction_ext_texture;
+
+      if( maxsize <= size )
+         return 0;
+      instruction_ext_texture =
+         (struct  tgsi_instruction_ext_texture *) &tokens[size];
+      size++;
+
+      *instruction_ext_texture = tgsi_build_instruction_ext_texture(
+         full_inst->InstructionExtTexture.Texture,
+         prev_token,
+         instruction,
+         header   );
+      prev_token = (struct tgsi_token  *) instruction_ext_texture;
+   }
+
+   for( i = 0;  i <   full_inst->Instruction.NumDstRegs; i++ ) {
+      const struct tgsi_full_dst_register *reg = &full_inst->FullDstRegisters[i];
+      struct tgsi_dst_register *dst_register;
+      struct tgsi_token *prev_token;
+
+      if( maxsize <= size )
+         return 0;
+      dst_register = (struct tgsi_dst_register *) &tokens[size];
+      size++;
+
+      *dst_register = tgsi_build_dst_register(
+         reg->DstRegister.File,
+         reg->DstRegister.WriteMask,
+         reg->DstRegister.Index,
+         instruction,
+         header );
+      prev_token = (struct tgsi_token  *) dst_register;
+
+      if( tgsi_compare_dst_register_ext_concode(
+            reg->DstRegisterExtConcode,
+            tgsi_default_dst_register_ext_concode() ) ) {
+         struct tgsi_dst_register_ext_concode *dst_register_ext_concode;
+
+         if( maxsize <= size )
+            return 0;
+         dst_register_ext_concode =
+            (struct  tgsi_dst_register_ext_concode *) &tokens[size];
+         size++;
+
+         *dst_register_ext_concode =   tgsi_build_dst_register_ext_concode(
+            reg->DstRegisterExtConcode.CondMask,
+            reg->DstRegisterExtConcode.CondSwizzleX,
+            reg->DstRegisterExtConcode.CondSwizzleY,
+            reg->DstRegisterExtConcode.CondSwizzleZ,
+            reg->DstRegisterExtConcode.CondSwizzleW,
+            reg->DstRegisterExtConcode.CondSrcIndex,
+            prev_token,
+            instruction,
+            header );
+         prev_token = (struct tgsi_token  *) dst_register_ext_concode;
+      }
+
+      if( tgsi_compare_dst_register_ext_modulate(
+            reg->DstRegisterExtModulate,
+            tgsi_default_dst_register_ext_modulate() ) ) {
+         struct tgsi_dst_register_ext_modulate *dst_register_ext_modulate;
+
+         if( maxsize <= size )
+            return 0;
+         dst_register_ext_modulate =
+            (struct  tgsi_dst_register_ext_modulate *) &tokens[size];
+         size++;
+
+         *dst_register_ext_modulate = tgsi_build_dst_register_ext_modulate(
+            reg->DstRegisterExtModulate.Modulate,
+            prev_token,
+            instruction,
+            header );
+         prev_token = (struct tgsi_token  *) dst_register_ext_modulate;
+      }
+   }
+
+   for( i = 0;  i < full_inst->Instruction.NumSrcRegs; i++ ) {
+      const struct tgsi_full_src_register *reg = &full_inst->FullSrcRegisters[i];
+      struct tgsi_src_register *src_register;
+      struct tgsi_token *prev_token;
+
+      if( maxsize <= size )
+         return 0;
+      src_register = (struct tgsi_src_register *)  &tokens[size];
+      size++;
+
+      *src_register = tgsi_build_src_register(
+         reg->SrcRegister.File,
+         reg->SrcRegister.SwizzleX,
+         reg->SrcRegister.SwizzleY,
+         reg->SrcRegister.SwizzleZ,
+         reg->SrcRegister.SwizzleW,
+         reg->SrcRegister.Negate,
+         reg->SrcRegister.Indirect,
+         reg->SrcRegister.Dimension,
+         reg->SrcRegister.Index,
+         instruction,
+         header );
+      prev_token = (struct tgsi_token  *) src_register;
+
+      if( tgsi_compare_src_register_ext_swz(
+            reg->SrcRegisterExtSwz,
+            tgsi_default_src_register_ext_swz() ) ) {
+         struct tgsi_src_register_ext_swz *src_register_ext_swz;
+
+         if( maxsize <= size )
+            return 0;
+         src_register_ext_swz =
+            (struct  tgsi_src_register_ext_swz *) &tokens[size];
+         size++;
+
+         *src_register_ext_swz = tgsi_build_src_register_ext_swz(
+            reg->SrcRegisterExtSwz.ExtSwizzleX,
+            reg->SrcRegisterExtSwz.ExtSwizzleY,
+            reg->SrcRegisterExtSwz.ExtSwizzleZ,
+            reg->SrcRegisterExtSwz.ExtSwizzleW,
+            reg->SrcRegisterExtSwz.NegateX,
+            reg->SrcRegisterExtSwz.NegateY,
+            reg->SrcRegisterExtSwz.NegateZ,
+            reg->SrcRegisterExtSwz.NegateW,
+            reg->SrcRegisterExtSwz.ExtDivide,
+            prev_token,
+            instruction,
+            header );
+         prev_token = (struct tgsi_token  *) src_register_ext_swz;
+      }
+
+      if( tgsi_compare_src_register_ext_mod(
+            reg->SrcRegisterExtMod,
+            tgsi_default_src_register_ext_mod() ) ) {
+         struct tgsi_src_register_ext_mod *src_register_ext_mod;
+
+         if( maxsize <= size )
+            return 0;
+         src_register_ext_mod =
+            (struct  tgsi_src_register_ext_mod *) &tokens[size];
+         size++;
+
+         *src_register_ext_mod = tgsi_build_src_register_ext_mod(
+            reg->SrcRegisterExtMod.Complement,
+            reg->SrcRegisterExtMod.Bias,
+            reg->SrcRegisterExtMod.Scale2X,
+            reg->SrcRegisterExtMod.Absolute,
+            reg->SrcRegisterExtMod.Negate,
+            prev_token,
+            instruction,
+            header );
+         prev_token = (struct tgsi_token  *) src_register_ext_mod;
+      }
+
+      if( reg->SrcRegister.Indirect ) {
+         struct  tgsi_src_register *ind;
+
+         if( maxsize <= size )
+            return 0;
+         ind = (struct tgsi_src_register *) &tokens[size];
+         size++;
+
+         *ind = tgsi_build_src_register(
+            reg->SrcRegisterInd.File,
+            reg->SrcRegisterInd.SwizzleX,
+            reg->SrcRegisterInd.SwizzleY,
+            reg->SrcRegisterInd.SwizzleZ,
+            reg->SrcRegisterInd.SwizzleW,
+            reg->SrcRegisterInd.Negate,
+            reg->SrcRegisterInd.Indirect,
+            reg->SrcRegisterInd.Dimension,
+            reg->SrcRegisterInd.Index,
+            instruction,
+            header );
+      }
+
+      if( reg->SrcRegister.Dimension ) {
+         struct  tgsi_dimension *dim;
+
+         assert( !reg->SrcRegisterDim.Dimension );
+
+         if( maxsize <= size )
+            return 0;
+         dim = (struct tgsi_dimension *) &tokens[size];
+         size++;
+
+         *dim = tgsi_build_dimension(
+            reg->SrcRegisterDim.Indirect,
+            reg->SrcRegisterDim.Index,
+            instruction,
+            header );
+
+         if( reg->SrcRegisterDim.Indirect ) {
+            struct tgsi_src_register *ind;
+
+            if( maxsize <= size )
+               return 0;
+            ind = (struct tgsi_src_register *) &tokens[size];
+            size++;
+
+            *ind = tgsi_build_src_register(
+               reg->SrcRegisterDimInd.File,
+               reg->SrcRegisterDimInd.SwizzleX,
+               reg->SrcRegisterDimInd.SwizzleY,
+               reg->SrcRegisterDimInd.SwizzleZ,
+               reg->SrcRegisterDimInd.SwizzleW,
+               reg->SrcRegisterDimInd.Negate,
+               reg->SrcRegisterDimInd.Indirect,
+               reg->SrcRegisterDimInd.Dimension,
+               reg->SrcRegisterDimInd.Index,
+               instruction,
+               header );
+         }
+      }
+   }
+
+   return size;
+}
+
+struct tgsi_instruction_ext_nv
+tgsi_default_instruction_ext_nv( void )
+{
+   struct tgsi_instruction_ext_nv instruction_ext_nv;
+
+   instruction_ext_nv.Type = TGSI_INSTRUCTION_EXT_TYPE_NV;
+   instruction_ext_nv.Precision = TGSI_PRECISION_DEFAULT;
+   instruction_ext_nv.CondDstIndex = 0;
+   instruction_ext_nv.CondFlowIndex = 0;
+   instruction_ext_nv.CondMask = TGSI_CC_TR;
+   instruction_ext_nv.CondSwizzleX = TGSI_SWIZZLE_X;
+   instruction_ext_nv.CondSwizzleY = TGSI_SWIZZLE_Y;
+   instruction_ext_nv.CondSwizzleZ = TGSI_SWIZZLE_Z;
+   instruction_ext_nv.CondSwizzleW = TGSI_SWIZZLE_W;
+   instruction_ext_nv.CondDstUpdate = 0;
+   instruction_ext_nv.CondFlowEnable = 0;
+   instruction_ext_nv.Padding = 0;
+   instruction_ext_nv.Extended = 0;
+
+   return instruction_ext_nv;
+}
+
+union token_u32
+{
+   GLuint   u32;
+};
+
+GLuint
+tgsi_compare_instruction_ext_nv(
+   struct tgsi_instruction_ext_nv a,
+   struct tgsi_instruction_ext_nv b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32;
+}
+
+struct tgsi_instruction_ext_nv
+tgsi_build_instruction_ext_nv(
+   GLuint precision,
+   GLuint cond_dst_index,
+   GLuint cond_flow_index,
+   GLuint cond_mask,
+   GLuint cond_swizzle_x,
+   GLuint cond_swizzle_y,
+   GLuint cond_swizzle_z,
+   GLuint cond_swizzle_w,
+   GLuint cond_dst_update,
+   GLuint cond_flow_update,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_instruction_ext_nv instruction_ext_nv;
+
+   instruction_ext_nv = tgsi_default_instruction_ext_nv();
+   instruction_ext_nv.Precision = precision;
+   instruction_ext_nv.CondDstIndex = cond_dst_index;
+   instruction_ext_nv.CondFlowIndex = cond_flow_index;
+   instruction_ext_nv.CondMask = cond_mask;
+   instruction_ext_nv.CondSwizzleX = cond_swizzle_x;
+   instruction_ext_nv.CondSwizzleY = cond_swizzle_y;
+   instruction_ext_nv.CondSwizzleZ = cond_swizzle_z;
+   instruction_ext_nv.CondSwizzleW = cond_swizzle_w;
+   instruction_ext_nv.CondDstUpdate = cond_dst_update;
+   instruction_ext_nv.CondFlowEnable = cond_flow_update;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return instruction_ext_nv;
+}
+
+struct tgsi_instruction_ext_label
+tgsi_default_instruction_ext_label( void )
+{
+   struct tgsi_instruction_ext_label instruction_ext_label;
+
+   instruction_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL;
+   instruction_ext_label.Label = 0;
+   instruction_ext_label.Target = 0;
+   instruction_ext_label.Padding = 0;
+   instruction_ext_label.Extended = 0;
+
+   return instruction_ext_label;
+}
+
+GLuint
+tgsi_compare_instruction_ext_label(
+   struct tgsi_instruction_ext_label a,
+   struct tgsi_instruction_ext_label b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return *(GLuint *) &a != *(GLuint *) &b;
+}
+
+struct tgsi_instruction_ext_label
+tgsi_build_instruction_ext_label(
+   GLuint label,
+   GLuint target,
+   struct tgsi_token  *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_instruction_ext_label instruction_ext_label;
+
+   instruction_ext_label = tgsi_default_instruction_ext_label();
+   instruction_ext_label.Label = label;
+   instruction_ext_label.Target = target;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return instruction_ext_label;
+}
+
+struct tgsi_instruction_ext_texture
+tgsi_default_instruction_ext_texture( void )
+{
+   struct tgsi_instruction_ext_texture instruction_ext_texture;
+
+   instruction_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE;
+   instruction_ext_texture.Texture = TGSI_TEXTURE_UNKNOWN;
+   instruction_ext_texture.Padding = 0;
+   instruction_ext_texture.Extended = 0;
+
+   return instruction_ext_texture;
+}
+
+GLuint
+tgsi_compare_instruction_ext_texture(
+   struct tgsi_instruction_ext_texture a,
+   struct tgsi_instruction_ext_texture b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return *(GLuint *) &a != *(GLuint *) &b;
+}
+
+struct tgsi_instruction_ext_texture
+tgsi_build_instruction_ext_texture(
+   GLuint texture,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_instruction_ext_texture instruction_ext_texture;
+
+   instruction_ext_texture = tgsi_default_instruction_ext_texture();
+   instruction_ext_texture.Texture = texture;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return instruction_ext_texture;
+}
+
+struct tgsi_src_register
+tgsi_default_src_register( void )
+{
+   struct tgsi_src_register src_register;
+
+   src_register.File = TGSI_FILE_NULL;
+   src_register.SwizzleX = TGSI_SWIZZLE_X;
+   src_register.SwizzleY = TGSI_SWIZZLE_Y;
+   src_register.SwizzleZ = TGSI_SWIZZLE_Z;
+   src_register.SwizzleW = TGSI_SWIZZLE_W;
+   src_register.Negate = 0;
+   src_register.Indirect = 0;
+   src_register.Dimension = 0;
+   src_register.Index = 0;
+   src_register.Extended = 0;
+
+   return src_register;
+}
+
+struct tgsi_src_register
+tgsi_build_src_register(
+   GLuint file,
+   GLuint swizzle_x,
+   GLuint swizzle_y,
+   GLuint swizzle_z,
+   GLuint swizzle_w,
+   GLuint negate,
+   GLuint indirect,
+   GLuint dimension,
+   GLint index,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_src_register   src_register;
+
+   assert( file <= TGSI_FILE_IMMEDIATE );
+   assert( swizzle_x <= TGSI_SWIZZLE_W );
+   assert( swizzle_y <= TGSI_SWIZZLE_W );
+   assert( swizzle_z <= TGSI_SWIZZLE_W );
+   assert( swizzle_w <= TGSI_SWIZZLE_W );
+   assert( negate <= 1 );
+   assert( index >= -0x8000 && index <= 0x7FFF );
+
+   src_register = tgsi_default_src_register();
+   src_register.File = file;
+   src_register.SwizzleX = swizzle_x;
+   src_register.SwizzleY = swizzle_y;
+   src_register.SwizzleZ = swizzle_z;
+   src_register.SwizzleW = swizzle_w;
+   src_register.Negate = negate;
+   src_register.Indirect = indirect;
+   src_register.Dimension = dimension;
+   src_register.Index = index;
+
+   instruction_grow( instruction, header );
+
+   return src_register;
+}
+
+struct tgsi_full_src_register
+tgsi_default_full_src_register( void )
+{
+   struct tgsi_full_src_register full_src_register;
+
+   full_src_register.SrcRegister = tgsi_default_src_register();
+   full_src_register.SrcRegisterExtSwz = tgsi_default_src_register_ext_swz();
+   full_src_register.SrcRegisterExtMod = tgsi_default_src_register_ext_mod();
+   full_src_register.SrcRegisterInd = tgsi_default_src_register();
+   full_src_register.SrcRegisterDim = tgsi_default_dimension();
+   full_src_register.SrcRegisterDimInd = tgsi_default_src_register();
+
+   return full_src_register;
+}
+
+struct tgsi_src_register_ext_swz
+tgsi_default_src_register_ext_swz( void )
+{
+   struct tgsi_src_register_ext_swz src_register_ext_swz;
+
+   src_register_ext_swz.Type = TGSI_SRC_REGISTER_EXT_TYPE_SWZ;
+   src_register_ext_swz.ExtSwizzleX = TGSI_EXTSWIZZLE_X;
+   src_register_ext_swz.ExtSwizzleY = TGSI_EXTSWIZZLE_Y;
+   src_register_ext_swz.ExtSwizzleZ = TGSI_EXTSWIZZLE_Z;
+   src_register_ext_swz.ExtSwizzleW = TGSI_EXTSWIZZLE_W;
+   src_register_ext_swz.NegateX = 0;
+   src_register_ext_swz.NegateY = 0;
+   src_register_ext_swz.NegateZ = 0;
+   src_register_ext_swz.NegateW = 0;
+   src_register_ext_swz.ExtDivide = TGSI_EXTSWIZZLE_ONE;
+   src_register_ext_swz.Padding = 0;
+   src_register_ext_swz.Extended = 0;
+
+   return src_register_ext_swz;
+}
+
+GLuint
+tgsi_compare_src_register_ext_swz(
+   struct tgsi_src_register_ext_swz a,
+   struct tgsi_src_register_ext_swz b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return *(GLuint *) &a != *(GLuint *) &b;
+}
+
+struct tgsi_src_register_ext_swz
+tgsi_build_src_register_ext_swz(
+   GLuint ext_swizzle_x,
+   GLuint ext_swizzle_y,
+   GLuint ext_swizzle_z,
+   GLuint ext_swizzle_w,
+   GLuint negate_x,
+   GLuint negate_y,
+   GLuint negate_z,
+   GLuint negate_w,
+   GLuint ext_divide,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_src_register_ext_swz src_register_ext_swz;
+
+   assert (ext_swizzle_x <= TGSI_EXTSWIZZLE_ONE);
+   assert (ext_swizzle_y <= TGSI_EXTSWIZZLE_ONE);
+   assert (ext_swizzle_z <= TGSI_EXTSWIZZLE_ONE);
+   assert (ext_swizzle_w <= TGSI_EXTSWIZZLE_ONE);
+   assert (negate_x <= 1);
+   assert (negate_y <= 1);
+   assert (negate_z <= 1);
+   assert (negate_w <= 1);
+   assert (ext_divide <= TGSI_EXTSWIZZLE_ONE);
+
+   src_register_ext_swz = tgsi_default_src_register_ext_swz();
+   src_register_ext_swz.ExtSwizzleX = ext_swizzle_x;
+   src_register_ext_swz.ExtSwizzleY = ext_swizzle_y;
+   src_register_ext_swz.ExtSwizzleZ = ext_swizzle_z;
+   src_register_ext_swz.ExtSwizzleW = ext_swizzle_w;
+   src_register_ext_swz.NegateX = negate_x;
+   src_register_ext_swz.NegateY = negate_y;
+   src_register_ext_swz.NegateZ = negate_z;
+   src_register_ext_swz.NegateW = negate_w;
+   src_register_ext_swz.ExtDivide = ext_divide;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return src_register_ext_swz;
+}
+
+struct tgsi_src_register_ext_mod
+tgsi_default_src_register_ext_mod( void )
+{
+   struct tgsi_src_register_ext_mod src_register_ext_mod;
+
+   src_register_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD;
+   src_register_ext_mod.Complement = 0;
+   src_register_ext_mod.Bias = 0;
+   src_register_ext_mod.Scale2X = 0;
+   src_register_ext_mod.Absolute = 0;
+   src_register_ext_mod.Negate = 0;
+   src_register_ext_mod.Padding = 0;
+   src_register_ext_mod.Extended = 0;
+
+   return src_register_ext_mod;
+}
+
+GLuint
+tgsi_compare_src_register_ext_mod(
+   struct tgsi_src_register_ext_mod a,
+   struct tgsi_src_register_ext_mod b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return *(GLuint *) &a != *(GLuint *) &b;
+}
+
+struct tgsi_src_register_ext_mod
+tgsi_build_src_register_ext_mod(
+   GLuint  complement,
+   GLuint  bias,
+   GLuint  scale_2x,
+   GLuint  absolute,
+   GLuint  negate,
+   struct  tgsi_token *prev_token,
+   struct  tgsi_instruction *instruction,
+   struct  tgsi_header *header )
+{
+   struct tgsi_src_register_ext_mod src_register_ext_mod;
+
+   assert (complement <= 1);
+   assert (bias <= 1);
+   assert (scale_2x <= 1);
+   assert (absolute <= 1);
+   assert (negate <= 1);
+
+   src_register_ext_mod = tgsi_default_src_register_ext_mod();
+   src_register_ext_mod.Complement = complement;
+   src_register_ext_mod.Bias = bias;
+   src_register_ext_mod.Scale2X = scale_2x;
+   src_register_ext_mod.Absolute = absolute;
+   src_register_ext_mod.Negate = negate;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return src_register_ext_mod;
+}
+
+struct tgsi_dimension
+tgsi_default_dimension( void )
+{
+   struct tgsi_dimension dimension;
+
+   dimension.Indirect = 0;
+   dimension.Dimension = 0;
+   dimension.Padding = 0;
+   dimension.Index = 0;
+   dimension.Extended = 0;
+
+   return dimension;
+}
+
+struct tgsi_dimension
+tgsi_build_dimension(
+   GLuint indirect,
+   GLuint index,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_dimension dimension;
+
+   dimension = tgsi_default_dimension();
+   dimension.Indirect = indirect;
+   dimension.Index = index;
+
+   instruction_grow( instruction, header );
+
+   return dimension;
+}
+
+struct tgsi_dst_register
+tgsi_default_dst_register( void )
+{
+   struct tgsi_dst_register dst_register;
+
+   dst_register.File = TGSI_FILE_NULL;
+   dst_register.WriteMask = TGSI_WRITEMASK_XYZW;
+   dst_register.Indirect = 0;
+   dst_register.Dimension = 0;
+   dst_register.Index = 0;
+   dst_register.Padding = 0;
+   dst_register.Extended = 0;
+
+   return dst_register;
+}
+
+struct tgsi_dst_register
+tgsi_build_dst_register(
+   GLuint file,
+   GLuint mask,
+   GLint index,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_dst_register dst_register;
+
+   assert (file <= TGSI_FILE_IMMEDIATE);
+   assert (mask <= TGSI_WRITEMASK_XYZW);
+   assert (index >= -32768 && index <= 32767);
+
+   dst_register = tgsi_default_dst_register();
+   dst_register.File = file;
+   dst_register.WriteMask = mask;
+   dst_register.Index = index;
+
+   instruction_grow( instruction, header );
+
+   return dst_register;
+}
+
+struct tgsi_full_dst_register
+tgsi_default_full_dst_register( void )
+{
+   struct tgsi_full_dst_register full_dst_register;
+
+   full_dst_register.DstRegister = tgsi_default_dst_register();
+   full_dst_register.DstRegisterExtConcode =
+      tgsi_default_dst_register_ext_concode();
+   full_dst_register.DstRegisterExtModulate =
+      tgsi_default_dst_register_ext_modulate();
+
+   return full_dst_register;
+}
+
+struct tgsi_dst_register_ext_concode
+tgsi_default_dst_register_ext_concode( void )
+{
+   struct tgsi_dst_register_ext_concode dst_register_ext_concode;
+
+   dst_register_ext_concode.Type = TGSI_DST_REGISTER_EXT_TYPE_CONDCODE;
+   dst_register_ext_concode.CondMask = TGSI_CC_TR;
+   dst_register_ext_concode.CondSwizzleX = TGSI_SWIZZLE_X;
+   dst_register_ext_concode.CondSwizzleY = TGSI_SWIZZLE_Y;
+   dst_register_ext_concode.CondSwizzleZ = TGSI_SWIZZLE_Z;
+   dst_register_ext_concode.CondSwizzleW = TGSI_SWIZZLE_W;
+   dst_register_ext_concode.CondSrcIndex = 0;
+   dst_register_ext_concode.Padding = 0;
+   dst_register_ext_concode.Extended = 0;
+
+   return dst_register_ext_concode;
+}
+
+GLuint
+tgsi_compare_dst_register_ext_concode(
+   struct tgsi_dst_register_ext_concode a,
+   struct tgsi_dst_register_ext_concode b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return *(GLuint *) &a != *(GLuint *) &b;
+}
+
+struct tgsi_dst_register_ext_concode
+tgsi_build_dst_register_ext_concode(
+   GLuint  cc,
+   GLuint  swizzle_x,
+   GLuint  swizzle_y,
+   GLuint  swizzle_z,
+   GLuint  swizzle_w,
+   GLint index,
+   struct  tgsi_token *prev_token,
+   struct  tgsi_instruction *instruction,
+   struct  tgsi_header *header )
+{
+   struct tgsi_dst_register_ext_concode dst_register_ext_concode;
+
+   assert (cc <= TGSI_CC_FL);
+   assert (swizzle_x <= TGSI_SWIZZLE_W);
+   assert (swizzle_y <= TGSI_SWIZZLE_W);
+   assert (swizzle_z <= TGSI_SWIZZLE_W);
+   assert (swizzle_w <= TGSI_SWIZZLE_W);
+   assert (index >= -32768 && index <= 32767);
+
+   dst_register_ext_concode = tgsi_default_dst_register_ext_concode();
+   dst_register_ext_concode.CondMask = cc;
+   dst_register_ext_concode.CondSwizzleX = swizzle_x;
+   dst_register_ext_concode.CondSwizzleY = swizzle_y;
+   dst_register_ext_concode.CondSwizzleZ = swizzle_z;
+   dst_register_ext_concode.CondSwizzleW = swizzle_w;
+   dst_register_ext_concode.CondSrcIndex = index;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return dst_register_ext_concode;
+}
+
+struct tgsi_dst_register_ext_modulate
+tgsi_default_dst_register_ext_modulate( void )
+{
+   struct tgsi_dst_register_ext_modulate dst_register_ext_modulate;
+
+   dst_register_ext_modulate.Type = TGSI_DST_REGISTER_EXT_TYPE_MODULATE;
+   dst_register_ext_modulate.Modulate = TGSI_MODULATE_1X;
+   dst_register_ext_modulate.Padding = 0;
+   dst_register_ext_modulate.Extended = 0;
+
+   return dst_register_ext_modulate;
+}
+
+GLuint
+tgsi_compare_dst_register_ext_modulate(
+   struct tgsi_dst_register_ext_modulate a,
+   struct tgsi_dst_register_ext_modulate b )
+{
+   a.Padding = b.Padding = 0;
+   a.Extended = b.Extended = 0;
+   return *(GLuint *) &a != *(GLuint *) &b;
+}
+
+struct tgsi_dst_register_ext_modulate
+tgsi_build_dst_register_ext_modulate(
+   GLuint modulate,
+   struct tgsi_token  *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header )
+{
+   struct tgsi_dst_register_ext_modulate dst_register_ext_modulate;
+
+   assert (modulate <=  TGSI_MODULATE_EIGHTH);
+
+   dst_register_ext_modulate = tgsi_default_dst_register_ext_modulate();
+   dst_register_ext_modulate.Modulate = modulate;
+
+   prev_token->Extended = 1;
+   instruction_grow( instruction, header );
+
+   return dst_register_ext_modulate;
+}
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_build.h b/src/mesa/pipe/tgsi/core/tgsi_build.h
new file mode 100644 (file)
index 0000000..db25956
--- /dev/null
@@ -0,0 +1,309 @@
+#if !defined TGSI_BUILD_H
+#define TGSI_BUILD_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+/*
+ * version
+ */
+
+struct tgsi_version
+tgsi_build_version( void );
+
+/*
+ * header
+ */
+
+struct tgsi_header
+tgsi_build_header( void );
+
+struct tgsi_processor
+tgsi_default_processor( void );
+
+struct tgsi_processor
+tgsi_build_processor(
+   GLuint processor,
+   struct tgsi_header *header );
+
+/*
+ * declaration
+ */
+
+struct tgsi_declaration
+tgsi_default_declaration( void );
+
+struct tgsi_declaration
+tgsi_build_declaration(
+   GLuint file,
+   GLuint declare,
+   GLuint interpolate,
+   struct tgsi_header *header );
+
+struct tgsi_full_declaration
+tgsi_default_full_declaration( void );
+
+GLuint
+tgsi_build_full_declaration(
+   const struct tgsi_full_declaration *full_decl,
+   struct tgsi_token *tokens,
+   struct tgsi_header *header,
+   GLuint maxsize );
+
+struct tgsi_declaration_range
+tgsi_build_declaration_range(
+   GLuint first,
+   GLuint last,
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header );
+
+struct tgsi_declaration_mask
+tgsi_build_declaration_mask(
+   GLuint mask,
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header );
+
+struct tgsi_declaration_interpolation
+tgsi_default_declaration_interpolation( void );
+
+struct tgsi_declaration_interpolation
+tgsi_build_declaration_interpolation(
+   GLuint interpolate,
+   struct tgsi_declaration *declaration,
+   struct tgsi_header *header );
+
+/*
+ * immediate
+ */
+
+struct tgsi_immediate
+tgsi_default_immediate( void );
+
+struct tgsi_immediate
+tgsi_build_immediate(
+   struct tgsi_header *header );
+
+struct tgsi_full_immediate
+tgsi_default_full_immediate( void );
+
+struct tgsi_immediate_float32
+tgsi_build_immediate_float32(
+   GLfloat value,
+   struct tgsi_immediate *immediate,
+   struct tgsi_header *header );
+
+GLuint
+tgsi_build_full_immediate(
+   const struct tgsi_full_immediate *full_imm,
+   struct tgsi_token *tokens,
+   struct tgsi_header *header,
+   GLuint maxsize );
+
+/*
+ * instruction
+ */
+
+struct tgsi_instruction
+tgsi_default_instruction( void );
+
+struct tgsi_instruction
+tgsi_build_instruction(
+   GLuint opcode,
+   GLuint saturate,
+   GLuint num_dst_regs,
+   GLuint num_src_regs,
+   struct tgsi_header *header );
+
+struct tgsi_full_instruction
+tgsi_default_full_instruction( void );
+
+GLuint
+tgsi_build_full_instruction(
+   const struct tgsi_full_instruction *full_inst,
+   struct tgsi_token *tokens,
+   struct tgsi_header *header,
+   GLuint maxsize );
+
+struct tgsi_instruction_ext_nv
+tgsi_default_instruction_ext_nv( void );
+
+GLuint
+tgsi_compare_instruction_ext_nv(
+   struct tgsi_instruction_ext_nv a,
+   struct tgsi_instruction_ext_nv b );
+
+struct tgsi_instruction_ext_nv
+tgsi_build_instruction_ext_nv(
+   GLuint precision,
+   GLuint cond_dst_index,
+   GLuint cond_flow_index,
+   GLuint cond_mask,
+   GLuint cond_swizzle_x,
+   GLuint cond_swizzle_y,
+   GLuint cond_swizzle_z,
+   GLuint cond_swizzle_w,
+   GLuint cond_dst_update,
+   GLuint cond_flow_update,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_instruction_ext_label
+tgsi_default_instruction_ext_label( void );
+
+GLuint
+tgsi_compare_instruction_ext_label(
+   struct tgsi_instruction_ext_label a,
+   struct tgsi_instruction_ext_label b );
+
+struct tgsi_instruction_ext_label
+tgsi_build_instruction_ext_label(
+   GLuint label,
+   GLuint target,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_instruction_ext_texture
+tgsi_default_instruction_ext_texture( void );
+
+GLuint
+tgsi_compare_instruction_ext_texture(
+   struct tgsi_instruction_ext_texture a,
+   struct tgsi_instruction_ext_texture b );
+
+struct tgsi_instruction_ext_texture
+tgsi_build_instruction_ext_texture(
+   GLuint texture,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_src_register
+tgsi_default_src_register( void );
+
+struct tgsi_src_register
+tgsi_build_src_register(
+   GLuint file,
+   GLuint swizzle_x,
+   GLuint swizzle_y,
+   GLuint swizzle_z,
+   GLuint swizzle_w,
+   GLuint negate,
+   GLuint indirect,
+   GLuint dimension,
+   GLint index,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_full_src_register
+tgsi_default_full_src_register( void );
+
+struct tgsi_src_register_ext_swz
+tgsi_default_src_register_ext_swz( void );
+
+GLuint
+tgsi_compare_src_register_ext_swz(
+   struct tgsi_src_register_ext_swz a,
+   struct tgsi_src_register_ext_swz b );
+
+struct tgsi_src_register_ext_swz
+tgsi_build_src_register_ext_swz(
+   GLuint ext_swizzle_x,
+   GLuint ext_swizzle_y,
+   GLuint ext_swizzle_z,
+   GLuint ext_swizzle_w,
+   GLuint negate_x,
+   GLuint negate_y,
+   GLuint negate_z,
+   GLuint negate_w,
+   GLuint ext_divide,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_src_register_ext_mod
+tgsi_default_src_register_ext_mod( void );
+
+GLuint
+tgsi_compare_src_register_ext_mod(
+   struct tgsi_src_register_ext_mod a,
+   struct tgsi_src_register_ext_mod b );
+
+struct tgsi_src_register_ext_mod
+tgsi_build_src_register_ext_mod(
+   GLuint complement,
+   GLuint bias,
+   GLuint scale_2x,
+   GLuint absolute,
+   GLuint negate,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_dimension
+tgsi_default_dimension( void );
+
+struct tgsi_dimension
+tgsi_build_dimension(
+   GLuint indirect,
+   GLuint index,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_dst_register
+tgsi_default_dst_register( void );
+
+struct tgsi_dst_register
+tgsi_build_dst_register(
+   GLuint file,
+   GLuint mask,
+   GLint index,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_full_dst_register
+tgsi_default_full_dst_register( void );
+
+struct tgsi_dst_register_ext_concode
+tgsi_default_dst_register_ext_concode( void );
+
+GLuint
+tgsi_compare_dst_register_ext_concode(
+   struct tgsi_dst_register_ext_concode a,
+   struct tgsi_dst_register_ext_concode b );
+
+struct tgsi_dst_register_ext_concode
+tgsi_build_dst_register_ext_concode(
+   GLuint cc,
+   GLuint swizzle_x,
+   GLuint swizzle_y,
+   GLuint swizzle_z,
+   GLuint swizzle_w,
+   GLint index,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+struct tgsi_dst_register_ext_modulate
+tgsi_default_dst_register_ext_modulate( void );
+
+GLuint
+tgsi_compare_dst_register_ext_modulate(
+   struct tgsi_dst_register_ext_modulate a,
+   struct tgsi_dst_register_ext_modulate b );
+
+struct tgsi_dst_register_ext_modulate
+tgsi_build_dst_register_ext_modulate(
+   GLuint modulate,
+   struct tgsi_token *prev_token,
+   struct tgsi_instruction *instruction,
+   struct tgsi_header *header );
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_BUILD_H
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_core.h b/src/mesa/pipe/tgsi/core/tgsi_core.h
new file mode 100644 (file)
index 0000000..1f5f00a
--- /dev/null
@@ -0,0 +1,12 @@
+#if !defined TGSI_CORE_H
+#define TGSI_CORE_H
+
+#include "tgsi_token.h"
+#include "tgsi_parse.h"
+#include "tgsi_build.h"
+#include "tgsi_exec.h"
+#include "tgsi_dump.h"
+#include "tgsi_util.h"
+
+#endif // !defined TGSI_CORE_H
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_dump.c b/src/mesa/pipe/tgsi/core/tgsi_dump.c
new file mode 100644 (file)
index 0000000..33a898e
--- /dev/null
@@ -0,0 +1,881 @@
+#include "tgsi_platform.h"
+#include "tgsi_core.h"
+
+struct text_dump
+{
+    FILE *file;
+    GLuint tabs;
+};
+
+static void
+text_dump_write(
+   struct text_dump *dump,
+   const void *buffer,
+   GLuint size )
+{
+   fwrite( buffer, size, 1, dump->file );
+}
+
+static void
+text_dump_str(
+   struct text_dump *dump,
+   const char *str )
+{
+   GLuint i;
+   GLuint len = strlen( str );
+
+   for( i = 0; i < len; i++ ) {
+      text_dump_write( dump, &str[i], 1 );
+
+      if( str[i] == '\n' ) {
+         GLuint i;
+
+         for( i = 0; i < dump->tabs; i++ ) {
+            text_dump_write( dump, "    ", 4 );
+         }
+      }
+   }
+}
+
+static void
+text_dump_chr(
+   struct text_dump *dump,
+   const char chr )
+{
+   char str[2];
+
+   str[0] = chr;
+   str[1] = '\0';
+   text_dump_str( dump, str );
+}
+
+static void
+text_dump_uix(
+   struct text_dump *dump,
+   const GLuint ui)
+{
+   char str[36];
+
+   sprintf( str, "0x%x", ui );
+   text_dump_str( dump, str );
+}
+
+static void
+text_dump_uid(
+   struct text_dump *dump,
+   const GLuint ui )
+{
+   char str[16];
+
+   sprintf( str, "%u", ui );
+   text_dump_str( dump, str );
+}
+
+static void
+text_dump_sid(
+   struct text_dump *dump,
+   const GLint si )
+{
+   char str[16];
+
+   sprintf( str, "%d", si );
+   text_dump_str( dump, str );
+}
+
+static void
+text_dump_flt(
+   struct text_dump *dump,
+   const GLfloat f )
+{
+   char str[48];
+
+   sprintf( str, "%40.6f", f );
+   text_dump_str( dump, str );
+}
+
+static void
+text_dump_enum(
+   struct text_dump *dump,
+   const GLuint e,
+   const char **enums,
+   const GLuint enums_count )
+{
+   if( e >= enums_count ) {
+      text_dump_uid( dump, e );
+   }
+   else {
+      text_dump_str( dump, enums[e] );
+   }
+}
+
+static void
+text_dump_tab(
+   struct text_dump *dump )
+{
+   dump->tabs++;
+}
+
+static void
+text_dump_untab(
+   struct text_dump *dump )
+{
+   assert( dump->tabs > 0 );
+
+   --dump->tabs;
+}
+
+#define TXT(S)          text_dump_str( &dump, S )
+#define CHR(C)          text_dump_chr( &dump, C )
+#define UIX(I)          text_dump_uix( &dump, I )
+#define UID(I)          text_dump_uid( &dump, I )
+#define SID(I)          text_dump_sid( &dump, I )
+#define FLT(F)          text_dump_flt( &dump, F )
+#define TAB()           text_dump_tab( &dump )
+#define UNT()           text_dump_untab( &dump )
+#define ENM(E,ENUMS)    text_dump_enum( &dump, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
+
+static const char *TGSI_PROCESSOR_TYPES[] =
+{
+   "PROCESSOR_FRAGMENT",
+   "PROCESSOR_VERTEX"
+};
+
+static const char *TGSI_TOKEN_TYPES[] =
+{
+   "TOKEN_TYPE_DECLARATION",
+   "TOKEN_TYPE_IMMEDIATE",
+   "TOKEN_TYPE_INSTRUCTION"
+};
+
+static const char *TGSI_FILES[] =
+{
+   "FILE_NULL",
+   "FILE_CONSTANT",
+   "FILE_INPUT",
+   "FILE_OUTPUT",
+   "FILE_TEMPORARY",
+   "FILE_SAMPLER",
+   "FILE_ADDRESS",
+   "FILE_IMMEDIATE"
+};
+
+static const char *TGSI_DECLARES[] =
+{
+   "DECLARE_RANGE",
+   "DECLARE_MASK"
+};
+
+static const char *TGSI_INTERPOLATES[] =
+{
+   "INTERPOLATE_CONSTANT",
+   "INTERPOLATE_LINEAR",
+   "INTERPOLATE_PERSPECTIVE"
+};
+
+static const char *TGSI_IMMS[] =
+{
+   "IMM_FLOAT32"
+};
+
+static const char *TGSI_OPCODES[] =
+{
+   "OPCODE_ARL",
+   "OPCODE_MOV",
+   "OPCODE_LIT",
+   "OPCODE_RCP",
+   "OPCODE_RSQ",
+   "OPCODE_EXP",
+   "OPCODE_LOG",
+   "OPCODE_MUL",
+   "OPCODE_ADD",
+   "OPCODE_DP3",
+   "OPCODE_DP4",
+   "OPCODE_DST",
+   "OPCODE_MIN",
+   "OPCODE_MAX",
+   "OPCODE_SLT",
+   "OPCODE_SGE",
+   "OPCODE_MAD",
+   "OPCODE_SUB",
+   "OPCODE_LERP",
+   "OPCODE_CND",
+   "OPCODE_CND0",
+   "OPCODE_DOT2ADD",
+   "OPCODE_INDEX",
+   "OPCODE_NEGATE",
+   "OPCODE_FRAC",
+   "OPCODE_CLAMP",
+   "OPCODE_FLOOR",
+   "OPCODE_ROUND",
+   "OPCODE_EXPBASE2",
+   "OPCODE_LOGBASE2",
+   "OPCODE_POWER",
+   "OPCODE_CROSSPRODUCT",
+   "OPCODE_MULTIPLYMATRIX",
+   "OPCODE_ABS",
+   "OPCODE_RCC",
+   "OPCODE_DPH",
+   "OPCODE_COS",
+   "OPCODE_DDX",
+   "OPCODE_DDY",
+   "OPCODE_KIL",
+   "OPCODE_PK2H",
+   "OPCODE_PK2US",
+   "OPCODE_PK4B",
+   "OPCODE_PK4UB",
+   "OPCODE_RFL",
+   "OPCODE_SEQ",
+   "OPCODE_SFL",
+   "OPCODE_SGT",
+   "OPCODE_SIN",
+   "OPCODE_SLE",
+   "OPCODE_SNE",
+   "OPCODE_STR",
+   "OPCODE_TEX",
+   "OPCODE_TXD",
+   "OPCODE_UP2H",
+   "OPCODE_UP2US",
+   "OPCODE_UP4B",
+   "OPCODE_UP4UB",
+   "OPCODE_X2D",
+   "OPCODE_ARA",
+   "OPCODE_ARR",
+   "OPCODE_BRA",
+   "OPCODE_CAL",
+   "OPCODE_RET",
+   "OPCODE_SSG",
+   "OPCODE_CMP",
+   "OPCODE_SCS",
+   "OPCODE_TXB",
+   "OPCODE_NRM",
+   "OPCODE_DIV",
+   "OPCODE_DP2",
+   "OPCODE_TXL",
+   "OPCODE_BRK",
+   "OPCODE_IF",
+   "OPCODE_LOOP",
+   "OPCODE_REP",
+   "OPCODE_ELSE",
+   "OPCODE_ENDIF",
+   "OPCODE_ENDLOOP",
+   "OPCODE_ENDREP",
+   "OPCODE_PUSHA",
+   "OPCODE_POPA",
+   "OPCODE_CEIL",
+   "OPCODE_I2F",
+   "OPCODE_NOT",
+   "OPCODE_TRUNC",
+   "OPCODE_SHL",
+   "OPCODE_SHR",
+   "OPCODE_AND",
+   "OPCODE_OR",
+   "OPCODE_MOD",
+   "OPCODE_XOR",
+   "OPCODE_SAD",
+   "OPCODE_TXF",
+   "OPCODE_TXQ",
+   "OPCODE_CONT",
+   "OPCODE_EMIT",
+   "OPCODE_ENDPRIM"
+};
+
+static const char *TGSI_SATS[] =
+{
+   "SAT_NONE",
+   "SAT_ZERO_ONE",
+   "SAT_MINUS_PLUS_ONE"
+};
+
+static const char *TGSI_INSTRUCTION_EXTS[] =
+{
+   "INSTRUCTION_EXT_TYPE_NV",
+   "INSTRUCTION_EXT_TYPE_LABEL",
+   "INSTRUCTION_EXT_TYPE_TEXTURE"
+};
+
+static const char *TGSI_PRECISIONS[] =
+{
+   "PRECISION_DEFAULT",
+   "TGSI_PRECISION_FLOAT32",
+   "TGSI_PRECISION_FLOAT16",
+   "TGSI_PRECISION_FIXED12"
+};
+
+static const char *TGSI_CCS[] =
+{
+   "CC_GT",
+   "CC_EQ",
+   "CC_LT",
+   "CC_UN",
+   "CC_GE",
+   "CC_LE",
+   "CC_NE",
+   "CC_TR",
+   "CC_FL"
+};
+
+static const char *TGSI_SWIZZLES[] =
+{
+   "SWIZZLE_X",
+   "SWIZZLE_Y",
+   "SWIZZLE_Z",
+   "SWIZZLE_W"
+};
+
+static const char *TGSI_TEXTURES[] =
+{
+   "TEXTURE_UNKNOWN",
+   "TEXTURE_1D",
+   "TEXTURE_2D",
+   "TEXTURE_3D",
+   "TEXTURE_CUBE",
+   "TEXTURE_RECT",
+   "TEXTURE_SHADOW1D",
+   "TEXTURE_SHADOW2D",
+   "TEXTURE_SHADOWRECT"
+};
+
+static const char *TGSI_SRC_REGISTER_EXTS[] =
+{
+   "SRC_REGISTER_EXT_TYPE_SWZ",
+   "SRC_REGISTER_EXT_TYPE_MOD"
+};
+
+static const char *TGSI_EXTSWIZZLES[] =
+{
+   "EXTSWIZZLE_X",
+   "EXTSWIZZLE_Y",
+   "EXTSWIZZLE_Z",
+   "EXTSWIZZLE_W",
+   "EXTSWIZZLE_ZERO",
+   "EXTSWIZZLE_ONE"
+};
+
+static const char *TGSI_WRITEMASKS[] =
+{
+   "0",
+   "WRITEMASK_X",
+   "WRITEMASK_Y",
+   "WRITEMASK_XY",
+   "WRITEMASK_Z",
+   "WRITEMASK_XZ",
+   "WRITEMASK_YZ",
+   "WRITEMASK_XYZ",
+   "WRITEMASK_W",
+   "WRITEMASK_XW",
+   "WRITEMASK_YW",
+   "WRITEMASK_XYW",
+   "WRITEMASK_ZW",
+   "WRITEMASK_XZW",
+   "WRITEMASK_YZW",
+   "WRITEMASK_XYZW"
+};
+
+static const char *TGSI_DST_REGISTER_EXTS[] =
+{
+   "DST_REGISTER_EXT_TYPE_CONDCODE",
+   "DST_REGISTER_EXT_TYPE_MODULATE"
+};
+
+static const char *TGSI_MODULATES[] =
+{
+   "MODULATE_1X",
+   "MODULATE_2X",
+   "MODULATE_4X",
+   "MODULATE_8X",
+   "MODULATE_HALF",
+   "MODULATE_QUARTER",
+   "MODULATE_EIGHTH"
+};
+
+void
+tgsi_dump(
+   const struct tgsi_token *tokens,
+   GLuint flags )
+{
+   struct text_dump dump;
+   struct tgsi_parse_context parse;
+   struct tgsi_full_instruction fi;
+   struct tgsi_full_declaration fd;
+   GLuint ignored = !(flags & TGSI_DUMP_NO_IGNORED);
+   GLuint deflt = !(flags & TGSI_DUMP_NO_DEFAULT);
+
+   {
+#if 0
+      static GLuint counter = 0;
+      char buffer[64];
+
+      sprintf( buffer, "tgsi-dump-%.4u.txt", counter++ );
+      dump.file = fopen( buffer, "wt" );
+#else
+      dump.file = stderr;
+      dump.tabs = 0;
+#endif
+   }
+
+   /* sanity check */
+   assert(strcmp(TGSI_OPCODES[TGSI_OPCODE_CONT], "OPCODE_CONT") == 0);
+
+   tgsi_parse_init( &parse, tokens );
+
+   TXT( "tgsi-dump begin" );
+
+   CHR( '\n' );
+   TXT( "\nMajorVersion: " );
+   UID( parse.FullVersion.Version.MajorVersion );
+   TXT( "\nMinorVersion: " );
+   UID( parse.FullVersion.Version.MinorVersion );
+
+   CHR( '\n' );
+   TXT( "\nHeaderSize: " );
+   UID( parse.FullHeader.Header.HeaderSize );
+   TXT( "\nBodySize  : " );
+   UID( parse.FullHeader.Header.BodySize );
+   TXT( "\nProcessor : " );
+   ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES );
+
+   fi = tgsi_default_full_instruction();
+   fd = tgsi_default_full_declaration();
+
+   while( !tgsi_parse_end_of_tokens( &parse ) ) {
+      GLuint i;
+
+      tgsi_parse_token( &parse );
+
+      CHR( '\n' );
+      TXT( "\nType       : " );
+      ENM( parse.FullToken.Token.Type, TGSI_TOKEN_TYPES );
+      if( ignored ) {
+         TXT( "\nSize       : " );
+         UID( parse.FullToken.Token.Size );
+         if( deflt || parse.FullToken.Token.Extended ) {
+            TXT( "\nExtended   : " );
+            UID( parse.FullToken.Token.Extended );
+         }
+      }
+
+      switch( parse.FullToken.Token.Type ) {
+      case TGSI_TOKEN_TYPE_DECLARATION:
+         {
+            struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration;
+
+            TXT( "\nFile       : " );
+            ENM( decl->Declaration.File, TGSI_FILES );
+            TXT( "\nDeclare    : " );
+            ENM( decl->Declaration.Declare, TGSI_DECLARES );
+            if( deflt || fd.Declaration.Interpolate != decl->Declaration.Interpolate ) {
+               TXT( "\nInterpolate: " );
+               UID( decl->Declaration.Interpolate );
+            }
+            if( ignored ) {
+               TXT( "\nPadding    : " );
+               UIX( decl->Declaration.Padding );
+            }
+
+            CHR( '\n' );
+            switch( decl->Declaration.Declare ) {
+            case TGSI_DECLARE_RANGE:
+               TXT( "\nFirst: " );
+               UID( decl->u.DeclarationRange.First );
+               TXT( "\nLast : " );
+               UID( decl->u.DeclarationRange.Last );
+               break;
+
+            case TGSI_DECLARE_MASK:
+               TXT( "\nMask: " );
+               UIX( decl->u.DeclarationMask.Mask );
+               break;
+
+            default:
+               assert( 0 );
+            }
+
+            if( decl->Declaration.Interpolate ) {
+               CHR( '\n' );
+               TXT( "\nInterpolate: " );
+               ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES );
+               if( ignored ) {
+                  TXT( "\nPadding    : " );
+                  UIX( decl->Interpolation.Padding );
+               }
+            }
+         }
+         break;
+
+      case TGSI_TOKEN_TYPE_IMMEDIATE:
+         TXT( "\nDataType   : " );
+         ENM( parse.FullToken.FullImmediate.Immediate.DataType, TGSI_IMMS );
+         if( ignored ) {
+            TXT( "\nPadding    : " );
+            UIX( parse.FullToken.FullImmediate.Immediate.Padding );
+         }
+
+         for( i = 0; i < parse.FullToken.FullImmediate.Immediate.Size - 1; i++ ) {
+            CHR( '\n' );
+            switch( parse.FullToken.FullImmediate.Immediate.DataType ) {
+            case TGSI_IMM_FLOAT32:
+               TXT( "\nFloat: " );
+               FLT( parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float );
+               break;
+
+            default:
+               assert( 0 );
+            }
+         }
+         break;
+
+      case TGSI_TOKEN_TYPE_INSTRUCTION:
+         {
+            struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction;
+
+            TXT( "\nOpcode     : " );
+            ENM( inst->Instruction.Opcode, TGSI_OPCODES );
+            if( deflt || fi.Instruction.Saturate != inst->Instruction.Saturate ) {
+               TXT( "\nSaturate   : " );
+               ENM( inst->Instruction.Saturate, TGSI_SATS );
+            }
+            if( deflt || fi.Instruction.NumDstRegs != inst->Instruction.NumDstRegs ) {
+               TXT( "\nNumDstRegs : " );
+               UID( inst->Instruction.NumDstRegs );
+            }
+            if( deflt || fi.Instruction.NumSrcRegs != inst->Instruction.NumSrcRegs ) {
+               TXT( "\nNumSrcRegs : " );
+               UID( inst->Instruction.NumSrcRegs );
+            }
+            if( ignored ) {
+               TXT( "\nPadding    : " );
+               UIX( inst->Instruction.Padding );
+            }
+
+            if( deflt || tgsi_compare_instruction_ext_nv( inst->InstructionExtNv, fi.InstructionExtNv)) {
+               CHR( '\n' );
+               TXT( "\nType          : " );
+               ENM( inst->InstructionExtNv.Type, TGSI_INSTRUCTION_EXTS );
+               if( deflt || fi.InstructionExtNv.Precision != inst->InstructionExtNv.Precision ) {
+                  TXT( "\nPrecision     : " );
+                  ENM( inst->InstructionExtNv.Precision, TGSI_PRECISIONS );
+               }
+               if( deflt || fi.InstructionExtNv.CondDstIndex != inst->InstructionExtNv.CondDstIndex ) {
+                  TXT( "\nCondDstIndex  : " );
+                  UID( inst->InstructionExtNv.CondDstIndex );
+               }
+               if( deflt || fi.InstructionExtNv.CondFlowIndex != inst->InstructionExtNv.CondFlowIndex ) {
+                  TXT( "\nCondFlowIndex : " );
+                  UID( inst->InstructionExtNv.CondFlowIndex );
+               }
+               if( deflt || fi.InstructionExtNv.CondMask != inst->InstructionExtNv.CondMask ) {
+                  TXT( "\nCondMask      : " );
+                  ENM( inst->InstructionExtNv.CondMask, TGSI_CCS );
+               }
+               if( deflt || fi.InstructionExtNv.CondSwizzleX != inst->InstructionExtNv.CondSwizzleX ) {
+                  TXT( "\nCondSwizzleX  : " );
+                  ENM( inst->InstructionExtNv.CondSwizzleX, TGSI_SWIZZLES );
+               }
+               if( deflt || fi.InstructionExtNv.CondSwizzleY != inst->InstructionExtNv.CondSwizzleY ) {
+                  TXT( "\nCondSwizzleY  : " );
+                  ENM( inst->InstructionExtNv.CondSwizzleY, TGSI_SWIZZLES );
+               }
+               if( deflt || fi.InstructionExtNv.CondSwizzleZ != inst->InstructionExtNv.CondSwizzleZ ) {
+                  TXT( "\nCondSwizzleZ  : " );
+                  ENM( inst->InstructionExtNv.CondSwizzleZ, TGSI_SWIZZLES );
+               }
+               if( deflt || fi.InstructionExtNv.CondSwizzleW != inst->InstructionExtNv.CondSwizzleW ) {
+                  TXT( "\nCondSwizzleW  : " );
+                  ENM( inst->InstructionExtNv.CondSwizzleW, TGSI_SWIZZLES );
+               }
+               if( deflt || fi.InstructionExtNv.CondDstUpdate != inst->InstructionExtNv.CondDstUpdate ) {
+                  TXT( "\nCondDstUpdate : " );
+                  UID( inst->InstructionExtNv.CondDstUpdate );
+               }
+               if( deflt || fi.InstructionExtNv.CondFlowEnable != inst->InstructionExtNv.CondFlowEnable ) {
+                  TXT( "\nCondFlowEnable: " );
+                  UID( inst->InstructionExtNv.CondFlowEnable );
+               }
+               if( ignored ) {
+                  TXT( "\nPadding       : " );
+                  UIX( inst->InstructionExtNv.Padding );
+                  if( deflt || fi.InstructionExtNv.Extended != inst->InstructionExtNv.Extended ) {
+                     TXT( "\nExtended      : " );
+                     UID( inst->InstructionExtNv.Extended );
+                  }
+               }
+            }
+
+            if( deflt || tgsi_compare_instruction_ext_label( inst->InstructionExtLabel, fi.InstructionExtLabel ) ) {
+               CHR( '\n' );
+               TXT( "\nType    : " );
+               ENM( inst->InstructionExtLabel.Type, TGSI_INSTRUCTION_EXTS );
+               if( deflt || fi.InstructionExtLabel.Label != inst->InstructionExtLabel.Label ) {
+                  TXT( "\nLabel   : " );
+                  UID( inst->InstructionExtLabel.Label );
+               }
+               if( deflt || fi.InstructionExtLabel.Target != inst->InstructionExtLabel.Target ) {
+                  TXT( "\nTarget  : " );
+                  UID( inst->InstructionExtLabel.Target );
+               }
+               if( ignored ) {
+                  TXT( "\nPadding : " );
+                  UIX( inst->InstructionExtLabel.Padding );
+                  if( deflt || fi.InstructionExtLabel.Extended != inst->InstructionExtLabel.Extended ) {
+                     TXT( "\nExtended: " );
+                     UID( inst->InstructionExtLabel.Extended );
+                  }
+               }
+            }
+
+            if( deflt || tgsi_compare_instruction_ext_texture( inst->InstructionExtTexture, fi.InstructionExtTexture ) ) {
+               CHR( '\n' );
+               TXT( "\nType    : " );
+               ENM( inst->InstructionExtTexture.Type, TGSI_INSTRUCTION_EXTS );
+               if( deflt || fi.InstructionExtTexture.Texture != inst->InstructionExtTexture.Texture ) {
+                  TXT( "\nTexture : " );
+                  ENM( inst->InstructionExtTexture.Texture, TGSI_TEXTURES );
+               }
+               if( ignored ) {
+                  TXT( "\nPadding : " );
+                  UIX( inst->InstructionExtTexture.Padding );
+                  if( deflt || fi.InstructionExtTexture.Extended != inst->InstructionExtTexture.Extended ) {
+                     TXT( "\nExtended: " );
+                     UID( inst->InstructionExtTexture.Extended );
+                  }
+               }
+            }
+
+            for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
+               struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
+               struct tgsi_full_dst_register *fd = &fi.FullDstRegisters[i];
+
+               CHR( '\n' );
+               TXT( "\nFile     : " );
+               ENM( dst->DstRegister.File, TGSI_FILES );
+               if( deflt || fd->DstRegister.WriteMask != dst->DstRegister.WriteMask ) {
+                  TXT( "\nWriteMask: " );
+                  ENM( dst->DstRegister.WriteMask, TGSI_WRITEMASKS );
+               }
+               if( ignored ) {
+                  if( deflt || fd->DstRegister.Indirect != dst->DstRegister.Indirect ) {
+                     TXT( "\nIndirect : " );
+                     UID( dst->DstRegister.Indirect );
+                  }
+                  if( deflt || fd->DstRegister.Dimension != dst->DstRegister.Dimension ) {
+                     TXT( "\nDimension: " );
+                     UID( dst->DstRegister.Dimension );
+                  }
+               }
+               if( deflt || fd->DstRegister.Index != dst->DstRegister.Index ) {
+                  TXT( "\nIndex    : " );
+                  SID( dst->DstRegister.Index );
+               }
+               if( ignored ) {
+                  TXT( "\nPadding  : " );
+                  UIX( dst->DstRegister.Padding );
+                  if( deflt || fd->DstRegister.Extended != dst->DstRegister.Extended ) {
+                     TXT( "\nExtended : " );
+                     UID( dst->DstRegister.Extended );
+                  }
+               }
+
+               if( deflt || tgsi_compare_dst_register_ext_concode( dst->DstRegisterExtConcode, fd->DstRegisterExtConcode ) ) {
+                  CHR( '\n' );
+                  TXT( "\nType        : " );
+                  ENM( dst->DstRegisterExtConcode.Type, TGSI_DST_REGISTER_EXTS );
+                  if( deflt || fd->DstRegisterExtConcode.CondMask != dst->DstRegisterExtConcode.CondMask ) {
+                     TXT( "\nCondMask    : " );
+                     ENM( dst->DstRegisterExtConcode.CondMask, TGSI_CCS );
+                  }
+                  if( deflt || fd->DstRegisterExtConcode.CondSwizzleX != dst->DstRegisterExtConcode.CondSwizzleX ) {
+                     TXT( "\nCondSwizzleX: " );
+                     ENM( dst->DstRegisterExtConcode.CondSwizzleX, TGSI_SWIZZLES );
+                  }
+                  if( deflt || fd->DstRegisterExtConcode.CondSwizzleY != dst->DstRegisterExtConcode.CondSwizzleY ) {
+                     TXT( "\nCondSwizzleY: " );
+                     ENM( dst->DstRegisterExtConcode.CondSwizzleY, TGSI_SWIZZLES );
+                  }
+                  if( deflt || fd->DstRegisterExtConcode.CondSwizzleZ != dst->DstRegisterExtConcode.CondSwizzleZ ) {
+                     TXT( "\nCondSwizzleZ: " );
+                     ENM( dst->DstRegisterExtConcode.CondSwizzleZ, TGSI_SWIZZLES );
+                  }
+                  if( deflt || fd->DstRegisterExtConcode.CondSwizzleW != dst->DstRegisterExtConcode.CondSwizzleW ) {
+                     TXT( "\nCondSwizzleW: " );
+                     ENM( dst->DstRegisterExtConcode.CondSwizzleW, TGSI_SWIZZLES );
+                  }
+                  if( deflt || fd->DstRegisterExtConcode.CondSrcIndex != dst->DstRegisterExtConcode.CondSrcIndex ) {
+                     TXT( "\nCondSrcIndex: " );
+                     UID( dst->DstRegisterExtConcode.CondSrcIndex );
+                  }
+                  if( ignored ) {
+                     TXT( "\nPadding     : " );
+                     UIX( dst->DstRegisterExtConcode.Padding );
+                     if( deflt || fd->DstRegisterExtConcode.Extended != dst->DstRegisterExtConcode.Extended ) {
+                        TXT( "\nExtended    : " );
+                        UID( dst->DstRegisterExtConcode.Extended );
+                     }
+                  }
+               }
+
+               if( deflt || tgsi_compare_dst_register_ext_modulate( dst->DstRegisterExtModulate, fd->DstRegisterExtModulate ) ) {
+                  CHR( '\n' );
+                  TXT( "\nType    : " );
+                  ENM( dst->DstRegisterExtModulate.Type, TGSI_DST_REGISTER_EXTS );
+                  if( deflt || fd->DstRegisterExtModulate.Modulate != dst->DstRegisterExtModulate.Modulate ) {
+                     TXT( "\nModulate: " );
+                     ENM( dst->DstRegisterExtModulate.Modulate, TGSI_MODULATES );
+                  }
+                  if( ignored ) {
+                     TXT( "\nPadding : " );
+                     UIX( dst->DstRegisterExtModulate.Padding );
+                     if( deflt || fd->DstRegisterExtModulate.Extended != dst->DstRegisterExtModulate.Extended ) {
+                        TXT( "\nExtended: " );
+                        UID( dst->DstRegisterExtModulate.Extended );
+                     }
+                  }
+               }
+            }
+
+            for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
+               struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
+               struct tgsi_full_src_register *fs = &fi.FullSrcRegisters[i];
+
+               CHR( '\n' );
+               TXT( "\nFile     : ");
+               ENM( src->SrcRegister.File, TGSI_FILES );
+               if( deflt || fs->SrcRegister.SwizzleX != src->SrcRegister.SwizzleX ) {
+                  TXT( "\nSwizzleX : " );
+                  ENM( src->SrcRegister.SwizzleX, TGSI_SWIZZLES );
+               }
+               if( deflt || fs->SrcRegister.SwizzleY != src->SrcRegister.SwizzleY ) {
+                  TXT( "\nSwizzleY : " );
+                  ENM( src->SrcRegister.SwizzleY, TGSI_SWIZZLES );
+               }
+               if( deflt || fs->SrcRegister.SwizzleZ != src->SrcRegister.SwizzleZ ) {
+                  TXT( "\nSwizzleZ : " );
+                  ENM( src->SrcRegister.SwizzleZ, TGSI_SWIZZLES );
+               }
+               if( deflt || fs->SrcRegister.SwizzleW != src->SrcRegister.SwizzleW ) {
+                  TXT( "\nSwizzleW : " );
+                  ENM( src->SrcRegister.SwizzleW, TGSI_SWIZZLES );
+               }
+               if( deflt || fs->SrcRegister.Negate != src->SrcRegister.Negate ) {
+                  TXT( "\nNegate   : " );
+                  UID( src->SrcRegister.Negate );
+               }
+               if( ignored ) {
+                  if( deflt || fs->SrcRegister.Indirect != src->SrcRegister.Indirect ) {
+                     TXT( "\nIndirect : " );
+                     UID( src->SrcRegister.Indirect );
+                  }
+                  if( deflt || fs->SrcRegister.Dimension != src->SrcRegister.Dimension ) {
+                     TXT( "\nDimension: " );
+                     UID( src->SrcRegister.Dimension );
+                  }
+               }
+               if( deflt || fs->SrcRegister.Index != src->SrcRegister.Index ) {
+                  TXT( "\nIndex    : " );
+                  SID( src->SrcRegister.Index );
+               }
+               if( ignored ) {
+                  if( deflt || fs->SrcRegister.Extended != src->SrcRegister.Extended ) {
+                     TXT( "\nExtended : " );
+                     UID( src->SrcRegister.Extended );
+                  }
+               }
+
+               if( deflt || tgsi_compare_src_register_ext_swz( src->SrcRegisterExtSwz, fs->SrcRegisterExtSwz ) ) {
+                  CHR( '\n' );
+                  TXT( "\nType       : " );
+                  ENM( src->SrcRegisterExtSwz.Type, TGSI_SRC_REGISTER_EXTS );
+                  if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleX != src->SrcRegisterExtSwz.ExtSwizzleX ) {
+                     TXT( "\nExtSwizzleX: " );
+                     ENM( src->SrcRegisterExtSwz.ExtSwizzleX, TGSI_EXTSWIZZLES );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleY != src->SrcRegisterExtSwz.ExtSwizzleY ) {
+                     TXT( "\nExtSwizzleY: " );
+                     ENM( src->SrcRegisterExtSwz.ExtSwizzleY, TGSI_EXTSWIZZLES );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleZ != src->SrcRegisterExtSwz.ExtSwizzleZ ) {
+                     TXT( "\nExtSwizzleZ: " );
+                     ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, TGSI_EXTSWIZZLES );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleW != src->SrcRegisterExtSwz.ExtSwizzleW ) {
+                     TXT( "\nExtSwizzleW: " );
+                     ENM( src->SrcRegisterExtSwz.ExtSwizzleW, TGSI_EXTSWIZZLES );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.NegateX != src->SrcRegisterExtSwz.NegateX ) {
+                     TXT( "\nNegateX   : " );
+                     UID( src->SrcRegisterExtSwz.NegateX );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.NegateY != src->SrcRegisterExtSwz.NegateY ) {
+                     TXT( "\nNegateY   : " );
+                     UID( src->SrcRegisterExtSwz.NegateY );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.NegateZ != src->SrcRegisterExtSwz.NegateZ ) {
+                     TXT( "\nNegateZ   : " );
+                     UID( src->SrcRegisterExtSwz.NegateZ );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.NegateW != src->SrcRegisterExtSwz.NegateW ) {
+                     TXT( "\nNegateW   : " );
+                     UID( src->SrcRegisterExtSwz.NegateW );
+                  }
+                  if( deflt || fs->SrcRegisterExtSwz.ExtDivide != src->SrcRegisterExtSwz.ExtDivide ) {
+                     TXT( "\nExtDivide  : " );
+                     ENM( src->SrcRegisterExtSwz.ExtDivide, TGSI_EXTSWIZZLES );
+                  }
+                  if( ignored ) {
+                     TXT( "\nPadding   : " );
+                     UIX( src->SrcRegisterExtSwz.Padding );
+                     if( deflt || fs->SrcRegisterExtSwz.Extended != src->SrcRegisterExtSwz.Extended ) {
+                        TXT( "\nExtended   : " );
+                        UID( src->SrcRegisterExtSwz.Extended );
+                     }
+                  }
+               }
+
+               if( deflt || tgsi_compare_src_register_ext_mod( src->SrcRegisterExtMod, fs->SrcRegisterExtMod ) ) {
+                  CHR( '\n' );
+                  TXT( "\nType     : " );
+                  ENM( src->SrcRegisterExtMod.Type, TGSI_SRC_REGISTER_EXTS );
+                  if( deflt || fs->SrcRegisterExtMod.Complement != src->SrcRegisterExtMod.Complement ) {
+                     TXT( "\nComplement: " );
+                     UID( src->SrcRegisterExtMod.Complement );
+                  }
+                  if( deflt || fs->SrcRegisterExtMod.Bias != src->SrcRegisterExtMod.Bias ) {
+                     TXT( "\nBias     : " );
+                     UID( src->SrcRegisterExtMod.Bias );
+                  }
+                  if( deflt || fs->SrcRegisterExtMod.Scale2X != src->SrcRegisterExtMod.Scale2X ) {
+                     TXT( "\nScale2X   : " );
+                     UID( src->SrcRegisterExtMod.Scale2X );
+                  }
+                  if( deflt || fs->SrcRegisterExtMod.Absolute != src->SrcRegisterExtMod.Absolute ) {
+                     TXT( "\nAbsolute  : " );
+                     UID( src->SrcRegisterExtMod.Absolute );
+                  }
+                  if( deflt || fs->SrcRegisterExtMod.Negate != src->SrcRegisterExtMod.Negate ) {
+                     TXT( "\nNegate   : " );
+                     UID( src->SrcRegisterExtMod.Negate );
+                  }
+                  if( ignored ) {
+                     TXT( "\nPadding   : " );
+                     UIX( src->SrcRegisterExtMod.Padding );
+                     if( deflt || fs->SrcRegisterExtMod.Extended != src->SrcRegisterExtMod.Extended ) {
+                        TXT( "\nExtended  : " );
+                        UID( src->SrcRegisterExtMod.Extended );
+                     }
+                  }
+               }
+            }
+         }
+         break;
+
+      default:
+         assert( 0 );
+      }
+   }
+
+   TXT( "\ntgsi-dump end\n" );
+
+   tgsi_parse_free( &parse );
+
+   fclose( dump.file );
+}
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_dump.h b/src/mesa/pipe/tgsi/core/tgsi_dump.h
new file mode 100644 (file)
index 0000000..dc34a84
--- /dev/null
@@ -0,0 +1,22 @@
+#if !defined TGSI_DUMP_H
+#define TGSI_DUMP_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+#define TGSI_DUMP_VERBOSE       0
+#define TGSI_DUMP_NO_IGNORED    1
+#define TGSI_DUMP_NO_DEFAULT    2
+
+void
+tgsi_dump(
+   const struct tgsi_token *tokens,
+   GLuint flags );
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_DUMP_H
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.c b/src/mesa/pipe/tgsi/core/tgsi_exec.c
new file mode 100644 (file)
index 0000000..6aaaef9
--- /dev/null
@@ -0,0 +1,2249 @@
+#include "tgsi_platform.h"
+#include "tgsi_core.h"
+
+#define MESA 1
+#if MESA
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/colormac.h"
+#include "swrast/swrast.h"
+#include "swrast/s_context.h"
+#endif
+
+#define TILE_BOTTOM_LEFT  0
+#define TILE_BOTTOM_RIGHT 1
+#define TILE_TOP_LEFT     2
+#define TILE_TOP_RIGHT    3
+
+#define TEMP_0_I           TGSI_EXEC_TEMP_00000000_I
+#define TEMP_0_C           TGSI_EXEC_TEMP_00000000_C
+#define TEMP_7F_I          TGSI_EXEC_TEMP_7FFFFFFF_I
+#define TEMP_7F_C          TGSI_EXEC_TEMP_7FFFFFFF_C
+#define TEMP_80_I          TGSI_EXEC_TEMP_80000000_I
+#define TEMP_80_C          TGSI_EXEC_TEMP_80000000_C
+#define TEMP_FF_I          TGSI_EXEC_TEMP_FFFFFFFF_I
+#define TEMP_FF_C          TGSI_EXEC_TEMP_FFFFFFFF_C
+#define TEMP_1_I           TGSI_EXEC_TEMP_ONE_I
+#define TEMP_1_C           TGSI_EXEC_TEMP_ONE_C
+#define TEMP_2_I           TGSI_EXEC_TEMP_TWO_I
+#define TEMP_2_C           TGSI_EXEC_TEMP_TWO_C
+#define TEMP_128_I         TGSI_EXEC_TEMP_128_I
+#define TEMP_128_C         TGSI_EXEC_TEMP_128_C
+#define TEMP_M128_I        TGSI_EXEC_TEMP_MINUS_128_I
+#define TEMP_M128_C        TGSI_EXEC_TEMP_MINUS_128_C
+#define TEMP_KILMASK_I     TGSI_EXEC_TEMP_KILMASK_I
+#define TEMP_KILMASK_C     TGSI_EXEC_TEMP_KILMASK_C
+#define TEMP_OUTPUT_I      TGSI_EXEC_TEMP_OUTPUT_I
+#define TEMP_OUTPUT_C      TGSI_EXEC_TEMP_OUTPUT_C
+#define TEMP_PRIMITIVE_I   TGSI_EXEC_TEMP_PRIMITIVE_I
+#define TEMP_PRIMITIVE_C   TGSI_EXEC_TEMP_PRIMITIVE_C
+#define TEMP_R0            TGSI_EXEC_TEMP_R0
+
+#define FOR_EACH_CHANNEL(CHAN)\
+   for (CHAN = 0; CHAN < 4; CHAN++)
+
+#define IS_CHANNEL_ENABLED(INST, CHAN)\
+   ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define IS_CHANNEL_ENABLED2(INST, CHAN)\
+   ((INST).FullDstRegisters[1].DstRegister.WriteMask & (1 << (CHAN)))
+
+#define FOR_EACH_ENABLED_CHANNEL(INST, CHAN)\
+   FOR_EACH_CHANNEL( CHAN )\
+      if (IS_CHANNEL_ENABLED( INST, CHAN ))
+
+#define FOR_EACH_ENABLED_CHANNEL2(INST, CHAN)\
+   FOR_EACH_CHANNEL( CHAN )\
+      if (IS_CHANNEL_ENABLED2( INST, CHAN ))
+
+#define CHAN_X  0
+#define CHAN_Y  1
+#define CHAN_Z  2
+#define CHAN_W  3
+
+void
+tgsi_exec_machine_init(
+   struct tgsi_exec_machine *mach,
+   struct tgsi_token *tokens )
+{
+   GLuint i, k;
+   struct tgsi_parse_context parse;
+
+   mach->Tokens = tokens;
+
+   k = tgsi_parse_init (&parse, mach->Tokens);
+   if (k != TGSI_PARSE_OK) {
+      printf("Problem parsing!\n");
+      return;
+   }
+
+   mach->Processor = parse.FullHeader.Processor.Processor;
+   tgsi_parse_free (&parse);
+
+   mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps);
+   mach->Addrs = &mach->Temps[TGSI_EXEC_NUM_TEMPS];
+
+#if XXX_SSE
+    tgsi_emit_sse (tokens,
+                   &mach->Function);
+#endif
+
+   /* Setup constants. */
+   for( i = 0; i < 4; i++ ) {
+      mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].u[i] = 0x00000000;
+      mach->Temps[TEMP_7F_I].xyzw[TEMP_7F_C].u[i] = 0x7FFFFFFF;
+      mach->Temps[TEMP_80_I].xyzw[TEMP_80_C].u[i] = 0x80000000;
+      mach->Temps[TEMP_FF_I].xyzw[TEMP_FF_C].u[i] = 0xFFFFFFFF;
+      mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].f[i] = 1.0f;
+      mach->Temps[TEMP_2_I].xyzw[TEMP_2_C].f[i] = 2.0f;
+      mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].f[i] = 128.0f;
+      mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].f[i] = -128.0f;
+   }
+}
+
+void
+tgsi_exec_prepare(
+   struct tgsi_exec_machine *mach,
+   struct tgsi_exec_labels *labels )
+{
+   struct tgsi_parse_context parse;
+   GLuint k;
+
+   mach->ImmLimit = 0;
+   labels->count = 0;
+
+   k = tgsi_parse_init( &parse, mach->Tokens );
+   if (k != TGSI_PARSE_OK) {
+      printf("Problem parsing!\n");
+      return;
+   }
+
+   while( !tgsi_parse_end_of_tokens( &parse ) ) {
+      GLuint pointer = parse.Position;
+      GLuint i;
+      tgsi_parse_token( &parse );
+      switch( parse.FullToken.Token.Type ) {
+      case TGSI_TOKEN_TYPE_DECLARATION:
+         break;
+      case TGSI_TOKEN_TYPE_IMMEDIATE:
+         assert( (parse.FullToken.FullImmediate.Immediate.Size - 1) % 4 == 0 );
+         assert( mach->ImmLimit + (parse.FullToken.FullImmediate.Immediate.Size - 1) / 4 <= 256 );
+         for( i = 0; i < parse.FullToken.FullImmediate.Immediate.Size - 1; i++ ) {
+            mach->Imms[mach->ImmLimit + i / 4][i % 4] = parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+         }
+         mach->ImmLimit += (parse.FullToken.FullImmediate.Immediate.Size - 1) / 4;
+         break;
+      case TGSI_TOKEN_TYPE_INSTRUCTION:
+         if( parse.FullToken.FullInstruction.InstructionExtLabel.Label &&
+             parse.FullToken.FullInstruction.InstructionExtLabel.Target ) {
+            assert( labels->count < 128 );
+            labels->labels[labels->count][0] = parse.FullToken.FullInstruction.InstructionExtLabel.Label;
+            labels->labels[labels->count][1] = pointer;
+            labels->count++;
+         }
+         break;
+      default:
+         assert( 0 );
+      }
+   }
+   tgsi_parse_free (&parse);
+}
+
+void
+tgsi_exec_machine_run(
+   struct tgsi_exec_machine *mach )
+{
+   struct tgsi_exec_labels labels;
+
+   tgsi_exec_prepare( mach, &labels );
+   tgsi_exec_machine_run2( mach, &labels );
+}
+
+static void
+micro_abs(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) fabs( (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) fabs( (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) fabs( (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) fabs( (GLdouble) src->f[3] );
+}
+
+static void
+micro_add(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = src0->f[0] + src1->f[0];
+   dst->f[1] = src0->f[1] + src1->f[1];
+   dst->f[2] = src0->f[2] + src1->f[2];
+   dst->f[3] = src0->f[3] + src1->f[3];
+}
+
+static void
+micro_iadd(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->i[0] = src0->i[0] + src1->i[0];
+   dst->i[1] = src0->i[1] + src1->i[1];
+   dst->i[2] = src0->i[2] + src1->i[2];
+   dst->i[3] = src0->i[3] + src1->i[3];
+}
+
+static void
+micro_and(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] & src1->u[0];
+   dst->u[1] = src0->u[1] & src1->u[1];
+   dst->u[2] = src0->u[2] & src1->u[2];
+   dst->u[3] = src0->u[3] & src1->u[3];
+}
+
+static void
+micro_ceil(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) ceil( (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) ceil( (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) ceil( (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) ceil( (GLdouble) src->f[3] );
+}
+
+static void
+micro_cos(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) cos( (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) cos( (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) cos( (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) cos( (GLdouble) src->f[3] );
+}
+
+static void
+micro_ddx(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] =
+   dst->f[1] =
+   dst->f[2] =
+   dst->f[3] = src->f[TILE_BOTTOM_RIGHT] - src->f[TILE_BOTTOM_LEFT];
+}
+
+static void
+micro_ddy(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] =
+   dst->f[1] =
+   dst->f[2] =
+   dst->f[3] = src->f[TILE_TOP_LEFT] - src->f[TILE_BOTTOM_LEFT];
+}
+
+static void
+micro_div(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = src0->f[0] / src1->f[0];
+   dst->f[1] = src0->f[1] / src1->f[1];
+   dst->f[2] = src0->f[2] / src1->f[2];
+   dst->f[3] = src0->f[3] / src1->f[3];
+}
+
+static void
+micro_udiv(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] / src1->u[0];
+   dst->u[1] = src0->u[1] / src1->u[1];
+   dst->u[2] = src0->u[2] / src1->u[2];
+   dst->u[3] = src0->u[3] / src1->u[3];
+}
+
+static void
+micro_eq(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1,
+   const union tgsi_exec_channel *src2,
+   const union tgsi_exec_channel *src3 )
+{
+   dst->f[0] = src0->f[0] == src1->f[0] ? src2->f[0] : src3->f[0];
+   dst->f[1] = src0->f[1] == src1->f[1] ? src2->f[1] : src3->f[1];
+   dst->f[2] = src0->f[2] == src1->f[2] ? src2->f[2] : src3->f[2];
+   dst->f[3] = src0->f[3] == src1->f[3] ? src2->f[3] : src3->f[3];
+}
+
+static void
+micro_ieq(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1,
+   const union tgsi_exec_channel *src2,
+   const union tgsi_exec_channel *src3 )
+{
+   dst->i[0] = src0->i[0] == src1->i[0] ? src2->i[0] : src3->i[0];
+   dst->i[1] = src0->i[1] == src1->i[1] ? src2->i[1] : src3->i[1];
+   dst->i[2] = src0->i[2] == src1->i[2] ? src2->i[2] : src3->i[2];
+   dst->i[3] = src0->i[3] == src1->i[3] ? src2->i[3] : src3->i[3];
+}
+
+static void
+micro_exp2(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) pow( 2.0, (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) pow( 2.0, (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) pow( 2.0, (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) pow( 2.0, (GLdouble) src->f[3] );
+}
+
+static void
+micro_f2it(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->i[0] = (GLint) src->f[0];
+   dst->i[1] = (GLint) src->f[1];
+   dst->i[2] = (GLint) src->f[2];
+   dst->i[3] = (GLint) src->f[3];
+}
+
+static void
+micro_f2ut(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->u[0] = (GLuint) src->f[0];
+   dst->u[1] = (GLuint) src->f[1];
+   dst->u[2] = (GLuint) src->f[2];
+   dst->u[3] = (GLuint) src->f[3];
+}
+
+static void
+micro_flr(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) floor( (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) floor( (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) floor( (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) floor( (GLdouble) src->f[3] );
+}
+
+static void
+micro_frc(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = src->f[0] - (GLfloat) floor( (GLdouble) src->f[0] );
+   dst->f[1] = src->f[1] - (GLfloat) floor( (GLdouble) src->f[1] );
+   dst->f[2] = src->f[2] - (GLfloat) floor( (GLdouble) src->f[2] );
+   dst->f[3] = src->f[3] - (GLfloat) floor( (GLdouble) src->f[3] );
+}
+
+static void
+micro_i2f(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) src->i[0];
+   dst->f[1] = (GLfloat) src->i[1];
+   dst->f[2] = (GLfloat) src->i[2];
+   dst->f[3] = (GLfloat) src->i[3];
+}
+
+static void
+micro_lg2(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) log( (GLdouble) src->f[0] ) * 1.442695f;
+   dst->f[1] = (GLfloat) log( (GLdouble) src->f[1] ) * 1.442695f;
+   dst->f[2] = (GLfloat) log( (GLdouble) src->f[2] ) * 1.442695f;
+   dst->f[3] = (GLfloat) log( (GLdouble) src->f[3] ) * 1.442695f;
+}
+
+static void
+micro_lt(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1,
+   const union tgsi_exec_channel *src2,
+   const union tgsi_exec_channel *src3 )
+{
+   dst->f[0] = src0->f[0] < src1->f[0] ? src2->f[0] : src3->f[0];
+   dst->f[1] = src0->f[1] < src1->f[1] ? src2->f[1] : src3->f[1];
+   dst->f[2] = src0->f[2] < src1->f[2] ? src2->f[2] : src3->f[2];
+   dst->f[3] = src0->f[3] < src1->f[3] ? src2->f[3] : src3->f[3];
+}
+
+static void
+micro_ilt(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1,
+   const union tgsi_exec_channel *src2,
+   const union tgsi_exec_channel *src3 )
+{
+   dst->i[0] = src0->i[0] < src1->i[0] ? src2->i[0] : src3->i[0];
+   dst->i[1] = src0->i[1] < src1->i[1] ? src2->i[1] : src3->i[1];
+   dst->i[2] = src0->i[2] < src1->i[2] ? src2->i[2] : src3->i[2];
+   dst->i[3] = src0->i[3] < src1->i[3] ? src2->i[3] : src3->i[3];
+}
+
+static void
+micro_ult(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1,
+   const union tgsi_exec_channel *src2,
+   const union tgsi_exec_channel *src3 )
+{
+   dst->u[0] = src0->u[0] < src1->u[0] ? src2->u[0] : src3->u[0];
+   dst->u[1] = src0->u[1] < src1->u[1] ? src2->u[1] : src3->u[1];
+   dst->u[2] = src0->u[2] < src1->u[2] ? src2->u[2] : src3->u[2];
+   dst->u[3] = src0->u[3] < src1->u[3] ? src2->u[3] : src3->u[3];
+}
+
+static void
+micro_max(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = src0->f[0] > src1->f[0] ? src0->f[0] : src1->f[0];
+   dst->f[1] = src0->f[1] > src1->f[1] ? src0->f[1] : src1->f[1];
+   dst->f[2] = src0->f[2] > src1->f[2] ? src0->f[2] : src1->f[2];
+   dst->f[3] = src0->f[3] > src1->f[3] ? src0->f[3] : src1->f[3];
+}
+
+static void
+micro_imax(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->i[0] = src0->i[0] > src1->i[0] ? src0->i[0] : src1->i[0];
+   dst->i[1] = src0->i[1] > src1->i[1] ? src0->i[1] : src1->i[1];
+   dst->i[2] = src0->i[2] > src1->i[2] ? src0->i[2] : src1->i[2];
+   dst->i[3] = src0->i[3] > src1->i[3] ? src0->i[3] : src1->i[3];
+}
+
+static void
+micro_umax(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] > src1->u[0] ? src0->u[0] : src1->u[0];
+   dst->u[1] = src0->u[1] > src1->u[1] ? src0->u[1] : src1->u[1];
+   dst->u[2] = src0->u[2] > src1->u[2] ? src0->u[2] : src1->u[2];
+   dst->u[3] = src0->u[3] > src1->u[3] ? src0->u[3] : src1->u[3];
+}
+
+static void
+micro_min(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = src0->f[0] < src1->f[0] ? src0->f[0] : src1->f[0];
+   dst->f[1] = src0->f[1] < src1->f[1] ? src0->f[1] : src1->f[1];
+   dst->f[2] = src0->f[2] < src1->f[2] ? src0->f[2] : src1->f[2];
+   dst->f[3] = src0->f[3] < src1->f[3] ? src0->f[3] : src1->f[3];
+}
+
+static void
+micro_imin(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->i[0] = src0->i[0] < src1->i[0] ? src0->i[0] : src1->i[0];
+   dst->i[1] = src0->i[1] < src1->i[1] ? src0->i[1] : src1->i[1];
+   dst->i[2] = src0->i[2] < src1->i[2] ? src0->i[2] : src1->i[2];
+   dst->i[3] = src0->i[3] < src1->i[3] ? src0->i[3] : src1->i[3];
+}
+
+static void
+micro_umin(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] < src1->u[0] ? src0->u[0] : src1->u[0];
+   dst->u[1] = src0->u[1] < src1->u[1] ? src0->u[1] : src1->u[1];
+   dst->u[2] = src0->u[2] < src1->u[2] ? src0->u[2] : src1->u[2];
+   dst->u[3] = src0->u[3] < src1->u[3] ? src0->u[3] : src1->u[3];
+}
+
+static void
+micro_umod(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] % src1->u[0];
+   dst->u[1] = src0->u[1] % src1->u[1];
+   dst->u[2] = src0->u[2] % src1->u[2];
+   dst->u[3] = src0->u[3] % src1->u[3];
+}
+
+static void
+micro_mul(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = src0->f[0] * src1->f[0];
+   dst->f[1] = src0->f[1] * src1->f[1];
+   dst->f[2] = src0->f[2] * src1->f[2];
+   dst->f[3] = src0->f[3] * src1->f[3];
+}
+
+static void
+micro_imul(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->i[0] = src0->i[0] * src1->i[0];
+   dst->i[1] = src0->i[1] * src1->i[1];
+   dst->i[2] = src0->i[2] * src1->i[2];
+   dst->i[3] = src0->i[3] * src1->i[3];
+}
+
+static void
+micro_imul64(
+   union tgsi_exec_channel *dst0,
+   union tgsi_exec_channel *dst1,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst1->i[0] = src0->i[0] * src1->i[0];
+   dst1->i[1] = src0->i[1] * src1->i[1];
+   dst1->i[2] = src0->i[2] * src1->i[2];
+   dst1->i[3] = src0->i[3] * src1->i[3];
+   dst0->i[0] = 0;
+   dst0->i[1] = 0;
+   dst0->i[2] = 0;
+   dst0->i[3] = 0;
+}
+
+static void
+micro_umul64(
+   union tgsi_exec_channel *dst0,
+   union tgsi_exec_channel *dst1,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst1->u[0] = src0->u[0] * src1->u[0];
+   dst1->u[1] = src0->u[1] * src1->u[1];
+   dst1->u[2] = src0->u[2] * src1->u[2];
+   dst1->u[3] = src0->u[3] * src1->u[3];
+   dst0->u[0] = 0;
+   dst0->u[1] = 0;
+   dst0->u[2] = 0;
+   dst0->u[3] = 0;
+}
+
+static void
+micro_movc(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1,
+   const union tgsi_exec_channel *src2 )
+{
+   dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0];
+   dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1];
+   dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2];
+   dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3];
+}
+
+static void
+micro_neg(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = -src->f[0];
+   dst->f[1] = -src->f[1];
+   dst->f[2] = -src->f[2];
+   dst->f[3] = -src->f[3];
+}
+
+static void
+micro_ineg(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->i[0] = -src->i[0];
+   dst->i[1] = -src->i[1];
+   dst->i[2] = -src->i[2];
+   dst->i[3] = -src->i[3];
+}
+
+static void
+micro_not(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->u[0] = ~src->u[0];
+   dst->u[1] = ~src->u[1];
+   dst->u[2] = ~src->u[2];
+   dst->u[3] = ~src->u[3];
+}
+
+static void
+micro_or(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] | src1->u[0];
+   dst->u[1] = src0->u[1] | src1->u[1];
+   dst->u[2] = src0->u[2] | src1->u[2];
+   dst->u[3] = src0->u[3] | src1->u[3];
+}
+
+static void
+micro_pow(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = (GLfloat) pow( (GLdouble) src0->f[0], (GLdouble) src1->f[0] );
+   dst->f[1] = (GLfloat) pow( (GLdouble) src0->f[1], (GLdouble) src1->f[1] );
+   dst->f[2] = (GLfloat) pow( (GLdouble) src0->f[2], (GLdouble) src1->f[2] );
+   dst->f[3] = (GLfloat) pow( (GLdouble) src0->f[3], (GLdouble) src1->f[3] );
+}
+
+static void
+micro_rnd(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) floor( (GLdouble) (src->f[0] + 0.5f) );
+   dst->f[1] = (GLfloat) floor( (GLdouble) (src->f[1] + 0.5f) );
+   dst->f[2] = (GLfloat) floor( (GLdouble) (src->f[2] + 0.5f) );
+   dst->f[3] = (GLfloat) floor( (GLdouble) (src->f[3] + 0.5f) );
+}
+
+static void
+micro_shl(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->i[0] = src0->i[0] << src1->i[0];
+   dst->i[1] = src0->i[1] << src1->i[1];
+   dst->i[2] = src0->i[2] << src1->i[2];
+   dst->i[3] = src0->i[3] << src1->i[3];
+}
+
+static void
+micro_ishr(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->i[0] = src0->i[0] >> src1->i[0];
+   dst->i[1] = src0->i[1] >> src1->i[1];
+   dst->i[2] = src0->i[2] >> src1->i[2];
+   dst->i[3] = src0->i[3] >> src1->i[3];
+}
+
+static void
+micro_ushr(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] >> src1->u[0];
+   dst->u[1] = src0->u[1] >> src1->u[1];
+   dst->u[2] = src0->u[2] >> src1->u[2];
+   dst->u[3] = src0->u[3] >> src1->u[3];
+}
+
+static void
+micro_sin(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) sin( (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) sin( (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) sin( (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) sin( (GLdouble) src->f[3] );
+}
+
+static void
+micro_sqrt( union tgsi_exec_channel *dst,
+            const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) sqrt( (GLdouble) src->f[0] );
+   dst->f[1] = (GLfloat) sqrt( (GLdouble) src->f[1] );
+   dst->f[2] = (GLfloat) sqrt( (GLdouble) src->f[2] );
+   dst->f[3] = (GLfloat) sqrt( (GLdouble) src->f[3] );
+}
+
+static void
+micro_sub(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->f[0] = src0->f[0] - src1->f[0];
+   dst->f[1] = src0->f[1] - src1->f[1];
+   dst->f[2] = src0->f[2] - src1->f[2];
+   dst->f[3] = src0->f[3] - src1->f[3];
+}
+
+static void
+micro_u2f(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src )
+{
+   dst->f[0] = (GLfloat) src->u[0];
+   dst->f[1] = (GLfloat) src->u[1];
+   dst->f[2] = (GLfloat) src->u[2];
+   dst->f[3] = (GLfloat) src->u[3];
+}
+
+static void
+micro_xor(
+   union tgsi_exec_channel *dst,
+   const union tgsi_exec_channel *src0,
+   const union tgsi_exec_channel *src1 )
+{
+   dst->u[0] = src0->u[0] ^ src1->u[0];
+   dst->u[1] = src0->u[1] ^ src1->u[1];
+   dst->u[2] = src0->u[2] ^ src1->u[2];
+   dst->u[3] = src0->u[3] ^ src1->u[3];
+}
+
+static void
+fetch_src_file_channel(
+   const struct tgsi_exec_machine *mach,
+   const GLuint file,
+   const GLuint swizzle,
+   const union tgsi_exec_channel *index,
+   union tgsi_exec_channel *chan )
+{
+   switch( swizzle ) {
+   case TGSI_EXTSWIZZLE_X:
+   case TGSI_EXTSWIZZLE_Y:
+   case TGSI_EXTSWIZZLE_Z:
+   case TGSI_EXTSWIZZLE_W:
+      switch( file ) {
+      case TGSI_FILE_CONSTANT:
+         chan->f[0] = mach->Consts[index->i[0]][swizzle];
+         chan->f[1] = mach->Consts[index->i[1]][swizzle];
+         chan->f[2] = mach->Consts[index->i[2]][swizzle];
+         chan->f[3] = mach->Consts[index->i[3]][swizzle];
+         break;
+
+      case TGSI_FILE_INPUT:
+         chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0];
+         chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1];
+         chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2];
+         chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3];
+         break;
+
+      case TGSI_FILE_TEMPORARY:
+         chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0];
+         chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1];
+         chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2];
+         chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3];
+         break;
+
+      case TGSI_FILE_IMMEDIATE:
+         assert( index->i[0] < (GLint) mach->ImmLimit );
+         chan->f[0] = mach->Imms[index->i[0]][swizzle];
+         assert( index->i[1] < (GLint) mach->ImmLimit );
+         chan->f[1] = mach->Imms[index->i[1]][swizzle];
+         assert( index->i[2] < (GLint) mach->ImmLimit );
+         chan->f[2] = mach->Imms[index->i[2]][swizzle];
+         assert( index->i[3] < (GLint) mach->ImmLimit );
+         chan->f[3] = mach->Imms[index->i[3]][swizzle];
+         break;
+
+      case TGSI_FILE_ADDRESS:
+         chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0];
+         chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1];
+         chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2];
+         chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3];
+         break;
+
+      default:
+         assert( 0 );
+      }
+      break;
+
+   case TGSI_EXTSWIZZLE_ZERO:
+      *chan = mach->Temps[TEMP_0_I].xyzw[TEMP_0_C];
+      break;
+
+   case TGSI_EXTSWIZZLE_ONE:
+      *chan = mach->Temps[TEMP_1_I].xyzw[TEMP_1_C];
+      break;
+
+   default:
+      assert( 0 );
+   }
+}
+
+static void
+fetch_source(
+   const struct tgsi_exec_machine *mach,
+   union tgsi_exec_channel *chan,
+   const struct tgsi_full_src_register *reg,
+   const GLuint chan_index )
+{
+   union tgsi_exec_channel index;
+   GLuint swizzle;
+
+   index.i[0] =
+   index.i[1] =
+   index.i[2] =
+   index.i[3] = reg->SrcRegister.Index;
+
+   if (reg->SrcRegister.Indirect) {
+      union tgsi_exec_channel index2;
+      union tgsi_exec_channel indir_index;
+
+      index2.i[0] =
+      index2.i[1] =
+      index2.i[2] =
+      index2.i[3] = reg->SrcRegisterInd.Index;
+
+      swizzle = tgsi_util_get_src_register_swizzle( &reg->SrcRegisterInd, CHAN_X );
+      fetch_src_file_channel(
+         mach,
+         reg->SrcRegisterInd.File,
+         swizzle,
+         &index2,
+         &indir_index );
+
+      index.i[0] += indir_index.i[0];
+      index.i[1] += indir_index.i[1];
+      index.i[2] += indir_index.i[2];
+      index.i[3] += indir_index.i[3];
+   }
+
+   if( reg->SrcRegister.Dimension ) {
+      switch( reg->SrcRegister.File ) {
+      case TGSI_FILE_INPUT:
+         index.i[0] *= 17;
+         index.i[1] *= 17;
+         index.i[2] *= 17;
+         index.i[3] *= 17;
+         break;
+      case TGSI_FILE_CONSTANT:
+         index.i[0] *= 4096;
+         index.i[1] *= 4096;
+         index.i[2] *= 4096;
+         index.i[3] *= 4096;
+         break;
+      default:
+         assert( 0 );
+      }
+
+      index.i[0] += reg->SrcRegisterDim.Index;
+      index.i[1] += reg->SrcRegisterDim.Index;
+      index.i[2] += reg->SrcRegisterDim.Index;
+      index.i[3] += reg->SrcRegisterDim.Index;
+
+      if (reg->SrcRegisterDim.Indirect) {
+         union tgsi_exec_channel index2;
+         union tgsi_exec_channel indir_index;
+
+         index2.i[0] =
+         index2.i[1] =
+         index2.i[2] =
+         index2.i[3] = reg->SrcRegisterDimInd.Index;
+
+         swizzle = tgsi_util_get_src_register_swizzle( &reg->SrcRegisterDimInd, CHAN_X );
+         fetch_src_file_channel(
+            mach,
+            reg->SrcRegisterDimInd.File,
+            swizzle,
+            &index2,
+            &indir_index );
+
+         index.i[0] += indir_index.i[0];
+         index.i[1] += indir_index.i[1];
+         index.i[2] += indir_index.i[2];
+         index.i[3] += indir_index.i[3];
+      }
+   }
+
+   swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
+   fetch_src_file_channel(
+      mach,
+      reg->SrcRegister.File,
+      swizzle,
+      &index,
+      chan );
+
+   switch (tgsi_util_get_full_src_register_sign_mode( reg, chan_index )) {
+   case TGSI_UTIL_SIGN_CLEAR:
+      micro_abs( chan, chan );
+      break;
+
+   case TGSI_UTIL_SIGN_SET:
+      micro_abs( chan, chan );
+      micro_neg( chan, chan );
+      break;
+
+   case TGSI_UTIL_SIGN_TOGGLE:
+      micro_neg( chan, chan );
+      break;
+
+   case TGSI_UTIL_SIGN_KEEP:
+      break;
+   }
+}
+
+static void
+store_dest(
+   struct tgsi_exec_machine *mach,
+   const union tgsi_exec_channel *chan,
+   const struct tgsi_full_dst_register *reg,
+   const struct tgsi_full_instruction *inst,
+   GLuint chan_index )
+{
+   union tgsi_exec_channel *dst;
+
+   switch( reg->DstRegister.File ) {
+   case TGSI_FILE_NULL:
+      return;
+
+   case TGSI_FILE_OUTPUT:
+      dst = &mach->Outputs[mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] + reg->DstRegister.Index].xyzw[chan_index];
+      break;
+
+   case TGSI_FILE_TEMPORARY:
+      dst = &mach->Temps[reg->DstRegister.Index].xyzw[chan_index];
+      break;
+
+   case TGSI_FILE_ADDRESS:
+      dst = &mach->Addrs[reg->DstRegister.Index].xyzw[chan_index];
+      break;
+
+   default:
+      assert( 0 );
+   }
+
+   switch (inst->Instruction.Saturate)
+   {
+   case TGSI_SAT_NONE:
+      *dst = *chan;
+      break;
+
+   case TGSI_SAT_ZERO_ONE:
+      micro_lt( dst, chan, &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], chan );
+      micro_lt( dst, chan, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], chan, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] );
+      break;
+
+   case TGSI_SAT_MINUS_PLUS_ONE:
+      assert( 0 );
+      break;
+
+   default:
+      assert( 0 );
+   }
+}
+
+#define FETCH(VAL,INDEX,CHAN)\
+    fetch_source (mach, VAL, &inst->FullSrcRegisters[INDEX], CHAN)
+
+#define STORE(VAL,INDEX,CHAN)\
+    store_dest (mach, VAL, &inst->FullDstRegisters[INDEX], inst, CHAN)
+
+static void
+exec_kil (struct tgsi_exec_machine *mach,
+          const struct tgsi_full_instruction *inst)
+{
+    GLuint uniquemask;
+    GLuint chan_index;
+    GLuint kilmask = 0;
+    union tgsi_exec_channel r[1];
+
+    /* This mask stores component bits that were already tested. Note that
+     * we test if the value is less than zero, so 1.0 and 0.0 need not to be
+     * tested. */
+    uniquemask = (1 << TGSI_EXTSWIZZLE_ZERO) | (1 << TGSI_EXTSWIZZLE_ONE);
+
+    for (chan_index = 0; chan_index < 4; chan_index++)
+    {
+        GLuint swizzle;
+        GLuint i;
+
+        /* unswizzle channel */
+        swizzle = tgsi_util_get_full_src_register_extswizzle (
+                        &inst->FullSrcRegisters[0],
+                        chan_index);
+
+        /* check if the component has not been already tested */
+        if (uniquemask & (1 << swizzle))
+            continue;
+        uniquemask |= 1 << swizzle;
+
+        FETCH(&r[0], 0, chan_index);
+        for (i = 0; i < 4; i++)
+            if (r[0].f[i] < 0.0f)
+                kilmask |= 1 << (i * 4);
+    }
+
+    mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
+}
+
+#if MESA
+/*
+ * Fetch a texel using S texture coordinate.
+ */
+static void
+fetch_texel_1d( GLcontext *ctx,
+                struct tgsi_sampler_state *sampler,
+                const union tgsi_exec_channel *s,
+                GLuint unit,
+                union tgsi_exec_channel *r,
+                union tgsi_exec_channel *g,
+                union tgsi_exec_channel *b,
+                union tgsi_exec_channel *a )
+{
+    SWcontext *swrast = SWRAST_CONTEXT(ctx);
+    GLuint fragment_index;
+    GLfloat stpq[4][4];
+    GLfloat lambdas[4];
+    GLchan rgba[4][4];
+
+    for (fragment_index = 0; fragment_index < 4; fragment_index++)
+    {
+        stpq[fragment_index][0] = s->f[fragment_index];
+    }
+
+    if (sampler->NeedLambda)
+    {
+        GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT];
+        GLfloat dsdy = s->f[TILE_TOP_LEFT]     - s->f[TILE_BOTTOM_LEFT];
+
+        GLfloat rho, lambda;
+
+        dsdx = FABSF(dsdx);
+        dsdy = FABSF(dsdy);
+
+        rho = MAX2(dsdx, dsdy) * sampler->ImageWidth;
+
+        lambda = LOG2(rho);
+
+        if (sampler->NeedLodBias)
+            lambda += sampler->LodBias;
+
+        if (sampler->NeedLambdaClamp)
+            lambda = CLAMP(lambda, sampler->MinLod, sampler->MaxLod);
+
+        /* XXX: Use the same lambda value throughout the tile.  Could
+         * end up with four unique values by recalculating partial
+         * derivs in the other row and column, and calculating lambda
+         * using the dx and dy values appropriate for each fragment in
+         * the tile.
+         */
+        lambdas[0] =
+        lambdas[1] =
+        lambdas[2] = 
+        lambdas[3] = lambda;
+    }
+
+    if (!swrast->TextureSample[unit]) {
+       _swrast_update_texture_samplers(ctx);
+    }
+
+    /* XXX use a float-valued TextureSample routine here!!! */
+    swrast->TextureSample[unit] (ctx,
+                                 ctx->Texture.Unit[unit]._Current,
+                                 4,
+                                 (const GLfloat (*)[4])stpq,
+                                 lambdas,
+                                 rgba);
+
+    for (fragment_index = 0; fragment_index < 4; fragment_index++)
+    {
+        r->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][0]);
+        g->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][1]);
+        b->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][2]);
+        a->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][3]);
+    }
+}
+
+/*
+ * Fetch a texel using ST texture coordinates.
+ */
+static void
+fetch_texel_2d( GLcontext *ctx,
+                struct tgsi_sampler_state *sampler,
+                const union tgsi_exec_channel *s,
+                const union tgsi_exec_channel *t,
+                GLuint unit,
+                union tgsi_exec_channel *r,
+                union tgsi_exec_channel *g,
+                union tgsi_exec_channel *b,
+                union tgsi_exec_channel *a )
+{
+   SWcontext *swrast = SWRAST_CONTEXT( ctx );
+   GLuint fragment_index;
+   GLfloat stpq[4][4];
+   GLfloat lambdas[4];
+   GLchan rgba[4][4];
+
+   for (fragment_index = 0; fragment_index < 4; fragment_index++) {
+      stpq[fragment_index][0] = s->f[fragment_index];
+      stpq[fragment_index][1] = t->f[fragment_index];
+   }
+
+   if (sampler->NeedLambda) {
+      GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT];
+      GLfloat dsdy = s->f[TILE_TOP_LEFT]     - s->f[TILE_BOTTOM_LEFT];
+
+      GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT];
+      GLfloat dtdy = t->f[TILE_TOP_LEFT]     - t->f[TILE_BOTTOM_LEFT];
+
+      GLfloat maxU, maxV, rho, lambda;
+
+      dsdx = FABSF( dsdx );
+      dsdy = FABSF( dsdy );
+      dtdx = FABSF( dtdx );
+      dtdy = FABSF( dtdy );
+
+      maxU = MAX2( dsdx, dsdy ) * sampler->ImageWidth;
+      maxV = MAX2( dtdx, dtdy ) * sampler->ImageHeight;
+
+      rho = MAX2( maxU, maxV );
+
+      lambda = LOG2( rho );
+
+      if (sampler->NeedLodBias)
+        lambda += sampler->LodBias;
+
+      if (sampler->NeedLambdaClamp)
+         lambda = CLAMP(
+                    lambda,
+                    sampler->MinLod,
+                    sampler->MaxLod );
+
+      /* XXX: Use the same lambda value throughout the tile.  Could
+        * end up with four unique values by recalculating partial
+        * derivs in the other row and column, and calculating lambda
+        * using the dx and dy values appropriate for each fragment in
+        * the tile.
+        */
+      lambdas[0] =
+      lambdas[1] =
+      lambdas[2] = 
+      lambdas[3] = lambda;
+   }
+
+   if (!swrast->TextureSample[unit]) {
+      _swrast_update_texture_samplers(ctx);
+   }
+
+   /* XXX use a float-valued TextureSample routine here!!! */
+   swrast->TextureSample[unit](
+      ctx,
+      ctx->Texture.Unit[unit]._Current,
+      4,
+      (const GLfloat (*)[4]) stpq,
+      lambdas,
+      rgba );
+
+   for (fragment_index = 0; fragment_index < 4; fragment_index++) {
+      r->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][0] );
+      g->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][1] );
+      b->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][2] );
+      a->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][3] );
+   }
+}
+
+/*
+ * Fetch a texel using STR texture coordinates.
+ */
+static void
+fetch_texel_3d( GLcontext *ctx,
+                struct tgsi_sampler_state *sampler,
+                const union tgsi_exec_channel *s,
+                const union tgsi_exec_channel *t,
+                const union tgsi_exec_channel *p,
+                GLuint unit,
+                union tgsi_exec_channel *r,
+                union tgsi_exec_channel *g,
+                union tgsi_exec_channel *b,
+                union tgsi_exec_channel *a )
+{
+    SWcontext *swrast = SWRAST_CONTEXT(ctx);
+    GLuint fragment_index;
+    GLfloat stpq[4][4];
+    GLfloat lambdas[4];
+    GLchan rgba[4][4];
+
+    for (fragment_index = 0; fragment_index < 4; fragment_index++)
+    {
+        stpq[fragment_index][0] = s->f[fragment_index];
+        stpq[fragment_index][1] = t->f[fragment_index];
+        stpq[fragment_index][2] = p->f[fragment_index];
+    }
+
+    if (sampler->NeedLambda)
+    {
+        GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT];
+        GLfloat dsdy = s->f[TILE_TOP_LEFT]     - s->f[TILE_BOTTOM_LEFT];
+
+        GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT];
+        GLfloat dtdy = t->f[TILE_TOP_LEFT]     - t->f[TILE_BOTTOM_LEFT];
+
+        GLfloat dpdx = p->f[TILE_BOTTOM_RIGHT] - p->f[TILE_BOTTOM_LEFT];
+        GLfloat dpdy = p->f[TILE_TOP_LEFT]     - p->f[TILE_BOTTOM_LEFT];
+
+        GLfloat maxU, maxV, maxW, rho, lambda;
+
+        dsdx = FABSF(dsdx);
+        dsdy = FABSF(dsdy);
+        dtdx = FABSF(dtdx);
+        dtdy = FABSF(dtdy);
+        dpdx = FABSF(dpdx);
+        dpdy = FABSF(dpdy);
+
+        maxU = MAX2(dsdx, dsdy) * sampler->ImageWidth;
+        maxV = MAX2(dtdx, dtdy) * sampler->ImageHeight;
+        maxW = MAX2(dpdx, dpdy) * sampler->ImageDepth;
+
+        rho = MAX2(maxU, MAX2(maxV, maxW));
+
+        lambda = LOG2(rho);
+
+        if (sampler->NeedLodBias)
+            lambda += sampler->LodBias;
+
+        if (sampler->NeedLambdaClamp)
+            lambda = CLAMP(lambda, sampler->MinLod, sampler->MaxLod);
+
+        /* XXX: Use the same lambda value throughout the tile.  Could
+         * end up with four unique values by recalculating partial
+         * derivs in the other row and column, and calculating lambda
+         * using the dx and dy values appropriate for each fragment in
+         * the tile.
+         */
+        lambdas[0] =
+        lambdas[1] =
+        lambdas[2] = 
+        lambdas[3] = lambda;
+    }
+
+    if (!swrast->TextureSample[unit]) {
+       _swrast_update_texture_samplers(ctx);
+    }
+
+    /* XXX use a float-valued TextureSample routine here!!! */
+    swrast->TextureSample[unit] (ctx,
+                                 ctx->Texture.Unit[unit]._Current,
+                                 4,
+                                 (const GLfloat (*)[4])stpq,
+                                 lambdas,
+                                 rgba);
+
+    for (fragment_index = 0; fragment_index < 4; fragment_index++)
+    {
+        r->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][0]);
+        g->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][1]);
+        b->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][2]);
+        a->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][3]);
+    }
+}
+#endif
+
+static GLuint
+map_label(
+   GLuint label,
+   struct tgsi_exec_labels *labels )
+{
+   GLuint i;
+
+   for( i = 0; i < labels->count; i++ ) {
+      if( labels->labels[i][0] == label ) {
+         return labels->labels[i][1];
+      }
+   }
+   assert( 0 );
+   return 0;
+}
+
+static void
+exec_instruction(
+   struct tgsi_exec_machine *mach,
+   const struct tgsi_full_instruction *inst,
+   struct tgsi_exec_labels *labels,
+   GLuint *programCounter )
+{
+#if MESA
+   GET_CURRENT_CONTEXT(ctx);
+#endif
+   GLuint chan_index;
+   union tgsi_exec_channel r[8];
+
+   switch (inst->Instruction.Opcode) {
+   case TGSI_OPCODE_ARL:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        FETCH( &r[0], 0, chan_index );
+        micro_f2it( &r[0], &r[0] );
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_MOV:
+   /* TGSI_OPCODE_SWZ */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_LIT:
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+        STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X );
+      }
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_Y ) || IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+        FETCH( &r[0], 0, CHAN_X );
+        if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+           micro_max( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+           STORE( &r[0], 0, CHAN_Y );
+        }
+
+        if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+           FETCH( &r[1], 0, CHAN_Y );
+           micro_max( &r[1], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+
+           FETCH( &r[2], 0, CHAN_W );
+           micro_min( &r[2], &r[2], &mach->Temps[TEMP_128_I].xyzw[TEMP_128_C] );
+           micro_max( &r[2], &r[2], &mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C] );
+           micro_pow( &r[1], &r[1], &r[2] );
+           micro_lt( &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+           STORE( &r[0], 0, CHAN_Z );
+        }
+      }
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+        STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+      }
+      break;
+
+   case TGSI_OPCODE_RCP:
+   /* TGSI_OPCODE_RECIP */
+      FETCH( &r[0], 0, CHAN_X );
+      micro_div( &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0] );
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_RSQ:
+   /* TGSI_OPCODE_RECIPSQRT */
+      FETCH( &r[0], 0, CHAN_X );
+      micro_sqrt( &r[0], &r[0] );
+      micro_div( &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0] );
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_EXP:
+      assert (0);
+      break;
+
+    case TGSI_OPCODE_LOG:
+        assert (0);
+        break;
+
+    case TGSI_OPCODE_MUL:
+        FOR_EACH_ENABLED_CHANNEL( *inst, chan_index )
+        {
+            FETCH(&r[0], 0, chan_index);
+            FETCH(&r[1], 1, chan_index);
+
+            micro_mul( &r[0], &r[0], &r[1] );
+
+            STORE(&r[0], 0, chan_index);
+        }
+        break;
+
+   case TGSI_OPCODE_ADD:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_add( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_DP3:
+   /* TGSI_OPCODE_DOT3 */
+      FETCH( &r[0], 0, CHAN_X );
+      FETCH( &r[1], 1, CHAN_X );
+      micro_mul( &r[0], &r[0], &r[1] );
+
+      FETCH( &r[1], 0, CHAN_Y );
+      FETCH( &r[2], 1, CHAN_Y );
+      micro_mul( &r[1], &r[1], &r[2] );
+      micro_add( &r[0], &r[0], &r[1] );
+
+      FETCH( &r[1], 0, CHAN_Z );
+      FETCH( &r[2], 1, CHAN_Z );
+      micro_mul( &r[1], &r[1], &r[2] );
+      micro_add( &r[0], &r[0], &r[1] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+    case TGSI_OPCODE_DP4:
+    /* TGSI_OPCODE_DOT4 */
+       FETCH(&r[0], 0, CHAN_X);
+       FETCH(&r[1], 1, CHAN_X);
+
+       micro_mul( &r[0], &r[0], &r[1] );
+
+       FETCH(&r[1], 0, CHAN_Y);
+       FETCH(&r[2], 1, CHAN_Y);
+
+       micro_mul( &r[1], &r[1], &r[2] );
+       micro_add( &r[0], &r[0], &r[1] );
+
+       FETCH(&r[1], 0, CHAN_Z);
+       FETCH(&r[2], 1, CHAN_Z);
+
+       micro_mul( &r[1], &r[1], &r[2] );
+       micro_add( &r[0], &r[0], &r[1] );
+
+       FETCH(&r[1], 0, CHAN_W);
+       FETCH(&r[2], 1, CHAN_W);
+
+       micro_mul( &r[1], &r[1], &r[2] );
+       micro_add( &r[0], &r[0], &r[1] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_DST:
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+        STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X );
+      }
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+        FETCH( &r[0], 0, CHAN_Y );
+        FETCH( &r[1], 1, CHAN_Y);
+        micro_mul( &r[0], &r[0], &r[1] );
+        STORE( &r[0], 0, CHAN_Y );
+      }
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+        FETCH( &r[0], 0, CHAN_Z );
+        STORE( &r[0], 0, CHAN_Z );
+      }
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+        FETCH( &r[0], 1, CHAN_W );
+        STORE( &r[0], 0, CHAN_W );
+      }
+      break;
+
+   case TGSI_OPCODE_MIN:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH(&r[0], 0, chan_index);
+         FETCH(&r[1], 1, chan_index);
+
+         micro_lt( &r[0], &r[0], &r[1], &r[0], &r[1] );
+
+         STORE(&r[0], 0, chan_index);
+      }
+      break;
+
+   case TGSI_OPCODE_MAX:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH(&r[0], 0, chan_index);
+         FETCH(&r[1], 1, chan_index);
+
+         micro_lt( &r[0], &r[0], &r[1], &r[1], &r[0] );
+
+         STORE(&r[0], 0, chan_index);
+      }
+      break;
+
+   case TGSI_OPCODE_SLT:
+   /* TGSI_OPCODE_SETLT */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_lt( &r[0], &r[0], &r[1], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_SGE:
+   /* TGSI_OPCODE_SETGE */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH(&r[0], 0, chan_index);
+         FETCH(&r[1], 1, chan_index);
+
+         micro_lt( &r[0], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] );
+
+         STORE(&r[0], 0, chan_index);
+      }
+      break;
+
+   case TGSI_OPCODE_MAD:
+   /* TGSI_OPCODE_MADD */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_mul( &r[0], &r[0], &r[1] );
+         FETCH( &r[1], 2, chan_index );
+         micro_add( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+    case TGSI_OPCODE_SUB:
+       FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+          FETCH(&r[0], 0, chan_index);
+          FETCH(&r[1], 1, chan_index);
+
+          micro_sub( &r[0], &r[0], &r[1] );
+
+          STORE(&r[0], 0, chan_index);
+       }
+       break;
+
+   case TGSI_OPCODE_LERP:
+   /* TGSI_OPCODE_LRP */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH(&r[0], 0, chan_index);
+         FETCH(&r[1], 1, chan_index);
+         FETCH(&r[2], 2, chan_index);
+
+         micro_sub( &r[1], &r[1], &r[2] );
+         micro_mul( &r[0], &r[0], &r[1] );
+         micro_add( &r[0], &r[0], &r[2] );
+
+         STORE(&r[0], 0, chan_index);
+      }
+      break;
+
+   case TGSI_OPCODE_CND:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_CND0:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_DOT2ADD:
+      /* TGSI_OPCODE_DP2A */
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_INDEX:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_NEGATE:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_FRAC:
+   /* TGSI_OPCODE_FRC */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_frc( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_CLAMP:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_FLOOR:
+   /* TGSI_OPCODE_FLR */
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_flr( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_ROUND:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_rnd( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_EXPBASE2:
+    /* TGSI_OPCODE_EX2 */
+      FETCH(&r[0], 0, CHAN_X);
+
+      micro_pow( &r[0], &mach->Temps[TEMP_2_I].xyzw[TEMP_2_C], &r[0] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_LOGBASE2:
+   /* TGSI_OPCODE_LG2 */
+      FETCH( &r[0], 0, CHAN_X );
+      micro_lg2( &r[0], &r[0] );
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_POWER:
+      /* TGSI_OPCODE_POW */
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 1, CHAN_X);
+
+      micro_pow( &r[0], &r[0], &r[1] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_CROSSPRODUCT:
+      /* TGSI_OPCODE_XPD */
+      FETCH(&r[0], 0, CHAN_Y);
+      FETCH(&r[1], 1, CHAN_Z);
+
+      micro_mul( &r[2], &r[0], &r[1] );
+
+      FETCH(&r[3], 0, CHAN_Z);
+      FETCH(&r[4], 1, CHAN_Y);
+
+      micro_mul( &r[5], &r[3], &r[4] );
+      micro_sub( &r[2], &r[2], &r[5] );
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) {
+        STORE( &r[2], 0, CHAN_X );
+      }
+
+      FETCH(&r[2], 1, CHAN_X);
+
+      micro_mul( &r[3], &r[3], &r[2] );
+
+      FETCH(&r[5], 0, CHAN_X);
+
+      micro_mul( &r[1], &r[1], &r[5] );
+      micro_sub( &r[3], &r[3], &r[1] );
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) {
+        STORE( &r[3], 0, CHAN_Y );
+      }
+
+      micro_mul( &r[5], &r[5], &r[4] );
+      micro_mul( &r[0], &r[0], &r[2] );
+      micro_sub( &r[5], &r[5], &r[0] );
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) {
+        STORE( &r[5], 0, CHAN_Z );
+      }
+
+      if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) {
+        STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+      }
+      break;
+
+    case TGSI_OPCODE_MULTIPLYMATRIX:
+       assert (0);
+       break;
+
+    case TGSI_OPCODE_ABS:
+       FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+          FETCH(&r[0], 0, chan_index);
+
+          micro_abs( &r[0], &r[0] );
+
+          STORE(&r[0], 0, chan_index);
+       }
+       break;
+
+   case TGSI_OPCODE_RCC:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_DPH:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 1, CHAN_X);
+
+      micro_mul( &r[0], &r[0], &r[1] );
+
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 1, CHAN_Y);
+
+      micro_mul( &r[1], &r[1], &r[2] );
+      micro_add( &r[0], &r[0], &r[1] );
+
+      FETCH(&r[1], 0, CHAN_Z);
+      FETCH(&r[2], 1, CHAN_Z);
+
+      micro_mul( &r[1], &r[1], &r[2] );
+      micro_add( &r[0], &r[0], &r[1] );
+
+      FETCH(&r[1], 1, CHAN_W);
+
+      micro_add( &r[0], &r[0], &r[1] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_COS:
+      FETCH(&r[0], 0, CHAN_X);
+
+      micro_cos( &r[0], &r[0] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_DDX:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_ddx( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_DDY:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_ddy( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_KIL:
+       exec_kil (mach, inst);
+       break;
+
+   case TGSI_OPCODE_PK2H:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_PK2US:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_PK4B:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_PK4UB:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_RFL:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_SEQ:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_SFL:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_SGT:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_SIN:
+      FETCH(&r[0], 0, CHAN_X);
+
+      micro_sin( &r[0], &r[0] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_SLE:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_SNE:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_STR:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_TEX:
+      switch (inst->InstructionExtTexture.Texture) {
+      case TGSI_TEXTURE_1D:
+
+         FETCH(&r[0], 0, CHAN_X);
+
+         switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) {
+         case TGSI_EXTSWIZZLE_W:
+            FETCH(&r[1], 0, CHAN_W);
+            micro_div( &r[0], &r[0], &r[1] );
+            break;
+
+         case TGSI_EXTSWIZZLE_ONE:
+            break;
+
+         default:
+            assert (0);
+         }
+#if MESA
+         fetch_texel_1d (ctx,
+                         &mach->Samplers[inst->FullSrcRegisters[1].SrcRegister.Index],
+                         &r[0],
+                         inst->FullSrcRegisters[1].SrcRegister.Index,
+                         &r[0], &r[1], &r[2], &r[3]);
+#endif
+         break;
+
+      case TGSI_TEXTURE_2D:
+      case TGSI_TEXTURE_RECT:
+
+         FETCH(&r[0], 0, CHAN_X);
+         FETCH(&r[1], 0, CHAN_Y);
+
+         switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) {
+         case TGSI_EXTSWIZZLE_W:
+            FETCH(&r[2], 0, CHAN_W);
+            micro_div( &r[0], &r[0], &r[2] );
+            micro_div( &r[1], &r[1], &r[2] );
+            break;
+
+         case TGSI_EXTSWIZZLE_ONE:
+            break;
+
+         default:
+            assert (0);
+         }
+
+#if MESA
+         fetch_texel_2d (ctx,
+                         &mach->Samplers[inst->FullSrcRegisters[1].SrcRegister.Index],
+                         &r[0], &r[1],
+                         inst->FullSrcRegisters[1].SrcRegister.Index,
+                         &r[0], &r[1], &r[2], &r[3]);
+#endif
+         break;
+
+      case TGSI_TEXTURE_3D:
+      case TGSI_TEXTURE_CUBE:
+
+         FETCH(&r[0], 0, CHAN_X);
+         FETCH(&r[1], 0, CHAN_Y);
+         FETCH(&r[2], 0, CHAN_Z);
+
+         switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) {
+         case TGSI_EXTSWIZZLE_W:
+            FETCH(&r[3], 0, CHAN_W);
+            micro_div( &r[0], &r[0], &r[3] );
+            micro_div( &r[1], &r[1], &r[3] );
+            micro_div( &r[2], &r[2], &r[3] );
+            break;
+
+         case TGSI_EXTSWIZZLE_ONE:
+            break;
+
+         default:
+            assert (0);
+         }
+
+#if MESA
+         fetch_texel_3d (ctx,
+                         &mach->Samplers[inst->FullSrcRegisters[1].SrcRegister.Index],
+                         &r[0], &r[1], &r[2],
+                         inst->FullSrcRegisters[1].SrcRegister.Index,
+                         &r[0], &r[1], &r[2], &r[3]);
+#endif
+         break;
+
+      default:
+         assert (0);
+      }
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+        STORE( &r[chan_index], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_TXD:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_UP2H:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_UP2US:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_UP4B:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_UP4UB:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_X2D:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_ARA:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_ARR:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_BRA:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_CAL:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_RET:
+      /* XXX: end of shader! */
+      /*assert (0);*/
+      break;
+
+   case TGSI_OPCODE_SSG:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_CMP:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH(&r[0], 0, chan_index);
+         FETCH(&r[1], 1, chan_index);
+         FETCH(&r[2], 2, chan_index);
+
+         micro_lt( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[1], &r[2] );
+
+         STORE(&r[0], 0, chan_index);
+      }
+      break;
+
+   case TGSI_OPCODE_SCS:
+      if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+         FETCH( &r[0], 0, CHAN_X );
+      }
+      if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) ) {
+         micro_cos( &r[1], &r[0] );
+         STORE( &r[1], 0, CHAN_X );
+      }
+      if( IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
+         micro_sin( &r[1], &r[0] );
+         STORE( &r[1], 0, CHAN_Y );
+      }
+      if( IS_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
+         STORE( &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], 0, CHAN_Z );
+      }
+      if( IS_CHANNEL_ENABLED( *inst, CHAN_W ) ) {
+         STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W );
+      }
+      break;
+
+   case TGSI_OPCODE_TXB:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_NRM:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_DIV:
+      assert( 0 );
+      break;
+
+   case TGSI_OPCODE_DP2:
+      FETCH( &r[0], 0, CHAN_X );
+      FETCH( &r[1], 1, CHAN_X );
+      micro_mul( &r[0], &r[0], &r[1] );
+
+      FETCH( &r[1], 0, CHAN_Y );
+      FETCH( &r[2], 1, CHAN_Y );
+      micro_mul( &r[1], &r[1], &r[2] );
+      micro_add( &r[0], &r[0], &r[1] );
+
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_TXL:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_BRK:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_IF:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_LOOP:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_REP:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_ELSE:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_ENDIF:
+       assert (0);
+       break;
+
+   case TGSI_OPCODE_ENDLOOP:
+       assert (0);
+       break;
+
+   case TGSI_OPCODE_ENDREP:
+       assert (0);
+       break;
+
+   case TGSI_OPCODE_PUSHA:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_POPA:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_CEIL:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_ceil( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_I2F:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_i2f( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_NOT:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         micro_not( &r[0], &r[0] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_TRUNC:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_SHL:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_shl( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_SHR:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_ishr( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_AND:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_and( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_OR:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_or( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_MOD:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_XOR:
+      FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
+         FETCH( &r[0], 0, chan_index );
+         FETCH( &r[1], 1, chan_index );
+         micro_xor( &r[0], &r[0], &r[1] );
+         STORE( &r[0], 0, chan_index );
+      }
+      break;
+
+   case TGSI_OPCODE_SAD:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_TXF:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_TXQ:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_CONT:
+      assert (0);
+      break;
+
+   case TGSI_OPCODE_EMIT:
+      mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += 16;
+      mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++;
+      break;
+
+   case TGSI_OPCODE_ENDPRIM:
+      mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]++;
+      mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0;
+      break;
+
+   default:
+      assert( 0 );
+   }
+}
+
+
+#if !defined(XSTDCALL) 
+#if defined(WIN32)
+#define XSTDCALL __stdcall
+#else
+#define XSTDCALL
+#endif
+#endif
+
+typedef void (XSTDCALL *fp_function) (const struct tgsi_exec_vector *input,
+                                    struct tgsi_exec_vector *output,
+                                    GLfloat (*constant)[4],
+                                    struct tgsi_exec_vector *temporary);
+
+void
+tgsi_exec_machine_run2(
+   struct tgsi_exec_machine *mach,
+   struct tgsi_exec_labels *labels )
+{
+#if MESA
+   GET_CURRENT_CONTEXT(ctx);
+   GLuint i;
+#endif
+
+#if XXX_SSE
+   fp_function function;
+
+   mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
+    
+   function = (fp_function) x86_get_func (&mach->Function);
+
+   function (mach->Inputs,
+             mach->Outputs,
+             mach->Consts,
+             mach->Temps);
+#else
+   struct tgsi_parse_context parse;
+   GLuint k;
+
+   mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
+   mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;
+
+   if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) {
+      mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0;
+      mach->Primitives[0] = 0;
+   }
+
+   k = tgsi_parse_init( &parse, mach->Tokens );
+   if (k != TGSI_PARSE_OK) {
+      printf("Problem parsing!\n");
+      return;
+   }
+
+   while( !tgsi_parse_end_of_tokens( &parse ) ) {
+      tgsi_parse_token( &parse );
+      switch( parse.FullToken.Token.Type ) {
+      case TGSI_TOKEN_TYPE_DECLARATION:
+         break;
+      case TGSI_TOKEN_TYPE_IMMEDIATE:
+         break;
+      case TGSI_TOKEN_TYPE_INSTRUCTION:
+         exec_instruction( mach, &parse.FullToken.FullInstruction, labels, &parse.Position );
+         break;
+      default:
+         assert( 0 );
+      }
+   }
+   tgsi_parse_free (&parse);
+#endif
+
+#if MESA
+   if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
+      /*
+       * Scale back depth component.
+       */
+      for (i = 0; i < 4; i++)
+         mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF;
+   }
+#endif
+}
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.h b/src/mesa/pipe/tgsi/core/tgsi_exec.h
new file mode 100644 (file)
index 0000000..abce6ee
--- /dev/null
@@ -0,0 +1,137 @@
+#if !defined TGSI_EXEC_H
+#define TGSI_EXEC_H
+
+#if 0
+#include "x86/rtasm/x86sse.h"
+#endif
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+union tgsi_exec_channel
+{
+   GLfloat  f[4];
+   GLint    i[4];
+   GLuint   u[4];
+};
+
+struct tgsi_exec_vector
+{
+   union tgsi_exec_channel xyzw[4];
+};
+
+struct tgsi_sampler_state
+{
+    GLboolean   NeedLambda;
+    GLboolean   NeedLodBias;        /* if NeedLambda */
+    GLboolean   NeedLambdaClamp;    /* if NeedLambda */
+    GLfloat     LodBias;            /* if NeedLodBias */
+    GLfloat     MinLod;             /* if NeedLambdaClamp */
+    GLfloat     MaxLod;             /* if NeedLambdaClamp */
+    GLfloat     ImageWidth;
+    GLfloat     ImageHeight;
+    GLfloat     ImageDepth;
+};
+
+struct tgsi_exec_labels
+{
+   GLuint   labels[128][2];
+   GLuint   count;
+};
+
+#define TGSI_EXEC_TEMP_00000000_I   32
+#define TGSI_EXEC_TEMP_00000000_C   0
+
+#define TGSI_EXEC_TEMP_7FFFFFFF_I   32
+#define TGSI_EXEC_TEMP_7FFFFFFF_C   1
+
+#define TGSI_EXEC_TEMP_80000000_I   32
+#define TGSI_EXEC_TEMP_80000000_C   2
+
+#define TGSI_EXEC_TEMP_FFFFFFFF_I   32
+#define TGSI_EXEC_TEMP_FFFFFFFF_C   3
+
+#define TGSI_EXEC_TEMP_ONE_I        33
+#define TGSI_EXEC_TEMP_ONE_C        0
+
+#define TGSI_EXEC_TEMP_TWO_I        33
+#define TGSI_EXEC_TEMP_TWO_C        1
+
+#define TGSI_EXEC_TEMP_128_I        33
+#define TGSI_EXEC_TEMP_128_C        2
+
+#define TGSI_EXEC_TEMP_MINUS_128_I  33
+#define TGSI_EXEC_TEMP_MINUS_128_C  3
+
+#define TGSI_EXEC_TEMP_KILMASK_I    34
+#define TGSI_EXEC_TEMP_KILMASK_C    0
+
+#define TGSI_EXEC_TEMP_OUTPUT_I     34
+#define TGSI_EXEC_TEMP_OUTPUT_C     1
+
+#define TGSI_EXEC_TEMP_PRIMITIVE_I  34
+#define TGSI_EXEC_TEMP_PRIMITIVE_C  2
+
+#define TGSI_EXEC_TEMP_R0           35
+
+#define TGSI_EXEC_NUM_TEMPS   (32 + 4)
+#define TGSI_EXEC_NUM_ADDRS   1
+
+struct tgsi_exec_machine
+{
+   /*
+    * 32 program temporaries
+    * 4  internal temporaries
+    * 1  address
+    * 1  temporary of padding to align to 16 bytes
+    */
+   struct tgsi_exec_vector       _Temps[TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_ADDRS + 1];
+
+   /*
+    * This will point to _Temps after aligning to 16B boundary.
+    */
+   struct tgsi_exec_vector       *Temps;
+   struct tgsi_exec_vector       *Addrs;
+
+   struct tgsi_sampler_state     Samplers[16];
+
+   GLfloat                       Imms[256][4];
+   GLuint                        ImmLimit;
+   GLfloat                       (*Consts)[4];
+   const struct tgsi_exec_vector *Inputs;
+   struct tgsi_exec_vector       *Outputs;
+   struct tgsi_token             *Tokens;
+   GLuint                        Processor;
+
+   GLuint                        *Primitives;
+#if XXX_SSE
+   struct x86_function           Function;
+#endif
+};
+
+void
+tgsi_exec_machine_init(
+   struct tgsi_exec_machine *mach,
+   struct tgsi_token *tokens );
+
+void
+tgsi_exec_prepare(
+   struct tgsi_exec_machine *mach,
+   struct tgsi_exec_labels *labels );
+
+void
+tgsi_exec_machine_run(
+   struct tgsi_exec_machine *mach );
+
+void
+tgsi_exec_machine_run2(
+   struct tgsi_exec_machine *mach,
+   struct tgsi_exec_labels *labels );
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_EXEC_H
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_parse.c b/src/mesa/pipe/tgsi/core/tgsi_parse.c
new file mode 100644 (file)
index 0000000..df34fa7
--- /dev/null
@@ -0,0 +1,284 @@
+#include "tgsi_platform.h"
+#include "tgsi_core.h"
+
+void
+tgsi_full_token_init(
+   union tgsi_full_token *full_token )
+{
+   full_token->Token.Type = TGSI_TOKEN_TYPE_DECLARATION;
+}
+
+void
+tgsi_full_token_free(
+   union tgsi_full_token *full_token )
+{
+   if( full_token->Token.Type == TGSI_TOKEN_TYPE_IMMEDIATE )
+      free( full_token->FullImmediate.u.Pointer );
+}
+
+GLuint
+tgsi_parse_init(
+   struct tgsi_parse_context *ctx,
+   const struct tgsi_token *tokens )
+{
+   ctx->FullVersion.Version = *(struct tgsi_version *) &tokens[0];
+   if( ctx->FullVersion.Version.MajorVersion > 1 ) {
+      return TGSI_PARSE_ERROR;
+   }
+
+   ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[1];
+   if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
+      ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[2];
+   }
+   else {
+      ctx->FullHeader.Processor = tgsi_default_processor();
+   }
+
+   ctx->Tokens = tokens;
+   ctx->Position = 1 + ctx->FullHeader.Header.HeaderSize;
+
+   tgsi_full_token_init( &ctx->FullToken );
+
+   return TGSI_PARSE_OK;
+}
+
+void
+tgsi_parse_free(
+   struct tgsi_parse_context *ctx )
+{
+   tgsi_full_token_free( &ctx->FullToken );
+}
+
+GLuint
+tgsi_parse_end_of_tokens(
+   struct tgsi_parse_context *ctx )
+{
+   return ctx->Position >=
+      1 + ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
+}
+
+static void
+next_token(
+   struct tgsi_parse_context *ctx,
+   void *token )
+{
+   assert( !tgsi_parse_end_of_tokens( ctx ) );
+
+   *(struct tgsi_token *) token = ctx->Tokens[ctx->Position++];
+}
+
+void
+tgsi_parse_token(
+   struct tgsi_parse_context *ctx )
+{
+   struct tgsi_token token;
+   GLuint i;
+
+   tgsi_full_token_free( &ctx->FullToken );
+   tgsi_full_token_init( &ctx->FullToken );
+
+   next_token( ctx, &token );
+
+   switch( token.Type ) {
+   case TGSI_TOKEN_TYPE_DECLARATION:
+   {
+      struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
+
+      *decl = tgsi_default_full_declaration();
+      decl->Declaration = *(struct tgsi_declaration *) &token;
+
+      switch( decl->Declaration.Type ) {
+      case TGSI_DECLARE_RANGE:
+         next_token( ctx, &decl->u.DeclarationRange );
+         break;
+
+      case TGSI_DECLARE_MASK:
+         next_token( ctx, &decl->u.DeclarationMask );
+         break;
+
+      default:
+         assert (0);
+      }
+
+      if( decl->Declaration.Interpolate ) {
+         next_token( ctx, &decl->Interpolation );
+      }
+
+      break;
+   }
+
+   case TGSI_TOKEN_TYPE_IMMEDIATE:
+   {
+      struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
+
+      *imm = tgsi_default_full_immediate();
+      imm->Immediate = *(struct tgsi_immediate *) &token;
+
+      assert( !imm->Immediate.Extended );
+
+      switch (imm->Immediate.DataType) {
+      case TGSI_IMM_FLOAT32:
+         imm->u.Pointer = malloc(
+            sizeof( struct tgsi_immediate_float32 ) * (imm->Immediate.Size - 1) );
+         for( i = 0; i < imm->Immediate.Size - 1; i++ ) {
+            next_token( ctx, &imm->u.ImmediateFloat32[i] );
+         }
+         break;
+
+      default:
+         assert( 0 );
+      }
+
+      break;
+   }
+
+   case TGSI_TOKEN_TYPE_INSTRUCTION:
+   {
+      struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
+      GLuint extended;
+
+      *inst = tgsi_default_full_instruction();
+      inst->Instruction = *(struct tgsi_instruction *) &token;
+
+      extended = inst->Instruction.Extended;
+
+      while( extended ) {
+         struct tgsi_src_register_ext token;
+
+         next_token( ctx, &token );
+
+         switch( token.Type ) {
+         case TGSI_INSTRUCTION_EXT_TYPE_NV:
+            inst->InstructionExtNv =
+               *(struct tgsi_instruction_ext_nv *) &token;
+            break;
+
+         case TGSI_INSTRUCTION_EXT_TYPE_LABEL:
+            inst->InstructionExtLabel =
+               *(struct tgsi_instruction_ext_label *) &token;
+            break;
+
+         case TGSI_INSTRUCTION_EXT_TYPE_TEXTURE:
+            inst->InstructionExtTexture =
+               *(struct tgsi_instruction_ext_texture *) &token;
+            break;
+
+         default:
+            assert( 0 );
+         }
+
+         extended = token.Extended;
+      }
+
+      assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
+
+      for(  i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
+         GLuint extended;
+
+         next_token( ctx, &inst->FullDstRegisters[i].DstRegister );
+
+         /*
+          * No support for indirect or multi-dimensional addressing.
+          */
+         assert( !inst->FullDstRegisters[i].DstRegister.Indirect );
+         assert( !inst->FullDstRegisters[i].DstRegister.Dimension );
+
+         extended = inst->FullDstRegisters[i].DstRegister.Extended;
+
+         while( extended ) {
+            struct tgsi_src_register_ext token;
+
+            next_token( ctx, &token );
+
+            switch( token.Type ) {
+            case TGSI_DST_REGISTER_EXT_TYPE_CONDCODE:
+               inst->FullDstRegisters[i].DstRegisterExtConcode =
+                  *(struct tgsi_dst_register_ext_concode *) &token;
+               break;
+
+            case TGSI_DST_REGISTER_EXT_TYPE_MODULATE:
+               inst->FullDstRegisters[i].DstRegisterExtModulate =
+                  *(struct tgsi_dst_register_ext_modulate *) &token;
+               break;
+
+            default:
+               assert( 0 );
+            }
+
+            extended = token.Extended;
+         }
+      }
+
+      assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
+
+      for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
+         GLuint extended;
+
+         next_token( ctx, &inst->FullSrcRegisters[i].SrcRegister );
+
+         extended = inst->FullSrcRegisters[i].SrcRegister.Extended;
+
+         while( extended ) {
+            struct tgsi_src_register_ext token;
+
+            next_token( ctx, &token );
+
+            switch( token.Type ) {
+            case TGSI_SRC_REGISTER_EXT_TYPE_SWZ:
+               inst->FullSrcRegisters[i].SrcRegisterExtSwz =
+                  *(struct tgsi_src_register_ext_swz *) &token;
+               break;
+
+            case TGSI_SRC_REGISTER_EXT_TYPE_MOD:
+               inst->FullSrcRegisters[i].SrcRegisterExtMod =
+                  *(struct tgsi_src_register_ext_mod *) &token;
+               break;
+
+            default:
+               assert( 0 );
+            }
+
+            extended = token.Extended;
+         }
+
+         if( inst->FullSrcRegisters[i].SrcRegister.Indirect ) {
+            next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterInd );
+
+            /*
+             * No support for indirect or multi-dimensional addressing.
+             */
+            assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect );
+            assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension );
+            assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended );
+         }
+
+         if( inst->FullSrcRegisters[i].SrcRegister.Dimension ) {
+            next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDim );
+
+            /*
+             * No support for multi-dimensional addressing.
+             */
+            assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Dimension );
+            assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Extended );
+
+            if( inst->FullSrcRegisters[i].SrcRegisterDim.Indirect ) {
+               next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDimInd );
+
+               /*
+               * No support for indirect or multi-dimensional addressing.
+               */
+               assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect );
+               assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension );
+               assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended );
+            }
+         }
+      }
+
+      break;
+   }
+
+   default:
+      assert( 0 );
+   }
+}
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_parse.h b/src/mesa/pipe/tgsi/core/tgsi_parse.h
new file mode 100644 (file)
index 0000000..61ad066
--- /dev/null
@@ -0,0 +1,120 @@
+#if !defined TGSI_PARSE_H
+#define TGSI_PARSE_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+struct tgsi_full_version
+{
+   struct tgsi_version  Version;
+};
+
+struct tgsi_full_header
+{
+   struct tgsi_header      Header;
+   struct tgsi_processor   Processor;
+};
+
+struct tgsi_full_dst_register
+{
+   struct tgsi_dst_register               DstRegister;
+   struct tgsi_dst_register_ext_concode   DstRegisterExtConcode;
+   struct tgsi_dst_register_ext_modulate  DstRegisterExtModulate;
+};
+
+struct tgsi_full_src_register
+{
+   struct tgsi_src_register         SrcRegister;
+   struct tgsi_src_register_ext_swz SrcRegisterExtSwz;
+   struct tgsi_src_register_ext_mod SrcRegisterExtMod;
+   struct tgsi_src_register         SrcRegisterInd;
+   struct tgsi_dimension            SrcRegisterDim;
+   struct tgsi_src_register         SrcRegisterDimInd;
+};
+
+struct tgsi_full_declaration
+{
+   struct tgsi_declaration Declaration;
+   union
+   {
+      struct tgsi_declaration_range DeclarationRange;
+      struct tgsi_declaration_mask  DeclarationMask;
+   } u;
+   struct tgsi_declaration_interpolation  Interpolation;
+};
+
+struct tgsi_full_immediate
+{
+   struct tgsi_immediate   Immediate;
+   union
+   {
+      void                          *Pointer;
+      struct tgsi_immediate_float32 *ImmediateFloat32;
+   } u;
+};
+
+#define TGSI_FULL_MAX_DST_REGISTERS 2
+#define TGSI_FULL_MAX_SRC_REGISTERS 3
+
+struct tgsi_full_instruction
+{
+   struct tgsi_instruction             Instruction;
+   struct tgsi_instruction_ext_nv      InstructionExtNv;
+   struct tgsi_instruction_ext_label   InstructionExtLabel;
+   struct tgsi_instruction_ext_texture InstructionExtTexture;
+   struct tgsi_full_dst_register       FullDstRegisters[TGSI_FULL_MAX_DST_REGISTERS];
+   struct tgsi_full_src_register       FullSrcRegisters[TGSI_FULL_MAX_SRC_REGISTERS];
+};
+
+union tgsi_full_token
+{
+   struct tgsi_token             Token;
+   struct tgsi_full_declaration  FullDeclaration;
+   struct tgsi_full_immediate    FullImmediate;
+   struct tgsi_full_instruction  FullInstruction;
+};
+
+void
+tgsi_full_token_init(
+   union tgsi_full_token *full_token );
+
+void
+tgsi_full_token_free(
+   union tgsi_full_token *full_token );
+
+struct tgsi_parse_context
+{
+   const struct tgsi_token    *Tokens;
+   GLuint                     Position;
+   struct tgsi_full_version   FullVersion;
+   struct tgsi_full_header    FullHeader;
+   union tgsi_full_token      FullToken;
+};
+
+#define TGSI_PARSE_OK      0
+#define TGSI_PARSE_ERROR   1
+
+GLuint
+tgsi_parse_init(
+   struct tgsi_parse_context *ctx,
+   const struct tgsi_token *tokens );
+
+void
+tgsi_parse_free(
+   struct tgsi_parse_context *ctx );
+
+GLuint
+tgsi_parse_end_of_tokens(
+   struct tgsi_parse_context *ctx );
+
+void
+tgsi_parse_token(
+   struct tgsi_parse_context *ctx );
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_PARSE_H
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_token.h b/src/mesa/pipe/tgsi/core/tgsi_token.h
new file mode 100644 (file)
index 0000000..becdd48
--- /dev/null
@@ -0,0 +1,1045 @@
+#if !defined TGSI_TOKEN_H
+#define TGSI_TOKEN_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+struct tgsi_version
+{
+   GLuint MajorVersion  : 8;
+   GLuint MinorVersion  : 8;
+   GLuint Padding       : 16;
+};
+
+struct tgsi_header
+{
+   GLuint HeaderSize : 8;
+   GLuint BodySize   : 24;
+};
+
+#define TGSI_PROCESSOR_FRAGMENT  0
+#define TGSI_PROCESSOR_VERTEX    1
+#define TGSI_PROCESSOR_GEOMETRY  2
+
+struct tgsi_processor
+{
+   GLuint Processor  : 4;  /* TGSI_PROCESSOR_ */
+   GLuint Padding    : 28;
+};
+
+#define TGSI_TOKEN_TYPE_DECLARATION    0
+#define TGSI_TOKEN_TYPE_IMMEDIATE      1
+#define TGSI_TOKEN_TYPE_INSTRUCTION    2
+
+struct tgsi_token
+{
+   GLuint Type       : 4;  /* TGSI_TOKEN_TYPE_ */
+   GLuint Size       : 8;  /* UINT */
+   GLuint Padding    : 19;
+   GLuint Extended   : 1;  /* BOOL */
+};
+
+#define TGSI_FILE_NULL        0
+#define TGSI_FILE_CONSTANT    1
+#define TGSI_FILE_INPUT       2
+#define TGSI_FILE_OUTPUT      3
+#define TGSI_FILE_TEMPORARY   4
+#define TGSI_FILE_SAMPLER     5
+#define TGSI_FILE_ADDRESS     6
+#define TGSI_FILE_IMMEDIATE   7
+
+#define TGSI_DECLARE_RANGE    0
+#define TGSI_DECLARE_MASK     1
+
+struct tgsi_declaration
+{
+   GLuint Type          : 4;  /* TGSI_TOKEN_TYPE_DECLARATION */
+   GLuint Size          : 8;  /* UINT */
+   GLuint File          : 4;  /* TGSI_FILE_ */
+   GLuint Declare       : 4;  /* TGSI_DECLARE_ */
+   GLuint Interpolate   : 1;  /* BOOL */
+   GLuint Padding       : 10;
+   GLuint Extended      : 1;  /* BOOL */
+};
+
+struct tgsi_declaration_range
+{
+   GLuint First   : 16; /* UINT */
+   GLuint Last    : 16; /* UINT */
+};
+
+struct tgsi_declaration_mask
+{
+   GLuint Mask : 32; /* UINT */
+};
+
+#define TGSI_INTERPOLATE_CONSTANT      0
+#define TGSI_INTERPOLATE_LINEAR        1
+#define TGSI_INTERPOLATE_PERSPECTIVE   2
+
+struct tgsi_declaration_interpolation
+{
+   GLuint Interpolate   : 4;  /* TGSI_INTERPOLATE_ */
+   GLuint Padding       : 28;
+};
+
+#define TGSI_IMM_FLOAT32   0
+
+struct tgsi_immediate
+{
+   GLuint Type       : 4;  /* TGSI_TOKEN_TYPE_IMMEDIATE */
+   GLuint Size       : 8;  /* UINT */
+   GLuint DataType   : 4;  /* TGSI_IMM_ */
+   GLuint Padding    : 15;
+   GLuint Extended   : 1;  /* BOOL */
+};
+
+struct tgsi_immediate_float32
+{
+   GLfloat Float;
+};
+
+/*
+ * GL_NV_vertex_program
+ */
+#define TGSI_OPCODE_ARL                 0
+#define TGSI_OPCODE_MOV                 1
+#define TGSI_OPCODE_LIT                 2
+#define TGSI_OPCODE_RCP                 3
+#define TGSI_OPCODE_RSQ                 4
+#define TGSI_OPCODE_EXP                 5
+#define TGSI_OPCODE_LOG                 6
+#define TGSI_OPCODE_MUL                 7
+#define TGSI_OPCODE_ADD                 8
+#define TGSI_OPCODE_DP3                 9
+#define TGSI_OPCODE_DP4                 10
+#define TGSI_OPCODE_DST                 11
+#define TGSI_OPCODE_MIN                 12
+#define TGSI_OPCODE_MAX                 13
+#define TGSI_OPCODE_SLT                 14
+#define TGSI_OPCODE_SGE                 15
+#define TGSI_OPCODE_MAD                 16
+
+/*
+ * GL_ATI_fragment_shader
+ */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_MUL */
+#define TGSI_OPCODE_SUB                 17
+#define TGSI_OPCODE_DOT3                TGSI_OPCODE_DP3
+#define TGSI_OPCODE_DOT4                TGSI_OPCODE_DP4
+/* TGSI_OPCODE_MAD */
+#define TGSI_OPCODE_LERP                18
+#define TGSI_OPCODE_CND                 19
+#define TGSI_OPCODE_CND0                20
+#define TGSI_OPCODE_DOT2ADD             21
+
+/*
+ * GL_EXT_vertex_shader
+ */
+#define TGSI_OPCODE_INDEX               22
+#define TGSI_OPCODE_NEGATE              23
+/* TGSI_OPCODE_DOT3 */
+/* TGSI_OPCODE_DOT4 */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_ADD */
+#define TGSI_OPCODE_MADD                TGSI_OPCODE_MAD
+#define TGSI_OPCODE_FRAC                24
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+#define TGSI_OPCODE_SETGE               TGSI_OPCODE_SGE
+#define TGSI_OPCODE_SETLT               TGSI_OPCODE_SLT
+#define TGSI_OPCODE_CLAMP               25
+#define TGSI_OPCODE_FLOOR               26
+#define TGSI_OPCODE_ROUND               27
+#define TGSI_OPCODE_EXPBASE2            28
+#define TGSI_OPCODE_LOGBASE2            29
+#define TGSI_OPCODE_POWER               30
+#define TGSI_OPCODE_RECIP               TGSI_OPCODE_RCP
+#define TGSI_OPCODE_RECIPSQRT           TGSI_OPCODE_RSQ
+/* TGSI_OPCODE_SUB */
+#define TGSI_OPCODE_CROSSPRODUCT        31
+#define TGSI_OPCODE_MULTIPLYMATRIX      32
+/* TGSI_OPCODE_MOV */
+
+/*
+ * GL_NV_vertex_program1_1
+ */
+/* TGSI_OPCODE_ARL */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_LIT */
+#define TGSI_OPCODE_ABS                 33
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_EXP */
+/* TGSI_OPCODE_LOG */
+#define TGSI_OPCODE_RCC                 34
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SGE */
+#define TGSI_OPCODE_DPH                 35
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_MAD */
+
+/*
+ * GL_NV_fragment_program
+ */
+/* TGSI_OPCODE_ADD */
+#define TGSI_OPCODE_COS                 36
+#define TGSI_OPCODE_DDX                 37
+#define TGSI_OPCODE_DDY                 38
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DST */
+#define TGSI_OPCODE_EX2                 TGSI_OPCODE_EXPBASE2
+#define TGSI_OPCODE_FLR                 TGSI_OPCODE_FLOOR
+#define TGSI_OPCODE_FRC                 TGSI_OPCODE_FRAC
+#define TGSI_OPCODE_KIL                 39
+#define TGSI_OPCODE_LG2                 TGSI_OPCODE_LOGBASE2
+/* TGSI_OPCODE_LIT */
+#define TGSI_OPCODE_LRP                 TGSI_OPCODE_LERP
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_MUL */
+#define TGSI_OPCODE_PK2H                40
+#define TGSI_OPCODE_PK2US               41
+#define TGSI_OPCODE_PK4B                42
+#define TGSI_OPCODE_PK4UB               43
+#define TGSI_OPCODE_POW                 TGSI_OPCODE_POWER
+/* TGSI_OPCODE_RCP */
+#define TGSI_OPCODE_RFL                 44
+/* TGSI_OPCODE_RSQ */
+#define TGSI_OPCODE_SEQ                 45
+#define TGSI_OPCODE_SFL                 46
+/* TGSI_OPCODE_SGE */
+#define TGSI_OPCODE_SGT                 47
+#define TGSI_OPCODE_SIN                 48
+#define TGSI_OPCODE_SLE                 49
+/* TGSI_OPCODE_SLT */
+#define TGSI_OPCODE_SNE                 50
+#define TGSI_OPCODE_STR                 51
+/* TGSI_OPCODE_SUB */
+#define TGSI_OPCODE_TEX                 52
+#define TGSI_OPCODE_TXD                 53
+/* TGSI_OPCODE_TXP - use TGSI_OPCODE_TEX */
+#define TGSI_OPCODE_UP2H                54
+#define TGSI_OPCODE_UP2US               55
+#define TGSI_OPCODE_UP4B                56
+#define TGSI_OPCODE_UP4UB               57
+#define TGSI_OPCODE_X2D                 58
+
+/*
+ * GL_NV_vertex_program2
+ */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_ADD */
+#define TGSI_OPCODE_ARA                 59
+/* TGSI_OPCODE_ARL */
+#define TGSI_OPCODE_ARR                 60
+#define TGSI_OPCODE_BRA                 61
+#define TGSI_OPCODE_CAL                 62
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_EXP */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_LOG */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_RCC */
+/* TGSI_OPCODE_RCP */
+#define TGSI_OPCODE_RET                 63
+/* TGSI_OPCODE_RSQNV */
+/* TGSI_OPCODE_SEQ */
+/* TGSI_OPCODE_SFL */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SGT */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_SLE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SNE */
+#define TGSI_OPCODE_SSG                 64
+/* TGSI_OPCODE_STR */
+/* TGSI_OPCODE_SUB */
+
+/*
+ * GL_ARB_vertex_program
+ */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_ARL */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_EXP */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_LOG */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SUB */
+#define TGSI_OPCODE_SWZ                 TGSI_OPCODE_MOV
+#define TGSI_OPCODE_XPD                 TGSI_OPCODE_CROSSPRODUCT
+
+/*
+ * GL_ARB_fragment_program
+ */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_ADD */
+#define TGSI_OPCODE_CMP                 65
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_LRP */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+#define TGSI_OPCODE_SCS                 66
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_SWZ */
+/* TGSI_OPCODE_XPD */
+/* TGSI_OPCODE_TEX */
+/* TGSI_OPCODE_TXP */
+#define TGSI_OPCODE_TXB                 67
+/* TGSI_OPCODE_KIL */
+
+/*
+ * GL_NV_fragment_program_option
+ */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_DDX */
+/* TGSI_OPCODE_DDY */
+/* TGSI_OPCODE_PK2H */
+/* TGSI_OPCODE_PK2US */
+/* TGSI_OPCODE_PK4B */
+/* TGSI_OPCODE_PK4UB */
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_SCS */
+/* TGSI_OPCODE_UP2H */
+/* TGSI_OPCODE_UP2US */
+/* TGSI_OPCODE_UP4B */
+/* TGSI_OPCODE_UP4UB */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_XPD */
+/* TGSI_OPCODE_RFL */
+/* TGSI_OPCODE_SEQ */
+/* TGSI_OPCODE_SFL */
+/* TGSI_OPCODE_SGT */
+/* TGSI_OPCODE_SLE */
+/* TGSI_OPCODE_SNE */
+/* TGSI_OPCODE_STR */
+/* TGSI_OPCODE_CMP */
+/* TGSI_OPCODE_LRP */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_X2D */
+/* TGSI_OPCODE_SWZ */
+/* TGSI_OPCODE_TEX */
+/* TGSI_OPCODE_TXP */
+/* TGSI_OPCODE_TXB */
+/* TGSI_OPCODE_KIL */
+/* TGSI_OPCODE_TXD */
+
+/*
+ * GL_NV_fragment_program2
+ */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_DDX */
+/* TGSI_OPCODE_DDY */
+/* TGSI_OPCODE_PK2H */
+/* TGSI_OPCODE_PK2US */
+/* TGSI_OPCODE_PK4B */
+/* TGSI_OPCODE_PK4UB */
+#define TGSI_OPCODE_NRM                 68
+#define TGSI_OPCODE_DIV                 69
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_SCS */
+/* TGSI_OPCODE_UP2H */
+/* TGSI_OPCODE_UP2US */
+/* TGSI_OPCODE_UP4B */
+/* TGSI_OPCODE_UP4UB */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_XPD */
+/* TGSI_OPCODE_RFL */
+/* TGSI_OPCODE_SEQ */
+/* TGSI_OPCODE_SFL */
+/* TGSI_OPCODE_SGT */
+/* TGSI_OPCODE_SLE */
+/* TGSI_OPCODE_SNE */
+/* TGSI_OPCODE_STR */
+#define TGSI_OPCODE_DP2                 70
+/* TGSI_OPCODE_CMP */
+/* TGSI_OPCODE_LRP */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_X2D */
+#define TGSI_OPCODE_DP2A                TGSI_OPCODE_DOT2ADD
+/* TGSI_OPCODE_SWZ */
+/* TGSI_OPCODE_TEX */
+/* TGSI_OPCODE_TXP */
+/* TGSI_OPCODE_TXB */
+#define TGSI_OPCODE_TXL                 71
+/* TGSI_OPCODE_KIL */
+/* TGSI_OPCODE_TXD */
+/* TGSI_OPCODE_CAL */
+/* TGSI_OPCODE_RET */
+#define TGSI_OPCODE_BRK                 72
+#define TGSI_OPCODE_IF                  73
+#define TGSI_OPCODE_LOOP                74
+#define TGSI_OPCODE_REP                 75
+#define TGSI_OPCODE_ELSE                76
+#define TGSI_OPCODE_ENDIF               77
+#define TGSI_OPCODE_ENDLOOP             78
+#define TGSI_OPCODE_ENDREP              79
+
+/*
+ * GL_NV_vertex_program2_option
+ */
+/* TGSI_OPCODE_ARL */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_SSG */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_EXP */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_LOG */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_RCC */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_XPD */
+/* TGSI_OPCODE_SEQ */
+/* TGSI_OPCODE_SFL */
+/* TGSI_OPCODE_SGT */
+/* TGSI_OPCODE_SLE */
+/* TGSI_OPCODE_SNE */
+/* TGSI_OPCODE_STR */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_SWZ */
+/* TGSI_OPCODE_ARR */
+/* TGSI_OPCODE_ARA */
+/* TGSI_OPCODE_BRA */
+/* TGSI_OPCODE_CAL */
+/* TGSI_OPCODE_RET */
+
+/*
+ * GL_NV_vertex_program3
+ */
+/* TGSI_OPCODE_ARL */
+/* TGSI_OPCODE_ABS */
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_MOV */
+/* TGSI_OPCODE_SSG */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_EXP */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_LOG */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_RCC */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_ADD */
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MUL */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_XPD */
+/* TGSI_OPCODE_SEQ */
+/* TGSI_OPCODE_SFL */
+/* TGSI_OPCODE_SGT */
+/* TGSI_OPCODE_SLE */
+/* TGSI_OPCODE_SNE */
+/* TGSI_OPCODE_STR */
+/* TGSI_OPCODE_MAD */
+/* TGSI_OPCODE_SWZ */
+/* TGSI_OPCODE_ARR */
+/* TGSI_OPCODE_ARA */
+/* TGSI_OPCODE_BRA */
+/* TGSI_OPCODE_CAL */
+/* TGSI_OPCODE_RET */
+#define TGSI_OPCODE_PUSHA               80
+#define TGSI_OPCODE_POPA                81
+/* TGSI_OPCODE_TEX */
+/* TGSI_OPCODE_TXP */
+/* TGSI_OPCODE_TXB */
+/* TGSI_OPCODE_TXL */
+
+/*
+ * GL_NV_gpu_program4
+ */
+/* TGSI_OPCODE_ABS */
+#define TGSI_OPCODE_CEIL                82
+/* TGSI_OPCODE_FLR */
+/* TGSI_OPCODE_FRC */
+#define TGSI_OPCODE_I2F                 83
+/* TGSI_OPCODE_LIT */
+/* TGSI_OPCODE_MOV */
+#define TGSI_OPCODE_NOT                 84
+/* TGSI_OPCODE_NRM */
+/* TGSI_OPCODE_PK2H */
+/* TGSI_OPCODE_PK2US */
+/* TGSI_OPCODE_PK4B */
+/* TGSI_OPCODE_PK4UB */
+/* TGSI_OPCODE_ROUND */
+/* TGSI_OPCODE_SSG */
+#define TGSI_OPCODE_TRUNC               85
+/* TGSI_OPCODE_COS */
+/* TGSI_OPCODE_EX2 */
+/* TGSI_OPCODE_LG2 */
+/* TGSI_OPCODE_RCC */
+/* TGSI_OPCODE_RCP */
+/* TGSI_OPCODE_RSQ */
+/* TGSI_OPCODE_SCS */
+/* TGSI_OPCODE_SIN */
+/* TGSI_OPCODE_UP2H */
+/* TGSI_OPCODE_UP2US */
+/* TGSI_OPCODE_UP4B */
+/* TGSI_OPCODE_UP4UB */
+/* TGSI_OPCODE_POW */
+/* TGSI_OPCODE_DIV */
+#define TGSI_OPCODE_SHL                 86
+#define TGSI_OPCODE_SHR                 87
+/* TGSI_OPCODE_ADD */
+#define TGSI_OPCODE_AND                 88
+/* TGSI_OPCODE_DP3 */
+/* TGSI_OPCODE_DP4 */
+/* TGSI_OPCODE_DPH */
+/* TGSI_OPCODE_DST */
+/* TGSI_OPCODE_MAX */
+/* TGSI_OPCODE_MIN */
+/* TGSI_OPCODE_MUL */
+#define TGSI_OPCODE_OR                  89
+/* TGSI_OPCODE_RFL */
+/* TGSI_OPCODE_SEQ */
+/* TGSI_OPCODE_SFL */
+/* TGSI_OPCODE_SGE */
+/* TGSI_OPCODE_SGT */
+/* TGSI_OPCODE_SLE */
+/* TGSI_OPCODE_SLT */
+/* TGSI_OPCODE_SNE */
+/* TGSI_OPCODE_STR */
+/* TGSI_OPCODE_SUB */
+/* TGSI_OPCODE_XPD */
+/* TGSI_OPCODE_DP2 */
+#define TGSI_OPCODE_MOD                 90
+#define TGSI_OPCODE_XOR                 91
+/* TGSI_OPCODE_CMP */
+/* TGSI_OPCODE_DP2A */
+/* TGSI_OPCODE_LRP */
+/* TGSI_OPCODE_MAD */
+#define TGSI_OPCODE_SAD                 92
+/* TGSI_OPCODE_X2D */
+/* TGSI_OPCODE_SWZ */
+/* TGSI_OPCODE_TEX */
+/* TGSI_OPCODE_TXB */
+#define TGSI_OPCODE_TXF                 93
+/* TGSI_OPCODE_TXL */
+/* TGSI_OPCODE_TXP */
+#define TGSI_OPCODE_TXQ                 94
+/* TGSI_OPCODE_TXD */
+/* TGSI_OPCODE_CAL */
+/* TGSI_OPCODE_RET */
+/* TGSI_OPCODE_BRK */
+#define TGSI_OPCODE_CONT                95
+/* TGSI_OPCODE_IF */
+/* TGSI_OPCODE_REP */
+/* TGSI_OPCODE_ELSE */
+/* TGSI_OPCODE_ENDIF */
+/* TGSI_OPCODE_ENDREP */
+
+/*
+ * GL_NV_vertex_program4
+ */
+/* Same as GL_NV_gpu_program4 */
+
+/*
+ * GL_NV_fragment_program4
+ */
+/* Same as GL_NV_gpu_program4 */
+/* TGSI_OPCODE_KIL */
+/* TGSI_OPCODE_DDX */
+/* TGSI_OPCODE_DDY */
+
+/*
+ * GL_NV_geometry_program4
+ */
+/* Same as GL_NV_gpu_program4 */
+#define TGSI_OPCODE_EMIT                96
+#define TGSI_OPCODE_ENDPRIM             97
+
+#define TGSI_OPCODE_LAST                98
+
+#define TGSI_SAT_NONE            0  /* do not saturate */
+#define TGSI_SAT_ZERO_ONE        1  /* clamp to [0,1] */
+#define TGSI_SAT_MINUS_PLUS_ONE  2  /* clamp to [-1,1] */
+
+/*
+ * Opcode is the operation code to execute. A given operation defines the
+ * semantics how the source registers (if any) are interpreted and what is
+ * written to the destination registers (if any) as a result of execution.
+ *
+ * NumDstRegs and NumSrcRegs is the number of destination and source registers,
+ * respectively. For a given operation code, those numbers are fixed and are
+ * present here only for convenience.
+ *
+ * If Extended is TRUE, it is now executed.
+ *
+ * Saturate controls how are final results in destination registers modified.
+ */
+
+struct tgsi_instruction
+{
+   GLuint Type       : 4;  /* TGSI_TOKEN_TYPE_INSTRUCTION */
+   GLuint Size       : 8;  /* UINT */
+   GLuint Opcode     : 8;  /* TGSI_OPCODE_ */
+   GLuint Saturate   : 2;  /* TGSI_SAT_ */
+   GLuint NumDstRegs : 2;  /* UINT */
+   GLuint NumSrcRegs : 4;  /* UINT */
+   GLuint Padding    : 3;
+   GLuint Extended   : 1;  /* BOOL */
+};
+
+/*
+ * If tgsi_instruction::Extended is TRUE, tgsi_instruction_ext follows.
+ * 
+ * Then, tgsi_instruction::NumDstRegs of tgsi_dst_register follow.
+ * 
+ * Then, tgsi_instruction::NumSrcRegs of tgsi_src_register follow.
+ *
+ * tgsi_instruction::Size contains the total number of words that make the
+ * instruction, including the instruction word.
+ */
+
+#define TGSI_INSTRUCTION_EXT_TYPE_NV        0
+#define TGSI_INSTRUCTION_EXT_TYPE_LABEL     1
+#define TGSI_INSTRUCTION_EXT_TYPE_TEXTURE   2
+
+struct tgsi_instruction_ext
+{
+   GLuint Type       : 4;  /* TGSI_INSTRUCTION_EXT_TYPE_ */
+   GLuint Padding    : 27;
+   GLuint Extended   : 1;  /* BOOL */
+};
+
+/*
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_NV, it should
+ * be cast to tgsi_instruction_ext_nv.
+ * 
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_LABEL, it
+ * should be cast to tgsi_instruction_ext_label.
+ * 
+ * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_TEXTURE, it
+ * should be cast to tgsi_instruction_ext_texture.
+ * 
+ * If tgsi_instruction_ext::Extended is TRUE, another tgsi_instruction_ext
+ * follows.
+ */
+
+#define TGSI_PRECISION_DEFAULT      0
+#define TGSI_PRECISION_FLOAT32      1
+#define TGSI_PRECISION_FLOAT16      2
+#define TGSI_PRECISION_FIXED12      3
+
+#define TGSI_CC_GT      0
+#define TGSI_CC_EQ      1
+#define TGSI_CC_LT      2
+#define TGSI_CC_UN      3
+#define TGSI_CC_GE      4
+#define TGSI_CC_LE      5
+#define TGSI_CC_NE      6
+#define TGSI_CC_TR      7
+#define TGSI_CC_FL      8
+
+#define TGSI_SWIZZLE_X      0
+#define TGSI_SWIZZLE_Y      1
+#define TGSI_SWIZZLE_Z      2
+#define TGSI_SWIZZLE_W      3
+
+/*
+ * Precision controls the precision at which the operation should be executed.
+ *
+ * CondDstUpdate enables condition code register writes. When this field is
+ * TRUE, CondDstIndex specifies the index of the condition code register to
+ * update.
+ *
+ * CondFlowEnable enables conditional execution of the operation. When this
+ * field is TRUE, CondFlowIndex specifies the index of the condition code
+ * register to test against CondMask with component swizzle controled by
+ * CondSwizzleX, CondSwizzleY, CondSwizzleZ and CondSwizzleW. If the test fails,
+ * the operation is not executed.
+ */
+
+struct tgsi_instruction_ext_nv
+{
+   GLuint Type             : 4;    /* TGSI_INSTRUCTION_EXT_TYPE_NV */
+   GLuint Precision        : 4;    /* TGSI_PRECISION_ */
+   GLuint CondDstIndex     : 4;    /* UINT */
+   GLuint CondFlowIndex    : 4;    /* UINT */
+   GLuint CondMask         : 4;    /* TGSI_CC_ */
+   GLuint CondSwizzleX     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSwizzleY     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSwizzleZ     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSwizzleW     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondDstUpdate    : 1;    /* BOOL */
+   GLuint CondFlowEnable   : 1;    /* BOOL */
+   GLuint Padding          : 1;
+   GLuint Extended         : 1;    /* BOOL */
+};
+
+struct tgsi_instruction_ext_label
+{
+   GLuint Type     : 4;    /* TGSI_INSTRUCTION_EXT_TYPE_LABEL */
+   GLuint Label    : 24;   /* UINT */
+   GLuint Target   : 1;    /* BOOL */
+   GLuint Padding  : 2;
+   GLuint Extended : 1;    /* BOOL */
+};
+
+#define TGSI_TEXTURE_UNKNOWN        0
+#define TGSI_TEXTURE_1D             1
+#define TGSI_TEXTURE_2D             2
+#define TGSI_TEXTURE_3D             3
+#define TGSI_TEXTURE_CUBE           4
+#define TGSI_TEXTURE_RECT           5
+#define TGSI_TEXTURE_SHADOW1D       6
+#define TGSI_TEXTURE_SHADOW2D       7
+#define TGSI_TEXTURE_SHADOWRECT     8
+
+struct tgsi_instruction_ext_texture
+{
+   GLuint Type     : 4;    /* TGSI_INSTRUCTION_EXT_TYPE_TEXTURE */
+   GLuint Texture  : 8;    /* TGSI_TEXTURE_ */
+   GLuint Padding  : 19;
+   GLuint Extended : 1;    /* BOOL */
+};
+
+/*
+ * File specifies the register array to access.
+ *
+ * Index specifies the element number of a register in the register file.
+ *
+ * If Indirect is TRUE, Index should be offset by the X component of a source
+ * register that follows. The register can be now fetched into local storage
+ * for further processing.
+ *
+ * If Negate is TRUE, all components of the fetched register are negated.
+ *
+ * The fetched register components are swizzled according to SwizzleX, SwizzleY,
+ * SwizzleZ and SwizzleW.
+ *
+ * If Extended is TRUE, any further modifications to the source register are
+ * made to this temporary storage.
+ */
+
+struct tgsi_src_register
+{
+   GLuint File         : 4;    /* TGSI_FILE_ */
+   GLuint SwizzleX     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint SwizzleY     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint SwizzleZ     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint SwizzleW     : 2;    /* TGSI_SWIZZLE_ */
+   GLuint Negate       : 1;    /* BOOL */
+   GLuint Indirect     : 1;    /* BOOL */
+   GLuint Dimension    : 1;    /* BOOL */
+   GLint  Index        : 16;   /* SINT */
+   GLuint Extended     : 1;    /* BOOL */
+};
+
+/*
+ * If tgsi_src_register::Extended is TRUE, tgsi_src_register_ext follows.
+ * 
+ * Then, if tgsi_src_register::Indirect is TRUE, another tgsi_src_register
+ * follows.
+ *
+ * Then, if tgsi_src_register::Dimension is TRUE, tgsi_dimension follows.
+ */
+
+#define TGSI_SRC_REGISTER_EXT_TYPE_SWZ      0
+#define TGSI_SRC_REGISTER_EXT_TYPE_MOD      1
+
+struct tgsi_src_register_ext
+{
+   GLuint Type     : 4;    /* TGSI_SRC_REGISTER_EXT_TYPE_ */
+   GLuint Padding  : 27;
+   GLuint Extended : 1;    /* BOOL */
+};
+
+/*
+ * If tgsi_src_register_ext::Type is TGSI_SRC_REGISTER_EXT_TYPE_SWZ,
+ * it should be cast to tgsi_src_register_ext_extswz.
+ * 
+ * If tgsi_src_register_ext::Type is TGSI_SRC_REGISTER_EXT_TYPE_MOD,
+ * it should be cast to tgsi_src_register_ext_mod.
+ * 
+ * If tgsi_dst_register_ext::Extended is TRUE, another tgsi_dst_register_ext
+ * follows.
+ */
+
+#define TGSI_EXTSWIZZLE_X       TGSI_SWIZZLE_X
+#define TGSI_EXTSWIZZLE_Y       TGSI_SWIZZLE_Y
+#define TGSI_EXTSWIZZLE_Z       TGSI_SWIZZLE_Z
+#define TGSI_EXTSWIZZLE_W       TGSI_SWIZZLE_W
+#define TGSI_EXTSWIZZLE_ZERO    4
+#define TGSI_EXTSWIZZLE_ONE     5
+
+/*
+ * ExtSwizzleX, ExtSwizzleY, ExtSwizzleZ and ExtSwizzleW swizzle the source
+ * register in an extended manner.
+ *
+ * NegateX, NegateY, NegateZ and NegateW negate individual components of the
+ * source register.
+ *
+ * ExtDivide specifies which component is used to divide all components of the
+ * source register.
+ */
+
+struct tgsi_src_register_ext_swz
+{
+   GLuint Type         : 4;    /* TGSI_SRC_REGISTER_EXT_TYPE_SWZ */
+   GLuint ExtSwizzleX  : 4;    /* TGSI_EXTSWIZZLE_ */
+   GLuint ExtSwizzleY  : 4;    /* TGSI_EXTSWIZZLE_ */
+   GLuint ExtSwizzleZ  : 4;    /* TGSI_EXTSWIZZLE_ */
+   GLuint ExtSwizzleW  : 4;    /* TGSI_EXTSWIZZLE_ */
+   GLuint NegateX      : 1;    /* BOOL */
+   GLuint NegateY      : 1;    /* BOOL */
+   GLuint NegateZ      : 1;    /* BOOL */
+   GLuint NegateW      : 1;    /* BOOL */
+   GLuint ExtDivide    : 4;    /* TGSI_EXTSWIZZLE_ */
+   GLuint Padding      : 3;
+   GLuint Extended     : 1;    /* BOOL */
+};
+
+/*
+ * If Complement is TRUE, the source register is modified by subtracting it
+ * from 1.0.
+ *
+ * If Bias is TRUE, the source register is modified by subtracting 0.5 from it.
+ *
+ * If Scale2X is TRUE, the source register is modified by multiplying it by 2.0.
+ *
+ * If Absolute is TRUE, the source register is modified by removing the sign.
+ *
+ * If Negate is TRUE, the source register is modified by negating it.
+ */
+
+struct tgsi_src_register_ext_mod
+{
+   GLuint Type         : 4;    /* TGSI_SRC_REGISTER_EXT_TYPE_MOD */
+   GLuint Complement   : 1;    /* BOOL */
+   GLuint Bias         : 1;    /* BOOL */
+   GLuint Scale2X      : 1;    /* BOOL */
+   GLuint Absolute     : 1;    /* BOOL */
+   GLuint Negate       : 1;    /* BOOL */
+   GLuint Padding      : 22;
+   GLuint Extended     : 1;    /* BOOL */
+};
+
+struct tgsi_dimension
+{
+   GLuint Indirect     : 1;    /* BOOL */
+   GLuint Dimension    : 1;    /* BOOL */
+   GLuint Padding      : 13;
+   GLint  Index        : 16;   /* SINT */
+   GLuint Extended     : 1;    /* BOOL */
+};
+
+#define TGSI_WRITEMASK_NONE     0x00
+#define TGSI_WRITEMASK_X        0x01
+#define TGSI_WRITEMASK_Y        0x02
+#define TGSI_WRITEMASK_XY       0x03
+#define TGSI_WRITEMASK_Z        0x04
+#define TGSI_WRITEMASK_XZ       0x05
+#define TGSI_WRITEMASK_YZ       0x06
+#define TGSI_WRITEMASK_XYZ      0x07
+#define TGSI_WRITEMASK_W        0x08
+#define TGSI_WRITEMASK_XW       0x09
+#define TGSI_WRITEMASK_YW       0x0A
+#define TGSI_WRITEMASK_XYW      0x0B
+#define TGSI_WRITEMASK_ZW       0x0C
+#define TGSI_WRITEMASK_XZW      0x0D
+#define TGSI_WRITEMASK_YZW      0x0E
+#define TGSI_WRITEMASK_XYZW     0x0F
+
+struct tgsi_dst_register
+{
+   GLuint File         : 4;    /* TGSI_FILE_ */
+   GLuint WriteMask    : 4;    /* TGSI_WRITEMASK_ */
+   GLuint Indirect     : 1;    /* BOOL */
+   GLuint Dimension    : 1;    /* BOOL */
+   GLint  Index        : 16;   /* SINT */
+   GLuint Padding      : 5;
+   GLuint Extended     : 1;    /* BOOL */
+};
+
+/*
+ * If tgsi_dst_register::Extended is TRUE, tgsi_dst_register_ext follows.
+ * 
+ * Then, if tgsi_dst_register::Indirect is TRUE, tgsi_src_register follows.
+ */
+
+#define TGSI_DST_REGISTER_EXT_TYPE_CONDCODE     0
+#define TGSI_DST_REGISTER_EXT_TYPE_MODULATE     1
+
+struct tgsi_dst_register_ext
+{
+   GLuint Type     : 4;    /* TGSI_DST_REGISTER_EXT_TYPE_ */
+   GLuint Padding  : 27;
+   GLuint Extended : 1;    /* BOOL */
+};
+
+/*
+ * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_CONDCODE,
+ * it should be cast to tgsi_dst_register_ext_condcode.
+ * 
+ * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_MODULATE,
+ * it should be cast to tgsi_dst_register_ext_modulate.
+ * 
+ * If tgsi_dst_register_ext::Extended is TRUE, another tgsi_dst_register_ext
+ * follows.
+ */
+
+struct tgsi_dst_register_ext_concode
+{
+   GLuint Type         : 4;    /* TGSI_DST_REGISTER_EXT_TYPE_CONDCODE */
+   GLuint CondMask     : 4;    /* TGSI_CC_ */
+   GLuint CondSwizzleX : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSwizzleY : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSwizzleZ : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSwizzleW : 2;    /* TGSI_SWIZZLE_ */
+   GLuint CondSrcIndex : 4;    /* UINT */
+   GLuint Padding      : 11;
+   GLuint Extended     : 1;    /* BOOL */
+};
+
+#define TGSI_MODULATE_1X        0
+#define TGSI_MODULATE_2X        1
+#define TGSI_MODULATE_4X        2
+#define TGSI_MODULATE_8X        3
+#define TGSI_MODULATE_HALF      4
+#define TGSI_MODULATE_QUARTER   5
+#define TGSI_MODULATE_EIGHTH    6
+
+struct tgsi_dst_register_ext_modulate
+{
+   GLuint Type     : 4;    /* TGSI_DST_REGISTER_EXT_TYPE_MODULATE */
+   GLuint Modulate : 4;    /* TGSI_MODULATE_ */
+   GLuint Padding  : 23;
+   GLuint Extended : 1;    /* BOOL */
+};
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_TOKEN_H
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_util.c b/src/mesa/pipe/tgsi/core/tgsi_util.c
new file mode 100644 (file)
index 0000000..38d6d6e
--- /dev/null
@@ -0,0 +1,270 @@
+#include "tgsi_platform.h"
+#include "tgsi_core.h"
+
+union pointer_hack
+{
+   void *pointer;
+   unsigned long long uint64;
+};
+
+void *
+tgsi_align_128bit(
+   void *unaligned )
+{
+   union pointer_hack ph;
+
+   ph.uint64 = 0;
+   ph.pointer = unaligned;
+   ph.uint64 = (ph.uint64 + 15) & ~15;
+   return ph.pointer;
+}
+
+GLuint
+tgsi_util_get_src_register_swizzle(
+   const struct tgsi_src_register *reg,
+   GLuint component )
+{
+   switch( component ) {
+   case 0:
+      return reg->SwizzleX;
+   case 1:
+      return reg->SwizzleY;
+   case 2:
+      return reg->SwizzleZ;
+   case 3:
+      return reg->SwizzleW;
+   default:
+      assert( 0 );
+   }
+   return 0;
+}
+
+GLuint
+tgsi_util_get_src_register_extswizzle(
+   const struct   tgsi_src_register_ext_swz *reg,
+   GLuint component )
+{
+   switch( component ) {
+   case 0:
+      return reg->ExtSwizzleX;
+   case 1:
+      return reg->ExtSwizzleY;
+   case 2:
+      return reg->ExtSwizzleZ;
+   case 3:
+      return reg->ExtSwizzleW;
+   default:
+      assert( 0 );
+   }
+   return 0;
+}
+
+GLuint
+tgsi_util_get_full_src_register_extswizzle(
+   const struct tgsi_full_src_register  *reg,
+   GLuint component )
+{
+   GLuint swizzle;
+
+   /*
+    * First, calculate  the   extended swizzle for a given channel. This will give
+    * us either a channel index into the simple swizzle or  a constant 1 or   0.
+    */
+   swizzle = tgsi_util_get_src_register_extswizzle(
+      &reg->SrcRegisterExtSwz,
+      component );
+
+   assert (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X);
+   assert (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y);
+   assert (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z);
+   assert (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W);
+   assert (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W);
+   assert (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W);
+
+   /*
+    * Second, calculate the simple  swizzle  for   the   unswizzled channel index.
+    * Leave the constants intact, they are   not   affected by the   simple swizzle.
+    */
+   if( swizzle <= TGSI_SWIZZLE_W ) {
+      swizzle = tgsi_util_get_src_register_swizzle(
+         &reg->SrcRegister,
+         swizzle );
+   }
+
+   return swizzle;
+}
+
+void
+tgsi_util_set_src_register_swizzle(
+   struct tgsi_src_register *reg,
+   GLuint swizzle,
+   GLuint component )
+{
+   switch( component ) {
+   case 0:
+      reg->SwizzleX = swizzle;
+      break;
+   case 1:
+      reg->SwizzleY = swizzle;
+      break;
+   case 2:
+      reg->SwizzleZ = swizzle;
+      break;
+   case 3:
+      reg->SwizzleW = swizzle;
+      break;
+   default:
+      assert( 0 );
+   }
+}
+
+void
+tgsi_util_set_src_register_extswizzle(
+   struct tgsi_src_register_ext_swz *reg,
+   GLuint swizzle,
+   GLuint component )
+{
+   switch( component ) {
+   case 0:
+      reg->ExtSwizzleX = swizzle;
+      break;
+   case 1:
+      reg->ExtSwizzleY = swizzle;
+      break;
+   case 2:
+      reg->ExtSwizzleZ = swizzle;
+      break;
+   case 3:
+      reg->ExtSwizzleW = swizzle;
+      break;
+   default:
+      assert( 0 );
+   }
+}
+
+GLuint
+tgsi_util_get_src_register_extnegate(
+   const  struct tgsi_src_register_ext_swz *reg,
+   GLuint component )
+{
+   switch( component ) {
+   case 0:
+      return reg->NegateX;
+   case 1:
+      return reg->NegateY;
+   case 2:
+      return reg->NegateZ;
+   case 3:
+      return reg->NegateW;
+   default:
+      assert( 0 );
+   }
+   return 0;
+}
+
+void
+tgsi_util_set_src_register_extnegate(
+   struct tgsi_src_register_ext_swz *reg,
+   GLuint negate,
+   GLuint component )
+{
+   switch( component ) {
+   case 0:
+      reg->NegateX = negate;
+      break;
+   case 1:
+      reg->NegateY = negate;
+      break;
+   case 2:
+      reg->NegateZ = negate;
+      break;
+   case 3:
+      reg->NegateW = negate;
+      break;
+   default:
+      assert( 0 );
+   }
+}
+
+GLuint
+tgsi_util_get_full_src_register_sign_mode(
+   const struct  tgsi_full_src_register *reg,
+   GLuint component )
+{
+   GLuint sign_mode;
+
+   if( reg->SrcRegisterExtMod.Absolute ) {
+      /* Consider only the post-abs negation. */
+
+      if( reg->SrcRegisterExtMod.Negate ) {
+         sign_mode = TGSI_UTIL_SIGN_SET;
+      }
+      else {
+         sign_mode = TGSI_UTIL_SIGN_CLEAR;
+      }
+   }
+   else {
+      /* Accumulate the three negations. */
+
+      GLuint negate;
+
+      negate = reg->SrcRegister.Negate;
+      if( tgsi_util_get_src_register_extnegate( &reg->SrcRegisterExtSwz, component ) ) {
+         negate = !negate;
+      }
+      if( reg->SrcRegisterExtMod.Negate ) {
+         negate = !negate;
+      }
+
+      if( negate ) {
+         sign_mode = TGSI_UTIL_SIGN_TOGGLE;
+      }
+      else {
+         sign_mode = TGSI_UTIL_SIGN_KEEP;
+      }
+   }
+
+   return sign_mode;
+}
+
+void
+tgsi_util_set_full_src_register_sign_mode(
+   struct tgsi_full_src_register *reg,
+   GLuint sign_mode )
+{
+   reg->SrcRegisterExtSwz.NegateX = 0;
+   reg->SrcRegisterExtSwz.NegateY = 0;
+   reg->SrcRegisterExtSwz.NegateZ = 0;
+   reg->SrcRegisterExtSwz.NegateW = 0;
+
+   switch (sign_mode)
+   {
+   case TGSI_UTIL_SIGN_CLEAR:
+      reg->SrcRegister.Negate = 0;
+      reg->SrcRegisterExtMod.Absolute = 1;
+      reg->SrcRegisterExtMod.Negate = 0;
+      break;
+
+   case TGSI_UTIL_SIGN_SET:
+      reg->SrcRegister.Negate = 0;
+      reg->SrcRegisterExtMod.Absolute = 1;
+      reg->SrcRegisterExtMod.Negate = 1;
+      break;
+
+   case TGSI_UTIL_SIGN_TOGGLE:
+      reg->SrcRegister.Negate = 1;
+      reg->SrcRegisterExtMod.Absolute = 0;
+      reg->SrcRegisterExtMod.Negate = 0;
+      break;
+
+   case TGSI_UTIL_SIGN_KEEP:
+      reg->SrcRegister.Negate = 0;
+      reg->SrcRegisterExtMod.Absolute = 0;
+      reg->SrcRegisterExtMod.Negate = 0;
+      break;
+
+   default:
+      assert( 0 );
+   }
+}
+
diff --git a/src/mesa/pipe/tgsi/core/tgsi_util.h b/src/mesa/pipe/tgsi/core/tgsi_util.h
new file mode 100644 (file)
index 0000000..70c4869
--- /dev/null
@@ -0,0 +1,70 @@
+#if !defined TGSI_UTIL_H
+#define TGSI_UTIL_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+void *
+tgsi_align_128bit(
+   void *unaligned );
+
+GLuint
+tgsi_util_get_src_register_swizzle(
+   const struct tgsi_src_register *reg,
+   GLuint component );
+
+GLuint
+tgsi_util_get_src_register_extswizzle(
+   const struct tgsi_src_register_ext_swz *reg,
+   GLuint component);
+
+GLuint
+tgsi_util_get_full_src_register_extswizzle(
+   const struct tgsi_full_src_register *reg,
+   GLuint component );
+
+void
+tgsi_util_set_src_register_swizzle(
+   struct tgsi_src_register *reg,
+   GLuint swizzle,
+   GLuint component );
+
+void
+tgsi_util_set_src_register_extswizzle(
+   struct tgsi_src_register_ext_swz *reg,
+   GLuint swizzle,
+   GLuint component );
+
+GLuint
+tgsi_util_get_src_register_extnegate(
+   const struct tgsi_src_register_ext_swz *reg,
+   GLuint component );
+
+void
+tgsi_util_set_src_register_extnegate(
+   struct tgsi_src_register_ext_swz *reg,
+   GLuint negate,
+   GLuint component );
+
+#define TGSI_UTIL_SIGN_CLEAR    0   /* Force positive */
+#define TGSI_UTIL_SIGN_SET      1   /* Force negative */
+#define TGSI_UTIL_SIGN_TOGGLE   2   /* Negate */
+#define TGSI_UTIL_SIGN_KEEP     3   /* No change */
+
+GLuint
+tgsi_util_get_full_src_register_sign_mode(
+   const struct tgsi_full_src_register *reg,
+   GLuint component );
+
+void
+tgsi_util_set_full_src_register_sign_mode(
+   struct tgsi_full_src_register *reg,
+   GLuint sign_mode );
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_UTIL_H
+
diff --git a/src/mesa/pipe/tgsi/mesa/Makefile b/src/mesa/pipe/tgsi/mesa/Makefile
new file mode 100644 (file)
index 0000000..eb8b14e
--- /dev/null
@@ -0,0 +1,3 @@
+default:
+       cd ../../.. ; make
+
diff --git a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c
new file mode 100644 (file)
index 0000000..a9415ac
--- /dev/null
@@ -0,0 +1,546 @@
+#include "tgsi_platform.h"\r
+#include "tgsi_mesa.h"\r
+\r
+/*\r
+ * Map mesa register file to SBIR register file.\r
+ */\r
+static GLuint\r
+map_register_file(\r
+   enum register_file file )\r
+{\r
+   switch( file ) {\r
+   case PROGRAM_UNDEFINED:\r
+      return TGSI_FILE_NULL;\r
+   case PROGRAM_TEMPORARY:\r
+      return TGSI_FILE_TEMPORARY;\r
+   //case PROGRAM_LOCAL_PARAM:\r
+   //case PROGRAM_ENV_PARAM:\r
+   case PROGRAM_STATE_VAR:\r
+   case PROGRAM_NAMED_PARAM:\r
+   case PROGRAM_CONSTANT:\r
+   case PROGRAM_UNIFORM:\r
+      return TGSI_FILE_CONSTANT;\r
+   case PROGRAM_INPUT:\r
+      return TGSI_FILE_INPUT;\r
+   case PROGRAM_OUTPUT:\r
+      return TGSI_FILE_OUTPUT;\r
+   case PROGRAM_ADDRESS:\r
+      return TGSI_FILE_ADDRESS;\r
+   default:\r
+      assert( 0 );\r
+      return TGSI_FILE_NULL;\r
+   }\r
+}\r
+\r
+/**\r
+ * Map mesa register file index to SBIR index.\r
+ * Take special care when processing input and output indices.\r
+ * \param processor  either TGSI_PROCESSOR_FRAGMENT or  TGSI_PROCESSOR_VERTEX\r
+ * \param file  one of TGSI_FILE_x\r
+ * \param index  the mesa register file index\r
+ * \param usage_bitmask  ???\r
+ */\r
+static GLuint\r
+map_register_file_index(\r
+   GLuint processor,\r
+   GLuint file,\r
+   GLuint index,\r
+   GLbitfield usage_bitmask )\r
+{\r
+   GLuint mapped_index;\r
+   GLuint i;\r
+\r
+   switch( file ) {\r
+   case TGSI_FILE_INPUT:\r
+      /*\r
+       * The fragment/vertex program input indexes (FRAG/VERT_ATTRIB_x) get\r
+       * mapped to a packed sequence of integers.\r
+       * If a program uses one input attribute, the mapped index will be 1.\r
+       * If a program uses two input attribs, the mapped indexes will be 1,2.\r
+       * If a program uses 3 input attribs, the mapped indexes will be 1,2,3.\r
+       * etc.\r
+       */\r
+      assert( index < 32 );\r
+      assert( usage_bitmask & (1 << index) );\r
+      mapped_index = 0;\r
+      for( i = 0; i < index; i++ ) {\r
+         if( usage_bitmask & (1 << i) ) {\r
+            mapped_index++;\r
+         }\r
+      }\r
+      printf("Map input %d to %d\n", index, mapped_index);\r
+      break;\r
+\r
+   case TGSI_FILE_OUTPUT:\r
+      assert( usage_bitmask == 0x0 );\r
+      if( processor == TGSI_PROCESSOR_FRAGMENT ) {\r
+         /* depth result  -> index 0\r
+          * color results -> index 1, 2, ...\r
+          */\r
+        if( index == FRAG_RESULT_DEPR ) {\r
+            mapped_index = 0;\r
+         }\r
+         else {\r
+            assert( index == FRAG_RESULT_COLR );\r
+            mapped_index = index + 1;\r
+         }\r
+      }\r
+      else {\r
+         /* mapped_index = VERT_RESULT_x */\r
+         mapped_index = index;\r
+      }\r
+      break;\r
+\r
+   default:\r
+      mapped_index = index;\r
+   }\r
+\r
+   return mapped_index;\r
+}\r
+\r
+/*\r
+ * Map mesa texture target to SBIR texture target.\r
+ */\r
+static GLuint\r
+map_texture_target(\r
+   GLuint textarget )\r
+{\r
+   switch( textarget ) {\r
+   case TEXTURE_1D_INDEX:\r
+      return TGSI_TEXTURE_1D;\r
+   case TEXTURE_2D_INDEX:\r
+      return TGSI_TEXTURE_2D;\r
+   case TEXTURE_3D_INDEX:\r
+      return TGSI_TEXTURE_3D;\r
+   case TEXTURE_CUBE_INDEX:\r
+      return TGSI_TEXTURE_CUBE;\r
+   case TEXTURE_RECT_INDEX:\r
+      return TGSI_TEXTURE_RECT;\r
+   default:\r
+      assert( 0 );\r
+   }\r
+\r
+   return TGSI_TEXTURE_1D;\r
+}\r
+\r
+static GLuint\r
+convert_sat(\r
+   GLuint sat )\r
+{\r
+   switch( sat ) {\r
+   case SATURATE_OFF:\r
+      return TGSI_SAT_NONE;\r
+   case SATURATE_ZERO_ONE:\r
+      return TGSI_SAT_ZERO_ONE;\r
+   case SATURATE_PLUS_MINUS_ONE:\r
+      return TGSI_SAT_MINUS_PLUS_ONE;\r
+   default:\r
+      assert( 0 );\r
+      return TGSI_SAT_NONE;\r
+   }\r
+}\r
+\r
+static GLuint\r
+convert_writemask(\r
+   GLuint writemask )\r
+{\r
+   assert( WRITEMASK_X == TGSI_WRITEMASK_X );\r
+   assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );\r
+   assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );\r
+   assert( WRITEMASK_W == TGSI_WRITEMASK_W );\r
+   assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );\r
+\r
+   return writemask;\r
+}\r
+\r
+static GLboolean\r
+compile_instruction(\r
+   const struct prog_instruction *inst,\r
+   struct tgsi_full_instruction *fullinst,\r
+   GLuint inputs_read,\r
+   GLuint processor )\r
+{\r
+   GLuint i;\r
+   struct tgsi_full_dst_register *fulldst;\r
+   struct tgsi_full_src_register *fullsrc;\r
+\r
+   *fullinst = tgsi_default_full_instruction();\r
+\r
+   fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );\r
+   fullinst->Instruction.NumDstRegs = 1;\r
+   fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );\r
+\r
+   fulldst = &fullinst->FullDstRegisters[0];\r
+   fulldst->DstRegister.File = map_register_file( inst->DstReg.File );\r
+   fulldst->DstRegister.Index = map_register_file_index(\r
+      processor,\r
+      fulldst->DstRegister.File,\r
+      inst->DstReg.Index,\r
+      0x0 );\r
+   fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );\r
+\r
+   for( i = 0; i < fullinst->Instruction.NumSrcRegs; i++ ) {\r
+      GLuint j;\r
+\r
+      fullsrc = &fullinst->FullSrcRegisters[i];\r
+      fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File );\r
+      fullsrc->SrcRegister.Index = map_register_file_index(\r
+         processor,\r
+         fullsrc->SrcRegister.File,\r
+         inst->SrcReg[i].Index,\r
+         inputs_read );\r
+\r
+      for( j = 0; j < 4; j++ ) {\r
+         GLuint swz;\r
+\r
+         swz = GET_SWZ( inst->SrcReg[i].Swizzle, j );\r
+         if( swz > SWIZZLE_W ) {\r
+            tgsi_util_set_src_register_extswizzle(\r
+               &fullsrc->SrcRegisterExtSwz,\r
+               swz,\r
+               j );\r
+         }\r
+         else {\r
+            tgsi_util_set_src_register_swizzle(\r
+               &fullsrc->SrcRegister,\r
+               swz,\r
+               j );\r
+         }\r
+      }\r
+\r
+      if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {\r
+         fullsrc->SrcRegister.Negate = 1;\r
+      }\r
+      else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {\r
+         if( inst->SrcReg[i].NegateBase & NEGATE_X ) {\r
+            fullsrc->SrcRegisterExtSwz.NegateX = 1;\r
+         }\r
+         if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {\r
+            fullsrc->SrcRegisterExtSwz.NegateY = 1;\r
+         }\r
+         if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {\r
+            fullsrc->SrcRegisterExtSwz.NegateZ = 1;\r
+         }\r
+         if( inst->SrcReg[i].NegateBase & NEGATE_W ) {\r
+            fullsrc->SrcRegisterExtSwz.NegateW = 1;\r
+         }\r
+      }\r
+\r
+      if( inst->SrcReg[i].Abs ) {\r
+         fullsrc->SrcRegisterExtMod.Absolute = 1;\r
+      }\r
+\r
+      if( inst->SrcReg[i].NegateAbs ) {\r
+         fullsrc->SrcRegisterExtMod.Negate = 1;\r
+      }\r
+\r
+      if( inst->SrcReg[i].RelAddr ) {\r
+         fullsrc->SrcRegister.Indirect = 1;\r
+\r
+         fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;\r
+         fullsrc->SrcRegisterInd.Index = 0;\r
+      }\r
+   }\r
+\r
+   switch( inst->Opcode ) {\r
+   case OPCODE_ARL:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;\r
+      break;\r
+   case OPCODE_ABS:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;\r
+      break;\r
+   case OPCODE_ADD:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;\r
+      break;\r
+   case OPCODE_CMP:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;\r
+      break;\r
+   case OPCODE_COS:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_COS;\r
+      break;\r
+   case OPCODE_DP3:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;\r
+      break;\r
+   case OPCODE_DDX:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;\r
+      break;\r
+   case OPCODE_DDY:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;\r
+      break;\r
+   case OPCODE_DP4:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;\r
+      break;\r
+   case OPCODE_DPH:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;\r
+      break;\r
+   case OPCODE_DST:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_DST;\r
+      break;\r
+   case OPCODE_EX2:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;\r
+      break;\r
+   case OPCODE_FLR:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;\r
+      break;\r
+   case OPCODE_FRC:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;\r
+      break;\r
+   case OPCODE_KIL:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;\r
+      break;\r
+   case OPCODE_LG2:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;\r
+      break;\r
+   case OPCODE_LIT:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;\r
+      break;\r
+   case OPCODE_LRP:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;\r
+      break;\r
+   case OPCODE_MAD:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;\r
+      break;\r
+   case OPCODE_MAX:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;\r
+      break;\r
+   case OPCODE_MIN:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;\r
+      break;\r
+   case OPCODE_MOV:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;\r
+      break;\r
+   case OPCODE_MUL:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;\r
+      break;\r
+   case OPCODE_POW:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_POW;\r
+      break;\r
+   case OPCODE_RCP:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;\r
+      break;\r
+   case OPCODE_RSQ:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;\r
+      tgsi_util_set_full_src_register_sign_mode(\r
+         &fullinst->FullSrcRegisters[0],\r
+         TGSI_UTIL_SIGN_CLEAR );\r
+      break;\r
+   case OPCODE_SCS:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;\r
+      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;\r
+      break;\r
+   case OPCODE_SGE:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;\r
+      break;\r
+   case OPCODE_SIN:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;\r
+      break;\r
+   case OPCODE_SLT:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;\r
+      break;\r
+   case OPCODE_SUB:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;\r
+      break;\r
+   case OPCODE_SWZ:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;\r
+      break;\r
+   case OPCODE_TEX:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;\r
+      fullinst->Instruction.NumSrcRegs = 2;\r
+      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );\r
+      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;\r
+      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;\r
+      break;\r
+   case OPCODE_TXB:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;\r
+      fullinst->Instruction.NumSrcRegs = 2;\r
+      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );\r
+      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;\r
+      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;\r
+      break;\r
+   case OPCODE_TXP:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;\r
+      fullinst->Instruction.NumSrcRegs = 2;\r
+      fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );\r
+      fullinst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide = TGSI_EXTSWIZZLE_W;\r
+      fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;\r
+      fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;\r
+      break;\r
+   case OPCODE_XPD:\r
+      fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;\r
+      fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;\r
+      break;\r
+   case OPCODE_END:\r
+      return GL_TRUE;\r
+   default:\r
+      assert( 0 );\r
+   }\r
+\r
+   return GL_FALSE;\r
+}\r
+\r
+GLboolean\r
+tgsi_mesa_compile_fp_program(\r
+   const struct gl_fragment_program *program,\r
+   struct tgsi_token *tokens,\r
+   GLuint maxTokens )\r
+{\r
+   GLuint i, ti;\r
+   struct tgsi_header *header;\r
+   struct tgsi_full_declaration fulldecl;\r
+   struct tgsi_full_instruction fullinst;\r
+   struct tgsi_full_dst_register *fulldst;\r
+   struct tgsi_full_src_register *fullsrc;\r
+   GLuint inputs_read;\r
+\r
+   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();\r
+\r
+   header = (struct tgsi_header *) &tokens[1];\r
+   *header = tgsi_build_header();\r
+\r
+   ti = 2;\r
+\r
+   /*\r
+    * Input 0 is always read, at least implicitly by the instruction generated\r
+    * above, so mark it as used.\r
+    */\r
+   inputs_read = program->Base.InputsRead | 1;\r
+\r
+   /*\r
+    * Declare input attributes.\r
+    */\r
+   fulldecl = tgsi_default_full_declaration();\r
+\r
+   fulldecl.Declaration.File = TGSI_FILE_INPUT;\r
+   fulldecl.Declaration.Declare = TGSI_DECLARE_RANGE;\r
+   fulldecl.Declaration.Interpolate = 1;\r
+\r
+   /*\r
+    * Do not interpolate fragment position.\r
+    */\r
+   fulldecl.u.DeclarationRange.First = 0;\r
+   fulldecl.u.DeclarationRange.Last = 0;\r
+\r
+   fulldecl.Interpolation.Interpolate = TGSI_INTERPOLATE_CONSTANT;\r
+\r
+   ti += tgsi_build_full_declaration(\r
+      &fulldecl,\r
+      &tokens[ti],\r
+      header,\r
+      maxTokens - ti );\r
+\r
+   /*\r
+    * Interpolate generic attributes.\r
+    */\r
+   fulldecl.u.DeclarationRange.First = 1;\r
+   fulldecl.u.DeclarationRange.Last = 1;\r
+   for( i = 1; i < 32; i++ ) {\r
+      if( inputs_read & (1 << i) ) {\r
+         fulldecl.u.DeclarationRange.Last++;\r
+      }\r
+   }\r
+\r
+   fulldecl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;\r
+\r
+   ti += tgsi_build_full_declaration(\r
+      &fulldecl,\r
+      &tokens[ti],\r
+      header,\r
+      maxTokens - ti );\r
+\r
+   /*\r
+    * Copy input fragment xyz to output xyz.\r
+    * If the shader writes depth, do not copy the z component.\r
+    */\r
+\r
+   fullinst = tgsi_default_full_instruction();\r
+\r
+   fullinst.Instruction.Opcode = TGSI_OPCODE_MOV;\r
+   fullinst.Instruction.NumDstRegs = 1;\r
+   fullinst.Instruction.NumSrcRegs = 1;\r
+\r
+   fulldst = &fullinst.FullDstRegisters[0];\r
+   fulldst->DstRegister.File = TGSI_FILE_OUTPUT;\r
+   fulldst->DstRegister.Index = 0;\r
+   if( program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR) ) {\r
+      fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XY;\r
+   }\r
+   else {\r
+      fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;\r
+   }\r
+\r
+   fullsrc = &fullinst.FullSrcRegisters[0];\r
+   fullsrc->SrcRegister.File = TGSI_FILE_INPUT;\r
+   fullsrc->SrcRegister.Index = 0;\r
+\r
+   ti += tgsi_build_full_instruction(\r
+      &fullinst,\r
+      &tokens[ti],\r
+      header,\r
+      maxTokens - ti );\r
+\r
+   for( i = 0; i < program->Base.NumInstructions; i++ ) {\r
+      if( compile_instruction(\r
+            &program->Base.Instructions[i],\r
+            &fullinst,\r
+            inputs_read,\r
+            TGSI_PROCESSOR_FRAGMENT ) ) {\r
+         assert( i == program->Base.NumInstructions - 1 );\r
+         tgsi_dump(\r
+            tokens,\r
+            TGSI_DUMP_NO_IGNORED | TGSI_DUMP_NO_DEFAULT );\r
+         break;\r
+      }\r
+\r
+      ti += tgsi_build_full_instruction(\r
+         &fullinst,\r
+         &tokens[ti],\r
+         header,\r
+         maxTokens - ti );\r
+   }\r
+\r
+   return GL_TRUE;\r
+}\r
+\r
+GLboolean\r
+tgsi_mesa_compile_vp_program(\r
+   const struct gl_vertex_program *program,\r
+   struct tgsi_token *tokens,\r
+   GLuint maxTokens )\r
+{\r
+   GLuint ii, ti;\r
+   struct tgsi_header *header;\r
+   struct tgsi_processor *processor;\r
+   struct tgsi_full_instruction fullinst;\r
+   GLuint inputs_read = ~0;\r
+\r
+   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();\r
+\r
+   header = (struct tgsi_header *) &tokens[1];\r
+   *header = tgsi_build_header();\r
+\r
+   processor = (struct tgsi_processor *) &tokens[2];\r
+   *processor = tgsi_build_processor( TGSI_PROCESSOR_VERTEX, header );\r
+\r
+   ti = 3;\r
+\r
+   for( ii = 0; ii < program->Base.NumInstructions; ii++ ) {\r
+      if( compile_instruction(\r
+            &program->Base.Instructions[ii],\r
+            &fullinst,\r
+            inputs_read,\r
+            TGSI_PROCESSOR_VERTEX ) ) {\r
+         assert( ii == program->Base.NumInstructions - 1 );\r
+         tgsi_dump( tokens, TGSI_DUMP_NO_IGNORED | TGSI_DUMP_NO_DEFAULT );\r
+         break;\r
+      }\r
+\r
+      ti += tgsi_build_full_instruction(\r
+         &fullinst,\r
+         &tokens[ti],\r
+         header,\r
+         maxTokens - ti );\r
+   }\r
+\r
+   return GL_TRUE;\r
+}\r
+\r
diff --git a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.h b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.h
new file mode 100644 (file)
index 0000000..9256318
--- /dev/null
@@ -0,0 +1,27 @@
+#if !defined MESA_TO_TGSI_H\r
+#define MESA_TO_TGSI_H\r
+\r
+#if defined __cplusplus\r
+extern "C" {\r
+#endif // defined __cplusplus\r
+\r
+struct tgsi_token;\r
+\r
+GLboolean\r
+tgsi_mesa_compile_fp_program(\r
+   const struct gl_fragment_program *program,\r
+   struct tgsi_token *tokens,\r
+   GLuint maxTokens );\r
+\r
+GLboolean\r
+tgsi_mesa_compile_vp_program(\r
+   const struct gl_vertex_program *program,\r
+   struct tgsi_token *tokens,\r
+   GLuint maxTokens );\r
+\r
+#if defined __cplusplus\r
+} // extern "C"\r
+#endif // defined __cplusplus\r
+\r
+#endif // !defined MESA_TO_TGSI_H\r
+\r
diff --git a/src/mesa/pipe/tgsi/mesa/tgsi_mesa.h b/src/mesa/pipe/tgsi/mesa/tgsi_mesa.h
new file mode 100644 (file)
index 0000000..0053748
--- /dev/null
@@ -0,0 +1,8 @@
+#if !defined TGSI_MESA_H\r
+#define TGSI_MESA_H\r
+\r
+#include "../core/tgsi_core.h"\r
+#include "mesa_to_tgsi.h"\r
+\r
+#endif // !defined TGSI_MESA_H\r
+\r
diff --git a/src/mesa/pipe/tgsi/tgsi_platform.h b/src/mesa/pipe/tgsi/tgsi_platform.h
new file mode 100644 (file)
index 0000000..553f0b2
--- /dev/null
@@ -0,0 +1,18 @@
+#if !defined TGSI_PLATFORM_H
+#define TGSI_PLATFORM_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+#include "imports.h"
+#include "mtypes.h"
+#include "prog_instruction.h"
+#include "program.h"
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined TGSI_PLATFORM_H
+
index dbfc01d0edfb2270ee27b4e930a2ad2d2b4ef90c..a589ae4373b87618912ed3e9462c5a70e548f09e 100644 (file)
@@ -149,6 +149,75 @@ VBO_SOURCES = \
        vbo/vbo_save_draw.c \
        vbo/vbo_save_loopback.c 
 
+VF_SOURCES = \
+       vf/vf.c \
+       vf/vf_generic.c \
+       vf/vf_sse.c
+
+SOFTPIPE_SOURCES = \
+       pipe/softpipe/sp_clear.c \
+       pipe/softpipe/sp_context.c \
+       pipe/softpipe/sp_quad.c \
+       pipe/softpipe/sp_quad_alpha_test.c \
+       pipe/softpipe/sp_quad_blend.c \
+       pipe/softpipe/sp_quad_bufloop.c \
+       pipe/softpipe/sp_quad_colormask.c \
+       pipe/softpipe/sp_quad_coverage.c \
+       pipe/softpipe/sp_quad_depth_test.c \
+       pipe/softpipe/sp_quad_fs.c \
+       pipe/softpipe/sp_quad_occlusion.c \
+       pipe/softpipe/sp_quad_output.c \
+       pipe/softpipe/sp_quad_stipple.c \
+       pipe/softpipe/sp_quad_stencil.c \
+       pipe/softpipe/sp_state_blend.c \
+       pipe/softpipe/sp_state_clip.c \
+       pipe/softpipe/sp_state_derived.c \
+       pipe/softpipe/sp_state_fs.c \
+       pipe/softpipe/sp_state_sampler.c \
+       pipe/softpipe/sp_state_setup.c \
+       pipe/softpipe/sp_state_surface.c \
+       pipe/softpipe/sp_prim_setup.c
+
+DRAW_SOURCES = \
+       pipe/draw/draw_clip.c \
+       pipe/draw/draw_context.c\
+       pipe/draw/draw_cull.c \
+       pipe/draw/draw_flatshade.c \
+       pipe/draw/draw_offset.c \
+       pipe/draw/draw_twoside.c \
+       pipe/draw/draw_unfilled.c \
+       pipe/draw/draw_vb.c
+
+TGSICORE_SOURCES = \
+       pipe/tgsi/core/tgsi_build.c \
+       pipe/tgsi/core/tgsi_dump.c \
+       pipe/tgsi/core/tgsi_exec.c \
+       pipe/tgsi/core/tgsi_parse.c \
+       pipe/tgsi/core/tgsi_util.c
+
+TGSIMESA_SOURCES = \
+       pipe/tgsi/mesa/mesa_to_tgsi.c
+
+STATETRACKER_SOURCES = \
+       state_tracker/st_atom.c \
+       state_tracker/st_atom_alphatest.c \
+       state_tracker/st_atom_blend.c \
+       state_tracker/st_atom_clear_color.c \
+       state_tracker/st_atom_clip.c \
+       state_tracker/st_atom_depth.c \
+       state_tracker/st_atom_fs.c \
+       state_tracker/st_atom_vs.c \
+       state_tracker/st_atom_framebuffer.c \
+       state_tracker/st_atom_sampler.c \
+       state_tracker/st_atom_scissor.c \
+       state_tracker/st_atom_setup.c \
+       state_tracker/st_atom_stencil.c \
+       state_tracker/st_atom_stipple.c \
+       state_tracker/st_atom_viewport.c \
+       state_tracker/st_cb_program.c \
+       state_tracker/st_draw.c \
+       state_tracker/st_context.c \
+       state_tracker/st_texobj.c
 
 SHADER_SOURCES = \
        shader/arbprogparse.c \
@@ -250,6 +319,7 @@ X11_DRIVER_SOURCES =                \
        drivers/x11/xm_glide.c  \
        drivers/x11/xm_line.c   \
        drivers/x11/xm_span.c   \
+       drivers/x11/xm_surface.c        \
        drivers/x11/xm_tri.c
 
 OSMESA_DRIVER_SOURCES = \
@@ -294,6 +364,12 @@ SOLO_SOURCES = \
        $(MAIN_SOURCES)         \
        $(MATH_SOURCES)         \
        $(VBO_SOURCES)          \
+       $(VF_SOURCES)           \
+       $(SOFTPIPE_SOURCES)     \
+       $(DRAW_SOURCES)         \
+       $(TGSICORE_SOURCES)     \
+       $(TGSIMESA_SOURCES)     \
+       $(STATETRACKER_SOURCES) \
        $(TNL_SOURCES)          \
        $(SHADER_SOURCES)       \
        $(SWRAST_SOURCES)       \
@@ -339,4 +415,5 @@ INCLUDE_DIRS = \
        -I$(TOP)/src/mesa/shader/grammar \
        -I$(TOP)/src/mesa/shader/slang \
        -I$(TOP)/src/mesa/swrast \
-       -I$(TOP)/src/mesa/swrast_setup
+       -I$(TOP)/src/mesa/swrast_setup \
+       -I$(TOP)/src/mesa/pipe/tgsi
diff --git a/src/mesa/state_tracker/Makefile b/src/mesa/state_tracker/Makefile
new file mode 100644 (file)
index 0000000..0ab1dc6
--- /dev/null
@@ -0,0 +1,2 @@
+default:
+       cd ../.. ; make
\ No newline at end of file
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c
new file mode 100644 (file)
index 0000000..85c99bc
--- /dev/null
@@ -0,0 +1,175 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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 "glheader.h"
+#include "context.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+
+       
+
+/* This is used to initialize st->atoms[].  We could use this list
+ * directly except for a single atom, st_update_constants, which has a
+ * .dirty value which changes according to the parameters of the
+ * current fragment and vertex programs, and so cannot be a static
+ * value.
+ */
+static const struct st_tracked_state *atoms[] =
+{
+   &st_update_framebuffer,
+   &st_update_clear_color,
+   &st_update_depth,
+   &st_update_clip,
+   &st_update_vs,
+   &st_update_fs,
+   &st_update_setup,
+   &st_update_polygon_stipple,
+   &st_update_viewport,
+   &st_update_scissor,
+   &st_update_blend,
+   &st_update_stencil,
+   /* will be patched out at runtime */
+/*    &st_update_constants */
+};
+
+
+void st_init_atoms( struct st_context *st )
+{
+   GLuint i;
+
+   st->atoms = malloc(sizeof(atoms));
+   st->nr_atoms = sizeof(atoms)/sizeof(*atoms);
+   memcpy(st->atoms, atoms, sizeof(atoms));
+
+   /* Patch in a pointer to the dynamic state atom:
+    */
+   for (i = 0; i < st->nr_atoms; i++)
+      if (st->atoms[i] == &st_update_constants)
+        st->atoms[i] = &st->constants.tracked_state;
+
+   memcpy(&st->constants.tracked_state, 
+          &st_update_constants,
+          sizeof(st_update_constants));
+}
+
+
+void st_destroy_atoms( struct st_context *st )
+{
+   if (st->atoms) {
+      free(st->atoms);
+      st->atoms = NULL;
+   }
+}
+
+
+/***********************************************************************
+ */
+
+static GLboolean check_state( const struct st_state_flags *a,
+                             const struct st_state_flags *b )
+{
+   return ((a->mesa & b->mesa) ||
+          (a->st & b->st));
+}
+
+static void accumulate_state( struct st_state_flags *a,
+                             const struct st_state_flags *b )
+{
+   a->mesa |= b->mesa;
+   a->st |= b->st;
+}
+
+
+static void xor_states( struct st_state_flags *result,
+                            const struct st_state_flags *a,
+                             const struct st_state_flags *b )
+{
+   result->mesa = a->mesa ^ b->mesa;
+   result->st = a->st ^ b->st;
+}
+
+
+/***********************************************************************
+ * Update all derived state:
+ */
+
+void st_validate_state( struct st_context *st )
+{
+   struct st_state_flags *state = &st->dirty;
+   GLuint i;
+
+   if (state->st == 0)
+      return;
+
+   if (1) {
+      /* Debug version which enforces various sanity checks on the
+       * state flags which are generated and checked to help ensure
+       * state atoms are ordered correctly in the list.
+       */
+      struct st_state_flags examined, prev;      
+      memset(&examined, 0, sizeof(examined));
+      prev = *state;
+
+      for (i = 0; i < st->nr_atoms; i++) {      
+        const struct st_tracked_state *atom = st->atoms[i];
+        struct st_state_flags generated;
+
+        assert(atom->dirty.mesa ||
+               atom->dirty.st);
+        assert(atom->update);
+
+        if (check_state(state, &atom->dirty)) {
+           st->atoms[i]->update( st );
+        }
+
+        accumulate_state(&examined, &atom->dirty);
+
+        /* generated = (prev ^ state)
+         * if (examined & generated)
+         *     fail;
+         */
+        xor_states(&generated, &prev, state);
+        assert(!check_state(&examined, &generated));
+        prev = *state;
+      }
+   }
+   else {
+      const GLuint nr = st->nr_atoms;
+
+      for (i = 0; i < nr; i++) {        
+        if (check_state(state, &st->atoms[i]->dirty))
+           st->atoms[i]->update( st );
+      }
+   }
+
+   memset(state, 0, sizeof(*state));
+}
+
+
+
diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h
new file mode 100644 (file)
index 0000000..1b70e27
--- /dev/null
@@ -0,0 +1,62 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+    
+
+#ifndef ST_ATOM_H
+#define ST_ATOM_H
+
+struct st_context;
+struct st_tracked_state;
+
+void st_init_atoms( struct st_context *st );
+void st_destroy_atoms( struct st_context *st );
+
+
+void st_validate_state( struct st_context *st );
+
+
+const struct st_tracked_state st_update_framebuffer;
+const struct st_tracked_state st_update_clip;
+const struct st_tracked_state st_update_clear_color;
+const struct st_tracked_state st_update_depth;
+const struct st_tracked_state st_update_fs;
+const struct st_tracked_state st_update_vs;
+const struct st_tracked_state st_update_setup;
+const struct st_tracked_state st_update_polygon_stipple;
+const struct st_tracked_state st_update_viewport;
+const struct st_tracked_state st_update_constants;
+const struct st_tracked_state st_update_scissor;
+const struct st_tracked_state st_update_blend;
+const struct st_tracked_state st_update_stencil;
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_atom_alphatest.c b/src/mesa/state_tracker/st_atom_alphatest.c
new file mode 100644 (file)
index 0000000..1e2e449
--- /dev/null
@@ -0,0 +1,94 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Convert GLenum stencil func tokens to pipe tokens.
+ */
+static GLuint
+gl_alpha_func_to_sp(GLenum func)
+{
+   /* Same values, just biased */
+   assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER);
+   assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER);
+   assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER);
+   assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER);
+   assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER);
+   assert(func >= GL_NEVER);
+   assert(func <= GL_ALWAYS);
+   return func - GL_NEVER;
+}
+
+
+static void 
+update_alpha_test( struct st_context *st )
+{
+   struct pipe_alpha_test_state alpha;
+
+   memset(&alpha, 0, sizeof(alpha));
+
+   if (st->ctx->Color.AlphaEnabled) {
+      alpha.enabled = 1;
+      alpha.func = gl_alpha_func_to_sp(st->ctx->Color.AlphaFunc);
+      alpha.ref = st->ctx->Color.AlphaRef;
+   }
+
+   if (memcmp(&alpha, &st->state.alpha_test, sizeof(alpha)) != 0) {
+      /* state has changed */
+      st->state.alpha_test = alpha;  /* struct copy */
+      st->pipe->set_alpha_test_state(st->pipe, &alpha); /* set new state */
+   }
+}
+
+
+const struct st_tracked_state st_update_alpha_test = {
+   .dirty = {
+      .mesa = (_NEW_COLOR),
+      .st  = 0,
+   },
+   .update = update_alpha_test
+};
+
+
+
+
+
diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c
new file mode 100644 (file)
index 0000000..256f134
--- /dev/null
@@ -0,0 +1,240 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Convert GLenum blend tokens to pipe tokens.
+ * Both blend factors and blend funcs are accepted.
+ */
+static GLuint
+gl_blend_to_sp(GLenum blend)
+{
+   switch (blend) {
+   /* blend functions */
+   case GL_FUNC_ADD:
+      return PIPE_BLEND_ADD;
+   case GL_FUNC_SUBTRACT:
+      return PIPE_BLEND_SUBTRACT;
+   case GL_FUNC_REVERSE_SUBTRACT:
+      return PIPE_BLEND_REVERSE_SUBTRACT;
+   case GL_MIN:
+      return PIPE_BLEND_MIN;
+   case GL_MAX:
+      return PIPE_BLEND_MAX;
+
+   /* blend factors */
+   case GL_ONE:
+      return PIPE_BLENDFACTOR_ONE;
+   case GL_SRC_COLOR:
+      return PIPE_BLENDFACTOR_SRC_COLOR;
+   case GL_SRC_ALPHA:
+      return PIPE_BLENDFACTOR_SRC_ALPHA;
+   case GL_DST_ALPHA:
+      return PIPE_BLENDFACTOR_DST_ALPHA;
+   case GL_DST_COLOR:
+      return PIPE_BLENDFACTOR_DST_COLOR;
+   case GL_SRC_ALPHA_SATURATE:
+      return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
+   case GL_CONSTANT_COLOR:
+      return PIPE_BLENDFACTOR_CONST_COLOR;
+   case GL_CONSTANT_ALPHA:
+      return PIPE_BLENDFACTOR_CONST_ALPHA;
+      /*
+      return PIPE_BLENDFACTOR_SRC1_COLOR;
+      return PIPE_BLENDFACTOR_SRC1_ALPHA;
+      */
+   case GL_ZERO:
+      return PIPE_BLENDFACTOR_ZERO;
+   case GL_ONE_MINUS_SRC_COLOR:
+      return PIPE_BLENDFACTOR_INV_SRC_COLOR;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+   case GL_ONE_MINUS_DST_COLOR:
+      return PIPE_BLENDFACTOR_INV_DST_ALPHA;
+   case GL_ONE_MINUS_DST_ALPHA:
+      return PIPE_BLENDFACTOR_INV_DST_COLOR;
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+      return PIPE_BLENDFACTOR_INV_CONST_COLOR;
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+      return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
+      /*
+      return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
+      return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
+      */
+   default:
+      assert("invalid GL token in gl_blend_to_sp()" == NULL);
+      return 0;
+   }
+}
+
+
+/**
+ * Convert GLenum logicop tokens to pipe tokens.
+ */
+static GLuint
+gl_logicop_to_sp(GLenum logicop)
+{
+   switch (logicop) {
+   case GL_CLEAR:
+      return PIPE_LOGICOP_CLEAR;
+   case GL_NOR:
+      return PIPE_LOGICOP_NOR;
+   case GL_AND_INVERTED:
+      return PIPE_LOGICOP_AND_INVERTED;
+   case GL_COPY_INVERTED:
+      return PIPE_LOGICOP_COPY_INVERTED;
+   case GL_AND_REVERSE:
+      return PIPE_LOGICOP_AND_REVERSE;
+   case GL_INVERT:
+      return PIPE_LOGICOP_INVERT;
+   case GL_XOR:
+      return PIPE_LOGICOP_XOR;
+   case GL_NAND:
+      return PIPE_LOGICOP_NAND;
+   case GL_AND:
+      return PIPE_LOGICOP_AND;
+   case GL_EQUIV:
+      return PIPE_LOGICOP_EQUIV;
+   case GL_NOOP:
+      return PIPE_LOGICOP_NOOP;
+   case GL_OR_INVERTED:
+      return PIPE_LOGICOP_OR_INVERTED;
+   case GL_COPY:
+      return PIPE_LOGICOP_COPY;
+   case GL_OR_REVERSE:
+      return PIPE_LOGICOP_OR_REVERSE;
+   case GL_OR:
+      return PIPE_LOGICOP_OR;
+   case GL_SET:
+      return PIPE_LOGICOP_SET;
+   default:
+      assert("invalid GL token in gl_logicop_to_sp()" == NULL);
+      return 0;
+   }
+}
+
+
+static void 
+update_blend( struct st_context *st )
+{
+   struct pipe_blend_state blend;
+
+   memset(&blend, 0, sizeof(blend));
+
+   if (st->ctx->Color.ColorLogicOpEnabled ||
+       (st->ctx->Color.BlendEnabled &&
+        st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) {
+      /* logicop enabled */
+      blend.logicop_enable = 1;
+      blend.logicop_func = gl_logicop_to_sp(st->ctx->Color.LogicOp);
+   }
+   else if (st->ctx->Color.BlendEnabled) {
+      /* blending enabled */
+      blend.blend_enable = 1;
+
+      blend.rgb_func = gl_blend_to_sp(st->ctx->Color.BlendEquationRGB);
+      if (st->ctx->Color.BlendEquationRGB == GL_MIN ||
+          st->ctx->Color.BlendEquationRGB == GL_MAX) {
+         /* Min/max are special */
+         blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+         blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+      }
+      else {
+         blend.rgb_src_factor = gl_blend_to_sp(st->ctx->Color.BlendSrcRGB);
+         blend.rgb_dst_factor = gl_blend_to_sp(st->ctx->Color.BlendDstRGB);
+      }
+
+      blend.alpha_func = gl_blend_to_sp(st->ctx->Color.BlendEquationA);
+      if (st->ctx->Color.BlendEquationA == GL_MIN ||
+          st->ctx->Color.BlendEquationA == GL_MAX) {
+         /* Min/max are special */
+         blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+         blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+      }
+      else {
+         blend.alpha_src_factor = gl_blend_to_sp(st->ctx->Color.BlendSrcA);
+         blend.alpha_dst_factor = gl_blend_to_sp(st->ctx->Color.BlendDstA);
+      }
+   }
+   else {
+      /* no blending / logicop */
+   }
+
+   /* Colormask - maybe reverse these bits? */
+   if (st->ctx->Color.ColorMask[0])
+      blend.colormask |= PIPE_MASK_R;
+   if (st->ctx->Color.ColorMask[1])
+      blend.colormask |= PIPE_MASK_G;
+   if (st->ctx->Color.ColorMask[2])
+      blend.colormask |= PIPE_MASK_B;
+   if (st->ctx->Color.ColorMask[3])
+      blend.colormask |= PIPE_MASK_A;
+
+   if (st->ctx->Color.DitherFlag)
+      blend.dither = 1;
+
+   if (memcmp(&blend, &st->state.blend, sizeof(blend)) != 0) {
+      /* state has changed */
+      st->state.blend = blend;  /* struct copy */
+      st->pipe->set_blend_state(st->pipe, &blend); /* set new state */
+   }
+
+   if (memcmp(st->ctx->Color.BlendColor, &st->state.blend_color, 4 * sizeof(GLfloat)) != 0) {
+      /* state has changed */
+      st->state.blend_color.color[0] = st->ctx->Color.BlendColor[0];
+      st->state.blend_color.color[1] = st->ctx->Color.BlendColor[1];
+      st->state.blend_color.color[2] = st->ctx->Color.BlendColor[2];
+      st->state.blend_color.color[3] = st->ctx->Color.BlendColor[3];
+      st->pipe->set_blend_color(st->pipe, (struct pipe_blend_color *) st->ctx->Color.BlendColor);
+   }
+}
+
+
+const struct st_tracked_state st_update_blend = {
+   .dirty = {
+      .mesa = (_NEW_COLOR),  /* XXX _NEW_BLEND someday? */
+      .st  = 0,
+   },
+   .update = update_blend
+};
+
+
+
+
+
diff --git a/src/mesa/state_tracker/st_atom_cbuf.c b/src/mesa/state_tracker/st_atom_cbuf.c
new file mode 100644 (file)
index 0000000..0f90aa7
--- /dev/null
@@ -0,0 +1,72 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+extern GLboolean xmesa_get_cbuf_details( GLcontext *ctx,
+                                        void **ptr,
+                                        GLuint *cpp,
+                                        GLint *stride,
+                                        GLuint *format );
+
+
+/* This is a hack to work with the X11 driver as a test harness
+ */
+static void update_cbuf_state( struct st_context *st )
+{
+   struct pipe_surface cbuf;
+   GLboolean ok;
+
+   ok = xmesa_get_cbuf_details( st->ctx,
+                               (void **)&cbuf.ptr,
+                               &cbuf.cpp,
+                               &cbuf.stride,
+                               &cbuf.format );
+
+   assert(ok);
+
+   if (memcmp(&cbuf, &st->state.cbuf, sizeof(cbuf)) != 0) {
+      st->state.cbuf = cbuf;
+      st->pipe->set_cbuf_state( st->pipe, &cbuf );
+   }
+}
+
+const struct st_tracked_state st_update_cbuf = {
+   .dirty = {
+      .mesa = _NEW_BUFFERS,
+      .st  = 0,
+   },
+   .update = update_cbuf_state
+};
+
diff --git a/src/mesa/state_tracker/st_atom_clear_color.c b/src/mesa/state_tracker/st_atom_clear_color.c
new file mode 100644 (file)
index 0000000..adf730c
--- /dev/null
@@ -0,0 +1,62 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+
+
+static void
+update_clear_color_state( struct st_context *st )
+{
+   struct pipe_clear_color_state clear;
+
+   clear.color[0] = st->ctx->Color.ClearColor[0];
+   clear.color[1] = st->ctx->Color.ClearColor[1];
+   clear.color[2] = st->ctx->Color.ClearColor[2];
+   clear.color[3] = st->ctx->Color.ClearColor[3];
+
+   if (memcmp(&clear, &st->state.clear_color, sizeof(clear)) != 0) {
+      st->state.clear_color = clear;
+      st->pipe->set_clear_color_state( st->pipe, &clear );
+   }
+}
+
+
+const struct st_tracked_state st_update_clear_color = {
+   .dirty = {
+      .mesa = _NEW_COLOR,
+      .st  = 0,
+   },
+   .update = update_clear_color_state
+};
diff --git a/src/mesa/state_tracker/st_atom_clip.c b/src/mesa/state_tracker/st_atom_clip.c
new file mode 100644 (file)
index 0000000..8ccad63
--- /dev/null
@@ -0,0 +1,75 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+/* Second state atom for user clip planes:
+ */
+static void update_clip( struct st_context *st )
+{
+   struct pipe_clip_state clip;
+   GLuint i;
+
+   memset(&clip, 0, sizeof(clip));
+
+   for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) {
+      if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) {
+        memcpy(clip.ucp[clip.nr], 
+               st->ctx->Transform._ClipUserPlane[i], 
+               sizeof(clip.ucp[0]));
+        clip.nr++;
+      }
+   }
+      
+   if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) {
+      st->state.clip = clip;
+      st->pipe->set_clip_state(st->pipe, &clip);
+   }
+}
+
+
+const struct st_tracked_state st_update_clip = {
+   .dirty = {
+      .mesa = (_NEW_TRANSFORM),
+      .st  = 0,
+   },
+   .update = update_clip
+};
+
+
+
+
+
diff --git a/src/mesa/state_tracker/st_atom_depth.c b/src/mesa/state_tracker/st_atom_depth.c
new file mode 100644 (file)
index 0000000..7fc5195
--- /dev/null
@@ -0,0 +1,92 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Convert GLenum depth func tokens to pipe tokens.
+ */
+static GLuint
+gl_depth_func_to_sp(GLenum func)
+{
+   /* Same values, just biased */
+   assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER);
+   assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER);
+   assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER);
+   assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER);
+   assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER);
+   assert(func >= GL_NEVER);
+   assert(func <= GL_ALWAYS);
+   return func - GL_NEVER;
+}
+
+
+static void 
+update_depth( struct st_context *st )
+{
+   struct pipe_depth_state depth;
+
+   memset(&depth, 0, sizeof(depth));
+
+   depth.enabled = st->ctx->Depth.Test;
+   depth.writemask = st->ctx->Depth.Mask;
+   depth.func = gl_depth_func_to_sp(st->ctx->Depth.Func);
+   depth.clear = st->ctx->Depth.Clear;
+
+   if (st->ctx->Query.CurrentOcclusionObject &&
+       st->ctx->Query.CurrentOcclusionObject->Active)
+      depth.occlusion_count = 1;
+
+   if (memcmp(&depth, &st->state.depth, sizeof(depth)) != 0) {
+      /* state has changed */
+      st->state.depth = depth;  /* struct copy */
+      st->pipe->set_depth_state(st->pipe, &depth); /* set new state */
+   }
+}
+
+
+const struct st_tracked_state st_update_depth = {
+   .dirty = {
+      .mesa = (_NEW_DEPTH),
+      .st  = 0,
+   },
+   .update = update_depth
+};
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
new file mode 100644 (file)
index 0000000..595f390
--- /dev/null
@@ -0,0 +1,89 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+
+
+extern struct pipe_surface *
+xmesa_get_color_surface(GLcontext *ctx, GLuint i);
+
+extern struct pipe_surface *
+xmesa_get_z_surface(GLcontext *ctx);
+
+extern struct pipe_surface *
+xmesa_get_stencil_surface(GLcontext *ctx);
+
+
+/**
+ * Update framebuffer state (color, depth, stencil, etc. buffers)
+ * XXX someday: separate draw/read buffers.
+ */
+static void
+update_framebuffer_state( struct st_context *st )
+{
+   struct pipe_framebuffer_state framebuffer;
+   GLuint i;
+
+   /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
+    * to determine which surfaces to draw to
+    */
+   framebuffer.num_cbufs = st->ctx->DrawBuffer->_NumColorDrawBuffers[0];
+   for (i = 0; i < framebuffer.num_cbufs; i++) {
+      framebuffer.cbufs[i] = xmesa_get_color_surface(st->ctx, i);
+   }
+
+   if (st->ctx->DrawBuffer->_DepthBuffer/*Attachment[BUFFER_DEPTH].Renderbuffer*/) {
+      framebuffer.zbuf = xmesa_get_z_surface(st->ctx);
+   }
+
+   if (st->ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) {
+      framebuffer.sbuf = xmesa_get_stencil_surface(st->ctx);
+   }
+
+   if (memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0) {
+      st->state.framebuffer = framebuffer;
+      st->pipe->set_framebuffer_state( st->pipe, &framebuffer );
+   }
+}
+
+
+const struct st_tracked_state st_update_framebuffer = {
+   .dirty = {
+      .mesa = _NEW_BUFFERS,
+      .st  = 0,
+   },
+   .update = update_framebuffer_state
+};
+
diff --git a/src/mesa/state_tracker/st_atom_fs.c b/src/mesa/state_tracker/st_atom_fs.c
new file mode 100644 (file)
index 0000000..9ca1807
--- /dev/null
@@ -0,0 +1,102 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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.
+ * 
+ **************************************************************************/
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+                   
+#include "shader/prog_parameter.h"
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+#include "st_program.h"
+#include "pipe/tgsi/mesa/mesa_to_tgsi.h"
+#include "pipe/tgsi/core/tgsi_dump.h"
+
+static void compile_fs( struct st_context *st,
+                       struct st_fragment_program *fs )
+{
+   /* XXX: fix static allocation of tokens:
+    */
+   tgsi_mesa_compile_fp_program( &fs->Base, fs->tokens, ST_FP_MAX_TOKENS );
+
+   tgsi_dump( fs->tokens, TGSI_DUMP_VERBOSE );
+}
+
+
+static void update_fs( struct st_context *st )
+{
+   struct pipe_fs_state fs;
+   struct st_fragment_program *fp = NULL;
+   struct gl_program_parameter_list *params = NULL;
+
+   if (st->ctx->Shader.CurrentProgram &&
+       st->ctx->Shader.CurrentProgram->LinkStatus &&
+       st->ctx->Shader.CurrentProgram->FragmentProgram) {
+      struct gl_fragment_program *f
+         = st->ctx->Shader.CurrentProgram->FragmentProgram;
+      fp = st_fragment_program(f);
+      params = f->Base.Parameters;
+   }
+   else if (st->ctx->FragmentProgram._Current) {
+      fp = st_fragment_program(st->ctx->FragmentProgram._Current);
+      params = st->ctx->FragmentProgram._Current->Base.Parameters;
+   }
+
+   if (fp && params) {
+      /* load program's constants array */
+      fp->constants.nr_constants = params->NumParameters;
+      memcpy(fp->constants.constant, 
+             params->ParameterValues,
+             params->NumParameters * sizeof(GLfloat) * 4);
+   }
+
+   if (fp->dirty)
+      compile_fs( st, fp );
+
+   memset( &fs, 0, sizeof(fs) );
+   fs.inputs_read = fp->Base.Base.InputsRead;
+   fs.tokens = &fp->tokens[0];
+   fs.constants = &fp->constants;
+   
+   if (memcmp(&fs, &st->state.fs, sizeof(fs)) != 0 ||
+       fp->dirty) 
+   {
+      fp->dirty = 0;
+      st->state.fs = fs;
+      st->pipe->set_fs_state(st->pipe, &fs);
+   }
+}
+
+
+const struct st_tracked_state st_update_fs = {
+   .dirty = {
+      .mesa  = _NEW_PROGRAM,
+      .st   = ST_NEW_FRAGMENT_PROGRAM,
+   },
+   .update = update_fs
+};
diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c
new file mode 100644 (file)
index 0000000..1aa9da8
--- /dev/null
@@ -0,0 +1,135 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Convert GLenum texcoord wrap tokens to pipe tokens.
+ */
+static GLuint
+gl_wrap_to_sp(GLenum wrap)
+{
+   switch (wrap) {
+   case GL_REPEAT:
+      return PIPE_TEX_WRAP_REPEAT;
+   case GL_CLAMP:
+      return PIPE_TEX_WRAP_CLAMP;
+   case GL_CLAMP_TO_EDGE:
+      return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+   case GL_CLAMP_TO_BORDER:
+      return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+   case GL_MIRRORED_REPEAT:
+      return PIPE_TEX_WRAP_MIRROR_REPEAT;
+   case GL_MIRROR_CLAMP_EXT:
+      return PIPE_TEX_WRAP_MIRROR_CLAMP;
+   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
+      return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
+      return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER;
+   default:
+      abort();
+      return 0;
+   }
+}
+
+
+static GLuint
+gl_filter_to_sp(GLenum filter)
+{
+   switch (filter) {
+   case GL_NEAREST:
+      return PIPE_TEX_FILTER_NEAREST;
+   case GL_LINEAR:
+      return PIPE_TEX_FILTER_LINEAR;
+   case GL_NEAREST_MIPMAP_NEAREST:
+      return PIPE_TEX_FILTER_NEAREST_MIPMAP_NEAREST;
+   case GL_NEAREST_MIPMAP_LINEAR:
+      return PIPE_TEX_FILTER_NEAREST_MIPMAP_LINEAR;
+   case GL_LINEAR_MIPMAP_NEAREST:
+      return PIPE_TEX_FILTER_LINEAR_MIPMAP_NEAREST;
+   case GL_LINEAR_MIPMAP_LINEAR:
+      return PIPE_TEX_FILTER_LINEAR_MIPMAP_LINEAR;
+   default:
+      abort();
+      return 0;
+   }
+}
+
+
+static void 
+update_samplers(struct st_context *st)
+{
+   GLuint u;
+
+   for (u = 0; u < st->ctx->Const.MaxTextureImageUnits; u++) {
+      const struct gl_texture_object *texobj
+         = st->ctx->Texture.Unit[u]._Current;
+      struct pipe_sampler_state sampler;
+
+      memset(&sampler, 0, sizeof(sampler));
+
+      sampler.wrap_s = gl_wrap_to_sp(texobj->WrapS);
+      sampler.wrap_t = gl_wrap_to_sp(texobj->WrapT);
+      sampler.wrap_r = gl_wrap_to_sp(texobj->WrapR);
+
+      sampler.min_filter = gl_filter_to_sp(texobj->MinFilter);
+      sampler.mag_filter = gl_filter_to_sp(texobj->MagFilter);
+
+      /* XXX more sampler state here */
+
+      if (memcmp(&sampler, &st->state.sampler[u], sizeof(sampler)) != 0) {
+         /* state has changed */
+         st->state.sampler[u] = sampler;
+         st->pipe->set_sampler_state(st->pipe, u, &sampler);
+      }
+   }
+}
+
+
+const struct st_tracked_state st_update_sampler = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .st  = 0,
+   },
+   .update = update_samplers
+};
+
+
+
+
+
diff --git a/src/mesa/state_tracker/st_atom_scissor.c b/src/mesa/state_tracker/st_atom_scissor.c
new file mode 100644 (file)
index 0000000..05a9f3e
--- /dev/null
@@ -0,0 +1,88 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+/**
+ * Scissor depends on the scissor box, and the framebuffer dimensions.
+ */
+static void
+update_scissor( struct st_context *st )
+{
+   struct pipe_scissor_state scissor;
+   const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+
+   scissor.minx = 0;
+   scissor.miny = 0;
+   scissor.maxx = fb->Width;
+   scissor.maxy = fb->Height;
+
+   if (st->ctx->Scissor.Enabled) {
+      if (st->ctx->Scissor.X > scissor.minx)
+         scissor.minx = st->ctx->Scissor.X;
+      if (st->ctx->Scissor.Y > scissor.miny)
+         scissor.miny = st->ctx->Scissor.Y;
+
+      if (st->ctx->Scissor.X + st->ctx->Scissor.Width < scissor.maxx)
+         scissor.maxx = st->ctx->Scissor.X + st->ctx->Scissor.Width;
+      if (st->ctx->Scissor.Y + st->ctx->Scissor.Height < scissor.maxy)
+         scissor.maxy = st->ctx->Scissor.Y + st->ctx->Scissor.Height;
+
+      /* check for null space */
+      if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy)
+         scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0;
+   }
+
+   if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) {
+      /* state has changed */
+      st->state.scissor = scissor;  /* struct copy */
+      st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */
+   }
+}
+
+
+const struct st_tracked_state st_update_scissor = {
+   .dirty = {
+      .mesa = (_NEW_SCISSOR | _NEW_BUFFERS),
+      .st  = 0,
+   },
+   .update = update_scissor
+};
+
+
+
+
+
diff --git a/src/mesa/state_tracker/st_atom_setup.c b/src/mesa/state_tracker/st_atom_setup.c
new file mode 100644 (file)
index 0000000..6ee96f6
--- /dev/null
@@ -0,0 +1,216 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "st_atom.h"
+
+static GLuint translate_fill( GLenum mode )
+{
+   switch (mode) {
+   case GL_POINT:
+      return PIPE_POLYGON_MODE_POINT;
+   case GL_LINE:
+      return PIPE_POLYGON_MODE_LINE;
+   case GL_FILL:
+      return PIPE_POLYGON_MODE_FILL;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+static GLboolean get_offset_flag( GLuint fill_mode, 
+                                 const struct gl_polygon_attrib *p )
+{
+   switch (fill_mode) {
+   case PIPE_POLYGON_MODE_POINT:
+      return p->OffsetPoint;
+   case PIPE_POLYGON_MODE_LINE:
+      return p->OffsetLine;
+   case PIPE_POLYGON_MODE_FILL:
+      return p->OffsetFill;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+
+static void update_setup_state( struct st_context *st )
+{
+   GLcontext *ctx = st->ctx;
+   struct pipe_setup_state setup;
+
+   memset(&setup, 0, sizeof(setup));
+   
+   /* _NEW_POLYGON, _NEW_BUFFERS
+    */
+   {
+      if (ctx->Polygon.FrontFace == GL_CCW)
+         setup.front_winding = PIPE_WINDING_CCW;
+      else
+         setup.front_winding = PIPE_WINDING_CW;
+
+      /* XXX
+       * I think the intention here is that user-created framebuffer objects
+       * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout.
+       * Flipping Y changes CW to CCW and vice-versa.
+       * But this is an implementation/driver-specific artifact - remove...
+       */
+      if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
+         setup.front_winding ^= PIPE_WINDING_BOTH;
+   }
+
+   /* _NEW_LIGHT
+    */
+   if (ctx->Light.ShadeModel == GL_FLAT)
+      setup.flatshade = 1;
+
+   /* _NEW_LIGHT | _NEW_PROGRAM
+    *
+    * Back-face colors can come from traditional lighting (when
+    * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs (when
+    * GL_VERTEX_PROGRAM_TWO_SIDE is set).  Note the logic here.
+    */
+   if (ctx->VertexProgram._Enabled) {
+      setup.light_twoside = ctx->VertexProgram.TwoSideEnabled;
+   }
+   else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+      setup.light_twoside = 1;
+   }
+
+   /* _NEW_POLYGON
+    */
+   if (ctx->Polygon.CullFlag) {
+      if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
+        setup.cull_mode = PIPE_WINDING_BOTH;
+      }
+      else if (ctx->Polygon.CullFaceMode == GL_FRONT) {
+        setup.cull_mode = setup.front_winding;
+      }
+      else {
+        setup.cull_mode = setup.front_winding ^ PIPE_WINDING_BOTH;
+      }
+   }
+
+   /* _NEW_POLYGON
+    */
+   {
+      GLuint fill_front = translate_fill( ctx->Polygon.FrontMode );
+      GLuint fill_back = translate_fill( ctx->Polygon.BackMode );
+      
+      if (setup.front_winding == PIPE_WINDING_CW) {
+        setup.fill_cw = fill_front;
+        setup.fill_ccw = fill_back;
+      }
+      else {
+        setup.fill_cw = fill_back;
+        setup.fill_ccw = fill_front;
+      }
+
+      /* Simplify when culling is active:
+       */
+      if (setup.cull_mode & PIPE_WINDING_CW) {
+        setup.fill_cw = setup.fill_ccw;
+      }
+      
+      if (setup.cull_mode & PIPE_WINDING_CCW) {
+        setup.fill_ccw = setup.fill_cw;
+      }
+   }
+
+   /* _NEW_POLYGON 
+    */
+   if (ctx->Polygon.OffsetUnits != 0.0 ||
+       ctx->Polygon.OffsetFactor != 0.0) {
+      setup.offset_cw = get_offset_flag( setup.fill_cw, &ctx->Polygon );
+      setup.offset_ccw = get_offset_flag( setup.fill_ccw, &ctx->Polygon );
+      setup.offset_units = ctx->Polygon.OffsetUnits;
+      setup.offset_scale = ctx->Polygon.OffsetFactor;
+   }
+
+   if (ctx->Polygon.SmoothFlag)
+      setup.poly_smooth = 1;
+
+   if (ctx->Polygon.StippleFlag)
+      setup.poly_stipple_enable = 1;
+
+
+   /* _NEW_BUFFERS, _NEW_POLYGON
+    */
+   if (setup.fill_cw != PIPE_POLYGON_MODE_FILL ||
+       setup.fill_ccw != PIPE_POLYGON_MODE_FILL)
+   {
+      GLfloat mrd = (ctx->DrawBuffer ? 
+                    ctx->DrawBuffer->_MRD : 
+                    1.0);
+
+      setup.offset_units = ctx->Polygon.OffsetFactor * mrd;
+      setup.offset_scale = (ctx->Polygon.OffsetUnits * mrd *
+                           st->polygon_offset_scale);
+   }
+      
+   /* _NEW_POINT
+    */
+   setup.point_size = ctx->Point.Size;
+   setup.point_smooth = ctx->Point.SmoothFlag;
+
+   /* _NEW_LINE
+    */
+   setup.line_width = ctx->Line.Width;
+   setup.line_smooth = ctx->Line.SmoothFlag;
+   setup.line_stipple_enable = ctx->Line.StippleFlag;
+   setup.line_stipple_pattern = ctx->Line.StipplePattern;
+   /* GL stipple factor is in [1,256], remap to [0, 255] here */
+   setup.line_stipple_factor = ctx->Line.StippleFactor - 1;
+
+   /* _NEW_MULTISAMPLE */
+   if (ctx->Multisample.Enabled)
+      setup.multisample = 1;
+
+   if (memcmp(&setup, &st->state.setup, sizeof(setup)) != 0) {
+      st->state.setup = setup;
+      st->pipe->set_setup_state( st->pipe, &setup );
+   }
+}
+
+const struct st_tracked_state st_update_setup = {
+   .dirty = {
+      .mesa = (_NEW_LIGHT | _NEW_POLYGON | _NEW_LINE |
+               _NEW_POINT | _NEW_BUFFERS | _NEW_MULTISAMPLE),
+      .st  = 0,
+   },
+   .update = update_setup_state
+};
diff --git a/src/mesa/state_tracker/st_atom_stencil.c b/src/mesa/state_tracker/st_atom_stencil.c
new file mode 100644 (file)
index 0000000..d037335
--- /dev/null
@@ -0,0 +1,140 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Brian Paul
+  */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Convert GLenum stencil func tokens to pipe tokens.
+ */
+static GLuint
+gl_stencil_func_to_sp(GLenum func)
+{
+   /* Same values, just biased */
+   assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER);
+   assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER);
+   assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER);
+   assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER);
+   assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER);
+   assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER);
+   assert(func >= GL_NEVER);
+   assert(func <= GL_ALWAYS);
+   return func - GL_NEVER;
+}
+
+
+/**
+ * Convert GLenum stencil op tokens to pipe tokens.
+ */
+static GLuint
+gl_stencil_op_to_sp(GLenum func)
+{
+   switch (func) {
+   case GL_KEEP:
+      return PIPE_STENCIL_OP_KEEP;
+   case GL_ZERO:
+      return PIPE_STENCIL_OP_ZERO;
+   case GL_REPLACE:
+      return PIPE_STENCIL_OP_REPLACE;
+   case GL_INCR:
+      return PIPE_STENCIL_OP_INCR;
+   case GL_DECR:
+      return PIPE_STENCIL_OP_DECR;
+   case GL_INCR_WRAP:
+      return PIPE_STENCIL_OP_INCR_WRAP;
+   case GL_DECR_WRAP:
+      return PIPE_STENCIL_OP_DECR_WRAP;
+   case GL_INVERT:
+      return PIPE_STENCIL_OP_INVERT;
+   default:
+      assert("invalid GL token in gl_stencil_op_to_sp()" == NULL);
+      return 0;
+   }
+}
+
+
+static void 
+update_stencil( struct st_context *st )
+{
+   struct pipe_stencil_state stencil;
+
+   memset(&stencil, 0, sizeof(stencil));
+
+   if (st->ctx->Stencil.Enabled) {
+      stencil.front_enabled = 1;
+      stencil.front_func = gl_stencil_func_to_sp(st->ctx->Stencil.Function[0]);
+      stencil.front_fail_op = gl_stencil_op_to_sp(st->ctx->Stencil.FailFunc[0]);
+      stencil.front_zfail_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZFailFunc[0]);
+      stencil.front_zpass_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZPassFunc[0]);
+      stencil.ref_value[0] = st->ctx->Stencil.Ref[0] & 0xff;
+      stencil.value_mask[0] = st->ctx->Stencil.ValueMask[0] & 0xff;
+      stencil.write_mask[0] = st->ctx->Stencil.WriteMask[0] & 0xff;
+      if (st->ctx->Stencil.TestTwoSide) {
+         stencil.back_enabled = 1;
+         stencil.back_func = gl_stencil_func_to_sp(st->ctx->Stencil.Function[1]);
+         stencil.back_fail_op = gl_stencil_op_to_sp(st->ctx->Stencil.FailFunc[1]);
+         stencil.back_zfail_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZFailFunc[1]);
+         stencil.back_zpass_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZPassFunc[1]);
+         stencil.ref_value[1] = st->ctx->Stencil.Ref[1] & 0xff;
+         stencil.value_mask[1] = st->ctx->Stencil.ValueMask[1] & 0xff;
+         stencil.write_mask[1] = st->ctx->Stencil.WriteMask[1] & 0xff;
+      }
+      stencil.clear_value = st->ctx->Stencil.Clear & 0xff;
+   }
+
+   if (memcmp(&stencil, &st->state.stencil, sizeof(stencil)) != 0) {
+      /* state has changed */
+      st->state.stencil = stencil;  /* struct copy */
+      st->pipe->set_stencil_state(st->pipe, &stencil); /* set new state */
+   }
+}
+
+
+const struct st_tracked_state st_update_stencil = {
+   .dirty = {
+      .mesa = (_NEW_STENCIL),
+      .st  = 0,
+   },
+   .update = update_stencil
+};
+
+
+
+
+
diff --git a/src/mesa/state_tracker/st_atom_stipple.c b/src/mesa/state_tracker/st_atom_stipple.c
new file mode 100644 (file)
index 0000000..dd04d21
--- /dev/null
@@ -0,0 +1,62 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * \brief polygon stipple state
+  *
+  * Authors:
+  *   Brian Paul
+  */
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+
+
+static void 
+update_stipple( struct st_context *st )
+{
+   const GLuint sz = sizeof(st->state.poly_stipple.stipple);
+   assert(sz == sizeof(st->ctx->PolygonStipple));
+
+   if (memcmp(&st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz)) {
+      /* state has changed */
+      memcpy(st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz);
+      st->pipe->set_polygon_stipple(st->pipe, &st->state.poly_stipple);
+   }
+}
+
+
+const struct st_tracked_state st_update_polygon_stipple = {
+   .dirty = {
+      .mesa = (_NEW_POLYGONSTIPPLE),
+      .st  = 0,
+   },
+   .update = update_stipple
+};
diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c
new file mode 100644 (file)
index 0000000..ac91f62
--- /dev/null
@@ -0,0 +1,117 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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 "context.h"
+#include "colormac.h"
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+
+
+
+/**
+ * Update the viewport transformation matrix.  Depends on:
+ *  - viewport pos/size
+ *  - depthrange
+ *  - window pos/size or FBO size
+ */
+static void update_viewport( struct st_context *st )
+{
+   GLcontext *ctx = st->ctx;
+   const GLframebuffer *DrawBuffer = ctx->DrawBuffer;
+   GLfloat yScale = 1.0;
+   GLfloat yBias = 0.0;
+
+   /* _NEW_BUFFERS
+    */
+   if (DrawBuffer) {
+
+#if 0
+      if (DrawBuffer->Name) {
+        /* User created FBO */
+        struct st_renderbuffer *irb
+           = st_renderbuffer(DrawBuffer->_ColorDrawBuffers[0][0]);
+        if (irb && !irb->RenderToTexture) {
+           /* y=0=top */
+           yScale = -1.0;
+           yBias = irb->Base.Height;
+        }
+        else {
+           /* y=0=bottom */
+           yScale = 1.0;
+           yBias = 0.0;
+        }
+      }
+      else 
+      {
+        /* window buffer, y=0=top */
+        yScale = -1.0;
+        yBias = DrawBuffer->Height;
+      }
+#endif
+   }
+
+   {
+      /* _NEW_VIEWPORT 
+       */
+      GLfloat x = ctx->Viewport.X;
+      GLfloat y = ctx->Viewport.Y;
+      GLfloat z = ctx->Viewport.Near;
+      GLfloat half_width = ctx->Viewport.Width / 2.0;
+      GLfloat half_height = ctx->Viewport.Height / 2.0;
+      GLfloat half_depth = (ctx->Viewport.Far - ctx->Viewport.Near) / 2.0;
+
+      struct pipe_viewport_state vp;
+      
+      vp.scale[0] = half_width;
+      vp.scale[1] = half_height * yScale;
+      vp.scale[2] = half_depth;
+      vp.scale[3] = 1.0;
+
+      vp.translate[0] = (half_width + x);
+      vp.translate[1] = (half_height + y) * yScale + yBias;
+      vp.translate[2] = (half_depth + z);
+      vp.translate[3] = 0.0;
+
+      if (memcmp(&vp, &st->state.viewport, sizeof(vp)) != 0) {
+        st->state.viewport = vp;
+        st->pipe->set_viewport_state(st->pipe, &vp);
+      }
+   }
+}
+
+
+const struct st_tracked_state st_update_viewport = {
+   .dirty = {
+      .mesa = _NEW_BUFFERS | _NEW_VIEWPORT,
+      .st = 0,
+   },
+   .update = update_viewport
+};
diff --git a/src/mesa/state_tracker/st_atom_vs.c b/src/mesa/state_tracker/st_atom_vs.c
new file mode 100644 (file)
index 0000000..6a26bfd
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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.
+ * 
+ **************************************************************************/
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+                   
+#include "st_context.h"
+#include "pipe/p_context.h"
+#include "st_atom.h"
+
+
+static void update_vs( struct st_context *st )
+{
+}
+
+
+const struct st_tracked_state st_update_vs = {
+   .dirty = {
+      .mesa  = 0,
+      .st   = ST_NEW_VERTEX_PROGRAM,
+   },
+   .update = update_vs
+};
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
new file mode 100644 (file)
index 0000000..fa9eaf4
--- /dev/null
@@ -0,0 +1,168 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "st_context.h"
+#include "st_program.h"    
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "program.h"
+#include "programopt.h"
+#include "tnl/tnl.h"
+#include "pipe/tgsi/mesa/tgsi_mesa.h"
+
+
+static void st_bind_program( GLcontext *ctx,
+                            GLenum target, 
+                            struct gl_program *prog )
+{
+   struct st_context *st = st_context(ctx);
+
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB: 
+      st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+      break;
+   case GL_FRAGMENT_PROGRAM_ARB:
+      st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+      break;
+   }
+}
+
+static struct gl_program *st_new_program( GLcontext *ctx,
+                                         GLenum target, 
+                                         GLuint id )
+{
+   struct st_context *st = st_context(ctx);
+
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB: {
+      struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program);
+
+      prog->id = st->program_id++;
+      prog->dirty = 1;
+
+      return _mesa_init_vertex_program( ctx, 
+                                       &prog->Base,
+                                       target, 
+                                       id );
+   }
+
+   case GL_FRAGMENT_PROGRAM_ARB:
+   case GL_FRAGMENT_PROGRAM_NV:
+   {
+      struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program);
+
+      prog->id = st->program_id++;
+      prog->dirty = 1;
+
+      return _mesa_init_fragment_program( ctx, 
+                                         &prog->Base,
+                                         target, 
+                                         id );
+   }
+
+   default:
+      return _mesa_new_program(ctx, target, id);
+   }
+}
+
+static void st_delete_program( GLcontext *ctx,
+                              struct gl_program *prog )
+{
+   _mesa_delete_program( ctx, prog );
+}
+
+
+static GLboolean st_is_program_native( GLcontext *ctx,
+                                      GLenum target, 
+                                      struct gl_program *prog )
+{
+   return GL_TRUE;
+}
+
+static void st_program_string_notify( GLcontext *ctx,
+                                     GLenum target,
+                                     struct gl_program *prog )
+{
+   struct st_context *st = st_context(ctx);
+
+   if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      struct st_fragment_program *p = (struct st_fragment_program *)prog;
+
+      if (prog == &ctx->FragmentProgram._Current->Base)
+        st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+
+      p->id = st->program_id++;      
+      p->param_state = p->Base.Base.Parameters->StateFlags;
+   }
+   else if (target == GL_VERTEX_PROGRAM_ARB) {
+      struct st_vertex_program *p = (struct st_vertex_program *)prog;
+
+      if (prog == &ctx->VertexProgram._Current->Base)
+        st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+
+      p->id = st->program_id++;      
+      p->param_state = p->Base.Base.Parameters->StateFlags;
+
+      /* Also tell tnl about it:
+       */
+      _tnl_program_string(ctx, target, prog);
+   }
+}
+
+
+
+void st_init_cb_program( struct st_context *st )
+{
+   struct dd_function_table *functions = &st->ctx->Driver;
+
+   /* Need these flags:
+    */
+   st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
+   st->ctx->FragmentProgram._UseTexEnvProgram = GL_TRUE;
+
+   assert(functions->ProgramStringNotify == _tnl_program_string); 
+   functions->BindProgram = st_bind_program;
+   functions->NewProgram = st_new_program;
+   functions->DeleteProgram = st_delete_program;
+   functions->IsProgramNative = st_is_program_native;
+   functions->ProgramStringNotify = st_program_string_notify;
+}
+
+
+void st_destroy_cb_program( struct st_context *st )
+{
+}
+
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
new file mode 100644 (file)
index 0000000..6308e81
--- /dev/null
@@ -0,0 +1,76 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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 "imports.h"
+#include "st_public.h"
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "st_program.h"
+#include "pipe/p_context.h"
+
+void st_invalidate_state(GLcontext * ctx, GLuint new_state)
+{
+   struct st_context *st = st_context(ctx);
+
+   st->dirty.mesa |= new_state;
+   st->dirty.st |= ST_NEW_MESA;
+}
+
+
+struct st_context *st_create_context( GLcontext *ctx,
+                                     struct pipe_context *pipe )
+{
+   struct st_context *st = CALLOC_STRUCT( st_context );
+   
+   ctx->st = st;
+
+   st->ctx = ctx;
+   st->pipe = pipe;
+
+   st->dirty.mesa = ~0;
+   st->dirty.st = ~0;
+
+   st_init_atoms( st );
+   st_init_draw( st );
+   st_init_cb_program( st );
+
+   return st;
+}
+
+
+void st_destroy_context( struct st_context *st )
+{
+   st_destroy_atoms( st );
+   st_destroy_draw( st );
+   st_destroy_cb_program( st );
+   st->pipe->destroy( st->pipe );
+   FREE( st );
+}
+
+
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
new file mode 100644 (file)
index 0000000..ef3cdb3
--- /dev/null
@@ -0,0 +1,116 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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_CONTEXT_H
+#define ST_CONTEXT_H
+
+#include "mtypes.h"
+#include "pipe/p_state.h"
+
+
+struct st_context;
+struct st_region;
+struct st_texture_object;
+struct st_texture_image;
+struct st_fragment_program;
+
+#define ST_NEW_MESA                    0x1 /* Mesa state has changed */
+#define ST_NEW_FRAGMENT_PROGRAM        0x2
+#define ST_NEW_VERTEX_PROGRAM          0x4
+
+struct st_state_flags {
+   GLuint mesa;
+   GLuint st;
+};
+
+struct st_tracked_state {
+   struct st_state_flags dirty;
+   void (*update)( struct st_context *st );
+};
+
+
+
+
+struct st_context
+{
+   GLcontext *ctx;
+
+   struct pipe_context *pipe;
+
+   /* Eventually will use a cache to feed the pipe with
+    * create/bind/delete calls to constant state objects.  Not yet
+    * though, we just shove random objects across the interface.  
+    */
+   struct {
+      struct pipe_alpha_test_state  alpha_test;
+      struct pipe_blend_state  blend;
+      struct pipe_blend_color  blend_color;
+      struct pipe_clear_color_state clear_color;
+      struct pipe_clip_state clip;
+      struct pipe_depth_state depth;
+      struct pipe_framebuffer_state framebuffer;
+      struct pipe_fs_state     fs;
+      struct pipe_poly_stipple poly_stipple;
+      struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
+      struct pipe_scissor_state scissor;
+      struct pipe_setup_state  setup;
+      struct pipe_stencil_state stencil;
+      struct pipe_viewport_state viewport;
+   } state;
+
+   struct {
+      struct st_tracked_state tracked_state;
+   } constants;
+
+   struct {
+      struct gl_fragment_program *fragment_program;
+   } cb;
+
+   /* State to be validated:
+    */
+   struct st_tracked_state **atoms;
+   GLuint nr_atoms;
+
+   struct st_state_flags dirty;
+
+   /* Counter to track program string changes:
+    */
+   GLuint program_id;
+
+   GLfloat polygon_offset_scale; /* ?? */
+};
+
+
+/* Need this so that we can implement Mesa callbacks in this module.
+ */
+static INLINE struct st_context *st_context(GLcontext *ctx)
+{
+   return ctx->st;
+}
+
+
+#endif
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
new file mode 100644 (file)
index 0000000..a424d1d
--- /dev/null
@@ -0,0 +1,120 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+
+#include "imports.h"
+
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "st_context.h"
+#include "st_atom.h"
+#include "st_draw.h"
+#include "pipe/p_context.h"
+
+/*
+ * TNL stage which feeds into the above.
+ *
+ * XXX: this needs to go into each driver using this code, because we
+ * cannot make the leap from ctx->draw_context in this file.  The
+ * driver needs to customize tnl anyway, so this isn't a big deal.
+ */
+static GLboolean draw( GLcontext * ctx, struct tnl_pipeline_stage *stage )
+{
+   struct st_context *st = st_context(ctx);
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   /* Validate driver and pipe state:
+    */
+   st_validate_state( st );
+
+   /* Call into the new draw code to handle the VB:
+    */
+   st->pipe->draw_vb( st->pipe, VB );
+   
+   /* Finished 
+    */
+   return GL_FALSE;
+}
+
+const struct tnl_pipeline_stage st_draw = {
+   "check state and draw",
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   draw
+};
+
+static const struct tnl_pipeline_stage *st_pipeline[] = {
+   &_tnl_vertex_transform_stage,
+   &_tnl_vertex_cull_stage,
+   &_tnl_normal_transform_stage,
+   &_tnl_lighting_stage,
+   &_tnl_fog_coordinate_stage,
+   &_tnl_texgen_stage,
+   &_tnl_texture_transform_stage,
+   &_tnl_point_attenuation_stage,
+   &_tnl_vertex_program_stage,
+   &st_draw,     /* ADD: escape to pipe */
+   0,
+};
+
+/* This is all a hack to keep using tnl until we have vertex programs
+ * up and running.
+ */
+void st_init_draw( struct st_context *st )
+{
+   GLcontext *ctx = st->ctx;
+
+   _tnl_destroy_pipeline( ctx );
+   _tnl_install_pipeline( ctx, st_pipeline );
+}
+
+
+void st_destroy_draw( struct st_context *st )
+{
+   /* Nothing to do. 
+    */
+}
+
+
+/** XXX temporary here */
+void
+st_clear(struct st_context *st, GLboolean color, GLboolean depth,
+         GLboolean stencil, GLboolean accum)
+{
+   /* This makes sure the softpipe has the latest scissor, etc values */
+   st_validate_state( st );
+
+   st->pipe->clear(st->pipe, color, depth, stencil, accum);
+}
+
diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h
new file mode 100644 (file)
index 0000000..7a3ba52
--- /dev/null
@@ -0,0 +1,44 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+    
+
+#ifndef ST_DRAW_H
+#define ST_DRAW_H
+
+void st_init_draw( struct st_context *st );
+void st_destroy_draw( struct st_context *st );
+
+/** XXX temporary here */
+void st_clear(struct st_context *st, GLboolean color, GLboolean depth,
+              GLboolean stencil, GLboolean accum);
+
+#endif
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
new file mode 100644 (file)
index 0000000..f6d5f6d
--- /dev/null
@@ -0,0 +1,105 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 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.
+ * 
+ **************************************************************************/
+
+ /*
+  * Authors:
+  *   Keith Whitwell <keith@tungstengraphics.com>
+  */
+    
+
+#ifndef ST_PROGRAM_H
+#define ST_PROGRAM_H
+
+#include "mtypes.h"
+#include "pipe/tgsi/core/tgsi_token.h"
+
+#define ST_FP_MAX_TOKENS 1024
+
+
+struct st_fragment_program
+{
+   struct gl_fragment_program Base;
+   GLboolean error;             /* If program is malformed for any reason. */
+
+   GLuint    id;               /* String id, for tracking
+                                * ProgramStringNotify changes.
+                                */
+
+
+   struct tgsi_token tokens[ST_FP_MAX_TOKENS];
+   GLboolean dirty;
+   
+   struct pipe_constant_buffer constants;
+
+#if 0   
+   GLfloat (*cbuffer)[4];
+   GLuint nr_constants;
+
+   /* Translate all the parameters, etc, into a constant buffer which
+    * we update on state changes.
+    */
+   struct
+   {
+      GLuint reg;               /* Constant idx */
+      const GLfloat *values;    /* Pointer to tracked values */
+   } *param;
+   GLuint nr_params;
+#endif
+
+   GLuint param_state;
+};
+
+
+struct st_vertex_program
+{
+   struct gl_vertex_program Base;
+   GLboolean error;             /* If program is malformed for any reason. */
+
+   GLuint    id;               /* String id, for tracking
+                                * ProgramStringNotify changes.
+                                */
+
+   GLboolean dirty;
+   GLuint param_state;
+};
+
+void st_init_cb_program( struct st_context *st );
+void st_destroy_cb_program( struct st_context *st );
+
+static inline struct st_fragment_program *
+st_fragment_program( struct gl_fragment_program *fp )
+{
+   return (struct st_fragment_program *)fp;
+}
+
+static inline struct st_vertex_program *
+st_vertex_program( struct gl_vertex_program *vp )
+{
+   return (struct st_vertex_program *)vp;
+}
+
+#endif
diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h
new file mode 100644 (file)
index 0000000..3191549
--- /dev/null
@@ -0,0 +1,43 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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_PUBLIC_H
+#define ST_PUBLIC_H
+
+#include "mtypes.h"
+
+struct st_context;
+struct pipe_context;
+
+struct st_context *st_create_context( GLcontext *ctx,
+                                     struct pipe_context *pipe);
+
+void st_destroy_context( struct st_context *st );
+
+void st_invalidate_state(GLcontext * ctx, GLuint new_state);
+
+#endif
diff --git a/src/mesa/state_tracker/st_texobj.c b/src/mesa/state_tracker/st_texobj.c
new file mode 100644 (file)
index 0000000..eb5bdb2
--- /dev/null
@@ -0,0 +1,102 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/*
+ * Authors:
+ *   Brian Paul
+ */
+
+#include "imports.h"
+#include "texformat.h"
+
+#include "st_context.h"
+#include "st_texobj.h"
+#include "pipe/p_defines.h"
+
+
+/**
+ * Create a pipe_texture_object from a Mesa texture object.
+ * Eventually, gl_texture_object may be derived from this...
+ */
+struct pipe_texture_object *
+create_texture_object(struct gl_texture_object *texObj)
+{
+   struct pipe_texture_object *pto;
+   const struct gl_texture_image *texImage;
+
+   pto = calloc(1, sizeof(*pto));
+   if (!pto)
+      return NULL;
+
+   /* XXX: Member not defined. Comment-out to get it compile. */
+   /*assert(texObj->Complete);*/
+
+   switch (texObj->Target) {
+   case GL_TEXTURE_1D:
+      pto->type = PIPE_TEXTURE_1D;
+      break;
+   case GL_TEXTURE_2D:
+      pto->type = PIPE_TEXTURE_2D;
+      break;
+   case GL_TEXTURE_3D:
+      pto->type = PIPE_TEXTURE_3D;
+      break;
+   case GL_TEXTURE_CUBE_MAP:
+      pto->type = PIPE_TEXTURE_CUBE;
+      break;
+   default:
+      assert(0);
+      return NULL;
+   }
+
+   texImage = texObj->Image[0][texObj->BaseLevel];
+   assert(texImage);
+
+   switch (texImage->TexFormat->MesaFormat) {
+   case MESA_FORMAT_RGBA8888:
+      pto->format = PIPE_FORMAT_U_R8_G8_B8_A8;
+      break;
+   case MESA_FORMAT_RGB565:
+      pto->format = PIPE_FORMAT_U_R5_G6_B5;
+      break;
+
+   /* XXX fill in more formats */
+
+   default:
+      assert(0);
+      return NULL;
+   }
+
+   pto->width = texImage->Width;
+   pto->height = texImage->Height;
+   pto->depth = texImage->Depth;
+
+   /* XXX verify this */
+   pto->mipmapped = texObj->Image[0][texObj->BaseLevel + 1] != NULL;
+
+   return pto;
+}
diff --git a/src/mesa/state_tracker/st_texobj.h b/src/mesa/state_tracker/st_texobj.h
new file mode 100644 (file)
index 0000000..3c66031
--- /dev/null
@@ -0,0 +1,41 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 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.
+ * 
+ **************************************************************************/
+
+/*
+ * Authors:
+ *   Brian Paul
+ */
+
+#ifndef ST_TEXOBJ_H
+#define ST_TEXOBJ_H 1
+
+
+extern struct pipe_texture_object *
+create_texture_object(struct gl_texture_object *texObj);
+
+
+#endif /* ST_TEXOBJ_H */
diff --git a/src/mesa/vf/vf.c b/src/mesa/vf/vf.c
new file mode 100644 (file)
index 0000000..cb25f2e
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * on 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 THEIR 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+
+#include "vf.h"
+
+#define DBG 0
+
+
+
+static GLboolean match_fastpath( struct vertex_fetch *vf,
+                                const struct vf_fastpath *fp)
+{
+   GLuint j;
+
+   if (vf->attr_count != fp->attr_count) 
+      return GL_FALSE;
+
+   for (j = 0; j < vf->attr_count; j++) 
+      if (vf->attr[j].format != fp->attr[j].format ||
+         vf->attr[j].inputsize != fp->attr[j].size ||
+         vf->attr[j].vertoffset != fp->attr[j].offset) 
+        return GL_FALSE;
+      
+   if (fp->match_strides) {
+      if (vf->vertex_stride != fp->vertex_stride)
+        return GL_FALSE;
+
+      for (j = 0; j < vf->attr_count; j++) 
+        if (vf->attr[j].inputstride != fp->attr[j].stride) 
+           return GL_FALSE;
+   }
+   
+   return GL_TRUE;
+}
+
+static GLboolean search_fastpath_emit( struct vertex_fetch *vf )
+{
+   struct vf_fastpath *fp = vf->fastpath;
+
+   for ( ; fp ; fp = fp->next) {
+      if (match_fastpath(vf, fp)) {
+         vf->emit = fp->func;
+        return GL_TRUE;
+      }
+   }
+
+   return GL_FALSE;
+}
+
+void vf_register_fastpath( struct vertex_fetch *vf,
+                            GLboolean match_strides )
+{
+   struct vf_fastpath *fastpath = CALLOC_STRUCT(vf_fastpath);
+   GLuint i;
+
+   fastpath->vertex_stride = vf->vertex_stride;
+   fastpath->attr_count = vf->attr_count;
+   fastpath->match_strides = match_strides;
+   fastpath->func = vf->emit;
+   fastpath->attr = (struct vf_attr_type *)
+      _mesa_malloc(vf->attr_count * sizeof(fastpath->attr[0]));
+
+   for (i = 0; i < vf->attr_count; i++) {
+      fastpath->attr[i].format = vf->attr[i].format;
+      fastpath->attr[i].stride = vf->attr[i].inputstride;
+      fastpath->attr[i].size = vf->attr[i].inputsize;
+      fastpath->attr[i].offset = vf->attr[i].vertoffset;
+   }
+
+   fastpath->next = vf->fastpath;
+   vf->fastpath = fastpath;
+}
+
+
+
+
+/***********************************************************************
+ * Build codegen functions or return generic ones:
+ */
+static void choose_emit_func( struct vertex_fetch *vf, 
+                             GLuint count, 
+                             GLubyte *dest)
+{
+   vf->emit = NULL;
+   
+   /* Does this match an existing (hardwired, codegen or known-bad)
+    * fastpath?
+    */
+   if (search_fastpath_emit(vf)) {
+      /* Use this result.  If it is null, then it is already known
+       * that the current state will fail for codegen and there is no
+       * point trying again.
+       */
+   }
+   else if (vf->codegen_emit) {
+      vf->codegen_emit( vf );
+   }
+
+   if (!vf->emit) {
+      vf_generate_hardwired_emit(vf);
+   }
+
+   /* Otherwise use the generic version:
+    */
+   if (!vf->emit)
+      vf->emit = vf_generic_emit;
+
+   vf->emit( vf, count, dest );
+}
+
+
+
+
+
+/***********************************************************************
+ * Public entrypoints, mostly dispatch to the above:
+ */
+
+
+
+GLuint vf_set_vertex_attributes( struct vertex_fetch *vf, 
+                                const struct vf_attr_map *map,
+                                GLuint nr, 
+                                GLuint vertex_stride )
+{
+   GLuint offset = 0;
+   GLuint i, j;
+
+   assert(nr < VF_ATTRIB_MAX);
+
+   memset(vf->lookup, 0, sizeof(vf->lookup));
+
+   for (j = 0, i = 0; i < nr; i++) {
+      const GLuint format = map[i].format;
+      if (format == EMIT_PAD) {
+        if (DBG)
+           _mesa_printf("%d: pad %d, offset %d\n", i,  
+                        map[i].offset, offset);  
+
+        offset += map[i].offset;
+
+      }
+      else {
+        assert(vf->lookup[map[i].attrib] == 0);
+        vf->lookup[map[i].attrib] = &vf->attr[j];
+
+        vf->attr[j].attrib = map[i].attrib;
+        vf->attr[j].format = format;
+        vf->attr[j].insert = vf_format_info[format].insert;
+        vf->attr[j].extract = vf_format_info[format].extract;
+        vf->attr[j].vertattrsize = vf_format_info[format].attrsize;
+        vf->attr[j].vertoffset = offset;
+        
+        if (DBG)
+           _mesa_printf("%d: %s, offset %d\n", i,  
+                        vf_format_info[format].name,
+                        vf->attr[j].vertoffset);   
+
+        offset += vf_format_info[format].attrsize;
+        j++;
+      }
+   }
+
+   vf->attr_count = j;
+   vf->vertex_stride = vertex_stride ? vertex_stride : offset;
+   vf->emit = choose_emit_func;
+
+   assert(vf->vertex_stride >= offset);
+   return vf->vertex_stride;
+}
+
+
+
+void vf_set_vp_matrix( struct vertex_fetch *vf,
+                      const GLfloat *viewport )
+{
+   assert(vf->allow_viewport_emits);
+
+   /* scale */
+   vf->vp[0] = viewport[MAT_SX];
+   vf->vp[1] = viewport[MAT_SY];
+   vf->vp[2] = viewport[MAT_SZ];
+   vf->vp[3] = 1.0;
+
+   /* translate */
+   vf->vp[4] = viewport[MAT_TX];
+   vf->vp[5] = viewport[MAT_TY];
+   vf->vp[6] = viewport[MAT_TZ];
+   vf->vp[7] = 0.0;
+}
+
+void vf_set_vp_scale_translate( struct vertex_fetch *vf,
+                               const GLfloat *scale,
+                               const GLfloat *translate )
+{
+   assert(vf->allow_viewport_emits);
+
+   vf->vp[0] = scale[0];
+   vf->vp[1] = scale[1];
+   vf->vp[2] = scale[2];
+   vf->vp[3] = scale[3];
+
+   vf->vp[4] = translate[0];
+   vf->vp[5] = translate[1];
+   vf->vp[6] = translate[2];
+   vf->vp[7] = translate[3];
+}
+
+
+/* Set attribute pointers, adjusted for start position:
+ */
+void vf_set_sources( struct vertex_fetch *vf,
+                    GLvector4f * const sources[],
+                    GLuint start )
+{
+   struct vf_attr *a = vf->attr;
+   GLuint j;
+   
+   for (j = 0; j < vf->attr_count; j++) {
+      const GLvector4f *vptr = sources[a[j].attrib];
+      
+      if ((a[j].inputstride != vptr->stride) ||
+         (a[j].inputsize != vptr->size))
+        vf->emit = choose_emit_func;
+      
+      a[j].inputstride = vptr->stride;
+      a[j].inputsize = vptr->size;
+      a[j].do_insert = a[j].insert[vptr->size - 1]; 
+      a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
+   }
+}
+
+
+
+/* Emit count VB vertices to dest.  
+ */
+void vf_emit_vertices( struct vertex_fetch *vf,
+                      GLuint count,
+                      void *dest )
+{
+   vf->emit( vf, count, (GLubyte*) dest );     
+}
+
+
+/* Extract a named attribute from a hardware vertex.  Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied.
+ *
+ * This is mainly required for on-the-fly vertex translations to
+ * swrast format.
+ */
+void vf_get_attr( struct vertex_fetch *vf,
+                 const void *vertex,
+                 GLenum attr, 
+                 const GLfloat *dflt,
+                 GLfloat *dest )
+{
+   const struct vf_attr *a = vf->attr;
+   const GLuint attr_count = vf->attr_count;
+   GLuint j;
+
+   for (j = 0; j < attr_count; j++) {
+      if (a[j].attrib == attr) {
+        a[j].extract( &a[j], dest, (GLubyte *)vertex + a[j].vertoffset );
+        return;
+      }
+   }
+
+   /* Else return the value from ctx->Current.
+    */
+   _mesa_memcpy( dest, dflt, 4*sizeof(GLfloat));
+}
+
+
+
+
+struct vertex_fetch *vf_create( GLboolean allow_viewport_emits )
+{
+   struct vertex_fetch *vf = CALLOC_STRUCT(vertex_fetch);
+   GLuint i;
+
+   for (i = 0; i < VF_ATTRIB_MAX; i++)
+      vf->attr[i].vf = vf;
+
+   vf->allow_viewport_emits = allow_viewport_emits;
+
+   switch(CHAN_TYPE) {
+   case GL_UNSIGNED_BYTE:
+      vf->chan_scale[0] = 255.0;
+      vf->chan_scale[1] = 255.0;
+      vf->chan_scale[2] = 255.0;
+      vf->chan_scale[3] = 255.0;
+      break;
+   case GL_UNSIGNED_SHORT:
+      vf->chan_scale[0] = 65535.0;
+      vf->chan_scale[1] = 65535.0;
+      vf->chan_scale[2] = 65535.0;
+      vf->chan_scale[3] = 65535.0;
+      break;
+   default:
+      vf->chan_scale[0] = 1.0;
+      vf->chan_scale[1] = 1.0;
+      vf->chan_scale[2] = 1.0;
+      vf->chan_scale[3] = 1.0;
+      break;
+   }
+
+   vf->identity[0] = 0.0;
+   vf->identity[1] = 0.0;
+   vf->identity[2] = 0.0;
+   vf->identity[3] = 1.0;
+
+   vf->codegen_emit = NULL;
+
+#ifdef USE_SSE_ASM
+   if (!_mesa_getenv("MESA_NO_CODEGEN"))
+      vf->codegen_emit = vf_generate_sse_emit;
+#endif
+
+   return vf;
+}
+
+
+void vf_destroy( struct vertex_fetch *vf )
+{
+   struct vf_fastpath *fp, *tmp;
+
+   for (fp = vf->fastpath ; fp ; fp = tmp) {
+      tmp = fp->next;
+      FREE(fp->attr);
+
+      /* KW: At the moment, fp->func is constrained to be allocated by
+       * _mesa_exec_alloc(), as the hardwired fastpaths in
+       * t_vertex_generic.c are handled specially.  It would be nice
+       * to unify them, but this probably won't change until this
+       * module gets another overhaul.
+       */
+      _mesa_exec_free((void *) fp->func);
+      FREE(fp);
+   }
+   
+   vf->fastpath = NULL;
+   FREE(vf);
+}
diff --git a/src/mesa/vf/vf.h b/src/mesa/vf/vf.h
new file mode 100644 (file)
index 0000000..fc988b9
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * on 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 THEIR 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#ifndef VF_VERTEX_H
+#define VF_VERTEX_H
+
+#include "mtypes.h"
+#include "m_vector.h"
+
+enum {
+   VF_ATTRIB_POS = 0,
+   VF_ATTRIB_WEIGHT = 1,
+   VF_ATTRIB_NORMAL = 2,
+   VF_ATTRIB_COLOR0 = 3,
+   VF_ATTRIB_COLOR1 = 4,
+   VF_ATTRIB_FOG = 5,
+   VF_ATTRIB_COLOR_INDEX = 6,
+   VF_ATTRIB_EDGEFLAG = 7,
+   VF_ATTRIB_TEX0 = 8,
+   VF_ATTRIB_TEX1 = 9,
+   VF_ATTRIB_TEX2 = 10,
+   VF_ATTRIB_TEX3 = 11,
+   VF_ATTRIB_TEX4 = 12,
+   VF_ATTRIB_TEX5 = 13,
+   VF_ATTRIB_TEX6 = 14,
+   VF_ATTRIB_TEX7 = 15,
+   VF_ATTRIB_VAR0 = 16,
+   VF_ATTRIB_VAR1 = 17,
+   VF_ATTRIB_VAR2 = 18,
+   VF_ATTRIB_VAR3 = 19,
+   VF_ATTRIB_VAR4 = 20,
+   VF_ATTRIB_VAR5 = 21,
+   VF_ATTRIB_VAR6 = 22,
+   VF_ATTRIB_VAR7 = 23,
+   VF_ATTRIB_POINTSIZE = 24,
+   VF_ATTRIB_BFC0 = 25,
+   VF_ATTRIB_BFC1 = 26,
+   VF_ATTRIB_CLIP_POS = 27,
+   VF_ATTRIB_VERTEX_HEADER = 28,
+   VF_ATTRIB_MAX = 29
+};
+
+
+enum vf_attr_format {
+   EMIT_1F,
+   EMIT_2F,
+   EMIT_3F,
+   EMIT_4F,
+   EMIT_2F_VIEWPORT,           /* do viewport transform and emit */
+   EMIT_3F_VIEWPORT,           /* do viewport transform and emit */
+   EMIT_4F_VIEWPORT,           /* do viewport transform and emit */
+   EMIT_3F_XYW,                        /* for projective texture */
+   EMIT_1UB_1F,                        /* for fog coordinate */
+   EMIT_3UB_3F_RGB,            /* for specular color */
+   EMIT_3UB_3F_BGR,            /* for specular color */
+   EMIT_4UB_4F_RGBA,           /* for color */
+   EMIT_4UB_4F_BGRA,           /* for color */
+   EMIT_4UB_4F_ARGB,           /* for color */
+   EMIT_4UB_4F_ABGR,           /* for color */
+   EMIT_4CHAN_4F_RGBA,         /* for swrast color */
+   EMIT_PAD,                   /* leave a hole of 'offset' bytes */
+   EMIT_MAX
+};
+
+struct vf_attr_map {
+   GLuint attrib;
+   enum vf_attr_format format;
+   GLuint offset;
+};
+
+struct vertex_fetch;
+
+void vf_set_vp_matrix( struct vertex_fetch *vf,
+                     const GLfloat *viewport );
+
+void vf_set_vp_scale_translate( struct vertex_fetch *vf,
+                               const GLfloat *scale,
+                               const GLfloat *translate );
+
+GLuint vf_set_vertex_attributes( struct vertex_fetch *vf,
+                                const struct vf_attr_map *map,
+                                GLuint nr, 
+                                GLuint vertex_stride );
+
+void vf_set_sources( struct vertex_fetch *vf,
+                    GLvector4f * const attrib[],
+                    GLuint start ); 
+
+void vf_emit_vertices( struct vertex_fetch *vf,
+                      GLuint count,
+                      void *dest );
+
+void vf_get_attr( struct vertex_fetch *vf,
+                 const void *vertex,
+                 GLenum attr, 
+                 const GLfloat *dflt,
+                 GLfloat *dest );
+
+struct vertex_fetch *vf_create( GLboolean allow_viewport_emits );
+
+void vf_destroy( struct vertex_fetch *vf );
+
+
+
+/***********************************************************************
+ * Internal functions and structs:
+ */
+
+struct vf_attr;
+
+typedef void (*vf_extract_func)( const struct vf_attr *a, 
+                                GLfloat *out, 
+                                const GLubyte *v );
+
+typedef void (*vf_insert_func)( const struct vf_attr *a, 
+                               GLubyte *v, 
+                               const GLfloat *in );
+
+typedef void (*vf_emit_func)( struct vertex_fetch *vf,
+                             GLuint count, 
+                             GLubyte *dest );
+
+
+
+/* Describes how to convert/move a vertex attribute from a vertex
+ * array to a vertex structure.
+ */
+struct vf_attr
+{
+   struct vertex_fetch *vf;
+
+   GLuint format;
+   GLuint inputsize;
+   GLuint inputstride;
+   GLuint vertoffset;      /* position of the attrib in the vertex struct */
+
+   GLuint attrib;          /* which vertex attrib (0=position, etc) */
+   GLuint vertattrsize;    /* size of the attribute in bytes */
+
+   GLubyte *inputptr;
+   const vf_insert_func *insert;
+   vf_insert_func do_insert;
+   vf_extract_func extract;
+};
+
+struct vertex_fetch
+{
+   struct vf_attr attr[VF_ATTRIB_MAX];
+   GLuint attr_count;
+   GLuint vertex_stride;
+
+   struct vf_attr *lookup[VF_ATTRIB_MAX];
+   
+   vf_emit_func emit;
+
+   /* Parameters and constants for codegen:
+    */
+   GLboolean allow_viewport_emits;
+   GLfloat vp[8];              
+   GLfloat chan_scale[4];
+   GLfloat identity[4];
+
+   struct vf_fastpath *fastpath;
+   
+   void (*codegen_emit)( struct vertex_fetch *vf );
+};
+
+
+struct vf_attr_type {
+   GLuint format;
+   GLuint size;
+   GLuint stride;
+   GLuint offset;
+};
+
+struct vf_fastpath {
+   GLuint vertex_stride;
+   GLuint attr_count;
+   GLboolean match_strides;
+
+   struct vf_attr_type *attr;
+
+   vf_emit_func func;
+   struct vf_fastpath *next;
+};
+
+
+void vf_register_fastpath( struct vertex_fetch *vtx,
+                            GLboolean match_strides );
+
+void vf_generic_emit( struct vertex_fetch *vf,
+                       GLuint count,
+                       GLubyte *v );
+
+void vf_generate_hardwired_emit( struct vertex_fetch *vf );
+
+void vf_generate_sse_emit( struct vertex_fetch *vf );
+
+
+struct vf_format_info {
+   const char *name;
+   vf_extract_func extract;
+   vf_insert_func insert[4];
+   const GLuint attrsize;
+};
+
+const struct vf_format_info vf_format_info[EMIT_MAX];
+
+
+#endif
diff --git a/src/mesa/vf/vf_generic.c b/src/mesa/vf/vf_generic.c
new file mode 100644 (file)
index 0000000..68d8d08
--- /dev/null
@@ -0,0 +1,981 @@
+
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * on 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 THEIR 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "simple_list.h"
+
+#include "vf/vf.h"
+
+
+/*
+ * These functions take the NDC coordinates pointed to by 'in', apply the
+ * NDC->Viewport mapping and store the results at 'v'.
+ */
+
+static INLINE void insert_4f_viewport_4( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = scale[1] * in[1] + trans[1];
+   out[2] = scale[2] * in[2] + trans[2];
+   out[3] = in[3];
+}
+
+static INLINE void insert_4f_viewport_3( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = scale[1] * in[1] + trans[1];
+   out[2] = scale[2] * in[2] + trans[2];
+   out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_2( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = scale[1] * in[1] + trans[1];
+   out[2] =                    trans[2];
+   out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_1( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] =                    trans[1];
+   out[2] =                    trans[2];
+   out[3] = 1;
+}
+
+static INLINE void insert_3f_viewport_3( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = scale[1] * in[1] + trans[1];
+   out[2] = scale[2] * in[2] + trans[2];
+}
+
+static INLINE void insert_3f_viewport_2( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = scale[1] * in[1] + trans[1];
+   out[2] = scale[2] * in[2] + trans[2];
+}
+
+static INLINE void insert_3f_viewport_1( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] =                    trans[1];
+   out[2] =                    trans[2];
+}
+
+static INLINE void insert_2f_viewport_2( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = scale[1] * in[1] + trans[1];
+}
+
+static INLINE void insert_2f_viewport_1( const struct vf_attr *a, GLubyte *v,
+                                        const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = scale[0] * in[0] + trans[0];
+   out[1] = trans[1];
+}
+
+
+/*
+ * These functions do the same as above, except for the viewport mapping.
+ */
+
+static INLINE void insert_4f_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = in[2];
+   out[3] = in[3];
+}
+
+static INLINE void insert_4f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = in[2];
+   out[3] = 1;
+}
+
+static INLINE void insert_4f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = 0;
+   out[3] = 1;
+}
+
+static INLINE void insert_4f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = 0;
+   out[2] = 0;
+   out[3] = 1;
+}
+
+static INLINE void insert_3f_xyw_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = in[3];
+}
+
+static INLINE void insert_3f_xyw_err( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   (void) a; (void) v; (void) in;
+   _mesa_exit(1);
+}
+
+static INLINE void insert_3f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = in[2];
+}
+
+static INLINE void insert_3f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = 0;
+}
+
+static INLINE void insert_3f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = 0;
+   out[2] = 0;
+}
+
+
+static INLINE void insert_2f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+}
+
+static INLINE void insert_2f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = 0;
+}
+
+static INLINE void insert_1f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   GLfloat *out = (GLfloat *)(v);
+   (void) a;
+
+   out[0] = in[0];
+}
+
+static INLINE void insert_null( const struct vf_attr *a, GLubyte *v, const GLfloat *in )
+{
+   (void) a; (void) v; (void) in;
+}
+
+static INLINE void insert_4chan_4f_rgba_4( const struct vf_attr *a, GLubyte *v, 
+                                          const GLfloat *in )
+{
+   GLchan *c = (GLchan *)v;
+   (void) a;
+   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); 
+   UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); 
+   UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); 
+   UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
+}
+
+static INLINE void insert_4chan_4f_rgba_3( const struct vf_attr *a, GLubyte *v, 
+                                          const GLfloat *in )
+{
+   GLchan *c = (GLchan *)v;
+   (void) a;
+   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); 
+   UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); 
+   UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); 
+   c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_2( const struct vf_attr *a, GLubyte *v, 
+                                          const GLfloat *in )
+{
+   GLchan *c = (GLchan *)v;
+   (void) a;
+   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); 
+   UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); 
+   c[2] = 0;
+   c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_1( const struct vf_attr *a, GLubyte *v, 
+                                          const GLfloat *in )
+{
+   GLchan *c = (GLchan *)v;
+   (void) a;
+   UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); 
+   c[1] = 0;
+   c[2] = 0;
+   c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4ub_4f_rgba_4( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_rgba_3( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+   v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_2( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   v[2] = 0;
+   v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_1( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   v[1] = 0;
+   v[2] = 0;
+   v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_4( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_bgra_3( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+   v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_2( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   v[0] = 0;
+   v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_1( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   v[1] = 0;
+   v[0] = 0;
+   v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_4( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_argb_3( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+   v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_2( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+   v[3] = 0x00;
+   v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_1( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+   v[2] = 0x00;
+   v[3] = 0x00;
+   v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_4( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_abgr_3( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+   v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_2( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+   v[1] = 0x00;
+   v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_1( const struct vf_attr *a, GLubyte *v, 
+                                        const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+   v[2] = 0x00;
+   v[1] = 0x00;
+   v[0] = 0xff;
+}
+
+static INLINE void insert_3ub_3f_rgb_3( const struct vf_attr *a, GLubyte *v, 
+                                       const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+}
+
+static INLINE void insert_3ub_3f_rgb_2( const struct vf_attr *a, GLubyte *v, 
+                                       const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_rgb_1( const struct vf_attr *a, GLubyte *v, 
+                                       const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+   v[1] = 0;
+   v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_3( const struct vf_attr *a, GLubyte *v, 
+                                       const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+}
+
+static INLINE void insert_3ub_3f_bgr_2( const struct vf_attr *a, GLubyte *v, 
+                                       const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+   v[0] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_1( const struct vf_attr *a, GLubyte *v, 
+                                       const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+   v[1] = 0;
+   v[0] = 0;
+}
+
+
+static INLINE void insert_1ub_1f_1( const struct vf_attr *a, GLubyte *v, 
+                                   const GLfloat *in )
+{
+   (void) a;
+   UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+}
+
+
+/***********************************************************************
+ * Functions to perform the reverse operations to the above, for
+ * swrast translation and clip-interpolation.
+ * 
+ * Currently always extracts a full 4 floats.
+ */
+
+static void extract_4f_viewport( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   /* Although included for completeness, the position coordinate is
+    * usually handled differently during clipping.
+    */
+   out[0] = (in[0] - trans[0]) / scale[0];
+   out[1] = (in[1] - trans[1]) / scale[1];
+   out[2] = (in[2] - trans[2]) / scale[2];
+   out[3] = in[3];
+}
+
+static void extract_3f_viewport( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = (in[0] - trans[0]) / scale[0];
+   out[1] = (in[1] - trans[1]) / scale[1];
+   out[2] = (in[2] - trans[2]) / scale[2];
+   out[3] = 1;
+}
+
+
+static void extract_2f_viewport( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   const GLfloat *scale = a->vf->vp;
+   const GLfloat *trans = a->vf->vp + 4;
+   
+   out[0] = (in[0] - trans[0]) / scale[0];
+   out[1] = (in[1] - trans[1]) / scale[1];
+   out[2] = 0;
+   out[3] = 1;
+}
+
+
+static void extract_4f( const struct vf_attr *a, GLfloat *out, const GLubyte *v  )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = in[2];
+   out[3] = in[3];
+}
+
+static void extract_3f_xyw( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = 0;
+   out[3] = in[2];
+}
+
+
+static void extract_3f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = in[2];
+   out[3] = 1;
+}
+
+
+static void extract_2f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = in[1];
+   out[2] = 0;
+   out[3] = 1;
+}
+
+static void extract_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+   const GLfloat *in = (const GLfloat *)v;
+   (void) a;
+   
+   out[0] = in[0];
+   out[1] = 0;
+   out[2] = 0;
+   out[3] = 1;
+}
+
+static void extract_4chan_4f_rgba( const struct vf_attr *a, GLfloat *out, 
+                                  const GLubyte *v )
+{
+   GLchan *c = (GLchan *)v;
+   (void) a;
+
+   out[0] = CHAN_TO_FLOAT(c[0]);
+   out[1] = CHAN_TO_FLOAT(c[1]);
+   out[2] = CHAN_TO_FLOAT(c[2]);
+   out[3] = CHAN_TO_FLOAT(c[3]);
+}
+
+static void extract_4ub_4f_rgba( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   (void) a;
+   out[0] = UBYTE_TO_FLOAT(v[0]);
+   out[1] = UBYTE_TO_FLOAT(v[1]);
+   out[2] = UBYTE_TO_FLOAT(v[2]);
+   out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_bgra( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   (void) a;
+   out[2] = UBYTE_TO_FLOAT(v[0]);
+   out[1] = UBYTE_TO_FLOAT(v[1]);
+   out[0] = UBYTE_TO_FLOAT(v[2]);
+   out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_argb( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   (void) a;
+   out[3] = UBYTE_TO_FLOAT(v[0]);
+   out[0] = UBYTE_TO_FLOAT(v[1]);
+   out[1] = UBYTE_TO_FLOAT(v[2]);
+   out[2] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_abgr( const struct vf_attr *a, GLfloat *out, 
+                                const GLubyte *v )
+{
+   (void) a;
+   out[3] = UBYTE_TO_FLOAT(v[0]);
+   out[2] = UBYTE_TO_FLOAT(v[1]);
+   out[1] = UBYTE_TO_FLOAT(v[2]);
+   out[0] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_3ub_3f_rgb( const struct vf_attr *a, GLfloat *out, 
+                               const GLubyte *v )
+{
+   (void) a;
+   out[0] = UBYTE_TO_FLOAT(v[0]);
+   out[1] = UBYTE_TO_FLOAT(v[1]);
+   out[2] = UBYTE_TO_FLOAT(v[2]);
+   out[3] = 1;
+}
+
+static void extract_3ub_3f_bgr( const struct vf_attr *a, GLfloat *out, 
+                               const GLubyte *v )
+{
+   (void) a;
+   out[2] = UBYTE_TO_FLOAT(v[0]);
+   out[1] = UBYTE_TO_FLOAT(v[1]);
+   out[0] = UBYTE_TO_FLOAT(v[2]);
+   out[3] = 1;
+}
+
+static void extract_1ub_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v )
+{
+   (void) a;
+   out[0] = UBYTE_TO_FLOAT(v[0]);
+   out[1] = 0;
+   out[2] = 0;
+   out[3] = 1;
+}
+
+
+const struct vf_format_info vf_format_info[EMIT_MAX] = 
+{
+   { "1f",
+     extract_1f,
+     { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
+     sizeof(GLfloat) },
+
+   { "2f",
+     extract_2f,
+     { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
+     2 * sizeof(GLfloat) },
+
+   { "3f",
+     extract_3f,
+     { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
+     3 * sizeof(GLfloat) },
+
+   { "4f",
+     extract_4f,
+     { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
+     4 * sizeof(GLfloat) },
+
+   { "2f_viewport",
+     extract_2f_viewport,
+     { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
+       insert_2f_viewport_2 },
+     2 * sizeof(GLfloat) },
+
+   { "3f_viewport",
+     extract_3f_viewport,
+     { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
+       insert_3f_viewport_3 },
+     3 * sizeof(GLfloat) },
+
+   { "4f_viewport",
+     extract_4f_viewport,
+     { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
+       insert_4f_viewport_4 }, 
+     4 * sizeof(GLfloat) },
+
+   { "3f_xyw",
+     extract_3f_xyw,
+     { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err, 
+       insert_3f_xyw_4 },
+     3 * sizeof(GLfloat) },
+
+   { "1ub_1f",
+     extract_1ub_1f,
+     { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
+     sizeof(GLubyte) },
+
+   { "3ub_3f_rgb",
+     extract_3ub_3f_rgb,
+     { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
+       insert_3ub_3f_rgb_3 },
+     3 * sizeof(GLubyte) },
+
+   { "3ub_3f_bgr",
+     extract_3ub_3f_bgr,
+     { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
+       insert_3ub_3f_bgr_3 },
+     3 * sizeof(GLubyte) },
+
+   { "4ub_4f_rgba",
+     extract_4ub_4f_rgba,
+     { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3, 
+       insert_4ub_4f_rgba_4 },
+     4 * sizeof(GLubyte) },
+
+   { "4ub_4f_bgra",
+     extract_4ub_4f_bgra,
+     { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
+       insert_4ub_4f_bgra_4 },
+     4 * sizeof(GLubyte) },
+
+   { "4ub_4f_argb",
+     extract_4ub_4f_argb,
+     { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
+       insert_4ub_4f_argb_4 },
+     4 * sizeof(GLubyte) },
+
+   { "4ub_4f_abgr",
+     extract_4ub_4f_abgr,
+     { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
+       insert_4ub_4f_abgr_4 },
+     4 * sizeof(GLubyte) },
+
+   { "4chan_4f_rgba",
+     extract_4chan_4f_rgba,
+     { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
+       insert_4chan_4f_rgba_4 },
+     4 * sizeof(GLchan) },
+
+   { "pad",
+     NULL,
+     { NULL, NULL, NULL, NULL },
+     0 }
+
+};
+
+
+
+    
+/***********************************************************************
+ * Hardwired fastpaths for emitting whole vertices or groups of
+ * vertices
+ */
+#define EMIT5(NR, F0, F1, F2, F3, F4, NAME)                            \
+static void NAME( struct vertex_fetch *vf,                             \
+                 GLuint count,                                         \
+                 GLubyte *v )                                          \
+{                                                                      \
+   struct vf_attr *a = vf->attr;                               \
+   GLuint i;                                                           \
+                                                                       \
+   for (i = 0 ; i < count ; i++, v += vf->vertex_stride) {             \
+      if (NR > 0) {                                                    \
+        F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );    \
+        a[0].inputptr += a[0].inputstride;                             \
+      }                                                                        \
+                                                                       \
+      if (NR > 1) {                                                    \
+        F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );    \
+        a[1].inputptr += a[1].inputstride;                             \
+      }                                                                        \
+                                                                       \
+      if (NR > 2) {                                                    \
+        F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr );    \
+        a[2].inputptr += a[2].inputstride;                             \
+      }                                                                        \
+                                                                       \
+      if (NR > 3) {                                                    \
+        F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr );    \
+        a[3].inputptr += a[3].inputstride;                             \
+      }                                                                        \
+                                                                       \
+      if (NR > 4) {                                                    \
+        F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr );    \
+        a[4].inputptr += a[4].inputstride;                             \
+      }                                                                        \
+   }                                                                   \
+}
+
+   
+#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \
+                                 insert_null, insert_null, NAME)
+
+#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \
+                                     insert_null, NAME)
+   
+#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \
+                                         insert_null, NAME)
+   
+
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
+EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
+
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2,  emit_viewport4_bgra4_st2)
+EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
+
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2,  emit_viewport4_bgra4_st2_st2)
+EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2)
+
+
+/* Use the codegen paths to select one of a number of hardwired
+ * fastpaths.
+ */
+void vf_generate_hardwired_emit( struct vertex_fetch *vf )
+{
+   vf_emit_func func = NULL;
+
+   /* Does it fit a hardwired fastpath?  Help! this is growing out of
+    * control!
+    */
+   switch (vf->attr_count) {
+   case 2:
+      if (vf->attr[0].do_insert == insert_3f_viewport_3) {
+        if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4) 
+           func = emit_viewport3_bgra4;
+        else if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) 
+           func = emit_viewport3_rgba4;
+      }
+      else if (vf->attr[0].do_insert == insert_3f_3 &&
+              vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+        func = emit_xyz3_rgba4; 
+      }
+      break;
+   case 3:
+      if (vf->attr[2].do_insert == insert_2f_2) {
+        if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+           if (vf->attr[0].do_insert == insert_4f_viewport_4)
+              func = emit_viewport4_rgba4_st2;
+           else if (vf->attr[0].do_insert == insert_4f_4) 
+              func = emit_xyzw4_rgba4_st2;
+        }
+        else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 &&
+                 vf->attr[0].do_insert == insert_4f_viewport_4)
+           func = emit_viewport4_bgra4_st2;
+      }
+      break;
+   case 4:
+      if (vf->attr[2].do_insert == insert_2f_2 &&
+         vf->attr[3].do_insert == insert_2f_2) {
+        if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) {
+           if (vf->attr[0].do_insert == insert_4f_viewport_4)
+              func = emit_viewport4_rgba4_st2_st2;
+           else if (vf->attr[0].do_insert == insert_4f_4) 
+              func = emit_xyzw4_rgba4_st2_st2;
+        }
+        else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 &&
+                 vf->attr[0].do_insert == insert_4f_viewport_4)
+           func = emit_viewport4_bgra4_st2_st2;
+      }
+      break;
+   }
+
+   vf->emit = func;
+}
+
+/***********************************************************************
+ * Generic (non-codegen) functions for whole vertices or groups of
+ * vertices
+ */
+
+void vf_generic_emit( struct vertex_fetch *vf,
+                     GLuint count,
+                     GLubyte *v )
+{
+   struct vf_attr *a = vf->attr;
+   const GLuint attr_count = vf->attr_count;
+   const GLuint stride = vf->vertex_stride;
+   GLuint i, j;
+
+   for (i = 0 ; i < count ; i++, v += stride) {
+      for (j = 0; j < attr_count; j++) {
+        GLfloat *in = (GLfloat *)a[j].inputptr;
+        a[j].inputptr += a[j].inputstride;
+        a[j].do_insert( &a[j], v + a[j].vertoffset, in );
+      }
+   }
+}
+
+
diff --git a/src/mesa/vf/vf_sse.c b/src/mesa/vf/vf_sse.c
new file mode 100644 (file)
index 0000000..a5d1434
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+ * Copyright 2003 Tungsten Graphics, 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
+ * on 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 THEIR 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.
+ *
+ * Authors:
+ *    Keith Whitwell <keithw@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "colormac.h"
+#include "simple_list.h"
+#include "enums.h"
+
+#include "vf/vf.h"
+
+#if defined(USE_SSE_ASM)
+
+#include "x86/rtasm/x86sse.h"
+#include "x86/common_x86_asm.h"
+
+
+#define X    0
+#define Y    1
+#define Z    2
+#define W    3
+
+
+struct x86_program {
+   struct x86_function func;
+
+   struct vertex_fetch *vf;
+   GLboolean inputs_safe;
+   GLboolean outputs_safe;
+   GLboolean have_sse2;
+   
+   struct x86_reg identity;
+   struct x86_reg chan0;
+};
+
+
+static struct x86_reg get_identity( struct x86_program *p )
+{
+   return p->identity;
+}
+
+static void emit_load4f_4( struct x86_program *p,                         
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_load4f_3( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   /* Have to jump through some hoops:
+    *
+    * c 0 0 0
+    * c 0 0 1
+    * 0 0 c 1
+    * a b c 1
+    */
+   sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+   sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+   sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
+   sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_2( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   /* Initialize from identity, then pull in low two words:
+    */
+   sse_movups(&p->func, dest, get_identity(p));
+   sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_1( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   /* Pull in low word, then swizzle in identity */
+   sse_movss(&p->func, dest, arg0);
+   sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+}
+
+
+
+static void emit_load3f_3( struct x86_program *p,                         
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   /* Over-reads by 1 dword - potential SEGV if input is a vertex
+    * array.
+    */
+   if (p->inputs_safe) {
+      sse_movups(&p->func, dest, arg0);
+   } 
+   else {
+      /* c 0 0 0
+       * c c c c
+       * a b c c 
+       */
+      sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+      sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
+      sse_movlps(&p->func, dest, arg0);
+   }
+}
+
+static void emit_load3f_2( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   emit_load4f_2(p, dest, arg0);
+}
+
+static void emit_load3f_1( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   emit_load4f_1(p, dest, arg0);
+}
+
+static void emit_load2f_2( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load2f_1( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   emit_load4f_1(p, dest, arg0);
+}
+
+static void emit_load1f_1( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   sse_movss(&p->func, dest, arg0);
+}
+
+static void (*load[4][4])( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 ) = {
+   { emit_load1f_1, 
+     emit_load1f_1, 
+     emit_load1f_1, 
+     emit_load1f_1 },
+
+   { emit_load2f_1, 
+     emit_load2f_2, 
+     emit_load2f_2, 
+     emit_load2f_2 },
+
+   { emit_load3f_1, 
+     emit_load3f_2, 
+     emit_load3f_3, 
+     emit_load3f_3 },
+
+   { emit_load4f_1, 
+     emit_load4f_2, 
+     emit_load4f_3, 
+     emit_load4f_4 } 
+};
+
+static void emit_load( struct x86_program *p,
+                      struct x86_reg dest,
+                      GLuint sz,
+                      struct x86_reg src,
+                      GLuint src_sz)
+{
+   load[sz-1][src_sz-1](p, dest, src);
+}
+
+static void emit_store4f( struct x86_program *p,                          
+                         struct x86_reg dest,
+                         struct x86_reg arg0 )
+{
+   sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_store3f( struct x86_program *p, 
+                         struct x86_reg dest,
+                         struct x86_reg arg0 )
+{
+   if (p->outputs_safe) {
+      /* Emit the extra dword anyway.  This may hurt writecombining,
+       * may cause other problems.
+       */
+      sse_movups(&p->func, dest, arg0);
+   }
+   else {
+      /* Alternate strategy - emit two, shuffle, emit one.
+       */
+      sse_movlps(&p->func, dest, arg0);
+      sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+      sse_movss(&p->func, x86_make_disp(dest,8), arg0);
+   }
+}
+
+static void emit_store2f( struct x86_program *p, 
+                          struct x86_reg dest,
+                          struct x86_reg arg0 )
+{
+   sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_store1f( struct x86_program *p, 
+                         struct x86_reg dest,
+                         struct x86_reg arg0 )
+{
+   sse_movss(&p->func, dest, arg0);
+}
+
+
+static void (*store[4])( struct x86_program *p, 
+                        struct x86_reg dest,
+                        struct x86_reg arg0 ) = 
+{
+   emit_store1f, 
+   emit_store2f, 
+   emit_store3f, 
+   emit_store4f 
+};
+
+static void emit_store( struct x86_program *p,
+                       struct x86_reg dest,
+                       GLuint sz,
+                       struct x86_reg temp )
+
+{
+   store[sz-1](p, dest, temp);
+}
+
+static void emit_pack_store_4ub( struct x86_program *p,
+                                struct x86_reg dest,
+                                struct x86_reg temp )
+{
+   /* Scale by 255.0
+    */
+   sse_mulps(&p->func, temp, p->chan0);
+
+   if (p->have_sse2) {
+      sse2_cvtps2dq(&p->func, temp, temp);
+      sse2_packssdw(&p->func, temp, temp);
+      sse2_packuswb(&p->func, temp, temp);
+      sse_movss(&p->func, dest, temp);
+   }
+   else {
+      struct x86_reg mmx0 = x86_make_reg(file_MMX, 0);
+      struct x86_reg mmx1 = x86_make_reg(file_MMX, 1);
+      sse_cvtps2pi(&p->func, mmx0, temp);
+      sse_movhlps(&p->func, temp, temp);
+      sse_cvtps2pi(&p->func, mmx1, temp);
+      mmx_packssdw(&p->func, mmx0, mmx1);
+      mmx_packuswb(&p->func, mmx0, mmx0);
+      mmx_movd(&p->func, dest, mmx0);
+   }
+}
+
+static GLint get_offset( const void *a, const void *b )
+{
+   return (const char *)b - (const char *)a;
+}
+
+/* Not much happens here.  Eventually use this function to try and
+ * avoid saving/reloading the source pointers each vertex (if some of
+ * them can fit in registers).
+ */
+static void get_src_ptr( struct x86_program *p,
+                        struct x86_reg srcREG,
+                        struct x86_reg vfREG,
+                        struct vf_attr *a )
+{
+   struct vertex_fetch *vf = p->vf;
+   struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr));
+
+   /* Load current a[j].inputptr
+    */
+   x86_mov(&p->func, srcREG, ptr_to_src);
+}
+
+static void update_src_ptr( struct x86_program *p,
+                        struct x86_reg srcREG,
+                        struct x86_reg vfREG,
+                        struct vf_attr *a )
+{
+   if (a->inputstride) {
+      struct vertex_fetch *vf = p->vf;
+      struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr));
+
+      /* add a[j].inputstride (hardcoded value - could just as easily
+       * pull the stride value from memory each time).
+       */
+      x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride));
+      
+      /* save new value of a[j].inputptr 
+       */
+      x86_mov(&p->func, ptr_to_src, srcREG);
+   }
+}
+
+
+/* Lots of hardcoding
+ *
+ * EAX -- pointer to current output vertex
+ * ECX -- pointer to current attribute 
+ * 
+ */
+static GLboolean build_vertex_emit( struct x86_program *p )
+{
+   struct vertex_fetch *vf = p->vf;
+   GLuint j = 0;
+
+   struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX);
+   struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX);
+   struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP);
+   struct x86_reg vfESI = x86_make_reg(file_REG32, reg_SI);
+   struct x86_reg temp = x86_make_reg(file_XMM, 0);
+   struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
+   struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+   GLubyte *fixup, *label;
+
+   x86_init_func(&p->func);
+   
+   /* Push a few regs?
+    */
+   x86_push(&p->func, countEBP);
+   x86_push(&p->func, vfESI);
+
+
+   /* Get vertex count, compare to zero
+    */
+   x86_xor(&p->func, srcECX, srcECX);
+   x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2));
+   x86_cmp(&p->func, countEBP, srcECX);
+   fixup = x86_jcc_forward(&p->func, cc_E);
+
+   /* Initialize destination register. 
+    */
+   x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3));
+
+   /* Move argument 1 (vf) into a reg:
+    */
+   x86_mov(&p->func, vfESI, x86_fn_arg(&p->func, 1));
+
+   
+   /* Possibly load vp0, vp1 for viewport calcs:
+    */
+   if (vf->allow_viewport_emits) {
+      sse_movups(&p->func, vp0, x86_make_disp(vfESI, get_offset(vf, &vf->vp[0])));
+      sse_movups(&p->func, vp1, x86_make_disp(vfESI, get_offset(vf, &vf->vp[4])));
+   }
+
+   /* always load, needed or not:
+    */
+   sse_movups(&p->func, p->chan0, x86_make_disp(vfESI, get_offset(vf, &vf->chan_scale[0])));
+   sse_movups(&p->func, p->identity, x86_make_disp(vfESI, get_offset(vf, &vf->identity[0])));
+
+   /* Note address for loop jump */
+   label = x86_get_label(&p->func);
+
+   /* Emit code for each of the attributes.  Currently routes
+    * everything through SSE registers, even when it might be more
+    * efficient to stick with regular old x86.  No optimization or
+    * other tricks - enough new ground to cover here just getting
+    * things working.
+    */
+   while (j < vf->attr_count) {
+      struct vf_attr *a = &vf->attr[j];
+      struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset);
+
+      /* Now, load an XMM reg from src, perhaps transform, then save.
+       * Could be shortcircuited in specific cases:
+       */
+      switch (a->format) {
+      case EMIT_1F:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+        emit_store(p, dest, 1, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_2F:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+        emit_store(p, dest, 2, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_3F:
+        /* Potentially the worst case - hardcode 2+1 copying:
+         */
+        if (0) {
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+           emit_store(p, dest, 3, temp);
+           update_src_ptr(p, srcECX, vfESI, a);
+        }
+        else {
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+           emit_store(p, dest, 2, temp);
+           if (a->inputsize > 2) {
+              emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1);
+              emit_store(p, x86_make_disp(dest,8), 1, temp);
+           }
+           else {
+              sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p));
+           }
+           update_src_ptr(p, srcECX, vfESI, a);
+        }
+        break;
+      case EMIT_4F:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        emit_store(p, dest, 4, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_2F_VIEWPORT: 
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+        sse_mulps(&p->func, temp, vp0);
+        sse_addps(&p->func, temp, vp1);
+        emit_store(p, dest, 2, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_3F_VIEWPORT: 
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+        sse_mulps(&p->func, temp, vp0);
+        sse_addps(&p->func, temp, vp1);
+        emit_store(p, dest, 3, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_4F_VIEWPORT: 
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        sse_mulps(&p->func, temp, vp0);
+        sse_addps(&p->func, temp, vp1);
+        emit_store(p, dest, 4, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_3F_XYW:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
+        emit_store(p, dest, 3, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+
+      case EMIT_1UB_1F:         
+        /* Test for PAD3 + 1UB:
+         */
+        if (j > 0 &&
+            a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3)
+        {
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+           sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
+           emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
+           update_src_ptr(p, srcECX, vfESI, a);
+        }
+        else {
+           _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+           return GL_FALSE;
+        }
+        break;
+      case EMIT_3UB_3F_RGB:
+      case EMIT_3UB_3F_BGR:
+        /* Test for 3UB + PAD1:
+         */
+        if (j == vf->attr_count - 1 ||
+            a[1].vertoffset >= a->vertoffset + 4) {
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+           if (a->format == EMIT_3UB_3F_BGR)
+              sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+           emit_pack_store_4ub(p, dest, temp);
+           update_src_ptr(p, srcECX, vfESI, a);
+        }
+        /* Test for 3UB + 1UB:
+         */
+        else if (j < vf->attr_count - 1 &&
+                 a[1].format == EMIT_1UB_1F &&
+                 a[1].vertoffset == a->vertoffset + 3) {
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+           update_src_ptr(p, srcECX, vfESI, a);
+
+           /* Make room for incoming value:
+            */
+           sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+
+           get_src_ptr(p, srcECX, vfESI, &a[1]);
+           emit_load(p, temp, 1, x86_deref(srcECX), a[1].inputsize);
+           update_src_ptr(p, srcECX, vfESI, &a[1]);
+
+           /* Rearrange and possibly do BGR conversion:
+            */
+           if (a->format == EMIT_3UB_3F_BGR)
+              sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+           else
+              sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
+
+           emit_pack_store_4ub(p, dest, temp);
+           j++;                /* NOTE: two attrs consumed */
+        }
+        else {
+           _mesa_printf("Can't emit 3ub\n");
+        }
+        return GL_FALSE;       /* add this later */
+        break;
+
+      case EMIT_4UB_4F_RGBA:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        emit_pack_store_4ub(p, dest, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_4UB_4F_BGRA:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+        emit_pack_store_4ub(p, dest, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_4UB_4F_ARGB:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+        emit_pack_store_4ub(p, dest, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_4UB_4F_ABGR:
+        get_src_ptr(p, srcECX, vfESI, a);
+        emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+        sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+        emit_pack_store_4ub(p, dest, temp);
+        update_src_ptr(p, srcECX, vfESI, a);
+        break;
+      case EMIT_4CHAN_4F_RGBA:
+        switch (CHAN_TYPE) {
+        case GL_UNSIGNED_BYTE:
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+           emit_pack_store_4ub(p, dest, temp);
+           update_src_ptr(p, srcECX, vfESI, a);
+           break;
+        case GL_FLOAT:
+           get_src_ptr(p, srcECX, vfESI, a);
+           emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+           emit_store(p, dest, 4, temp);
+           update_src_ptr(p, srcECX, vfESI, a);
+           break;
+        case GL_UNSIGNED_SHORT:
+        default:
+           _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+           return GL_FALSE;
+        }
+        break;
+      default:
+        _mesa_printf("unknown a[%d].format %d\n", j, a->format);
+        return GL_FALSE;       /* catch any new opcodes */
+      }
+      
+      /* Increment j by at least 1 - may have been incremented above also:
+       */
+      j++;
+   }
+
+   /* Next vertex:
+    */
+   x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vf->vertex_stride));
+
+   /* decr count, loop if not zero
+    */
+   x86_dec(&p->func, countEBP);
+   x86_test(&p->func, countEBP, countEBP); 
+   x86_jcc(&p->func, cc_NZ, label);
+
+   /* Exit mmx state?
+    */
+   if (p->func.need_emms)
+      mmx_emms(&p->func);
+
+   /* Land forward jump here:
+    */
+   x86_fixup_fwd_jump(&p->func, fixup);
+
+   /* Pop regs and return
+    */
+   x86_pop(&p->func, x86_get_base_reg(vfESI));
+   x86_pop(&p->func, countEBP);
+   x86_ret(&p->func);
+
+   vf->emit = (vf_emit_func)x86_get_func(&p->func);
+   return GL_TRUE;
+}
+
+
+
+void vf_generate_sse_emit( struct vertex_fetch *vf )
+{
+   struct x86_program p;   
+
+   if (!cpu_has_xmm) {
+      vf->codegen_emit = NULL;
+      return;
+   }
+
+   _mesa_memset(&p, 0, sizeof(p));
+
+   p.vf = vf;
+   p.inputs_safe = 0;          /* for now */
+   p.outputs_safe = 1;         /* for now */
+   p.have_sse2 = cpu_has_xmm2;
+   p.identity = x86_make_reg(file_XMM, 6);
+   p.chan0 = x86_make_reg(file_XMM, 7);
+
+   x86_init_func(&p.func);
+
+   if (build_vertex_emit(&p)) {
+      vf_register_fastpath( vf, GL_TRUE );
+   }
+   else {
+      /* Note the failure so that we don't keep trying to codegen an
+       * impossible state:
+       */
+      vf_register_fastpath( vf, GL_FALSE );
+      x86_release_func(&p.func);
+   }
+}
+
+#else
+
+void vf_generate_sse_emit( struct vertex_fetch *vf )
+{
+   /* Dummy version for when USE_SSE_ASM not defined */
+}
+
+#endif