Merge branch 'gallium-embedded'
authorJosé Fonseca <jfonseca@vmware.com>
Wed, 3 Feb 2010 18:54:13 +0000 (18:54 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Wed, 3 Feb 2010 18:54:13 +0000 (18:54 +0000)
82 files changed:
docs/egl.html
docs/envvars.html
progs/es2/xegl/tri.c
progs/fpglsl/.gitignore [new file with mode: 0644]
progs/fpglsl/Makefile [new file with mode: 0644]
progs/fpglsl/SConscript [new file with mode: 0644]
progs/fpglsl/fp-tri.c [new file with mode: 0644]
progs/fpglsl/mov-imm.glsl [new file with mode: 0644]
progs/fpglsl/mov.glsl [new file with mode: 0644]
progs/fpglsl/tex-multi.glsl [new file with mode: 0644]
progs/fpglsl/tex.glsl [new file with mode: 0644]
progs/tests/Makefile
progs/tests/SConscript
progs/tests/fbotest3.c [new file with mode: 0644]
src/egl/main/egldriver.c
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_pipe_aaline.c
src/gallium/auxiliary/draw/draw_pipe_aapoint.c
src/gallium/auxiliary/draw/draw_pipe_pstipple.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_parse.c
src/gallium/auxiliary/tgsi/tgsi_parse.h
src/gallium/auxiliary/tgsi/tgsi_ureg.c
src/gallium/auxiliary/tgsi/tgsi_ureg.h
src/gallium/docs/source/conf.py
src/gallium/docs/source/exts/tgsi.py [new file with mode: 0644]
src/gallium/docs/source/screen.rst
src/gallium/docs/source/tgsi.rst
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/r300/r300_fs.c
src/gallium/drivers/r300/r300_texture.h
src/gallium/drivers/r300/r300_tgsi_to_rc.c
src/gallium/drivers/r300/r300_tgsi_to_rc.h
src/gallium/drivers/softpipe/sp_state_derived.c
src/gallium/drivers/svga/svga_context.c
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_state_fs.c
src/gallium/drivers/svga/svga_tgsi.h
src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
src/gallium/drivers/svga/svga_tgsi_emit.h
src/gallium/drivers/svga/svga_tgsi_insn.c
src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/vega/asm_fill.h
src/gallium/state_trackers/vega/shaders_cache.c
src/mesa/drivers/directfb/idirectfbgl_mesa.c
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/r200/r200_maos_arrays.c
src/mesa/drivers/dri/r300/compiler/r300_fragprog.c
src/mesa/drivers/dri/r300/compiler/r300_fragprog_emit.c
src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c
src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c
src/mesa/drivers/dri/r300/compiler/radeon_compiler.h
src/mesa/drivers/dri/r300/compiler/radeon_pair_translate.c
src/mesa/drivers/dri/r300/compiler/radeon_program_pair.h
src/mesa/drivers/dri/r300/compiler/radeon_program_print.c
src/mesa/drivers/dri/r300/r300_blit.c
src/mesa/drivers/dri/r300/r300_fragprog_common.c
src/mesa/drivers/dri/radeon/radeon_screen.c
src/mesa/drivers/dri/swrast/swrast.c
src/mesa/drivers/fbdev/glfbdev.c
src/mesa/drivers/glslcompiler/Makefile
src/mesa/drivers/windows/gdi/wmesa.c
src/mesa/drivers/x11/xm_api.c
src/mesa/main/bitset.h
src/mesa/main/framebuffer.c
src/mesa/main/framebuffer.h
src/mesa/shader/prog_print.c
src/mesa/shader/prog_print.h
src/mesa/shader/program.c
src/mesa/shader/program.h
src/mesa/shader/programopt.c
src/mesa/state_tracker/st_atom_shader.c
src/mesa/state_tracker/st_atom_viewport.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_strings.c
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_framebuffer.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h
src/mesa/vbo/vbo_split_inplace.c

index 57b1d1488a8fc47116d45ca8e19dd0f05150d771..30cbe0eaeddb03eb0dc707d079acc3770e2df73b 100644 (file)
@@ -126,10 +126,21 @@ test your build.  For example,</p>
 runtime</p>
 
 <ul>
+<li><code>EGL_DRIVERS_PATH</code>
+
+<p>By default, the main library will look for drivers in the directory where
+the drivers are installed to.  This variable specifies a list of
+colon-separated directories where the main library will look for drivers, in
+addition to the default directory.  This variable is ignored for setuid/setgid
+binaries.</p>
+
+</li>
+
 <li><code>EGL_DRIVER</code>
 
-<p>This variable forces the specified EGL driver to be loaded.  It comes in
-handy when one wants to test a specific driver.</p>
+<p>This variable specifies a full path to an EGL driver and it forces the
+specified EGL driver to be loaded.  It comes in handy when one wants to test a
+specific driver.  This variable is ignored for setuid/setgid binaries.</p>
 
 </li>
 
index bb1c914cc73e2be6e2999a9676ccd9c7774e4a1a..fd1700a02f14aeeb0540f450702edd5527d3c4f6 100644 (file)
@@ -69,6 +69,10 @@ These environment variables are for the Radeon R300 driver:
 <li>R300_NO_TCL - if set, disable hardware-accelerated Transform/Clip/Lighting.
 </ul>
 
+<p>
+Mesa EGL supports different sets of environment variables.  See the
+<a href="egl.html">Mesa EGL</a> page for the details.
+</p>
 
 </BODY>
 </HTML>
index 7729a099578678c9c04a7c7d147a23242425dc8f..8981d8a7e217e9a5e8507b503fba8da39dc934d6 100644 (file)
@@ -334,14 +334,15 @@ make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
       exit(1);
    }
 
+   /* sanity checks */
    {
       EGLint val;
       eglQuerySurface(egl_dpy, *surfRet, EGL_WIDTH, &val);
       assert(val == width);
       eglQuerySurface(egl_dpy, *surfRet, EGL_HEIGHT, &val);
       assert(val == height);
-      eglQuerySurface(egl_dpy, *surfRet, EGL_SURFACE_TYPE, &val);
-      assert(val == EGL_WINDOW_BIT);
+      assert(eglGetConfigAttrib(egl_dpy, config, EGL_SURFACE_TYPE, &val));
+      assert(val & EGL_WINDOW_BIT);
    }
 
    XFree(visInfo);
diff --git a/progs/fpglsl/.gitignore b/progs/fpglsl/.gitignore
new file mode 100644 (file)
index 0000000..9fe73ab
--- /dev/null
@@ -0,0 +1 @@
+fp-tri
diff --git a/progs/fpglsl/Makefile b/progs/fpglsl/Makefile
new file mode 100644 (file)
index 0000000..3bf14b4
--- /dev/null
@@ -0,0 +1,52 @@
+# progs/tests/Makefile
+
+
+# These programs aren't intended to be included with the normal distro.
+# They're not too interesting but they're good for testing.
+
+TOP = ../..
+include $(TOP)/configs/current
+
+LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB)  -l$(GLEW_LIB) -l$(GLU_LIB) -l$(GL_LIB) $(APP_LIB_DEPS)
+
+SOURCES = \
+       fp-tri.c
+
+
+
+PROGS = $(SOURCES:%.c=%)
+
+INCLUDES = -I. -I$(TOP)/include -I../samples
+
+
+##### RULES #####
+
+.SUFFIXES:
+.SUFFIXES: .c
+
+.c:
+       $(CC) $(INCLUDES) $(CFLAGS) $< $(LIBS) -o $@
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES)  $< -o $@
+
+
+##### TARGETS #####
+
+default: $(PROGS)
+
+clean:
+       rm -f $(PROGS)
+       rm -f *.o
+       rm -f getproclist.h
+
+
+
+
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
diff --git a/progs/fpglsl/SConscript b/progs/fpglsl/SConscript
new file mode 100644 (file)
index 0000000..e31fa32
--- /dev/null
@@ -0,0 +1,13 @@
+Import('env')
+
+if not env['GLUT']:
+    Return()
+
+env = env.Clone()
+
+env.Prepend(LIBS = ['$GLUT_LIB'])
+
+env.Program(
+        target = 'fp-tri',
+        source = ['fp-tri.c'],
+    )
diff --git a/progs/fpglsl/fp-tri.c b/progs/fpglsl/fp-tri.c
new file mode 100644 (file)
index 0000000..c9b08fb
--- /dev/null
@@ -0,0 +1,415 @@
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <signal.h>
+#endif
+
+#include <GL/glew.h>
+#include <GL/glut.h>
+
+#include "readtex.c"
+
+
+#define TEXTURE_FILE "../images/bw.rgb"
+
+unsigned show_fps = 0;
+unsigned int frame_cnt = 0;
+void alarmhandler(int);
+static const char *filename = NULL;
+
+static GLuint fragShader;
+static GLuint vertShader;
+static GLuint program;
+
+
+static void usage(char *name)
+{
+   fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
+#ifndef WIN32
+   fprintf(stderr, "\n" );
+   fprintf(stderr, "options:\n");
+   fprintf(stderr, "    -fps  show frames per second\n");
+#endif
+}
+
+#ifndef WIN32
+void alarmhandler (int sig)
+{
+   if (sig == SIGALRM) {
+      printf("%d frames in 5.0 seconds = %.3f FPS\n", frame_cnt,
+             frame_cnt / 5.0);
+
+      frame_cnt = 0;
+   }
+   signal(SIGALRM, alarmhandler);
+   alarm(5);
+}
+#endif
+
+
+
+
+static void load_and_compile_shader(GLuint shader, const char *text)
+{
+   GLint stat;
+
+   glShaderSource(shader, 1, (const GLchar **) &text, NULL);
+
+   glCompileShader(shader);
+
+   glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      glGetShaderInfoLog(shader, 1000, &len, log);
+      fprintf(stderr, "fp-tri: problem compiling shader:\n%s\n", log);
+      exit(1);
+   }
+}
+
+static void read_shader(GLuint shader, const char *filename)
+{
+   const int max = 100*1000;
+   int n;
+   char *buffer = (char*) malloc(max);
+   FILE *f = fopen(filename, "r");
+   if (!f) {
+      fprintf(stderr, "fp-tri: Unable to open shader file %s\n", filename);
+      exit(1);
+   }
+
+   n = fread(buffer, 1, max, f);
+   printf("fp-tri: read %d bytes from shader file %s\n", n, filename);
+   if (n > 0) {
+      buffer[n] = 0;
+      load_and_compile_shader(shader, buffer);
+   }
+
+   fclose(f);
+   free(buffer);
+}
+
+static void check_link(GLuint prog)
+{
+   GLint stat;
+   glGetProgramiv(prog, GL_LINK_STATUS, &stat);
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      glGetProgramInfoLog(prog, 1000, &len, log);
+      fprintf(stderr, "Linker error:\n%s\n", log);
+   }
+}
+
+static void setup_uniforms()
+{
+   {
+      GLint loc1f = glGetUniformLocationARB(program, "Offset1f");
+      GLint loc2f = glGetUniformLocationARB(program, "Offset2f");
+      GLint loc4f = glGetUniformLocationARB(program, "Offset4f");
+      GLfloat vecKer[] =
+         { 1.0, 0.0, 0.0,  1.0,
+           0.0, 1.0, 0.0,  1.0,
+           1.0, 0.0, 0.0,  1.0,
+           0.0, 0.0, 0.0,  1.0
+         };
+      if (loc1f >= 0)
+         glUniform1fv(loc1f, 16, vecKer);
+
+      if (loc2f >= 0)
+         glUniform2fv(loc2f, 8, vecKer);
+
+      if (loc4f >= 0)
+         glUniform4fv(loc4f, 4, vecKer);
+
+   }
+
+   {
+      GLint loc1f = glGetUniformLocationARB(program, "KernelValue1f");
+      GLint loc2f = glGetUniformLocationARB(program, "KernelValue2f");
+      GLint loc4f = glGetUniformLocationARB(program, "KernelValue4f");
+      GLfloat vecKer[] =
+         { 1.0, 0.0, 0.0,  0.25,
+           0.0, 1.0, 0.0,  0.25,
+           0.0, 0.0, 1.0,  0.25,
+           0.0, 0.0, 0.0,  0.25,
+           0.5, 0.0, 0.0,  0.35,
+           0.0, 0.5, 0.0,  0.35,
+           0.0, 0.0, 0.5,  0.35,
+           0.0, 0.0, 0.0,  0.35
+         };
+      if (loc1f >= 0)
+         glUniform1fv(loc1f, 16, vecKer);
+
+      if (loc2f >= 0)
+         glUniform2fv(loc2f, 8, vecKer);
+
+      if (loc4f >= 0)
+         glUniform4fv(loc4f, 4, vecKer);
+   }
+}
+
+static void prepare_shaders()
+{
+   static const char *fragShaderText =
+      "void main() {\n"
+      "    gl_FragColor = gl_Color;\n"
+      "}\n";
+   static const char *vertShaderText =
+      "void main() {\n"
+      "   gl_FrontColor = gl_Color;\n"
+      "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+      "}\n";
+   fragShader = glCreateShader(GL_FRAGMENT_SHADER);
+   if (filename)
+      read_shader(fragShader, filename);
+   else
+      load_and_compile_shader(fragShader, fragShaderText);
+
+
+   vertShader = glCreateShader(GL_VERTEX_SHADER);
+   load_and_compile_shader(vertShader, vertShaderText);
+
+   program = glCreateProgram();
+   glAttachShader(program, fragShader);
+   glAttachShader(program, vertShader);
+   glLinkProgram(program);
+   check_link(program);
+   glUseProgram(program);
+
+   setup_uniforms();
+}
+
+#define LEVELS 8
+#define SIZE (1<<LEVELS)
+static int TexWidth = SIZE, TexHeight = SIZE;
+
+
+static void
+ResetTextureLevel( int i )
+{
+   GLubyte tex2d[SIZE*SIZE][4];
+      
+   {
+      GLint Width = TexWidth / (1 << i);
+      GLint Height = TexHeight / (1 << i);
+      GLint s, t;
+         
+      for (s = 0; s < Width; s++) {
+         for (t = 0; t < Height; t++) {
+            tex2d[t*Width+s][0] = ((s / 16) % 2) ? 0 : 255;
+            tex2d[t*Width+s][1] = ((t / 16) % 2) ? 0 : 255;
+            tex2d[t*Width+s][2] = 128;
+            tex2d[t*Width+s][3] = 255;
+         }
+      }
+         
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+         
+      glTexImage2D(GL_TEXTURE_2D, i, GL_RGB, Width, Height, 0,
+                   GL_RGBA, GL_UNSIGNED_BYTE, tex2d);
+   }
+}
+
+
+static void
+ResetTexture( void )
+{
+   int i;
+      
+   for (i = 0; i <= LEVELS; i++)
+   {
+      ResetTextureLevel(i);
+   }
+}
+
+static void Init( void )
+{
+   GLuint Texture;
+
+   /* Load texture */
+   glGenTextures(1, &Texture);
+   glBindTexture(GL_TEXTURE_2D, Texture);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+   if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
+      printf("Error: couldn't load texture image file %s\n", TEXTURE_FILE);
+      exit(1);
+   }
+
+
+   glGenTextures(1, &Texture);
+   glActiveTextureARB(GL_TEXTURE0_ARB + 1);
+   glBindTexture(GL_TEXTURE_2D, Texture);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+   {
+      GLubyte data[32][32];
+      int width = 32;
+      int height = 32;
+      int i;
+      int j;
+
+      for (i = 0; i < 32; i++)
+         for (j = 0; j < 32; j++)
+        {
+           /**
+            ** +-----------+
+            ** |     W     |
+            ** |  +-----+  |
+            ** |  |     |  |
+            ** |  |  B  |  |
+            ** |  |     |  |
+            ** |  +-----+  |
+            ** |           |
+            ** +-----------+
+            **/
+           int i2 = i - height / 2;
+           int j2 = j - width / 2;
+           int h8 = height / 8;
+           int w8 = width / 8;
+           if ( -h8 <= i2 && i2 <= h8 && -w8 <= j2 && j2 <= w8 ) {
+              data[i][j] = 0x00;
+           } else if ( -2 * h8 <= i2 && i2 <= 2 * h8 && -2 * w8 <= j2 && j2 <= 2 * w8 ) {
+              data[i][j] = 0x55;
+           } else if ( -3 * h8 <= i2 && i2 <= 3 * h8 && -3 * w8 <= j2 && j2 <= 3 * w8 ) {
+              data[i][j] = 0xaa;
+           } else {
+              data[i][j] = 0xff;
+           }
+        }
+
+      glTexImage2D( GL_TEXTURE_2D, 0,
+                    GL_ALPHA8,
+                    32, 32, 0,
+                    GL_ALPHA, GL_UNSIGNED_BYTE, data );
+   }
+
+   glGenTextures(1, &Texture);
+   glActiveTextureARB(GL_TEXTURE0_ARB + 2);
+   glBindTexture(GL_TEXTURE_2D, Texture);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+   ResetTexture();
+
+   glClearColor(.1, .3, .5, 0);
+}
+
+
+
+
+static void args(int argc, char *argv[])
+{
+   GLint i;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-fps") == 0) {
+         show_fps = 1;
+      }
+      else if (i == argc - 1) {
+        filename = argv[i];
+      }
+      else {
+        usage(argv[0]);
+        exit(1);
+      }
+   }
+}
+
+
+
+
+
+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);
+    glMatrixMode(GL_MODELVIEW);
+}
+
+static void CleanUp(void)
+{
+   glDeleteShader(fragShader);
+   glDeleteShader(vertShader);
+   glDeleteProgram(program);
+}
+
+static void Key(unsigned char key, int x, int y)
+{
+
+   switch (key) {
+   case 27:
+      CleanUp();
+      exit(1);
+   default:
+      break;
+   }
+
+   glutPostRedisplay();
+}
+
+static void Display(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   glUseProgram(program);
+   glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 1.0, 1.0, 0.0, 0.0);
+   glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 0.0, 0.0, 1.0, 1.0);
+   glBegin(GL_TRIANGLES);
+
+   glColor3f(0,0,1);
+   glTexCoord3f(1,1,0);
+   glVertex3f( 0.9, -0.9, -30.0);
+
+   glColor3f(1,0,0);
+   glTexCoord3f(1,-1,0);
+   glVertex3f( 0.9,  0.9, -30.0);
+
+   glColor3f(0,1,0);
+   glTexCoord3f(-1,0,0);
+   glVertex3f(-0.9,  0.0, -30.0);
+   glEnd();
+
+   glFlush();
+   if (show_fps) {
+      ++frame_cnt;
+      glutPostRedisplay();
+   }
+}
+
+
+int main(int argc, char **argv)
+{
+   glutInit(&argc, argv);
+   glutInitWindowPosition(0, 0);
+   glutInitWindowSize(250, 250);
+   glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
+   args(argc, argv);
+   glutCreateWindow(filename ? filename : "fp-tri");
+   glewInit();
+   glutReshapeFunc(Reshape);
+   glutKeyboardFunc(Key);
+   glutDisplayFunc(Display);
+   prepare_shaders();
+   Init();
+#ifndef WIN32
+   if (show_fps) {
+      signal(SIGALRM, alarmhandler);
+      alarm(5);
+   }
+#endif
+   glutMainLoop();
+   return 0;
+}
diff --git a/progs/fpglsl/mov-imm.glsl b/progs/fpglsl/mov-imm.glsl
new file mode 100644 (file)
index 0000000..cbb75ce
--- /dev/null
@@ -0,0 +1,3 @@
+void main() {
+    gl_FragColor = vec4(1,0,1,1);
+}
diff --git a/progs/fpglsl/mov.glsl b/progs/fpglsl/mov.glsl
new file mode 100644 (file)
index 0000000..4a1f185
--- /dev/null
@@ -0,0 +1,3 @@
+void main() {
+    gl_FragColor = gl_Color;
+}
diff --git a/progs/fpglsl/tex-multi.glsl b/progs/fpglsl/tex-multi.glsl
new file mode 100644 (file)
index 0000000..5220b7e
--- /dev/null
@@ -0,0 +1,15 @@
+// Multi-texture fragment shader
+// Brian Paul
+
+// Composite second texture over first.
+// We're assuming the 2nd texture has a meaningful alpha channel.
+
+uniform sampler2D tex1;
+uniform sampler2D tex2;
+
+void main()
+{
+   vec4 t1 = texture2D(tex1, gl_Color.xy);
+   vec4 t2 = texture2D(tex2, gl_Color.yz);
+   gl_FragColor = mix(t1, t2, t2.w);
+}
diff --git a/progs/fpglsl/tex.glsl b/progs/fpglsl/tex.glsl
new file mode 100644 (file)
index 0000000..4302fab
--- /dev/null
@@ -0,0 +1,6 @@
+uniform sampler2D tex1;
+
+void main()
+{
+   gl_FragColor = texture2D(tex1, gl_Color.xy);
+}
index 836396b24995a5699d2582377bc0cd35f96ce6d6..a38f411def84f77b60654c08fd85460ba763380c 100644 (file)
@@ -48,6 +48,7 @@ SOURCES = \
        floattex.c \
        fbotest1.c \
        fbotest2.c \
+       fbotest3.c \
        fillrate.c \
        fog.c \
        fogcoord.c \
index e2c6538288746cae531dd33e91e8296dab6bb251..0a11b965f791b4d98761bfd2112dc98ecad49524 100644 (file)
@@ -51,6 +51,7 @@ progs = [
     'ext422square',
     'fbotest1',
     'fbotest2',
+    'fbotest3',
     'fillrate',
     'floattex',
     'fog',
diff --git a/progs/tests/fbotest3.c b/progs/tests/fbotest3.c
new file mode 100644 (file)
index 0000000..8e288b3
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Test GL_EXT_framebuffer_object
+ * Like fbotest2.c but use a texture for the Z buffer / renderbuffer.
+ * Note: the Z texture is never resized so that limits what can be
+ * rendered if the window is resized.
+ *
+ * This tests a bug reported by Christoph Bumiller on 1 Feb 2010
+ * on mesa3d-dev.
+ *
+ * XXX this should be made into a piglit test.
+ *
+ * Brian Paul
+ * 1 Feb 2010
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glew.h>
+#include <GL/glut.h>
+
+
+static int Win = 0;
+static int Width = 400, Height = 400;
+static GLuint Tex = 0;
+static GLuint MyFB, ColorRb, DepthRb;
+static GLboolean Animate = GL_FALSE;
+static GLfloat Rotation = 0.0;
+
+
+static void
+CheckError(int line)
+{
+   GLenum err = glGetError();
+   if (err) {
+      printf("fbotest3: GL Error 0x%x at line %d\n", (int) err, line);
+   }
+}
+
+
+static void
+Display( void )
+{
+   GLubyte *buffer = malloc(Width * Height * 4);
+   GLenum status;
+
+   CheckError(__LINE__);
+
+   /* draw to user framebuffer */
+   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
+   glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
+   glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
+
+   status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      printf("fbotest3: Error: Framebuffer is incomplete!!!\n");
+   }
+
+   CheckError(__LINE__);
+
+   glClearColor(0.5, 0.5, 1.0, 0.0);
+   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+   glEnable(GL_DEPTH_TEST);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+
+   glPushMatrix();
+   glRotatef(30.0, 1, 0, 0);
+   glRotatef(Rotation, 0, 1, 0);
+   glutSolidTeapot(2.0);
+   glPopMatrix();
+
+   /* read from user framebuffer */
+   glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+   /* draw to window */
+   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+   glDisable(GL_DEPTH_TEST);  /* in case window has depth buffer */
+   glWindowPos2iARB(0, 0);
+   glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+   free(buffer);
+   glutSwapBuffers();
+   CheckError(__LINE__);
+}
+
+
+static void
+Reshape( int width, int height )
+{
+   float ar = (float) width / (float) height;
+
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+   glFrustum( -ar, ar, -1.0, 1.0, 5.0, 25.0 );
+
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+   glTranslatef( 0.0, 0.0, -15.0 );
+
+   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb);
+   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height);
+
+   Width = width;
+   Height = height;
+}
+
+
+static void
+CleanUp(void)
+{
+   glDeleteFramebuffersEXT(1, &MyFB);
+   glDeleteRenderbuffersEXT(1, &ColorRb);
+   glDeleteRenderbuffersEXT(1, &DepthRb);
+   glDeleteTextures(1, &Tex);
+   assert(!glIsFramebufferEXT(MyFB));
+   assert(!glIsRenderbufferEXT(ColorRb));
+   assert(!glIsRenderbufferEXT(DepthRb));
+   glutDestroyWindow(Win);
+   exit(0);
+}
+
+
+static void
+Idle(void)
+{
+   Rotation = glutGet(GLUT_ELAPSED_TIME) * 0.1;
+   glutPostRedisplay();
+}
+
+
+static void
+Key( unsigned char key, int x, int y )
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+   case 'a':
+      Animate = !Animate;
+      if (Animate)
+         glutIdleFunc(Idle);
+      else
+         glutIdleFunc(NULL);
+      break;
+   case 27:
+      CleanUp();
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+Init( void )
+{
+   if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
+      printf("fbotest3: GL_EXT_framebuffer_object not found!\n");
+      exit(0);
+   }
+   printf("fbotest3: GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+
+   /* create initial tex obj as an RGBA texture */
+   glGenTextures(1, &Tex);
+   glBindTexture(GL_TEXTURE_2D, Tex);
+   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+   glEnable(GL_TEXTURE_2D);
+
+   /* draw something to make sure the texture is used */
+   glBegin(GL_POINTS);
+   glVertex2f(0, 0);
+   glEnd();
+
+   /* done w/ texturing */
+   glDisable(GL_TEXTURE_2D);
+
+   /* Create my Framebuffer Object */
+   glGenFramebuffersEXT(1, &MyFB);
+   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
+   assert(glIsFramebufferEXT(MyFB));
+
+   /* Setup color renderbuffer */
+   glGenRenderbuffersEXT(1, &ColorRb);
+   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb);
+   assert(glIsRenderbufferEXT(ColorRb));
+   glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
+                                GL_RENDERBUFFER_EXT, ColorRb);
+   glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+
+   /* Setup depth renderbuffer (a texture) */
+   glGenRenderbuffersEXT(1, &DepthRb);
+   glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb);
+   assert(glIsRenderbufferEXT(DepthRb));
+   /* replace RGBA texture with Z texture */
+   glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, Width, Height, 0,
+                GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+                             GL_TEXTURE_2D, Tex, 0);
+
+   CheckError(__LINE__);
+
+   /* restore to default */
+   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+   CheckError(__LINE__);
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+   glutInit( &argc, argv );
+   glutInitWindowPosition( 0, 0 );
+   glutInitWindowSize(Width, Height);
+   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
+   Win = glutCreateWindow(argv[0]);
+   glewInit();
+   glutReshapeFunc( Reshape );
+   glutKeyboardFunc( Key );
+   glutDisplayFunc( Display );
+   if (Animate)
+      glutIdleFunc(Idle);
+   Init();
+   glutMainLoop();
+   return 0;
+}
index 1dadbf783b629697cbcb1aa72150c372508a6a72..a8a8e302e48b55bf508486f6cba310f7efb4ae0a 100644 (file)
@@ -25,6 +25,7 @@
 #include <dlfcn.h>
 #include <sys/types.h>
 #include <dirent.h>
+#include <unistd.h>
 #endif
 
 
@@ -55,21 +56,7 @@ close_library(HMODULE lib)
 static const char *
 library_suffix(void)
 {
-   return "dll";
-}
-
-
-static EGLBoolean
-make_library_path(char *buf, unsigned int size, const char *name)
-{
-   EGLBoolean need_suffix;
-   const char *suffix = ".dll";
-   int ret;
-
-   need_suffix = (strchr(name, '.') == NULL);
-   ret = snprintf(buf, size, "%s%s", name, (need_suffix) ? suffix : "");
-
-   return ((unsigned int) ret < size);
+   return ".dll";
 }
 
 
@@ -96,30 +83,13 @@ close_library(void *lib)
 static const char *
 library_suffix(void)
 {
-   return "so";
-}
-
-
-static EGLBoolean
-make_library_path(char *buf, unsigned int size, const char *name)
-{
-   EGLBoolean need_dir, need_suffix;
-   const char *suffix = ".so";
-   int ret;
-
-   need_dir = (strchr(name, '/') == NULL);
-   need_suffix = (strchr(name, '.') == NULL);
-
-   ret = snprintf(buf, size, "%s%s%s",
-         (need_dir) ? _EGL_DRIVER_SEARCH_DIR"/" : "", name,
-         (need_suffix) ? suffix : "");
-
-   return ((unsigned int) ret < size);
+   return ".so";
 }
 
 
 #else /* _EGL_PLATFORM_NO_OS */
 
+
 static const char DefaultDriverName[] = "builtin";
 
 typedef void *lib_handle;
@@ -143,14 +113,6 @@ library_suffix(void)
 }
 
 
-static EGLBoolean
-make_library_path(char *buf, unsigned int size, const char *name)
-{
-   int ret = snprintf(buf, size, name);
-   return ((unsigned int) ret < size);
-}
-
-
 #endif
 
 
@@ -299,122 +261,260 @@ _eglMatchDriver(_EGLDisplay *dpy)
 
 
 /**
- * Preload a user driver.
- *
- * A user driver can be specified by EGL_DRIVER.
+ * A loader function for use with _eglPreloadForEach.  The loader data is the
+ * filename of the driver.   This function stops on the first valid driver.
  */
 static EGLBoolean
-_eglPreloadUserDriver(void)
+_eglLoaderFile(const char *dir, size_t len, void *loader_data)
 {
-#if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS)
    _EGLDriver *drv;
    char path[1024];
-   char *env;
-
-   env = getenv("EGL_DRIVER");
-   if (!env)
-      return EGL_FALSE;
+   const char *filename = (const char *) loader_data;
+   size_t flen = strlen(filename);
 
-   if (!make_library_path(path, sizeof(path), env))
-      return EGL_FALSE;
+   /* make a full path */
+   if (len + flen + 2 > sizeof(path))
+      return EGL_TRUE;
+   if (len) {
+      memcpy(path, dir, len);
+      path[len++] = '/';
+   }
+   memcpy(path + len, filename, flen);
+   len += flen;
+   path[len] = '\0';
 
    drv = _eglLoadDriver(path, NULL);
-   if (!drv) {
-      _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver");
-      return EGL_FALSE;
+   /* fix the path and load again */
+   if (!drv && library_suffix()) {
+      const char *suffix = library_suffix();
+      size_t slen = strlen(suffix);
+      const char *p;
+      EGLBoolean need_suffix;
+
+      p = filename + flen - slen;
+      need_suffix = (p < filename || strcmp(p, suffix) != 0);
+      if (need_suffix && len + slen + 1 <= sizeof(path)) {
+         strcpy(path + len, suffix);
+         drv = _eglLoadDriver(path, NULL);
+      }
    }
+   if (!drv)
+      return EGL_TRUE;
 
+   /* remember the driver and stop */
    _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
-
-   return EGL_TRUE;
-#else /* _EGL_PLATFORM_POSIX || _EGL_PLATFORM_WINDOWS */
    return EGL_FALSE;
-#endif
 }
 
 
 /**
- * Preload display drivers.
- *
- * Display drivers are a set of drivers that support a certain display system.
- * The display system may be specified by EGL_DISPLAY.
- *
- * FIXME This makes libEGL a memory hog if an user driver is not specified and
- * there are many display drivers.
+ * A loader function for use with _eglPreloadForEach.  The loader data is the
+ * pattern (prefix) of the files to look for.
  */
 static EGLBoolean
-_eglPreloadDisplayDrivers(void)
+_eglLoaderPattern(const char *dir, size_t len, void *loader_data)
 {
 #if defined(_EGL_PLATFORM_POSIX)
-   const char *dpy, *suffix;
-   char path[1024], prefix[32];
+   const char *prefix, *suffix;
+   size_t prefix_len, suffix_len;
    DIR *dirp;
    struct dirent *dirent;
+   char path[1024];
 
-   dpy = getenv("EGL_DISPLAY");
-   if (!dpy || !dpy[0])
-      dpy = _EGL_DEFAULT_DISPLAY;
-   if (!dpy || !dpy[0])
-      return EGL_FALSE;
-
-   snprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
-   suffix = library_suffix();
+   if (len + 2 > sizeof(path))
+      return EGL_TRUE;
+   if (len) {
+      memcpy(path, dir, len);
+      path[len++] = '/';
+   }
+   path[len] = '\0';
 
-   dirp = opendir(_EGL_DRIVER_SEARCH_DIR);
+   dirp = opendir(path);
    if (!dirp)
-      return EGL_FALSE;
+      return EGL_TRUE;
+
+   prefix = (const char *) loader_data;
+   prefix_len = strlen(prefix);
+   suffix = library_suffix();
+   suffix_len = (suffix) ? strlen(suffix) : 0;
 
    while ((dirent = readdir(dirp))) {
       _EGLDriver *drv;
+      size_t dirent_len = strlen(dirent->d_name);
       const char *p;
 
       /* match the prefix */
-      if (strncmp(dirent->d_name, prefix, strlen(prefix)) != 0)
+      if (strncmp(dirent->d_name, prefix, prefix_len) != 0)
          continue;
-
       /* match the suffix */
-      p = strrchr(dirent->d_name, '.');
-      if ((p && !suffix) || (!p && suffix))
-         continue;
-      else if (p && suffix && strcmp(p + 1, suffix) != 0)
-         continue;
-
-      snprintf(path, sizeof(path),
-            _EGL_DRIVER_SEARCH_DIR"/%s", dirent->d_name);
+      if (suffix) {
+         p = dirent->d_name + dirent_len - suffix_len;
+         if (p < dirent->d_name || strcmp(p, suffix) != 0)
+            continue;
+      }
 
-      drv = _eglLoadDriver(path, NULL);
-      if (drv)
-         _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+      /* make a full path and load the driver */
+      if (len + dirent_len + 1 <= sizeof(path)) {
+         strcpy(path + len, dirent->d_name);
+         drv = _eglLoadDriver(path, NULL);
+         if (drv)
+            _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+      }
    }
 
    closedir(dirp);
 
-   return (_eglGlobal.NumDrivers > 0);
+   return EGL_TRUE;
 #else /* _EGL_PLATFORM_POSIX */
+   /* stop immediately */
    return EGL_FALSE;
 #endif
 }
 
 
 /**
- * Preload the default driver.
+ * Run the preload function on each driver directory and return the number of
+ * drivers loaded.
+ *
+ * The process may end prematurely if the callback function returns false.
+ */
+static EGLint
+_eglPreloadForEach(const char *search_path,
+                   EGLBoolean (*loader)(const char *, size_t, void *),
+                   void *loader_data)
+{
+   const char *cur, *next;
+   size_t len;
+   EGLint num_drivers = _eglGlobal.NumDrivers;
+
+   cur = search_path;
+   while (cur) {
+      next = strchr(cur, ':');
+      len = (next) ? next - cur : strlen(cur);
+
+      if (!loader(cur, len, loader))
+         break;
+
+      cur = (next) ? next + 1 : NULL;
+   }
+
+   return (_eglGlobal.NumDrivers - num_drivers);
+}
+
+
+/**
+ * Return a list of colon-separated driver directories.
+ */
+static const char *
+_eglGetSearchPath(void)
+{
+   static const char *search_path;
+
+#if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS)
+   if (!search_path) {
+      static char buffer[1024];
+      const char *p;
+      int ret;
+
+      p = getenv("EGL_DRIVERS_PATH");
+#if defined(_EGL_PLATFORM_POSIX)
+      if (p && (geteuid() != getuid() || getegid() != getgid())) {
+         _eglLog(_EGL_DEBUG,
+               "ignore EGL_DRIVERS_PATH for setuid/setgid binaries");
+         p = NULL;
+      }
+#endif /* _EGL_PLATFORM_POSIX */
+
+      if (p) {
+         ret = snprintf(buffer, sizeof(buffer),
+               "%s:%s", p, _EGL_DRIVER_SEARCH_DIR);
+         if (ret > 0 && ret < sizeof(buffer))
+            search_path = buffer;
+      }
+   }
+   if (!search_path)
+      search_path = _EGL_DRIVER_SEARCH_DIR;
+#else
+   search_path = "";
+#endif
+
+   return search_path;
+}
+
+
+/**
+ * Preload a user driver.
+ *
+ * A user driver can be specified by EGL_DRIVER.
  */
 static EGLBoolean
-_eglPreloadDefaultDriver(void)
+_eglPreloadUserDriver(void)
 {
-   _EGLDriver *drv;
-   char path[1024];
+   const char *search_path = _eglGetSearchPath();
+   char *env;
+
+   env = getenv("EGL_DRIVER");
+#if defined(_EGL_PLATFORM_POSIX)
+   if (env && strchr(env, '/')) {
+      search_path = "";
+      if ((geteuid() != getuid() || getegid() != getgid())) {
+         _eglLog(_EGL_DEBUG,
+               "ignore EGL_DRIVER for setuid/setgid binaries");
+         env = NULL;
+      }
+   }
+#endif /* _EGL_PLATFORM_POSIX */
+   if (!env)
+      return EGL_FALSE;
 
-   if (!make_library_path(path, sizeof(path), DefaultDriverName))
+   if (!_eglPreloadForEach(search_path, _eglLoaderFile, (void *) env)) {
+      _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver");
       return EGL_FALSE;
+   }
 
-   drv = _eglLoadDriver(path, NULL);
-   if (!drv)
+   return EGL_TRUE;
+}
+
+
+/**
+ * Preload display drivers.
+ *
+ * Display drivers are a set of drivers that support a certain display system.
+ * The display system may be specified by EGL_DISPLAY.
+ *
+ * FIXME This makes libEGL a memory hog if an user driver is not specified and
+ * there are many display drivers.
+ */
+static EGLBoolean
+_eglPreloadDisplayDrivers(void)
+{
+   const char *dpy;
+   char prefix[32];
+   int ret;
+
+   dpy = getenv("EGL_DISPLAY");
+   if (!dpy || !dpy[0])
+      dpy = _EGL_DEFAULT_DISPLAY;
+   if (!dpy || !dpy[0])
       return EGL_FALSE;
 
-   _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+   ret = snprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
+   if (ret < 0 || ret >= sizeof(prefix))
+      return EGL_FALSE;
 
-   return EGL_TRUE;
+   return (_eglPreloadForEach(_eglGetSearchPath(),
+            _eglLoaderPattern, (void *) prefix) > 0);
+}
+
+
+/**
+ * Preload the default driver.
+ */
+static EGLBoolean
+_eglPreloadDefaultDriver(void)
+{
+   return (_eglPreloadForEach(_eglGetSearchPath(),
+            _eglLoaderFile, (void *) DefaultDriverName) > 0);
 }
 
 
index d3084fd428390e19424b0a8c63ddf8c0657a0471..d5ddc4a6a922c25cf1bb008f6284c601e9de4522 100644 (file)
@@ -352,7 +352,10 @@ draw_find_shader_output(const struct draw_context *draw,
 
 
 /**
- * Return number of the shader outputs.
+ * Return total number of the shader outputs.  This function is similar to
+ * draw_current_shader_outputs() but this function also counts any extra
+ * vertex/geometry output attributes that may be filled in by some draw
+ * stages (such as AA point, AA line).
  *
  * If geometry shader is present, its output will be returned,
  * if not vertex shader is used.
@@ -362,8 +365,9 @@ draw_num_shader_outputs(const struct draw_context *draw)
 {
    uint count = draw->vs.vertex_shader->info.num_outputs;
 
-   /* if geometry shader is present, its outputs go to te
-    * driver, not the vertex shaders */
+   /* If a geometry shader is present, its outputs go to the
+    * driver, else the vertex shader's outputs.
+    */
    if (draw->gs.geometry_shader)
       count = draw->gs.geometry_shader->info.num_outputs;
 
@@ -374,7 +378,8 @@ draw_num_shader_outputs(const struct draw_context *draw)
 
 
 /**
- * Provide TGSI sampler objects for vertex/geometry shaders that use texture fetches.
+ * Provide TGSI sampler objects for vertex/geometry shaders that use
+ * texture fetches.
  * This might only be used by software drivers for the time being.
  */
 void
@@ -454,14 +459,27 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
 }
 
 
-int draw_current_shader_outputs(struct draw_context *draw)
+/**
+ * Return the number of output attributes produced by the geometry
+ * shader, if present.  If no geometry shader, return the number of
+ * outputs from the vertex shader.
+ * \sa draw_num_shader_outputs
+ */
+uint
+draw_current_shader_outputs(const struct draw_context *draw)
 {
    if (draw->gs.geometry_shader)
       return draw->gs.num_gs_outputs;
    return draw->vs.num_vs_outputs;
 }
 
-int draw_current_shader_position_output(struct draw_context *draw)
+
+/**
+ * Return the index of the shader output which will contain the
+ * vertex position.
+ */
+uint
+draw_current_shader_position_output(const struct draw_context *draw)
 {
    if (draw->gs.geometry_shader)
       return draw->gs.position_output;
index e58129b99d85c9f67a36245c0ad84e26b7c7d90f..8f6ca15dfa2815383a4e15fe5a501ed3081064f1 100644 (file)
 #include "draw_pipe.h"
 
 
+/** Approx number of new tokens for instructions in aa_transform_inst() */
+#define NUM_NEW_TOKENS 50
+
+
 /**
  * Max texture level for the alpha texture used for antialiasing
  */
@@ -179,12 +183,7 @@ aa_transform_decl(struct tgsi_transform_context *ctx,
 static int
 free_bit(uint bitfield)
 {
-   int i;
-   for (i = 0; i < 32; i++) {
-      if ((bitfield & (1 << i)) == 0)
-         return i;
-   }
-   return -1;
+   return ffs(~bitfield) - 1;
 }
 
 
@@ -343,11 +342,10 @@ generate_aaline_fs(struct aaline_stage *aaline)
    const struct pipe_shader_state *orig_fs = &aaline->fs->state;
    struct pipe_shader_state aaline_fs;
    struct aa_transform_context transform;
-
-#define MAX 1000
+   const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
 
    aaline_fs = *orig_fs; /* copy to init */
-   aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+   aaline_fs.tokens = tgsi_alloc_tokens(newLen);
    if (aaline_fs.tokens == NULL)
       return FALSE;
 
@@ -363,7 +361,7 @@ generate_aaline_fs(struct aaline_stage *aaline)
 
    tgsi_transform_shader(orig_fs->tokens,
                          (struct tgsi_token *) aaline_fs.tokens,
-                         MAX, &transform.base);
+                         newLen, &transform.base);
 
 #if 0 /* DEBUG */
    tgsi_dump(orig_fs->tokens, 0);
index d86717e5182bbe5e23207f0bfcfe4381dfed04c3..97f348087937d85b98c3ae8cf91c4b9c032a8a84 100644 (file)
 #include "draw_pipe.h"
 
 
+/** Approx number of new tokens for instructions in aa_transform_inst() */
+#define NUM_NEW_TOKENS 200
+
+
 /*
  * Enabling NORMALIZE might give _slightly_ better results.
  * Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or
@@ -81,16 +85,19 @@ struct aapoint_stage
 {
    struct draw_stage stage;
 
-   int psize_slot;
+   /** half of pipe_rasterizer_state::point_size */
    float radius;
 
+   /** vertex attrib slot containing point size */
+   int psize_slot;
+
    /** this is the vertex attrib slot for the new texcoords */
    uint tex_slot;
+
+   /** vertex attrib slot containing position */
    uint pos_slot;
 
-   /*
-    * Currently bound state
-    */
+   /** Currently bound fragment shader */
    struct aapoint_fragment_shader *fs;
 
    /*
@@ -491,11 +498,10 @@ generate_aapoint_fs(struct aapoint_stage *aapoint)
    const struct pipe_shader_state *orig_fs = &aapoint->fs->state;
    struct pipe_shader_state aapoint_fs;
    struct aa_transform_context transform;
-
-#define MAX 1000
+   const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
 
    aapoint_fs = *orig_fs; /* copy to init */
-   aapoint_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+   aapoint_fs.tokens = tgsi_alloc_tokens(newLen);
    if (aapoint_fs.tokens == NULL)
       return FALSE;
 
@@ -511,7 +517,7 @@ generate_aapoint_fs(struct aapoint_stage *aapoint)
 
    tgsi_transform_shader(orig_fs->tokens,
                          (struct tgsi_token *) aapoint_fs.tokens,
-                         MAX, &transform.base);
+                         newLen, &transform.base);
 
 #if 0 /* DEBUG */
    printf("draw_aapoint, orig shader:\n");
@@ -575,8 +581,8 @@ aapoint_point(struct draw_stage *stage, struct prim_header *header)
    const struct aapoint_stage *aapoint = aapoint_stage(stage);
    struct prim_header tri;
    struct vertex_header *v[4];
-   uint texPos = aapoint->tex_slot;
-   uint pos_slot = aapoint->pos_slot;
+   const uint tex_slot = aapoint->tex_slot;
+   const uint pos_slot = aapoint->pos_slot;
    float radius, *pos, *tex;
    uint i;
    float k;
@@ -643,16 +649,16 @@ aapoint_point(struct draw_stage *stage, struct prim_header *header)
    pos[1] += radius;
 
    /* new texcoords */
-   tex = v[0]->data[texPos];
+   tex = v[0]->data[tex_slot];
    ASSIGN_4V(tex, -1, -1, k, 1);
 
-   tex = v[1]->data[texPos];
+   tex = v[1]->data[tex_slot];
    ASSIGN_4V(tex,  1, -1, k, 1);
 
-   tex = v[2]->data[texPos];
+   tex = v[2]->data[tex_slot];
    ASSIGN_4V(tex,  1,  1, k, 1);
 
-   tex = v[3]->data[texPos];
+   tex = v[3]->data[tex_slot];
    ASSIGN_4V(tex, -1,  1, k, 1);
 
    /* emit 2 tris for the quad strip */
index f047d8359c42e2c42ccbcfe8da25b44b3bdcfa93..d0d99aa331aa4d08c06f30ec87b808182fd8872d 100644 (file)
@@ -50,6 +50,9 @@
 #include "draw_pipe.h"
 
 
+/** Approx number of new tokens for instructions in pstip_transform_inst() */
+#define NUM_NEW_TOKENS 50
+
 
 /**
  * Subclass of pipe_shader_state to carry extra fragment shader info.
@@ -172,12 +175,7 @@ pstip_transform_immed(struct tgsi_transform_context *ctx,
 static int
 free_bit(uint bitfield)
 {
-   int i;
-   for (i = 0; i < 32; i++) {
-      if ((bitfield & (1 << i)) == 0)
-         return i;
-   }
-   return -1;
+   return ffs(~bitfield) - 1;
 }
 
 
@@ -333,11 +331,10 @@ generate_pstip_fs(struct pstip_stage *pstip)
    /*struct draw_context *draw = pstip->stage.draw;*/
    struct pipe_shader_state pstip_fs;
    struct pstip_transform_context transform;
-
-#define MAX 1000
+   const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
 
    pstip_fs = *orig_fs; /* copy to init */
-   pstip_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
+   pstip_fs.tokens = tgsi_alloc_tokens(newLen);
    if (pstip_fs.tokens == NULL)
       return FALSE;
 
@@ -352,7 +349,7 @@ generate_pstip_fs(struct pstip_stage *pstip)
 
    tgsi_transform_shader(orig_fs->tokens,
                          (struct tgsi_token *) pstip_fs.tokens,
-                         MAX, &transform.base);
+                         newLen, &transform.base);
 
 #if 0 /* DEBUG */
    tgsi_dump(orig_fs->tokens, 0);
index 6a7190e9750b0985e6b02a14677223d106a99b76..69466d8749de7bbbdc07589fb1f754931f7047ba 100644 (file)
@@ -280,8 +280,8 @@ void draw_gs_destroy( struct draw_context *draw );
 /*******************************************************************************
  * Common shading code:
  */
-int draw_current_shader_outputs(struct draw_context *draw);
-int draw_current_shader_position_output(struct draw_context *draw);
+uint draw_current_shader_outputs(const struct draw_context *draw);
+uint draw_current_shader_position_output(const struct draw_context *draw);
 
 /*******************************************************************************
  * Vertex processing (was passthrough) code:
index fbb9aa0e63a68b73d4d707b770501d1556321df1..f7a1bb74a9d12f9858536c49dd67f84459404758 100644 (file)
@@ -264,6 +264,12 @@ static void
 micro_rcp(union tgsi_exec_channel *dst,
           const union tgsi_exec_channel *src)
 {
+#if 0 /* for debugging */
+   assert(src->f[0] != 0.0f);
+   assert(src->f[1] != 0.0f);
+   assert(src->f[2] != 0.0f);
+   assert(src->f[3] != 0.0f);
+#endif
    dst->f[0] = 1.0f / src->f[0];
    dst->f[1] = 1.0f / src->f[1];
    dst->f[2] = 1.0f / src->f[2];
@@ -284,6 +290,12 @@ static void
 micro_rsq(union tgsi_exec_channel *dst,
           const union tgsi_exec_channel *src)
 {
+#if 0 /* for debugging */
+   assert(src->f[0] != 0.0f);
+   assert(src->f[1] != 0.0f);
+   assert(src->f[2] != 0.0f);
+   assert(src->f[3] != 0.0f);
+#endif
    dst->f[0] = 1.0f / sqrtf(fabsf(src->f[0]));
    dst->f[1] = 1.0f / sqrtf(fabsf(src->f[1]));
    dst->f[2] = 1.0f / sqrtf(fabsf(src->f[2]));
@@ -450,12 +462,20 @@ static const union tgsi_exec_channel ZeroVec =
    { { 0.0, 0.0, 0.0, 0.0 } };
 
 
-#define CHECK_INF_OR_NAN(chan) do {\
-      assert(!util_is_inf_or_nan((chan)->f[0]));\
-      assert(!util_is_inf_or_nan((chan)->f[1]));\
-      assert(!util_is_inf_or_nan((chan)->f[2]));\
-      assert(!util_is_inf_or_nan((chan)->f[3]));\
-   } while (0)
+/**
+ * Assert that none of the float values in 'chan' are infinite or NaN.
+ * NaN and Inf may occur normally during program execution and should
+ * not lead to crashes, etc.  But when debugging, it's helpful to catch
+ * them.
+ */
+static INLINE void
+check_inf_or_nan(const union tgsi_exec_channel *chan)
+{
+   assert(!util_is_inf_or_nan((chan)->f[0]));
+   assert(!util_is_inf_or_nan((chan)->f[1]));
+   assert(!util_is_inf_or_nan((chan)->f[2]));
+   assert(!util_is_inf_or_nan((chan)->f[3]));
+}
 
 
 #ifdef DEBUG
@@ -1219,8 +1239,9 @@ store_dest(struct tgsi_exec_machine *mach,
    int offset = 0;  /* indirection offset */
    int index;
 
-   if (dst_datatype == TGSI_EXEC_DATA_FLOAT) {
-      CHECK_INF_OR_NAN(chan);
+   /* for debugging */
+   if (0 && dst_datatype == TGSI_EXEC_DATA_FLOAT) {
+      check_inf_or_nan(chan);
    }
 
    /* There is an extra source register that indirectly subscripts
@@ -1478,7 +1499,7 @@ emit_primitive(struct tgsi_exec_machine *mach)
 }
 
 /*
- * Fetch four texture samples using STR texture coordinates.
+ * Fetch four texture samples using STR texture coordinates.
  */
 static void
 fetch_texel( struct tgsi_sampler *sampler,
index fd37fc3079bd875440fe9ee476ef793670f7eb28..7e19e1fe36fa567c9000d8fd425e311a6a805b20 100644 (file)
@@ -284,3 +284,14 @@ tgsi_dup_tokens(const struct tgsi_token *tokens)
       memcpy(new_tokens, tokens, bytes);
    return new_tokens;
 }
+
+
+/**
+ * Allocate memory for num_tokens tokens.
+ */
+struct tgsi_token *
+tgsi_alloc_tokens(unsigned num_tokens)
+{
+   unsigned bytes = num_tokens * sizeof(struct tgsi_token);
+   return (struct tgsi_token *) MALLOC(bytes);
+}
index 8150e3cd29d16e62d284c0edacb1e70114ebfc80..b45ccee2f632557a45737f8f1390dfb1d700e56b 100644 (file)
@@ -130,6 +130,10 @@ tgsi_num_tokens(const struct tgsi_token *tokens);
 struct tgsi_token *
 tgsi_dup_tokens(const struct tgsi_token *tokens);
 
+struct tgsi_token *
+tgsi_alloc_tokens(unsigned num_tokens);
+
+
 #if defined __cplusplus
 }
 #endif
index 60a1cb1af4fb5dba16cf9a4d340f72707e20018e..27960bac221dc2ed9aa700660c06b9a024ba8bcd 100644 (file)
@@ -104,6 +104,8 @@ struct ureg_program
 
    struct {
       unsigned index;
+      unsigned semantic_name;
+      unsigned semantic_index;
    } gs_input[UREG_MAX_INPUT];
    unsigned nr_gs_inputs;
 
@@ -326,10 +328,14 @@ ureg_DECL_vs_input( struct ureg_program *ureg,
 
 struct ureg_src
 ureg_DECL_gs_input(struct ureg_program *ureg,
-                   unsigned index)
+                   unsigned index,
+                   unsigned semantic_name,
+                   unsigned semantic_index)
 {
    if (ureg->nr_gs_inputs < UREG_MAX_INPUT) {
       ureg->gs_input[ureg->nr_gs_inputs].index = index;
+      ureg->gs_input[ureg->nr_gs_inputs].semantic_name = semantic_name;
+      ureg->gs_input[ureg->nr_gs_inputs].semantic_index = semantic_index;
       ureg->nr_gs_inputs++;
    } else {
       set_bad(ureg);
@@ -1252,10 +1258,12 @@ static void emit_decls( struct ureg_program *ureg )
       }
    } else {
       for (i = 0; i < ureg->nr_gs_inputs; i++) {
-         emit_decl_range(ureg, 
-                         TGSI_FILE_INPUT, 
-                         ureg->gs_input[i].index,
-                         1);
+         emit_decl(ureg,
+                   TGSI_FILE_INPUT,
+                   ureg->gs_input[i].index,
+                   ureg->gs_input[i].semantic_name,
+                   ureg->gs_input[i].semantic_index,
+                   TGSI_INTERPOLATE_CONSTANT);
       }
    }
 
index 6198ca34642633976b4c8b1edd376b625f5ea9cb..6be66d0694b65e121b5d656bb818e299950f3efa 100644 (file)
@@ -161,7 +161,9 @@ ureg_DECL_vs_input( struct ureg_program *,
 
 struct ureg_src
 ureg_DECL_gs_input(struct ureg_program *,
-                   unsigned index);
+                   unsigned index,
+                   unsigned semantic_name,
+                   unsigned semantic_index);
 
 struct ureg_src
 ureg_DECL_system_value(struct ureg_program *,
index 9b0c86babdbb34431b5a386e7b2d8525b3456bc5..59c19ed98ddebdce55932204598bb1c15253536d 100644 (file)
@@ -16,13 +16,13 @@ import sys, os
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.append(os.path.abspath('.'))
+sys.path.append(os.path.abspath('exts'))
 
 # -- General configuration -----------------------------------------------------
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.pngmath']
+extensions = ['sphinx.ext.pngmath', 'tgsi']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
diff --git a/src/gallium/docs/source/exts/tgsi.py b/src/gallium/docs/source/exts/tgsi.py
new file mode 100644 (file)
index 0000000..e92cd5c
--- /dev/null
@@ -0,0 +1,17 @@
+# tgsi.py
+# Sphinx extension providing formatting for TGSI opcodes
+# (c) Corbin Simpson 2010
+
+import docutils.nodes
+import sphinx.addnodes
+
+def parse_opcode(env, sig, signode):
+    opcode, desc = sig.split("-", 1)
+    opcode = opcode.strip().upper()
+    desc = " (%s)" % desc.strip()
+    signode += sphinx.addnodes.desc_name(opcode, opcode)
+    signode += sphinx.addnodes.desc_annotation(desc, desc)
+    return opcode
+
+def setup(app):
+    app.add_description_unit("opcode", "opcode", "%s (TGSI opcode)", parse_opcode)
index 3e57a282fd4a9df056dec2b410f18a8f68c6df10..55a4c6990de0ffa9f24686cdc38fbe30fc0bf04c 100644 (file)
@@ -227,7 +227,7 @@ buffer_map
 
 Map a buffer into memory.
 
-**usage** is a bitmask of :ref:`PIPE_TEXTURE_USAGE` flags.
+**usage** is a bitmask of :ref:`PIPE_BUFFER_USAGE` flags.
 
 Returns a pointer to the map, or NULL if the mapping failed.
 
@@ -248,7 +248,7 @@ Flush a range of mapped memory into a buffer.
 
 The buffer must have been mapped with ``PIPE_BUFFER_USAGE_FLUSH_EXPLICIT``.
 
-**usage** is a bitmask of :ref:`PIPE_TEXTURE_USAGE` flags.
+**usage** is a bitmask of :ref:`PIPE_BUFFER_USAGE` flags.
 
 buffer_unmap
 ^^^^^^^^^^^^
index 3e702ceeda4960666196c1cd9a4830a297e24111..5478d866678bbd2309cf997b878591797b982c8a 100644 (file)
@@ -6,6 +6,23 @@ for describing shaders. Since Gallium is inherently shaderful, shaders are
 an important part of the API. TGSI is the only intermediate representation
 used by all drivers.
 
+Basics
+------
+
+All TGSI instructions, known as *opcodes*, operate on arbitrary-precision
+floating-point four-component vectors. An opcode may have up to one
+destination register, known as *dst*, and between zero and three source
+registers, called *src0* through *src2*, or simply *src* if there is only
+one.
+
+Some instructions, like :opcode:`I2F`, permit re-interpretation of vector
+components as integers. Other instructions permit using registers as
+two-component vectors with double precision; see :ref:`Double Opcodes`.
+
+When an instruction has a scalar result, the result is usually copied into
+each of the components of *dst*. When this happens, the result is said to be
+*replicated* to *dst*. :opcode:`RCP` is one such instruction.
+
 Instruction Set
 ---------------
 
@@ -13,7 +30,7 @@ From GL_NV_vertex_program
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
-ARL - Address Register Load
+.. opcode:: ARL - Address Register Load
 
 .. math::
 
@@ -26,7 +43,7 @@ ARL - Address Register Load
   dst.w = \lfloor src.w\rfloor
 
 
-MOV - Move
+.. opcode:: MOV - Move
 
 .. math::
 
@@ -39,7 +56,7 @@ MOV - Move
   dst.w = src.w
 
 
-LIT - Light Coefficients
+.. opcode:: LIT - Light Coefficients
 
 .. math::
 
@@ -52,33 +69,25 @@ LIT - Light Coefficients
   dst.w = 1
 
 
-RCP - Reciprocal
-
-.. math::
+.. opcode:: RCP - Reciprocal
 
-  dst.x = \frac{1}{src.x}
+This instruction replicates its result.
 
-  dst.y = \frac{1}{src.x}
+.. math::
 
-  dst.z = \frac{1}{src.x}
+  dst = \frac{1}{src.x}
 
-  dst.w = \frac{1}{src.x}
 
+.. opcode:: RSQ - Reciprocal Square Root
 
-RSQ - Reciprocal Square Root
+This instruction replicates its result.
 
 .. math::
 
-  dst.x = \frac{1}{\sqrt{|src.x|}}
-
-  dst.y = \frac{1}{\sqrt{|src.x|}}
-
-  dst.z = \frac{1}{\sqrt{|src.x|}}
+  dst = \frac{1}{\sqrt{|src.x|}}
 
-  dst.w = \frac{1}{\sqrt{|src.x|}}
 
-
-EXP - Approximate Exponential Base 2
+.. opcode:: EXP - Approximate Exponential Base 2
 
 .. math::
 
@@ -91,7 +100,7 @@ EXP - Approximate Exponential Base 2
   dst.w = 1
 
 
-LOG - Approximate Logarithm Base 2
+.. opcode:: LOG - Approximate Logarithm Base 2
 
 .. math::
 
@@ -104,7 +113,7 @@ LOG - Approximate Logarithm Base 2
   dst.w = 1
 
 
-MUL - Multiply
+.. opcode:: MUL - Multiply
 
 .. math::
 
@@ -117,7 +126,7 @@ MUL - Multiply
   dst.w = src0.w \times src1.w
 
 
-ADD - Add
+.. opcode:: ADD - Add
 
 .. math::
 
@@ -130,33 +139,25 @@ ADD - Add
   dst.w = src0.w + src1.w
 
 
-DP3 - 3-component Dot Product
-
-.. math::
+.. opcode:: DP3 - 3-component Dot Product
 
-  dst.x = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z
+This instruction replicates its result.
 
-  dst.y = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z
+.. math::
 
-  dst.z = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z
+  dst = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z
 
-  dst.w = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z
 
+.. opcode:: DP4 - 4-component Dot Product
 
-DP4 - 4-component Dot Product
+This instruction replicates its result.
 
 .. math::
 
-  dst.x = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src0.w \times src1.w
-
-  dst.y = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src0.w \times src1.w
+  dst = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src0.w \times src1.w
 
-  dst.z = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src0.w \times src1.w
 
-  dst.w = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src0.w \times src1.w
-
-
-DST - Distance Vector
+.. opcode:: DST - Distance Vector
 
 .. math::
 
@@ -169,7 +170,7 @@ DST - Distance Vector
   dst.w = src1.w
 
 
-MIN - Minimum
+.. opcode:: MIN - Minimum
 
 .. math::
 
@@ -182,7 +183,7 @@ MIN - Minimum
   dst.w = min(src0.w, src1.w)
 
 
-MAX - Maximum
+.. opcode:: MAX - Maximum
 
 .. math::
 
@@ -195,7 +196,7 @@ MAX - Maximum
   dst.w = max(src0.w, src1.w)
 
 
-SLT - Set On Less Than
+.. opcode:: SLT - Set On Less Than
 
 .. math::
 
@@ -208,7 +209,7 @@ SLT - Set On Less Than
   dst.w = (src0.w < src1.w) ? 1 : 0
 
 
-SGE - Set On Greater Equal Than
+.. opcode:: SGE - Set On Greater Equal Than
 
 .. math::
 
@@ -221,7 +222,7 @@ SGE - Set On Greater Equal Than
   dst.w = (src0.w >= src1.w) ? 1 : 0
 
 
-MAD - Multiply And Add
+.. opcode:: MAD - Multiply And Add
 
 .. math::
 
@@ -234,7 +235,7 @@ MAD - Multiply And Add
   dst.w = src0.w \times src1.w + src2.w
 
 
-SUB - Subtract
+.. opcode:: SUB - Subtract
 
 .. math::
 
@@ -247,7 +248,7 @@ SUB - Subtract
   dst.w = src0.w - src1.w
 
 
-LRP - Linear Interpolate
+.. opcode:: LRP - Linear Interpolate
 
 .. math::
 
@@ -260,7 +261,7 @@ LRP - Linear Interpolate
   dst.w = src0.w \times src1.w + (1 - src0.w) \times src2.w
 
 
-CND - Condition
+.. opcode:: CND - Condition
 
 .. math::
 
@@ -273,7 +274,7 @@ CND - Condition
   dst.w = (src2.w > 0.5) ? src0.w : src1.w
 
 
-DP2A - 2-component Dot Product And Add
+.. opcode:: DP2A - 2-component Dot Product And Add
 
 .. math::
 
@@ -286,7 +287,7 @@ DP2A - 2-component Dot Product And Add
   dst.w = src0.x \times src1.x + src0.y \times src1.y + src2.x
 
 
-FRAC - Fraction
+.. opcode:: FRAC - Fraction
 
 .. math::
 
@@ -299,7 +300,7 @@ FRAC - Fraction
   dst.w = src.w - \lfloor src.w\rfloor
 
 
-CLAMP - Clamp
+.. opcode:: CLAMP - Clamp
 
 .. math::
 
@@ -312,9 +313,9 @@ CLAMP - Clamp
   dst.w = clamp(src0.w, src1.w, src2.w)
 
 
-FLR - Floor
+.. opcode:: FLR - Floor
 
-This is identical to ARL.
+This is identical to :opcode:`ARL`.
 
 .. math::
 
@@ -327,7 +328,7 @@ This is identical to ARL.
   dst.w = \lfloor src.w\rfloor
 
 
-ROUND - Round
+.. opcode:: ROUND - Round
 
 .. math::
 
@@ -340,45 +341,33 @@ ROUND - Round
   dst.w = round(src.w)
 
 
-EX2 - Exponential Base 2
+.. opcode:: EX2 - Exponential Base 2
 
-.. math::
+This instruction replicates its result.
 
-  dst.x = 2^{src.x}
-
-  dst.y = 2^{src.x}
+.. math::
 
-  dst.z = 2^{src.x}
+  dst = 2^{src.x}
 
-  dst.w = 2^{src.x}
 
+.. opcode:: LG2 - Logarithm Base 2
 
-LG2 - Logarithm Base 2
+This instruction replicates its result.
 
 .. math::
 
-  dst.x = \log_2{src.x}
-
-  dst.y = \log_2{src.x}
-
-  dst.z = \log_2{src.x}
+  dst = \log_2{src.x}
 
-  dst.w = \log_2{src.x}
 
+.. opcode:: POW - Power
 
-POW - Power
+This instruction replicates its result.
 
 .. math::
 
-  dst.x = src0.x^{src1.x}
+  dst = src0.x^{src1.x}
 
-  dst.y = src0.x^{src1.x}
-
-  dst.z = src0.x^{src1.x}
-
-  dst.w = src0.x^{src1.x}
-
-XPD - Cross Product
+.. opcode:: XPD - Cross Product
 
 .. math::
 
@@ -391,7 +380,7 @@ XPD - Cross Product
   dst.w = 1
 
 
-ABS - Absolute
+.. opcode:: ABS - Absolute
 
 .. math::
 
@@ -404,48 +393,36 @@ ABS - Absolute
   dst.w = |src.w|
 
 
-RCC - Reciprocal Clamped
+.. opcode:: RCC - Reciprocal Clamped
+
+This instruction replicates its result.
 
 XXX cleanup on aisle three
 
 .. math::
 
-  dst.x = (1 / src.x) > 0 ? clamp(1 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1 / src.x, -1.884467e+019, -5.42101e-020)
-
-  dst.y = (1 / src.x) > 0 ? clamp(1 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1 / src.x, -1.884467e+019, -5.42101e-020)
-
-  dst.z = (1 / src.x) > 0 ? clamp(1 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1 / src.x, -1.884467e+019, -5.42101e-020)
+  dst = (1 / src.x) > 0 ? clamp(1 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1 / src.x, -1.884467e+019, -5.42101e-020)
 
-  dst.w = (1 / src.x) > 0 ? clamp(1 / src.x, 5.42101e-020, 1.884467e+019) : clamp(1 / src.x, -1.884467e+019, -5.42101e-020)
 
+.. opcode:: DPH - Homogeneous Dot Product
 
-DPH - Homogeneous Dot Product
+This instruction replicates its result.
 
 .. math::
 
-  dst.x = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src1.w
+  dst = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src1.w
 
-  dst.y = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src1.w
 
-  dst.z = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src1.w
+.. opcode:: COS - Cosine
 
-  dst.w = src0.x \times src1.x + src0.y \times src1.y + src0.z \times src1.z + src1.w
-
-
-COS - Cosine
+This instruction replicates its result.
 
 .. math::
 
-  dst.x = \cos{src.x}
-
-  dst.y = \cos{src.x}
-
-  dst.z = \cos{src.x}
+  dst = \cos{src.x}
 
-  dst.w = \cos{src.x}
 
-
-DDX - Derivative Relative To X
+.. opcode:: DDX - Derivative Relative To X
 
 .. math::
 
@@ -458,7 +435,7 @@ DDX - Derivative Relative To X
   dst.w = partialx(src.w)
 
 
-DDY - Derivative Relative To Y
+.. opcode:: DDY - Derivative Relative To Y
 
 .. math::
 
@@ -471,32 +448,32 @@ DDY - Derivative Relative To Y
   dst.w = partialy(src.w)
 
 
-KILP - Predicated Discard
+.. opcode:: KILP - Predicated Discard
 
   discard
 
 
-PK2H - Pack Two 16-bit Floats
+.. opcode:: PK2H - Pack Two 16-bit Floats
 
   TBD
 
 
-PK2US - Pack Two Unsigned 16-bit Scalars
+.. opcode:: PK2US - Pack Two Unsigned 16-bit Scalars
 
   TBD
 
 
-PK4B - Pack Four Signed 8-bit Scalars
+.. opcode:: PK4B - Pack Four Signed 8-bit Scalars
 
   TBD
 
 
-PK4UB - Pack Four Unsigned 8-bit Scalars
+.. opcode:: PK4UB - Pack Four Unsigned 8-bit Scalars
 
   TBD
 
 
-RFL - Reflection Vector
+.. opcode:: RFL - Reflection Vector
 
 .. math::
 
@@ -508,10 +485,12 @@ RFL - Reflection Vector
 
   dst.w = 1
 
-Considered for removal.
+.. note::
+
+   Considered for removal.
 
 
-SEQ - Set On Equal
+.. opcode:: SEQ - Set On Equal
 
 .. math::
 
@@ -524,21 +503,20 @@ SEQ - Set On Equal
   dst.w = (src0.w == src1.w) ? 1 : 0
 
 
-SFL - Set On False
+.. opcode:: SFL - Set On False
 
-.. math::
+This instruction replicates its result.
 
-  dst.x = 0
+.. math::
 
-  dst.y = 0
+  dst = 0
 
-  dst.z = 0
+.. note::
 
-  dst.w = 0
+   Considered for removal.
 
-Considered for removal.
 
-SGT - Set On Greater Than
+.. opcode:: SGT - Set On Greater Than
 
 .. math::
 
@@ -551,20 +529,16 @@ SGT - Set On Greater Than
   dst.w = (src0.w > src1.w) ? 1 : 0
 
 
-SIN - Sine
+.. opcode:: SIN - Sine
 
-.. math::
+This instruction replicates its result.
 
-  dst.x = \sin{src.x}
-
-  dst.y = \sin{src.x}
-
-  dst.z = \sin{src.x}
+.. math::
 
-  dst.w = \sin{src.x}
+  dst = \sin{src.x}
 
 
-SLE - Set On Less Equal Than
+.. opcode:: SLE - Set On Less Equal Than
 
 .. math::
 
@@ -577,7 +551,7 @@ SLE - Set On Less Equal Than
   dst.w = (src0.w <= src1.w) ? 1 : 0
 
 
-SNE - Set On Not Equal
+.. opcode:: SNE - Set On Not Equal
 
 .. math::
 
@@ -590,59 +564,63 @@ SNE - Set On Not Equal
   dst.w = (src0.w != src1.w) ? 1 : 0
 
 
-STR - Set On True
+.. opcode:: STR - Set On True
 
-.. math::
+This instruction replicates its result.
 
-  dst.x = 1
-
-  dst.y = 1
-
-  dst.z = 1
+.. math::
 
-  dst.w = 1
+  dst = 1
 
 
-TEX - Texture Lookup
+.. opcode:: TEX - Texture Lookup
 
   TBD
 
 
-TXD - Texture Lookup with Derivatives
+.. opcode:: TXD - Texture Lookup with Derivatives
 
   TBD
 
 
-TXP - Projective Texture Lookup
+.. opcode:: TXP - Projective Texture Lookup
 
   TBD
 
 
-UP2H - Unpack Two 16-Bit Floats
+.. opcode:: UP2H - Unpack Two 16-Bit Floats
 
   TBD
 
-  Considered for removal.
+.. note::
 
-UP2US - Unpack Two Unsigned 16-Bit Scalars
+   Considered for removal.
+
+.. opcode:: UP2US - Unpack Two Unsigned 16-Bit Scalars
 
   TBD
 
-  Considered for removal.
+.. note::
+
+   Considered for removal.
 
-UP4B - Unpack Four Signed 8-Bit Values
+.. opcode:: UP4B - Unpack Four Signed 8-Bit Values
 
   TBD
 
-  Considered for removal.
+.. note::
+
+   Considered for removal.
 
-UP4UB - Unpack Four Unsigned 8-Bit Scalars
+.. opcode:: UP4UB - Unpack Four Unsigned 8-Bit Scalars
 
   TBD
 
-  Considered for removal.
+.. note::
 
-X2D - 2D Coordinate Transformation
+   Considered for removal.
+
+.. opcode:: X2D - 2D Coordinate Transformation
 
 .. math::
 
@@ -654,20 +632,24 @@ X2D - 2D Coordinate Transformation
 
   dst.w = src0.y + src1.x \times src2.z + src1.y \times src2.w
 
-Considered for removal.
+.. note::
+
+   Considered for removal.
 
 
 From GL_NV_vertex_program2
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
-ARA - Address Register Add
+.. opcode:: ARA - Address Register Add
 
   TBD
 
-  Considered for removal.
+.. note::
 
-ARR - Address Register Load With Round
+   Considered for removal.
+
+.. opcode:: ARR - Address Register Load With Round
 
 .. math::
 
@@ -680,26 +662,28 @@ ARR - Address Register Load With Round
   dst.w = round(src.w)
 
 
-BRA - Branch
+.. opcode:: BRA - Branch
 
   pc = target
 
-  Considered for removal.
+.. note::
+
+   Considered for removal.
 
-CAL - Subroutine Call
+.. opcode:: CAL - Subroutine Call
 
   push(pc)
   pc = target
 
 
-RET - Subroutine Call Return
+.. opcode:: RET - Subroutine Call Return
 
   pc = pop()
 
   Potential restrictions:  
   * Only occurs at end of function.
 
-SSG - Set Sign
+.. opcode:: SSG - Set Sign
 
 .. math::
 
@@ -712,7 +696,7 @@ SSG - Set Sign
   dst.w = (src.w > 0) ? 1 : (src.w < 0) ? -1 : 0
 
 
-CMP - Compare
+.. opcode:: CMP - Compare
 
 .. math::
 
@@ -725,7 +709,7 @@ CMP - Compare
   dst.w = (src0.w < 0) ? src1.w : src2.w
 
 
-KIL - Conditional Discard
+.. opcode:: KIL - Conditional Discard
 
 .. math::
 
@@ -734,7 +718,7 @@ KIL - Conditional Discard
   endif
 
 
-SCS - Sine Cosine
+.. opcode:: SCS - Sine Cosine
 
 .. math::
 
@@ -747,12 +731,12 @@ SCS - Sine Cosine
   dst.y = 1
 
 
-TXB - Texture Lookup With Bias
+.. opcode:: TXB - Texture Lookup With Bias
 
   TBD
 
 
-NRM - 3-component Vector Normalise
+.. opcode:: NRM - 3-component Vector Normalise
 
 .. math::
 
@@ -765,7 +749,7 @@ NRM - 3-component Vector Normalise
   dst.w = 1
 
 
-DIV - Divide
+.. opcode:: DIV - Divide
 
 .. math::
 
@@ -778,35 +762,31 @@ DIV - Divide
   dst.w = \frac{src0.w}{src1.w}
 
 
-DP2 - 2-component Dot Product
-
-.. math::
-
-  dst.x = src0.x \times src1.x + src0.y \times src1.y
+.. opcode:: DP2 - 2-component Dot Product
 
-  dst.y = src0.x \times src1.x + src0.y \times src1.y
+This instruction replicates its result.
 
-  dst.z = src0.x \times src1.x + src0.y \times src1.y
+.. math::
 
-  dst.w = src0.x \times src1.x + src0.y \times src1.y
+  dst = src0.x \times src1.x + src0.y \times src1.y
 
 
-TXL - Texture Lookup With LOD
+.. opcode:: TXL - Texture Lookup With LOD
 
   TBD
 
 
-BRK - Break
+.. opcode:: BRK - Break
 
   TBD
 
 
-IF - If
+.. opcode:: IF - If
 
   TBD
 
 
-BGNFOR - Begin a For-Loop
+.. opcode:: BGNFOR - Begin a For-Loop
 
   dst.x = floor(src.x)
   dst.y = floor(src.y)
@@ -819,25 +799,31 @@ BGNFOR - Begin a For-Loop
   Note: The destination must be a loop register.
         The source must be a constant register.
 
-  Considered for cleanup / removal.
+.. note::
 
+   Considered for cleanup.
 
-REP - Repeat
+.. note::
+
+   Considered for removal.
+
+
+.. opcode:: REP - Repeat
 
   TBD
 
 
-ELSE - Else
+.. opcode:: ELSE - Else
 
   TBD
 
 
-ENDIF - End If
+.. opcode:: ENDIF - End If
 
   TBD
 
 
-ENDFOR - End a For-Loop
+.. opcode:: ENDFOR - End a For-Loop
 
   dst.x = dst.x + dst.z
   dst.y = dst.y - 1.0
@@ -848,30 +834,48 @@ ENDFOR - End a For-Loop
 
   Note: The destination must be a loop register.
 
-  Considered for cleanup / removal.
+.. note::
+
+   Considered for cleanup.
+
+.. note::
 
-ENDREP - End Repeat
+   Considered for removal.
+
+.. opcode:: ENDREP - End Repeat
 
   TBD
 
 
-PUSHA - Push Address Register On Stack
+.. opcode:: PUSHA - Push Address Register On Stack
 
   push(src.x)
   push(src.y)
   push(src.z)
   push(src.w)
 
-  Considered for cleanup / removal.
+.. note::
+
+   Considered for cleanup.
+
+.. note::
 
-POPA - Pop Address Register From Stack
+   Considered for removal.
+
+.. opcode:: POPA - Pop Address Register From Stack
 
   dst.w = pop()
   dst.z = pop()
   dst.y = pop()
   dst.x = pop()
 
-  Considered for cleanup / removal.
+.. note::
+
+   Considered for cleanup.
+
+.. note::
+
+   Considered for removal.
 
 
 From GL_NV_gpu_program4
@@ -879,7 +883,7 @@ From GL_NV_gpu_program4
 
 Support for these opcodes indicated by a special pipe capability bit (TBD).
 
-CEIL - Ceiling
+.. opcode:: CEIL - Ceiling
 
 .. math::
 
@@ -892,7 +896,7 @@ CEIL - Ceiling
   dst.w = \lceil src.w\rceil
 
 
-I2F - Integer To Float
+.. opcode:: I2F - Integer To Float
 
 .. math::
 
@@ -905,7 +909,7 @@ I2F - Integer To Float
   dst.w = (float) src.w
 
 
-NOT - Bitwise Not
+.. opcode:: NOT - Bitwise Not
 
 .. math::
 
@@ -918,7 +922,7 @@ NOT - Bitwise Not
   dst.w = ~src.w
 
 
-TRUNC - Truncate
+.. opcode:: TRUNC - Truncate
 
 .. math::
 
@@ -931,7 +935,7 @@ TRUNC - Truncate
   dst.w = trunc(src.w)
 
 
-SHL - Shift Left
+.. opcode:: SHL - Shift Left
 
 .. math::
 
@@ -944,7 +948,7 @@ SHL - Shift Left
   dst.w = src0.w << src1.x
 
 
-SHR - Shift Right
+.. opcode:: SHR - Shift Right
 
 .. math::
 
@@ -957,7 +961,7 @@ SHR - Shift Right
   dst.w = src0.w >> src1.x
 
 
-AND - Bitwise And
+.. opcode:: AND - Bitwise And
 
 .. math::
 
@@ -970,7 +974,7 @@ AND - Bitwise And
   dst.w = src0.w & src1.w
 
 
-OR - Bitwise Or
+.. opcode:: OR - Bitwise Or
 
 .. math::
 
@@ -983,7 +987,7 @@ OR - Bitwise Or
   dst.w = src0.w | src1.w
 
 
-MOD - Modulus
+.. opcode:: MOD - Modulus
 
 .. math::
 
@@ -996,7 +1000,7 @@ MOD - Modulus
   dst.w = src0.w \bmod src1.w
 
 
-XOR - Bitwise Xor
+.. opcode:: XOR - Bitwise Xor
 
 .. math::
 
@@ -1009,7 +1013,7 @@ XOR - Bitwise Xor
   dst.w = src0.w \oplus src1.w
 
 
-SAD - Sum Of Absolute Differences
+.. opcode:: SAD - Sum Of Absolute Differences
 
 .. math::
 
@@ -1022,17 +1026,17 @@ SAD - Sum Of Absolute Differences
   dst.w = |src0.w - src1.w| + src2.w
 
 
-TXF - Texel Fetch
+.. opcode:: TXF - Texel Fetch
 
   TBD
 
 
-TXQ - Texture Size Query
+.. opcode:: TXQ - Texture Size Query
 
   TBD
 
 
-CONT - Continue
+.. opcode:: CONT - Continue
 
   TBD
 
@@ -1041,12 +1045,12 @@ From GL_NV_geometry_program4
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
-EMIT - Emit
+.. opcode:: EMIT - Emit
 
   TBD
 
 
-ENDPRIM - End Primitive
+.. opcode:: ENDPRIM - End Primitive
 
   TBD
 
@@ -1055,66 +1059,64 @@ From GLSL
 ^^^^^^^^^^
 
 
-BGNLOOP - Begin a Loop
+.. opcode:: BGNLOOP - Begin a Loop
 
   TBD
 
 
-BGNSUB - Begin Subroutine
+.. opcode:: BGNSUB - Begin Subroutine
 
   TBD
 
 
-ENDLOOP - End a Loop
+.. opcode:: ENDLOOP - End a Loop
 
   TBD
 
 
-ENDSUB - End Subroutine
+.. opcode:: ENDSUB - End Subroutine
 
   TBD
 
 
-NOP - No Operation
+.. opcode:: NOP - No Operation
 
   Do nothing.
 
 
-NRM4 - 4-component Vector Normalise
-
-.. math::
+.. opcode:: NRM4 - 4-component Vector Normalise
 
-  dst.x = \frac{src.x}{src.x \times src.x + src.y \times src.y + src.z \times src.z + src.w \times src.w}
+This instruction replicates its result.
 
-  dst.y = \frac{src.y}{src.x \times src.x + src.y \times src.y + src.z \times src.z + src.w \times src.w}
-
-  dst.z = \frac{src.z}{src.x \times src.x + src.y \times src.y + src.z \times src.z + src.w \times src.w}
+.. math::
 
-  dst.w = \frac{src.w}{src.x \times src.x + src.y \times src.y + src.z \times src.z + src.w \times src.w}
+  dst = \frac{src.x}{src.x \times src.x + src.y \times src.y + src.z \times src.z + src.w \times src.w}
 
 
 ps_2_x
 ^^^^^^^^^^^^
 
 
-CALLNZ - Subroutine Call If Not Zero
+.. opcode:: CALLNZ - Subroutine Call If Not Zero
 
   TBD
 
 
-IFC - If
+.. opcode:: IFC - If
 
   TBD
 
 
-BREAKC - Break Conditional
+.. opcode:: BREAKC - Break Conditional
 
   TBD
 
+.. _doubleopcodes:
+
 Double Opcodes
 ^^^^^^^^^^^^^^^
 
-DADD - Add Double
+.. opcode:: DADD - Add Double
 
 .. math::
 
@@ -1123,7 +1125,7 @@ DADD - Add Double
   dst.zw = src0.zw + src1.zw
 
 
-DDIV - Divide Double
+.. opcode:: DDIV - Divide Double
 
 .. math::
 
@@ -1131,7 +1133,7 @@ DDIV - Divide Double
 
   dst.zw = src0.zw / src1.zw
 
-DSEQ - Set Double on Equal
+.. opcode:: DSEQ - Set Double on Equal
 
 .. math::
 
@@ -1139,7 +1141,7 @@ DSEQ - Set Double on Equal
 
   dst.zw = src0.zw == src1.zw ? 1.0F : 0.0F
 
-DSLT - Set Double on Less than
+.. opcode:: DSLT - Set Double on Less than
 
 .. math::
 
@@ -1147,7 +1149,7 @@ DSLT - Set Double on Less than
 
   dst.zw = src0.zw < src1.zw ? 1.0F : 0.0F
 
-DFRAC - Double Fraction
+.. opcode:: DFRAC - Double Fraction
 
 .. math::
 
@@ -1156,7 +1158,7 @@ DFRAC - Double Fraction
   dst.zw = src.zw - \lfloor src.zw\rfloor
 
 
-DFRACEXP - Convert Double Number to Fractional and Integral Components
+.. opcode:: DFRACEXP - Convert Double Number to Fractional and Integral Components
 
 .. math::
 
@@ -1164,7 +1166,7 @@ DFRACEXP - Convert Double Number to Fractional and Integral Components
 
   dst0.zw = frexp(src.zw, dst1.zw)
 
-DLDEXP - Multiple Double Number by Integral Power of 2
+.. opcode:: DLDEXP - Multiple Double Number by Integral Power of 2
 
 .. math::
 
@@ -1172,7 +1174,7 @@ DLDEXP - Multiple Double Number by Integral Power of 2
 
   dst.zw = ldexp(src0.zw, src1.zw)
 
-DMIN - Minimum Double
+.. opcode:: DMIN - Minimum Double
 
 .. math::
 
@@ -1180,7 +1182,7 @@ DMIN - Minimum Double
 
   dst.zw = min(src0.zw, src1.zw)
 
-DMAX - Maximum Double
+.. opcode:: DMAX - Maximum Double
 
 .. math::
 
@@ -1188,7 +1190,7 @@ DMAX - Maximum Double
 
   dst.zw = max(src0.zw, src1.zw)
 
-DMUL - Multiply Double
+.. opcode:: DMUL - Multiply Double
 
 .. math::
 
@@ -1197,7 +1199,7 @@ DMUL - Multiply Double
   dst.zw = src0.zw \times src1.zw
 
 
-DMAD - Multiply And Add Doubles
+.. opcode:: DMAD - Multiply And Add Doubles
 
 .. math::
 
@@ -1206,7 +1208,7 @@ DMAD - Multiply And Add Doubles
   dst.zw = src0.zw \times src1.zw + src2.zw
 
 
-DRCP - Reciprocal Double
+.. opcode:: DRCP - Reciprocal Double
 
 .. math::
 
@@ -1214,7 +1216,7 @@ DRCP - Reciprocal Double
 
    dst.zw = \frac{1}{src.zw}
 
-DSQRT - Square root double
+.. opcode:: DSQRT - Square root double
 
 .. math::
 
@@ -1269,20 +1271,8 @@ Keywords
 
   discard           Discard fragment.
 
-  dst               First destination register.
-
-  dst0              First destination register.
-
   pc                Program counter.
 
-  src               First source register.
-
-  src0              First source register.
-
-  src1              Second source register.
-
-  src2              Third source register.
-
   target            Label of target instruction.
 
 
@@ -1441,3 +1431,43 @@ GL_ARB_fragment_coord_conventions extension.
 
 DirectX 9 uses INTEGER.
 DirectX 10 uses HALF_INTEGER.
+
+
+
+Texture Sampling and Texture Formats
+------------------------------------
+
+This table shows how texture image components are returned as (x,y,z,w) tuples
+by TGSI texture instructions, such as :opcode:`TEX`, :opcode:`TXD`, and
+:opcode:`TXP`. For reference, OpenGL and Direct3D conventions are shown as
+well.
+
++--------------------+--------------+--------------------+--------------+
+| Texture Components | Gallium      | OpenGL             | Direct3D 9   |
++====================+==============+====================+==============+
+| R                  | XXX TBD      | (r, 0, 0, 1)       | (r, 1, 1, 1) |
++--------------------+--------------+--------------------+--------------+
+| RG                 | XXX TBD      | (r, g, 0, 1)       | (r, g, 1, 1) |
++--------------------+--------------+--------------------+--------------+
+| RGB                | (r, g, b, 1) | (r, g, b, 1)       | (r, g, b, 1) |
++--------------------+--------------+--------------------+--------------+
+| RGBA               | (r, g, b, a) | (r, g, b, a)       | (r, g, b, a) |
++--------------------+--------------+--------------------+--------------+
+| A                  | (0, 0, 0, a) | (0, 0, 0, a)       | (0, 0, 0, a) |
++--------------------+--------------+--------------------+--------------+
+| L                  | (l, l, l, 1) | (l, l, l, 1)       | (l, l, l, 1) |
++--------------------+--------------+--------------------+--------------+
+| LA                 | (l, l, l, a) | (l, l, l, a)       | (l, l, l, a) |
++--------------------+--------------+--------------------+--------------+
+| I                  | (i, i, i, i) | (i, i, i, i)       | N/A          |
++--------------------+--------------+--------------------+--------------+
+| UV                 | XXX TBD      | (0, 0, 0, 1)       | (u, v, 1, 1) |
+|                    |              | [#envmap-bumpmap]_ |              |
++--------------------+--------------+--------------------+--------------+
+| Z                  | XXX TBD      | (z, z, z, 1)       | (0, z, 0, 1) |
+|                    |              | [#depth-tex-mode]_ |              |
++--------------------+--------------+--------------------+--------------+
+
+.. [#envmap-bumpmap] http://www.opengl.org/registry/specs/ATI/envmap_bumpmap.txt
+.. [#depth-tex-mode] the default is (z, z, z, 1) but may also be (0, 0, 0, z)
+   or (z, z, z, z) depending on the value of GL_DEPTH_TEXTURE_MODE.
index 0155b9be50100e7b90e2cf5e68a44525b3bc5319..353ae176fdb33bb9e3f45441ab152a4fafeaf811 100644 (file)
@@ -65,7 +65,7 @@ llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe)
       /* compute vertex layout now */
       const struct lp_fragment_shader *lpfs = llvmpipe->fs;
       struct vertex_info *vinfo_vbuf = &llvmpipe->vertex_info_vbuf;
-      const uint num = draw_current_shader_outputs(llvmpipe->draw);
+      const uint num = draw_num_shader_outputs(llvmpipe->draw);
       uint i;
 
       /* Tell draw_vbuf to simply emit the whole post-xform vertex
index 60ea9c171d5d9eef7090986dcf8080ce4fb1d8f7..39bcdc8fe60c9e6837262a366dd2fd7b376d8bcf 100644 (file)
@@ -77,17 +77,21 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
 static void find_output_registers(struct r300_fragment_program_compiler * compiler,
                                   struct r300_fragment_shader * fs)
 {
-    unsigned i;
+    unsigned i, colorbuf_count = 0;
 
     /* Mark the outputs as not present initially */
-    compiler->OutputColor = fs->info.num_outputs;
+    compiler->OutputColor[0] = fs->info.num_outputs;
+    compiler->OutputColor[1] = fs->info.num_outputs;
+    compiler->OutputColor[2] = fs->info.num_outputs;
+    compiler->OutputColor[3] = fs->info.num_outputs;
     compiler->OutputDepth = fs->info.num_outputs;
 
     /* Now see where they really are. */
     for(i = 0; i < fs->info.num_outputs; ++i) {
         switch(fs->info.output_semantic_name[i]) {
             case TGSI_SEMANTIC_COLOR:
-                compiler->OutputColor = i;
+                compiler->OutputColor[colorbuf_count] = i;
+                colorbuf_count++;
                 break;
             case TGSI_SEMANTIC_POSITION:
                 compiler->OutputDepth = i;
index 453fb1accc26b50e74fdffe6e88fa8d66f3326d5..b37be261337f416eb883a80a32a28829bc7d5b3e 100644 (file)
@@ -37,24 +37,31 @@ unsigned r300_texture_get_stride(struct r300_screen* screen,
 unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
                                  unsigned zslice, unsigned face);
 
-/* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */
+/* Translate a pipe_format into a useful texture format for sampling.
+ *
+ * R300_EASY_TX_FORMAT swizzles the texture.
+ * Note the signature of R300_EASY_TX_FORMAT:
+ *   R300_EASY_TX_FORMAT(B, G, R, A, FORMAT);
+ *
+ * The FORMAT specifies how the texture sampler will treat the texture, and
+ * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
 static INLINE uint32_t r300_translate_texformat(enum pipe_format format)
 {
     switch (format) {
         /* X8 */
         case PIPE_FORMAT_A8_UNORM:
+            return R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8);
         case PIPE_FORMAT_I8_UNORM:
             return R300_EASY_TX_FORMAT(X, X, X, X, X8);
         case PIPE_FORMAT_L8_UNORM:
             return R300_EASY_TX_FORMAT(X, X, X, ONE, X8);
         /* X16 */
         case PIPE_FORMAT_R16_UNORM:
+        case PIPE_FORMAT_Z16_UNORM:
             return R300_EASY_TX_FORMAT(X, X, X, X, X16);
         case PIPE_FORMAT_R16_SNORM:
             return R300_EASY_TX_FORMAT(X, X, X, X, X16) |
                 R300_TX_FORMAT_SIGNED;
-        case PIPE_FORMAT_Z16_UNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, X, X16);
         /* Y8X8 */
         case PIPE_FORMAT_A8L8_UNORM:
             return R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8);
index a792c2cf9890c77a14be9d05a43ed07f31632517..941ec17016b1e670890d309a7c786a9486264f70 100644 (file)
@@ -201,6 +201,8 @@ static void transform_srcreg(
     struct rc_src_register * dst,
     struct tgsi_full_src_register * src)
 {
+    unsigned i, j;
+
     dst->File = translate_register_file(src->Register.File);
     dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
     dst->RelAddr = src->Register.Indirect;
@@ -210,6 +212,21 @@ static void transform_srcreg(
     dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9;
     dst->Abs = src->Register.Absolute;
     dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0;
+
+    if (src->Register.File == TGSI_FILE_IMMEDIATE) {
+        for (i = 0; i < ttr->imms_to_swizzle_count; i++) {
+            if (ttr->imms_to_swizzle[i].index == src->Register.Index) {
+                dst->File = RC_FILE_TEMPORARY;
+                dst->Index = 0;
+                dst->Swizzle = 0;
+                for (j = 0; j < 4; j++) {
+                    dst->Swizzle |= GET_SWZ(ttr->imms_to_swizzle[i].swizzle,
+                        tgsi_util_get_full_src_register_swizzle(src, j)) << (j * 3);
+                }
+                break;
+            }
+        }
+    }
 }
 
 static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src,
@@ -277,21 +294,45 @@ static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_inst
                           &ttr->compiler->Program.ShadowSamplers);
 }
 
-static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm)
+static void handle_immediate(struct tgsi_to_rc * ttr,
+                             struct tgsi_full_immediate * imm,
+                             unsigned index)
 {
     struct rc_constant constant;
-    int i;
+    unsigned swizzle = 0;
+    boolean can_swizzle = TRUE;
+    unsigned i;
 
-    constant.Type = RC_CONSTANT_IMMEDIATE;
-    constant.Size = 4;
-    for(i = 0; i < 4; ++i)
-        constant.u.Immediate[i] = imm->u[i].Float;
-    rc_constants_add(&ttr->compiler->Program.Constants, &constant);
+    for (i = 0; i < 4; i++) {
+        if (imm->u[i].Float == 0.0f) {
+            swizzle |= RC_SWIZZLE_ZERO << (i * 3);
+        } else if (imm->u[i].Float == 0.5f) {
+            swizzle |= RC_SWIZZLE_HALF << (i * 3);
+        } else if (imm->u[i].Float == 1.0f) {
+            swizzle |= RC_SWIZZLE_ONE << (i * 3);
+        } else {
+            can_swizzle = FALSE;
+            break;
+        }
+    }
+
+    if (can_swizzle) {
+        ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].index = index;
+        ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].swizzle = swizzle;
+        ttr->imms_to_swizzle_count++;
+    } else {
+        constant.Type = RC_CONSTANT_IMMEDIATE;
+        constant.Size = 4;
+        for(i = 0; i < 4; ++i)
+            constant.u.Immediate[i] = imm->u[i].Float;
+        rc_constants_add(&ttr->compiler->Program.Constants, &constant);
+    }
 }
 
 void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
 {
     struct tgsi_parse_context parser;
+    unsigned imm_index = 0;
     int i;
 
     /* Allocate constants placeholders.
@@ -308,6 +349,9 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
 
     ttr->immediate_offset = ttr->compiler->Program.Constants.Count;
 
+    ttr->imms_to_swizzle = malloc(ttr->info->immediate_count * sizeof(struct swizzled_imms));
+    ttr->imms_to_swizzle_count = 0;
+
     tgsi_parse_init(&parser, tokens);
 
     while (!tgsi_parse_end_of_tokens(&parser)) {
@@ -317,7 +361,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
             case TGSI_TOKEN_TYPE_DECLARATION:
                 break;
             case TGSI_TOKEN_TYPE_IMMEDIATE:
-                handle_immediate(ttr, &parser.FullToken.FullImmediate);
+                handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index);
+                imm_index++;
                 break;
             case TGSI_TOKEN_TYPE_INSTRUCTION:
                 transform_instruction(ttr, &parser.FullToken.FullInstruction);
@@ -327,6 +372,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
 
     tgsi_parse_free(&parser);
 
+    free(ttr->imms_to_swizzle);
+
     rc_calculate_inputs_outputs(ttr->compiler);
 }
 
index 93e90ec6d2cc1ef1793ed4db0ea3d15a3261d05e..39b473c7bf5cc35762c67c034fb8920bbd4fb680 100644 (file)
@@ -29,11 +29,18 @@ struct tgsi_full_declaration;
 struct tgsi_shader_info;
 struct tgsi_token;
 
+struct swizzled_imms {
+    unsigned index;
+    unsigned swizzle;
+};
+
 struct tgsi_to_rc {
     struct radeon_compiler * compiler;
     const struct tgsi_shader_info * info;
 
     int immediate_offset;
+    struct swizzled_imms * imms_to_swizzle;
+    unsigned imms_to_swizzle_count;
 };
 
 void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens);
index f6856a5f69102dd22bf1d5649840f5057a1bbdaf..d2eda7324ca22a887d50fed9e71b1b7244a31697 100644 (file)
@@ -30,7 +30,6 @@
 #include "pipe/p_shader_tokens.h"
 #include "draw/draw_context.h"
 #include "draw/draw_vertex.h"
-#include "draw/draw_private.h"
 #include "sp_context.h"
 #include "sp_screen.h"
 #include "sp_state.h"
@@ -67,7 +66,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe)
       /* compute vertex layout now */
       const struct sp_fragment_shader *spfs = softpipe->fs;
       struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
-      const uint num = draw_current_shader_outputs(softpipe->draw);
+      const uint num = draw_num_shader_outputs(softpipe->draw);
       uint i;
 
       /* Tell draw_vbuf to simply emit the whole post-xform vertex
index e88ef8d8fe3a955fd2a1fd4e35630283c579a4d2..c4181c3f5b77e26acd05c3a974c7be1f42702d1d 100644 (file)
@@ -215,7 +215,6 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen )
    svga->state.hw_draw.num_views = 0;
 
    svga->dirty = ~0;
-   svga->state.white_fs_id = SVGA3D_INVALID_ID;
 
    LIST_INITHEAD(&svga->dirty_buffers);
 
index 66259fd01034a1fc9f81b247361a579e7ca7c417..ba86256eb268d507fbadc07b4735e152a7b0d015 100644 (file)
@@ -327,10 +327,6 @@ struct svga_context
 
       unsigned texture_timestamp;
 
-      /* Internally generated shaders:
-       */
-      unsigned white_fs_id;
-
       /* 
        */
       struct svga_sw_state          sw;
index adc7120217b400df007cbb4d75aff4c18759de1d..2973444d0ab084e8b89cd86a477a573599f9daa3 100644 (file)
@@ -108,70 +108,6 @@ fail:
    return ret;
 }
 
-/* The blend workaround for simulating logicop xor behaviour requires
- * that the incoming fragment color be white.  This change achieves
- * that by hooking up a hard-wired fragment shader that just emits
- * color 1,1,1,1
- *   
- * This is a slightly incomplete solution as it assumes that the
- * actual bound shader has no other effects beyond generating a
- * fragment color.  In particular shaders containing TEXKIL and/or
- * depth-write will not have the correct behaviour, nor will those
- * expecting to use alphatest.
- *   
- * These are avoidable issues, but they are not much worse than the
- * unavoidable ones associated with this technique, so it's not clear
- * how much effort should be expended trying to resolve them - the
- * ultimate result will still not be correct in most cases.
- *
- * Shader below was generated with:
- *   SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt
- */
-static int emit_white_fs( struct svga_context *svga )
-{
-   int ret = PIPE_ERROR;
-
-   /* ps_3_0
-    * def c0, 1.000000, 0.000000, 0.000000, 1.000000
-    * mov oC0, c0.x
-    * end
-    */
-   static const unsigned white_tokens[] = {
-      0xffff0300,
-      0x05000051,
-      0xa00f0000,
-      0x3f800000,
-      0x00000000,
-      0x00000000,
-      0x3f800000,
-      0x02000001,
-      0x800f0800,
-      0xa0000000,
-      0x0000ffff,
-   };
-
-   assert(SVGA3D_INVALID_ID == UTIL_BITMASK_INVALID_INDEX);
-   svga->state.white_fs_id = util_bitmask_add(svga->fs_bm);
-   if(svga->state.white_fs_id == SVGA3D_INVALID_ID)
-      goto no_fs_id;
-
-   ret = SVGA3D_DefineShader(svga->swc, 
-                             svga->state.white_fs_id,
-                             SVGA3D_SHADERTYPE_PS,
-                             white_tokens, 
-                             sizeof(white_tokens));
-   if (ret)
-      goto no_definition;
-
-   return 0;
-
-no_definition:
-   util_bitmask_clear(svga->fs_bm, svga->state.white_fs_id);
-   svga->state.white_fs_id = SVGA3D_INVALID_ID;
-no_fs_id:
-   return ret;
-}
-
 
 /* SVGA_NEW_TEXTURE_BINDING
  * SVGA_NEW_RAST
@@ -199,6 +135,23 @@ static int make_fs_key( const struct svga_context *svga,
                        PIPE_WINDING_CW);
    }
 
+   /* The blend workaround for simulating logicop xor behaviour
+    * requires that the incoming fragment color be white.  This change
+    * achieves that by creating a varient of the current fragment
+    * shader that overrides all output colors with 1,1,1,1
+    *   
+    * This will work for most shaders, including those containing
+    * TEXKIL and/or depth-write.  However, it will break on the
+    * combination of xor-logicop plus alphatest.
+    *
+    * Ultimately, we could implement alphatest in the shader using
+    * texkil prior to overriding the outgoing fragment color.
+    *   
+    * SVGA_NEW_BLEND
+    */
+   if (svga->curr.blend->need_white_fragments) {
+      key->white_fragments = 1;
+   }
    
    /* XXX: want to limit this to the textures that the shader actually
     * refers to.
@@ -238,40 +191,29 @@ static int emit_hw_fs( struct svga_context *svga,
    unsigned id = SVGA3D_INVALID_ID;
    int ret = 0;
 
+   struct svga_fragment_shader *fs = svga->curr.fs;
+   struct svga_fs_compile_key key;
+
    /* SVGA_NEW_BLEND
+    * SVGA_NEW_TEXTURE_BINDING
+    * SVGA_NEW_RAST
+    * SVGA_NEW_NEED_SWTNL
+    * SVGA_NEW_SAMPLER
     */
-   if (svga->curr.blend->need_white_fragments) {
-      if (svga->state.white_fs_id == SVGA3D_INVALID_ID) {
-         ret = emit_white_fs( svga );
-         if (ret)
-            return ret;
-      }
-      id = svga->state.white_fs_id;
-   }
-   else {
-      struct svga_fragment_shader *fs = svga->curr.fs;
-      struct svga_fs_compile_key key;
-
-      /* SVGA_NEW_TEXTURE_BINDING
-       * SVGA_NEW_RAST
-       * SVGA_NEW_NEED_SWTNL
-       * SVGA_NEW_SAMPLER
-       */
-      ret = make_fs_key( svga, &key );
+   ret = make_fs_key( svga, &key );
+   if (ret)
+      return ret;
+
+   result = search_fs_key( fs, &key );
+   if (!result) {
+      ret = compile_fs( svga, fs, &key, &result );
       if (ret)
          return ret;
-
-      result = search_fs_key( fs, &key );
-      if (!result) {
-         ret = compile_fs( svga, fs, &key, &result );
-         if (ret)
-            return ret;
-      }
-
-      assert (result);
-      id = result->id;
    }
 
+   assert (result);
+   id = result->id;
+
    assert(id != SVGA3D_INVALID_ID);
 
    if (result != svga->state.hw_draw.fs) {
index 737a2213af5c8e9b7f39da50f2250d43037b995b..063c9cf4221574cf06e8aeca54cd646c40a81d7c 100644 (file)
@@ -49,6 +49,7 @@ struct svga_fs_compile_key
 {
    unsigned light_twoside:1;
    unsigned front_cw:1;
+   unsigned white_fragments:1;
    unsigned num_textures:8;
    unsigned num_unnormalized_coords:8;
    struct {
index 43fc0d3235969bb24a3e3403f2c0c92843679b58..73102a72a8379910ac749d301cad4cfc4f4c2780 100644 (file)
@@ -194,8 +194,19 @@ static boolean ps30_output( struct svga_shader_emitter *emit,
 
    switch (semantic.Name) {
    case TGSI_SEMANTIC_COLOR:
-      emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, 
-                                            semantic.Index );
+      if (emit->unit == PIPE_SHADER_FRAGMENT &&
+          emit->key.fkey.white_fragments) {
+
+         emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
+                                               emit->nr_hw_temp++ );
+         emit->temp_col[idx] = emit->output_map[idx];
+         emit->true_col[idx] = dst_register( SVGA3DREG_COLOROUT, 
+                                              semantic.Index );
+      }
+      else {
+         emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, 
+                                               semantic.Index );
+      }
       break;
    case TGSI_SEMANTIC_POSITION:
       emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
index 2557824293ee042f5055dfacc070890a7b656900..e8f75485d5559ac6f698e8570a3c1d410625d2a3 100644 (file)
@@ -79,6 +79,8 @@ struct svga_shader_emitter
 
    int ps30_input_count;
 
+   int dynamic_branching_level;
+
    boolean in_main_func;
 
    boolean created_zero_immediate;
@@ -199,6 +201,23 @@ static INLINE boolean emit_op3( struct svga_shader_emitter *emit,
 }
 
 
+static INLINE boolean emit_op4( struct svga_shader_emitter *emit,
+                                SVGA3dShaderInstToken inst,
+                                SVGA3dShaderDestToken dest,
+                                struct src_register src0,
+                                struct src_register src1,
+                                struct src_register src2,
+                                struct src_register src3)
+{
+   return (emit_instruction( emit, inst ) &&
+           emit_dst( emit, dest ) &&
+           emit_src( emit, src0 ) &&
+           emit_src( emit, src1 ) &&
+           emit_src( emit, src2 ) &&
+           emit_src( emit, src3 ));
+}
+
+
 #define TRANSLATE_SWIZZLE(x,y,z,w)  ((x) | ((y) << 2) | ((z) << 4) | ((w) << 6))
 #define SWIZZLE_XYZW  \
  TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_W)
index dc5eb8fc60656ff2d0101cd0d55e31e866f919ba..be821e98217168306958e62b8bb14a981312f68f 100644 (file)
@@ -46,8 +46,6 @@ translate_opcode(
    case TGSI_OPCODE_ABS:        return SVGA3DOP_ABS;
    case TGSI_OPCODE_ADD:        return SVGA3DOP_ADD;
    case TGSI_OPCODE_BREAKC:     return SVGA3DOP_BREAKC;
-   case TGSI_OPCODE_DDX:        return SVGA3DOP_DSX;
-   case TGSI_OPCODE_DDY:        return SVGA3DOP_DSY;
    case TGSI_OPCODE_DP2A:       return SVGA3DOP_DP2ADD;
    case TGSI_OPCODE_DP3:        return SVGA3DOP_DP3;
    case TGSI_OPCODE_DP4:        return SVGA3DOP_DP4;
@@ -415,6 +413,88 @@ static boolean submit_op3( struct svga_shader_emitter *emit,
 }
 
 
+
+
+/* SVGA shaders may not refer to >1 constant register in a single
+ * instruction.  This function checks for that usage and inserts a
+ * move to temporary if detected.
+ */
+static boolean submit_op4( struct svga_shader_emitter *emit,
+                           SVGA3dShaderInstToken inst,
+                           SVGA3dShaderDestToken dest,
+                           struct src_register src0,
+                           struct src_register src1,
+                           struct src_register src2,
+                           struct src_register src3)
+{
+   SVGA3dShaderDestToken temp0;
+   SVGA3dShaderDestToken temp3;
+   boolean need_temp0 = FALSE;
+   boolean need_temp3 = FALSE;
+   SVGA3dShaderRegType type0, type1, type2, type3;
+
+   temp0.value = 0;
+   temp3.value = 0;
+   type0 = SVGA3dShaderGetRegType( src0.base.value );
+   type1 = SVGA3dShaderGetRegType( src1.base.value );
+   type2 = SVGA3dShaderGetRegType( src2.base.value );
+   type3 = SVGA3dShaderGetRegType( src2.base.value );
+
+   /* Make life a little easier - this is only used by the TXD
+    * instruction which is guaranteed not to have a constant/input reg
+    * in one slot at least:
+    */
+   assert(type1 == SVGA3DREG_SAMPLER);
+
+   if (type0 == SVGA3DREG_CONST &&
+       ((type3 == SVGA3DREG_CONST && src0.base.num != src3.base.num) ||
+        (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num)))
+      need_temp0 = TRUE;
+
+   if (type3 == SVGA3DREG_CONST &&
+       (type2 == SVGA3DREG_CONST && src3.base.num != src2.base.num))
+      need_temp3 = TRUE;
+
+   if (type0 == SVGA3DREG_INPUT &&
+       ((type3 == SVGA3DREG_INPUT && src0.base.num != src3.base.num) ||
+        (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num)))
+      need_temp0 = TRUE;
+
+   if (type3 == SVGA3DREG_INPUT &&
+       (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num))
+      need_temp3 = TRUE;
+
+   if (need_temp0)
+   {
+      temp0 = get_temp( emit );
+      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 ))
+         return FALSE;
+         
+      src0 = src( temp0 );
+   }
+
+   if (need_temp3)
+   {
+      temp3 = get_temp( emit );
+
+      if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp3, src3 ))
+         return FALSE;
+
+      src3 = src( temp3 );
+   }
+
+   if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 ))
+      return FALSE;
+
+   if (need_temp3)
+      release_temp( emit, temp3 );
+   if (need_temp0)
+      release_temp( emit, temp0 );
+   return TRUE;
+}
+
+
 static boolean emit_def_const( struct svga_shader_emitter *emit,
                                SVGA3dShaderConstType type,
                                unsigned idx,
@@ -660,6 +740,8 @@ static boolean emit_if(struct svga_shader_emitter *emit,
    if_token.control = SVGA3DOPCOMPC_NE;
    zero = scalar(zero, TGSI_SWIZZLE_X);
 
+   emit->dynamic_branching_level++;
+
    return (emit_instruction( emit, if_token ) &&
            emit_src( emit, src ) &&
            emit_src( emit, zero ) );
@@ -668,6 +750,8 @@ static boolean emit_if(struct svga_shader_emitter *emit,
 static boolean emit_endif(struct svga_shader_emitter *emit,
                        const struct tgsi_full_instruction *insn)
 {
+   emit->dynamic_branching_level--;
+
    return (emit_instruction( emit,
                              inst_token( SVGA3DOP_ENDIF )));
 }
@@ -1011,10 +1095,10 @@ static boolean emit_kilp(struct svga_shader_emitter *emit,
 {
    SVGA3dShaderInstToken inst;
    SVGA3dShaderDestToken temp;
-   struct src_register one = get_zero_immediate( emit );
+   struct src_register one = scalar( get_zero_immediate( emit ),
+                                     TGSI_SWIZZLE_W );
 
    inst = inst_token( SVGA3DOP_TEXKILL );
-   one = scalar( one, TGSI_SWIZZLE_W );
 
    /* texkill doesn't allow negation on the operand so lets move
     * negation of {1} to a temp register */
@@ -1169,41 +1253,79 @@ static boolean emit_tex2(struct svga_shader_emitter *emit,
                          SVGA3dShaderDestToken dst )
 {
    SVGA3dShaderInstToken inst;
-   struct src_register src0;
-   struct src_register src1;
-
+   struct src_register texcoord;
+   struct src_register sampler;
+   SVGA3dShaderDestToken tmp;
+   
    inst.value = 0;
-   inst.op = SVGA3DOP_TEX;
 
    switch (insn->Instruction.Opcode) {
    case TGSI_OPCODE_TEX:
+      inst.op = SVGA3DOP_TEX;
       break;
    case TGSI_OPCODE_TXP:
+      inst.op = SVGA3DOP_TEX;
       inst.control = SVGA3DOPCONT_PROJECT;
       break;
    case TGSI_OPCODE_TXB:
+      inst.op = SVGA3DOP_TEX;
       inst.control = SVGA3DOPCONT_BIAS;
       break;
+   case TGSI_OPCODE_TXL:
+      inst.op = SVGA3DOP_TEXLDL;
+      break;
    default:
       assert(0);
       return FALSE;
    }
 
-   src0 = translate_src_register( emit, &insn->Src[0] );
-   src1 = translate_src_register( emit, &insn->Src[1] );
+   texcoord = translate_src_register( emit, &insn->Src[0] );
+   sampler = translate_src_register( emit, &insn->Src[1] );
 
-   if (emit->key.fkey.tex[src1.base.num].unnormalized) {
-      struct src_register wh = get_tex_dimensions( emit, src1.base.num );
-      SVGA3dShaderDestToken tmp = get_temp( emit );
+   if (emit->key.fkey.tex[sampler.base.num].unnormalized ||
+       emit->dynamic_branching_level > 0)
+      tmp = get_temp( emit );
+
+   /* Can't do mipmapping inside dynamic branch constructs.  Force LOD
+    * zero in that case.
+    */
+   if (emit->dynamic_branching_level > 0 &&
+       inst.op == SVGA3DOP_TEX &&
+       SVGA3dShaderGetRegType(texcoord.base.value) == SVGA3DREG_TEMP) {
+      struct src_register zero = get_zero_immediate( emit );
+
+      /* MOV  tmp, texcoord */
+      if (!submit_op1( emit,
+                       inst_token( SVGA3DOP_MOV ),
+                       tmp,
+                       texcoord ))
+         return FALSE;
+
+      /* MOV  tmp.w, zero */
+      if (!submit_op1( emit, 
+                       inst_token( SVGA3DOP_MOV ),
+                       writemask( tmp, TGSI_WRITEMASK_W ), 
+                       scalar( zero, TGSI_SWIZZLE_X )))
+         return FALSE;
+      
+      texcoord = src( tmp );
+      inst.op = SVGA3DOP_TEXLDL;
+   }
+
+   /* Explicit normalization of texcoords:
+    */
+   if (emit->key.fkey.tex[sampler.base.num].unnormalized) {
+      struct src_register wh = get_tex_dimensions( emit, sampler.base.num );
 
       /* MUL  tmp, SRC0, WH */
       if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ),
-                       tmp, src0, wh ))
+                       tmp, texcoord, wh ))
          return FALSE;
-      src0 = src( tmp );
+
+      texcoord = src( tmp );
    }
 
-   return submit_op2( emit, inst, dst, src0, src1 );
+   return submit_op2( emit, inst, dst, texcoord, sampler );
 }
 
 
@@ -1211,31 +1333,33 @@ static boolean emit_tex2(struct svga_shader_emitter *emit,
 
 /* Translate texture instructions to SVGA3D representation.
  */
-static boolean emit_tex3(struct svga_shader_emitter *emit,
+static boolean emit_tex4(struct svga_shader_emitter *emit,
                          const struct tgsi_full_instruction *insn,
                          SVGA3dShaderDestToken dst )
 {
    SVGA3dShaderInstToken inst;
-   struct src_register src0;
-   struct src_register src1;
-   struct src_register src2;
+   struct src_register texcoord;
+   struct src_register ddx;
+   struct src_register ddy;
+   struct src_register sampler;
+
+   texcoord = translate_src_register( emit, &insn->Src[0] );
+   ddx      = translate_src_register( emit, &insn->Src[1] );
+   ddy      = translate_src_register( emit, &insn->Src[2] );
+   sampler  = translate_src_register( emit, &insn->Src[3] );
 
    inst.value = 0;
 
    switch (insn->Instruction.Opcode) {
    case TGSI_OPCODE_TXD: 
-      inst.op = SVGA3DOP_TEXLDD;
-      break;
-   case TGSI_OPCODE_TXL:
-      inst.op = SVGA3DOP_TEXLDL;
+      inst.op = SVGA3DOP_TEXLDD; /* 4 args! */
       break;
+   default:
+      assert(0);
+      return FALSE;
    }
 
-   src0 = translate_src_register( emit, &insn->Src[0] );
-   src1 = translate_src_register( emit, &insn->Src[1] );
-   src2 = translate_src_register( emit, &insn->Src[2] );
-
-   return submit_op3( emit, inst, dst, src0, src1, src2 );
+   return submit_op4( emit, inst, dst, texcoord, sampler, ddx, ddy );
 }
 
 
@@ -1271,12 +1395,12 @@ static boolean emit_tex(struct svga_shader_emitter *emit,
    case TGSI_OPCODE_TEX:
    case TGSI_OPCODE_TXB:
    case TGSI_OPCODE_TXP:
+   case TGSI_OPCODE_TXL:
       if (!emit_tex2( emit, insn, tex_result ))
          return FALSE;
       break;
-   case TGSI_OPCODE_TXL:
    case TGSI_OPCODE_TXD:
-      if (!emit_tex3( emit, insn, tex_result ))
+      if (!emit_tex4( emit, insn, tex_result ))
          return FALSE;
       break;
    default:
@@ -1330,6 +1454,8 @@ static boolean emit_bgnloop2( struct svga_shader_emitter *emit,
    struct src_register loop_reg = src_register( SVGA3DREG_LOOP, 0 );
    struct src_register const_int = get_loop_const( emit );
 
+   emit->dynamic_branching_level++;
+
    return (emit_instruction( emit, inst ) &&
            emit_src( emit, loop_reg ) &&
            emit_src( emit, const_int ) );
@@ -1339,6 +1465,9 @@ static boolean emit_endloop2( struct svga_shader_emitter *emit,
                               const struct tgsi_full_instruction *insn )
 {
    SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_ENDLOOP );
+
+   emit->dynamic_branching_level--;
+
    return emit_instruction( emit, inst );
 }
 
@@ -1398,6 +1527,46 @@ static boolean emit_simple_instruction(struct svga_shader_emitter *emit,
    }
 }
 
+
+static boolean emit_deriv(struct svga_shader_emitter *emit,
+                          const struct tgsi_full_instruction *insn )
+{
+   if (emit->dynamic_branching_level > 0 &&
+       insn->Src[0].Register.File == TGSI_FILE_TEMPORARY) 
+   {
+      struct src_register zero = get_zero_immediate( emit );
+      SVGA3dShaderDestToken dst = 
+         translate_dst_register( emit, insn, 0 );
+
+      /* Deriv opcodes not valid inside dynamic branching, workaround
+       * by zeroing out the destination.
+       */
+      if (!submit_op1(emit, 
+                      inst_token( SVGA3DOP_MOV ), 
+                      dst,
+                      scalar(zero, TGSI_SWIZZLE_X)))
+         return FALSE;
+      
+      return TRUE;
+   }
+   else {
+      unsigned opcode;
+
+      switch (insn->Instruction.Opcode) {
+      case TGSI_OPCODE_DDX:
+         opcode = SVGA3DOP_DSX;
+         break;
+      case TGSI_OPCODE_DDY:
+         opcode = SVGA3DOP_DSY;
+         break;
+      default:
+         return FALSE;
+      }
+
+      return emit_simple_instruction( emit, opcode, insn );
+   }
+}
+
 static boolean emit_arl(struct svga_shader_emitter *emit,
                         const struct tgsi_full_instruction *insn)
 {
@@ -2002,6 +2171,10 @@ static boolean svga_emit_instruction( struct svga_shader_emitter *emit,
    case TGSI_OPCODE_TXD:
       return emit_tex( emit, insn );
 
+   case TGSI_OPCODE_DDX:
+   case TGSI_OPCODE_DDY:
+      return emit_deriv( emit, insn );
+
    case TGSI_OPCODE_BGNSUB:
       return emit_bgnsub( emit, position, insn );
 
@@ -2254,11 +2427,28 @@ static boolean emit_ps_postamble( struct svga_shader_emitter *emit )
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
       if (SVGA3dShaderGetRegType(emit->true_col[i].value) != 0) {
 
-         if (!submit_op1( emit,
-                          inst_token(SVGA3DOP_MOV),
-                          emit->true_col[i],
-                          src(emit->temp_col[i]) ))
-            return FALSE;
+         /* Potentially override output colors with white for XOR
+          * logicop workaround.
+          */
+         if (emit->unit == PIPE_SHADER_FRAGMENT &&
+             emit->key.fkey.white_fragments) {
+
+            struct src_register one = scalar( get_zero_immediate( emit ),
+                                              TGSI_SWIZZLE_W );
+
+            if (!submit_op1( emit,
+                             inst_token(SVGA3DOP_MOV),
+                             emit->true_col[i],
+                             one ))
+               return FALSE;
+         }
+         else {
+            if (!submit_op1( emit,
+                             inst_token(SVGA3DOP_MOV),
+                             emit->true_col[i],
+                             src(emit->temp_col[i]) ))
+               return FALSE;
+         }
       }
    }
 
@@ -2467,6 +2657,9 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
       if (emit->key.fkey.light_twoside)
          return TRUE;
 
+      if (emit->key.fkey.white_fragments)
+         return TRUE;
+
       if (emit->emit_frontface)
          return TRUE;
 
@@ -2476,6 +2669,10 @@ needs_to_create_zero( struct svga_shader_emitter *emit )
    }
 
    if (emit->info.opcode_count[TGSI_OPCODE_IF] >= 1 ||
+       emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1 ||
+       emit->info.opcode_count[TGSI_OPCODE_BGNFOR] >= 1 ||
+       emit->info.opcode_count[TGSI_OPCODE_DDX] >= 1 ||
+       emit->info.opcode_count[TGSI_OPCODE_DDY] >= 1 ||
        emit->info.opcode_count[TGSI_OPCODE_SGE] >= 1 ||
        emit->info.opcode_count[TGSI_OPCODE_SGT] >= 1 ||
        emit->info.opcode_count[TGSI_OPCODE_SLE] >= 1 ||
@@ -2702,6 +2899,8 @@ boolean svga_shader_emit_instructions( struct svga_shader_emitter *emit,
          goto done;
    }
 
+   assert(emit->dynamic_branching_level == 0);
+
    /* Need to terminate the whole shader:
     */
    ret = emit_instruction( emit, inst_token( SVGA3DOP_END ) );
index 8a73e81d4ac0d94c432162e0a4bf642ea768d707..30e2c347bd4a32df0c9a22b5d18e8b14e08d1e1c 100644 (file)
@@ -1087,8 +1087,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
                        _EGLSurface *surf, EGLint buffer)
 {
    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
-   _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
-   struct egl_g3d_context *gctx = egl_g3d_context(ctx);
+   _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
+   struct egl_g3d_context *gctx;
    enum pipe_format target_format;
    int target;
 
@@ -1118,6 +1118,11 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
       return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
    }
 
+   if (!es1)
+      return EGL_TRUE;
+   if (!gsurf->render_surface)
+      return EGL_FALSE;
+
    /* flush properly if the surface is bound */
    if (gsurf->base.CurrentContext) {
       gctx = egl_g3d_context(gsurf->base.CurrentContext);
@@ -1125,14 +1130,11 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
             PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
    }
 
-   if (gctx) {
-      if (!gsurf->render_surface)
-         return EGL_FALSE;
+   gctx = egl_g3d_context(es1);
+   gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
+         target, gsurf->base.MipmapLevel, target_format);
 
-      gctx->stapi->st_bind_texture_surface(gsurf->render_surface,
-            target, gsurf->base.MipmapLevel, target_format);
-      gsurf->base.BoundToTexture = EGL_TRUE;
-   }
+   gsurf->base.BoundToTexture = EGL_TRUE;
 
    return EGL_TRUE;
 }
index 2f394ad6c555586e4a1c57a3a8a1eb9377ecce2b..27773467fa8090ac18ca49b15e7446d00a02198d 100644 (file)
 #ifndef ASM_FILL_H
 #define ASM_FILL_H
 
-static const char solid_fill_asm[] =
-   "MOV %s, CONST[0]\n";
-
-
-static const char linear_grad_asm[] =
-   "MOV TEMP[0].xy, IN[0]\n"
-   "MOV TEMP[0].z, CONST[1].yyyy\n"
-   "DP3 TEMP[1], CONST[2], TEMP[0]\n"
-   "DP3 TEMP[2], CONST[3], TEMP[0]\n"
-   "DP3 TEMP[3], CONST[4], TEMP[0]\n"
-   "RCP TEMP[3], TEMP[3]\n"
-   "MUL TEMP[1], TEMP[1], TEMP[3]\n"
-   "MUL TEMP[2], TEMP[2], TEMP[3]\n"
-   "MOV TEMP[4].x, TEMP[1]\n"
-   "MOV TEMP[4].y, TEMP[2]\n"
-   "MUL TEMP[0], CONST[0].yyyy, TEMP[4].yyyy\n"
-   "MAD TEMP[1], CONST[0].xxxx, TEMP[4].xxxx, TEMP[0]\n"
-   "MUL TEMP[2], TEMP[1], CONST[0].zzzz\n"
-   "TEX %s, TEMP[2], SAMP[0], 1D\n";
-
-static const char radial_grad_asm[] =
-   "MOV TEMP[0].xy, IN[0]\n"
-   "MOV TEMP[0].z, CONST[1].yyyy\n"
-   "DP3 TEMP[1], CONST[2], TEMP[0]\n"
-   "DP3 TEMP[2], CONST[3], TEMP[0]\n"
-   "DP3 TEMP[3], CONST[4], TEMP[0]\n"
-   "RCP TEMP[3], TEMP[3]\n"
-   "MUL TEMP[1], TEMP[1], TEMP[3]\n"
-   "MUL TEMP[2], TEMP[2], TEMP[3]\n"
-   "MOV TEMP[5].x, TEMP[1]\n"
-   "MOV TEMP[5].y, TEMP[2]\n"
-   "MUL TEMP[0], CONST[0].yyyy, TEMP[5].yyyy\n"
-   "MAD TEMP[1], CONST[0].xxxx, TEMP[5].xxxx, TEMP[0]\n"
-   "ADD TEMP[1], TEMP[1], TEMP[1]\n"
-   "MUL TEMP[3], TEMP[5].yyyy, TEMP[5].yyyy\n"
-   "MAD TEMP[4], TEMP[5].xxxx, TEMP[5].xxxx, TEMP[3]\n"
-   "MOV TEMP[4], -TEMP[4]\n"
-   "MUL TEMP[2], CONST[0].zzzz, TEMP[4]\n"
-   "MUL TEMP[0], CONST[1].wwww, TEMP[2]\n"
-   "MUL TEMP[3], TEMP[1], TEMP[1]\n"
-   "SUB TEMP[2], TEMP[3], TEMP[0]\n"
-   "RSQ TEMP[2], |TEMP[2]|\n"
-   "RCP TEMP[2], TEMP[2]\n"
-   "SUB TEMP[1], TEMP[2], TEMP[1]\n"
-   "ADD TEMP[0], CONST[0].zzzz, CONST[0].zzzz\n"
-   "RCP TEMP[0], TEMP[0]\n"
-   "MUL TEMP[2], TEMP[1], TEMP[0]\n"
-   "TEX %s, TEMP[2], SAMP[0], 1D\n";
-
-static const char pattern_asm[] =
-   "MOV TEMP[0].xy, IN[0]\n"
-   "MOV TEMP[0].z, CONST[1].yyyy\n"
-   "DP3 TEMP[1], CONST[2], TEMP[0]\n"
-   "DP3 TEMP[2], CONST[3], TEMP[0]\n"
-   "DP3 TEMP[3], CONST[4], TEMP[0]\n"
-   "RCP TEMP[3], TEMP[3]\n"
-   "MUL TEMP[1], TEMP[1], TEMP[3]\n"
-   "MUL TEMP[2], TEMP[2], TEMP[3]\n"
-   "MOV TEMP[4].x, TEMP[1]\n"
-   "MOV TEMP[4].y, TEMP[2]\n"
-   "RCP TEMP[0], CONST[1].zwzw\n"
-   "MOV TEMP[1], TEMP[4]\n"
-   "MUL TEMP[1].x, TEMP[1], TEMP[0]\n"
-   "MUL TEMP[1].y, TEMP[1], TEMP[0]\n"
-   "TEX %s, TEMP[1], SAMP[0], 2D\n";
-
-
-static const char mask_asm[] =
-   "TEX TEMP[1], IN[0], SAMP[1], 2D\n"
-   "MUL TEMP[0].w, TEMP[0].wwww, TEMP[1].wwww\n"
-   "MOV %s, TEMP[0]\n";
-
-
-static const char image_normal_asm[] =
-   "TEX %s, IN[1], SAMP[3], 2D\n";
-
-static const char image_multiply_asm[] =
-   "TEX TEMP[1], IN[1], SAMP[3], 2D\n"
-   "MUL %s, TEMP[0], TEMP[1]\n";
-
-static const char image_stencil_asm[] =
-   "TEX TEMP[1], IN[1], SAMP[3], 2D\n"
-   "MUL %s, TEMP[0], TEMP[1]\n";
-
-
-#define EXTENDED_BLEND_OVER                     \
-   "SUB TEMP[3], CONST[1].yyyy, TEMP[1].wwww\n" \
-   "SUB TEMP[4], CONST[1].yyyy, TEMP[0].wwww\n" \
-   "MUL TEMP[3], TEMP[0], TEMP[3]\n"            \
-   "MUL TEMP[4], TEMP[1], TEMP[4]\n"            \
-   "ADD TEMP[3], TEMP[3], TEMP[4]\n"
-
-static const char blend_multiply_asm[] =
-   "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
-   EXTENDED_BLEND_OVER
-   "MUL TEMP[4], TEMP[0], TEMP[1]\n"
-   "ADD TEMP[1], TEMP[4], TEMP[3]\n"/*result.rgb*/
-   "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
-   "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
-   "SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
-   "MOV %s, TEMP[1]\n";
-#if 1
-static const char blend_screen_asm[] =
-   "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
-   "ADD TEMP[3], TEMP[0], TEMP[1]\n"
-   "MUL TEMP[2], TEMP[0], TEMP[1]\n"
-   "SUB %s, TEMP[3], TEMP[2]\n";
-#else
-static const char blend_screen_asm[] =
-   "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
-   "MOV %s, TEMP[1]\n";
-#endif
-
-static const char blend_darken_asm[] =
-   "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
-   EXTENDED_BLEND_OVER
-   "MUL TEMP[4], TEMP[0], TEMP[1].wwww\n"
-   "MUL TEMP[5], TEMP[1], TEMP[0].wwww\n"
-   "MIN TEMP[4], TEMP[4], TEMP[5]\n"
-   "ADD TEMP[1], TEMP[3], TEMP[4]\n"
-   "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
-   "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
-   "SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
-   "MOV %s, TEMP[1]\n";
-
-static const char blend_lighten_asm[] =
-   "TEX TEMP[1], IN[0], SAMP[2], 2D\n"
-   EXTENDED_BLEND_OVER
-   "MUL TEMP[4], TEMP[0], TEMP[1].wwww\n"
-   "MUL TEMP[5], TEMP[1], TEMP[0].wwww\n"
-   "MAX TEMP[4], TEMP[4], TEMP[5]\n"
-   "ADD TEMP[1], TEMP[3], TEMP[4]\n"
-   "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n"
-   "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n"
-   "SUB TEMP[1].w, TEMP[3], TEMP[2]\n"
-   "MOV %s, TEMP[1]\n";
-
-
-static const char premultiply_asm[] =
-   "MUL TEMP[0].xyz, TEMP[0], TEMP[0].wwww\n";
-
-static const char unpremultiply_asm[] =
-   "TEX TEMP[0], IN[0], SAMP[1], 2D\n";
-
-
-static const char color_bw_asm[] =
-   "ADD TEMP[1], CONST[1].yyyy, CONST[1].yyyy\n"
-   "RCP TEMP[2], TEMP[1]\n"
-   "ADD TEMP[1], CONST[1].yyyy, TEMP[2]\n"
-   "ADD TEMP[2].x, TEMP[0].xxxx, TEMP[0].yyyy\n"
-   "ADD TEMP[2].x, TEMP[0].zzzz, TEMP[0].xxxx\n"
-   "SGE TEMP[0].xyz, TEMP[2].xxxx, TEMP[1]\n"
-   "SGE TEMP[0].w, TEMP[0].wwww, TEMP[2].yyyy\n"
-   "MOV %s, TEMP[0]\n";
+#include "tgsi/tgsi_ureg.h"
+
+typedef void (* ureg_func)( struct ureg_program *ureg,
+                            struct ureg_dst *out,
+                            struct ureg_src *in,
+                            struct ureg_src *sampler,
+                            struct ureg_dst *temp,
+                            struct ureg_src *constant);
+
+static INLINE void
+solid_fill( struct ureg_program *ureg,
+            struct ureg_dst *out,
+            struct ureg_src *in,
+            struct ureg_src *sampler,
+            struct ureg_dst *temp,
+            struct ureg_src *constant)
+{
+   ureg_MOV(ureg, *out, constant[0]);
+}
+
+static INLINE void
+linear_grad( struct ureg_program *ureg,
+             struct ureg_dst *out,
+             struct ureg_src *in,
+             struct ureg_src *sampler,
+             struct ureg_dst *temp,
+             struct ureg_src *constant)
+{
+
+   ureg_MOV(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_XY),
+            in[0]);
+   ureg_MOV(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
+   ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
+   ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
+   ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
+   ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
+   ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
+   ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
+   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1]));
+   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
+   ureg_MUL(ureg, temp[0],
+            ureg_scalar(constant[0], TGSI_SWIZZLE_Y),
+            ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_Y));
+   ureg_MAD(ureg, temp[1],
+            ureg_scalar(constant[0], TGSI_SWIZZLE_X),
+            ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_X),
+            ureg_src(temp[0]));
+   ureg_MUL(ureg, temp[2], ureg_src(temp[1]),
+            ureg_scalar(constant[0], TGSI_SWIZZLE_Z));
+   ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]);
+}
+
+static INLINE void
+radial_grad( struct ureg_program *ureg,
+             struct ureg_dst *out,
+             struct ureg_src *in,
+             struct ureg_src *sampler,
+             struct ureg_dst *temp,
+             struct ureg_src *constant)
+{
+
+   ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_XY), in[0]);
+   ureg_MOV(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
+   ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
+   ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
+   ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
+   ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
+   ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
+   ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
+   ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_X), ureg_src(temp[1]));
+   ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
+   ureg_MUL(ureg, temp[0], ureg_scalar(constant[0], TGSI_SWIZZLE_Y),
+            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y));
+   ureg_MAD(ureg, temp[1],
+            ureg_scalar(constant[0], TGSI_SWIZZLE_X),
+            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X), ureg_src(temp[0]));
+   ureg_ADD(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[1]));
+   ureg_MUL(ureg, temp[3],
+            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y),
+            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y));
+   ureg_MAD(ureg, temp[4],
+            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X),
+            ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X),
+            ureg_src(temp[3]));
+   ureg_MOV(ureg, temp[4], ureg_negate(ureg_src(temp[4])));
+   ureg_MUL(ureg, temp[2],
+            ureg_scalar(constant[0], TGSI_SWIZZLE_Z),
+            ureg_src(temp[4]));
+   ureg_MUL(ureg, temp[0],
+            ureg_scalar(constant[1], TGSI_SWIZZLE_W),
+            ureg_src(temp[2]));
+   ureg_MUL(ureg, temp[3], ureg_src(temp[1]), ureg_src(temp[1]));
+
+   ureg_SUB(ureg, temp[2], ureg_src(temp[3]), ureg_src(temp[0]));
+   ureg_RSQ(ureg, temp[2], ureg_abs(ureg_src(temp[2])));
+   ureg_RCP(ureg, temp[2], ureg_src(temp[2]));
+   ureg_SUB(ureg, temp[1], ureg_src(temp[2]), ureg_src(temp[1]));
+   ureg_ADD(ureg, temp[0],
+            ureg_scalar(constant[0], TGSI_SWIZZLE_Z),
+            ureg_scalar(constant[0], TGSI_SWIZZLE_Z));
+   ureg_RCP(ureg, temp[0], ureg_src(temp[0]));
+   ureg_MUL(ureg, temp[2], ureg_src(temp[1]), ureg_src(temp[0]));
+   ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]);
+
+}
+
+
+static INLINE void
+pattern( struct ureg_program *ureg,
+         struct ureg_dst     *out,
+         struct ureg_src     *in,
+         struct ureg_src     *sampler,
+         struct ureg_dst     *temp,
+         struct ureg_src     *constant)
+{
+   ureg_MOV(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_XY),
+            in[0]);
+   ureg_MOV(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
+   ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
+   ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
+   ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
+   ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
+   ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
+   ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
+   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1]));
+   ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
+   ureg_RCP(ureg, temp[0],
+            ureg_swizzle(constant[1],
+                         TGSI_SWIZZLE_Z,
+                         TGSI_SWIZZLE_W,
+                         TGSI_SWIZZLE_Z,
+                         TGSI_SWIZZLE_W));
+   ureg_MOV(ureg, temp[1], ureg_src(temp[4]));
+   ureg_MUL(ureg,
+            ureg_writemask(temp[1], TGSI_WRITEMASK_X),
+            ureg_src(temp[1]),
+            ureg_src(temp[0]));
+   ureg_MUL(ureg,
+            ureg_writemask(temp[1], TGSI_WRITEMASK_Y),
+            ureg_src(temp[1]),
+            ureg_src(temp[0]));
+   ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, ureg_src(temp[1]), sampler[0]);
+}
+
+static INLINE void
+mask( struct ureg_program *ureg,
+      struct ureg_dst *out,
+      struct ureg_src *in,
+      struct ureg_src *sampler,
+      struct ureg_dst *temp,
+      struct ureg_src *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[1]);
+   ureg_MUL(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_W),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_MOV(ureg, *out, ureg_src(temp[0]));
+}
+
+static INLINE void
+image_normal( struct ureg_program *ureg,
+              struct ureg_dst *out,
+              struct ureg_src *in,
+              struct ureg_src *sampler,
+              struct ureg_dst *temp,
+              struct ureg_src *constant)
+{
+   ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, in[1], sampler[3]);
+}
+
+
+static INLINE void
+image_multiply( struct ureg_program *ureg,
+                struct ureg_dst *out,
+                struct ureg_src *in,
+                struct ureg_src *sampler,
+                struct ureg_dst *temp,
+                struct ureg_src *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
+   ureg_MUL(ureg, *out, ureg_src(temp[0]), ureg_src(temp[1]));
+}
+
+
+static INLINE void
+image_stencil( struct ureg_program *ureg,
+               struct ureg_dst *out,
+               struct ureg_src *in,
+               struct ureg_src *sampler,
+               struct ureg_dst *temp,
+               struct ureg_src *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
+   ureg_MUL(ureg, *out, ureg_src(temp[0]), ureg_src(temp[1]));
+}
+
+#define EXTENDED_BLENDER_OVER_FUNC                                      \
+   ureg_SUB(ureg, temp[3],                                              \
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),                   \
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));            \
+   ureg_SUB(ureg, temp[3],                                              \
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),                   \
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));            \
+   ureg_MUL(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[3]));       \
+   ureg_MUL(ureg, temp[4], ureg_src(temp[1]), ureg_src(temp[4]));       \
+   ureg_ADD(ureg, temp[3], ureg_src(temp[3]), ureg_src(temp[4]));
+
+
+static INLINE void
+blend_multiply( struct ureg_program *ureg,
+                struct ureg_dst *out,
+                struct ureg_src *in,
+                struct ureg_src *sampler,
+                struct ureg_dst *temp,
+                struct ureg_src *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
+   EXTENDED_BLENDER_OVER_FUNC
+   ureg_MUL(ureg, temp[4], ureg_src(temp[0]), ureg_src(temp[1]));
+   ureg_ADD(ureg, temp[1], ureg_src(temp[4]), ureg_src(temp[3]));
+
+   ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
+            ureg_src(temp[3]), ureg_src(temp[2]));
+
+   ureg_MOV(ureg, *out, ureg_src(temp[1]));
+}
+
+static INLINE void
+blend_screen( struct ureg_program *ureg,
+              struct ureg_dst     *out,
+              struct ureg_src     *in,
+              struct ureg_src     *sampler,
+              struct ureg_dst     *temp,
+              struct ureg_src     *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
+   ureg_ADD(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[1]));
+   ureg_MUL(ureg, temp[2], ureg_src(temp[0]), ureg_src(temp[1]));
+   ureg_SUB(ureg, *out, ureg_src(temp[3]), ureg_src(temp[2]));
+}
+
+static INLINE void
+blend_darken( struct ureg_program *ureg,
+              struct ureg_dst     *out,
+              struct ureg_src     *in,
+              struct ureg_src     *sampler,
+              struct ureg_dst     *temp,
+              struct ureg_src     *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
+   EXTENDED_BLENDER_OVER_FUNC
+   ureg_MUL(ureg, temp[4], ureg_src(temp[0]),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_MUL(ureg, temp[5], ureg_src(temp[1]),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
+   ureg_MIN(ureg, temp[4], ureg_src(temp[4]), ureg_src(temp[5]));
+   ureg_ADD(ureg, temp[1], ureg_src(temp[3]), ureg_src(temp[4]));
+
+   ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
+            ureg_src(temp[3]), ureg_src(temp[2]));
+
+   ureg_MOV(ureg, *out, ureg_src(temp[1]));
+}
+
+static INLINE void
+blend_lighten( struct ureg_program *ureg,
+               struct ureg_dst     *out,
+               struct ureg_src     *in,
+               struct ureg_src     *sampler,
+               struct ureg_dst *temp,
+               struct ureg_src     *constant)
+{
+   ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
+   EXTENDED_BLENDER_OVER_FUNC
+   ureg_MUL(ureg, temp[4], ureg_src(temp[0]),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_MUL(ureg, temp[5], ureg_src(temp[1]),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
+   ureg_MAX(ureg, temp[4], ureg_src(temp[4]), ureg_src(temp[5]));
+   ureg_ADD(ureg, temp[1], ureg_src(temp[3]), ureg_src(temp[4]));
+
+   ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+            ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+   ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
+            ureg_src(temp[3]), ureg_src(temp[2]));
+
+   ureg_MOV(ureg, *out, ureg_src(temp[1]));
+}
+
+static INLINE void
+premultiply( struct ureg_program *ureg,
+                struct ureg_dst *out,
+                struct ureg_src *in,
+                struct ureg_src *sampler,
+                struct ureg_dst *temp,
+                struct ureg_src *constant)
+{
+   ureg_MUL(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_XYZ),
+            ureg_src(temp[0]),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
+}
+
+static INLINE void
+unpremultiply( struct ureg_program *ureg,
+                struct ureg_dst *out,
+                struct ureg_src *in,
+                struct ureg_src *sampler,
+                struct ureg_dst *temp,
+                struct ureg_src *constant)
+{
+   ureg_TEX(ureg, temp[0], TGSI_TEXTURE_2D, in[0], sampler[1]);
+}
+
+
+static INLINE void
+color_bw( struct ureg_program *ureg,
+                struct ureg_dst *out,
+                struct ureg_src *in,
+                struct ureg_src *sampler,
+                struct ureg_dst *temp,
+                struct ureg_src *constant)
+{
+   ureg_ADD(ureg, temp[1],
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
+   ureg_RCP(ureg, temp[2], ureg_src(temp[1]));
+   ureg_ADD(ureg, temp[1],
+            ureg_scalar(constant[1], TGSI_SWIZZLE_Y),
+            ureg_src(temp[2]));
+   ureg_ADD(ureg, ureg_writemask(temp[2], TGSI_WRITEMASK_X),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_X),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_Y));
+   ureg_ADD(ureg, ureg_writemask(temp[2], TGSI_WRITEMASK_X),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_Z),
+            ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_X));
+   ureg_SGE(ureg,
+            ureg_writemask(temp[0], TGSI_WRITEMASK_XYZ),
+            ureg_scalar(ureg_src(temp[2]), TGSI_SWIZZLE_X),
+            ureg_src(temp[1]));
+  ureg_SGE(ureg,
+           ureg_writemask(temp[0], TGSI_WRITEMASK_W),
+           ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+           ureg_scalar(ureg_src(temp[2]), TGSI_SWIZZLE_Y));
+  ureg_MOV(ureg, *out, ureg_src(temp[0]));
+}
 
 
 struct shader_asm_info {
    VGint id;
-   VGint num_tokens;
-   const char * txt;
+   ureg_func func;
 
    VGboolean needs_position;
 
@@ -203,44 +412,44 @@ struct shader_asm_info {
 
 static const struct shader_asm_info shaders_asm[] = {
    /* fills */
-   {VEGA_SOLID_FILL_SHADER,       40,  solid_fill_asm,
+   {VEGA_SOLID_FILL_SHADER, solid_fill,
     VG_FALSE, 0, 1, 0, 0, 0, 0},
-   {VEGA_LINEAR_GRADIENT_SHADER, 200,  linear_grad_asm,
+   {VEGA_LINEAR_GRADIENT_SHADER, linear_grad,
     VG_TRUE,  0, 5, 0, 1, 0, 5},
-   {VEGA_RADIAL_GRADIENT_SHADER, 200,  radial_grad_asm,
+   {VEGA_RADIAL_GRADIENT_SHADER, radial_grad,
     VG_TRUE,  0, 5, 0, 1, 0, 6},
-   {VEGA_PATTERN_SHADER,         100,      pattern_asm,
+   {VEGA_PATTERN_SHADER, pattern,
     VG_TRUE,  1, 4, 0, 1, 0, 5},
 
    /* image draw modes */
-   {VEGA_IMAGE_NORMAL_SHADER,    200, image_normal_asm,
+   {VEGA_IMAGE_NORMAL_SHADER, image_normal,
     VG_TRUE,  0, 0, 3, 1, 0, 0},
-   {VEGA_IMAGE_MULTIPLY_SHADER,  200, image_multiply_asm,
+   {VEGA_IMAGE_MULTIPLY_SHADER, image_multiply,
     VG_TRUE,  0, 0, 3, 1, 0, 2},
-   {VEGA_IMAGE_STENCIL_SHADER,   200, image_stencil_asm,
+   {VEGA_IMAGE_STENCIL_SHADER, image_stencil,
     VG_TRUE,  0, 0, 3, 1, 0, 2},
 
-   {VEGA_MASK_SHADER,            100,         mask_asm,
+   {VEGA_MASK_SHADER, mask,
     VG_TRUE,  0, 0, 1, 1, 0, 2},
 
    /* extra blend modes */
-   {VEGA_BLEND_MULTIPLY_SHADER,  200, blend_multiply_asm,
+   {VEGA_BLEND_MULTIPLY_SHADER, blend_multiply,
     VG_TRUE,  1, 1, 2, 1, 0, 5},
-   {VEGA_BLEND_SCREEN_SHADER,    200, blend_screen_asm,
+   {VEGA_BLEND_SCREEN_SHADER, blend_screen,
     VG_TRUE,  0, 0, 2, 1, 0, 4},
-   {VEGA_BLEND_DARKEN_SHADER,    200, blend_darken_asm,
+   {VEGA_BLEND_DARKEN_SHADER, blend_darken,
     VG_TRUE,  1, 1, 2, 1, 0, 6},
-   {VEGA_BLEND_LIGHTEN_SHADER,   200, blend_lighten_asm,
+   {VEGA_BLEND_LIGHTEN_SHADER, blend_lighten,
     VG_TRUE,  1, 1, 2, 1, 0, 6},
 
    /* premultiply */
-   {VEGA_PREMULTIPLY_SHADER,   100, premultiply_asm,
+   {VEGA_PREMULTIPLY_SHADER, premultiply,
     VG_FALSE,  0, 0, 0, 0, 0, 1},
-   {VEGA_UNPREMULTIPLY_SHADER,   100, unpremultiply_asm,
+   {VEGA_UNPREMULTIPLY_SHADER, unpremultiply,
     VG_FALSE,  0, 0, 0, 0, 0, 1},
 
    /* color transform to black and white */
-   {VEGA_BW_SHADER,   150, color_bw_asm,
+   {VEGA_BW_SHADER, color_bw,
     VG_FALSE,  1, 1, 0, 0, 0, 3},
 };
 #endif
index 593e60fc63a66743e929e21566cc395b9de898a2..f43fe6ee4cbf3f88a3b57124af0184528f76cf25 100644 (file)
@@ -123,17 +123,23 @@ static INLINE VGint range_max(VGint max, VGint current)
    return MAX2(max, current);
 }
 
-static void
-create_preamble(char *txt,
-                const struct shader_asm_info *shaders[SHADER_STAGES],
-                int num_shaders)
+static void *
+combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
+                struct pipe_context *pipe,
+                struct pipe_shader_state *shader)
 {
    VGboolean declare_input = VG_FALSE;
    VGint start_const   = -1, end_const   = 0;
    VGint start_temp    = -1, end_temp    = 0;
    VGint start_sampler = -1, end_sampler = 0;
-   VGint i;
+   VGint i, current_shader = 0;
    VGint num_consts, num_temps, num_samplers;
+   struct ureg_program *ureg;
+   struct ureg_src in[2];
+   struct ureg_src *sampler = NULL;
+   struct ureg_src *constant = NULL;
+   struct ureg_dst out, *temp = NULL;
+   void *p = NULL;
 
    for (i = 0; i < num_shaders; ++i) {
       if (shaders[i]->num_consts)
@@ -158,99 +164,94 @@ create_preamble(char *txt,
    if (start_temp < 0)
       start_temp = 0;
    if (start_sampler < 0)
-      start_sampler = 0;
+       start_sampler = 0;
 
    num_consts   = end_const   - start_const;
    num_temps    = end_temp    - start_temp;
    num_samplers = end_sampler - start_sampler;
-   /* end exclusive */
-   --end_const;
-   --end_temp;
-   --end_sampler;
 
-   sprintf(txt, "FRAG\n");
+   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!ureg)
+       return NULL;
 
    if (declare_input) {
-      sprintf(txt + strlen(txt), "DCL IN[0], POSITION, LINEAR\n");
-      sprintf(txt + strlen(txt), "DCL IN[1], GENERIC[0], PERSPECTIVE\n");
+      in[0] = ureg_DECL_fs_input(ureg,
+                                 TGSI_SEMANTIC_POSITION,
+                                 0,
+                                 TGSI_INTERPOLATE_LINEAR);
+      in[1] = ureg_DECL_fs_input(ureg,
+                                 TGSI_SEMANTIC_GENERIC,
+                                 0,
+                                 TGSI_INTERPOLATE_PERSPECTIVE);
    }
 
    /* we always have a color output */
-   sprintf(txt + strlen(txt), "DCL OUT[0], COLOR, CONSTANT\n");
-
-   if (num_consts > 1)
-      sprintf(txt + strlen(txt), "DCL CONST[%d..%d], CONSTANT\n", start_const, end_const);
-   else if (num_consts == 1)
-      sprintf(txt + strlen(txt), "DCL CONST[%d], CONSTANT\n", start_const);
-
-   if (num_temps > 1)
-      sprintf(txt + strlen(txt), "DCL TEMP[%d..%d], CONSTANT\n", start_temp, end_temp);
-   else if (num_temps > 1)
-      sprintf(txt + strlen(txt), "DCL TEMP[%d], CONSTANT\n", start_temp);
-
-   if (num_samplers > 1)
-      sprintf(txt + strlen(txt), "DCL SAMP[%d..%d], CONSTANT\n", start_sampler, end_sampler);
-   else if (num_samplers == 1)
-      sprintf(txt + strlen(txt), "DCL SAMP[%d], CONSTANT\n", start_sampler);
-}
+   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
 
-static void *
-combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders,
-                struct pipe_context *pipe,
-                struct pipe_shader_state *shader)
-{
-   char *combined_txt;
-   int combined_len = MAX_PREAMBLE;
-   int combined_tokens = 0;
-   int i = 0;
-   int current_shader = 0;
-   int current_len;
+   if (num_consts >= 1) {
+      constant = (struct ureg_src *) malloc(sizeof(struct ureg_src) * end_const);
+      for (i = start_const; i < end_const; i++) {
+         constant[i] = ureg_DECL_constant(ureg, i);
+      }
 
-   for (i = 0; i < num_shaders; ++i) {
-      combined_len += strlen(shaders[i]->txt);
-      combined_tokens += shaders[i]->num_tokens;
    }
-   /* add for the %s->TEMP[0] substitutions */
-   combined_len += num_shaders * 7 /*TEMP[0]*/ + 4 /*"END\n"*/;
 
-   combined_txt = (char*)malloc(combined_len);
-   combined_txt[0] = '\0';
+   if (num_temps >= 1) {
+      temp = (struct ureg_dst *) malloc(sizeof(struct ureg_dst) * end_temp);
+      for (i = start_temp; i < end_temp; i++) {
+         temp[i] = ureg_DECL_temporary(ureg);
+      }
+   }
 
-   create_preamble(combined_txt, shaders, num_shaders);
+   if (num_samplers >= 1) {
+      sampler = (struct ureg_src *) malloc(sizeof(struct ureg_src) * end_sampler);
+      for (i = start_sampler; i < end_sampler; i++) {
+         sampler[i] = ureg_DECL_sampler(ureg, i);
+      }
+   }
 
    while (current_shader < num_shaders) {
-      const char temp[] = "TEMP[0]";
-      const char out[] = "OUT[0]";
-      const char *subst = temp;
-
-      current_len = strlen(combined_txt);
-
-      /* if the last shader then output */
-      if (current_shader + 1 == num_shaders)
-         subst = out;
-
-      snprintf(combined_txt + current_len,
-               combined_len - current_len,
-               shaders[current_shader]->txt,
-               subst);
-      ++current_shader;
+      if ((current_shader + 1) == num_shaders) {
+         shaders[current_shader]->func(ureg,
+                                       &out,
+                                       in,
+                                       sampler,
+                                       temp,
+                                       constant);
+      } else {
+         shaders[current_shader]->func(ureg,
+                                      &temp[0],
+                                      in,
+                                      sampler,
+                                      temp,
+                                      constant);
+      }
+      current_shader++;
    }
 
+   ureg_END(ureg);
 
-   current_len = strlen(combined_txt);
-   snprintf(combined_txt + current_len,
-            combined_len - current_len,
-            "END\n");
+   shader->tokens = ureg_finalize(ureg);
+   if(!shader->tokens)
+      return NULL;
 
-   debug_printf("Combined shader is : \n%s\n",
-                 combined_txt);
+   p = pipe->create_fs_state(pipe, shader);
+   ureg_destroy(ureg);
 
-   shader->tokens = tokens_from_assembly(
-            combined_txt, combined_tokens);
+   if (num_temps >= 1) {
+      for (i = start_temp; i < end_temp; i++) {
+         ureg_release_temporary(ureg, temp[i]);
+      }
+   }
 
-   free(combined_txt);
+   if (temp)
+      free(temp);
+   if (constant)
+      free(constant);
+   if (sampler)
+      free(sampler);
 
-   return pipe->create_fs_state(pipe, shader);
+   return p;
 }
 
 static void *
index 62a3269d17188df6f5a2a2cdba4fbbb7ee8107b4..85a6f0367247ba73140daf5b5a8b6a03b55b2389 100644 (file)
@@ -813,7 +813,7 @@ directfbgl_create_context( GLcontext        *context,
 {
      struct dd_function_table functions;
      
-     _mesa_initialize_framebuffer( framebuffer, visual ); 
+     _mesa_initialize_window_framebuffer( framebuffer, visual );
      
      _mesa_init_driver_functions( &functions );
      functions.GetString     = dfbGetString;
index e8cc202f889f17c55b51a29a7ece0389c110459c..c9ef1647a322822357a549727ab742b5c218d628 100644 (file)
@@ -202,7 +202,7 @@ intelCreateBuffer(__DRIscreen * driScrnPriv,
       if (!fb)
         return GL_FALSE;
 
-      _mesa_initialize_framebuffer(fb, mesaVis);
+      _mesa_initialize_window_framebuffer(fb, mesaVis);
 
       if (mesaVis->redBits == 5)
         rgbFormat = MESA_FORMAT_RGB565;
index 249c0bbc11d2ef7236f5d08d786c010ed7a1e8bc..aecba7f894900ed6e501349610d319fdd1c74c18 100644 (file)
@@ -74,7 +74,7 @@ static void r200_emit_vecfog(GLcontext *ctx, struct radeon_aos *aos,
                             GLvoid *data, int stride, int count)
 {
        radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-       uint32_t *out;
+       GLfloat *out;
        int i;
        int size = 1;
 
@@ -91,7 +91,7 @@ static void r200_emit_vecfog(GLcontext *ctx, struct radeon_aos *aos,
        aos->count = count;
 
        radeon_bo_map(aos->bo, 1);
-       out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
+       out = (GLfloat*)((char*)aos->bo->ptr + aos->offset);
        for (i = 0; i < count; i++) {
          out[0] = r200ComputeFogBlendFactor( ctx, *(GLfloat *)data );
          out++;
index aa69b0fc72b167307d26fb44762feb4acc0bca6a..928c15e1e405cd082d3532727350d234b736b76a 100644 (file)
@@ -297,7 +297,7 @@ void r300FragmentProgramDump(struct rX00_fragment_program_code *c)
                        if (flags[0] != 0) {
                                sprintf(tmp, "o%i.%s",
                                        (code->alu.inst[i].
-                                        rgb_addr >> R300_ALU_DSTC_SHIFT) & 31,
+                                        rgb_addr >> 29) & 3,
                                        flags);
                                strcat(dstc, tmp);
                        }
@@ -311,7 +311,7 @@ void r300FragmentProgramDump(struct rX00_fragment_program_code *c)
                        if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_OUTPUT) {
                                sprintf(tmp, "o%i.w ",
                                        (code->alu.inst[i].
-                                        alpha_addr >> R300_ALU_DSTA_SHIFT) & 31);
+                                        alpha_addr >> 25) & 3);
                                strcat(dsta, tmp);
                        }
                        if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_DEPTH) {
index 375838d98e76a4c8a969babfe7525e5d978fc17f..cc552aee176d210f5e6ca9723f67dd263bf74aa1 100644 (file)
@@ -176,7 +176,9 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i
                        (inst->RGB.WriteMask << R300_ALU_DSTC_REG_MASK_SHIFT);
        }
        if (inst->RGB.OutputWriteMask) {
-               code->alu.inst[ip].rgb_addr |= (inst->RGB.OutputWriteMask << R300_ALU_DSTC_OUTPUT_MASK_SHIFT);
+               code->alu.inst[ip].rgb_addr |=
+            (inst->RGB.OutputWriteMask << R300_ALU_DSTC_OUTPUT_MASK_SHIFT) |
+            R300_RGB_TARGET(inst->RGB.Target);
                emit->node_flags |= R300_RGBA_OUT;
        }
 
@@ -187,7 +189,8 @@ static int emit_alu(struct r300_emit_state * emit, struct rc_pair_instruction* i
                        R300_ALU_DSTA_REG;
        }
        if (inst->Alpha.OutputWriteMask) {
-               code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_OUTPUT;
+               code->alu.inst[ip].alpha_addr |= R300_ALU_DSTA_OUTPUT |
+            R300_ALPHA_TARGET(inst->Alpha.Target);
                emit->node_flags |= R300_RGBA_OUT;
        }
        if (inst->Alpha.DepthWriteMask) {
index 5581f25352dcc3c24d76b8a1292110a020ba38c9..c2d5dc27b4902fc599e03b7330785ca4b7e48080 100644 (file)
@@ -35,7 +35,10 @@ static void dataflow_outputs_mark_use(void * userdata, void * data,
                void (*callback)(void *, unsigned int, unsigned int))
 {
        struct r300_fragment_program_compiler * c = userdata;
-       callback(data, c->OutputColor, RC_MASK_XYZW);
+       callback(data, c->OutputColor[0], RC_MASK_XYZW);
+       callback(data, c->OutputColor[1], RC_MASK_XYZW);
+       callback(data, c->OutputColor[2], RC_MASK_XYZW);
+       callback(data, c->OutputColor[3], RC_MASK_XYZW);
        callback(data, c->OutputDepth, RC_MASK_W);
 }
 
index b1b14394b6e8c5c0c84465dd6e6b226ac46615ff..c2eb613b23f26c92d86affa3dd0ab6875221a046 100644 (file)
@@ -241,6 +241,9 @@ static void emit_paired(struct r300_fragment_program_compiler *c, struct rc_pair
        code->inst[ip].inst4 |= translate_arg_alpha(inst, 1) << R500_ALPHA_SEL_B_SHIFT;
        code->inst[ip].inst5 |= translate_arg_alpha(inst, 2) << R500_ALU_RGBA_ALPHA_SEL_C_SHIFT;
 
+    code->inst[ip].inst3 |= R500_ALU_RGB_TARGET(inst->RGB.Target);
+    code->inst[ip].inst4 |= R500_ALPHA_TARGET(inst->Alpha.Target);
+
        if (inst->WriteALUResult) {
                code->inst[ip].inst3 |= R500_ALU_RGB_WMASK;
 
index f27f858652e3556acef6d27f3573bcc9284a6baf..6bfda0574f64c5793a7904ae8926caae3cf44a91 100644 (file)
@@ -83,8 +83,10 @@ struct r300_fragment_program_compiler {
        struct rX00_fragment_program_code *code;
        struct r300_fragment_program_external_state state;
        unsigned is_r500;
+    /* Register corresponding to the depthbuffer. */
        unsigned OutputDepth;
-       unsigned OutputColor;
+    /* Registers corresponding to the four colorbuffers. */
+       unsigned OutputColor[4];
 
        void * UserData;
        void (*AllocateHwInputs)(
index 72117682725982887d2fa08409243f9c858760d0..fff5b0c21735a5158f96e8fc4c80429b56721856 100644 (file)
@@ -203,12 +203,21 @@ static void set_pair_instruction(struct r300_fragment_program_compiler *c,
 
        /* Destination handling */
        if (inst->DstReg.File == RC_FILE_OUTPUT) {
-               if (inst->DstReg.Index == c->OutputColor) {
-                       pair->RGB.OutputWriteMask |= inst->DstReg.WriteMask & RC_MASK_XYZ;
-                       pair->Alpha.OutputWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
-               } else if (inst->DstReg.Index == c->OutputDepth) {
-                       pair->Alpha.DepthWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
-               }
+        if (inst->DstReg.Index == c->OutputDepth) {
+            pair->Alpha.DepthWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
+        } else {
+            for (i = 0; i < 4; i++) {
+                if (inst->DstReg.Index == c->OutputColor[i]) {
+                    pair->RGB.Target = i;
+                    pair->Alpha.Target = i;
+                    pair->RGB.OutputWriteMask |=
+                        inst->DstReg.WriteMask & RC_MASK_XYZ;
+                    pair->Alpha.OutputWriteMask |=
+                        GET_BIT(inst->DstReg.WriteMask, 3);
+                    break;
+                }
+            }
+        }
        } else {
                if (needrgb) {
                        pair->RGB.DestIndex = inst->DstReg.Index;
index 6685ade3ea844eea7224264083395530f908f6cf..511cc707a38d987321e5af382d4414c2d3f49ee4 100644 (file)
@@ -60,6 +60,7 @@ struct radeon_pair_instruction_rgb {
        unsigned int Opcode:8;
        unsigned int DestIndex:RC_REGISTER_INDEX_BITS;
        unsigned int WriteMask:3;
+    unsigned int Target:2;
        unsigned int OutputWriteMask:3;
        unsigned int Saturate:1;
 
@@ -77,6 +78,7 @@ struct radeon_pair_instruction_alpha {
        unsigned int Opcode:8;
        unsigned int DestIndex:RC_REGISTER_INDEX_BITS;
        unsigned int WriteMask:1;
+    unsigned int Target:2;
        unsigned int OutputWriteMask:1;
        unsigned int DepthWriteMask:1;
        unsigned int Saturate:1;
index d863b82d53f1328bd9b4e5db772a9d7f6300d8b8..28fb9eae9256990cf3f137664d307431d20c796c 100644 (file)
@@ -229,7 +229,7 @@ static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst
                                (inst->RGB.WriteMask & 2) ? "y" : "",
                                (inst->RGB.WriteMask & 4) ? "z" : "");
                if (inst->RGB.OutputWriteMask)
-                       fprintf(f, " color.%s%s%s",
+                       fprintf(f, " color[%i].%s%s%s", inst->RGB.Target,
                                (inst->RGB.OutputWriteMask & 1) ? "x" : "",
                                (inst->RGB.OutputWriteMask & 2) ? "y" : "",
                                (inst->RGB.OutputWriteMask & 4) ? "z" : "");
@@ -255,7 +255,7 @@ static void rc_print_pair_instruction(FILE * f, struct rc_instruction * fullinst
                if (inst->Alpha.WriteMask)
                        fprintf(f, " temp[%i].w", inst->Alpha.DestIndex);
                if (inst->Alpha.OutputWriteMask)
-                       fprintf(f, " color.w");
+                       fprintf(f, " color[%i].w", inst->Alpha.Target);
                if (inst->Alpha.DepthWriteMask)
                        fprintf(f, " depth.w");
                if (inst->WriteALUResult == RC_ALURESULT_W)
index e24c7955d4b4471c150d0d36fa543a86db70b9b5..54ac2510e7a1f5419e22c4ed772c7ac90dfab5fb 100644 (file)
@@ -114,7 +114,7 @@ static void create_fragment_program(struct r300_context *r300)
     inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
 
     compiler.Base.Program.InputsRead = (1 << FRAG_ATTRIB_TEX0);
-    compiler.OutputColor = FRAG_RESULT_COLOR;
+    compiler.OutputColor[0] = FRAG_RESULT_COLOR;
     compiler.OutputDepth = FRAG_RESULT_DEPTH;
     compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515);
     compiler.code = &r300->blit.fp_code;
index e41aeff91a44a40e47c73ab3f56788865062976d..a0e2dd3c09f3dd60c339f405e9018c36c5f60dae 100644 (file)
@@ -221,7 +221,8 @@ static void translate_fragment_program(GLcontext *ctx, struct r300_fragment_prog
        compiler.state = fp->state;
        compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) ? GL_TRUE : GL_FALSE;
        compiler.OutputDepth = FRAG_RESULT_DEPTH;
-       compiler.OutputColor = FRAG_RESULT_COLOR;
+       memset(compiler.OutputColor, 0, 4 * sizeof(unsigned));
+       compiler.OutputColor[0] = FRAG_RESULT_COLOR;
        compiler.AllocateHwInputs = &allocate_hw_inputs;
 
        if (compiler.Base.Debug) {
index 6fa1a0663ba9a1da9991ebcb909d6009bb8d7498..93b6399a669f3082683c978cb9282f4e0c802414 100644 (file)
@@ -1479,7 +1479,7 @@ radeonCreateBuffer( __DRIscreen *driScrnPriv,
     if (!rfb)
       return GL_FALSE;
 
-    _mesa_initialize_framebuffer(&rfb->base, mesaVis);
+    _mesa_initialize_window_framebuffer(&rfb->base, mesaVis);
 
     if (mesaVis->redBits == 5)
         rgbFormat = _mesa_little_endian() ? MESA_FORMAT_RGB565 : MESA_FORMAT_RGB565_REV;
index 8340861aff8b5715259312f51639046e7b3fa086..4e823669bfcf2bb901af161e701cbeba8febc292 100644 (file)
@@ -368,7 +368,7 @@ driCreateNewDrawable(__DRIscreen *screen,
     buf->row = _mesa_malloc(MAX_WIDTH * 4);
 
     /* basic framebuffer setup */
-    _mesa_initialize_framebuffer(&buf->Base, &config->modes);
+    _mesa_initialize_window_framebuffer(&buf->Base, &config->modes);
 
     /* add front renderbuffer */
     frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE);
index 531558dc4d65a491b0ea0d9ccd1e540475172546..1a56b2395fa52182af338a9fb1aeff9450fdff31 100644 (file)
@@ -626,7 +626,7 @@ glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
       return NULL;
 
    /* basic framebuffer setup */
-   _mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual);
+   _mesa_initialize_window_framebuffer(&buf->glframebuffer, &visual->glvisual);
    /* add front renderbuffer */
    frontrb = new_glfbdev_renderbuffer(frontBuffer, visual);
    _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_FRONT_LEFT,
index fa8293d039a404b79011da97921658fc72f1b0f3..080fe475c16eb4f5a1ad632c6ef53c65ee146334 100644 (file)
@@ -10,6 +10,7 @@ PROGRAM = glslcompiler
 OBJECTS = \
        glslcompiler.o \
        ../../glapi/glapi.o \
+       ../../glapi/glapi_nop.o \
        ../../glapi/glthread.o \
        ../../main/dispatch.o \
        ../common/driverfuncs.o \
index ceeafd5f909e028654cf8db8f5bc989bbf072bb9..b24b758cfb26c866630179b5094628da4ab839cf 100644 (file)
@@ -35,7 +35,7 @@ wmesa_new_framebuffer(HDC hdc, GLvisual *visual)
     WMesaFramebuffer pwfb
         = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
     if (pwfb) {
-        _mesa_initialize_framebuffer(&pwfb->Base, visual);
+        _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
         pwfb->hDC = hdc;
         /* insert at head of list */
         pwfb->next = FirstFramebuffer;
index bf767bceddf28e387de4290a8e65877729cf23ae..1a5456e1be21161041818935bf2efb3e71880007 100644 (file)
@@ -375,7 +375,7 @@ create_xmesa_buffer(XMesaDrawable d, BufferType type,
    b->type = type;
    b->cmap = cmap;
 
-   _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
+   _mesa_initialize_window_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
    b->mesa_buffer.Delete = xmesa_delete_framebuffer;
 
    /*
index 8bd4526cb6fcb4049cd03cf01b7d2b210fee08fe..f2709abc9fd06cc5e1328cb5c6b7e089ea6efe4b 100644 (file)
  * \brief Bitset of arbitrary size definitions.
  * \author Michal Krol
  */
+
+#ifndef BITSET_H
+#define BITSET_H
+
+#include "imports.h"
+
 /****************************************************************************
  * generic bitset implementation
  */
    ((x)[BITSET_BITWORD(b)] &= ~BITSET_RANGE(b, e)) : \
    (assert (!"BITSET_CLEAR_RANGE: bit range crosses word boundary"), 0))
 
+/* Get first bit set in a bitset.
+ */
+static INLINE int
+__bitset_ffs(const BITSET_WORD *x, int n)
+{
+   int i;
+
+   for (i = 0; i < n; i++) {
+      if (x[i])
+        return _mesa_ffs(x[i]) + BITSET_WORDBITS * i;
+   }
+
+   return 0;
+}
+
+#define BITSET_FFS(x) __bitset_ffs(x, Elements(x))
+
 /****************************************************************************
  * 64-bit bitset implementation
  */
    ((x)[BITSET64_BITWORD(b)] &= ~BITSET64_RANGE(b, e)) : \
    (assert (!"BITSET64_CLEAR_RANGE: bit range crosses word boundary"), 0))
 
+#endif
index d958dbf7d48a76d33f2303d0dd18ec9f2ac992ea..96e534438366ef998a611de622254a1d5a921ae5 100644 (file)
@@ -88,7 +88,7 @@ _mesa_create_framebuffer(const GLvisual *visual)
    struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer);
    assert(visual);
    if (fb) {
-      _mesa_initialize_framebuffer(fb, visual);
+      _mesa_initialize_window_framebuffer(fb, visual);
    }
    return fb;
 }
@@ -109,15 +109,7 @@ _mesa_new_framebuffer(GLcontext *ctx, GLuint name)
    assert(name != 0);
    fb = CALLOC_STRUCT(gl_framebuffer);
    if (fb) {
-      fb->Name = name;
-      fb->RefCount = 1;
-      fb->_NumColorDrawBuffers = 1;
-      fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
-      fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;
-      fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
-      fb->_ColorReadBufferIndex = BUFFER_COLOR0;
-      fb->Delete = _mesa_destroy_framebuffer;
-      _glthread_INIT_MUTEX(fb->Mutex);
+      _mesa_initialize_user_framebuffer(fb, name);
    }
    return fb;
 }
@@ -126,10 +118,11 @@ _mesa_new_framebuffer(GLcontext *ctx, GLuint name)
 /**
  * Initialize a gl_framebuffer object.  Typically used to initialize
  * window system-created framebuffers, not user-created framebuffers.
- * \sa _mesa_create_framebuffer
+ * \sa _mesa_initialize_user_framebuffer
  */
 void
-_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual)
+_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
+                                    const GLvisual *visual)
 {
    assert(fb);
    assert(visual);
@@ -166,6 +159,30 @@ _mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual)
 }
 
 
+/**
+ * Initialize a user-created gl_framebuffer object.
+ * \sa _mesa_initialize_window_framebuffer
+ */
+void
+_mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name)
+{
+   assert(fb);
+   assert(name);
+
+   _mesa_bzero(fb, sizeof(struct gl_framebuffer));
+
+   fb->Name = name;
+   fb->RefCount = 1;
+   fb->_NumColorDrawBuffers = 1;
+   fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
+   fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;
+   fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
+   fb->_ColorReadBufferIndex = BUFFER_COLOR0;
+   fb->Delete = _mesa_destroy_framebuffer;
+   _glthread_INIT_MUTEX(fb->Mutex);
+}
+
+
 /**
  * Deallocate buffer and everything attached to it.
  * Typically called via the gl_framebuffer->Delete() method.
index ef21dd98e83e85cac83287285656dcfa82b6626b..960513812cf67ac67cbd810049dd903e4854b82e 100644 (file)
@@ -34,7 +34,11 @@ extern struct gl_framebuffer *
 _mesa_new_framebuffer(GLcontext *ctx, GLuint name);
 
 extern void
-_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual);
+_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb,
+                                    const GLvisual *visual);
+
+extern void
+_mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name);
 
 extern void
 _mesa_destroy_framebuffer(struct gl_framebuffer *buffer);
index 9f9789e010c7bc778d0fa28c11d331445b999b38..54fd88ad4fba3f6ad1c66b905e5f75ed790521ba 100644 (file)
@@ -150,6 +150,10 @@ arb_input_attrib_string(GLint index, GLenum progType)
       "fragment.varying[7]"
    };
 
+   /* sanity checks */
+   assert(strcmp(vertAttribs[VERT_ATTRIB_TEX0], "vertex.texcoord[0]") == 0);
+   assert(strcmp(vertAttribs[VERT_ATTRIB_GENERIC15], "vertex.attrib[15]") == 0);
+
    if (progType == GL_VERTEX_PROGRAM_ARB) {
       assert(index < sizeof(vertAttribs) / sizeof(vertAttribs[0]));
       return vertAttribs[index];
@@ -161,6 +165,43 @@ arb_input_attrib_string(GLint index, GLenum progType)
 }
 
 
+/**
+ * Print a vertex program's InputsRead field in human-readable format.
+ * For debugging.
+ */
+void
+_mesa_print_vp_inputs(GLbitfield inputs)
+{
+   _mesa_printf("VP Inputs 0x%x: \n", inputs);
+   while (inputs) {
+      GLint attr = _mesa_ffs(inputs) - 1;
+      const char *name = arb_input_attrib_string(attr,
+                                                 GL_VERTEX_PROGRAM_ARB);
+      _mesa_printf("  %d: %s\n", attr, name);
+      inputs &= ~(1 << attr);
+   }
+}
+
+
+/**
+ * Print a fragment program's InputsRead field in human-readable format.
+ * For debugging.
+ */
+void
+_mesa_print_fp_inputs(GLbitfield inputs)
+{
+   _mesa_printf("FP Inputs 0x%x: \n", inputs);
+   while (inputs) {
+      GLint attr = _mesa_ffs(inputs) - 1;
+      const char *name = arb_input_attrib_string(attr,
+                                                 GL_FRAGMENT_PROGRAM_ARB);
+      _mesa_printf("  %d: %s\n", attr, name);
+      inputs &= ~(1 << attr);
+   }
+}
+
+
+
 /**
  * Return ARB_v/f_prog-style output attrib string.
  */
index fc286ded540e1855ccb57bc7d49e58c96382eeb3..9ab745601693572aafd601f2f8357d7ad63d3b06 100644 (file)
@@ -37,6 +37,12 @@ typedef enum {
 } gl_prog_print_mode;
 
 
+extern void
+_mesa_print_vp_inputs(GLbitfield inputs);
+
+extern void
+_mesa_print_fp_inputs(GLbitfield inputs);
+
 extern const char *
 _mesa_condcode_string(GLuint condcode);
 
index 3e86d0adad47de590425e87a89b21653e4693e8f..aaf5f96e2a58be81fa63cd6af1c489f939907fb5 100644 (file)
@@ -677,6 +677,8 @@ _mesa_combine_programs(GLcontext *ctx,
    const GLuint lenB = progB->NumInstructions;
    const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
    const GLuint newLength = lenA + lenB;
+   GLboolean usedTemps[MAX_PROGRAM_TEMPS];
+   GLuint firstTemp = 0;
    GLbitfield inputsB;
    GLuint i;
 
@@ -698,6 +700,10 @@ _mesa_combine_programs(GLcontext *ctx,
    newProg->Instructions = newInst;
    newProg->NumInstructions = newLength;
 
+   /* find used temp regs (we may need new temps below) */
+   _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY,
+                             usedTemps, MAX_PROGRAM_TEMPS);
+
    if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
       struct gl_fragment_program *fprogA, *fprogB, *newFprog;
       GLbitfield progB_inputsRead = progB->InputsRead;
@@ -741,12 +747,15 @@ _mesa_combine_programs(GLcontext *ctx,
        */
       if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) &&
           (progB_inputsRead & FRAG_BIT_COL0)) {
-         GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY);
+         GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS,
+                                                  firstTemp);
          if (tempReg < 0) {
             _mesa_problem(ctx, "No free temp regs found in "
                           "_mesa_combine_programs(), using 31");
             tempReg = 31;
          }
+         firstTemp = tempReg + 1;
+
          /* replace writes to result.color[0] with tempReg */
          replace_registers(newInst, lenA,
                            PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
@@ -784,53 +793,64 @@ _mesa_combine_programs(GLcontext *ctx,
 }
 
 
-
-
 /**
- * Scan the given program to find a free register of the given type.
- * \param regFile - PROGRAM_INPUT, PROGRAM_OUTPUT or PROGRAM_TEMPORARY
+ * Populate the 'used' array with flags indicating which registers (TEMPs,
+ * INPUTs, OUTPUTs, etc, are used by the given program.
+ * \param file  type of register to scan for
+ * \param used  returns true/false flags for in use / free
+ * \param usedSize  size of the 'used' array
  */
-GLint
-_mesa_find_free_register(const struct gl_program *prog, GLuint regFile)
+void
+_mesa_find_used_registers(const struct gl_program *prog,
+                          gl_register_file file,
+                          GLboolean used[], GLuint usedSize)
 {
-   GLboolean used[MAX_PROGRAM_TEMPS];
-   GLuint i, k;
-
-   assert(regFile == PROGRAM_INPUT ||
-          regFile == PROGRAM_OUTPUT ||
-          regFile == PROGRAM_TEMPORARY);
+   GLuint i, j;
 
-   _mesa_memset(used, 0, sizeof(used));
+   _mesa_memset(used, 0, usedSize);
 
    for (i = 0; i < prog->NumInstructions; i++) {
       const struct prog_instruction *inst = prog->Instructions + i;
       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
 
-      /* check dst reg first */
-      if (inst->DstReg.File == regFile) {
+      if (inst->DstReg.File == file) {
          used[inst->DstReg.Index] = GL_TRUE;
       }
-      else {
-         /* check src regs otherwise */
-         for (k = 0; k < n; k++) {
-            if (inst->SrcReg[k].File == regFile) {
-               used[inst->SrcReg[k].Index] = GL_TRUE;
-               break;
-            }
+
+      for (j = 0; j < n; j++) {
+         if (inst->SrcReg[j].File == file) {
+            used[inst->SrcReg[j].Index] = GL_TRUE;
          }
       }
    }
+}
 
-   for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+
+/**
+ * Scan the given 'used' register flag array for the first entry
+ * that's >= firstReg.
+ * \param used  vector of flags indicating registers in use (as returned
+ *              by _mesa_find_used_registers())
+ * \param usedSize  size of the 'used' array
+ * \param firstReg  first register to start searching at
+ * \return index of unused register, or -1 if none.
+ */
+GLint
+_mesa_find_free_register(const GLboolean used[],
+                         GLuint usedSize, GLuint firstReg)
+{
+   GLuint i;
+
+   assert(firstReg < usedSize);
+
+   for (i = firstReg; i < usedSize; i++)
       if (!used[i])
          return i;
-   }
 
    return -1;
 }
 
 
-
 /**
  * "Post-process" a GPU program.  This is intended to be used for debugging.
  * Example actions include no-op'ing instructions or changing instruction
index 56a4191f5788f7f2b2d571f992ed21856f2fa5bd..0187a2c55ff7f8f6f63702d6c4c75ab31dbb9455 100644 (file)
@@ -119,8 +119,14 @@ _mesa_combine_programs(GLcontext *ctx,
                        const struct gl_program *progA,
                        const struct gl_program *progB);
 
+extern void
+_mesa_find_used_registers(const struct gl_program *prog,
+                          gl_register_file file,
+                          GLboolean used[], GLuint usedSize);
+
 extern GLint
-_mesa_find_free_register(const struct gl_program *prog, GLuint regFile);
+_mesa_find_free_register(const GLboolean used[],
+                         GLuint maxRegs, GLuint firstReg);
 
 extern void
 _mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog);
index 9514545709d5262e09a7c9842e668fbfa948c422..fb2ebe6338f5f5801c4e38e25723ce61fd4765bc 100644 (file)
@@ -495,6 +495,11 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type)
    GLuint i;
    GLint outputMap[VERT_RESULT_MAX];
    GLuint numVaryingReads = 0;
+   GLboolean usedTemps[MAX_PROGRAM_TEMPS];
+   GLuint firstTemp = 0;
+
+   _mesa_find_used_registers(prog, PROGRAM_TEMPORARY,
+                             usedTemps, MAX_PROGRAM_TEMPS);
 
    assert(type == PROGRAM_VARYING || type == PROGRAM_OUTPUT);
    assert(prog->Target == GL_VERTEX_PROGRAM_ARB || type != PROGRAM_VARYING);
@@ -513,8 +518,10 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type)
             const GLuint var = inst->SrcReg[j].Index;
             if (outputMap[var] == -1) {
                numVaryingReads++;
-               outputMap[var] = _mesa_find_free_register(prog,
-                                                         PROGRAM_TEMPORARY);
+               outputMap[var] = _mesa_find_free_register(usedTemps,
+                                                         MAX_PROGRAM_TEMPS,
+                                                         firstTemp);
+               firstTemp = outputMap[var] + 1;
             }
             inst->SrcReg[j].File = PROGRAM_TEMPORARY;
             inst->SrcReg[j].Index = outputMap[var];
index aa0508a41fc02d8487a6d5feed58ca3c06fd2212..d9b508537d054cd719442a4628a6c39b3407304d 100644 (file)
@@ -60,26 +60,10 @@ static void
 translate_fp(struct st_context *st,
              struct st_fragment_program *stfp)
 {
-   const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
-
    if (!stfp->state.tokens) {
-      GLuint inAttr, numIn = 0;
-
-      for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
-         if (fragInputsRead & (1 << inAttr)) {
-            stfp->input_to_slot[inAttr] = numIn;
-            numIn++;
-         }
-         else {
-            stfp->input_to_slot[inAttr] = -1;
-         }
-      }
-
-      stfp->num_input_slots = numIn;
-
       assert(stfp->Base.Base.NumInstructions > 0);
 
-      st_translate_fragment_program(st, stfp, stfp->input_to_slot);
+      st_translate_fragment_program(st, stfp);
    }
 }
 
index 27ec2eb0331587ecfe0865ad2015e8af27bda30e..b82bbfe410fe36e622415edbb4d53dcdc81d0157 100644 (file)
@@ -62,9 +62,9 @@ update_viewport( struct st_context *st )
       GLfloat x = (GLfloat)ctx->Viewport.X;
       GLfloat y = (GLfloat)ctx->Viewport.Y;
       GLfloat z = ctx->Viewport.Near;
-      GLfloat half_width = (GLfloat)ctx->Viewport.Width / 2.0f;
-      GLfloat half_height = (GLfloat)ctx->Viewport.Height / 2.0f;
-      GLfloat half_depth = (GLfloat)(ctx->Viewport.Far - ctx->Viewport.Near) / 2.0f;
+      GLfloat half_width = (GLfloat)ctx->Viewport.Width * 0.5f;
+      GLfloat half_height = (GLfloat)ctx->Viewport.Height * 0.5f;
+      GLfloat half_depth = (GLfloat)(ctx->Viewport.Far - ctx->Viewport.Near) * 0.5f;
       
       st->state.viewport.scale[0] = half_width;
       st->state.viewport.scale[1] = half_height * yScale;
index c70bbc880c0649c9a3ba78abd6f7b4cee225ff74..85420a950f49da4f355b4880f52f3d21bd7e5421 100644 (file)
@@ -221,7 +221,7 @@ combined_bitmap_fragment_program(GLcontext *ctx)
 #endif
 
       /* translate to TGSI tokens */
-      st_translate_fragment_program(st, stfp->bitmap_program, NULL);
+      st_translate_fragment_program(st, stfp->bitmap_program);
    }
 
    return stfp->bitmap_program;
index 9b1d2103f17a17e031aaac0c7eff1b7aa7dbba31..2a084ca577972db030be40b9998c3b3f61fd9ada 100644 (file)
@@ -140,7 +140,7 @@ combined_drawpix_fragment_program(GLcontext *ctx)
 #endif
 
       /* translate to TGSI tokens */
-      st_translate_fragment_program(st, stfp, NULL);
+      st_translate_fragment_program(st, stfp);
 
       /* save new program, update serial numbers */
       st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
@@ -221,7 +221,7 @@ make_fragment_shader_z(struct st_context *st)
    p->SamplersUsed = 0x1;  /* sampler 0 (bit 0) is used */
 
    st->drawpix.z_shader = (struct st_fragment_program *) p;
-   st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
+   st_translate_fragment_program(st, st->drawpix.z_shader);
 
    return st->drawpix.z_shader;
 }
index 996e065fedc5077fd45af7a528b2e3e2ff7cabfc..0fcb427f30aede4378e1ec677fff24a27811eed0 100644 (file)
@@ -39,7 +39,7 @@
 #include "st_context.h"
 #include "st_cb_strings.h"
 
-#define ST_VERSION_STRING "0.3"
+#define ST_VERSION_STRING "0.4"
 
 static const GLubyte *
 st_get_string(GLcontext * ctx, GLenum name)
index 7c5664be1d8e684fa0350c8819fa3a43fe39297c..13f050900a61a8b7fe95ec862e53b8462b842a59 100644 (file)
@@ -543,22 +543,15 @@ st_TexImage(GLcontext * ctx,
       _mesa_align_free(texImage->Data);
    }
 
-   if (width == 0 || height == 0 || depth == 0) {
-      /* stop after freeing old image */
-      return;
-   }
-
-   /* If this is the only mipmap level in the texture, could call
-    * bmBufferData with NULL data to free the old block and avoid
-    * waiting on any outstanding fences.
+   /*
+    * See if the new image is somehow incompatible with the existing
+    * mipmap.  If so, free the old mipmap.
     */
    if (stObj->pt) {
       if (stObj->teximage_realloc ||
           level > (GLint) stObj->pt->last_level ||
-          (stObj->pt->last_level == level &&
-           stObj->pt->target != PIPE_TEXTURE_CUBE &&
-           !st_texture_match_image(stObj->pt, &stImage->base,
-                                   stImage->face, stImage->level))) {
+          !st_texture_match_image(stObj->pt, &stImage->base,
+                                  stImage->face, stImage->level)) {
          DBG("release it\n");
          pipe_texture_reference(&stObj->pt, NULL);
          assert(!stObj->pt);
@@ -566,6 +559,11 @@ st_TexImage(GLcontext * ctx,
       }
    }
 
+   if (width == 0 || height == 0 || depth == 0) {
+      /* stop after freeing old image */
+      return;
+   }
+
    if (!stObj->pt) {
       guess_and_alloc_texture(ctx->st, stObj, stImage);
       if (!stObj->pt) {
index ed9c0ff5b76cf9f11781bd1449c8974e27c1ce7b..4e225a123c885d041b10859d7c11de0562c091dc 100644 (file)
@@ -54,7 +54,7 @@ st_create_framebuffer( const __GLcontextModes *visual,
       if (visual->sampleBuffers)
          samples = visual->samples;
 
-      _mesa_initialize_framebuffer(&stfb->Base, visual);
+      _mesa_initialize_window_framebuffer(&stfb->Base, visual);
 
       if (visual->doubleBufferMode) {
          struct gl_renderbuffer *rb
index 5c87e47ca3dedd31278eecb7d3e1a1bdf1963492..a639003dbd07957e8ac867132bec65ea51afc1e9 100644 (file)
@@ -269,24 +269,20 @@ fail:
 
 /**
  * Translate a Mesa fragment shader into a TGSI shader.
- * \param inputMapping  to map fragment program input registers to TGSI
- *                      input slots
  * \return  pointer to cached pipe_shader object.
  */
 void
 st_translate_fragment_program(struct st_context *st,
-                              struct st_fragment_program *stfp,
-                              const GLuint inputMapping[])
+                              struct st_fragment_program *stfp )
 {
    struct pipe_context *pipe = st->pipe;
    GLuint outputMapping[FRAG_RESULT_MAX];
-   GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
+   GLuint inputMapping[FRAG_ATTRIB_MAX];
    GLuint interpMode[16];  /* XXX size? */
    GLuint attr;
    enum pipe_error error;
    const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
    struct ureg_program *ureg;
-   GLuint vslot = 0;
 
    uint fs_num_inputs = 0;
 
@@ -294,24 +290,14 @@ st_translate_fragment_program(struct st_context *st,
    ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
    uint fs_num_outputs = 0;
 
-   /* which vertex output goes to the first fragment input: */
-   if (inputsRead & FRAG_BIT_WPOS)
-      vslot = 0;
-   else
-      vslot = 1;
-
    /*
     * Convert Mesa program inputs to TGSI input register semantics.
     */
    for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
       if (inputsRead & (1 << attr)) {
-         const GLuint slot = fs_num_inputs;
-
-         defaultInputMapping[attr] = slot;
-
-         stfp->input_map[slot] = vslot++;
+         const GLuint slot = fs_num_inputs++;
 
-         fs_num_inputs++;
+         inputMapping[attr] = slot;
 
          switch (attr) {
          case FRAG_ATTRIB_WPOS:
@@ -376,6 +362,9 @@ st_translate_fragment_program(struct st_context *st,
             break;
          }
       }
+      else {
+        inputMapping[attr] = -1;
+      }
    }
 
    /*
@@ -417,9 +406,6 @@ st_translate_fragment_program(struct st_context *st,
       }
    }
 
-   if (!inputMapping)
-      inputMapping = defaultInputMapping;
-
    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
    if (ureg == NULL)
       return;
index 6b9a9226df583b0de95b340d1ab59a5dacafd384..d9822e50f552bd88b95c891dd49c7d357312dc86 100644 (file)
@@ -52,12 +52,6 @@ struct st_fragment_program
    struct gl_fragment_program Base;
    GLuint serialNo;
 
-   GLuint input_to_slot[FRAG_ATTRIB_MAX];  /**< Maps FRAG_ATTRIB_x to slot */
-   GLuint num_input_slots;
-
-   /** map FP input back to VP output */
-   GLuint input_map[PIPE_MAX_SHADER_INPUTS];
-
    ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
    ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
 
@@ -171,8 +165,7 @@ st_reference_fragprog(struct st_context *st,
 
 extern void
 st_translate_fragment_program(struct st_context *st,
-                              struct st_fragment_program *fp,
-                              const GLuint inputMapping[]);
+                              struct st_fragment_program *fp);
 
 
 /* Called after program string change, discard all previous
index da84eaa6ead48fec9676a145e591e458bd3edad2..2fc866c577306fc77797a3713b8fa2b858e48a61 100644 (file)
 #include "main/mtypes.h"
 #include "main/macros.h"
 #include "main/enums.h"
+#include "main/image.h"
 #include "vbo_split.h"
 
 
 #define MAX_PRIM 32
 
-/* Used for splitting without copying.
+/* Used for splitting without copying. No attempt is made to handle
+ * too large indexed vertex buffers: In general you need to copy to do
+ * that.
  */
 struct split_context {
    GLcontext *ctx;
@@ -48,6 +51,7 @@ struct split_context {
    vbo_draw_func draw;
 
    const struct split_limits *limits;
+   GLuint limit;
 
    struct _mesa_prim dstprim[MAX_PRIM];
    GLuint dstprim_nr;
@@ -58,38 +62,38 @@ struct split_context {
 
 static void flush_vertex( struct split_context *split )
 {
-   GLuint min_index, max_index;
+   struct _mesa_index_buffer ib;
    GLuint i;
 
    if (!split->dstprim_nr) 
       return;
 
-   min_index = split->dstprim[0].start;
-   max_index = min_index + split->dstprim[0].count - 1;
+   if (split->ib) {
+      ib = *split->ib;
 
-   for (i = 1; i < split->dstprim_nr; i++) {
-      GLuint tmp_min = split->dstprim[i].start;
-      GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
+      ib.count = split->max_index - split->min_index + 1;
+      ib.ptr = (const void *)((const char *)ib.ptr + 
+                              split->min_index * _mesa_sizeof_type(ib.type));
 
-      if (tmp_min < min_index)
-        min_index = tmp_min;
-
-      if (tmp_max > max_index)
-        max_index = tmp_max;
+      /* Rebase the primitives to save index buffer entries. */
+      for (i = 0; i < split->dstprim_nr; i++)
+        split->dstprim[i].start -= split->min_index;
    }
 
-   assert(max_index >= min_index);
+   assert(split->max_index >= split->min_index);
 
-   split->draw( split->ctx, 
-               split->array, 
-               split->dstprim,
-               split->dstprim_nr,
-               NULL,
-               GL_TRUE,
-               min_index,
-               max_index);
+   split->draw(split->ctx,
+              split->array,
+              split->dstprim,
+              split->dstprim_nr,
+              split->ib ? &ib : NULL,
+              !split->ib,
+              split->min_index,
+              split->max_index);
 
    split->dstprim_nr = 0;
+   split->min_index = ~0;
+   split->max_index = 0;
 }
 
 
@@ -106,62 +110,67 @@ static struct _mesa_prim *next_outprim( struct split_context *split )
    }
 }
 
-static int align(int value, int alignment)
+static void update_index_bounds(struct split_context *split,
+                               const struct _mesa_prim *prim)
 {
-   return (value + alignment - 1) & ~(alignment - 1);
+   split->min_index = MIN2(split->min_index, prim->start);
+   split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
 }
 
-
+/* Return the maximum amount of vertices that can be emitted for a
+ * primitive starting at 'prim->start', depending on the previous
+ * index bounds.
+ */
+static GLuint get_max_vertices(struct split_context *split,
+                              const struct _mesa_prim *prim)
+{
+   if ((prim->start > split->min_index &&
+       prim->start - split->min_index >= split->limit) ||
+       (prim->start < split->max_index &&
+        split->max_index - prim->start >= split->limit))
+      /* "prim" starts too far away from the old range. */
+      return 0;
+
+   return MIN2(split->min_index, prim->start) + split->limit - prim->start;
+}
 
 /* Break large primitives into smaller ones.  If not possible, convert
  * the primitive to indexed and pass to split_elts().
  */
 static void split_prims( struct split_context *split) 
 {
-   GLuint csr = 0;
    GLuint i;
 
    for (i = 0; i < split->nr_prims; i++) {
       const struct _mesa_prim *prim = &split->prim[i];
       GLuint first, incr;
       GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
-      GLuint count;
-
-      /* Always wrap on an even numbered vertex to avoid problems with
-       * triangle strips.  
-       */
-      GLuint available = align(split->limits->max_verts - csr - 1, 2); 
-      assert(split->limits->max_verts >= csr);
+      GLuint available = get_max_vertices(split, prim);
+      GLuint count = prim->count - (prim->count - first) % incr;
 
       if (prim->count < first)
         continue;
-      
-      count = prim->count - (prim->count - first) % incr; 
 
-
-      if ((available < count && !split_inplace) || 
+      if ((available < count && !split_inplace) ||
          (available < first && split_inplace)) {
         flush_vertex(split);
-        csr = 0;
-        available = align(split->limits->max_verts - csr - 1, 2);
+        available = get_max_vertices(split, prim);
       }
       
       if (available >= count) {
         struct _mesa_prim *outprim = next_outprim(split);
+
         *outprim = *prim;
-        csr += prim->count;
-        available = align(split->limits->max_verts - csr - 1, 2); 
-      } 
+        update_index_bounds(split, outprim);
+      }
       else if (split_inplace) {
         GLuint j, nr;
 
-
         for (j = 0 ; j < count ; ) {
            GLuint remaining = count - j;
            struct _mesa_prim *outprim = next_outprim(split);
 
            nr = MIN2( available, remaining );
-           
            nr -= (nr - first) % incr;
            
            outprim->mode = prim->mode;
@@ -169,21 +178,20 @@ static void split_prims( struct split_context *split)
            outprim->end = (nr == remaining && prim->end);
            outprim->start = prim->start + j;
            outprim->count = nr;
-           
+
+           update_index_bounds(split, outprim);
+
            if (nr == remaining) {
               /* Finished. 
                */
-              j += nr;         
-              csr += nr;
-              available = align(split->limits->max_verts - csr - 1, 2); 
+              j += nr;
            }
            else {
               /* Wrapped the primitive: 
                */
               j += nr - (first - incr);
               flush_vertex(split);
-              csr = 0;
-              available = align(split->limits->max_verts - csr - 1, 2); 
+              available = get_max_vertices(split, prim);
            }
         }
       }
@@ -260,10 +268,14 @@ void vbo_split_inplace( GLcontext *ctx,
    split.prim = prim;
    split.nr_prims = nr_prims;
    split.ib = ib;
-   split.min_index = min_index;
-   split.max_index = max_index;
+
+   /* Empty interval, makes calculations simpler. */
+   split.min_index = ~0;
+   split.max_index = 0;
+
    split.draw = draw;
    split.limits = limits;
+   split.limit = ib ? limits->max_indices : limits->max_verts;
 
    split_prims( &split );
 }