merge current trunk into vbo branch
authorAlan Hourihane <alanh@tungstengraphics.com>
Thu, 2 Nov 2006 12:02:13 +0000 (12:02 +0000)
committerAlan Hourihane <alanh@tungstengraphics.com>
Thu, 2 Nov 2006 12:02:13 +0000 (12:02 +0000)
183 files changed:
configs/linux-dri
docs/relnotes-6.5.2.html
progs/demos/Makefile
progs/demos/streaming_rect.c [new file with mode: 0644]
progs/demos/texdown.c
progs/trivial/Makefile
progs/trivial/quad-tex-pbo.c [new file with mode: 0644]
src/glx/x11/glxext.c
src/mesa/drivers/directfb/idirectfbgl_mesa.c
src/mesa/drivers/dri/Makefile.template
src/mesa/drivers/dri/common/dri_bufmgr.c [new file with mode: 0644]
src/mesa/drivers/dri/common/dri_bufmgr.h [new file with mode: 0644]
src/mesa/drivers/dri/common/dri_bufpool.h [new file with mode: 0644]
src/mesa/drivers/dri/common/dri_drmpool.c [new file with mode: 0644]
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/dri_util.h
src/mesa/drivers/dri/ffb/ffb_clear.c
src/mesa/drivers/dri/ffb/ffb_clear.h
src/mesa/drivers/dri/ffb/ffb_xmesa.c
src/mesa/drivers/dri/gamma/gamma_state.c
src/mesa/drivers/dri/i810/i810ioctl.c
src/mesa/drivers/dri/i915/i830_metaops.c
src/mesa/drivers/dri/i915/i915_fragprog.c
src/mesa/drivers/dri/i915/i915_metaops.c
src/mesa/drivers/dri/i915/intel_batchbuffer.c
src/mesa/drivers/dri/i915/intel_ioctl.c
src/mesa/drivers/dri/i915/intel_ioctl.h
src/mesa/drivers/dri/i915tex/Makefile [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_context.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_context.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_metaops.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_state.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_texblend.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i830_vtbl.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_context.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_context.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_debug.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_fragprog.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_metaops.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_program.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_program.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_state.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_tex_layout.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/i915_vtbl.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_batchbuffer.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_batchbuffer.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_batchpool.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_blit.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_blit.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_buffer_objects.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_buffer_objects.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_buffers.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_buffers.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_context.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_context.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_depthstencil.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_depthstencil.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_fbo.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_fbo.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_ioctl.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_ioctl.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_pixel.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_pixel.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_pixel_bitmap.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_pixel_copy.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_pixel_draw.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_pixel_read.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_regions.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_regions.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_render.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_rotate.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_rotate.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_screen.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_span.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_span.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_state.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_structs.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex_copy.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex_format.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex_image.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex_subimage.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tex_validate.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tris.c [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/intel_tris.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/server/i830_common.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/server/i830_dri.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/server/intel.h [new file with mode: 0644]
src/mesa/drivers/dri/i915tex/server/intel_dri.c [new file with mode: 0644]
src/mesa/drivers/dri/i965/intel_blit.c
src/mesa/drivers/dri/i965/intel_blit.h
src/mesa/drivers/dri/i965/intel_buffers.c
src/mesa/drivers/dri/mach64/mach64_ioctl.c
src/mesa/drivers/dri/mga/mga_xmesa.c
src/mesa/drivers/dri/mga/mgacontext.h
src/mesa/drivers/dri/mga/mgadd.c
src/mesa/drivers/dri/mga/mgaioctl.c
src/mesa/drivers/dri/mga/mgaspan.c
src/mesa/drivers/dri/mga/mgastate.c
src/mesa/drivers/dri/r128/r128_ioctl.c
src/mesa/drivers/dri/r200/r200_ioctl.c
src/mesa/drivers/dri/r300/r300_fragprog.c
src/mesa/drivers/dri/r300/r300_fragprog.h
src/mesa/drivers/dri/r300/r300_ioctl.c
src/mesa/drivers/dri/r300/r300_reg.h
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/r300_texstate.c
src/mesa/drivers/dri/r300/radeon_context.c
src/mesa/drivers/dri/r300/radeon_context.h
src/mesa/drivers/dri/r300/radeon_lock.c
src/mesa/drivers/dri/r300/radeon_state.c
src/mesa/drivers/dri/r300/radeon_state.h
src/mesa/drivers/dri/radeon/radeon_ioctl.c
src/mesa/drivers/dri/radeon/radeon_state.c
src/mesa/drivers/dri/s3v/s3v_state.c
src/mesa/drivers/dri/savage/savageioctl.c
src/mesa/drivers/dri/sis/sis6326_clear.c
src/mesa/drivers/dri/sis/sis_clear.c
src/mesa/drivers/dri/sis/sis_screen.c
src/mesa/drivers/dri/sis/sis_state.h
src/mesa/drivers/dri/tdfx/tdfx_render.c
src/mesa/drivers/dri/tdfx/tdfx_tex.c
src/mesa/drivers/dri/trident/trident_state.c
src/mesa/drivers/dri/unichrome/via_ioctl.c
src/mesa/drivers/ggi/ggimesa.c
src/mesa/drivers/glide/fxdd.c
src/mesa/drivers/svga/svgamesa15.c
src/mesa/drivers/svga/svgamesa16.c
src/mesa/drivers/svga/svgamesa24.c
src/mesa/drivers/svga/svgamesa32.c
src/mesa/drivers/svga/svgamesa8.c
src/mesa/drivers/windows/gdi/wmesa.c
src/mesa/drivers/x11/xm_dd.c
src/mesa/main/attrib.c
src/mesa/main/buffers.c
src/mesa/main/context.c
src/mesa/main/dd.h
src/mesa/main/extensions.c
src/mesa/main/fbobject.c
src/mesa/main/get.c
src/mesa/main/get_gen.py
src/mesa/main/getstring.c
src/mesa/main/mipmap.c
src/mesa/main/mtypes.h
src/mesa/main/state.c
src/mesa/main/state.h
src/mesa/main/stencil.c
src/mesa/main/texcompress_s3tc.c
src/mesa/main/texenvprogram.c
src/mesa/main/teximage.c
src/mesa/main/teximage.h
src/mesa/main/texobj.c
src/mesa/main/texobj.h
src/mesa/main/texstate.c
src/mesa/shader/arbprogparse.c
src/mesa/shader/nvfragparse.c
src/mesa/shader/nvprogram.c
src/mesa/shader/nvvertexec.c
src/mesa/shader/nvvertexec.h
src/mesa/shader/nvvertparse.c
src/mesa/shader/program.c
src/mesa/shader/program_instruction.h
src/mesa/shader/programopt.c
src/mesa/swrast/s_arbshader.c
src/mesa/swrast/s_buffers.c
src/mesa/swrast/s_context.c
src/mesa/swrast/s_nvfragprog.c
src/mesa/swrast/s_span.c
src/mesa/swrast/s_texstore.c
src/mesa/swrast/swrast.h
src/mesa/tnl/t_context.c
src/mesa/tnl/t_vb_program.c

index 8504297d0e1e7f96b5f6e0c22964d0b17e3a1c95..7e822e2eb61a1b404ae428f1d50e8c5c034a523e 100644 (file)
@@ -65,5 +65,5 @@ WINDOW_SYSTEM=dri
 
 # gamma are missing because they have not been converted to use the new
 # interface.
-DRI_DIRS = i810 i915 i965 mach64 mga r128 r200 r300 radeon s3v \
+DRI_DIRS = i810 i915tex i915 i965 mach64 mga r128 r200 r300 radeon s3v \
        savage sis tdfx trident unichrome ffb
index 5b69daf0c5ce0a62226e3c5f128de9ae5afcd90d..06a4763c67651d5f8b68f39d92bd4e0a0e9a209c 100644 (file)
@@ -23,6 +23,8 @@ Mesa 6.5.2 is a 6.5 follow-on development release mostly consisting of
 
 <h2>New Features</h2>
 <ul>
+<li>New <code>minstall</code> script to replace normal install program
+<li>Faster fragment program execution in software
 </ul>
 
 <h2>Changes</h2>
@@ -36,6 +38,7 @@ Mesa 6.5.2 is a 6.5 follow-on development release mostly consisting of
 <li>OPTION NV_position_invariant didn't work in NV vertex programs
 <li>glDrawPixels into a user-created framebuffer object could crash Xlib driver
 <li>Line clipping was broken in some circumstances
+<li>fragment.fogcoord register didn't always contain the correct value
 </ul>
 
 
index 43d0f17c85fca7db124aea333e479d8bdc596ab8..feb2abd6cfc79ff1e25f827d8f8e8e97b4892718 100644 (file)
@@ -47,6 +47,7 @@ PROGS = \
        renormal \
        shadowtex \
        singlebuffer \
+       streaming_rect \
        spectex \
        spriteblast \
        stex3d \
diff --git a/progs/demos/streaming_rect.c b/progs/demos/streaming_rect.c
new file mode 100644 (file)
index 0000000..86e0080
--- /dev/null
@@ -0,0 +1,322 @@
+
+/*
+ * GL_ARB_multitexture demo
+ *
+ * Command line options:
+ *    -info      print GL implementation information
+ *
+ *
+ * Brian Paul  November 1998  This program is in the public domain.
+ * Modified on 12 Feb 2002 for > 2 texture units.
+ */
+
+#define GL_GLEXT_PROTOTYPES
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <GL/glut.h>
+
+#include "readtex.h"
+
+
+#define ANIMATE 10
+#define PBO 11
+#define QUIT 100
+
+static GLboolean Animate = GL_TRUE;
+static GLboolean use_pbo = 1;
+static GLboolean whole_rect = 1;
+
+static GLfloat Drift = 0.0;
+static GLfloat drift_increment = 1/255.0;
+static GLfloat Xrot = 20.0, Yrot = 30.0;
+
+static GLuint Width = 1024;
+static GLuint Height = 512;
+
+
+static void Idle( void )
+{
+   if (Animate) {
+
+      Drift += drift_increment;
+      if (Drift >= 1.0)
+         Drift = 0.0;
+
+      glutPostRedisplay();
+   }
+}
+
+static int max( int a, int b ) { return a > b ? a : b; }
+static int min( int a, int b ) { return a < b ? a : b; }
+
+static void DrawObject()
+{
+   GLint size = Width * Height * 4;
+   
+   if (use_pbo) {
+      /* XXX: This is extremely important - semantically makes the buffer
+       * contents undefined, but in practice means that the driver can
+       * release the old copy of the texture and allocate a new one
+       * without waiting for outstanding rendering to complete.
+       */
+      glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, size, NULL, GL_STREAM_DRAW_ARB);
+
+      {
+        char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB);
+      
+        printf("char %d\n", (unsigned char)(Drift * 255));
+
+        memset(image, size, (unsigned char)(Drift * 255));
+      
+        glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT);
+      }
+   
+
+      /* BGRA is required for most hardware paths:
+       */
+      glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0,
+                  GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+   }
+   else {
+      static char *image = NULL;
+
+      if (image == NULL) 
+        image = malloc(size);
+
+      memset(image, size, (unsigned char)(Drift * 255));
+
+      /* BGRA should be the fast path for regular uploads as well.
+       */
+      glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0,
+                  GL_BGRA, GL_UNSIGNED_BYTE, image);
+   }
+
+   {
+      int x,y,w,h;
+
+      if (whole_rect) {
+        x = y = 0;
+        w = Width;
+        h = Height;
+      }
+      else {
+        x = y = 0;
+        w = min(10, Width);
+        h = min(10, Height);
+      }
+
+      glBegin(GL_QUADS);
+
+      glTexCoord2f( x, y);
+      glVertex2f( x, y );
+
+      glTexCoord2f( x, y + h);
+      glVertex2f( x, y + h);
+
+      glTexCoord2f( x + w + .5, y + h);
+      glVertex2f( x + w, y + h );
+
+      glTexCoord2f( x + w, y + .5);
+      glVertex2f( x + w, y );
+
+      glEnd();
+   }
+}
+
+
+
+static void Display( void )
+{
+   static GLint T0 = 0;
+   static GLint Frames = 0;
+   GLint t;
+
+   glClear( GL_COLOR_BUFFER_BIT );
+
+   glPushMatrix();
+      DrawObject();
+   glPopMatrix();
+
+   glutSwapBuffers();
+
+   Frames++;
+
+   t = glutGet(GLUT_ELAPSED_TIME);
+   if (t - T0 >= 1000) {
+      GLfloat seconds = (t - T0) / 1000.0;
+
+      GLfloat fps = Frames / seconds;
+      printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
+
+      drift_increment = 2.2 * seconds / Frames;
+      T0 = t;
+      Frames = 0;
+   }
+}
+
+
+static void Reshape( int width, int height )
+{
+   glViewport( 0, 0, width, height );
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+/*    glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); */
+   gluOrtho2D( 0, width, height, 0 );
+   glMatrixMode( GL_MODELVIEW );
+   glLoadIdentity();
+   glTranslatef(0.375, 0.375, 0);
+}
+
+
+static void ModeMenu(int entry)
+{
+   if (entry==ANIMATE) {
+      Animate = !Animate;
+   }
+   else if (entry==PBO) {
+      use_pbo = !use_pbo;
+   }
+   else if (entry==QUIT) {
+      exit(0);
+   }
+
+   glutPostRedisplay();
+}
+
+
+static void Key( unsigned char key, int x, int y )
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+      case 27:
+         exit(0);
+         break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void SpecialKey( int key, int x, int y )
+{
+   float step = 3.0;
+   (void) x;
+   (void) y;
+
+   switch (key) {
+      case GLUT_KEY_UP:
+         Xrot += step;
+         break;
+      case GLUT_KEY_DOWN:
+         Xrot -= step;
+         break;
+      case GLUT_KEY_LEFT:
+         Yrot += step;
+         break;
+      case GLUT_KEY_RIGHT:
+         Yrot -= step;
+         break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void Init( int argc, char *argv[] )
+{
+   const char *exten = (const char *) glGetString(GL_EXTENSIONS);
+   GLuint texObj, DrawPBO;
+   GLint size;
+
+
+   if (!strstr(exten, "GL_ARB_multitexture")) {
+      printf("Sorry, GL_ARB_multitexture not supported by this renderer.\n");
+      exit(1);
+   }
+
+   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
+   printf("%d x %d max texture size\n", size, size);
+
+   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+   /* allocate two texture objects */
+   glGenTextures(1, &texObj);
+
+   /* setup the texture objects */
+   glActiveTextureARB(GL_TEXTURE0_ARB);
+   glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texObj);
+
+   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+   glGenBuffersARB(1, &DrawPBO);
+
+   glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
+   glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT,
+                  Width * Height * 4, NULL, GL_STREAM_DRAW);
+
+   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+   glEnable(GL_TEXTURE_RECTANGLE_ARB);
+
+   glShadeModel(GL_SMOOTH);
+   glClearColor(0.3, 0.3, 0.4, 1.0);
+
+   if (argc > 1 && strcmp(argv[1], "-info")==0) {
+      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
+      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
+      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
+      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
+   }
+}
+
+
+int main( int argc, char *argv[] )
+{
+   GLint i;
+
+   glutInit( &argc, argv );
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "-w") == 0) {
+         Width = atoi(argv[i+1]);
+         if (Width <= 0) {
+            printf("Error, bad width\n");
+            exit(1);
+         }
+         i++;
+      }
+      else if (strcmp(argv[i], "-h") == 0) {
+         Height = atoi(argv[i+1]);
+         if (Height <= 0) {
+            printf("Error, bad height\n");
+            exit(1);
+         }
+         i++;
+      }
+   }
+
+   glutInitWindowSize( Width, Height );
+   glutInitWindowPosition( 0, 0 );
+   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
+   glutCreateWindow(argv[0] );
+
+   Init( argc, argv );
+
+   glutReshapeFunc( Reshape );
+   glutKeyboardFunc( Key );
+   glutSpecialFunc( SpecialKey );
+   glutDisplayFunc( Display );
+   glutIdleFunc( Idle );
+
+   glutCreateMenu(ModeMenu);
+   glutAddMenuEntry("Toggle Animation", ANIMATE);
+   glutAddMenuEntry("Toggle PBO", PBO);
+   glutAddMenuEntry("Quit", QUIT);
+   glutAttachMenu(GLUT_RIGHT_BUTTON);
+
+   glutMainLoop();
+   return 0;
+}
index 79525a0395e849778ec806c13e32fdc7c7274022..fc98fddb3100ac2afd765a3fd6bb88fc4206eba6 100644 (file)
@@ -38,8 +38,8 @@
 #include <GL/glut.h>
 
 
-static GLsizei MaxSize = 1024;
-static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0;
+static GLsizei MaxSize = 2048;
+static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0;
 static GLboolean ScaleAndBias = GL_FALSE;
 static GLboolean SubImage = GL_FALSE;
 static GLdouble DownloadRate = 0.0;  /* texels/sec */
@@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0;  /* texels/sec */
 static GLuint Mode = 0;
 
 
+/* Try and avoid L2 cache effects by cycling through a small number of
+ * textures.
+ * 
+ * At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will
+ * keep us out of most caches at 32mb total.
+ *
+ * This turns into a fairly interesting question of what exactly you
+ * expect to be in cache in normal usage, and what you think should be
+ * outside.  There's no rules for this, no reason to favour one usage
+ * over another except what the application you care about happens to
+ * resemble most closely.
+ *
+ * - Should the client texture image be in L2 cache?  Has it just been
+ *   generated or read from disk?
+ * - Does the application really use >1 texture, or is it constantly 
+ *   updating one image in-place?
+ *
+ * Different answers will favour different texture upload mechanisms.
+ * To upload an image that is purely outside of cache, a DMA-based
+ * upload will probably win, whereas for small, in-cache textures,
+ * copying looks good.
+ */
+#define NR_TEXOBJ 4
+static GLuint TexObj[NR_TEXOBJ];
+
+
 struct FormatRec {
    GLenum Format;
    GLenum Type;
@@ -116,25 +142,57 @@ TypeStr(GLenum type)
    }
 }
 
+/* On x86, there is a performance cliff for memcpy to texture memory
+ * for sources below 64 byte alignment.  We do our best with this in
+ * the driver, but it is better if the images are correctly aligned to
+ * start with:
+ */
+#define ALIGN (1<<12)
+
+static unsigned align(unsigned value, unsigned a)
+{
+   return (value + a - 1) & ~(a-1);
+}
+
+static int MIN2(int a, int b)
+{
+   return a < b ? a : b;
+}
 
 static void
 MeasureDownloadRate(void)
 {
    const int w = TexWidth + 2 * TexBorder;
    const int h = TexHeight + 2 * TexBorder;
-   const int bytes = w * h * BytesPerTexel(Format);
+   const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN);
+   const int bytes = image_bytes * NR_TEXOBJ;
+   GLubyte *orig_texImage, *orig_getImage;
    GLubyte *texImage, *getImage;
    GLdouble t0, t1, time;
    int count;
    int i;
+   int offset = 0;
+   GLdouble total = 0;         /* ints will tend to overflow */
+
+   printf("allocating %d bytes for %d %dx%d images\n",
+         bytes, NR_TEXOBJ, w, h);
 
-   texImage = (GLubyte *) malloc(bytes);
-   getImage = (GLubyte *) malloc(bytes);
-   if (!texImage || !getImage) {
+   orig_texImage = (GLubyte *) malloc(bytes + ALIGN);
+   orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN);
+   if (!orig_texImage || !orig_getImage) {
       DownloadRate = 0.0;
       return;
    }
 
+   printf("alloc %p %p\n", orig_texImage, orig_getImage);
+
+   texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN);
+   getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);   
+
+   for (i = 1; !(((unsigned)texImage) & i); i<<=1)
+      ;
+   printf("texture image alignment: %d bytes (%p)\n", i, texImage);
+      
    for (i = 0; i < bytes; i++) {
       texImage[i] = i & 0xff;
    }
@@ -166,16 +224,50 @@ MeasureDownloadRate(void)
    count = 0;
    t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
    do {
+      int img = count%NR_TEXOBJ;
+      GLubyte *img_ptr = texImage + img * image_bytes;
+
+      glBindTexture(GL_TEXTURE_2D, TexObj[img]);
+
       if (SubImage && count > 0) {
-         glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h,
+        /* Only update a portion of the image each iteration.  This
+         * is presumably why you'd want to use texsubimage, otherwise
+         * you may as well just call teximage again.
+         *
+         * A bigger question is whether to use a pointer that moves
+         * with each call, ie does the incoming data come from L2
+         * cache under normal circumstances, or is it pulled from
+         * uncached memory?  
+         * 
+         * There's a good argument to say L2 cache, ie you'd expect
+         * the data to have been recently generated.  It's possible
+         * that it could have come from a file read, which may or may
+         * not have gone through the cpu.
+         */
+         glTexSubImage2D(GL_TEXTURE_2D, 0, 
+                        -TexBorder, 
+                        -TexBorder + offset * h/8, 
+                        w, 
+                        h/8,
                          FormatTable[Format].Format,
-                         FormatTable[Format].Type, texImage);
+                         FormatTable[Format].Type, 
+#if 1
+                        texImage /* likely in L2$ */
+#else
+                        img_ptr + offset * bytes/8 /* unlikely in L2$ */
+#endif
+           );
+        offset += 1;
+        offset %= 8;
+        total += w * h / 8;
       }
       else {
          glTexImage2D(GL_TEXTURE_2D, 0,
                       FormatTable[Format].IntFormat, w, h, TexBorder,
                       FormatTable[Format].Format,
-                      FormatTable[Format].Type, texImage);
+                      FormatTable[Format].Type, 
+                     img_ptr);
+        total += w*h;
       }
 
       /* draw a tiny polygon to force texture into texram */
@@ -192,25 +284,12 @@ MeasureDownloadRate(void)
 
    glDisable(GL_TEXTURE_2D);
 
-   printf("w*h=%d  count=%d  time=%f\n", w*h, count, time);
-   DownloadRate = w * h * count / time;
-
-#if 0
-   if (!ScaleAndBias) {
-      /* verify texture readback */
-      glGetTexImage(GL_TEXTURE_2D, 0,
-                    FormatTable[Format].Format,
-                    FormatTable[Format].Type, getImage);
-      for (i = 0; i < w * h; i++) {
-         if (texImage[i] != getImage[i]) {
-            printf("[%d] %d != %d\n", i, texImage[i], getImage[i]);
-         }
-      }
-   }
-#endif
+   printf("total texels=%f  time=%f\n", total, time);
+   DownloadRate = total / time;
+
 
-   free(texImage);
-   free(getImage);
+   free(orig_texImage); 
+   free(orig_getImage); 
 
    {
       GLint err = glGetError();
index cdc63283538b6b13d170047407c5a17bd85d4645..b9ed5c70dc528aa13b425f6734bf4aec6e977902 100644 (file)
@@ -38,7 +38,9 @@ SOURCES = \
        quad-offset-unfilled.c \
        quad-unfilled.c \
        quad-tex-2d.c \
+       quad-tex-pbo.c \
        quad-tex-3d.c \
+       quad-tex-dep.c \
        quad.c \
        quads.c \
        quadstrip.c \
diff --git a/progs/trivial/quad-tex-pbo.c b/progs/trivial/quad-tex-pbo.c
new file mode 100644 (file)
index 0000000..5b63c69
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the name of
+ * Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
+ * ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#define GL_GLEXT_PROTOTYPES
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <GL/glut.h>
+
+
+#define CI_OFFSET_1 16
+#define CI_OFFSET_2 32
+
+GLenum doubleBuffer;
+
+static GLuint DrawPBO;
+
+static void Init(void)
+{
+   fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
+   fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
+   fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
+
+   glClearColor(0.0, 0.0, 1.0, 0.0);
+
+#define SIZE 16
+   {
+      GLubyte tex2d[SIZE][SIZE][4];
+      GLint s, t;
+
+      for (s = 0; s < SIZE; s++) {
+        for (t = 0; t < SIZE; t++) {
+           /* bgra:
+            */
+           tex2d[t][s][0] = 0x30;
+           tex2d[t][s][1] = t*255/(SIZE-1);
+           tex2d[t][s][2] = s*255/(SIZE-1);
+           tex2d[t][s][3] = 0xff;
+        }
+      }
+
+
+      /* put image into DrawPBO */
+      glGenBuffersARB(1, &DrawPBO);
+      glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, DrawPBO);
+      glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
+                     SIZE * SIZE * 4, tex2d, GL_STATIC_DRAW);
+      glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
+
+
+      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
+      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE, SIZE, 0,
+                  GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+      glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
+      glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+      glEnable(GL_TEXTURE_2D);
+   }
+
+}
+
+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 Key(unsigned char key, int x, int y)
+{
+
+    switch (key) {
+      case 27:
+       exit(1);
+      default:
+       return;
+    }
+
+    glutPostRedisplay();
+}
+
+static void Draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT); 
+
+   glBegin(GL_QUADS);
+   glTexCoord2f(1,0); 
+   glVertex3f( 0.9, -0.9, -30.0);
+   glTexCoord2f(1,1); 
+   glVertex3f( 0.9,  0.9, -30.0);
+   glTexCoord2f(0,1); 
+   glVertex3f(-0.9,  0.9, -30.0);
+   glTexCoord2f(0,0); 
+   glVertex3f(-0.9,  -0.9, -30.0);
+   glEnd();
+
+   glFlush();
+
+   if (doubleBuffer) {
+      glutSwapBuffers();
+   }
+}
+
+static GLenum Args(int argc, char **argv)
+{
+    GLint i;
+
+    doubleBuffer = GL_FALSE;
+
+    for (i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-sb") == 0) {
+           doubleBuffer = GL_FALSE;
+       } else if (strcmp(argv[i], "-db") == 0) {
+           doubleBuffer = GL_TRUE;
+       } else {
+           fprintf(stderr, "%s (Bad option).\n", argv[i]);
+           return GL_FALSE;
+       }
+    }
+    return GL_TRUE;
+}
+
+int main(int argc, char **argv)
+{
+    GLenum type;
+
+    glutInit(&argc, argv);
+
+    if (Args(argc, argv) == GL_FALSE) {
+       exit(1);
+    }
+
+    glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
+
+    type = GLUT_RGB;
+    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
+    glutInitDisplayMode(type);
+
+    if (glutCreateWindow("First Tri") == GL_FALSE) {
+       exit(1);
+    }
+
+    Init();
+
+    glutReshapeFunc(Reshape);
+    glutKeyboardFunc(Key);
+    glutDisplayFunc(Draw);
+    glutMainLoop();
+       return 0;
+}
index d38643639650f1d581725555c5d68e11424a962e..bad09ce4ccf9254f659f38e7c4355f5b58daad18 100644 (file)
@@ -722,6 +722,69 @@ static const __DRIinterfaceMethods interface_methods = {
     __glXGetMscRateOML,
 };
 
+#define DRM_MAX_FDS 16
+static struct {
+   char *BusID;
+   int fd;
+   int refcount;
+} connection[DRM_MAX_FDS];
+
+static int nr_fds = 0;
+
+int drmOpenOnce(void *unused, 
+               const char *BusID,
+               int *newlyopened)
+{
+   int i;
+   int fd;
+   
+   for (i = 0; i < nr_fds; i++)
+      if (strcmp(BusID, connection[i].BusID) == 0) {
+        connection[i].refcount++;
+        *newlyopened = 0;
+        return connection[i].fd;
+      }
+
+   fd = drmOpen(unused, BusID);
+   if (fd <= 0 || nr_fds == DRM_MAX_FDS)
+      return fd;
+   
+   connection[nr_fds].BusID = strdup(BusID);
+   connection[nr_fds].fd = fd;
+   connection[nr_fds].refcount = 1;
+   *newlyopened = 1;
+
+   if (0)
+      fprintf(stderr, "saved connection %d for %s %d\n", 
+              nr_fds, connection[nr_fds].BusID, 
+              strcmp(BusID, connection[nr_fds].BusID));
+
+   nr_fds++;
+
+   return fd;   
+}
+
+void drmCloseOnce(int fd)
+{
+   int i;
+
+   
+
+   for (i = 0; i < nr_fds; i++) {
+      if (fd == connection[i].fd) {
+        if (--connection[i].refcount == 0) {
+           drmClose(connection[i].fd);
+           free(connection[i].BusID);
+           
+           if (i < --nr_fds) 
+              connection[i] = connection[nr_fds];
+
+           return;
+        }
+      }
+   }
+}
+
 
 /**
  * Perform the required libGL-side initialization and call the client-side
@@ -773,7 +836,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
     framebuffer.dev_priv = NULL;
 
     if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
-       fd = drmOpen(NULL,BusID);
+        int newlyopened;
+       fd = drmOpenOnce(NULL,BusID, &newlyopened);
        Xfree(BusID); /* No longer needed */
 
        err_msg = "open DRM";
@@ -800,7 +864,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
                }
 
                err_msg = "XF86DRIAuthConnection";
-               if (XF86DRIAuthConnection(dpy, scrn, magic)) {
+               if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) {
                    char *driverName;
 
                    /*
@@ -904,7 +968,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
        }
 
        if ( fd >= 0 ) {
-           (void)drmClose(fd);
+           (void)drmCloseOnce(fd);
        }
 
        (void)XF86DRICloseConnection(dpy, scrn);
index 524249e8a55f7242fdc730cadb975f29c492558a..2a20bddb1b6ded4e50e5c2029f56714a53658415 100644 (file)
@@ -372,10 +372,14 @@ dfbSetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
 }
 
 static void
-dfbClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-          GLint x, GLint y, GLint width, GLint height )
+dfbClear( GLcontext *ctx, GLbitfield mask )
 {
      IDirectFBGL_data *data = (IDirectFBGL_data*) ctx->DriverCtx;
+     int x = ctx->DrawBuffer->_Xmin;
+     int y = ctx->DrawBuffer->_Ymin;
+     int width = ctx->DrawBuffer->_Xmax - x;
+     int height = ctx->DrawBuffer->_Ymax - y;
+     GLboolean all = (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->height)
      
      if (mask & BUFFER_BIT_FRONT_LEFT &&
          ctx->Color.ColorMask[0]      &&
@@ -420,7 +424,7 @@ dfbClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
      }
      
      if (mask)
-          _swrast_Clear( ctx, mask, all, x, y, width, height );
+          _swrast_Clear( ctx, mask );
 }        
           
      
index 1040194d0d0d6d1291c1f8cc4ec3a1240c1cf7f5..5261a4b55d1ef36628cbe7b349a685621870fab6 100644 (file)
@@ -9,7 +9,12 @@ COMMON_SOURCES = \
         ../common/vblank.c \
         ../common/dri_util.c \
         ../common/xmlconfig.c \
-        ../common/drirenderbuffer.c
+        ../common/drirenderbuffer.c 
+
+COMMON_BM_SOURCES = \
+       ../common/dri_bufmgr.c \
+       ../common/dri_drmpool.c
+
 
 ifeq ($(WINDOW_SYSTEM),dri)
 WINOBJ=
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.c b/src/mesa/drivers/dri/common/dri_bufmgr.c
new file mode 100644 (file)
index 0000000..370b56c
--- /dev/null
@@ -0,0 +1,493 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include <xf86drm.h>
+#include <stdlib.h>
+#include "glthread.h"
+#include "errno.h"
+#include "dri_bufmgr.h"
+#include "string.h"
+#include "imports.h"
+#include "dri_bufpool.h"
+
+_glthread_DECLARE_STATIC_MUTEX(bmMutex);
+
+/*
+ * TODO: Introduce fence pools in the same way as 
+ * buffer object pools.
+ */
+
+
+
+typedef struct _DriFenceObject
+{
+   int fd;
+   _glthread_Mutex mutex;
+   int refCount;
+   const char *name;
+   drmFence fence;
+} DriFenceObject;
+
+typedef struct _DriBufferObject
+{
+   DriBufferPool *pool;
+   _glthread_Mutex mutex;
+   int refCount;
+   const char *name;
+   unsigned flags;
+   unsigned hint;
+   unsigned alignment;
+   void *private;
+} DriBufferObject;
+
+
+void
+bmError(int val, const char *file, const char *function, int line)
+{
+   _mesa_printf("Fatal video memory manager error \"%s\".\n"
+                "Check kernel logs or set the LIBGL_DEBUG\n"
+                "environment variable to \"verbose\" for more info.\n"
+                "Detected in file %s, line %d, function %s.\n",
+                strerror(-val), file, line, function);
+#ifndef NDEBUG
+   abort();
+#else
+   abort();
+#endif
+}
+
+DriFenceObject *
+driFenceBuffers(int fd, char *name, unsigned flags)
+{
+   DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence));
+   int ret;
+
+   if (!fence)
+      BM_CKFATAL(-EINVAL);
+
+   _glthread_LOCK_MUTEX(bmMutex);
+   fence->refCount = 1;
+   fence->name = name;
+   fence->fd = fd;
+   _glthread_INIT_MUTEX(fence->mutex);
+   ret = drmFenceBuffers(fd, flags, &fence->fence);
+   _glthread_UNLOCK_MUTEX(bmMutex);
+   if (ret) {
+      free(fence);
+      BM_CKFATAL(ret);
+   }
+   return fence;
+}
+
+
+unsigned 
+driFenceType(DriFenceObject * fence)
+{
+    unsigned ret;
+
+    _glthread_LOCK_MUTEX(bmMutex);
+    ret = fence->fence.flags;
+    _glthread_UNLOCK_MUTEX(bmMutex);
+    
+    return ret;
+}
+
+
+DriFenceObject *
+driFenceReference(DriFenceObject * fence)
+{
+   _glthread_LOCK_MUTEX(bmMutex);
+   ++fence->refCount;
+   _glthread_UNLOCK_MUTEX(bmMutex);
+   return fence;
+}
+
+void
+driFenceUnReference(DriFenceObject * fence)
+{
+   if (!fence)
+      return;
+
+   _glthread_LOCK_MUTEX(bmMutex);
+   if (--fence->refCount == 0) {
+      drmFenceDestroy(fence->fd, &fence->fence);
+      free(fence);
+   }
+   _glthread_UNLOCK_MUTEX(bmMutex);
+}
+
+void
+driFenceFinish(DriFenceObject * fence, unsigned type, int lazy)
+{
+   int ret;
+   unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0;
+
+   _glthread_LOCK_MUTEX(fence->mutex);
+   ret = drmFenceWait(fence->fd, flags, &fence->fence, type);
+   _glthread_UNLOCK_MUTEX(fence->mutex);
+   BM_CKFATAL(ret);
+}
+
+int
+driFenceSignaled(DriFenceObject * fence, unsigned type)
+{
+   int signaled;
+   int ret;
+
+   if (fence == NULL)
+      return GL_TRUE;
+
+   _glthread_LOCK_MUTEX(fence->mutex);
+   ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled);
+   _glthread_UNLOCK_MUTEX(fence->mutex);
+   BM_CKFATAL(ret);
+   return signaled;
+}
+
+
+extern drmBO *
+driBOKernel(struct _DriBufferObject *buf)
+{
+   drmBO *ret;
+
+   assert(buf->private != NULL);
+   ret = buf->pool->kernel(buf->pool, buf->private);
+   if (!ret)
+      BM_CKFATAL(-EINVAL);
+
+   return ret;
+}
+
+void
+driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
+{
+   assert(buf->private != NULL);
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, lazy));
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+}
+
+void *
+driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
+{
+   void *virtual;
+
+   assert(buf->private != NULL);
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   BM_CKFATAL(buf->pool->map(buf->pool, buf->private, flags, hint, &virtual));
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+   return virtual;
+}
+
+void
+driBOUnmap(struct _DriBufferObject *buf)
+{
+   assert(buf->private != NULL);
+
+   buf->pool->unmap(buf->pool, buf->private);
+}
+
+unsigned long
+driBOOffset(struct _DriBufferObject *buf)
+{
+   unsigned long ret;
+
+   assert(buf->private != NULL);
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   ret = buf->pool->offset(buf->pool, buf->private);
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+   return ret;
+}
+
+unsigned
+driBOFlags(struct _DriBufferObject *buf)
+{
+   unsigned ret;
+
+   assert(buf->private != NULL);
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   ret = buf->pool->flags(buf->pool, buf->private);
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+   return ret;
+}
+
+struct _DriBufferObject *
+driBOReference(struct _DriBufferObject *buf)
+{
+   _glthread_LOCK_MUTEX(bmMutex);
+   if (++buf->refCount == 1) {
+      BM_CKFATAL(-EINVAL);
+   }
+   _glthread_UNLOCK_MUTEX(bmMutex);
+   return buf;
+}
+
+void
+driBOUnReference(struct _DriBufferObject *buf)
+{
+   int tmp;
+
+   if (!buf)
+      return;
+
+   _glthread_LOCK_MUTEX(bmMutex);
+   tmp = --buf->refCount;
+   _glthread_UNLOCK_MUTEX(bmMutex);
+   if (!tmp) {
+      buf->pool->destroy(buf->pool, buf->private);
+      free(buf);
+   }
+}
+
+void
+driBOData(struct _DriBufferObject *buf,
+          unsigned size, const void *data, unsigned flags)
+{
+   void *virtual;
+   int newBuffer;
+   struct _DriBufferPool *pool;
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   pool = buf->pool;
+   if (!pool->create) {
+      _mesa_error(NULL, GL_INVALID_OPERATION,
+                  "driBOData called on invalid buffer\n");
+      BM_CKFATAL(-EINVAL);
+   }
+   newBuffer = !buf->private || (pool->size(pool, buf->private) < size) ||
+      pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
+                DRM_BO_HINT_DONT_BLOCK, &virtual);
+
+   if (newBuffer) {
+      if (buf->private)
+         pool->destroy(pool, buf->private);
+      if (!flags)
+         flags = buf->flags;
+      buf->private = pool->create(pool, size, flags, 0, buf->alignment);
+      if (!buf->private)
+         BM_CKFATAL(-ENOMEM);
+      BM_CKFATAL(pool->map(pool, buf->private,
+                           DRM_BO_FLAG_WRITE,
+                           DRM_BO_HINT_DONT_BLOCK, &virtual));
+   }
+
+   if (data != NULL)
+      memcpy(virtual, data, size);
+
+   BM_CKFATAL(pool->unmap(pool, buf->private));
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+}
+
+void
+driBOSubData(struct _DriBufferObject *buf,
+             unsigned long offset, unsigned long size, const void *data)
+{
+   void *virtual;
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   if (size && data) {
+      BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
+                                DRM_BO_FLAG_WRITE, 0, &virtual));
+      memcpy((unsigned char *) virtual + offset, data, size);
+      BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
+   }
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+}
+
+void
+driBOGetSubData(struct _DriBufferObject *buf,
+                unsigned long offset, unsigned long size, void *data)
+{
+   void *virtual;
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   if (size && data) {
+      BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
+                                DRM_BO_FLAG_READ, 0, &virtual));
+      memcpy(data, (unsigned char *) virtual + offset, size);
+      BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
+   }
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+}
+
+void
+driBOSetStatic(struct _DriBufferObject *buf,
+               unsigned long offset,
+               unsigned long size, void *virtual, unsigned flags)
+{
+   _glthread_LOCK_MUTEX(buf->mutex);
+   if (buf->private != NULL) {
+      _mesa_error(NULL, GL_INVALID_OPERATION,
+                  "Invalid buffer for setStatic\n");
+      BM_CKFATAL(-EINVAL);
+   }
+   if (buf->pool->setstatic == NULL) {
+      _mesa_error(NULL, GL_INVALID_OPERATION,
+                  "Invalid buffer pool for setStatic\n");
+      BM_CKFATAL(-EINVAL);
+   }
+
+   if (!flags)
+      flags = buf->flags;
+
+   buf->private = buf->pool->setstatic(buf->pool, offset, size,
+                                       virtual, flags);
+   if (!buf->private) {
+      _mesa_error(NULL, GL_OUT_OF_MEMORY,
+                  "Invalid buffer pool for setStatic\n");
+      BM_CKFATAL(-ENOMEM);
+   }
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+}
+
+
+
+void
+driGenBuffers(struct _DriBufferPool *pool,
+              const char *name,
+              unsigned n,
+              struct _DriBufferObject *buffers[],
+              unsigned alignment, unsigned flags, unsigned hint)
+{
+   struct _DriBufferObject *buf;
+   int i;
+
+   flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
+      DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
+
+
+   for (i = 0; i < n; ++i) {
+      buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
+      if (!buf)
+         BM_CKFATAL(-ENOMEM);
+
+      _glthread_INIT_MUTEX(buf->mutex);
+      _glthread_LOCK_MUTEX(buf->mutex);
+      _glthread_LOCK_MUTEX(bmMutex);
+      buf->refCount = 1;
+      _glthread_UNLOCK_MUTEX(bmMutex);
+      buf->flags = flags;
+      buf->hint = hint;
+      buf->name = name;
+      buf->alignment = alignment;
+      buf->pool = pool;
+      _glthread_UNLOCK_MUTEX(buf->mutex);
+      buffers[i] = buf;
+   }
+}
+
+void
+driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
+{
+   int i;
+
+   for (i = 0; i < n; ++i) {
+      driBOUnReference(buffers[i]);
+   }
+}
+
+
+void
+driInitBufMgr(int fd)
+{
+   ;
+}
+
+
+void
+driBOCreateList(int target, drmBOList * list)
+{
+   _glthread_LOCK_MUTEX(bmMutex);
+   BM_CKFATAL(drmBOCreateList(20, list));
+   _glthread_UNLOCK_MUTEX(bmMutex);
+}
+
+void
+driBOResetList(drmBOList * list)
+{
+   _glthread_LOCK_MUTEX(bmMutex);
+   BM_CKFATAL(drmBOResetList(list));
+   _glthread_UNLOCK_MUTEX(bmMutex);
+}
+
+void
+driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
+                 unsigned flags, unsigned mask)
+{
+   int newItem;
+
+   _glthread_LOCK_MUTEX(buf->mutex);
+   _glthread_LOCK_MUTEX(bmMutex);
+   BM_CKFATAL(drmAddValidateItem(list, driBOKernel(buf),
+                                 flags, mask, &newItem));
+   _glthread_UNLOCK_MUTEX(bmMutex);
+
+   /*
+    * Tell userspace pools to validate the buffer. This should be a 
+    * noop if the pool is already validated.
+    * FIXME: We should have a list for this as well.
+    */
+
+   if (buf->pool->validate) {
+      BM_CKFATAL(buf->pool->validate(buf->pool, buf->private));
+   }
+
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+}
+
+void
+driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
+{
+   _glthread_LOCK_MUTEX(buf->mutex);
+   BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
+   _glthread_UNLOCK_MUTEX(buf->mutex);
+
+}
+
+void
+driBOValidateList(int fd, drmBOList * list)
+{
+   _glthread_LOCK_MUTEX(bmMutex);
+   BM_CKFATAL(drmBOValidateList(fd, list));
+   _glthread_UNLOCK_MUTEX(bmMutex);
+}
+
+void
+driPoolTakeDown(struct _DriBufferPool *pool)
+{
+   pool->takeDown(pool);
+
+}
diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.h b/src/mesa/drivers/dri/common/dri_bufmgr.h
new file mode 100644 (file)
index 0000000..01f149a
--- /dev/null
@@ -0,0 +1,99 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _DRI_BUFMGR_H_
+#define _DRI_BUFMGR_H_
+#include <xf86drm.h>
+
+
+struct _DriFenceObject;
+struct _DriBufferObject;
+struct _DriBufferPool;
+
+extern struct _DriFenceObject *driFenceBuffers(int fd, char *name,
+                                               unsigned flags);
+
+extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence);
+
+extern void driFenceUnReference(struct _DriFenceObject *fence);
+
+extern void
+driFenceFinish(struct _DriFenceObject *fence, unsigned type, int lazy);
+
+extern int driFenceSignaled(struct _DriFenceObject *fence, unsigned type);
+extern unsigned driFenceType(struct _DriFenceObject *fence);
+
+/*
+ * Return a pointer to the libdrm buffer object this DriBufferObject
+ * uses.
+ */
+
+extern drmBO *driBOKernel(struct _DriBufferObject *buf);
+extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags,
+                      unsigned hint);
+extern void driBOUnmap(struct _DriBufferObject *buf);
+extern unsigned long driBOOffset(struct _DriBufferObject *buf);
+extern unsigned driBOFlags(struct _DriBufferObject *buf);
+extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf);
+extern void driBOUnReference(struct _DriBufferObject *buf);
+extern void driBOData(struct _DriBufferObject *r_buf,
+                      unsigned size, const void *data, unsigned flags);
+extern void driBOSubData(struct _DriBufferObject *buf,
+                         unsigned long offset, unsigned long size,
+                         const void *data);
+extern void driBOGetSubData(struct _DriBufferObject *buf,
+                            unsigned long offset, unsigned long size,
+                            void *data);
+extern void driGenBuffers(struct _DriBufferPool *pool,
+                          const char *name,
+                          unsigned n,
+                          struct _DriBufferObject *buffers[],
+                          unsigned alignment, unsigned flags, unsigned hint);
+extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]);
+extern void driInitBufMgr(int fd);
+extern void driBOCreateList(int target, drmBOList * list);
+extern void driBOResetList(drmBOList * list);
+extern void driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
+                             unsigned flags, unsigned mask);
+extern void driBOValidateList(int fd, drmBOList * list);
+
+extern void driBOFence(struct _DriBufferObject *buf,
+                       struct _DriFenceObject *fence);
+
+extern void driPoolTakeDown(struct _DriBufferPool *pool);
+extern void driBOSetStatic(struct _DriBufferObject *buf,
+                           unsigned long offset,
+                           unsigned long size, void *virtual, unsigned flags);
+extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy);
+extern void driPoolTakeDown(struct _DriBufferPool *pool);
+
+#endif
diff --git a/src/mesa/drivers/dri/common/dri_bufpool.h b/src/mesa/drivers/dri/common/dri_bufpool.h
new file mode 100644 (file)
index 0000000..c6fb2c3
--- /dev/null
@@ -0,0 +1,86 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _DRI_BUFPOOL_H_
+#define _DRI_BUFPOOL_H_
+
+#include <xf86drm.h>
+struct _DriFenceObject;
+
+typedef struct _DriBufferPool
+{
+   int fd;
+   int (*map) (struct _DriBufferPool * pool, void *private,
+               unsigned flags, int hint, void **virtual);
+   int (*unmap) (struct _DriBufferPool * pool, void *private);
+   int (*destroy) (struct _DriBufferPool * pool, void *private);
+   unsigned long (*offset) (struct _DriBufferPool * pool, void *private);
+   unsigned (*flags) (struct _DriBufferPool * pool, void *private);
+   unsigned long (*size) (struct _DriBufferPool * pool, void *private);
+   void *(*create) (struct _DriBufferPool * pool, unsigned long size,
+                    unsigned flags, unsigned hint, unsigned alignment);
+   int (*fence) (struct _DriBufferPool * pool, void *private,
+                 struct _DriFenceObject * fence);
+   drmBO *(*kernel) (struct _DriBufferPool * pool, void *private);
+   int (*validate) (struct _DriBufferPool * pool, void *private);
+   void *(*setstatic) (struct _DriBufferPool * pool, unsigned long offset,
+                       unsigned long size, void *virtual, unsigned flags);
+   int (*waitIdle) (struct _DriBufferPool *pool, void *private,
+                   int lazy);
+   void (*takeDown) (struct _DriBufferPool * pool);
+   void *data;
+} DriBufferPool;
+
+extern void bmError(int val, const char *file, const char *function,
+                    int line);
+#define BM_CKFATAL(val)                                               \
+  do{                                                         \
+    int tstVal = (val);                                               \
+    if (tstVal)                                               \
+      bmError(tstVal, __FILE__, __FUNCTION__, __LINE__);       \
+  } while(0);
+
+
+
+
+
+/*
+ * Builtin pools.
+ */
+
+/*
+ * Kernel buffer objects. Size in multiples of page size. Page size aligned.
+ */
+
+extern struct _DriBufferPool *driDRMPoolInit(int fd);
+extern struct _DriBufferPool *driDRMStaticPoolInit(int fd);
+
+#endif
diff --git a/src/mesa/drivers/dri/common/dri_drmpool.c b/src/mesa/drivers/dri/common/dri_drmpool.c
new file mode 100644 (file)
index 0000000..b5b324b
--- /dev/null
@@ -0,0 +1,227 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <xf86drm.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "dri_bufpool.h"
+
+/*
+ * Buffer pool implementation using DRM buffer objects as DRI buffer objects.
+ */
+
+static void *
+pool_create(struct _DriBufferPool *pool,
+            unsigned long size, unsigned flags, unsigned hint,
+            unsigned alignment)
+{
+   drmBO *buf = (drmBO *) malloc(sizeof(*buf));
+   int ret;
+   unsigned pageSize = getpagesize();
+
+   if (!buf)
+      return NULL;
+
+   if ((alignment > pageSize) && (alignment % pageSize)) {
+      return NULL;
+   }
+
+   ret = drmBOCreate(pool->fd, 0, size, alignment / pageSize,
+                    NULL, drm_bo_type_dc,
+                     flags, hint, buf);
+   if (ret) {
+      free(buf);
+      return NULL;
+   }
+
+   return (void *) buf;
+}
+
+static int
+pool_destroy(struct _DriBufferPool *pool, void *private)
+{
+   int ret;
+   drmBO *buf = (drmBO *) private;
+   ret = drmBODestroy(pool->fd, buf);
+   free(buf);
+   return ret;
+}
+
+static int
+pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
+         int hint, void **virtual)
+{
+   drmBO *buf = (drmBO *) private;
+
+   return drmBOMap(pool->fd, buf, flags, hint, virtual);
+}
+
+static int
+pool_unmap(struct _DriBufferPool *pool, void *private)
+{
+   drmBO *buf = (drmBO *) private;
+   return drmBOUnmap(pool->fd, buf);
+}
+
+static unsigned long
+pool_offset(struct _DriBufferPool *pool, void *private)
+{
+   drmBO *buf = (drmBO *) private;
+   return buf->offset;
+}
+
+static unsigned
+pool_flags(struct _DriBufferPool *pool, void *private)
+{
+   drmBO *buf = (drmBO *) private;
+   return buf->flags;
+}
+
+
+static unsigned long
+pool_size(struct _DriBufferPool *pool, void *private)
+{
+   drmBO *buf = (drmBO *) private;
+   return buf->size;
+}
+
+static int
+pool_fence(struct _DriBufferPool *pool, void *private,
+           struct _DriFenceObject *fence)
+{
+   /*
+    * Noop. The kernel handles all fencing.
+    */
+
+   return 0;
+}
+
+static drmBO *
+pool_kernel(struct _DriBufferPool *pool, void *private)
+{
+   return (drmBO *) private;
+}
+
+static int
+pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
+{
+   drmBO *buf = (drmBO *) private;
+   return drmBOWaitIdle(pool->fd, buf, (lazy) ? DRM_BO_HINT_WAIT_LAZY:0);
+}
+
+    
+static void
+pool_takedown(struct _DriBufferPool *pool)
+{
+   free(pool);
+}
+
+
+struct _DriBufferPool *
+driDRMPoolInit(int fd)
+{
+   struct _DriBufferPool *pool;
+
+   pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
+
+   if (!pool)
+      return NULL;
+
+   pool->fd = fd;
+   pool->map = &pool_map;
+   pool->unmap = &pool_unmap;
+   pool->destroy = &pool_destroy;
+   pool->offset = &pool_offset;
+   pool->flags = &pool_flags;
+   pool->size = &pool_size;
+   pool->create = &pool_create;
+   pool->fence = &pool_fence;
+   pool->kernel = &pool_kernel;
+   pool->validate = NULL;
+   pool->setstatic = NULL;
+   pool->waitIdle = &pool_waitIdle;
+   pool->takeDown = &pool_takedown;
+   pool->data = NULL;
+   return pool;
+}
+
+
+static void *
+pool_setstatic(struct _DriBufferPool *pool, unsigned long offset,
+               unsigned long size, void *virtual, unsigned flags)
+{
+   drmBO *buf = (drmBO *) malloc(sizeof(*buf));
+   int ret;
+
+   if (!buf)
+      return NULL;
+
+   ret = drmBOCreate(pool->fd, offset, size, 0, NULL, drm_bo_type_fake,
+                     flags, 0, buf);
+
+   if (ret) {
+      free(buf);
+      return NULL;
+   }
+
+   buf->virtual = virtual;
+
+   return (void *) buf;
+}
+
+
+struct _DriBufferPool *
+driDRMStaticPoolInit(int fd)
+{
+   struct _DriBufferPool *pool;
+
+   pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
+
+   if (!pool)
+      return NULL;
+
+   pool->fd = fd;
+   pool->map = &pool_map;
+   pool->unmap = &pool_unmap;
+   pool->destroy = &pool_destroy;
+   pool->offset = &pool_offset;
+   pool->flags = &pool_flags;
+   pool->size = &pool_size;
+   pool->create = NULL;
+   pool->fence = &pool_fence;
+   pool->kernel = &pool_kernel;
+   pool->validate = NULL;
+   pool->setstatic = &pool_setstatic;
+   pool->waitIdle = &pool_waitIdle;
+   pool->takeDown = &pool_takedown;
+   pool->data = NULL;
+   return pool;
+}
index 1ca2756e012315f0d87e63948ee7dfca7fa1a95d..e7f07569f4e21860386b4d19357b994c2868b6e5 100644 (file)
@@ -849,7 +849,7 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv
        (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
        (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
        _mesa_free(psp->pDevPriv);
-       (void)drmClose(psp->fd);
+       (void)drmCloseOnce(psp->fd);
        if ( psp->modes != NULL ) {
            (*dri_interface->destroyContextModes)( psp->modes );
        }
index 885d5899e0f46bb7123c8ad5870c68ef6e53e931..e43e653250033b20b732f15e9e410303d2608365 100644 (file)
@@ -87,15 +87,15 @@ typedef struct __DRIutilversionRec2    __DRIutilversion2;
 #define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp)                            \
 do {                                                                    \
     while (*(pdp->pStamp) != pdp->lastStamp) {                          \
-       DRM_UNLOCK(psp->fd, &psp->pSAREA->lock,                         \
-                  pdp->driContextPriv->hHWContext);                    \
+        register unsigned int hwContext = psp->pSAREA->lock.lock &      \
+                    ~(DRM_LOCK_HELD | DRM_LOCK_CONT);                  \
+       DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext);             \
                                                                         \
        DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);     \
        DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
        DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);   \
                                                                         \
-       DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock,                     \
-                      pdp->driContextPriv->hHWContext);                \
+       DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext);         \
     }                                                                   \
 } while (0)
 
index 9cd5a12b7dc2098a252118b5e6efa1e208608eca..e8dfcbe2543be13ed6b405fa4553d908ee8b5c55 100644 (file)
@@ -249,8 +249,7 @@ ffb_do_clear(GLcontext *ctx, __DRIdrawablePrivate *dPriv)
        }
 }
 
-void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-               GLint cxFoo, GLint cyFoo, GLint cwidthFoo, GLint cheightFoo)
+void ffbDDClear(GLcontext *ctx, GLbitfield mask)
 {
        ffbContextPtr fmesa = FFB_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
@@ -334,6 +333,6 @@ void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
        }
 
        if (mask) 
-               _swrast_Clear(ctx, mask, 0, 0, 0, 0, 0);
+               _swrast_Clear(ctx, mask);
 }
 
index 4b707f19b2ae0c73f749fbc90b6bcfee841e2011..c3b8ce714b335811ca4d74975e1daffcb4380856 100644 (file)
@@ -1,9 +1,6 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */
-
 #ifndef _FFB_CLEAR_H
 #define _FFB_CLEAR_H
 
-extern void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                      GLint cx, GLint cy, GLint cwidth, GLint cheight);
+extern void ffbDDClear(GLcontext *ctx, GLbitfield mask);
 
 #endif /* !(_FFB_CLEAR_H) */
index 7c1e4393645b0671f605f6e3ae3727aecee147a0..215aaf8ffbaff0b72075afec3972b345934263f4 100644 (file)
@@ -568,8 +568,7 @@ ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
                         */
                        ffbDDClear(fmesa->glCtx,
                                   (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT |
-                                   BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL),
-                                  1, 0, 0, 0, 0);
+                                   BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL));
                }
        } else {
                _mesa_make_current(NULL, NULL, NULL);
index 1d5ce20995a1dd370fb26fc84ca1863e6a4dac28..8dbe0a97caa408ea5293847ad8e3544230e2b2a2 100644 (file)
@@ -205,8 +205,7 @@ static void gammaDDBlendFuncSeparate( GLcontext *ctx,
  * Buffer clear
  */
 
-static void gammaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                              GLint cx, GLint cy, GLint cw, GLint ch )
+static void gammaDDClear( GLcontext *ctx, GLbitfield mask )
 {
    gammaContextPtr gmesa = GAMMA_CONTEXT(ctx);
    GLINTDRIPtr gDRIPriv = (GLINTDRIPtr)gmesa->driScreen->pDevPriv;
@@ -410,7 +409,7 @@ static void gammaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
 #endif
 
    if ( mask )
-      _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+      _swrast_Clear( ctx, mask );
 }
 
 /* =============================================================
index 9e52d80a8b93a1b9c65f932a61317abbb02f7f77..57c84193faf42464c42d64ab2650eb87a6fc3108 100644 (file)
@@ -48,8 +48,7 @@ static drmBufPtr i810_get_buffer_ioctl( i810ContextPtr imesa )
 
 #define DEPTH_SCALE ((1<<16)-1)
 
-static void i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                      GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo ) 
+static void i810Clear( GLcontext *ctx, GLbitfield mask )
 {
    i810ContextPtr imesa = I810_CONTEXT( ctx );
    __DRIdrawablePrivate *dPriv = imesa->driDrawable;
@@ -142,7 +141,7 @@ static void i810Clear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    }
 
    if (mask) 
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
 }
 
 
index 17fde2f4804c11cf17253061f2b364e4314ca7de..dbf5f043498fb71f1cdf299330c6ff0e83f91026 100644 (file)
@@ -395,13 +395,15 @@ static void draw_poly(i830ContextPtr i830,
 
 void 
 i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
-                 GLboolean all,
-                 GLint cx, GLint cy, GLint cw, GLint ch)
+                 GLboolean allFoo,
+                 GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
 {
    i830ContextPtr i830 = I830_CONTEXT( intel );
    __DRIdrawablePrivate *dPriv = intel->driDrawable;
    intelScreenPrivate *screen = intel->intelScreen;
    int x0, y0, x1, y1;
+   GLint cx, cy, cw, ch;
+   GLboolean all;
 
    INTEL_FIREVERTICES(intel);
    SET_STATE( i830, meta );
@@ -411,6 +413,14 @@ i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
 
    LOCK_HARDWARE(intel);
 
+   /* get clear bounds after locking */
+   cx = intel->ctx.DrawBuffer->_Xmin;
+   cy = intel->ctx.DrawBuffer->_Ymin;
+   cw = intel->ctx.DrawBuffer->_Xmax - cx;
+   ch = intel->ctx.DrawBuffer->_Ymax - cy;
+   all = (cw == intel->ctx.DrawBuffer->Width &&
+          ch == intel->ctx.DrawBuffer->Height);
+
    if(!all) {
       x0 = cx;
       y0 = cy;
index 0f3e6885f378059e6b75d34be2c73771b9b49dd3..7160234bced494476c1b0590700571bf6a94b32a 100644 (file)
@@ -29,6 +29,7 @@
 #include "macros.h"
 #include "enums.h"
 
+#include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "intel_batchbuffer.h"
 
@@ -937,6 +938,8 @@ static void i915ProgramStringNotify( GLcontext *ctx,
       ctx->Driver.Enable( ctx, GL_FRAGMENT_PROGRAM_ARB, 
                          ctx->FragmentProgram.Enabled );
    }
+
+   _tnl_program_string(ctx, target, prog);
 }
 
 
index 3ab5dbfd68531b91326fb48f7d971c54a5eed69f..1be7ac4c48531fe81624f7f75f378648e22b9012 100644 (file)
@@ -493,14 +493,16 @@ static void draw_poly(i915ContextPtr i915,
 
 
 void 
-i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
-                 GLboolean all,
-                 GLint cx, GLint cy, GLint cw, GLint ch)
+i915ClearWithTris(intelContextPtr intel, GLbitfield buffers,
+                 GLboolean allFoo,
+                 GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
 {
    i915ContextPtr i915 = I915_CONTEXT( intel );
    __DRIdrawablePrivate *dPriv = intel->driDrawable;
    intelScreenPrivate *screen = intel->intelScreen;
    int x0, y0, x1, y1;
+   GLint cx, cy, cw, ch;
+   GLboolean all;
 
    SET_STATE( i915, meta ); 
    set_initial_state( i915 ); 
@@ -509,6 +511,14 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
 
    LOCK_HARDWARE(intel);
 
+   /* get clear bounds after locking */
+   cx = intel->ctx.DrawBuffer->_Xmin;
+   cy = intel->ctx.DrawBuffer->_Ymin;
+   cw = intel->ctx.DrawBuffer->_Xmax - cx;
+   ch = intel->ctx.DrawBuffer->_Ymax - cy;
+   all = (cw == intel->ctx.DrawBuffer->Width &&
+          ch == intel->ctx.DrawBuffer->Height);
+
    if (!all) {
       x0 = cx;
       y0 = cy;
@@ -525,7 +535,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
     * The active cliprects will be applied as for any other geometry.
     */
 
-   if (mask & BUFFER_BIT_FRONT_LEFT) { 
+   if (buffers & BUFFER_BIT_FRONT_LEFT) { 
       set_no_depth_stencil_write( i915 );
       set_color_mask( i915, GL_TRUE );
       set_draw_region( i915, &screen->front );
@@ -536,7 +546,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
                0, 0, 0, 0);
    }
 
-   if (mask & BUFFER_BIT_BACK_LEFT) {
+   if (buffers & BUFFER_BIT_BACK_LEFT) {
       set_no_depth_stencil_write( i915 );
       set_color_mask( i915, GL_TRUE );
       set_draw_region( i915, &screen->back );
@@ -547,7 +557,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
                0, 0, 0, 0);
    }
 
-   if (mask & BUFFER_BIT_STENCIL) {
+   if (buffers & BUFFER_BIT_STENCIL) {
       set_stencil_replace( i915, 
                           intel->ctx.Stencil.WriteMask[0], 
                           intel->ctx.Stencil.Clear);
index 865f15e79f552fd202e0389f4c6c673afc7ead26..803b41b2567deb39128a92a18395d4a7c1482380 100644 (file)
@@ -621,13 +621,14 @@ void intelEmitCopyBlitLocked( intelContextPtr intel,
 
 
 
-void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
-                     GLint cx1, GLint cy1, GLint cw, GLint ch)
+void intelClearWithBlit(GLcontext *ctx, GLbitfield buffers, GLboolean allFoo,
+                        GLint cx1Foo, GLint cy1Foo, GLint cwFoo, GLint chFoo)
 {
    intelContextPtr intel = INTEL_CONTEXT( ctx );
    intelScreenPrivate *intelScreen = intel->intelScreen;
    GLuint clear_depth, clear_color;
-   GLint cx, cy;
+   GLint cx, cy, cw, ch;
+   GLboolean all;
    GLint pitch;
    GLint cpp = intelScreen->cpp;
    GLint i;
@@ -637,16 +638,24 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
    intelFlush( &intel->ctx );
    LOCK_HARDWARE( intel );
 
+   /* get clear bounds after locking */
+   cx = intel->ctx.DrawBuffer->_Xmin;
+   cy = intel->ctx.DrawBuffer->_Ymin;
+   cw = intel->ctx.DrawBuffer->_Xmax - cx;
+   ch = intel->ctx.DrawBuffer->_Ymax - cy;
+   all = (cw == intel->ctx.DrawBuffer->Width &&
+          ch == intel->ctx.DrawBuffer->Height);
+
    pitch = intelScreen->front.pitch;
 
    clear_color = intel->ClearColor;
    clear_depth = 0;
 
-   if (flags & BUFFER_BIT_DEPTH) {
+   if (buffers & BUFFER_BIT_DEPTH) {
       clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
    }
 
-   if (flags & BUFFER_BIT_STENCIL) {
+   if (buffers & BUFFER_BIT_STENCIL) {
       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
    }
 
@@ -661,8 +670,8 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
             XY_COLOR_BLT_WRITE_ALPHA | 
             XY_COLOR_BLT_WRITE_RGB);
       D_CMD = XY_COLOR_BLT_CMD;
-      if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
-      if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+      if (buffers & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
+      if (buffers & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
       break;
    default:
       BR13 = (0xF0 << 16) | (pitch) | (1<<24);
@@ -672,17 +681,17 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
 
    {
       /* flip top to bottom */
-      cy = intel->driDrawable->h-cy1-ch;
-      cx = cx1 + intel->drawX;
+      cy = intel->driDrawable->h - cy - ch;
+      cx = cx + intel->drawX;
       cy += intel->drawY;
 
       /* adjust for page flipping */
       if ( intel->sarea->pf_current_page == 1 ) {
-        GLuint tmp = flags;
+        GLuint tmp = buffers;
 
-        flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
-        if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
-        if ( tmp & BUFFER_BIT_BACK_LEFT )  flags |= BUFFER_BIT_FRONT_LEFT;
+        buffers &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
+        if ( tmp & BUFFER_BIT_FRONT_LEFT ) buffers |= BUFFER_BIT_BACK_LEFT;
+        if ( tmp & BUFFER_BIT_BACK_LEFT )  buffers |= BUFFER_BIT_FRONT_LEFT;
       }
 
       for (i = 0 ; i < intel->numClipRects ; i++) 
@@ -718,7 +727,7 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
             b.y2 > intelScreen->height)
            continue;
 
-        if ( flags & BUFFER_BIT_FRONT_LEFT ) {     
+        if ( buffers & BUFFER_BIT_FRONT_LEFT ) {           
            BEGIN_BATCH( 6);        
            OUT_BATCH( CMD );
            OUT_BATCH( BR13 );
@@ -729,7 +738,7 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
            ADVANCE_BATCH();
         }
 
-        if ( flags & BUFFER_BIT_BACK_LEFT ) {
+        if ( buffers & BUFFER_BIT_BACK_LEFT ) {
            BEGIN_BATCH( 6); 
            OUT_BATCH( CMD );
            OUT_BATCH( BR13 );
@@ -740,7 +749,7 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
            ADVANCE_BATCH();
         }
 
-        if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
+        if ( buffers & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
            BEGIN_BATCH( 6);
            OUT_BATCH( D_CMD );
            OUT_BATCH( BR13 );
index d8530367664ebb02e7c2b87493b771327d171305..ede3b6378fe3998f2a700141eb3ad5e220343cdc 100644 (file)
@@ -375,8 +375,7 @@ void intelFinish( GLcontext *ctx  )
 }
 
 
-void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-               GLint cx, GLint cy, GLint cw, GLint ch)
+void intelClear(GLcontext *ctx, GLbitfield mask)
 {
    intelContextPtr intel = INTEL_CONTEXT( ctx );
    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
@@ -429,13 +428,13 @@ void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
    swrast_mask |= (mask & BUFFER_BIT_ACCUM);
 
    if (blit_mask) 
-      intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
+      intelClearWithBlit( ctx, blit_mask, 0, 0, 0, 0, 0);
 
    if (tri_mask) 
-      intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch);
+      intel->vtbl.clear_with_tris( intel, tri_mask, 0, 0, 0, 0, 0);
 
    if (swrast_mask)
-      _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
+      _swrast_Clear( ctx, swrast_mask );
 }
 
 
index 099a7e1a44e2e0dd8ede3b1a26d6fa0dc3275286..6ea47e462e11b4a43945eaea8af8abe8d5781130 100644 (file)
@@ -32,8 +32,7 @@
 
 extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock );
 
-extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                      GLint cx, GLint cy, GLint cw, GLint ch);
+extern void intelClear(GLcontext *ctx, GLbitfield mask);
 
 extern void intelPageFlip( const __DRIdrawablePrivate *dpriv );
 
diff --git a/src/mesa/drivers/dri/i915tex/Makefile b/src/mesa/drivers/dri/i915tex/Makefile
new file mode 100644 (file)
index 0000000..94879d2
--- /dev/null
@@ -0,0 +1,66 @@
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = i915tex_dri.so
+
+MINIGLX_SOURCES = server/intel_dri.c
+
+DRIVER_SOURCES = \
+       i830_context.c \
+       i830_metaops.c \
+       i830_state.c \
+       i830_texblend.c \
+       i830_tex.c \
+       i830_texstate.c \
+       i830_vtbl.c \
+       intel_render.c \
+       intel_regions.c \
+       intel_buffer_objects.c \
+       intel_batchbuffer.c \
+       intel_mipmap_tree.c \
+       i915_tex_layout.c \
+       intel_tex_image.c \
+       intel_tex_subimage.c \
+       intel_tex_copy.c \
+       intel_tex_validate.c \
+       intel_tex_format.c \
+       intel_tex.c \
+       intel_pixel.c \
+       intel_pixel_copy.c \
+       intel_pixel_read.c \
+       intel_pixel_draw.c \
+       intel_buffers.c \
+       intel_blit.c \
+       i915_tex.c \
+       i915_texstate.c \
+       i915_context.c \
+       i915_debug.c \
+       i915_fragprog.c \
+       i915_metaops.c \
+       i915_program.c \
+       i915_state.c \
+       i915_vtbl.c \
+       intel_context.c \
+       intel_ioctl.c \
+       intel_rotate.c \
+       intel_screen.c \
+       intel_span.c \
+       intel_state.c \
+       intel_tris.c \
+       intel_fbo.c \
+       intel_depthstencil.c \
+       intel_batchpool.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(COMMON_BM_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+
+
+include ../Makefile.template
+
+symlinks:
diff --git a/src/mesa/drivers/dri/i915tex/i830_context.c b/src/mesa/drivers/dri/i915tex/i830_context.c
new file mode 100644 (file)
index 0000000..2ff8621
--- /dev/null
@@ -0,0 +1,104 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "i830_context.h"
+#include "imports.h"
+#include "texmem.h"
+#include "intel_tex.h"
+#include "tnl/tnl.h"
+#include "tnl/t_vertex.h"
+#include "tnl/t_context.h"
+#include "utils.h"
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+static const struct dri_extension i830_extensions[] = {
+   {"GL_ARB_texture_env_crossbar", NULL},
+   {NULL, NULL}
+};
+
+
+static void
+i830InitDriverFunctions(struct dd_function_table *functions)
+{
+   intelInitDriverFunctions(functions);
+   i830InitStateFuncs(functions);
+   i830InitTextureFuncs(functions);
+}
+
+
+GLboolean
+i830CreateContext(const __GLcontextModes * mesaVis,
+                  __DRIcontextPrivate * driContextPriv,
+                  void *sharedContextPrivate)
+{
+   struct dd_function_table functions;
+   struct i830_context *i830 = CALLOC_STRUCT(i830_context);
+   struct intel_context *intel = &i830->intel;
+   GLcontext *ctx = &intel->ctx;
+   if (!i830)
+      return GL_FALSE;
+
+   i830InitVtbl(i830);
+   i830InitDriverFunctions(&functions);
+
+   if (!intelInitContext(intel, mesaVis, driContextPriv,
+                         sharedContextPrivate, &functions)) {
+      FREE(i830);
+      return GL_FALSE;
+   }
+
+   intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS;
+   intel->ctx.Const.MaxTextureImageUnits = I830_TEX_UNITS;
+   intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS;
+
+   /* Advertise the full hardware capabilities.  The new memory
+    * manager should cope much better with overload situations:
+    */
+   ctx->Const.MaxTextureLevels = 12;
+   ctx->Const.Max3DTextureLevels = 9;
+   ctx->Const.MaxCubeTextureLevels = 11;
+   ctx->Const.MaxTextureRectSize = (1 << 11);
+   ctx->Const.MaxTextureUnits = I830_TEX_UNITS;
+
+   _tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
+                      18 * sizeof(GLfloat));
+
+   intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf;
+
+   driInitExtensions(ctx, i830_extensions, GL_FALSE);
+
+   i830InitState(i830);
+   i830InitMetaFuncs(i830);
+
+   _tnl_allow_vertex_fog(ctx, 1);
+   _tnl_allow_pixel_fog(ctx, 0);
+
+   return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i830_context.h b/src/mesa/drivers/dri/i915tex/i830_context.h
new file mode 100644 (file)
index 0000000..e5377b3
--- /dev/null
@@ -0,0 +1,208 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef I830CONTEXT_INC
+#define I830CONTEXT_INC
+
+#include "intel_context.h"
+
+#define I830_FALLBACK_TEXTURE           0x1000
+#define I830_FALLBACK_COLORMASK                 0x2000
+#define I830_FALLBACK_STENCIL           0x4000
+#define I830_FALLBACK_STIPPLE           0x8000
+#define I830_FALLBACK_LOGICOP           0x10000
+
+#define I830_UPLOAD_CTX              0x1
+#define I830_UPLOAD_BUFFERS          0x2
+#define I830_UPLOAD_STIPPLE          0x4
+#define I830_UPLOAD_INVARIENT        0x8
+#define I830_UPLOAD_TEX(i)           (0x10<<(i))
+#define I830_UPLOAD_TEXBLEND(i)      (0x100<<(i))
+#define I830_UPLOAD_TEX_ALL          (0x0f0)
+#define I830_UPLOAD_TEXBLEND_ALL     (0xf00)
+
+/* State structure offsets - these will probably disappear.
+ */
+#define I830_DESTREG_CBUFADDR0 0
+#define I830_DESTREG_CBUFADDR1 1
+#define I830_DESTREG_DBUFADDR0 2
+#define I830_DESTREG_DBUFADDR1 3
+#define I830_DESTREG_DV0 4
+#define I830_DESTREG_DV1 5
+#define I830_DESTREG_SENABLE 6
+#define I830_DESTREG_SR0 7
+#define I830_DESTREG_SR1 8
+#define I830_DESTREG_SR2 9
+#define I830_DEST_SETUP_SIZE 10
+
+#define I830_CTXREG_STATE1             0
+#define I830_CTXREG_STATE2             1
+#define I830_CTXREG_STATE3             2
+#define I830_CTXREG_STATE4             3
+#define I830_CTXREG_STATE5             4
+#define I830_CTXREG_IALPHAB            5
+#define I830_CTXREG_STENCILTST         6
+#define I830_CTXREG_ENABLES_1          7
+#define I830_CTXREG_ENABLES_2          8
+#define I830_CTXREG_AA                 9
+#define I830_CTXREG_FOGCOLOR           10
+#define I830_CTXREG_BLENDCOLOR0                11
+#define I830_CTXREG_BLENDCOLOR1                12
+#define I830_CTXREG_VF                 13
+#define I830_CTXREG_VF2                        14
+#define I830_CTXREG_MCSB0              15
+#define I830_CTXREG_MCSB1              16
+#define I830_CTX_SETUP_SIZE            17
+
+#define I830_STPREG_ST0        0
+#define I830_STPREG_ST1        1
+#define I830_STP_SETUP_SIZE    2
+
+#define I830_TEXREG_TM0LI      0        /* load immediate 2 texture map n */
+#define I830_TEXREG_TM0S1      1
+#define I830_TEXREG_TM0S2      2
+#define I830_TEXREG_TM0S3      3
+#define I830_TEXREG_TM0S4      4
+#define I830_TEXREG_MCS               5        /* _3DSTATE_MAP_COORD_SETS */
+#define I830_TEXREG_CUBE       6        /* _3DSTATE_MAP_SUBE */
+#define I830_TEX_SETUP_SIZE    7
+
+#define I830_TEXBLEND_SIZE     12      /* (4 args + op) * 2 + COLOR_FACTOR */
+
+struct i830_texture_object
+{
+   struct intel_texture_object intel;
+   GLuint Setup[I830_TEX_SETUP_SIZE];
+};
+
+#define I830_TEX_UNITS 4
+
+struct i830_hw_state
+{
+   GLuint Ctx[I830_CTX_SETUP_SIZE];
+   GLuint Buffer[I830_DEST_SETUP_SIZE];
+   GLuint Stipple[I830_STP_SETUP_SIZE];
+   GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE];
+   GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE];
+   GLuint TexBlendWordsUsed[I830_TEX_UNITS];
+
+   struct intel_region *draw_region;
+   struct intel_region *depth_region;
+
+   /* Regions aren't actually that appropriate here as the memory may
+    * be from a PBO or FBO.  Just use the buffer id.  Will have to do
+    * this for draw and depth for FBO's...
+    */
+   struct _DriBufferObject *tex_buffer[I830_TEX_UNITS];
+   GLuint tex_offset[I830_TEX_UNITS];
+
+   GLuint emitted;              /* I810_UPLOAD_* */
+   GLuint active;
+};
+
+struct i830_context
+{
+   struct intel_context intel;
+
+   GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS];
+     DECLARE_RENDERINPUTS(last_index_bitset);
+
+   struct i830_hw_state meta, initial, state, *current;
+};
+
+
+
+
+#define I830_STATECHANGE(i830, flag)                           \
+do {                                                           \
+   INTEL_FIREVERTICES( &i830->intel );                         \
+   i830->state.emitted &= ~flag;                                       \
+} while (0)
+
+#define I830_ACTIVESTATE(i830, flag, mode)     \
+do {                                           \
+   INTEL_FIREVERTICES( &i830->intel );         \
+   if (mode)                                   \
+      i830->state.active |= flag;              \
+   else                                                \
+      i830->state.active &= ~flag;             \
+} while (0)
+
+/* i830_vtbl.c
+ */
+extern void i830InitVtbl(struct i830_context *i830);
+
+/* i830_context.c
+ */
+extern GLboolean
+i830CreateContext(const __GLcontextModes * mesaVis,
+                  __DRIcontextPrivate * driContextPriv,
+                  void *sharedContextPrivate);
+
+/* i830_tex.c, i830_texstate.c
+ */
+extern void i830UpdateTextureState(struct intel_context *intel);
+
+extern void i830InitTextureFuncs(struct dd_function_table *functions);
+
+/* i830_texblend.c
+ */
+extern GLuint i830SetTexEnvCombine(struct i830_context *i830,
+                                   const struct gl_tex_env_combine_state
+                                   *combine, GLint blendUnit, GLuint texel_op,
+                                   GLuint * state, const GLfloat * factor);
+
+extern void i830EmitTextureBlend(struct i830_context *i830);
+
+
+/* i830_state.c
+ */
+extern void i830InitStateFuncs(struct dd_function_table *functions);
+
+extern void i830EmitState(struct i830_context *i830);
+
+extern void i830InitState(struct i830_context *i830);
+
+/* i830_metaops.c
+ */
+extern void i830InitMetaFuncs(struct i830_context *i830);
+
+extern void
+i830RotateWindow(struct intel_context *intel, __DRIdrawablePrivate * dPriv,
+                 GLuint srcBuf);
+
+/*======================================================================
+ * Inline conversion functions.  These are better-typed than the
+ * macros used previously:
+ */
+static INLINE struct i830_context *
+i830_context(GLcontext * ctx)
+{
+   return (struct i830_context *) ctx;
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/i830_metaops.c b/src/mesa/drivers/dri/i915tex/i830_metaops.c
new file mode 100644 (file)
index 0000000..c90f502
--- /dev/null
@@ -0,0 +1,485 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "utils.h"
+
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+#include "intel_ioctl.h"
+#include "intel_regions.h"
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+/* A large amount of state doesn't need to be uploaded.
+ */
+#define ACTIVE (I830_UPLOAD_INVARIENT |         \
+               I830_UPLOAD_CTX |               \
+               I830_UPLOAD_BUFFERS |           \
+               I830_UPLOAD_STIPPLE |           \
+               I830_UPLOAD_TEXBLEND(0) |       \
+               I830_UPLOAD_TEX(0))
+
+
+#define SET_STATE( i830, STATE )               \
+do {                                           \
+   i830->current->emitted &= ~ACTIVE;                  \
+   i830->current = &i830->STATE;               \
+   i830->current->emitted &= ~ACTIVE;                  \
+} while (0)
+
+
+static void
+set_no_stencil_write(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
+    */
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
+
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+static void
+set_no_depth_write(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
+    */
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
+
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+/* Set depth unit to replace.
+ */
+static void
+set_depth_replace(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
+    * ctx->Driver.DepthMask( ctx, GL_TRUE )
+    */
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE;
+
+   /* ctx->Driver.DepthFunc( ctx, GL_ALWAYS )
+    */
+   i830->meta.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
+   i830->meta.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC |
+                                          DEPTH_TEST_FUNC
+                                          (COMPAREFUNC_ALWAYS));
+
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+
+/* Set stencil unit to replace always with the reference value.
+ */
+static void
+set_stencil_replace(struct intel_context *intel,
+                    GLuint s_mask, GLuint s_clear)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
+    */
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
+
+   /* ctx->Driver.StencilMask( ctx, s_mask )
+    */
+   i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
+   i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
+                                          STENCIL_WRITE_MASK((s_mask &
+                                                              0xff)));
+
+   /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
+    */
+   i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
+   i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
+      (ENABLE_STENCIL_PARMS |
+       STENCIL_FAIL_OP(STENCILOP_REPLACE) |
+       STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
+       STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE));
+
+   /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
+    */
+   i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+   i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
+                                          STENCIL_TEST_MASK(0xff));
+
+   i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
+                                               ENABLE_STENCIL_TEST_FUNC_MASK);
+   i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
+      (ENABLE_STENCIL_REF_VALUE |
+       ENABLE_STENCIL_TEST_FUNC |
+       STENCIL_REF_VALUE((s_clear & 0xff)) |
+       STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
+
+
+
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+
+static void
+set_color_mask(struct intel_context *intel, GLboolean state)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
+                        (1 << WRITEMASK_GREEN_SHIFT) |
+                        (1 << WRITEMASK_BLUE_SHIFT) |
+                        (1 << WRITEMASK_ALPHA_SHIFT));
+
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
+
+   if (state) {
+      i830->meta.Ctx[I830_CTXREG_ENABLES_2] |=
+         (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
+   }
+
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+/* Installs a one-stage passthrough texture blend pipeline.  Is there
+ * more that can be done to turn off texturing?
+ */
+static void
+set_no_texture(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   static const struct gl_tex_env_combine_state comb = {
+      GL_NONE, GL_NONE,
+      {GL_TEXTURE, 0, 0,}, {GL_TEXTURE, 0, 0,},
+      {GL_SRC_COLOR, 0, 0}, {GL_SRC_ALPHA, 0, 0},
+      0, 0, 0, 0
+   };
+
+   i830->meta.TexBlendWordsUsed[0] =
+      i830SetTexEnvCombine(i830, &comb, 0, TEXBLENDARG_TEXEL0,
+                           i830->meta.TexBlend[0], NULL);
+
+   i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
+   i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
+}
+
+/* Set up a single element blend stage for 'replace' texturing with no
+ * funny ops.
+ */
+static void
+set_texture_blend_replace(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   static const struct gl_tex_env_combine_state comb = {
+      GL_REPLACE, GL_REPLACE,
+      {GL_TEXTURE, GL_TEXTURE, GL_TEXTURE,}, {GL_TEXTURE, GL_TEXTURE,
+                                              GL_TEXTURE,},
+      {GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR}, {GL_SRC_ALPHA, GL_SRC_ALPHA,
+                                                   GL_SRC_ALPHA},
+      0, 0, 1, 1
+   };
+
+   i830->meta.TexBlendWordsUsed[0] =
+      i830SetTexEnvCombine(i830, &comb, 0, TEXBLENDARG_TEXEL0,
+                           i830->meta.TexBlend[0], NULL);
+
+   i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
+   i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
+
+/*    fprintf(stderr, "%s: TexBlendWordsUsed[0]: %d\n",  */
+/*        __FUNCTION__, i830->meta.TexBlendWordsUsed[0]); */
+}
+
+
+
+/* Set up an arbitary piece of memory as a rectangular texture
+ * (including the front or back buffer).
+ */
+static GLboolean
+set_tex_rect_source(struct intel_context *intel,
+                    struct _DriBufferObject *buffer,
+                    GLuint offset,
+                    GLuint pitch, GLuint height, GLenum format, GLenum type)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   GLuint *setup = i830->meta.Tex[0];
+   GLint numLevels = 1;
+   GLuint textureFormat;
+   GLuint cpp;
+
+   /* A full implementation of this would do the upload through
+    * glTexImage2d, and get all the conversion operations at that
+    * point.  We are restricted, but still at least have access to the
+    * fragment program swizzle.
+    */
+   switch (format) {
+   case GL_BGRA:
+      switch (type) {
+      case GL_UNSIGNED_INT_8_8_8_8_REV:
+      case GL_UNSIGNED_BYTE:
+         textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
+         cpp = 4;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+   case GL_RGBA:
+      switch (type) {
+      case GL_UNSIGNED_INT_8_8_8_8_REV:
+      case GL_UNSIGNED_BYTE:
+         textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
+         cpp = 4;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+   case GL_BGR:
+      switch (type) {
+      case GL_UNSIGNED_SHORT_5_6_5_REV:
+         textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
+         cpp = 2;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+   case GL_RGB:
+      switch (type) {
+      case GL_UNSIGNED_SHORT_5_6_5:
+         textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
+         cpp = 2;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+
+   default:
+      return GL_FALSE;
+   }
+
+   i830->meta.tex_buffer[0] = buffer;
+   i830->meta.tex_offset[0] = offset;
+
+   setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+                               (LOAD_TEXTURE_MAP0 << 0) | 4);
+   setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
+                               ((pitch - 1) << TM0S1_WIDTH_SHIFT) |
+                               textureFormat);
+   setup[I830_TEXREG_TM0S2] =
+      (((((pitch * cpp) / 4) -
+         1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
+
+   setup[I830_TEXREG_TM0S3] =
+      ((((numLevels -
+          1) *
+         4) << TM0S3_MIN_MIP_SHIFT) | (FILTER_NEAREST <<
+                                       TM0S3_MIN_FILTER_SHIFT) |
+       (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT) | (FILTER_NEAREST <<
+                                                     TM0S3_MAG_FILTER_SHIFT));
+
+   setup[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(0));
+
+   setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
+                             MAP_UNIT(0) |
+                             ENABLE_TEXCOORD_PARAMS |
+                             TEXCOORDS_ARE_IN_TEXELUNITS |
+                             TEXCOORDTYPE_CARTESIAN |
+                             ENABLE_ADDR_V_CNTL |
+                             TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
+                             ENABLE_ADDR_U_CNTL |
+                             TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
+
+   i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
+   return GL_TRUE;
+}
+
+
+static void
+set_vertex_format(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
+                                     VFT0_TEX_COUNT(1) |
+                                     VFT0_DIFFUSE | VFT0_XYZ);
+   i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
+                                      VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
+                                      VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
+                                      VFT1_TEX2_FMT(TEXCOORDFMT_2D) |
+                                      VFT1_TEX3_FMT(TEXCOORDFMT_2D));
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+}
+
+
+static void
+meta_import_pixel_state(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   i830->meta.Ctx[I830_CTXREG_STATE1] = i830->state.Ctx[I830_CTXREG_STATE1];
+   i830->meta.Ctx[I830_CTXREG_STATE2] = i830->state.Ctx[I830_CTXREG_STATE2];
+   i830->meta.Ctx[I830_CTXREG_STATE3] = i830->state.Ctx[I830_CTXREG_STATE3];
+   i830->meta.Ctx[I830_CTXREG_STATE4] = i830->state.Ctx[I830_CTXREG_STATE4];
+   i830->meta.Ctx[I830_CTXREG_STATE5] = i830->state.Ctx[I830_CTXREG_STATE5];
+   i830->meta.Ctx[I830_CTXREG_IALPHAB] = i830->state.Ctx[I830_CTXREG_IALPHAB];
+   i830->meta.Ctx[I830_CTXREG_STENCILTST] =
+      i830->state.Ctx[I830_CTXREG_STENCILTST];
+   i830->meta.Ctx[I830_CTXREG_ENABLES_1] =
+      i830->state.Ctx[I830_CTXREG_ENABLES_1];
+   i830->meta.Ctx[I830_CTXREG_ENABLES_2] =
+      i830->state.Ctx[I830_CTXREG_ENABLES_2];
+   i830->meta.Ctx[I830_CTXREG_AA] = i830->state.Ctx[I830_CTXREG_AA];
+   i830->meta.Ctx[I830_CTXREG_FOGCOLOR] =
+      i830->state.Ctx[I830_CTXREG_FOGCOLOR];
+   i830->meta.Ctx[I830_CTXREG_BLENDCOLOR0] =
+      i830->state.Ctx[I830_CTXREG_BLENDCOLOR0];
+   i830->meta.Ctx[I830_CTXREG_BLENDCOLOR1] =
+      i830->state.Ctx[I830_CTXREG_BLENDCOLOR1];
+   i830->meta.Ctx[I830_CTXREG_MCSB0] = i830->state.Ctx[I830_CTXREG_MCSB0];
+   i830->meta.Ctx[I830_CTXREG_MCSB1] = i830->state.Ctx[I830_CTXREG_MCSB1];
+
+
+   i830->meta.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
+   i830->meta.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
+   i830->meta.emitted &= ~I830_UPLOAD_CTX;
+
+
+   i830->meta.Buffer[I830_DESTREG_SENABLE] =
+      i830->state.Buffer[I830_DESTREG_SENABLE];
+   i830->meta.Buffer[I830_DESTREG_SR1] = i830->state.Buffer[I830_DESTREG_SR1];
+   i830->meta.Buffer[I830_DESTREG_SR2] = i830->state.Buffer[I830_DESTREG_SR2];
+   i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
+}
+
+
+
+/* Select between front and back draw buffers.
+ */
+static void
+meta_draw_region(struct intel_context *intel,
+                 struct intel_region *draw_region,
+                 struct intel_region *depth_region)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   GLuint format;
+   GLuint depth_format = DEPTH_FRMT_16_FIXED;
+
+   intel_region_release(&i830->meta.draw_region);
+   intel_region_reference(&i830->meta.draw_region, draw_region);
+
+   intel_region_release(&i830->meta.depth_region);
+   intel_region_reference(&i830->meta.depth_region, depth_region);
+
+   /* XXX FBO: grab code from i915 meta_draw_region */
+
+   /* XXX: 555 support?
+    */
+   if (draw_region->cpp == 2)
+      format = DV_PF_565;
+   else
+      format = DV_PF_8888;
+
+   if (depth_region) {
+      if (depth_region->cpp == 2)
+         depth_format = DEPTH_FRMT_16_FIXED;
+      else
+         depth_format = DEPTH_FRMT_24_FIXED_8_OTHER;
+   }
+
+   i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |       /* .5 */
+                                          DSTORG_VERT_BIAS(0x8) |       /* .5 */
+                                          format | DEPTH_IS_Z | depth_format);
+
+   i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
+}
+
+
+/* Operations where the 3D engine is decoupled temporarily from the
+ * current GL state and used for other purposes than simply rendering
+ * incoming triangles.
+ */
+static void
+install_meta_state(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   memcpy(&i830->meta, &i830->initial, sizeof(i830->meta));
+
+   i830->meta.active = ACTIVE;
+   i830->meta.emitted = 0;
+
+   SET_STATE(i830, meta);
+   set_vertex_format(intel);
+   set_no_texture(intel);
+}
+
+static void
+leave_meta_state(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   intel_region_release(&i830->meta.draw_region);
+   intel_region_release(&i830->meta.depth_region);
+/*    intel_region_release(intel, &i830->meta.tex_region[0]); */
+   SET_STATE(i830, state);
+}
+
+
+
+void
+i830InitMetaFuncs(struct i830_context *i830)
+{
+   i830->intel.vtbl.install_meta_state = install_meta_state;
+   i830->intel.vtbl.leave_meta_state = leave_meta_state;
+   i830->intel.vtbl.meta_no_depth_write = set_no_depth_write;
+   i830->intel.vtbl.meta_no_stencil_write = set_no_stencil_write;
+   i830->intel.vtbl.meta_stencil_replace = set_stencil_replace;
+   i830->intel.vtbl.meta_depth_replace = set_depth_replace;
+   i830->intel.vtbl.meta_color_mask = set_color_mask;
+   i830->intel.vtbl.meta_no_texture = set_no_texture;
+   i830->intel.vtbl.meta_texture_blend_replace = set_texture_blend_replace;
+   i830->intel.vtbl.meta_tex_rect_source = set_tex_rect_source;
+   i830->intel.vtbl.meta_draw_region = meta_draw_region;
+   i830->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i830_reg.h b/src/mesa/drivers/dri/i915tex/i830_reg.h
new file mode 100644 (file)
index 0000000..24ac524
--- /dev/null
@@ -0,0 +1,641 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef _I830_REG_H_
+#define _I830_REG_H_
+
+
+#include "intel_reg.h"
+
+#define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+#define _3DSTATE_AA_CMD                        (CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE     (1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5        0
+#define AA_LINE_ECAAR_WIDTH_1_0                (1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0        (2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0        (3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE    (1<<8)
+#define AA_LINE_REGION_WIDTH_0_5       0
+#define AA_LINE_REGION_WIDTH_1_0       (1<<6)
+#define AA_LINE_REGION_WIDTH_2_0       (2<<6)
+#define AA_LINE_REGION_WIDTH_4_0       (3<<6)
+#define AA_LINE_ENABLE                 ((1<<1) | 1)
+#define AA_LINE_DISABLE                        (1<<1)
+
+#define _3DSTATE_BUF_INFO_CMD  (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK   (0x3<<24)
+#define BUF_3D_ID_DEPTH        (0x7<<24)
+#define BUF_3D_USE_FENCE       (1<<23)
+#define BUF_3D_TILED_SURFACE   (1<<22)
+#define BUF_3D_TILE_WALK_X     0
+#define BUF_3D_TILE_WALK_Y     (1<<21)
+#define BUF_3D_PITCH(x)         (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x)         ((x) & ~0x3)
+
+
+#define _3DSTATE_COLOR_FACTOR_CMD      (CMD_3D | (0x1d<<24) | (0x1<<16))
+
+#define _3DSTATE_COLOR_FACTOR_N_CMD(stage)     (CMD_3D | (0x1d<<24) | \
+                                                ((0x90+(stage))<<16))
+
+#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
+
+#define _3DSTATE_DFLT_DIFFUSE_CMD      (CMD_3D | (0x1d<<24) | (0x99<<16))
+
+#define _3DSTATE_DFLT_SPEC_CMD         (CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+#define _3DSTATE_DFLT_Z_CMD            (CMD_3D | (0x1d<<24) | (0x98<<16))
+
+
+#define _3DSTATE_DST_BUF_VARS_CMD      (CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define DSTORG_HORT_BIAS(x)            ((x)<<20)
+#define DSTORG_VERT_BIAS(x)            ((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL       0
+#define COLOR_4_2_2_CHNL_WRT_Y         (1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR                (2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB                (3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB      (4<<12)
+#define COLR_BUF_8BIT                  0
+#define COLR_BUF_RGB555                (1<<8)
+#define COLR_BUF_RGB565                (2<<8)
+#define COLR_BUF_ARGB8888              (3<<8)
+#define DEPTH_IS_Z                     0
+#define DEPTH_IS_W                     (1<<6)
+#define DEPTH_FRMT_16_FIXED            0
+#define DEPTH_FRMT_16_FLOAT            (1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER    (2<<2)
+#define DEPTH_FRMT_24_FLOAT_8_OTHER    (3<<2)
+#define VERT_LINE_STRIDE_1             (1<<1)
+#define VERT_LINE_STRIDE_0             0
+#define VERT_LINE_STRIDE_OFS_1         1
+#define VERT_LINE_STRIDE_OFS_0         0
+
+
+#define _3DSTATE_DRAW_RECT_CMD         (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS        (1<<30)
+#define DRAW_DITHER_OFS_X(x)           ((x)<<26)
+#define DRAW_DITHER_OFS_Y(x)           ((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x)                   ((x)<<16)
+#define DRAW_XMIN(x)                   (x)
+/* Dword 3 */
+#define DRAW_YMAX(x)                   ((x)<<16)
+#define DRAW_XMAX(x)                   (x)
+/* Dword 4 */
+#define DRAW_YORG(x)                   ((x)<<16)
+#define DRAW_XORG(x)                   (x)
+
+
+#define _3DSTATE_ENABLES_1_CMD         (CMD_3D|(0x3<<24))
+#define ENABLE_LOGIC_OP_MASK           ((1<<23)|(1<<22))
+#define ENABLE_LOGIC_OP                ((1<<23)|(1<<22))
+#define DISABLE_LOGIC_OP               (1<<23)
+#define ENABLE_STENCIL_TEST            ((1<<21)|(1<<20))
+#define DISABLE_STENCIL_TEST           (1<<21)
+#define ENABLE_DEPTH_BIAS              ((1<<11)|(1<<10))
+#define DISABLE_DEPTH_BIAS             (1<<11)
+#define ENABLE_SPEC_ADD_MASK           ((1<<9)|(1<<8))
+#define ENABLE_SPEC_ADD                ((1<<9)|(1<<8))
+#define DISABLE_SPEC_ADD               (1<<9)
+#define ENABLE_DIS_FOG_MASK            ((1<<7)|(1<<6))
+#define ENABLE_FOG                     ((1<<7)|(1<<6))
+#define DISABLE_FOG                    (1<<7)
+#define ENABLE_DIS_ALPHA_TEST_MASK     ((1<<5)|(1<<4))
+#define ENABLE_ALPHA_TEST              ((1<<5)|(1<<4))
+#define DISABLE_ALPHA_TEST             (1<<5)
+#define ENABLE_DIS_CBLEND_MASK         ((1<<3)|(1<<2))
+#define ENABLE_COLOR_BLEND             ((1<<3)|(1<<2))
+#define DISABLE_COLOR_BLEND            (1<<3)
+#define ENABLE_DIS_DEPTH_TEST_MASK     ((1<<1)|1)
+#define ENABLE_DEPTH_TEST              ((1<<1)|1)
+#define DISABLE_DEPTH_TEST             (1<<1)
+
+/* _3DSTATE_ENABLES_2, p138 */
+#define _3DSTATE_ENABLES_2_CMD         (CMD_3D|(0x4<<24))
+#define ENABLE_STENCIL_WRITE           ((1<<21)|(1<<20))
+#define DISABLE_STENCIL_WRITE          (1<<21)
+#define ENABLE_TEX_CACHE               ((1<<17)|(1<<16))
+#define DISABLE_TEX_CACHE              (1<<17)
+#define ENABLE_DITHER                  ((1<<9)|(1<<8))
+#define DISABLE_DITHER                 (1<<9)
+#define ENABLE_COLOR_MASK              (1<<10)
+#define WRITEMASK_ALPHA                        (1<<7)
+#define WRITEMASK_ALPHA_SHIFT          7
+#define WRITEMASK_RED                  (1<<6)
+#define WRITEMASK_RED_SHIFT            6
+#define WRITEMASK_GREEN                (1<<5)
+#define WRITEMASK_GREEN_SHIFT          5
+#define WRITEMASK_BLUE                 (1<<4)
+#define WRITEMASK_BLUE_SHIFT           4
+#define WRITEMASK_MASK                 ((1<<4)|(1<<5)|(1<<6)|(1<<7))
+#define ENABLE_COLOR_WRITE             ((1<<3)|(1<<2))
+#define DISABLE_COLOR_WRITE            (1<<3)
+#define ENABLE_DIS_DEPTH_WRITE_MASK    0x3
+#define ENABLE_DEPTH_WRITE             ((1<<1)|1)
+#define DISABLE_DEPTH_WRITE            (1<<1)
+
+/* _3DSTATE_FOG_COLOR, p139 */
+#define _3DSTATE_FOG_COLOR_CMD         (CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x)               ((x)<<16)
+#define FOG_COLOR_GREEN(x)             ((x)<<8)
+#define FOG_COLOR_BLUE(x)              (x)
+
+/* _3DSTATE_FOG_MODE, p140 */
+#define _3DSTATE_FOG_MODE_CMD          (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FOGFUNC_ENABLE                 (1<<31)
+#define FOGFUNC_VERTEX                 0
+#define FOGFUNC_PIXEL_EXP              (1<<28)
+#define FOGFUNC_PIXEL_EXP2             (2<<28)
+#define FOGFUNC_PIXEL_LINEAR           (3<<28)
+#define FOGSRC_INDEX_Z                 (1<<27)
+#define FOGSRC_INDEX_W                 ((1<<27)|(1<<25))
+#define FOG_LINEAR_CONST               (1<<24)
+#define FOG_CONST_1(x)                 ((x)<<4)
+#define ENABLE_FOG_DENSITY             (1<<23)
+/* Dword 2 */
+#define FOG_CONST_2(x)                 (x)
+/* Dword 3 */
+#define FOG_DENSITY(x)                 (x)
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p142 */
+#define _3DSTATE_INDPT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24))
+#define ENABLE_INDPT_ALPHA_BLEND       ((1<<23)|(1<<22))
+#define DISABLE_INDPT_ALPHA_BLEND      (1<<23)
+#define ALPHA_BLENDFUNC_MASK           0x3f0000
+#define ENABLE_ALPHA_BLENDFUNC         (1<<21)
+#define ABLENDFUNC_ADD                 0
+#define ABLENDFUNC_SUB                 (1<<16)
+#define ABLENDFUNC_RVSE_SUB            (2<<16)
+#define ABLENDFUNC_MIN                 (3<<16)
+#define ABLENDFUNC_MAX                 (4<<16)
+#define SRC_DST_ABLEND_MASK            0xfff
+#define ENABLE_SRC_ABLEND_FACTOR       (1<<11)
+#define SRC_ABLEND_FACT(x)             ((x)<<6)
+#define ENABLE_DST_ABLEND_FACTOR       (1<<5)
+#define DST_ABLEND_FACT(x)             (x)
+
+
+/* _3DSTATE_MAP_BLEND_ARG, p152 */
+#define _3DSTATE_MAP_BLEND_ARG_CMD(stage)      (CMD_3D|(0x0e<<24)|((stage)<<20))
+
+#define TEXPIPE_COLOR                  0
+#define TEXPIPE_ALPHA                  (1<<18)
+#define TEXPIPE_KILL                   (2<<18)
+#define TEXBLEND_ARG0                  0
+#define TEXBLEND_ARG1                  (1<<15)
+#define TEXBLEND_ARG2                  (2<<15)
+#define TEXBLEND_ARG3                  (3<<15)
+#define TEXBLENDARG_MODIFY_PARMS       (1<<6)
+#define TEXBLENDARG_REPLICATE_ALPHA    (1<<5)
+#define TEXBLENDARG_INV_ARG            (1<<4)
+#define TEXBLENDARG_ONE                0
+#define TEXBLENDARG_FACTOR             0x01
+#define TEXBLENDARG_ACCUM              0x02
+#define TEXBLENDARG_DIFFUSE            0x03
+#define TEXBLENDARG_SPEC               0x04
+#define TEXBLENDARG_CURRENT            0x05
+#define TEXBLENDARG_TEXEL0             0x06
+#define TEXBLENDARG_TEXEL1             0x07
+#define TEXBLENDARG_TEXEL2             0x08
+#define TEXBLENDARG_TEXEL3             0x09
+#define TEXBLENDARG_FACTOR_N           0x0e
+
+/* _3DSTATE_MAP_BLEND_OP, p155 */
+#define _3DSTATE_MAP_BLEND_OP_CMD(stage)       (CMD_3D|(0x0d<<24)|((stage)<<20))
+#if 0
+#   define TEXPIPE_COLOR               0
+#   define TEXPIPE_ALPHA               (1<<18)
+#   define TEXPIPE_KILL                        (2<<18)
+#endif
+#define ENABLE_TEXOUTPUT_WRT_SEL       (1<<17)
+#define TEXOP_OUTPUT_CURRENT           0
+#define TEXOP_OUTPUT_ACCUM             (1<<15)
+#define ENABLE_TEX_CNTRL_STAGE         ((1<<12)|(1<<11))
+#define DISABLE_TEX_CNTRL_STAGE                (1<<12)
+#define TEXOP_SCALE_SHIFT              9
+#define TEXOP_SCALE_1X                 (0 << TEXOP_SCALE_SHIFT)
+#define TEXOP_SCALE_2X                 (1 << TEXOP_SCALE_SHIFT)
+#define TEXOP_SCALE_4X                 (2 << TEXOP_SCALE_SHIFT)
+#define TEXOP_MODIFY_PARMS             (1<<8)
+#define TEXOP_LAST_STAGE               (1<<7)
+#define TEXBLENDOP_KILLPIXEL           0x02
+#define TEXBLENDOP_ARG1                0x01
+#define TEXBLENDOP_ARG2                0x02
+#define TEXBLENDOP_MODULATE            0x03
+#define TEXBLENDOP_ADD                 0x06
+#define TEXBLENDOP_ADDSIGNED           0x07
+#define TEXBLENDOP_BLEND               0x08
+#define TEXBLENDOP_BLEND_AND_ADD       0x09
+#define TEXBLENDOP_SUBTRACT            0x0a
+#define TEXBLENDOP_DOT3                0x0b
+#define TEXBLENDOP_DOT4                0x0c
+#define TEXBLENDOP_MODULATE_AND_ADD    0x0d
+#define TEXBLENDOP_MODULATE_2X_AND_ADD 0x0e
+#define TEXBLENDOP_MODULATE_4X_AND_ADD 0x0f
+
+/* _3DSTATE_MAP_BUMP_TABLE, p160 TODO */
+/* _3DSTATE_MAP_COLOR_CHROMA_KEY, p161 TODO */
+
+#define _3DSTATE_MAP_COORD_TRANSFORM   ((3<<29)|(0x1d<<24)|(0x8c<<16))
+#define DISABLE_TEX_TRANSFORM          (1<<28)
+#define TEXTURE_SET(x)                 (x<<29)
+
+#define _3DSTATE_VERTEX_TRANSFORM      ((3<<29)|(0x1d<<24)|(0x8b<<16))
+#define DISABLE_VIEWPORT_TRANSFORM     (1<<31)
+#define DISABLE_PERSPECTIVE_DIVIDE     (1<<29)
+
+
+/* _3DSTATE_MAP_COORD_SET_BINDINGS, p162 */
+#define _3DSTATE_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16))
+#define TEXBIND_MASK3                  ((1<<15)|(1<<14)|(1<<13)|(1<<12))
+#define TEXBIND_MASK2                  ((1<<11)|(1<<10)|(1<<9)|(1<<8))
+#define TEXBIND_MASK1                  ((1<<7)|(1<<6)|(1<<5)|(1<<4))
+#define TEXBIND_MASK0                  ((1<<3)|(1<<2)|(1<<1)|1)
+
+#define TEXBIND_SET3(x)                ((x)<<12)
+#define TEXBIND_SET2(x)                ((x)<<8)
+#define TEXBIND_SET1(x)                ((x)<<4)
+#define TEXBIND_SET0(x)                (x)
+
+#define TEXCOORDSRC_KEEP               0
+#define TEXCOORDSRC_DEFAULT            0x01
+#define TEXCOORDSRC_VTXSET_0           0x08
+#define TEXCOORDSRC_VTXSET_1           0x09
+#define TEXCOORDSRC_VTXSET_2           0x0a
+#define TEXCOORDSRC_VTXSET_3           0x0b
+#define TEXCOORDSRC_VTXSET_4           0x0c
+#define TEXCOORDSRC_VTXSET_5           0x0d
+#define TEXCOORDSRC_VTXSET_6           0x0e
+#define TEXCOORDSRC_VTXSET_7           0x0f
+
+#define MAP_UNIT(unit)                 ((unit)<<16)
+#define MAP_UNIT_MASK                  (0x7<<16)
+
+/* _3DSTATE_MAP_COORD_SETS, p164 */
+#define _3DSTATE_MAP_COORD_SET_CMD     (CMD_3D|(0x1c<<24)|(0x01<<19))
+#define ENABLE_TEXCOORD_PARAMS         (1<<15)
+#define TEXCOORDS_ARE_NORMAL           (1<<14)
+#define TEXCOORDS_ARE_IN_TEXELUNITS    0
+#define TEXCOORDTYPE_CARTESIAN         0
+#define TEXCOORDTYPE_HOMOGENEOUS       (1<<11)
+#define TEXCOORDTYPE_VECTOR            (2<<11)
+#define TEXCOORDTYPE_MASK              (0x7<<11)
+#define ENABLE_ADDR_V_CNTL             (1<<7)
+#define ENABLE_ADDR_U_CNTL             (1<<3)
+#define TEXCOORD_ADDR_V_MODE(x)        ((x)<<4)
+#define TEXCOORD_ADDR_U_MODE(x)        (x)
+#define TEXCOORDMODE_WRAP              0
+#define TEXCOORDMODE_MIRROR            1
+#define TEXCOORDMODE_CLAMP             2
+#define TEXCOORDMODE_WRAP_SHORTEST     3
+#define TEXCOORDMODE_CLAMP_BORDER      4
+#define TEXCOORD_ADDR_V_MASK           0x70
+#define TEXCOORD_ADDR_U_MASK           0x7
+
+/* _3DSTATE_MAP_CUBE, p168 TODO */
+#define _3DSTATE_MAP_CUBE              (CMD_3D|(0x1c<<24)|(0x0a<<19))
+#define CUBE_NEGX_ENABLE                (1<<5)
+#define CUBE_POSX_ENABLE                (1<<4)
+#define CUBE_NEGY_ENABLE                (1<<3)
+#define CUBE_POSY_ENABLE                (1<<2)
+#define CUBE_NEGZ_ENABLE                (1<<1)
+#define CUBE_POSZ_ENABLE                (1<<0)
+
+
+/* _3DSTATE_MODES_1, p190 */
+#define _3DSTATE_MODES_1_CMD           (CMD_3D|(0x08<<24))
+#define BLENDFUNC_MASK                 0x3f0000
+#define ENABLE_COLR_BLND_FUNC          (1<<21)
+#define BLENDFUNC_ADD                  0
+#define BLENDFUNC_SUB                  (1<<16)
+#define BLENDFUNC_RVRSE_SUB            (2<<16)
+#define BLENDFUNC_MIN                  (3<<16)
+#define BLENDFUNC_MAX                  (4<<16)
+#define SRC_DST_BLND_MASK              0xfff
+#define ENABLE_SRC_BLND_FACTOR         (1<<11)
+#define ENABLE_DST_BLND_FACTOR         (1<<5)
+#define SRC_BLND_FACT(x)               ((x)<<6)
+#define DST_BLND_FACT(x)               (x)
+
+
+/* _3DSTATE_MODES_2, p192 */
+#define _3DSTATE_MODES_2_CMD           (CMD_3D|(0x0f<<24))
+#define ENABLE_GLOBAL_DEPTH_BIAS       (1<<22)
+#define GLOBAL_DEPTH_BIAS(x)           ((x)<<14)
+#define ENABLE_ALPHA_TEST_FUNC         (1<<13)
+#define ENABLE_ALPHA_REF_VALUE         (1<<8)
+#define ALPHA_TEST_FUNC(x)             ((x)<<9)
+#define ALPHA_REF_VALUE(x)             (x)
+
+#define ALPHA_TEST_REF_MASK            0x3fff
+
+/* _3DSTATE_MODES_3, p193 */
+#define _3DSTATE_MODES_3_CMD           (CMD_3D|(0x02<<24))
+#define DEPTH_TEST_FUNC_MASK           0x1f0000
+#define ENABLE_DEPTH_TEST_FUNC         (1<<20)
+/* Uses COMPAREFUNC */
+#define DEPTH_TEST_FUNC(x)             ((x)<<16)
+#define ENABLE_ALPHA_SHADE_MODE        (1<<11)
+#define ENABLE_FOG_SHADE_MODE          (1<<9)
+#define ENABLE_SPEC_SHADE_MODE         (1<<7)
+#define ENABLE_COLOR_SHADE_MODE        (1<<5)
+#define ALPHA_SHADE_MODE(x)            ((x)<<10)
+#define FOG_SHADE_MODE(x)              ((x)<<8)
+#define SPEC_SHADE_MODE(x)             ((x)<<6)
+#define COLOR_SHADE_MODE(x)            ((x)<<4)
+#define CULLMODE_MASK                  0xf
+#define ENABLE_CULL_MODE               (1<<3)
+#define CULLMODE_BOTH                  0
+#define CULLMODE_NONE                  1
+#define CULLMODE_CW                    2
+#define CULLMODE_CCW                   3
+
+#define SHADE_MODE_LINEAR              0
+#define SHADE_MODE_FLAT                0x1
+
+/* _3DSTATE_MODES_4, p195 */
+#define _3DSTATE_MODES_4_CMD           (CMD_3D|(0x16<<24))
+#define ENABLE_LOGIC_OP_FUNC           (1<<23)
+#define LOGIC_OP_FUNC(x)               ((x)<<18)
+#define LOGICOP_MASK                   ((1<<18)|(1<<19)|(1<<20)|(1<<21))
+#define LOGICOP_CLEAR                  0
+#define LOGICOP_NOR                    0x1
+#define LOGICOP_AND_INV                0x2
+#define LOGICOP_COPY_INV               0x3
+#define LOGICOP_AND_RVRSE              0x4
+#define LOGICOP_INV                    0x5
+#define LOGICOP_XOR                    0x6
+#define LOGICOP_NAND                   0x7
+#define LOGICOP_AND                    0x8
+#define LOGICOP_EQUIV                  0x9
+#define LOGICOP_NOOP                   0xa
+#define LOGICOP_OR_INV                 0xb
+#define LOGICOP_COPY                   0xc
+#define LOGICOP_OR_RVRSE               0xd
+#define LOGICOP_OR                     0xe
+#define LOGICOP_SET                    0xf
+#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK       (1<<17)
+#define STENCIL_TEST_MASK(x)           (((x)&0xff)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK        ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK      (1<<16)
+#define STENCIL_WRITE_MASK(x)          ((x)&0xff)
+
+/* _3DSTATE_MODES_5, p196 */
+#define _3DSTATE_MODES_5_CMD           (CMD_3D|(0x0c<<24))
+#define ENABLE_SPRITE_POINT_TEX        (1<<23)
+#define SPRITE_POINT_TEX_ON            (1<<22)
+#define SPRITE_POINT_TEX_OFF           0
+#define FLUSH_RENDER_CACHE             (1<<18)
+#define FLUSH_TEXTURE_CACHE            (1<<16)
+#define FIXED_LINE_WIDTH_MASK          0xfc00
+#define ENABLE_FIXED_LINE_WIDTH        (1<<15)
+#define FIXED_LINE_WIDTH(x)            ((x)<<10)
+#define FIXED_POINT_WIDTH_MASK         0x3ff
+#define ENABLE_FIXED_POINT_WIDTH       (1<<9)
+#define FIXED_POINT_WIDTH(x)           (x)
+
+/* _3DSTATE_RASTERIZATION_RULES, p198 */
+#define _3DSTATE_RASTER_RULES_CMD      (CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE       (1<<15)
+#define OGL_POINT_RASTER_RULE          (1<<13)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX    (1<<5)
+#define ENABLE_TRI_STRIP_PROVOKE_VRTX  (1<<2)
+#define LINE_STRIP_PROVOKE_VRTX(x)     ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x)        ((x)<<3)
+#define TRI_STRIP_PROVOKE_VRTX(x)      (x)
+
+/* _3DSTATE_SCISSOR_ENABLE, p200 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD    (CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT            ((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT           (1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p201 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD    (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x)         ((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x)         (x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x)         ((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x)         (x)
+
+/* _3DSTATE_STENCIL_TEST, p202 */
+#define _3DSTATE_STENCIL_TEST_CMD      (CMD_3D|(0x09<<24))
+#define ENABLE_STENCIL_PARMS           (1<<23)
+#define STENCIL_OPS_MASK               (0xffc000)
+#define STENCIL_FAIL_OP(x)             ((x)<<20)
+#define STENCIL_PASS_DEPTH_FAIL_OP(x)  ((x)<<17)
+#define STENCIL_PASS_DEPTH_PASS_OP(x)  ((x)<<14)
+
+#define ENABLE_STENCIL_TEST_FUNC_MASK  ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9))
+#define ENABLE_STENCIL_TEST_FUNC       (1<<13)
+/* Uses COMPAREFUNC */
+#define STENCIL_TEST_FUNC(x)           ((x)<<9)
+#define STENCIL_REF_VALUE_MASK         ((1<<8)|0xff)
+#define ENABLE_STENCIL_REF_VALUE       (1<<8)
+#define STENCIL_REF_VALUE(x)           (x)
+
+/* _3DSTATE_VERTEX_FORMAT, p204 */
+#define _3DSTATE_VFT0_CMD      (CMD_3D|(0x05<<24))
+#define VFT0_POINT_WIDTH       (1<<12)
+#define VFT0_TEX_COUNT_MASK            (7<<8)
+#define VFT0_TEX_COUNT_SHIFT    8
+#define VFT0_TEX_COUNT(x)      ((x)<<8)
+#define VFT0_SPEC              (1<<7)
+#define VFT0_DIFFUSE           (1<<6)
+#define VFT0_DEPTH_OFFSET      (1<<5)
+#define VFT0_XYZ               (1<<1)
+#define VFT0_XYZW              (2<<1)
+#define VFT0_XY                        (3<<1)
+#define VFT0_XYW               (4<<1)
+#define VFT0_XYZW_MASK          (7<<1)
+
+/* _3DSTATE_VERTEX_FORMAT_2, p206 */
+#define _3DSTATE_VFT1_CMD      (CMD_3D|(0x0a<<24))
+#define VFT1_TEX7_FMT(x)       ((x)<<14)
+#define VFT1_TEX6_FMT(x)       ((x)<<12)
+#define VFT1_TEX5_FMT(x)       ((x)<<10)
+#define VFT1_TEX4_FMT(x)       ((x)<<8)
+#define VFT1_TEX3_FMT(x)       ((x)<<6)
+#define VFT1_TEX2_FMT(x)       ((x)<<4)
+#define VFT1_TEX1_FMT(x)       ((x)<<2)
+#define VFT1_TEX0_FMT(x)       (x)
+#define VFT1_TEX0_MASK          3
+#define VFT1_TEX1_SHIFT         2
+#define TEXCOORDFMT_2D         0
+#define TEXCOORDFMT_3D         1
+#define TEXCOORDFMT_4D         2
+#define TEXCOORDFMT_1D         3
+
+/*New stuff picked up along the way */
+
+#define MLC_LOD_BIAS_MASK ((1<<7)-1)
+
+
+/* _3DSTATE_VERTEX_TRANSFORM, p207 */
+#define _3DSTATE_VERTEX_TRANS_CMD      (CMD_3D|(0x1d<<24)|(0x8b<<16)|0)
+#define _3DSTATE_VERTEX_TRANS_MTX_CMD  (CMD_3D|(0x1d<<24)|(0x8b<<16)|6)
+/* Dword 1 */
+#define ENABLE_VIEWPORT_TRANSFORM      ((1<<31)|(1<<30))
+#define DISABLE_VIEWPORT_TRANSFORM     (1<<31)
+#define ENABLE_PERSP_DIVIDE            ((1<<29)|(1<<28))
+#define DISABLE_PERSP_DIVIDE           (1<<29)
+#define VRTX_TRANS_LOAD_MATRICES       0x7421
+#define VRTX_TRANS_NO_LOAD_MATRICES    0x0000
+/* Dword 2 -> 7  are matrix elements */
+
+/* _3DSTATE_W_STATE, p209 */
+#define _3DSTATE_W_STATE_CMD           (CMD_3D|(0x1d<<24)|(0x8d<<16)|1)
+/* Dword 1 */
+#define MAGIC_W_STATE_DWORD1           0x00000008
+/* Dword 2 */
+#define WFAR_VALUE(x)                  (x)
+
+
+/* Stipple command, carried over from the i810, apparently:
+ */
+#define _3DSTATE_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE               (1<<16)
+#define ST1_MASK                 (0xffff)
+
+
+
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP0                   (1<<11)
+#define LOAD_GLOBAL_COLOR_FACTOR            (1<<6)
+
+#define TM0S0_ADDRESS_MASK              0xfffffffc
+#define TM0S0_USE_FENCE                 (1<<1)
+
+#define TM0S1_HEIGHT_SHIFT              21
+#define TM0S1_WIDTH_SHIFT               10
+#define TM0S1_PALETTE_SELECT            (1<<9)
+#define TM0S1_MAPSURF_FORMAT_MASK       (0x7 << 6)
+#define TM0S1_MAPSURF_FORMAT_SHIFT      6
+#define    MAPSURF_8BIT_INDEXED                   (0<<6)
+#define    MAPSURF_8BIT                           (1<<6)
+#define    MAPSURF_16BIT                  (2<<6)
+#define    MAPSURF_32BIT                  (3<<6)
+#define    MAPSURF_411                    (4<<6)
+#define    MAPSURF_422                    (5<<6)
+#define    MAPSURF_COMPRESSED             (6<<6)
+#define    MAPSURF_4BIT_INDEXED                   (7<<6)
+#define TM0S1_MT_FORMAT_MASK         (0x7 << 3)
+#define TM0S1_MT_FORMAT_SHIFT        3
+#define    MT_4BIT_IDX_ARGB8888                   (7<<3)       /* SURFACE_4BIT_INDEXED */
+#define    MT_8BIT_IDX_RGB565             (0<<3)       /* SURFACE_8BIT_INDEXED */
+#define    MT_8BIT_IDX_ARGB1555                   (1<<3)
+#define    MT_8BIT_IDX_ARGB4444                   (2<<3)
+#define    MT_8BIT_IDX_AY88               (3<<3)
+#define    MT_8BIT_IDX_ABGR8888                   (4<<3)
+#define    MT_8BIT_IDX_BUMP_88DVDU        (5<<3)
+#define    MT_8BIT_IDX_BUMP_655LDVDU      (6<<3)
+#define    MT_8BIT_IDX_ARGB8888                   (7<<3)
+#define    MT_8BIT_I8                     (0<<3)       /* SURFACE_8BIT */
+#define    MT_8BIT_L8                     (1<<3)
+#define    MT_16BIT_RGB565                (0<<3)       /* SURFACE_16BIT */
+#define    MT_16BIT_ARGB1555              (1<<3)
+#define    MT_16BIT_ARGB4444              (2<<3)
+#define    MT_16BIT_AY88                  (3<<3)
+#define    MT_16BIT_DIB_ARGB1555_8888      (4<<3)
+#define    MT_16BIT_BUMP_88DVDU                   (5<<3)
+#define    MT_16BIT_BUMP_655LDVDU         (6<<3)
+#define    MT_16BIT_DIB_RGB565_8888       (7<<3)
+#define    MT_32BIT_ARGB8888              (0<<3)       /* SURFACE_32BIT */
+#define    MT_32BIT_ABGR8888              (1<<3)
+#define    MT_32BIT_BUMP_XLDVDU_8888      (6<<3)
+#define    MT_32BIT_DIB_8888              (7<<3)
+#define    MT_411_YUV411                  (0<<3)       /* SURFACE_411 */
+#define    MT_422_YCRCB_SWAPY             (0<<3)       /* SURFACE_422 */
+#define    MT_422_YCRCB_NORMAL            (1<<3)
+#define    MT_422_YCRCB_SWAPUV            (2<<3)
+#define    MT_422_YCRCB_SWAPUVY                   (3<<3)
+#define    MT_COMPRESS_DXT1               (0<<3)       /* SURFACE_COMPRESSED */
+#define    MT_COMPRESS_DXT2_3             (1<<3)
+#define    MT_COMPRESS_DXT4_5             (2<<3)
+#define    MT_COMPRESS_FXT1               (3<<3)
+#define TM0S1_COLORSPACE_CONVERSION     (1 << 2)
+#define TM0S1_TILED_SURFACE             (1 << 1)
+#define TM0S1_TILE_WALK                 (1 << 0)
+
+#define TM0S2_PITCH_SHIFT               21
+#define TM0S2_CUBE_FACE_ENA_SHIFT       15
+#define TM0S2_CUBE_FACE_ENA_MASK        (1<<15)
+#define TM0S2_MAP_FORMAT                (1<<14)
+#define TM0S2_VERTICAL_LINE_STRIDE      (1<<13)
+#define TM0S2_VERITCAL_LINE_STRIDE_OFF  (1<<12)
+#define TM0S2_OUTPUT_CHAN_SHIFT         10
+#define TM0S2_OUTPUT_CHAN_MASK          (3<<10)
+
+#define TM0S3_MIP_FILTER_MASK           (0x3<<30)
+#define TM0S3_MIP_FILTER_SHIFT          30
+#define MIPFILTER_NONE         0
+#define MIPFILTER_NEAREST      1
+#define MIPFILTER_LINEAR       3
+#define TM0S3_MAG_FILTER_MASK           (0x3<<28)
+#define TM0S3_MAG_FILTER_SHIFT          28
+#define TM0S3_MIN_FILTER_MASK           (0x3<<26)
+#define TM0S3_MIN_FILTER_SHIFT          26
+#define FILTER_NEAREST         0
+#define FILTER_LINEAR          1
+#define FILTER_ANISOTROPIC     2
+
+#define TM0S3_LOD_BIAS_SHIFT           17
+#define TM0S3_LOD_BIAS_MASK            (0x1ff<<17)
+#define TM0S3_MAX_MIP_SHIFT            9
+#define TM0S3_MAX_MIP_MASK             (0xff<<9)
+#define TM0S3_MIN_MIP_SHIFT            3
+#define TM0S3_MIN_MIP_MASK             (0x3f<<3)
+#define TM0S3_KILL_PIXEL               (1<<2)
+#define TM0S3_KEYED_FILTER             (1<<1)
+#define TM0S3_CHROMA_KEY               (1<<0)
+
+
+/* _3DSTATE_MAP_TEXEL_STREAM, p188 */
+#define _3DSTATE_MAP_TEX_STREAM_CMD    (CMD_3D|(0x1c<<24)|(0x05<<19))
+#define DISABLE_TEX_STREAM_BUMP        (1<<12)
+#define ENABLE_TEX_STREAM_BUMP         ((1<<12)|(1<<11))
+#define TEX_MODIFY_UNIT_0              0
+#define TEX_MODIFY_UNIT_1              (1<<8)
+#define ENABLE_TEX_STREAM_COORD_SET    (1<<7)
+#define TEX_STREAM_COORD_SET(x)        ((x)<<4)
+#define ENABLE_TEX_STREAM_MAP_IDX      (1<<3)
+#define TEX_STREAM_MAP_IDX(x)          (x)
+
+
+#define MI_FLUSH           ((0<<29)|(4<<23))
+#define FLUSH_MAP_CACHE    (1<<0)
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/i830_state.c b/src/mesa/drivers/dri/i915tex/i830_state.c
new file mode 100644 (file)
index 0000000..83d8288
--- /dev/null
@@ -0,0 +1,1113 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "enums.h"
+#include "dd.h"
+
+#include "texmem.h"
+
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+#include "intel_fbo.h"
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+#define FILE_DEBUG_FLAG DEBUG_STATE
+
+static void
+i830StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
+                        GLuint mask)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int test = intel_translate_compare_func(func);
+
+   mask = mask & 0xff;
+
+   DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(func), ref, mask);
+
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
+                                           STENCIL_TEST_MASK(mask));
+   i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
+                                                ENABLE_STENCIL_TEST_FUNC_MASK);
+   i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_REF_VALUE |
+                                               ENABLE_STENCIL_TEST_FUNC |
+                                               STENCIL_REF_VALUE(ref) |
+                                               STENCIL_TEST_FUNC(test));
+}
+
+static void
+i830StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
+{
+   struct i830_context *i830 = i830_context(ctx);
+
+   DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
+   
+   mask = mask & 0xff;
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
+                                           STENCIL_WRITE_MASK(mask));
+}
+
+static void
+i830StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail,
+                      GLenum zpass)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int fop, dfop, dpop;
+
+   DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(fail),
+       _mesa_lookup_enum_by_nr(zfail), 
+       _mesa_lookup_enum_by_nr(zpass));
+
+   fop = 0;
+   dfop = 0;
+   dpop = 0;
+
+   switch (fail) {
+   case GL_KEEP:
+      fop = STENCILOP_KEEP;
+      break;
+   case GL_ZERO:
+      fop = STENCILOP_ZERO;
+      break;
+   case GL_REPLACE:
+      fop = STENCILOP_REPLACE;
+      break;
+   case GL_INCR:
+      fop = STENCILOP_INCRSAT;
+      break;
+   case GL_DECR:
+      fop = STENCILOP_DECRSAT;
+      break;
+   case GL_INCR_WRAP:
+      fop = STENCILOP_INCR;
+      break;
+   case GL_DECR_WRAP:
+      fop = STENCILOP_DECR;
+      break;
+   case GL_INVERT:
+      fop = STENCILOP_INVERT;
+      break;
+   default:
+      break;
+   }
+   switch (zfail) {
+   case GL_KEEP:
+      dfop = STENCILOP_KEEP;
+      break;
+   case GL_ZERO:
+      dfop = STENCILOP_ZERO;
+      break;
+   case GL_REPLACE:
+      dfop = STENCILOP_REPLACE;
+      break;
+   case GL_INCR:
+      dfop = STENCILOP_INCRSAT;
+      break;
+   case GL_DECR:
+      dfop = STENCILOP_DECRSAT;
+      break;
+   case GL_INCR_WRAP:
+      dfop = STENCILOP_INCR;
+      break;
+   case GL_DECR_WRAP:
+      dfop = STENCILOP_DECR;
+      break;
+   case GL_INVERT:
+      dfop = STENCILOP_INVERT;
+      break;
+   default:
+      break;
+   }
+   switch (zpass) {
+   case GL_KEEP:
+      dpop = STENCILOP_KEEP;
+      break;
+   case GL_ZERO:
+      dpop = STENCILOP_ZERO;
+      break;
+   case GL_REPLACE:
+      dpop = STENCILOP_REPLACE;
+      break;
+   case GL_INCR:
+      dpop = STENCILOP_INCRSAT;
+      break;
+   case GL_DECR:
+      dpop = STENCILOP_DECRSAT;
+      break;
+   case GL_INCR_WRAP:
+      dpop = STENCILOP_INCR;
+      break;
+   case GL_DECR_WRAP:
+      dpop = STENCILOP_DECR;
+      break;
+   case GL_INVERT:
+      dpop = STENCILOP_INVERT;
+      break;
+   default:
+      break;
+   }
+
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
+   i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS |
+                                               STENCIL_FAIL_OP(fop) |
+                                               STENCIL_PASS_DEPTH_FAIL_OP
+                                               (dfop) |
+                                               STENCIL_PASS_DEPTH_PASS_OP
+                                               (dpop));
+}
+
+static void
+i830AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int test = intel_translate_compare_func(func);
+   GLubyte refByte;
+   GLuint refInt;
+
+   UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
+   refInt = (GLuint) refByte;
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE2] &= ~ALPHA_TEST_REF_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE2] |= (ENABLE_ALPHA_TEST_FUNC |
+                                           ENABLE_ALPHA_REF_VALUE |
+                                           ALPHA_TEST_FUNC(test) |
+                                           ALPHA_REF_VALUE(refInt));
+}
+
+/**
+ * Makes sure that the proper enables are set for LogicOp, Independant Alpha
+ * Blend, and Blending.  It needs to be called from numerous places where we
+ * could change the LogicOp or Independant Alpha Blend without subsequent
+ * calls to glEnable.
+ * 
+ * \todo
+ * This function is substantially different from the old i830-specific driver.
+ * I'm not sure which is correct.
+ */
+static void
+i830EvalLogicOpBlendState(GLcontext * ctx)
+{
+   struct i830_context *i830 = i830_context(ctx);
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+
+   if (ctx->Color._LogicOpEnabled) {
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND |
+                                                  ENABLE_LOGIC_OP_MASK);
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND |
+                                                 ENABLE_LOGIC_OP);
+   }
+   else if (ctx->Color.BlendEnabled) {
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND |
+                                                  ENABLE_LOGIC_OP_MASK);
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND |
+                                                 DISABLE_LOGIC_OP);
+   }
+   else {
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND |
+                                                  ENABLE_LOGIC_OP_MASK);
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND |
+                                                 DISABLE_LOGIC_OP);
+   }
+}
+
+static void
+i830BlendColor(GLcontext * ctx, const GLfloat color[4])
+{
+   struct i830_context *i830 = i830_context(ctx);
+   GLubyte r, g, b, a;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]);
+   UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]);
+   UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]);
+   UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]);
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] =
+      (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+/**
+ * Sets both the blend equation (called "function" in i830 docs) and the
+ * blend function (called "factor" in i830 docs).  This is done in a single
+ * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
+ * change the interpretation of the blend function.
+ */
+static void
+i830_set_blend_state(GLcontext * ctx)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int funcA;
+   int funcRGB;
+   int eqnA;
+   int eqnRGB;
+   int iab;
+   int s1;
+
+
+   funcRGB =
+      SRC_BLND_FACT(intel_translate_blend_factor(ctx->Color.BlendSrcRGB))
+      | DST_BLND_FACT(intel_translate_blend_factor(ctx->Color.BlendDstRGB));
+
+   switch (ctx->Color.BlendEquationRGB) {
+   case GL_FUNC_ADD:
+      eqnRGB = BLENDFUNC_ADD;
+      break;
+   case GL_MIN:
+      eqnRGB = BLENDFUNC_MIN;
+      funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
+      break;
+   case GL_MAX:
+      eqnRGB = BLENDFUNC_MAX;
+      funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
+      break;
+   case GL_FUNC_SUBTRACT:
+      eqnRGB = BLENDFUNC_SUB;
+      break;
+   case GL_FUNC_REVERSE_SUBTRACT:
+      eqnRGB = BLENDFUNC_RVRSE_SUB;
+      break;
+   default:
+      fprintf(stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
+              __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB);
+      return;
+   }
+
+
+   funcA = SRC_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.BlendSrcA))
+      | DST_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.BlendDstA));
+
+   switch (ctx->Color.BlendEquationA) {
+   case GL_FUNC_ADD:
+      eqnA = BLENDFUNC_ADD;
+      break;
+   case GL_MIN:
+      eqnA = BLENDFUNC_MIN;
+      funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
+      break;
+   case GL_MAX:
+      eqnA = BLENDFUNC_MAX;
+      funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
+      break;
+   case GL_FUNC_SUBTRACT:
+      eqnA = BLENDFUNC_SUB;
+      break;
+   case GL_FUNC_REVERSE_SUBTRACT:
+      eqnA = BLENDFUNC_RVRSE_SUB;
+      break;
+   default:
+      fprintf(stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n",
+              __FUNCTION__, __LINE__, ctx->Color.BlendEquationA);
+      return;
+   }
+
+   iab = eqnA | funcA
+      | _3DSTATE_INDPT_ALPHA_BLEND_CMD
+      | ENABLE_SRC_ABLEND_FACTOR | ENABLE_DST_ABLEND_FACTOR
+      | ENABLE_ALPHA_BLENDFUNC;
+   s1 = eqnRGB | funcRGB
+      | _3DSTATE_MODES_1_CMD
+      | ENABLE_SRC_BLND_FACTOR | ENABLE_DST_BLND_FACTOR
+      | ENABLE_COLR_BLND_FUNC;
+
+   if ((eqnA | funcA) != (eqnRGB | funcRGB))
+      iab |= ENABLE_INDPT_ALPHA_BLEND;
+   else
+      iab |= DISABLE_INDPT_ALPHA_BLEND;
+
+   if (iab != i830->state.Ctx[I830_CTXREG_IALPHAB] ||
+       s1 != i830->state.Ctx[I830_CTXREG_STATE1]) {
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_IALPHAB] = iab;
+      i830->state.Ctx[I830_CTXREG_STATE1] = s1;
+   }
+
+   /* This will catch a logicop blend equation.  It will also ensure
+    * independant alpha blend is really in the correct state (either enabled
+    * or disabled) if blending is already enabled.
+    */
+
+   i830EvalLogicOpBlendState(ctx);
+
+   if (0) {
+      fprintf(stderr,
+              "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n",
+              __FUNCTION__, __LINE__, i830->state.Ctx[I830_CTXREG_STATE1],
+              i830->state.Ctx[I830_CTXREG_IALPHAB],
+              (ctx->Color.BlendEnabled) ? "en" : "dis");
+   }
+}
+
+
+static void
+i830BlendEquationSeparate(GLcontext * ctx, GLenum modeRGB, GLenum modeA)
+{
+   DBG("%s -> %s, %s\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(modeRGB),
+       _mesa_lookup_enum_by_nr(modeA));
+
+   (void) modeRGB;
+   (void) modeA;
+   i830_set_blend_state(ctx);
+}
+
+
+static void
+i830BlendFuncSeparate(GLcontext * ctx, GLenum sfactorRGB,
+                      GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA)
+{
+   DBG("%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(sfactorRGB),
+       _mesa_lookup_enum_by_nr(dfactorRGB),
+       _mesa_lookup_enum_by_nr(sfactorA),
+       _mesa_lookup_enum_by_nr(dfactorA));
+
+   (void) sfactorRGB;
+   (void) dfactorRGB;
+   (void) sfactorA;
+   (void) dfactorA;
+   i830_set_blend_state(ctx);
+}
+
+
+
+static void
+i830DepthFunc(GLcontext * ctx, GLenum func)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int test = intel_translate_compare_func(func);
+
+   DBG("%s\n", __FUNCTION__);
+   
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC |
+                                           DEPTH_TEST_FUNC(test));
+}
+
+static void
+i830DepthMask(GLcontext * ctx, GLboolean flag)
+{
+   struct i830_context *i830 = i830_context(ctx);
+
+   DBG("%s flag (%d)\n", __FUNCTION__, flag);
+   
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+
+   i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
+
+   if (flag && ctx->Depth.Test)
+      i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE;
+   else
+      i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
+}
+
+/* =============================================================
+ * Polygon stipple
+ *
+ * The i830 supports a 4x4 stipple natively, GL wants 32x32.
+ * Fortunately stipple is usually a repeating pattern.
+ */
+static void
+i830PolygonStipple(GLcontext * ctx, const GLubyte * mask)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   const GLubyte *m = mask;
+   GLubyte p[4];
+   int i, j, k;
+   int active = (ctx->Polygon.StippleFlag &&
+                 i830->intel.reduced_primitive == GL_TRIANGLES);
+   GLuint newMask;
+
+   if (active) {
+      I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
+      i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
+   }
+
+   p[0] = mask[12] & 0xf;
+   p[0] |= p[0] << 4;
+   p[1] = mask[8] & 0xf;
+   p[1] |= p[1] << 4;
+   p[2] = mask[4] & 0xf;
+   p[2] |= p[2] << 4;
+   p[3] = mask[0] & 0xf;
+   p[3] |= p[3] << 4;
+
+   for (k = 0; k < 8; k++)
+      for (j = 3; j >= 0; j--)
+         for (i = 0; i < 4; i++, m++)
+            if (*m != p[j]) {
+               i830->intel.hw_stipple = 0;
+               return;
+            }
+
+   newMask = (((p[0] & 0xf) << 0) |
+              ((p[1] & 0xf) << 4) |
+              ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12));
+
+
+   if (newMask == 0xffff || newMask == 0x0) {
+      /* this is needed to make conform pass */
+      i830->intel.hw_stipple = 0;
+      return;
+   }
+
+   i830->state.Stipple[I830_STPREG_ST1] &= ~0xffff;
+   i830->state.Stipple[I830_STPREG_ST1] |= newMask;
+   i830->intel.hw_stipple = 1;
+
+   if (active)
+      i830->state.Stipple[I830_STPREG_ST1] |= ST1_ENABLE;
+}
+
+
+/* =============================================================
+ * Hardware clipping
+ */
+static void
+i830Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int x1, y1, x2, y2;
+
+   if (!ctx->DrawBuffer)
+      return;
+
+   DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h);
+
+   if (ctx->DrawBuffer->Name == 0) {
+      x1 = x;
+      y1 = ctx->DrawBuffer->Height - (y + h);
+      x2 = x + w - 1;
+      y2 = y1 + h - 1;
+      DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2);
+   }
+   else {
+      /* FBO - not inverted
+       */
+      x1 = x;
+      y1 = y;
+      x2 = x + w - 1;
+      y2 = y + h - 1;
+      DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2);
+   }
+
+   x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
+   y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
+   x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
+   y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
+   
+   DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2);
+
+   I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
+   i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
+   i830->state.Buffer[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
+}
+
+static void
+i830LogicOp(GLcontext * ctx, GLenum opcode)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int tmp = intel_translate_logic_op(opcode);
+
+   DBG("%s\n", __FUNCTION__);
+   
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE4] &= ~LOGICOP_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp);
+}
+
+
+
+static void
+i830CullFaceFrontFace(GLcontext * ctx, GLenum unused)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   GLuint mode;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   if (!ctx->Polygon.CullFlag) {
+      mode = CULLMODE_NONE;
+   }
+   else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
+      mode = CULLMODE_CW;
+
+      if (ctx->Polygon.CullFaceMode == GL_FRONT)
+         mode ^= (CULLMODE_CW ^ CULLMODE_CCW);
+      if (ctx->Polygon.FrontFace != GL_CCW)
+         mode ^= (CULLMODE_CW ^ CULLMODE_CCW);
+   }
+   else {
+      mode = CULLMODE_BOTH;
+   }
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE3] |= ENABLE_CULL_MODE | mode;
+}
+
+static void
+i830LineWidth(GLcontext * ctx, GLfloat widthf)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   int width;
+   int state5;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   width = (int) (widthf * 2);
+   CLAMP_SELF(width, 1, 15);
+
+   state5 = i830->state.Ctx[I830_CTXREG_STATE5] & ~FIXED_LINE_WIDTH_MASK;
+   state5 |= (ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(width));
+
+   if (state5 != i830->state.Ctx[I830_CTXREG_STATE5]) {
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_STATE5] = state5;
+   }
+}
+
+static void
+i830PointSize(GLcontext * ctx, GLfloat size)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   GLint point_size = (int) size;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   CLAMP_SELF(point_size, 1, 256);
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE5] &= ~FIXED_POINT_WIDTH_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE5] |= (ENABLE_FIXED_POINT_WIDTH |
+                                           FIXED_POINT_WIDTH(point_size));
+}
+
+
+/* =============================================================
+ * Color masks
+ */
+
+static void
+i830ColorMask(GLcontext * ctx,
+              GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   GLuint tmp = 0;
+
+   DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a);
+
+   tmp = ((i830->state.Ctx[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) |
+          ENABLE_COLOR_MASK |
+          ENABLE_COLOR_WRITE |
+          ((!r) << WRITEMASK_RED_SHIFT) |
+          ((!g) << WRITEMASK_GREEN_SHIFT) |
+          ((!b) << WRITEMASK_BLUE_SHIFT) | ((!a) << WRITEMASK_ALPHA_SHIFT));
+
+   if (tmp != i830->state.Ctx[I830_CTXREG_ENABLES_2]) {
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_ENABLES_2] = tmp;
+   }
+}
+
+static void
+update_specular(GLcontext * ctx)
+{
+   struct i830_context *i830 = i830_context(ctx);
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK;
+
+   if (NEED_SECONDARY_COLOR(ctx))
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_SPEC_ADD;
+   else
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD;
+}
+
+static void
+i830LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
+{
+   DBG("%s\n", __FUNCTION__);
+   
+   if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+      update_specular(ctx);
+   }
+}
+
+/* In Mesa 3.5 we can reliably do native flatshading.
+ */
+static void
+i830ShadeModel(GLcontext * ctx, GLenum mode)
+{
+   struct i830_context *i830 = i830_context(ctx);
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+
+
+#define SHADE_MODE_MASK ((1<<10)|(1<<8)|(1<<6)|(1<<4))
+
+   i830->state.Ctx[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK;
+
+   if (mode == GL_FLAT) {
+      i830->state.Ctx[I830_CTXREG_STATE3] |=
+         (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | FOG_SHADE_MODE(SHADE_MODE_FLAT)
+          | SPEC_SHADE_MODE(SHADE_MODE_FLAT) |
+          COLOR_SHADE_MODE(SHADE_MODE_FLAT));
+   }
+   else {
+      i830->state.Ctx[I830_CTXREG_STATE3] |=
+         (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
+          FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
+          SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
+          COLOR_SHADE_MODE(SHADE_MODE_LINEAR));
+   }
+}
+
+/* =============================================================
+ * Fog
+ */
+static void
+i830Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
+{
+   struct i830_context *i830 = i830_context(ctx);
+
+   DBG("%s\n", __FUNCTION__);
+   
+   if (pname == GL_FOG_COLOR) {
+      GLuint color = (((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) |
+                      ((GLubyte) (ctx->Fog.Color[1] * 255.0F) << 8) |
+                      ((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0));
+
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_FOGCOLOR] =
+         (_3DSTATE_FOG_COLOR_CMD | color);
+   }
+}
+
+/* =============================================================
+ */
+
+static void
+i830Enable(GLcontext * ctx, GLenum cap, GLboolean state)
+{
+   struct i830_context *i830 = i830_context(ctx);
+
+   switch (cap) {
+   case GL_LIGHTING:
+   case GL_COLOR_SUM:
+      update_specular(ctx);
+      break;
+
+   case GL_ALPHA_TEST:
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_ALPHA_TEST_MASK;
+      if (state)
+         i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_ALPHA_TEST;
+      else
+         i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_ALPHA_TEST;
+
+      break;
+
+   case GL_BLEND:
+      i830EvalLogicOpBlendState(ctx);
+      break;
+
+   case GL_COLOR_LOGIC_OP:
+      i830EvalLogicOpBlendState(ctx);
+
+      /* Logicop doesn't seem to work at 16bpp:
+       */
+      if (i830->intel.intelScreen->cpp == 2)
+         FALLBACK(&i830->intel, I830_FALLBACK_LOGICOP, state);
+      break;
+
+   case GL_DITHER:
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DITHER;
+
+      if (state)
+         i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DITHER;
+      else
+         i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DITHER;
+      break;
+
+   case GL_DEPTH_TEST:
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
+
+      if (state)
+         i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST;
+      else
+         i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
+
+      /* Also turn off depth writes when GL_DEPTH_TEST is disabled:
+       */
+      i830DepthMask(ctx, ctx->Depth.Mask);
+      break;
+
+   case GL_SCISSOR_TEST:
+      I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
+
+      if (state)
+         i830->state.Buffer[I830_DESTREG_SENABLE] =
+            (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT);
+      else
+         i830->state.Buffer[I830_DESTREG_SENABLE] =
+            (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+
+      break;
+
+   case GL_LINE_SMOOTH:
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+
+      i830->state.Ctx[I830_CTXREG_AA] &= ~AA_LINE_ENABLE;
+      if (state)
+         i830->state.Ctx[I830_CTXREG_AA] |= AA_LINE_ENABLE;
+      else
+         i830->state.Ctx[I830_CTXREG_AA] |= AA_LINE_DISABLE;
+      break;
+
+   case GL_FOG:
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+      i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_FOG_MASK;
+      if (state)
+         i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_FOG;
+      else
+         i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_FOG;
+      break;
+
+   case GL_CULL_FACE:
+      i830CullFaceFrontFace(ctx, 0);
+      break;
+
+   case GL_TEXTURE_2D:
+      break;
+
+   case GL_STENCIL_TEST:
+      {
+         GLboolean hw_stencil = GL_FALSE;
+         if (ctx->DrawBuffer) {
+            struct intel_renderbuffer *irbStencil
+               = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+            hw_stencil = (irbStencil && irbStencil->region);
+         }
+         if (hw_stencil) {
+            I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+
+            if (state) {
+               i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
+               i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
+            }
+            else {
+               i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
+               i830->state.Ctx[I830_CTXREG_ENABLES_2] &=
+                  ~ENABLE_STENCIL_WRITE;
+               i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
+               i830->state.Ctx[I830_CTXREG_ENABLES_2] |=
+                  DISABLE_STENCIL_WRITE;
+            }
+         }
+         else {
+            FALLBACK(&i830->intel, I830_FALLBACK_STENCIL, state);
+         }
+      }
+      break;
+
+   case GL_POLYGON_STIPPLE:
+      /* The stipple command worked on my 855GM box, but not my 845G.
+       * I'll do more testing later to find out exactly which hardware
+       * supports it.  Disabled for now.
+       */
+      if (i830->intel.hw_stipple &&
+          i830->intel.reduced_primitive == GL_TRIANGLES) {
+         I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
+         i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
+         if (state)
+            i830->state.Stipple[I830_STPREG_ST1] |= ST1_ENABLE;
+      }
+      break;
+
+   default:
+      ;
+   }
+}
+
+
+static void
+i830_init_packets(struct i830_context *i830)
+{
+   intelScreenPrivate *screen = i830->intel.intelScreen;
+
+   /* Zero all state */
+   memset(&i830->state, 0, sizeof(i830->state));
+
+   /* Set default blend state */
+   i830->state.TexBlend[0][0] = (_3DSTATE_MAP_BLEND_OP_CMD(0) |
+                                 TEXPIPE_COLOR |
+                                 ENABLE_TEXOUTPUT_WRT_SEL |
+                                 TEXOP_OUTPUT_CURRENT |
+                                 DISABLE_TEX_CNTRL_STAGE |
+                                 TEXOP_SCALE_1X |
+                                 TEXOP_MODIFY_PARMS |
+                                 TEXOP_LAST_STAGE | TEXBLENDOP_ARG1);
+   i830->state.TexBlend[0][1] = (_3DSTATE_MAP_BLEND_OP_CMD(0) |
+                                 TEXPIPE_ALPHA |
+                                 ENABLE_TEXOUTPUT_WRT_SEL |
+                                 TEXOP_OUTPUT_CURRENT |
+                                 TEXOP_SCALE_1X |
+                                 TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
+   i830->state.TexBlend[0][2] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) |
+                                 TEXPIPE_COLOR |
+                                 TEXBLEND_ARG1 |
+                                 TEXBLENDARG_MODIFY_PARMS |
+                                 TEXBLENDARG_DIFFUSE);
+   i830->state.TexBlend[0][3] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) |
+                                 TEXPIPE_ALPHA |
+                                 TEXBLEND_ARG1 |
+                                 TEXBLENDARG_MODIFY_PARMS |
+                                 TEXBLENDARG_DIFFUSE);
+
+   i830->state.TexBlendWordsUsed[0] = 4;
+
+
+   i830->state.Ctx[I830_CTXREG_VF] = 0;
+   i830->state.Ctx[I830_CTXREG_VF2] = 0;
+
+   i830->state.Ctx[I830_CTXREG_AA] = (_3DSTATE_AA_CMD |
+                                      AA_LINE_ECAAR_WIDTH_ENABLE |
+                                      AA_LINE_ECAAR_WIDTH_1_0 |
+                                      AA_LINE_REGION_WIDTH_ENABLE |
+                                      AA_LINE_REGION_WIDTH_1_0 |
+                                      AA_LINE_DISABLE);
+
+   i830->state.Ctx[I830_CTXREG_ENABLES_1] = (_3DSTATE_ENABLES_1_CMD |
+                                             DISABLE_LOGIC_OP |
+                                             DISABLE_STENCIL_TEST |
+                                             DISABLE_DEPTH_BIAS |
+                                             DISABLE_SPEC_ADD |
+                                             DISABLE_FOG |
+                                             DISABLE_ALPHA_TEST |
+                                             DISABLE_COLOR_BLEND |
+                                             DISABLE_DEPTH_TEST);
+
+#if 000                         /* XXX all the stencil enable state is set in i830Enable(), right? */
+   if (i830->intel.hw_stencil) {
+      i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD |
+                                                ENABLE_STENCIL_WRITE |
+                                                ENABLE_TEX_CACHE |
+                                                ENABLE_DITHER |
+                                                ENABLE_COLOR_MASK |
+                                                /* set no color comps disabled */
+                                                ENABLE_COLOR_WRITE |
+                                                ENABLE_DEPTH_WRITE);
+   }
+   else
+#endif
+   {
+      i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD |
+                                                DISABLE_STENCIL_WRITE |
+                                                ENABLE_TEX_CACHE |
+                                                ENABLE_DITHER |
+                                                ENABLE_COLOR_MASK |
+                                                /* set no color comps disabled */
+                                                ENABLE_COLOR_WRITE |
+                                                ENABLE_DEPTH_WRITE);
+   }
+
+   i830->state.Ctx[I830_CTXREG_STATE1] = (_3DSTATE_MODES_1_CMD |
+                                          ENABLE_COLR_BLND_FUNC |
+                                          BLENDFUNC_ADD |
+                                          ENABLE_SRC_BLND_FACTOR |
+                                          SRC_BLND_FACT(BLENDFACT_ONE) |
+                                          ENABLE_DST_BLND_FACTOR |
+                                          DST_BLND_FACT(BLENDFACT_ZERO));
+
+   i830->state.Ctx[I830_CTXREG_STATE2] = (_3DSTATE_MODES_2_CMD |
+                                          ENABLE_GLOBAL_DEPTH_BIAS |
+                                          GLOBAL_DEPTH_BIAS(0) |
+                                          ENABLE_ALPHA_TEST_FUNC |
+                                          ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS)
+                                          | ALPHA_REF_VALUE(0));
+
+   i830->state.Ctx[I830_CTXREG_STATE3] = (_3DSTATE_MODES_3_CMD |
+                                          ENABLE_DEPTH_TEST_FUNC |
+                                          DEPTH_TEST_FUNC(COMPAREFUNC_LESS) |
+                                          ENABLE_ALPHA_SHADE_MODE |
+                                          ALPHA_SHADE_MODE(SHADE_MODE_LINEAR)
+                                          | ENABLE_FOG_SHADE_MODE |
+                                          FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
+                                          ENABLE_SPEC_SHADE_MODE |
+                                          SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
+                                          ENABLE_COLOR_SHADE_MODE |
+                                          COLOR_SHADE_MODE(SHADE_MODE_LINEAR)
+                                          | ENABLE_CULL_MODE | CULLMODE_NONE);
+
+   i830->state.Ctx[I830_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD |
+                                          ENABLE_LOGIC_OP_FUNC |
+                                          LOGIC_OP_FUNC(LOGICOP_COPY) |
+                                          ENABLE_STENCIL_TEST_MASK |
+                                          STENCIL_TEST_MASK(0xff) |
+                                          ENABLE_STENCIL_WRITE_MASK |
+                                          STENCIL_WRITE_MASK(0xff));
+
+   i830->state.Ctx[I830_CTXREG_STENCILTST] = (_3DSTATE_STENCIL_TEST_CMD |
+                                              ENABLE_STENCIL_PARMS |
+                                              STENCIL_FAIL_OP(STENCILOP_KEEP)
+                                              |
+                                              STENCIL_PASS_DEPTH_FAIL_OP
+                                              (STENCILOP_KEEP) |
+                                              STENCIL_PASS_DEPTH_PASS_OP
+                                              (STENCILOP_KEEP) |
+                                              ENABLE_STENCIL_TEST_FUNC |
+                                              STENCIL_TEST_FUNC
+                                              (COMPAREFUNC_ALWAYS) |
+                                              ENABLE_STENCIL_REF_VALUE |
+                                              STENCIL_REF_VALUE(0));
+
+   i830->state.Ctx[I830_CTXREG_STATE5] = (_3DSTATE_MODES_5_CMD | FLUSH_TEXTURE_CACHE | ENABLE_SPRITE_POINT_TEX | SPRITE_POINT_TEX_OFF | ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(0x2) |       /* 1.0 */
+                                          ENABLE_FIXED_POINT_WIDTH |
+                                          FIXED_POINT_WIDTH(1));
+
+   i830->state.Ctx[I830_CTXREG_IALPHAB] = (_3DSTATE_INDPT_ALPHA_BLEND_CMD |
+                                           DISABLE_INDPT_ALPHA_BLEND |
+                                           ENABLE_ALPHA_BLENDFUNC |
+                                           ABLENDFUNC_ADD);
+
+   i830->state.Ctx[I830_CTXREG_FOGCOLOR] = (_3DSTATE_FOG_COLOR_CMD |
+                                            FOG_COLOR_RED(0) |
+                                            FOG_COLOR_GREEN(0) |
+                                            FOG_COLOR_BLUE(0));
+
+   i830->state.Ctx[I830_CTXREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
+   i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] = 0;
+
+   i830->state.Ctx[I830_CTXREG_MCSB0] = _3DSTATE_MAP_COORD_SETBIND_CMD;
+   i830->state.Ctx[I830_CTXREG_MCSB1] = (TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) |
+                                         TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) |
+                                         TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
+                                         TEXBIND_SET0(TEXCOORDSRC_VTXSET_0));
+
+
+   i830->state.Stipple[I830_STPREG_ST0] = _3DSTATE_STIPPLE;
+
+   i830->state.Buffer[I830_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+   i830->state.Buffer[I830_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(screen->front.pitch) |     /* pitch in bytes */
+                                                 BUF_3D_USE_FENCE);
+
+
+   i830->state.Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+   i830->state.Buffer[I830_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | BUF_3D_PITCH(screen->depth.pitch) |  /* pitch in bytes */
+                                                 BUF_3D_USE_FENCE);
+
+   i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
+
+   switch (screen->fbFormat) {
+   case DV_PF_565:
+      i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |   /* .5 */
+                                              DSTORG_VERT_BIAS(0x8) |   /* .5 */
+                                              screen->fbFormat |
+                                              DEPTH_IS_Z |
+                                              DEPTH_FRMT_16_FIXED);
+      break;
+   case DV_PF_8888:
+      i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |   /* .5 */
+                                              DSTORG_VERT_BIAS(0x8) |   /* .5 */
+                                              screen->fbFormat |
+                                              DEPTH_IS_Z |
+                                              DEPTH_FRMT_24_FIXED_8_OTHER);
+      break;
+   }
+
+   i830->state.Buffer[I830_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
+                                               DISABLE_SCISSOR_RECT);
+   i830->state.Buffer[I830_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD;
+   i830->state.Buffer[I830_DESTREG_SR1] = 0;
+   i830->state.Buffer[I830_DESTREG_SR2] = 0;
+}
+
+
+void
+i830InitStateFuncs(struct dd_function_table *functions)
+{
+   functions->AlphaFunc = i830AlphaFunc;
+   functions->BlendColor = i830BlendColor;
+   functions->BlendEquationSeparate = i830BlendEquationSeparate;
+   functions->BlendFuncSeparate = i830BlendFuncSeparate;
+   functions->ColorMask = i830ColorMask;
+   functions->CullFace = i830CullFaceFrontFace;
+   functions->DepthFunc = i830DepthFunc;
+   functions->DepthMask = i830DepthMask;
+   functions->Enable = i830Enable;
+   functions->Fogfv = i830Fogfv;
+   functions->FrontFace = i830CullFaceFrontFace;
+   functions->LightModelfv = i830LightModelfv;
+   functions->LineWidth = i830LineWidth;
+   functions->LogicOpcode = i830LogicOp;
+   functions->PointSize = i830PointSize;
+   functions->PolygonStipple = i830PolygonStipple;
+   functions->Scissor = i830Scissor;
+   functions->ShadeModel = i830ShadeModel;
+   functions->StencilFuncSeparate = i830StencilFuncSeparate;
+   functions->StencilMaskSeparate = i830StencilMaskSeparate;
+   functions->StencilOpSeparate = i830StencilOpSeparate;
+}
+
+void
+i830InitState(struct i830_context *i830)
+{
+   GLcontext *ctx = &i830->intel.ctx;
+
+   i830_init_packets(i830);
+
+   intelInitState(ctx);
+
+   memcpy(&i830->initial, &i830->state, sizeof(i830->state));
+
+   i830->current = &i830->state;
+   i830->state.emitted = 0;
+   i830->state.active = (I830_UPLOAD_INVARIENT |
+                         I830_UPLOAD_TEXBLEND(0) |
+                         I830_UPLOAD_STIPPLE |
+                         I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS);
+}
diff --git a/src/mesa/drivers/dri/i915tex/i830_tex.c b/src/mesa/drivers/dri/i915tex/i830_tex.c
new file mode 100644 (file)
index 0000000..fed464d
--- /dev/null
@@ -0,0 +1,100 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "image.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "texmem.h"
+#include "swrast/swrast.h"
+
+#include "mm.h"
+
+#include "intel_ioctl.h"
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+
+
+static void
+i830TexEnv(GLcontext * ctx, GLenum target,
+           GLenum pname, const GLfloat * param)
+{
+
+   switch (pname) {
+   case GL_TEXTURE_ENV_COLOR:
+   case GL_TEXTURE_ENV_MODE:
+   case GL_COMBINE_RGB:
+   case GL_COMBINE_ALPHA:
+   case GL_SOURCE0_RGB:
+   case GL_SOURCE1_RGB:
+   case GL_SOURCE2_RGB:
+   case GL_SOURCE0_ALPHA:
+   case GL_SOURCE1_ALPHA:
+   case GL_SOURCE2_ALPHA:
+   case GL_OPERAND0_RGB:
+   case GL_OPERAND1_RGB:
+   case GL_OPERAND2_RGB:
+   case GL_OPERAND0_ALPHA:
+   case GL_OPERAND1_ALPHA:
+   case GL_OPERAND2_ALPHA:
+   case GL_RGB_SCALE:
+   case GL_ALPHA_SCALE:
+      break;
+
+   case GL_TEXTURE_LOD_BIAS:{
+         struct i830_context *i830 = i830_context(ctx);
+         GLuint unit = ctx->Texture.CurrentUnit;
+         int b = (int) ((*param) * 16.0);
+         if (b > 63)
+            b = 63;
+         if (b < -64)
+            b = -64;
+         I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
+         i830->lodbias_tm0s3[unit] =
+            ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
+         break;
+      }
+
+   default:
+      break;
+   }
+}
+
+
+
+
+void
+i830InitTextureFuncs(struct dd_function_table *functions)
+{
+   functions->TexEnv = i830TexEnv;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i830_texblend.c b/src/mesa/drivers/dri/i915tex/i830_texblend.c
new file mode 100644 (file)
index 0000000..58f220e
--- /dev/null
@@ -0,0 +1,463 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "texformat.h"
+#include "texstore.h"
+
+#include "mm.h"
+
+#include "intel_screen.h"
+#include "intel_ioctl.h"
+#include "intel_tex.h"
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+
+/* ================================================================
+ * Texture combine functions
+ */
+static GLuint
+pass_through(GLuint * state, GLuint blendUnit)
+{
+   state[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+               TEXPIPE_COLOR |
+               ENABLE_TEXOUTPUT_WRT_SEL |
+               TEXOP_OUTPUT_CURRENT |
+               DISABLE_TEX_CNTRL_STAGE |
+               TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
+   state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+               TEXPIPE_ALPHA |
+               ENABLE_TEXOUTPUT_WRT_SEL |
+               TEXOP_OUTPUT_CURRENT |
+               TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
+   state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+               TEXPIPE_COLOR |
+               TEXBLEND_ARG1 |
+               TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT);
+   state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+               TEXPIPE_ALPHA |
+               TEXBLEND_ARG1 |
+               TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT);
+
+   return 4;
+}
+
+static GLuint
+emit_factor(GLuint blendUnit, GLuint * state, GLuint count,
+            const GLfloat * factor)
+{
+   GLubyte r, g, b, a;
+   GLuint col;
+
+   if (0)
+      fprintf(stderr, "emit constant %d: %.2f %.2f %.2f %.2f\n",
+              blendUnit, factor[0], factor[1], factor[2], factor[3]);
+
+   UNCLAMPED_FLOAT_TO_UBYTE(r, factor[0]);
+   UNCLAMPED_FLOAT_TO_UBYTE(g, factor[1]);
+   UNCLAMPED_FLOAT_TO_UBYTE(b, factor[2]);
+   UNCLAMPED_FLOAT_TO_UBYTE(a, factor[3]);
+
+   col = ((a << 24) | (r << 16) | (g << 8) | b);
+
+   state[count++] = _3DSTATE_COLOR_FACTOR_N_CMD(blendUnit);
+   state[count++] = col;
+
+   return count;
+}
+
+
+static INLINE GLuint
+GetTexelOp(GLint unit)
+{
+   switch (unit) {
+   case 0:
+      return TEXBLENDARG_TEXEL0;
+   case 1:
+      return TEXBLENDARG_TEXEL1;
+   case 2:
+      return TEXBLENDARG_TEXEL2;
+   case 3:
+      return TEXBLENDARG_TEXEL3;
+   default:
+      return TEXBLENDARG_TEXEL0;
+   }
+}
+
+
+/**
+ * Calculate the hardware instuctions to setup the current texture enviromnemt
+ * settings.  Since \c gl_texture_unit::_CurrentCombine is used, both
+ * "classic" texture enviroments and GL_ARB_texture_env_combine type texture
+ * environments are treated identically.
+ *
+ * \todo
+ * This function should return \c GLboolean.  When \c GL_FALSE is returned,
+ * it means that an environment is selected that the hardware cannot do.  This
+ * is the way the Radeon and R200 drivers work.
+ * 
+ * \todo
+ * Looking at i830_3d_regs.h, it seems the i830 can do part of
+ * GL_ATI_texture_env_combine3.  It can handle using \c GL_ONE and
+ * \c GL_ZERO as combine inputs (which the code already supports).  It can
+ * also handle the \c GL_MODULATE_ADD_ATI mode.  Is it worth investigating
+ * partial support for the extension?
+ */
+GLuint
+i830SetTexEnvCombine(struct i830_context * i830,
+                     const struct gl_tex_env_combine_state * combine,
+                     GLint blendUnit,
+                     GLuint texel_op, GLuint * state, const GLfloat * factor)
+{
+   const GLuint numColorArgs = combine->_NumArgsRGB;
+   const GLuint numAlphaArgs = combine->_NumArgsA;
+
+   GLuint blendop;
+   GLuint ablendop;
+   GLuint args_RGB[3];
+   GLuint args_A[3];
+   GLuint rgb_shift;
+   GLuint alpha_shift;
+   GLboolean need_factor = 0;
+   int i;
+   unsigned used;
+   static const GLuint tex_blend_rgb[3] = {
+      TEXPIPE_COLOR | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS,
+      TEXPIPE_COLOR | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS,
+      TEXPIPE_COLOR | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
+   };
+   static const GLuint tex_blend_a[3] = {
+      TEXPIPE_ALPHA | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS,
+      TEXPIPE_ALPHA | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS,
+      TEXPIPE_ALPHA | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
+   };
+
+   if (INTEL_DEBUG & DEBUG_TEXTURE)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+   /* The EXT version of the DOT3 extension does not support the
+    * scale factor, but the ARB version (and the version in OpenGL
+    * 1.3) does.
+    */
+   switch (combine->ModeRGB) {
+   case GL_DOT3_RGB_EXT:
+      alpha_shift = combine->ScaleShiftA;
+      rgb_shift = 0;
+      break;
+
+   case GL_DOT3_RGBA_EXT:
+      alpha_shift = 0;
+      rgb_shift = 0;
+      break;
+
+   default:
+      rgb_shift = combine->ScaleShiftRGB;
+      alpha_shift = combine->ScaleShiftA;
+      break;
+   }
+
+
+   switch (combine->ModeRGB) {
+   case GL_REPLACE:
+      blendop = TEXBLENDOP_ARG1;
+      break;
+   case GL_MODULATE:
+      blendop = TEXBLENDOP_MODULATE;
+      break;
+   case GL_ADD:
+      blendop = TEXBLENDOP_ADD;
+      break;
+   case GL_ADD_SIGNED:
+      blendop = TEXBLENDOP_ADDSIGNED;
+      break;
+   case GL_INTERPOLATE:
+      blendop = TEXBLENDOP_BLEND;
+      break;
+   case GL_SUBTRACT:
+      blendop = TEXBLENDOP_SUBTRACT;
+      break;
+   case GL_DOT3_RGB_EXT:
+   case GL_DOT3_RGB:
+      blendop = TEXBLENDOP_DOT3;
+      break;
+   case GL_DOT3_RGBA_EXT:
+   case GL_DOT3_RGBA:
+      blendop = TEXBLENDOP_DOT3;
+      break;
+   default:
+      return pass_through(state, blendUnit);
+   }
+
+   blendop |= (rgb_shift << TEXOP_SCALE_SHIFT);
+
+
+   /* Handle RGB args */
+   for (i = 0; i < 3; i++) {
+      switch (combine->SourceRGB[i]) {
+      case GL_TEXTURE:
+         args_RGB[i] = texel_op;
+         break;
+      case GL_TEXTURE0:
+      case GL_TEXTURE1:
+      case GL_TEXTURE2:
+      case GL_TEXTURE3:
+         args_RGB[i] = GetTexelOp(combine->SourceRGB[i] - GL_TEXTURE0);
+         break;
+      case GL_CONSTANT:
+         args_RGB[i] = TEXBLENDARG_FACTOR_N;
+         need_factor = 1;
+         break;
+      case GL_PRIMARY_COLOR:
+         args_RGB[i] = TEXBLENDARG_DIFFUSE;
+         break;
+      case GL_PREVIOUS:
+         args_RGB[i] = TEXBLENDARG_CURRENT;
+         break;
+      default:
+         return pass_through(state, blendUnit);
+      }
+
+      switch (combine->OperandRGB[i]) {
+      case GL_SRC_COLOR:
+         args_RGB[i] |= 0;
+         break;
+      case GL_ONE_MINUS_SRC_COLOR:
+         args_RGB[i] |= TEXBLENDARG_INV_ARG;
+         break;
+      case GL_SRC_ALPHA:
+         args_RGB[i] |= TEXBLENDARG_REPLICATE_ALPHA;
+         break;
+      case GL_ONE_MINUS_SRC_ALPHA:
+         args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA | TEXBLENDARG_INV_ARG);
+         break;
+      default:
+         return pass_through(state, blendUnit);
+      }
+   }
+
+
+   /* Need to knobble the alpha calculations of TEXBLENDOP_DOT4 to
+    * match the spec.  Can't use DOT3 as it won't propogate values
+    * into alpha as required:
+    *
+    * Note - the global factor is set up with alpha == .5, so 
+    * the alpha part of the DOT4 calculation should be zero.
+    */
+   if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
+       combine->ModeRGB == GL_DOT3_RGBA) {
+      ablendop = TEXBLENDOP_DOT4;
+      args_A[0] = TEXBLENDARG_FACTOR;   /* the global factor */
+      args_A[1] = TEXBLENDARG_FACTOR;
+      args_A[2] = TEXBLENDARG_FACTOR;
+   }
+   else {
+      switch (combine->ModeA) {
+      case GL_REPLACE:
+         ablendop = TEXBLENDOP_ARG1;
+         break;
+      case GL_MODULATE:
+         ablendop = TEXBLENDOP_MODULATE;
+         break;
+      case GL_ADD:
+         ablendop = TEXBLENDOP_ADD;
+         break;
+      case GL_ADD_SIGNED:
+         ablendop = TEXBLENDOP_ADDSIGNED;
+         break;
+      case GL_INTERPOLATE:
+         ablendop = TEXBLENDOP_BLEND;
+         break;
+      case GL_SUBTRACT:
+         ablendop = TEXBLENDOP_SUBTRACT;
+         break;
+      default:
+         return pass_through(state, blendUnit);
+      }
+
+
+      ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
+
+      /* Handle A args */
+      for (i = 0; i < 3; i++) {
+         switch (combine->SourceA[i]) {
+         case GL_TEXTURE:
+            args_A[i] = texel_op;
+            break;
+         case GL_TEXTURE0:
+         case GL_TEXTURE1:
+         case GL_TEXTURE2:
+         case GL_TEXTURE3:
+            args_A[i] = GetTexelOp(combine->SourceA[i] - GL_TEXTURE0);
+            break;
+         case GL_CONSTANT:
+            args_A[i] = TEXBLENDARG_FACTOR_N;
+            need_factor = 1;
+            break;
+         case GL_PRIMARY_COLOR:
+            args_A[i] = TEXBLENDARG_DIFFUSE;
+            break;
+         case GL_PREVIOUS:
+            args_A[i] = TEXBLENDARG_CURRENT;
+            break;
+         default:
+            return pass_through(state, blendUnit);
+         }
+
+         switch (combine->OperandA[i]) {
+         case GL_SRC_ALPHA:
+            args_A[i] |= 0;
+            break;
+         case GL_ONE_MINUS_SRC_ALPHA:
+            args_A[i] |= TEXBLENDARG_INV_ARG;
+            break;
+         default:
+            return pass_through(state, blendUnit);
+         }
+      }
+   }
+
+
+
+   /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
+   /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
+   /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
+
+   /* When we render we need to figure out which is the last really enabled
+    * tex unit, and put last stage on it
+    */
+
+
+   /* Build color & alpha pipelines */
+
+   used = 0;
+   state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT |
+                    DISABLE_TEX_CNTRL_STAGE | TEXOP_MODIFY_PARMS | blendop);
+   state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT | TEXOP_MODIFY_PARMS | ablendop);
+
+   for (i = 0; i < numColorArgs; i++) {
+      state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                       tex_blend_rgb[i] | args_RGB[i]);
+   }
+
+   for (i = 0; i < numAlphaArgs; i++) {
+      state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                       tex_blend_a[i] | args_A[i]);
+   }
+
+
+   if (need_factor)
+      return emit_factor(blendUnit, state, used, factor);
+   else
+      return used;
+}
+
+
+static void
+emit_texblend(struct i830_context *i830, GLuint unit, GLuint blendUnit,
+              GLboolean last_stage)
+{
+   struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
+   GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
+
+
+   if (0)
+      fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
+
+   /* Update i830->state.TexBlend
+    */
+   tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit,
+                                 GetTexelOp(unit), tmp, texUnit->EnvColor);
+
+   if (last_stage)
+      tmp[0] |= TEXOP_LAST_STAGE;
+
+   if (tmp_sz != i830->state.TexBlendWordsUsed[blendUnit] ||
+       memcmp(tmp, i830->state.TexBlend[blendUnit],
+              tmp_sz * sizeof(GLuint))) {
+
+      I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(blendUnit));
+      memcpy(i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint));
+      i830->state.TexBlendWordsUsed[blendUnit] = tmp_sz;
+   }
+
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), GL_TRUE);
+}
+
+static void
+emit_passthrough(struct i830_context *i830)
+{
+   GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
+   GLuint unit = 0;
+
+   tmp_sz = pass_through(tmp, unit);
+   tmp[0] |= TEXOP_LAST_STAGE;
+
+   if (tmp_sz != i830->state.TexBlendWordsUsed[unit] ||
+       memcmp(tmp, i830->state.TexBlend[unit], tmp_sz * sizeof(GLuint))) {
+
+      I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(unit));
+      memcpy(i830->state.TexBlend[unit], tmp, tmp_sz * sizeof(GLuint));
+      i830->state.TexBlendWordsUsed[unit] = tmp_sz;
+   }
+
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), GL_TRUE);
+}
+
+void
+i830EmitTextureBlend(struct i830_context *i830)
+{
+   GLcontext *ctx = &i830->intel.ctx;
+   GLuint unit, last_stage = 0, blendunit = 0;
+
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND_ALL, GL_FALSE);
+
+   if (ctx->Texture._EnabledUnits) {
+      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
+         if (ctx->Texture.Unit[unit]._ReallyEnabled)
+            last_stage = unit;
+
+      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
+         if (ctx->Texture.Unit[unit]._ReallyEnabled)
+            emit_texblend(i830, unit, blendunit++, last_stage == unit);
+   }
+   else {
+      emit_passthrough(i830);
+   }
+}
diff --git a/src/mesa/drivers/dri/i915tex/i830_texstate.c b/src/mesa/drivers/dri/i915tex/i830_texstate.c
new file mode 100644 (file)
index 0000000..ba79cf9
--- /dev/null
@@ -0,0 +1,316 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "texformat.h"
+#include "texstore.h"
+
+#include "mm.h"
+
+#include "intel_screen.h"
+#include "intel_ioctl.h"
+#include "intel_tex.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+
+
+static GLuint
+translate_texture_format(GLuint mesa_format)
+{
+   switch (mesa_format) {
+   case MESA_FORMAT_L8:
+      return MAPSURF_8BIT | MT_8BIT_L8;
+   case MESA_FORMAT_I8:
+      return MAPSURF_8BIT | MT_8BIT_I8;
+   case MESA_FORMAT_A8:
+      return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */
+   case MESA_FORMAT_AL88:
+      return MAPSURF_16BIT | MT_16BIT_AY88;
+   case MESA_FORMAT_RGB565:
+      return MAPSURF_16BIT | MT_16BIT_RGB565;
+   case MESA_FORMAT_ARGB1555:
+      return MAPSURF_16BIT | MT_16BIT_ARGB1555;
+   case MESA_FORMAT_ARGB4444:
+      return MAPSURF_16BIT | MT_16BIT_ARGB4444;
+   case MESA_FORMAT_ARGB8888:
+      return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+   case MESA_FORMAT_YCBCR_REV:
+      return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
+   case MESA_FORMAT_YCBCR:
+      return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
+   case MESA_FORMAT_RGB_FXT1:
+   case MESA_FORMAT_RGBA_FXT1:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
+   case MESA_FORMAT_RGBA_DXT1:
+   case MESA_FORMAT_RGB_DXT1:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
+   case MESA_FORMAT_RGBA_DXT3:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
+   case MESA_FORMAT_RGBA_DXT5:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
+   default:
+      fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
+      abort();
+      return 0;
+   }
+}
+
+
+
+
+/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
+ * Intel drivers for "other operating systems" implement GL_CLAMP as
+ * GL_CLAMP_TO_EDGE, so the same is done here.
+ */
+static GLuint
+translate_wrap_mode(GLenum wrap)
+{
+   switch (wrap) {
+   case GL_REPEAT:
+      return TEXCOORDMODE_WRAP;
+   case GL_CLAMP:
+   case GL_CLAMP_TO_EDGE:
+      return TEXCOORDMODE_CLAMP;        /* not really correct */
+   case GL_CLAMP_TO_BORDER:
+      return TEXCOORDMODE_CLAMP_BORDER;
+   case GL_MIRRORED_REPEAT:
+      return TEXCOORDMODE_MIRROR;
+   default:
+      return TEXCOORDMODE_WRAP;
+   }
+}
+
+
+/* Recalculate all state from scratch.  Perhaps not the most
+ * efficient, but this has gotten complex enough that we need
+ * something which is understandable and reliable.
+ */
+static GLboolean
+i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
+{
+   GLcontext *ctx = &intel->ctx;
+   struct i830_context *i830 = i830_context(ctx);
+   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
+   struct intel_texture_object *intelObj = intel_texture_object(tObj);
+   struct gl_texture_image *firstImage;
+   GLuint *state = i830->state.Tex[unit];
+
+   memset(state, 0, sizeof(state));
+
+   if (!intel_finalize_mipmap_tree(intel, unit))
+      return GL_FALSE;
+
+   /* Get first image here, since intelObj->firstLevel will get set in
+    * the intel_finalize_mipmap_tree() call above.
+    */
+   firstImage = tObj->Image[0][intelObj->firstLevel];
+
+   i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
+   i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0,
+                                                             intelObj->
+                                                             firstLevel);
+
+
+   state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+                               (LOAD_TEXTURE_MAP0 << unit) | 4);
+
+/*    state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */
+/*                            t->intel.TextureOffset); */
+
+
+   state[I830_TEXREG_TM0S1] =
+      (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
+       ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) |
+       translate_texture_format(firstImage->TexFormat->MesaFormat));
+
+   state[I830_TEXREG_TM0S2] =
+      (((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) -
+         1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
+
+   {
+      if (tObj->Target == GL_TEXTURE_CUBE_MAP)
+         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
+                                    CUBE_NEGX_ENABLE |
+                                    CUBE_POSX_ENABLE |
+                                    CUBE_NEGY_ENABLE |
+                                    CUBE_POSY_ENABLE |
+                                    CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
+      else
+         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
+   }
+
+
+
+
+   {
+      GLuint minFilt, mipFilt, magFilt;
+
+      switch (tObj->MinFilter) {
+      case GL_NEAREST:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_NONE;
+         break;
+      case GL_LINEAR:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_NONE;
+         break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_NEAREST;
+         break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_NEAREST;
+         break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_LINEAR;
+         break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_LINEAR;
+         break;
+      default:
+         return GL_FALSE;
+      }
+
+      if (tObj->MaxAnisotropy > 1.0) {
+         minFilt = FILTER_ANISOTROPIC;
+         magFilt = FILTER_ANISOTROPIC;
+      }
+      else {
+         switch (tObj->MagFilter) {
+         case GL_NEAREST:
+            magFilt = FILTER_NEAREST;
+            break;
+         case GL_LINEAR:
+            magFilt = FILTER_LINEAR;
+            break;
+         default:
+            return GL_FALSE;
+         }
+      }
+
+      state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit];
+
+#if 0
+      /* YUV conversion:
+       */
+      if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
+          firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
+         state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
+#endif
+
+      state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
+                                    intelObj->firstLevel) *
+                                   4) << TM0S3_MIN_MIP_SHIFT;
+
+      state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
+                                   (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
+                                   (magFilt << TM0S3_MAG_FILTER_SHIFT));
+   }
+
+   {
+      GLenum ws = tObj->WrapS;
+      GLenum wt = tObj->WrapT;
+
+
+      /* 3D textures not available on i830
+       */
+      if (tObj->Target == GL_TEXTURE_3D)
+         return GL_FALSE;
+
+      state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
+                                MAP_UNIT(unit) |
+                                ENABLE_TEXCOORD_PARAMS |
+                                ss3 |
+                                ENABLE_ADDR_V_CNTL |
+                                TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt))
+                                | ENABLE_ADDR_U_CNTL |
+                                TEXCOORD_ADDR_U_MODE(translate_wrap_mode
+                                                     (ws)));
+   }
+
+
+   state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
+                                                  tObj->_BorderChan[1],
+                                                  tObj->_BorderChan[2],
+                                                  tObj->_BorderChan[3]);
+
+
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
+   /* memcmp was already disabled, but definitely won't work as the
+    * region might now change and that wouldn't be detected:
+    */
+   I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
+   return GL_TRUE;
+}
+
+
+
+
+void
+i830UpdateTextureState(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   GLboolean ok = GL_TRUE;
+   GLuint i;
+
+   for (i = 0; i < I830_TEX_UNITS && ok; i++) {
+      switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
+      case TEXTURE_1D_BIT:
+      case TEXTURE_2D_BIT:
+      case TEXTURE_CUBE_BIT:
+         ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL);
+         break;
+      case TEXTURE_RECT_BIT:
+         ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS);
+         break;
+      case 0:
+         if (i830->state.active & I830_UPLOAD_TEX(i))
+            I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
+         break;
+      case TEXTURE_3D_BIT:
+      default:
+         ok = GL_FALSE;
+         break;
+      }
+   }
+
+   FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok);
+
+   if (ok)
+      i830EmitTextureBlend(i830);
+}
diff --git a/src/mesa/drivers/dri/i915tex/i830_vtbl.c b/src/mesa/drivers/dri/i915tex/i830_vtbl.c
new file mode 100644 (file)
index 0000000..45502da
--- /dev/null
@@ -0,0 +1,606 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "i830_context.h"
+#include "i830_reg.h"
+#include "intel_batchbuffer.h"
+#include "intel_regions.h"
+#include "tnl/t_context.h"
+#include "tnl/t_vertex.h"
+
+#define FILE_DEBUG_FLAG DEBUG_STATE
+
+static GLboolean i830_check_vertex_size(struct intel_context *intel,
+                                        GLuint expected);
+
+#define SZ_TO_HW(sz)  ((sz-2)&0x3)
+#define EMIT_SZ(sz)   (EMIT_1F + (sz) - 1)
+#define EMIT_ATTR( ATTR, STYLE, V0 )                                   \
+do {                                                                   \
+   intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR);      \
+   intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE);     \
+   intel->vertex_attr_count++;                                         \
+   v0 |= V0;                                                           \
+} while (0)
+
+#define EMIT_PAD( N )                                                  \
+do {                                                                   \
+   intel->vertex_attrs[intel->vertex_attr_count].attrib = 0;           \
+   intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD;    \
+   intel->vertex_attrs[intel->vertex_attr_count].offset = (N);         \
+   intel->vertex_attr_count++;                                         \
+} while (0)
+
+
+#define VRTX_TEX_SET_FMT(n, x)          ((x)<<((n)*2))
+#define TEXBIND_SET(n, x)              ((x)<<((n)*4))
+
+static void
+i830_render_start(struct intel_context *intel)
+{
+   GLcontext *ctx = &intel->ctx;
+   struct i830_context *i830 = i830_context(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   DECLARE_RENDERINPUTS(index_bitset);
+   GLuint v0 = _3DSTATE_VFT0_CMD;
+   GLuint v2 = _3DSTATE_VFT1_CMD;
+   GLuint mcsb1 = 0;
+
+   RENDERINPUTS_COPY(index_bitset, tnl->render_inputs_bitset);
+
+   /* Important:
+    */
+   VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
+   intel->vertex_attr_count = 0;
+
+   /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
+    * build up a hardware vertex.
+    */
+   if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) {
+      EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW);
+      intel->coloroffset = 4;
+   }
+   else {
+      EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ);
+      intel->coloroffset = 3;
+   }
+
+   if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_POINTSIZE)) {
+      EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH);
+   }
+
+   EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE);
+
+   intel->specoffset = 0;
+   if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1) ||
+       RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG)) {
+      if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1)) {
+         intel->specoffset = intel->coloroffset + 1;
+         EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC);
+      }
+      else
+         EMIT_PAD(3);
+
+      if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG))
+         EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC);
+      else
+         EMIT_PAD(1);
+   }
+
+   if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) {
+      int i, count = 0;
+
+      for (i = 0; i < I830_TEX_UNITS; i++) {
+         if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_TEX(i))) {
+            GLuint sz = VB->TexCoordPtr[i]->size;
+            GLuint emit;
+            GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
+                          ~TEXCOORDTYPE_MASK);
+
+            switch (sz) {
+            case 1:
+            case 2:
+               emit = EMIT_2F;
+               sz = 2;
+               mcs |= TEXCOORDTYPE_CARTESIAN;
+               break;
+            case 3:
+               emit = EMIT_3F;
+               sz = 3;
+               mcs |= TEXCOORDTYPE_VECTOR;
+               break;
+            case 4:
+               emit = EMIT_3F_XYW;
+               sz = 3;
+               mcs |= TEXCOORDTYPE_HOMOGENEOUS;
+               break;
+            default:
+               continue;
+            };
+
+
+            EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, emit, 0);
+            v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz));
+            mcsb1 |= (count + 8) << (i * 4);
+
+            if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) {
+               I830_STATECHANGE(i830, I830_UPLOAD_TEX(i));
+               i830->state.Tex[i][I830_TEXREG_MCS] = mcs;
+            }
+
+            count++;
+         }
+      }
+
+      v0 |= VFT0_TEX_COUNT(count);
+   }
+
+   /* Only need to change the vertex emit code if there has been a
+    * statechange to a new hardware vertex format:
+    */
+   if (v0 != i830->state.Ctx[I830_CTXREG_VF] ||
+       v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
+       mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
+       !RENDERINPUTS_EQUAL(index_bitset, i830->last_index_bitset)) {
+      int k;
+
+      I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+
+      /* Must do this *after* statechange, so as not to affect
+       * buffered vertices reliant on the old state:
+       */
+      intel->vertex_size =
+         _tnl_install_attrs(ctx,
+                            intel->vertex_attrs,
+                            intel->vertex_attr_count,
+                            intel->ViewportMatrix.m, 0);
+
+      intel->vertex_size >>= 2;
+
+      i830->state.Ctx[I830_CTXREG_VF] = v0;
+      i830->state.Ctx[I830_CTXREG_VF2] = v2;
+      i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
+      RENDERINPUTS_COPY(i830->last_index_bitset, index_bitset);
+
+      k = i830_check_vertex_size(intel, intel->vertex_size);
+      assert(k);
+   }
+}
+
+static void
+i830_reduced_primitive_state(struct intel_context *intel, GLenum rprim)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   GLuint st1 = i830->state.Stipple[I830_STPREG_ST1];
+
+   st1 &= ~ST1_ENABLE;
+
+   switch (rprim) {
+   case GL_TRIANGLES:
+      if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple)
+         st1 |= ST1_ENABLE;
+      break;
+   case GL_LINES:
+   case GL_POINTS:
+   default:
+      break;
+   }
+
+   i830->intel.reduced_primitive = rprim;
+
+   if (st1 != i830->state.Stipple[I830_STPREG_ST1]) {
+      INTEL_FIREVERTICES(intel);
+
+      I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
+      i830->state.Stipple[I830_STPREG_ST1] = st1;
+   }
+}
+
+/* Pull apart the vertex format registers and figure out how large a
+ * vertex is supposed to be. 
+ */
+static GLboolean
+i830_check_vertex_size(struct intel_context *intel, GLuint expected)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   int vft0 = i830->current->Ctx[I830_CTXREG_VF];
+   int vft1 = i830->current->Ctx[I830_CTXREG_VF2];
+   int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT;
+   int i, sz = 0;
+
+   switch (vft0 & VFT0_XYZW_MASK) {
+   case VFT0_XY:
+      sz = 2;
+      break;
+   case VFT0_XYZ:
+      sz = 3;
+      break;
+   case VFT0_XYW:
+      sz = 3;
+      break;
+   case VFT0_XYZW:
+      sz = 4;
+      break;
+   default:
+      fprintf(stderr, "no xyzw specified\n");
+      return 0;
+   }
+
+   if (vft0 & VFT0_SPEC)
+      sz++;
+   if (vft0 & VFT0_DIFFUSE)
+      sz++;
+   if (vft0 & VFT0_DEPTH_OFFSET)
+      sz++;
+   if (vft0 & VFT0_POINT_WIDTH)
+      sz++;
+
+   for (i = 0; i < nrtex; i++) {
+      switch (vft1 & VFT1_TEX0_MASK) {
+      case TEXCOORDFMT_2D:
+         sz += 2;
+         break;
+      case TEXCOORDFMT_3D:
+         sz += 3;
+         break;
+      case TEXCOORDFMT_4D:
+         sz += 4;
+         break;
+      case TEXCOORDFMT_1D:
+         sz += 1;
+         break;
+      }
+      vft1 >>= VFT1_TEX1_SHIFT;
+   }
+
+   if (sz != expected)
+      fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected);
+
+   return sz == expected;
+}
+
+static void
+i830_emit_invarient_state(struct intel_context *intel)
+{
+   BATCH_LOCALS;
+
+   BEGIN_BATCH(40, 0);
+
+   OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
+   OUT_BATCH(0);
+
+   OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
+   OUT_BATCH(0);
+
+   OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
+   OUT_BATCH(0);
+
+   OUT_BATCH(_3DSTATE_FOG_MODE_CMD);
+   OUT_BATCH(FOGFUNC_ENABLE |
+             FOG_LINEAR_CONST | FOGSRC_INDEX_Z | ENABLE_FOG_DENSITY);
+   OUT_BATCH(0);
+   OUT_BATCH(0);
+
+
+   OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
+             MAP_UNIT(0) |
+             DISABLE_TEX_STREAM_BUMP |
+             ENABLE_TEX_STREAM_COORD_SET |
+             TEX_STREAM_COORD_SET(0) |
+             ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0));
+   OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
+             MAP_UNIT(1) |
+             DISABLE_TEX_STREAM_BUMP |
+             ENABLE_TEX_STREAM_COORD_SET |
+             TEX_STREAM_COORD_SET(1) |
+             ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1));
+   OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
+             MAP_UNIT(2) |
+             DISABLE_TEX_STREAM_BUMP |
+             ENABLE_TEX_STREAM_COORD_SET |
+             TEX_STREAM_COORD_SET(2) |
+             ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2));
+   OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD |
+             MAP_UNIT(3) |
+             DISABLE_TEX_STREAM_BUMP |
+             ENABLE_TEX_STREAM_COORD_SET |
+             TEX_STREAM_COORD_SET(3) |
+             ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3));
+
+   OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0));
+   OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1));
+   OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2));
+   OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM);
+   OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3));
+
+   OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
+             ENABLE_POINT_RASTER_RULE |
+             OGL_POINT_RASTER_RULE |
+             ENABLE_LINE_STRIP_PROVOKE_VRTX |
+             ENABLE_TRI_FAN_PROVOKE_VRTX |
+             ENABLE_TRI_STRIP_PROVOKE_VRTX |
+             LINE_STRIP_PROVOKE_VRTX(1) |
+             TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2));
+
+   OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
+   OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
+
+   OUT_BATCH(_3DSTATE_W_STATE_CMD);
+   OUT_BATCH(MAGIC_W_STATE_DWORD1);
+   OUT_BATCH(0x3f800000 /* 1.0 in IEEE float */ );
+
+
+   OUT_BATCH(_3DSTATE_COLOR_FACTOR_CMD);
+   OUT_BATCH(0x80808080);       /* .5 required in alpha for GL_DOT3_RGBA_EXT */
+
+   ADVANCE_BATCH();
+}
+
+
+#define emit( intel, state, size )                     \
+do {                                                   \
+   int k;                                              \
+   BEGIN_BATCH(size / sizeof(GLuint), 0);              \
+   for (k = 0 ; k < size / sizeof(GLuint) ; k++) {     \
+      if (0) _mesa_printf("  0x%08x\n", state[k]);             \
+      OUT_BATCH(state[k]);                             \
+   }                                                   \
+   ADVANCE_BATCH();                                    \
+} while (0)
+
+static GLuint
+get_state_size(struct i830_hw_state *state)
+{
+   GLuint dirty = state->active & ~state->emitted;
+   GLuint sz = 0;
+   GLuint i;
+
+   if (dirty & I830_UPLOAD_INVARIENT)
+      sz += 40 * sizeof(int);
+
+   if (dirty & I830_UPLOAD_CTX)
+      sz += sizeof(state->Ctx);
+
+   if (dirty & I830_UPLOAD_BUFFERS)
+      sz += sizeof(state->Buffer);
+
+   if (dirty & I830_UPLOAD_STIPPLE)
+      sz += sizeof(state->Stipple);
+
+   for (i = 0; i < I830_TEX_UNITS; i++) {
+      if ((dirty & I830_UPLOAD_TEX(i)))
+         sz += sizeof(state->Tex[i]);
+
+      if (dirty & I830_UPLOAD_TEXBLEND(i))
+         sz += state->TexBlendWordsUsed[i] * 4;
+   }
+
+   return sz;
+}
+
+
+/* Push the state into the sarea and/or texture memory.
+ */
+static void
+i830_emit_state(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   struct i830_hw_state *state = i830->current;
+   int i;
+   GLuint dirty;
+   BATCH_LOCALS;
+
+   /* We don't hold the lock at this point, so want to make sure that
+    * there won't be a buffer wrap.  
+    *
+    * It might be better to talk about explicit places where
+    * scheduling is allowed, rather than assume that it is whenever a
+    * batchbuffer fills up.
+    */
+   intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
+
+   /* Do this here as we may have flushed the batchbuffer above,
+    * causing more state to be dirty!
+    */
+   dirty = state->active & ~state->emitted;
+
+   if (dirty & I830_UPLOAD_INVARIENT) {
+      DBG("I830_UPLOAD_INVARIENT:\n");
+      i830_emit_invarient_state(intel);
+   }
+
+   if (dirty & I830_UPLOAD_CTX) {
+      DBG("I830_UPLOAD_CTX:\n");
+      emit(i830, state->Ctx, sizeof(state->Ctx));
+
+   }
+
+   if (dirty & I830_UPLOAD_BUFFERS) {
+      DBG("I830_UPLOAD_BUFFERS:\n");
+      BEGIN_BATCH(I830_DEST_SETUP_SIZE + 2, 0);
+      OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]);
+      OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]);
+      OUT_RELOC(state->draw_region->buffer,
+                DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
+
+      if (state->depth_region) {
+         OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]);
+         OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]);
+         OUT_RELOC(state->depth_region->buffer,
+                   DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                   DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
+      }
+
+      OUT_BATCH(state->Buffer[I830_DESTREG_DV0]);
+      OUT_BATCH(state->Buffer[I830_DESTREG_DV1]);
+      OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]);
+      OUT_BATCH(state->Buffer[I830_DESTREG_SR0]);
+      OUT_BATCH(state->Buffer[I830_DESTREG_SR1]);
+      OUT_BATCH(state->Buffer[I830_DESTREG_SR2]);
+      ADVANCE_BATCH();
+   }
+
+   if (dirty & I830_UPLOAD_STIPPLE) {
+      DBG("I830_UPLOAD_STIPPLE:\n");
+      emit(i830, state->Stipple, sizeof(state->Stipple));
+   }
+
+   for (i = 0; i < I830_TEX_UNITS; i++) {
+      if ((dirty & I830_UPLOAD_TEX(i))) {
+         DBG("I830_UPLOAD_TEX(%d):\n", i);
+
+         BEGIN_BATCH(I830_TEX_SETUP_SIZE + 1, 0);
+         OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]);
+
+         if (state->tex_buffer[i]) {
+            OUT_RELOC(state->tex_buffer[i],
+                      DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                      DRM_BO_MASK_MEM | DRM_BO_FLAG_READ,
+                      state->tex_offset[i] | TM0S0_USE_FENCE);
+         }
+         else {
+            assert(i == 0);
+            assert(state == &i830->meta);
+            OUT_BATCH(0);
+         }
+
+         OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]);
+         OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]);
+         OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]);
+         OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]);
+         OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]);
+         OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]);
+      }
+
+      if (dirty & I830_UPLOAD_TEXBLEND(i)) {
+         DBG("I830_UPLOAD_TEXBLEND(%d): %d words\n", i,
+             state->TexBlendWordsUsed[i]);
+         emit(i830, state->TexBlend[i], state->TexBlendWordsUsed[i] * 4);
+      }
+   }
+
+   state->emitted |= dirty;
+}
+
+static void
+i830_destroy_context(struct intel_context *intel)
+{
+   _tnl_free_vertices(&intel->ctx);
+}
+
+static void
+i830_set_draw_region(struct intel_context *intel,
+                     struct intel_region *draw_region,
+                     struct intel_region *depth_region)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+
+   intel_region_release(&i830->state.draw_region);
+   intel_region_release(&i830->state.depth_region);
+   intel_region_reference(&i830->state.draw_region, draw_region);
+   intel_region_reference(&i830->state.depth_region, depth_region);
+
+   /* XXX FBO: Need code from i915_set_draw_region() */
+
+   I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
+   I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
+   i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
+      (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(draw_region->pitch) |
+       BUF_3D_USE_FENCE);
+   i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
+      (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depth_region->pitch) |
+       BUF_3D_USE_FENCE);
+}
+
+#if 0
+static void
+i830_update_color_z_regions(intelContextPtr intel,
+                            const intelRegion * colorRegion,
+                            const intelRegion * depthRegion)
+{
+   i830ContextPtr i830 = I830_CONTEXT(intel);
+
+   i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
+      (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) |
+       BUF_3D_USE_FENCE);
+   i830->state.Buffer[I830_DESTREG_CBUFADDR2] = colorRegion->offset;
+
+   i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
+      (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depthRegion->pitch) | BUF_3D_USE_FENCE);
+   i830->state.Buffer[I830_DESTREG_DBUFADDR2] = depthRegion->offset;
+}
+#endif
+
+
+/* This isn't really handled at the moment.
+ */
+static void
+i830_lost_hardware(struct intel_context *intel)
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   i830->state.emitted = 0;
+}
+
+
+
+static GLuint
+i830_flush_cmd(void)
+{
+   return MI_FLUSH | FLUSH_MAP_CACHE;
+}
+
+
+static void 
+i830_assert_not_dirty( struct intel_context *intel )
+{
+   struct i830_context *i830 = i830_context(&intel->ctx);
+   struct i830_hw_state *state = i830->current;
+   GLuint dirty = state->active & ~state->emitted;
+   assert(!dirty);
+}
+
+
+void
+i830InitVtbl(struct i830_context *i830)
+{
+   i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
+   i830->intel.vtbl.destroy = i830_destroy_context;
+   i830->intel.vtbl.emit_state = i830_emit_state;
+   i830->intel.vtbl.lost_hardware = i830_lost_hardware;
+   i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state;
+   i830->intel.vtbl.set_draw_region = i830_set_draw_region;
+   i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
+   i830->intel.vtbl.flush_cmd = i830_flush_cmd;
+   i830->intel.vtbl.render_start = i830_render_start;
+   i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_context.c b/src/mesa/drivers/dri/i915tex/i915_context.c
new file mode 100644 (file)
index 0000000..4cbe29d
--- /dev/null
@@ -0,0 +1,175 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "i915_context.h"
+#include "imports.h"
+#include "intel_tex.h"
+#include "intel_tris.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vertex.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "array_cache/acache.h"
+
+#include "utils.h"
+#include "i915_reg.h"
+
+#include "intel_regions.h"
+#include "intel_batchbuffer.h"
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+static const struct dri_extension i915_extensions[] = {
+   {"GL_ARB_depth_texture", NULL},
+   {"GL_ARB_fragment_program", NULL},
+   {"GL_ARB_shadow", NULL},
+   {"GL_ARB_texture_env_crossbar", NULL},
+   {"GL_ARB_texture_non_power_of_two", NULL},
+   {"GL_EXT_shadow_funcs", NULL},
+   /* ARB extn won't work if not enabled */
+   {"GL_SGIX_depth_texture", NULL},
+   {NULL, NULL}
+};
+
+/* Override intel default.
+ */
+static void
+i915InvalidateState(GLcontext * ctx, GLuint new_state)
+{
+   _swrast_InvalidateState(ctx, new_state);
+   _swsetup_InvalidateState(ctx, new_state);
+   _ac_InvalidateState(ctx, new_state);
+   _tnl_InvalidateState(ctx, new_state);
+   _tnl_invalidate_vertex_state(ctx, new_state);
+   intel_context(ctx)->NewGLState |= new_state;
+
+   /* Todo: gather state values under which tracked parameters become
+    * invalidated, add callbacks for things like
+    * ProgramLocalParameters, etc.
+    */
+   {
+      struct i915_fragment_program *p =
+         (struct i915_fragment_program *) ctx->FragmentProgram._Current;
+      if (p && p->nr_params)
+         p->params_uptodate = 0;
+   }
+
+   if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM))
+      i915_update_fog(ctx);
+}
+
+
+static void
+i915InitDriverFunctions(struct dd_function_table *functions)
+{
+   intelInitDriverFunctions(functions);
+   i915InitStateFunctions(functions);
+   i915InitTextureFuncs(functions);
+   i915InitFragProgFuncs(functions);
+   functions->UpdateState = i915InvalidateState;
+}
+
+
+
+GLboolean
+i915CreateContext(const __GLcontextModes * mesaVis,
+                  __DRIcontextPrivate * driContextPriv,
+                  void *sharedContextPrivate)
+{
+   struct dd_function_table functions;
+   struct i915_context *i915 =
+      (struct i915_context *) CALLOC_STRUCT(i915_context);
+   struct intel_context *intel = &i915->intel;
+   GLcontext *ctx = &intel->ctx;
+
+   if (!i915)
+      return GL_FALSE;
+
+   if (0)
+      _mesa_printf("\ntexmem-0-3 branch\n\n");
+
+   i915InitVtbl(i915);
+   i915InitMetaFuncs(i915);
+
+   i915InitDriverFunctions(&functions);
+
+   if (!intelInitContext(intel, mesaVis, driContextPriv,
+                         sharedContextPrivate, &functions)) {
+      FREE(i915);
+      return GL_FALSE;
+   }
+
+   ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
+   ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS;
+   ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS;
+
+
+   /* Advertise the full hardware capabilities.  The new memory
+    * manager should cope much better with overload situations:
+    */
+   ctx->Const.MaxTextureLevels = 12;
+   ctx->Const.Max3DTextureLevels = 9;
+   ctx->Const.MaxCubeTextureLevels = 12;
+   ctx->Const.MaxTextureRectSize = (1 << 11);
+   ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
+
+   /* GL_ARB_fragment_program limits - don't think Mesa actually
+    * validates programs against these, and in any case one ARB
+    * instruction can translate to more than one HW instruction, so
+    * we'll still have to check and fallback each time.
+    */
+   ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY;
+   ctx->Const.FragmentProgram.MaxNativeAttribs = 11;    /* 8 tex, 2 color, fog */
+   ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT;
+   ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN;
+   ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN;
+   ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +
+                                                       I915_MAX_TEX_INSN);
+   ctx->Const.FragmentProgram.MaxNativeTexIndirections =
+      I915_MAX_TEX_INDIRECT;
+   ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */
+
+   ctx->_MaintainTexEnvProgram = 1;
+   ctx->_UseTexEnvProgram = 1;
+
+   driInitExtensions(ctx, i915_extensions, GL_FALSE);
+
+
+   _tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
+                      36 * sizeof(GLfloat));
+
+   intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf;
+
+   i915InitState(i915);
+
+   return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_context.h b/src/mesa/drivers/dri/i915tex/i915_context.h
new file mode 100644 (file)
index 0000000..5ae76fc
--- /dev/null
@@ -0,0 +1,367 @@
+ /**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef I915CONTEXT_INC
+#define I915CONTEXT_INC
+
+#include "intel_context.h"
+
+#define I915_FALLBACK_TEXTURE           0x1000
+#define I915_FALLBACK_COLORMASK                 0x2000
+#define I915_FALLBACK_STENCIL           0x4000
+#define I915_FALLBACK_STIPPLE           0x8000
+#define I915_FALLBACK_PROGRAM           0x10000
+#define I915_FALLBACK_LOGICOP           0x20000
+#define I915_FALLBACK_POLYGON_SMOOTH    0x40000
+#define I915_FALLBACK_POINT_SMOOTH      0x80000
+
+#define I915_UPLOAD_CTX              0x1
+#define I915_UPLOAD_BUFFERS          0x2
+#define I915_UPLOAD_STIPPLE          0x4
+#define I915_UPLOAD_PROGRAM          0x8
+#define I915_UPLOAD_CONSTANTS        0x10
+#define I915_UPLOAD_FOG              0x20
+#define I915_UPLOAD_INVARIENT        0x40
+#define I915_UPLOAD_DEFAULTS         0x80
+#define I915_UPLOAD_TEX(i)           (0x00010000<<(i))
+#define I915_UPLOAD_TEX_ALL          (0x00ff0000)
+#define I915_UPLOAD_TEX_0_SHIFT      16
+
+
+/* State structure offsets - these will probably disappear.
+ */
+#define I915_DESTREG_CBUFADDR0 0
+#define I915_DESTREG_CBUFADDR1 1
+#define I915_DESTREG_DBUFADDR0 3
+#define I915_DESTREG_DBUFADDR1 4
+#define I915_DESTREG_DV0 6
+#define I915_DESTREG_DV1 7
+#define I915_DESTREG_SENABLE 8
+#define I915_DESTREG_SR0 9
+#define I915_DESTREG_SR1 10
+#define I915_DESTREG_SR2 11
+#define I915_DEST_SETUP_SIZE 12
+
+#define I915_CTXREG_STATE4             0
+#define I915_CTXREG_LI                 1
+#define I915_CTXREG_LIS2                       2
+#define I915_CTXREG_LIS4                       3
+#define I915_CTXREG_LIS5                       4
+#define I915_CTXREG_LIS6                       5
+#define I915_CTXREG_IAB                6
+#define I915_CTXREG_BLENDCOLOR0                7
+#define I915_CTXREG_BLENDCOLOR1                8
+#define I915_CTX_SETUP_SIZE            9
+
+#define I915_FOGREG_COLOR              0
+#define I915_FOGREG_MODE0              1
+#define I915_FOGREG_MODE1              2
+#define I915_FOGREG_MODE2              3
+#define I915_FOGREG_MODE3              4
+#define I915_FOG_SETUP_SIZE            5
+
+#define I915_STPREG_ST0        0
+#define I915_STPREG_ST1        1
+#define I915_STP_SETUP_SIZE    2
+
+#define I915_TEXREG_MS3        1
+#define I915_TEXREG_MS4        2
+#define I915_TEXREG_SS2        3
+#define I915_TEXREG_SS3        4
+#define I915_TEXREG_SS4        5
+#define I915_TEX_SETUP_SIZE    6
+
+#define I915_DEFREG_C0    0
+#define I915_DEFREG_C1    1
+#define I915_DEFREG_S0    2
+#define I915_DEFREG_S1    3
+#define I915_DEFREG_Z0    4
+#define I915_DEFREG_Z1    5
+#define I915_DEF_SETUP_SIZE    6
+
+
+#define I915_MAX_CONSTANT      32
+#define I915_CONSTANT_SIZE     (2+(4*I915_MAX_CONSTANT))
+
+
+#define I915_PROGRAM_SIZE      192
+
+
+/* Hardware version of a parsed fragment program.  "Derived" from the
+ * mesa fragment_program struct.
+ */
+struct i915_fragment_program
+{
+   struct gl_fragment_program FragProg;
+
+   GLboolean translated;
+   GLboolean params_uptodate;
+   GLboolean on_hardware;
+   GLboolean error;             /* If program is malformed for any reason. */
+
+   GLuint nr_tex_indirect;
+   GLuint nr_tex_insn;
+   GLuint nr_alu_insn;
+   GLuint nr_decl_insn;
+
+
+
+
+   /* TODO: split between the stored representation of a program and
+    * the state used to build that representation.
+    */
+   GLcontext *ctx;
+
+   GLuint declarations[I915_PROGRAM_SIZE];
+   GLuint program[I915_PROGRAM_SIZE];
+
+   GLfloat constant[I915_MAX_CONSTANT][4];
+   GLuint constant_flags[I915_MAX_CONSTANT];
+   GLuint nr_constants;
+
+   GLuint *csr;                 /* Cursor, points into program.
+                                 */
+
+   GLuint *decl;                /* Cursor, points into declarations.
+                                 */
+
+   GLuint decl_s;               /* flags for which s regs need to be decl'd */
+   GLuint decl_t;               /* flags for which t regs need to be decl'd */
+
+   GLuint temp_flag;            /* Tracks temporary regs which are in
+                                 * use.
+                                 */
+
+   GLuint utemp_flag;           /* Tracks TYPE_U temporary regs which are in
+                                 * use.
+                                 */
+
+
+
+   /* Helpers for i915_fragprog.c:
+    */
+   GLuint wpos_tex;
+   GLboolean depth_written;
+
+   struct
+   {
+      GLuint reg;               /* Hardware constant idx */
+      const GLfloat *values;    /* Pointer to tracked values */
+   } param[I915_MAX_CONSTANT];
+   GLuint nr_params;
+
+
+   /* Helpers for i915_texprog.c:
+    */
+   GLuint src_texture;          /* Reg containing sampled texture color,
+                                 * else UREG_BAD.
+                                 */
+
+   GLuint src_previous;         /* Reg containing color from previous 
+                                 * stage.  May need to be decl'd.
+                                 */
+
+   GLuint last_tex_stage;       /* Number of last enabled texture unit */
+
+   struct vertex_buffer *VB;
+};
+
+
+
+
+
+
+
+#define I915_TEX_UNITS 8
+
+
+struct i915_hw_state
+{
+   GLuint Ctx[I915_CTX_SETUP_SIZE];
+   GLuint Buffer[I915_DEST_SETUP_SIZE];
+   GLuint Stipple[I915_STP_SETUP_SIZE];
+   GLuint Fog[I915_FOG_SETUP_SIZE];
+   GLuint Defaults[I915_DEF_SETUP_SIZE];
+   GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE];
+   GLuint Constant[I915_CONSTANT_SIZE];
+   GLuint ConstantSize;
+   GLuint Program[I915_PROGRAM_SIZE];
+   GLuint ProgramSize;
+
+   /* Region pointers for relocation: 
+    */
+   struct intel_region *draw_region;
+   struct intel_region *depth_region;
+/*    struct intel_region *tex_region[I915_TEX_UNITS]; */
+
+   /* Regions aren't actually that appropriate here as the memory may
+    * be from a PBO or FBO.  Just use the buffer id.  Will have to do
+    * this for draw and depth for FBO's...
+    */
+   struct _DriBufferObject *tex_buffer[I915_TEX_UNITS];
+   GLuint tex_offset[I915_TEX_UNITS];
+
+
+   GLuint active;               /* I915_UPLOAD_* */
+   GLuint emitted;              /* I915_UPLOAD_* */
+};
+
+#define I915_FOG_PIXEL  2
+#define I915_FOG_VERTEX 1
+#define I915_FOG_NONE   0
+
+struct i915_context
+{
+   struct intel_context intel;
+
+   GLuint last_ReallyEnabled;
+   GLuint vertex_fog;
+   GLuint lodbias_ss2[MAX_TEXTURE_UNITS];
+
+
+   struct i915_fragment_program tex_program;
+   struct i915_fragment_program *current_program;
+
+   struct i915_hw_state meta, initial, state, *current;
+};
+
+
+#define I915_STATECHANGE(i915, flag)                                   \
+do {                                                                   \
+   INTEL_FIREVERTICES( &(i915)->intel );                                       \
+   (i915)->state.emitted &= ~(flag);                                   \
+} while (0)
+
+#define I915_ACTIVESTATE(i915, flag, mode)                     \
+do {                                                           \
+   INTEL_FIREVERTICES( &(i915)->intel );                               \
+   if (mode)                                                   \
+      (i915)->state.active |= (flag);                          \
+   else                                                                \
+      (i915)->state.active &= ~(flag);                         \
+} while (0)
+
+
+/*======================================================================
+ * i915_vtbl.c
+ */
+extern void i915InitVtbl(struct i915_context *i915);
+
+extern void
+i915_state_draw_region(struct intel_context *intel,
+                       struct i915_hw_state *state,
+                       struct intel_region *color_region,
+                       struct intel_region *depth_region);
+
+
+
+#define SZ_TO_HW(sz)  ((sz-2)&0x3)
+#define EMIT_SZ(sz)   (EMIT_1F + (sz) - 1)
+#define EMIT_ATTR( ATTR, STYLE, S4, SZ )                               \
+do {                                                                   \
+   intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR);      \
+   intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE);     \
+   s4 |= S4;                                                           \
+   intel->vertex_attr_count++;                                         \
+   offset += (SZ);                                                     \
+} while (0)
+
+#define EMIT_PAD( N )                                                  \
+do {                                                                   \
+   intel->vertex_attrs[intel->vertex_attr_count].attrib = 0;           \
+   intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD;    \
+   intel->vertex_attrs[intel->vertex_attr_count].offset = (N);         \
+   intel->vertex_attr_count++;                                         \
+   offset += (N);                                                      \
+} while (0)
+
+
+
+/*======================================================================
+ * i915_context.c
+ */
+extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
+                                   __DRIcontextPrivate * driContextPriv,
+                                   void *sharedContextPrivate);
+
+
+/*======================================================================
+ * i915_texprog.c
+ */
+extern void i915ValidateTextureProgram(struct i915_context *i915);
+
+
+/*======================================================================
+ * i915_debug.c
+ */
+extern void i915_disassemble_program(const GLuint * program, GLuint sz);
+extern void i915_print_ureg(const char *msg, GLuint ureg);
+
+
+/*======================================================================
+ * i915_state.c
+ */
+extern void i915InitStateFunctions(struct dd_function_table *functions);
+extern void i915InitState(struct i915_context *i915);
+extern void i915_update_fog(GLcontext * ctx);
+
+
+/*======================================================================
+ * i915_tex.c
+ */
+extern void i915UpdateTextureState(struct intel_context *intel);
+extern void i915InitTextureFuncs(struct dd_function_table *functions);
+
+/*======================================================================
+ * i915_metaops.c
+ */
+void i915InitMetaFuncs(struct i915_context *i915);
+
+
+/*======================================================================
+ * i915_fragprog.c
+ */
+extern void i915ValidateFragmentProgram(struct i915_context *i915);
+extern void i915InitFragProgFuncs(struct dd_function_table *functions);
+
+/*======================================================================
+ * Inline conversion functions.  These are better-typed than the
+ * macros used previously:
+ */
+static INLINE struct i915_context *
+i915_context(GLcontext * ctx)
+{
+   return (struct i915_context *) ctx;
+}
+
+
+
+#define I915_CONTEXT(ctx)      i915_context(ctx)
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/i915_debug.c b/src/mesa/drivers/dri/i915tex/i915_debug.c
new file mode 100644 (file)
index 0000000..974527e
--- /dev/null
@@ -0,0 +1,334 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include <stdio.h>
+
+
+static const char *opcodes[0x20] = {
+   "NOP",
+   "ADD",
+   "MOV",
+   "MUL",
+   "MAD",
+   "DP2ADD",
+   "DP3",
+   "DP4",
+   "FRC",
+   "RCP",
+   "RSQ",
+   "EXP",
+   "LOG",
+   "CMP",
+   "MIN",
+   "MAX",
+   "FLR",
+   "MOD",
+   "TRC",
+   "SGE",
+   "SLT",
+   "TEXLD",
+   "TEXLDP",
+   "TEXLDB",
+   "TEXKILL",
+   "DCL",
+   "0x1a",
+   "0x1b",
+   "0x1c",
+   "0x1d",
+   "0x1e",
+   "0x1f",
+};
+
+
+static const int args[0x20] = {
+   0,                           /* 0 nop */
+   2,                           /* 1 add */
+   1,                           /* 2 mov */
+   2,                           /* 3 m ul */
+   3,                           /* 4 mad */
+   3,                           /* 5 dp2add */
+   2,                           /* 6 dp3 */
+   2,                           /* 7 dp4 */
+   1,                           /* 8 frc */
+   1,                           /* 9 rcp */
+   1,                           /* a rsq */
+   1,                           /* b exp */
+   1,                           /* c log */
+   3,                           /* d cmp */
+   2,                           /* e min */
+   2,                           /* f max */
+   1,                           /* 10 flr */
+   1,                           /* 11 mod */
+   1,                           /* 12 trc */
+   2,                           /* 13 sge */
+   2,                           /* 14 slt */
+   1,
+   1,
+   1,
+   1,
+   0,
+   0,
+   0,
+   0,
+   0,
+   0,
+   0,
+};
+
+
+static const char *regname[0x8] = {
+   "R",
+   "T",
+   "CONST",
+   "S",
+   "OC",
+   "OD",
+   "U",
+   "UNKNOWN",
+};
+
+static void
+print_reg_type_nr(GLuint type, GLuint nr)
+{
+   switch (type) {
+   case REG_TYPE_T:
+      switch (nr) {
+      case T_DIFFUSE:
+         fprintf(stderr, "T_DIFFUSE");
+         return;
+      case T_SPECULAR:
+         fprintf(stderr, "T_SPECULAR");
+         return;
+      case T_FOG_W:
+         fprintf(stderr, "T_FOG_W");
+         return;
+      default:
+         fprintf(stderr, "T_TEX%d", nr);
+         return;
+      }
+   case REG_TYPE_OC:
+      if (nr == 0) {
+         fprintf(stderr, "oC");
+         return;
+      }
+      break;
+   case REG_TYPE_OD:
+      if (nr == 0) {
+         fprintf(stderr, "oD");
+         return;
+      }
+      break;
+   default:
+      break;
+   }
+
+   fprintf(stderr, "%s[%d]", regname[type], nr);
+}
+
+#define REG_SWIZZLE_MASK 0x7777
+#define REG_NEGATE_MASK 0x8888
+
+#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
+                     (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) |      \
+                     (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) |      \
+                     (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
+
+
+static void
+print_reg_neg_swizzle(GLuint reg)
+{
+   int i;
+
+   if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW &&
+       (reg & REG_NEGATE_MASK) == 0)
+      return;
+
+   fprintf(stderr, ".");
+
+   for (i = 3; i >= 0; i--) {
+      if (reg & (1 << ((i * 4) + 3)))
+         fprintf(stderr, "-");
+
+      switch ((reg >> (i * 4)) & 0x7) {
+      case 0:
+         fprintf(stderr, "x");
+         break;
+      case 1:
+         fprintf(stderr, "y");
+         break;
+      case 2:
+         fprintf(stderr, "z");
+         break;
+      case 3:
+         fprintf(stderr, "w");
+         break;
+      case 4:
+         fprintf(stderr, "0");
+         break;
+      case 5:
+         fprintf(stderr, "1");
+         break;
+      default:
+         fprintf(stderr, "?");
+         break;
+      }
+   }
+}
+
+
+static void
+print_src_reg(GLuint dword)
+{
+   GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK;
+   GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK;
+   print_reg_type_nr(type, nr);
+   print_reg_neg_swizzle(dword);
+}
+
+void
+i915_print_ureg(const char *msg, GLuint ureg)
+{
+   fprintf(stderr, "%s: ", msg);
+   print_src_reg(ureg >> 8);
+   fprintf(stderr, "\n");
+}
+
+static void
+print_dest_reg(GLuint dword)
+{
+   GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK;
+   GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK;
+   print_reg_type_nr(type, nr);
+   if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL)
+      return;
+   fprintf(stderr, ".");
+   if (dword & A0_DEST_CHANNEL_X)
+      fprintf(stderr, "x");
+   if (dword & A0_DEST_CHANNEL_Y)
+      fprintf(stderr, "y");
+   if (dword & A0_DEST_CHANNEL_Z)
+      fprintf(stderr, "z");
+   if (dword & A0_DEST_CHANNEL_W)
+      fprintf(stderr, "w");
+}
+
+
+#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT))
+#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT))
+#define GET_SRC2_REG(r)      (r)
+
+
+static void
+print_arith_op(GLuint opcode, const GLuint * program)
+{
+   if (opcode != A0_NOP) {
+      print_dest_reg(program[0]);
+      if (program[0] & A0_DEST_SATURATE)
+         fprintf(stderr, " = SATURATE ");
+      else
+         fprintf(stderr, " = ");
+   }
+
+   fprintf(stderr, "%s ", opcodes[opcode]);
+
+   print_src_reg(GET_SRC0_REG(program[0], program[1]));
+   if (args[opcode] == 1) {
+      fprintf(stderr, "\n");
+      return;
+   }
+
+   fprintf(stderr, ", ");
+   print_src_reg(GET_SRC1_REG(program[1], program[2]));
+   if (args[opcode] == 2) {
+      fprintf(stderr, "\n");
+      return;
+   }
+
+   fprintf(stderr, ", ");
+   print_src_reg(GET_SRC2_REG(program[2]));
+   fprintf(stderr, "\n");
+   return;
+}
+
+
+static void
+print_tex_op(GLuint opcode, const GLuint * program)
+{
+   print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL);
+   fprintf(stderr, " = ");
+
+   fprintf(stderr, "%s ", opcodes[opcode]);
+
+   fprintf(stderr, "S[%d],", program[0] & T0_SAMPLER_NR_MASK);
+
+   print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
+                     REG_TYPE_MASK,
+                     (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
+   fprintf(stderr, "\n");
+}
+
+static void
+print_dcl_op(GLuint opcode, const GLuint * program)
+{
+   fprintf(stderr, "%s ", opcodes[opcode]);
+   print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL);
+   fprintf(stderr, "\n");
+}
+
+
+void
+i915_disassemble_program(const GLuint * program, GLuint sz)
+{
+   GLuint size = program[0] & 0x1ff;
+   GLint i;
+
+   fprintf(stderr, "BEGIN\n");
+
+   if (size + 2 != sz) {
+      fprintf(stderr, "%s: program size mismatch %d/%d\n", __FUNCTION__,
+              size + 2, sz);
+      exit(1);
+   }
+
+   program++;
+   for (i = 1; i < sz; i += 3, program += 3) {
+      GLuint opcode = program[0] & (0x1f << 24);
+
+      if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT)
+         print_arith_op(opcode >> 24, program);
+      else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL)
+         print_tex_op(opcode >> 24, program);
+      else if (opcode == D0_DCL)
+         print_dcl_op(opcode >> 24, program);
+      else
+         fprintf(stderr, "Unknown opcode 0x%x\n", opcode);
+   }
+
+   fprintf(stderr, "END\n\n");
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_fragprog.c b/src/mesa/drivers/dri/i915tex/i915_fragprog.c
new file mode 100644 (file)
index 0000000..2ddcbc4
--- /dev/null
@@ -0,0 +1,1072 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "intel_batchbuffer.h"
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_program.h"
+
+#include "program_instruction.h"
+#include "program.h"
+
+
+
+/* 1, -1/3!, 1/5!, -1/7! */
+static const GLfloat sin_constants[4] = { 1.0,
+   -1.0 / (3 * 2 * 1),
+   1.0 / (5 * 4 * 3 * 2 * 1),
+   -1.0 / (7 * 6 * 5 * 4 * 3 * 2 * 1)
+};
+
+/* 1, -1/2!, 1/4!, -1/6! */
+static const GLfloat cos_constants[4] = { 1.0,
+   -1.0 / (2 * 1),
+   1.0 / (4 * 3 * 2 * 1),
+   -1.0 / (6 * 5 * 4 * 3 * 2 * 1)
+};
+
+/**
+ * Retrieve a ureg for the given source register.  Will emit
+ * constants, apply swizzling and negation as needed.
+ */
+static GLuint
+src_vector(struct i915_fragment_program *p,
+           const struct prog_src_register *source,
+           const struct gl_fragment_program *program)
+{
+   GLuint src;
+
+   switch (source->File) {
+
+      /* Registers:
+       */
+   case PROGRAM_TEMPORARY:
+      if (source->Index >= I915_MAX_TEMPORARY) {
+         i915_program_error(p, "Exceeded max temporary reg");
+         return 0;
+      }
+      src = UREG(REG_TYPE_R, source->Index);
+      break;
+   case PROGRAM_INPUT:
+      switch (source->Index) {
+      case FRAG_ATTRIB_WPOS:
+         src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL);
+         break;
+      case FRAG_ATTRIB_COL0:
+         src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
+         break;
+      case FRAG_ATTRIB_COL1:
+         src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ);
+         src = swizzle(src, X, Y, Z, ONE);
+         break;
+      case FRAG_ATTRIB_FOGC:
+         src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W);
+         src = swizzle(src, W, W, W, W);
+         break;
+      case FRAG_ATTRIB_TEX0:
+      case FRAG_ATTRIB_TEX1:
+      case FRAG_ATTRIB_TEX2:
+      case FRAG_ATTRIB_TEX3:
+      case FRAG_ATTRIB_TEX4:
+      case FRAG_ATTRIB_TEX5:
+      case FRAG_ATTRIB_TEX6:
+      case FRAG_ATTRIB_TEX7:
+         src = i915_emit_decl(p, REG_TYPE_T,
+                              T_TEX0 + (source->Index - FRAG_ATTRIB_TEX0),
+                              D0_CHANNEL_ALL);
+         break;
+
+      default:
+         i915_program_error(p, "Bad source->Index");
+         return 0;
+      }
+      break;
+
+      /* Various paramters and env values.  All emitted to
+       * hardware as program constants.
+       */
+   case PROGRAM_LOCAL_PARAM:
+      src = i915_emit_param4fv(p, program->Base.LocalParams[source->Index]);
+      break;
+
+   case PROGRAM_ENV_PARAM:
+      src =
+         i915_emit_param4fv(p,
+                            p->ctx->FragmentProgram.Parameters[source->
+                                                               Index]);
+      break;
+
+   case PROGRAM_STATE_VAR:
+   case PROGRAM_NAMED_PARAM:
+      src =
+         i915_emit_param4fv(p,
+                            program->Base.Parameters->ParameterValues[source->
+                                                                      Index]);
+      break;
+
+   default:
+      i915_program_error(p, "Bad source->File");
+      return 0;
+   }
+
+   src = swizzle(src,
+                 GET_SWZ(source->Swizzle, 0),
+                 GET_SWZ(source->Swizzle, 1),
+                 GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3));
+
+   if (source->NegateBase)
+      src = negate(src,
+                   GET_BIT(source->NegateBase, 0),
+                   GET_BIT(source->NegateBase, 1),
+                   GET_BIT(source->NegateBase, 2),
+                   GET_BIT(source->NegateBase, 3));
+
+   return src;
+}
+
+
+static GLuint
+get_result_vector(struct i915_fragment_program *p,
+                  const struct prog_instruction *inst)
+{
+   switch (inst->DstReg.File) {
+   case PROGRAM_OUTPUT:
+      switch (inst->DstReg.Index) {
+      case FRAG_RESULT_COLR:
+         return UREG(REG_TYPE_OC, 0);
+      case FRAG_RESULT_DEPR:
+         p->depth_written = 1;
+         return UREG(REG_TYPE_OD, 0);
+      default:
+         i915_program_error(p, "Bad inst->DstReg.Index");
+         return 0;
+      }
+   case PROGRAM_TEMPORARY:
+      return UREG(REG_TYPE_R, inst->DstReg.Index);
+   default:
+      i915_program_error(p, "Bad inst->DstReg.File");
+      return 0;
+   }
+}
+
+static GLuint
+get_result_flags(const struct prog_instruction *inst)
+{
+   GLuint flags = 0;
+
+   if (inst->SaturateMode == SATURATE_ZERO_ONE)
+      flags |= A0_DEST_SATURATE;
+   if (inst->DstReg.WriteMask & WRITEMASK_X)
+      flags |= A0_DEST_CHANNEL_X;
+   if (inst->DstReg.WriteMask & WRITEMASK_Y)
+      flags |= A0_DEST_CHANNEL_Y;
+   if (inst->DstReg.WriteMask & WRITEMASK_Z)
+      flags |= A0_DEST_CHANNEL_Z;
+   if (inst->DstReg.WriteMask & WRITEMASK_W)
+      flags |= A0_DEST_CHANNEL_W;
+
+   return flags;
+}
+
+static GLuint
+translate_tex_src_target(struct i915_fragment_program *p, GLubyte bit)
+{
+   switch (bit) {
+   case TEXTURE_1D_INDEX:
+      return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_2D_INDEX:
+      return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_RECT_INDEX:
+      return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_3D_INDEX:
+      return D0_SAMPLE_TYPE_VOLUME;
+   case TEXTURE_CUBE_INDEX:
+      return D0_SAMPLE_TYPE_CUBE;
+   default:
+      i915_program_error(p, "TexSrcBit");
+      return 0;
+   }
+}
+
+#define EMIT_TEX( OP )                                         \
+do {                                                           \
+   GLuint dim = translate_tex_src_target( p, inst->TexSrcTarget );     \
+   GLuint sampler = i915_emit_decl(p, REG_TYPE_S,              \
+                                 inst->TexSrcUnit, dim);       \
+   GLuint coord = src_vector( p, &inst->SrcReg[0], program);   \
+   /* Texel lookup */                                          \
+                                                               \
+   i915_emit_texld( p,                                         \
+              get_result_vector( p, inst ),                    \
+              get_result_flags( inst ),                        \
+              sampler,                                         \
+              coord,                                           \
+              OP);                                             \
+} while (0)
+
+#define EMIT_ARITH( OP, N )                                            \
+do {                                                                   \
+   i915_emit_arith( p,                                                 \
+              OP,                                                      \
+              get_result_vector( p, inst ),                            \
+              get_result_flags( inst ), 0,                     \
+              (N<1)?0:src_vector( p, &inst->SrcReg[0], program),       \
+              (N<2)?0:src_vector( p, &inst->SrcReg[1], program),       \
+              (N<3)?0:src_vector( p, &inst->SrcReg[2], program));      \
+} while (0)
+
+#define EMIT_1ARG_ARITH( OP ) EMIT_ARITH( OP, 1 )
+#define EMIT_2ARG_ARITH( OP ) EMIT_ARITH( OP, 2 )
+#define EMIT_3ARG_ARITH( OP ) EMIT_ARITH( OP, 3 )
+
+
+/* Possible concerns:
+ *
+ * SIN, COS -- could use another taylor step?
+ * LIT      -- results seem a little different to sw mesa
+ * LOG      -- different to mesa on negative numbers, but this is conformant.
+ * 
+ * Parse failures -- Mesa doesn't currently give a good indication
+ * internally whether a particular program string parsed or not.  This
+ * can lead to confusion -- hopefully we cope with it ok now.
+ *
+ */
+static void
+upload_program(struct i915_fragment_program *p)
+{
+   const struct gl_fragment_program *program =
+      p->ctx->FragmentProgram._Current;
+   const struct prog_instruction *inst = program->Base.Instructions;
+
+/*    _mesa_debug_fp_inst(program->Base.NumInstructions, inst); */
+
+   /* Is this a parse-failed program?  Ensure a valid program is
+    * loaded, as the flagging of an error isn't sufficient to stop
+    * this being uploaded to hardware.
+    */
+   if (inst[0].Opcode == OPCODE_END) {
+      GLuint tmp = i915_get_utemp(p);
+      i915_emit_arith(p,
+                      A0_MOV,
+                      UREG(REG_TYPE_OC, 0),
+                      A0_DEST_CHANNEL_ALL, 0,
+                      swizzle(tmp, ONE, ZERO, ONE, ONE), 0, 0);
+      return;
+   }
+
+   while (1) {
+      GLuint src0, src1, src2, flags;
+      GLuint tmp = 0;
+
+      switch (inst->Opcode) {
+      case OPCODE_ABS:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         i915_emit_arith(p,
+                         A0_MAX,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         src0, negate(src0, 1, 1, 1, 1), 0);
+         break;
+
+      case OPCODE_ADD:
+         EMIT_2ARG_ARITH(A0_ADD);
+         break;
+
+      case OPCODE_CMP:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+         src2 = src_vector(p, &inst->SrcReg[2], program);
+         i915_emit_arith(p, A0_CMP, get_result_vector(p, inst), get_result_flags(inst), 0, src0, src2, src1);   /* NOTE: order of src2, src1 */
+         break;
+
+      case OPCODE_COS:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         tmp = i915_get_utemp(p);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_X, 0,
+                         src0, i915_emit_const1f(p, 1.0 / (M_PI * 2)), 0);
+
+         i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
+
+         /* By choosing different taylor constants, could get rid of this mul:
+          */
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_X, 0,
+                         tmp, i915_emit_const1f(p, (M_PI * 2)), 0);
+
+         /* 
+          * t0.xy = MUL x.xx11, x.x1111  ; x^2, x, 1, 1
+          * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, 1
+          * t0 = MUL t0.xxz1 t0.z111    ; x^6 x^4 x^2 1
+          * result = DP4 t0, cos_constants
+          */
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_XY, 0,
+                         swizzle(tmp, X, X, ONE, ONE),
+                         swizzle(tmp, X, ONE, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_XYZ, 0,
+                         swizzle(tmp, X, Y, X, ONE),
+                         swizzle(tmp, X, X, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_XYZ, 0,
+                         swizzle(tmp, X, X, Z, ONE),
+                         swizzle(tmp, Z, ONE, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_DP4,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(tmp, ONE, Z, Y, X),
+                         i915_emit_const4fv(p, cos_constants), 0);
+
+         break;
+
+      case OPCODE_DP3:
+         EMIT_2ARG_ARITH(A0_DP3);
+         break;
+
+      case OPCODE_DP4:
+         EMIT_2ARG_ARITH(A0_DP4);
+         break;
+
+      case OPCODE_DPH:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+
+         i915_emit_arith(p,
+                         A0_DP4,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, X, Y, Z, ONE), src1, 0);
+         break;
+
+      case OPCODE_DST:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+
+         /* result[0] = 1    * 1;
+          * result[1] = a[1] * b[1];
+          * result[2] = a[2] * 1;
+          * result[3] = 1    * b[3];
+          */
+         i915_emit_arith(p,
+                         A0_MUL,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, ONE, Y, Z, ONE),
+                         swizzle(src1, ONE, Y, ONE, W), 0);
+         break;
+
+      case OPCODE_EX2:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+
+         i915_emit_arith(p,
+                         A0_EXP,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, X, X, X, X), 0, 0);
+         break;
+
+      case OPCODE_FLR:
+         EMIT_1ARG_ARITH(A0_FLR);
+         break;
+
+      case OPCODE_FRC:
+         EMIT_1ARG_ARITH(A0_FRC);
+         break;
+
+      case OPCODE_KIL:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         tmp = i915_get_utemp(p);
+
+         i915_emit_texld(p, tmp, A0_DEST_CHANNEL_ALL,   /* use a dummy dest reg */
+                         0, src0, T0_TEXKILL);
+         break;
+
+      case OPCODE_LG2:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+
+         i915_emit_arith(p,
+                         A0_LOG,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, X, X, X, X), 0, 0);
+         break;
+
+      case OPCODE_LIT:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         tmp = i915_get_utemp(p);
+
+         /* tmp = max( a.xyzw, a.00zw )
+          * XXX: Clamp tmp.w to -128..128
+          * tmp.y = log(tmp.y)
+          * tmp.y = tmp.w * tmp.y
+          * tmp.y = exp(tmp.y)
+          * result = cmp (a.11-x1, a.1x01, a.1xy1 )
+          */
+         i915_emit_arith(p, A0_MAX, tmp, A0_DEST_CHANNEL_ALL, 0,
+                         src0, swizzle(src0, ZERO, ZERO, Z, W), 0);
+
+         i915_emit_arith(p, A0_LOG, tmp, A0_DEST_CHANNEL_Y, 0,
+                         swizzle(tmp, Y, Y, Y, Y), 0, 0);
+
+         i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_Y, 0,
+                         swizzle(tmp, ZERO, Y, ZERO, ZERO),
+                         swizzle(tmp, ZERO, W, ZERO, ZERO), 0);
+
+         i915_emit_arith(p, A0_EXP, tmp, A0_DEST_CHANNEL_Y, 0,
+                         swizzle(tmp, Y, Y, Y, Y), 0, 0);
+
+         i915_emit_arith(p, A0_CMP,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         negate(swizzle(tmp, ONE, ONE, X, ONE), 0, 0, 1, 0),
+                         swizzle(tmp, ONE, X, ZERO, ONE),
+                         swizzle(tmp, ONE, X, Y, ONE));
+
+         break;
+
+      case OPCODE_LRP:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+         src2 = src_vector(p, &inst->SrcReg[2], program);
+         flags = get_result_flags(inst);
+         tmp = i915_get_utemp(p);
+
+         /* b*a + c*(1-a)
+          *
+          * b*a + c - ca 
+          *
+          * tmp = b*a + c, 
+          * result = (-c)*a + tmp 
+          */
+         i915_emit_arith(p, A0_MAD, tmp,
+                         flags & A0_DEST_CHANNEL_ALL, 0, src1, src0, src2);
+
+         i915_emit_arith(p, A0_MAD,
+                         get_result_vector(p, inst),
+                         flags, 0, negate(src2, 1, 1, 1, 1), src0, tmp);
+         break;
+
+      case OPCODE_MAD:
+         EMIT_3ARG_ARITH(A0_MAD);
+         break;
+
+      case OPCODE_MAX:
+         EMIT_2ARG_ARITH(A0_MAX);
+         break;
+
+      case OPCODE_MIN:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+         tmp = i915_get_utemp(p);
+         flags = get_result_flags(inst);
+
+         i915_emit_arith(p,
+                         A0_MAX,
+                         tmp, flags & A0_DEST_CHANNEL_ALL, 0,
+                         negate(src0, 1, 1, 1, 1),
+                         negate(src1, 1, 1, 1, 1), 0);
+
+         i915_emit_arith(p,
+                         A0_MOV,
+                         get_result_vector(p, inst),
+                         flags, 0, negate(tmp, 1, 1, 1, 1), 0, 0);
+         break;
+
+      case OPCODE_MOV:
+         EMIT_1ARG_ARITH(A0_MOV);
+         break;
+
+      case OPCODE_MUL:
+         EMIT_2ARG_ARITH(A0_MUL);
+         break;
+
+      case OPCODE_POW:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+         tmp = i915_get_utemp(p);
+         flags = get_result_flags(inst);
+
+         /* XXX: masking on intermediate values, here and elsewhere.
+          */
+         i915_emit_arith(p,
+                         A0_LOG,
+                         tmp, A0_DEST_CHANNEL_X, 0,
+                         swizzle(src0, X, X, X, X), 0, 0);
+
+         i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_X, 0, tmp, src1, 0);
+
+
+         i915_emit_arith(p,
+                         A0_EXP,
+                         get_result_vector(p, inst),
+                         flags, 0, swizzle(tmp, X, X, X, X), 0, 0);
+
+         break;
+
+      case OPCODE_RCP:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+
+         i915_emit_arith(p,
+                         A0_RCP,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, X, X, X, X), 0, 0);
+         break;
+
+      case OPCODE_RSQ:
+
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+
+         i915_emit_arith(p,
+                         A0_RSQ,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, X, X, X, X), 0, 0);
+         break;
+
+      case OPCODE_SCS:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         tmp = i915_get_utemp(p);
+
+         /* 
+          * t0.xy = MUL x.xx11, x.x1111  ; x^2, x, 1, 1
+          * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x
+          * t1 = MUL t0.xyyw t0.yz11    ; x^7 x^5 x^3 x
+          * scs.x = DP4 t1, sin_constants
+          * t1 = MUL t0.xxz1 t0.z111    ; x^6 x^4 x^2 1
+          * scs.y = DP4 t1, cos_constants
+          */
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_XY, 0,
+                         swizzle(src0, X, X, ONE, ONE),
+                         swizzle(src0, X, ONE, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_ALL, 0,
+                         swizzle(tmp, X, Y, X, Y),
+                         swizzle(tmp, X, X, ONE, ONE), 0);
+
+         if (inst->DstReg.WriteMask & WRITEMASK_Y) {
+            GLuint tmp1;
+
+            if (inst->DstReg.WriteMask & WRITEMASK_X)
+               tmp1 = i915_get_utemp(p);
+            else
+               tmp1 = tmp;
+
+            i915_emit_arith(p,
+                            A0_MUL,
+                            tmp1, A0_DEST_CHANNEL_ALL, 0,
+                            swizzle(tmp, X, Y, Y, W),
+                            swizzle(tmp, X, Z, ONE, ONE), 0);
+
+            i915_emit_arith(p,
+                            A0_DP4,
+                            get_result_vector(p, inst),
+                            A0_DEST_CHANNEL_Y, 0,
+                            swizzle(tmp1, W, Z, Y, X),
+                            i915_emit_const4fv(p, sin_constants), 0);
+         }
+
+         if (inst->DstReg.WriteMask & WRITEMASK_X) {
+            i915_emit_arith(p,
+                            A0_MUL,
+                            tmp, A0_DEST_CHANNEL_XYZ, 0,
+                            swizzle(tmp, X, X, Z, ONE),
+                            swizzle(tmp, Z, ONE, ONE, ONE), 0);
+
+            i915_emit_arith(p,
+                            A0_DP4,
+                            get_result_vector(p, inst),
+                            A0_DEST_CHANNEL_X, 0,
+                            swizzle(tmp, ONE, Z, Y, X),
+                            i915_emit_const4fv(p, cos_constants), 0);
+         }
+         break;
+
+      case OPCODE_SGE:
+         EMIT_2ARG_ARITH(A0_SGE);
+         break;
+
+      case OPCODE_SIN:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         tmp = i915_get_utemp(p);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_X, 0,
+                         src0, i915_emit_const1f(p, 1.0 / (M_PI * 2)), 0);
+
+         i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0);
+
+         /* By choosing different taylor constants, could get rid of this mul:
+          */
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_X, 0,
+                         tmp, i915_emit_const1f(p, (M_PI * 2)), 0);
+
+         /* 
+          * t0.xy = MUL x.xx11, x.x1111  ; x^2, x, 1, 1
+          * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x
+          * t1 = MUL t0.xyyw t0.yz11    ; x^7 x^5 x^3 x
+          * result = DP4 t1.wzyx, sin_constants
+          */
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_XY, 0,
+                         swizzle(tmp, X, X, ONE, ONE),
+                         swizzle(tmp, X, ONE, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_ALL, 0,
+                         swizzle(tmp, X, Y, X, Y),
+                         swizzle(tmp, X, X, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_ALL, 0,
+                         swizzle(tmp, X, Y, Y, W),
+                         swizzle(tmp, X, Z, ONE, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_DP4,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(tmp, W, Z, Y, X),
+                         i915_emit_const4fv(p, sin_constants), 0);
+         break;
+
+      case OPCODE_SLT:
+         EMIT_2ARG_ARITH(A0_SLT);
+         break;
+
+      case OPCODE_SUB:
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+
+         i915_emit_arith(p,
+                         A0_ADD,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         src0, negate(src1, 1, 1, 1, 1), 0);
+         break;
+
+      case OPCODE_SWZ:
+         EMIT_1ARG_ARITH(A0_MOV);       /* extended swizzle handled natively */
+         break;
+
+      case OPCODE_TEX:
+         EMIT_TEX(T0_TEXLD);
+         break;
+
+      case OPCODE_TXB:
+         EMIT_TEX(T0_TEXLDB);
+         break;
+
+      case OPCODE_TXP:
+         EMIT_TEX(T0_TEXLDP);
+         break;
+
+      case OPCODE_XPD:
+         /* Cross product:
+          *      result.x = src0.y * src1.z - src0.z * src1.y;
+          *      result.y = src0.z * src1.x - src0.x * src1.z;
+          *      result.z = src0.x * src1.y - src0.y * src1.x;
+          *      result.w = undef;
+          */
+         src0 = src_vector(p, &inst->SrcReg[0], program);
+         src1 = src_vector(p, &inst->SrcReg[1], program);
+         tmp = i915_get_utemp(p);
+
+         i915_emit_arith(p,
+                         A0_MUL,
+                         tmp, A0_DEST_CHANNEL_ALL, 0,
+                         swizzle(src0, Z, X, Y, ONE),
+                         swizzle(src1, Y, Z, X, ONE), 0);
+
+         i915_emit_arith(p,
+                         A0_MAD,
+                         get_result_vector(p, inst),
+                         get_result_flags(inst), 0,
+                         swizzle(src0, Y, Z, X, ONE),
+                         swizzle(src1, Z, X, Y, ONE),
+                         negate(tmp, 1, 1, 1, 0));
+         break;
+
+      case OPCODE_END:
+         return;
+
+      default:
+         i915_program_error(p, "bad opcode");
+         return;
+      }
+
+      inst++;
+      i915_release_utemps(p);
+   }
+}
+
+/* Rather than trying to intercept and jiggle depth writes during
+ * emit, just move the value into its correct position at the end of
+ * the program:
+ */
+static void
+fixup_depth_write(struct i915_fragment_program *p)
+{
+   if (p->depth_written) {
+      GLuint depth = UREG(REG_TYPE_OD, 0);
+
+      i915_emit_arith(p,
+                      A0_MOV,
+                      depth, A0_DEST_CHANNEL_W, 0,
+                      swizzle(depth, X, Y, Z, Z), 0, 0);
+   }
+}
+
+
+#define FRAG_BIT_TEX(n)  (FRAG_BIT_TEX0 << (n))
+
+
+static void
+check_wpos(struct i915_fragment_program *p)
+{
+   GLuint inputs = p->FragProg.Base.InputsRead;
+   GLint i;
+
+   p->wpos_tex = -1;
+
+   for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) {
+      if (inputs & FRAG_BIT_TEX(i))
+         continue;
+      else if (inputs & FRAG_BIT_WPOS) {
+         p->wpos_tex = i;
+         inputs &= ~FRAG_BIT_WPOS;
+      }
+   }
+
+   if (inputs & FRAG_BIT_WPOS) {
+      i915_program_error(p, "No free texcoord for wpos value");
+   }
+}
+
+
+static void
+translate_program(struct i915_fragment_program *p)
+{
+   struct i915_context *i915 = I915_CONTEXT(p->ctx);
+
+   i915_init_program(i915, p);
+   check_wpos(p);
+   upload_program(p);
+   fixup_depth_write(p);
+   i915_fini_program(p);
+
+   p->translated = 1;
+}
+
+
+static void
+track_params(struct i915_fragment_program *p)
+{
+   GLint i;
+
+   if (p->nr_params)
+      _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters);
+
+   for (i = 0; i < p->nr_params; i++) {
+      GLint reg = p->param[i].reg;
+      COPY_4V(p->constant[reg], p->param[i].values);
+   }
+
+   p->params_uptodate = 1;
+   p->on_hardware = 0;          /* overkill */
+}
+
+
+static void
+i915BindProgram(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+   if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      struct i915_context *i915 = I915_CONTEXT(ctx);
+      struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
+
+      if (i915->current_program == p)
+         return;
+
+      if (i915->current_program) {
+         i915->current_program->on_hardware = 0;
+         i915->current_program->params_uptodate = 0;
+      }
+
+      i915->current_program = p;
+
+      assert(p->on_hardware == 0);
+      assert(p->params_uptodate == 0);
+
+      /* Hack: make sure fog is correctly enabled according to this
+       * fragment program's fog options.
+       */
+      ctx->Driver.Enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                         ctx->FragmentProgram.Enabled);
+   }
+}
+
+static struct gl_program *
+i915NewProgram(GLcontext * ctx, GLenum target, GLuint id)
+{
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB:
+      return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
+                                       target, id);
+
+   case GL_FRAGMENT_PROGRAM_ARB:{
+         struct i915_fragment_program *prog =
+            CALLOC_STRUCT(i915_fragment_program);
+         if (prog) {
+            i915_init_program(I915_CONTEXT(ctx), prog);
+
+            return _mesa_init_fragment_program(ctx, &prog->FragProg,
+                                               target, id);
+         }
+         else
+            return NULL;
+      }
+
+   default:
+      /* Just fallback:
+       */
+      return _mesa_new_program(ctx, target, id);
+   }
+}
+
+static void
+i915DeleteProgram(GLcontext * ctx, struct gl_program *prog)
+{
+   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+      struct i915_context *i915 = I915_CONTEXT(ctx);
+      struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
+
+      if (i915->current_program == p)
+         i915->current_program = 0;
+   }
+
+   _mesa_delete_program(ctx, prog);
+}
+
+
+static GLboolean
+i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
+{
+   if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
+
+      if (!p->translated)
+         translate_program(p);
+
+      return !p->error;
+   }
+   else
+      return GL_TRUE;
+}
+
+static void
+i915ProgramStringNotify(GLcontext * ctx,
+                        GLenum target, struct gl_program *prog)
+{
+   if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
+      p->translated = 0;
+
+      /* Hack: make sure fog is correctly enabled according to this
+       * fragment program's fog options.
+       */
+      ctx->Driver.Enable(ctx, GL_FRAGMENT_PROGRAM_ARB,
+                         ctx->FragmentProgram.Enabled);
+   }
+
+   _tnl_program_string(ctx, target, prog);
+}
+
+
+void
+i915ValidateFragmentProgram(struct i915_context *i915)
+{
+   GLcontext *ctx = &i915->intel.ctx;
+   struct intel_context *intel = intel_context(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+
+   struct i915_fragment_program *p =
+      (struct i915_fragment_program *) ctx->FragmentProgram._Current;
+
+   const GLuint inputsRead = p->FragProg.Base.InputsRead;
+   GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
+   GLuint s2 = S2_TEXCOORD_NONE;
+   int i, offset = 0;
+
+   if (i915->current_program != p) {
+      if (i915->current_program) {
+         i915->current_program->on_hardware = 0;
+         i915->current_program->params_uptodate = 0;
+      }
+
+      i915->current_program = p;
+   }
+
+
+   /* Important:
+    */
+   VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
+
+   if (!p->translated)
+      translate_program(p);
+
+   intel->vertex_attr_count = 0;
+   intel->wpos_offset = 0;
+   intel->wpos_size = 0;
+   intel->coloroffset = 0;
+   intel->specoffset = 0;
+
+   if (inputsRead & FRAG_BITS_TEX_ANY) {
+      EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16);
+   }
+   else {
+      EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12);
+   }
+
+   if (inputsRead & FRAG_BIT_COL0) {
+      intel->coloroffset = offset / 4;
+      EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4);
+   }
+
+   if ((inputsRead & (FRAG_BIT_COL1 | FRAG_BIT_FOGC)) ||
+       i915->vertex_fog != I915_FOG_NONE) {
+
+      if (inputsRead & FRAG_BIT_COL1) {
+         intel->specoffset = offset / 4;
+         EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3);
+      }
+      else
+         EMIT_PAD(3);
+
+      if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE)
+         EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1);
+      else
+         EMIT_PAD(1);
+   }
+
+#if 0
+   if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) {
+      EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4);
+   }
+#endif
+
+   for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) {
+      if (inputsRead & FRAG_BIT_TEX(i)) {
+         int sz = VB->TexCoordPtr[i]->size;
+
+         s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
+         s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
+
+         EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4);
+      }
+      else if (i == p->wpos_tex) {
+
+         /* If WPOS is required, duplicate the XYZ position data in an
+          * unused texture coordinate:
+          */
+         s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
+         s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(3));
+
+         intel->wpos_offset = offset;
+         intel->wpos_size = 3 * sizeof(GLuint);
+
+         EMIT_PAD(intel->wpos_size);
+      }
+   }
+
+   if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
+       s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
+      int k;
+
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+
+      /* Must do this *after* statechange, so as not to affect
+       * buffered vertices reliant on the old state:
+       */
+      intel->vertex_size = _tnl_install_attrs(&intel->ctx,
+                                              intel->vertex_attrs,
+                                              intel->vertex_attr_count,
+                                              intel->ViewportMatrix.m, 0);
+
+      intel->vertex_size >>= 2;
+
+      i915->state.Ctx[I915_CTXREG_LIS2] = s2;
+      i915->state.Ctx[I915_CTXREG_LIS4] = s4;
+
+      k = intel->vtbl.check_vertex_size(intel, intel->vertex_size);
+      assert(k);
+   }
+
+   if (!p->params_uptodate)
+      track_params(p);
+
+   if (!p->on_hardware)
+      i915_upload_program(i915, p);
+}
+
+void
+i915InitFragProgFuncs(struct dd_function_table *functions)
+{
+   functions->BindProgram = i915BindProgram;
+   functions->NewProgram = i915NewProgram;
+   functions->DeleteProgram = i915DeleteProgram;
+   functions->IsProgramNative = i915IsProgramNative;
+   functions->ProgramStringNotify = i915ProgramStringNotify;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_metaops.c b/src/mesa/drivers/dri/i915tex/i915_metaops.c
new file mode 100644 (file)
index 0000000..3ab62bc
--- /dev/null
@@ -0,0 +1,509 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "utils.h"
+
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+#include "intel_ioctl.h"
+#include "intel_regions.h"
+#include "intel_rotate.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+/* We touch almost everything:
+ */
+#define ACTIVE (I915_UPLOAD_INVARIENT |        \
+               I915_UPLOAD_CTX |               \
+               I915_UPLOAD_BUFFERS |           \
+               I915_UPLOAD_STIPPLE |           \
+                I915_UPLOAD_PROGRAM |          \
+                I915_UPLOAD_FOG |              \
+               I915_UPLOAD_TEX(0))
+
+#define SET_STATE( i915, STATE )               \
+do {                                           \
+   i915->current->emitted &= ~ACTIVE;          \
+   i915->current = &i915->STATE;               \
+   i915->current->emitted &= ~ACTIVE;          \
+} while (0)
+
+
+static void
+meta_no_stencil_write(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
+                                         S5_STENCIL_WRITE_ENABLE);
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+static void
+meta_no_depth_write(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
+                                         S6_DEPTH_WRITE_ENABLE);
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+static void
+meta_depth_replace(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE )
+    * ctx->Driver.DepthMask( ctx, GL_TRUE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS6] |= (S6_DEPTH_TEST_ENABLE |
+                                        S6_DEPTH_WRITE_ENABLE);
+
+   /* ctx->Driver.DepthFunc( ctx, GL_REPLACE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
+   i915->meta.Ctx[I915_CTXREG_LIS6] |=
+      COMPAREFUNC_ALWAYS << S6_DEPTH_TEST_FUNC_SHIFT;
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+
+/* Set stencil unit to replace always with the reference value.
+ */
+static void
+meta_stencil_replace(struct intel_context *intel,
+                     GLuint s_mask, GLuint s_clear)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   GLuint op = STENCILOP_REPLACE;
+   GLuint func = COMPAREFUNC_ALWAYS;
+
+   /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
+                                        S5_STENCIL_WRITE_ENABLE);
+
+   /* ctx->Driver.StencilMask( ctx, s_mask )
+    */
+   i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
+
+   i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
+                                          STENCIL_WRITE_MASK(s_mask));
+
+   /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
+                                         S5_STENCIL_PASS_Z_FAIL_MASK |
+                                         S5_STENCIL_PASS_Z_PASS_MASK);
+
+   i915->meta.Ctx[I915_CTXREG_LIS5] |= ((op << S5_STENCIL_FAIL_SHIFT) |
+                                        (op << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
+                                        (op << S5_STENCIL_PASS_Z_PASS_SHIFT));
+
+
+   /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_ref, ~0 )
+    */
+   i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+   i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
+                                          STENCIL_TEST_MASK(0xff));
+
+   i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
+                                         S5_STENCIL_TEST_FUNC_MASK);
+
+   i915->meta.Ctx[I915_CTXREG_LIS5] |= ((s_clear << S5_STENCIL_REF_SHIFT) |
+                                        (func << S5_STENCIL_TEST_FUNC_SHIFT));
+
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+
+static void
+meta_color_mask(struct intel_context *intel, GLboolean state)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   const GLuint mask = (S5_WRITEDISABLE_RED |
+                        S5_WRITEDISABLE_GREEN |
+                        S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA);
+
+   /* Copy colormask state from "regular" hw context.
+    */
+   if (state) {
+      i915->meta.Ctx[I915_CTXREG_LIS5] &= ~mask;
+      i915->meta.Ctx[I915_CTXREG_LIS5] |=
+         (i915->state.Ctx[I915_CTXREG_LIS5] & mask);
+   }
+   else
+      i915->meta.Ctx[I915_CTXREG_LIS5] |= mask;
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+
+
+static void
+meta_import_pixel_state(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   memcpy(i915->meta.Fog, i915->state.Fog, I915_FOG_SETUP_SIZE * 4);
+
+   i915->meta.Ctx[I915_CTXREG_LIS5] = i915->state.Ctx[I915_CTXREG_LIS5];
+   i915->meta.Ctx[I915_CTXREG_LIS6] = i915->state.Ctx[I915_CTXREG_LIS6];
+   i915->meta.Ctx[I915_CTXREG_STATE4] = i915->state.Ctx[I915_CTXREG_STATE4];
+   i915->meta.Ctx[I915_CTXREG_BLENDCOLOR1] =
+      i915->state.Ctx[I915_CTXREG_BLENDCOLOR1];
+   i915->meta.Ctx[I915_CTXREG_IAB] = i915->state.Ctx[I915_CTXREG_IAB];
+
+   i915->meta.Buffer[I915_DESTREG_SENABLE] =
+      i915->state.Buffer[I915_DESTREG_SENABLE];
+   i915->meta.Buffer[I915_DESTREG_SR1] = i915->state.Buffer[I915_DESTREG_SR1];
+   i915->meta.Buffer[I915_DESTREG_SR2] = i915->state.Buffer[I915_DESTREG_SR2];
+
+   i915->meta.emitted &= ~I915_UPLOAD_FOG;
+   i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+
+
+
+#define REG( type, nr ) (((type)<<5)|(nr))
+
+#define REG_R(x)       REG(REG_TYPE_R, x)
+#define REG_T(x)       REG(REG_TYPE_T, x)
+#define REG_CONST(x)   REG(REG_TYPE_CONST, x)
+#define REG_S(x)       REG(REG_TYPE_S, x)
+#define REG_OC         REG(REG_TYPE_OC, 0)
+#define REG_OD        REG(REG_TYPE_OD, 0)
+#define REG_U(x)       REG(REG_TYPE_U, x)
+
+#define REG_T_DIFFUSE  REG(REG_TYPE_T, T_DIFFUSE)
+#define REG_T_SPECULAR REG(REG_TYPE_T, T_SPECULAR)
+#define REG_T_FOG_W    REG(REG_TYPE_T, T_FOG_W)
+#define REG_T_TEX(x)   REG(REG_TYPE_T, x)
+
+
+#define A0_DEST_REG( reg ) ( (reg) << A0_DEST_NR_SHIFT )
+#define A0_SRC0_REG( reg ) ( (reg) << A0_SRC0_NR_SHIFT )
+#define A1_SRC1_REG( reg ) ( (reg) << A1_SRC1_NR_SHIFT )
+#define A1_SRC2_REG( reg ) ( (reg) << A1_SRC2_NR_SHIFT )
+#define A2_SRC2_REG( reg ) ( (reg) << A2_SRC2_NR_SHIFT )
+#define D0_DECL_REG( reg ) ( (reg) << D0_NR_SHIFT )
+#define T0_DEST_REG( reg ) ( (reg) << T0_DEST_NR_SHIFT )
+
+#define T0_SAMPLER( unit )     ((unit)<<T0_SAMPLER_NR_SHIFT)
+
+#define T1_ADDRESS_REG( type, nr ) (((type)<<T1_ADDRESS_REG_TYPE_SHIFT)| \
+                                   ((nr)<<T1_ADDRESS_REG_NR_SHIFT))
+
+
+#define A1_SRC0_XYZW ((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) |     \
+                     (SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) |      \
+                     (SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) |      \
+                     (SRC_W << A1_SRC0_CHANNEL_W_SHIFT))
+
+#define A1_SRC1_XY   ((SRC_X << A1_SRC1_CHANNEL_X_SHIFT) |     \
+                     (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT))
+
+#define A2_SRC1_ZW   ((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) |     \
+                     (SRC_W << A2_SRC1_CHANNEL_W_SHIFT))
+
+#define A2_SRC2_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) |     \
+                     (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) |      \
+                     (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) |      \
+                     (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
+
+
+
+
+
+static void
+meta_no_texture(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   static const GLuint prog[] = {
+      _3DSTATE_PIXEL_SHADER_PROGRAM,
+
+      /* Declare incoming diffuse color:
+       */
+      (D0_DCL | D0_DECL_REG(REG_T_DIFFUSE) | D0_CHANNEL_ALL),
+      D1_MBZ,
+      D2_MBZ,
+
+      /* output-color = mov(t_diffuse)
+       */
+      (A0_MOV |
+       A0_DEST_REG(REG_OC) |
+       A0_DEST_CHANNEL_ALL | A0_SRC0_REG(REG_T_DIFFUSE)),
+      (A1_SRC0_XYZW),
+      0,
+   };
+
+
+   memcpy(i915->meta.Program, prog, sizeof(prog));
+   i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
+   i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
+   i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
+}
+
+static void
+meta_texture_blend_replace(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   static const GLuint prog[] = {
+      _3DSTATE_PIXEL_SHADER_PROGRAM,
+
+      /* Declare the sampler:
+       */
+      (D0_DCL | D0_DECL_REG(REG_S(0)) | D0_SAMPLE_TYPE_2D | D0_CHANNEL_NONE),
+      D1_MBZ,
+      D2_MBZ,
+
+      /* Declare the interpolated texture coordinate:
+       */
+      (D0_DCL | D0_DECL_REG(REG_T_TEX(0)) | D0_CHANNEL_ALL),
+      D1_MBZ,
+      D2_MBZ,
+
+      /* output-color = texld(sample0, texcoord0) 
+       */
+      (T0_TEXLD | T0_DEST_REG(REG_OC) | T0_SAMPLER(0)),
+      T1_ADDRESS_REG(REG_TYPE_T, 0),
+      T2_MBZ
+   };
+
+   memcpy(i915->meta.Program, prog, sizeof(prog));
+   i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
+   i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
+   i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
+}
+
+
+
+
+
+/* Set up an arbitary piece of memory as a rectangular texture
+ * (including the front or back buffer).
+ */
+static GLboolean
+meta_tex_rect_source(struct intel_context *intel,
+                     struct _DriBufferObject *buffer,
+                     GLuint offset,
+                     GLuint pitch, GLuint height, GLenum format, GLenum type)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   GLuint unit = 0;
+   GLint numLevels = 1;
+   GLuint *state = i915->meta.Tex[0];
+   GLuint textureFormat;
+   GLuint cpp;
+
+   /* A full implementation of this would do the upload through
+    * glTexImage2d, and get all the conversion operations at that
+    * point.  We are restricted, but still at least have access to the
+    * fragment program swizzle.
+    */
+   switch (format) {
+   case GL_BGRA:
+      switch (type) {
+      case GL_UNSIGNED_INT_8_8_8_8_REV:
+      case GL_UNSIGNED_BYTE:
+         textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
+         cpp = 4;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+   case GL_RGBA:
+      switch (type) {
+      case GL_UNSIGNED_INT_8_8_8_8_REV:
+      case GL_UNSIGNED_BYTE:
+         textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
+         cpp = 4;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+   case GL_BGR:
+      switch (type) {
+      case GL_UNSIGNED_SHORT_5_6_5_REV:
+         textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
+         cpp = 2;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+   case GL_RGB:
+      switch (type) {
+      case GL_UNSIGNED_SHORT_5_6_5:
+         textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
+         cpp = 2;
+         break;
+      default:
+         return GL_FALSE;
+      }
+      break;
+
+   default:
+      return GL_FALSE;
+   }
+
+
+   if ((pitch * cpp) & 3) {
+      _mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+/*    intel_region_release(&i915->meta.tex_region[0]); */
+/*    intel_region_reference(&i915->meta.tex_region[0], region); */
+   i915->meta.tex_buffer[0] = buffer;
+   i915->meta.tex_offset[0] = offset;
+
+   state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
+                             ((pitch - 1) << MS3_WIDTH_SHIFT) |
+                             textureFormat | MS3_USE_FENCE_REGS);
+
+   state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) |
+                             MS4_CUBE_FACE_ENA_MASK |
+                             ((((numLevels - 1) * 4)) << MS4_MAX_LOD_SHIFT));
+
+   state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
+                             (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
+                             (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
+
+   state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) |
+                             (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
+                             (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
+                             (unit << SS3_TEXTUREMAP_INDEX_SHIFT));
+
+   state[I915_TEXREG_SS4] = 0;
+
+   i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
+   return GL_TRUE;
+}
+
+
+/**
+ * Set the color and depth drawing region for meta ops.
+ */
+static void
+meta_draw_region(struct intel_context *intel,
+                 struct intel_region *color_region,
+                 struct intel_region *depth_region)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   i915_state_draw_region(intel, &i915->meta, color_region, depth_region);
+}
+
+
+static void
+set_vertex_format(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   i915->meta.Ctx[I915_CTXREG_LIS2] =
+      (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
+       S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
+       S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
+       S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
+       S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
+       S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
+       S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
+       S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
+
+   i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK;
+
+   i915->meta.Ctx[I915_CTXREG_LIS4] |= (S4_VFMT_COLOR | S4_VFMT_XYZ);
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+}
+
+
+
+/* Operations where the 3D engine is decoupled temporarily from the
+ * current GL state and used for other purposes than simply rendering
+ * incoming triangles.
+ */
+static void
+install_meta_state(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   memcpy(&i915->meta, &i915->initial, sizeof(i915->meta));
+   i915->meta.active = ACTIVE;
+   i915->meta.emitted = 0;
+
+   SET_STATE(i915, meta);
+   set_vertex_format(intel);
+   meta_no_texture(intel);
+}
+
+static void
+leave_meta_state(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   intel_region_release(&i915->meta.draw_region);
+   intel_region_release(&i915->meta.depth_region);
+/*    intel_region_release(&i915->meta.tex_region[0]); */
+   SET_STATE(i915, state);
+}
+
+
+
+void
+i915InitMetaFuncs(struct i915_context *i915)
+{
+   i915->intel.vtbl.install_meta_state = install_meta_state;
+   i915->intel.vtbl.leave_meta_state = leave_meta_state;
+   i915->intel.vtbl.meta_no_depth_write = meta_no_depth_write;
+   i915->intel.vtbl.meta_no_stencil_write = meta_no_stencil_write;
+   i915->intel.vtbl.meta_stencil_replace = meta_stencil_replace;
+   i915->intel.vtbl.meta_depth_replace = meta_depth_replace;
+   i915->intel.vtbl.meta_color_mask = meta_color_mask;
+   i915->intel.vtbl.meta_no_texture = meta_no_texture;
+   i915->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace;
+   i915->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source;
+   i915->intel.vtbl.meta_draw_region = meta_draw_region;
+   i915->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_program.c b/src/mesa/drivers/dri/i915tex/i915_program.c
new file mode 100644 (file)
index 0000000..4fb5622
--- /dev/null
@@ -0,0 +1,518 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include <strings.h>
+
+#include "glheader.h"
+#include "macros.h"
+#include "enums.h"
+
+#include "tnl/t_context.h"
+#include "intel_batchbuffer.h"
+
+#include "i915_reg.h"
+#include "i915_context.h"
+#include "i915_program.h"
+
+
+#define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define T0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
+#define A0_SRC0( reg ) (((reg)&UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT)
+#define A1_SRC0( reg ) (((reg)&UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT)
+#define A1_SRC1( reg ) (((reg)&UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT)
+#define A2_SRC1( reg ) (((reg)&UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT)
+#define A2_SRC2( reg ) (((reg)&UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT)
+
+/* These are special, and don't have swizzle/negate bits.
+ */
+#define T0_SAMPLER( reg )     (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT)
+#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \
+                              (GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT))
+
+
+/* Macros for translating UREG's into the various register fields used
+ * by the I915 programmable unit.
+ */
+#define UREG_A0_DEST_SHIFT_LEFT  (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT)
+#define UREG_A0_SRC0_SHIFT_LEFT  (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT)
+#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
+#define UREG_A1_SRC1_SHIFT_LEFT  (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT)
+#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
+#define UREG_A2_SRC2_SHIFT_LEFT  (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT)
+
+#define UREG_MASK         0xffffff00
+#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \
+                          (REG_NR_MASK << UREG_NR_SHIFT))
+
+
+#define I915_CONSTFLAG_PARAM 0x1f
+
+GLuint
+i915_get_temp(struct i915_fragment_program *p)
+{
+   int bit = ffs(~p->temp_flag);
+   if (!bit) {
+      fprintf(stderr, "%s: out of temporaries\n", __FILE__);
+      exit(1);
+   }
+
+   p->temp_flag |= 1 << (bit - 1);
+   return UREG(REG_TYPE_R, (bit - 1));
+}
+
+
+GLuint
+i915_get_utemp(struct i915_fragment_program * p)
+{
+   int bit = ffs(~p->utemp_flag);
+   if (!bit) {
+      fprintf(stderr, "%s: out of temporaries\n", __FILE__);
+      exit(1);
+   }
+
+   p->utemp_flag |= 1 << (bit - 1);
+   return UREG(REG_TYPE_U, (bit - 1));
+}
+
+void
+i915_release_utemps(struct i915_fragment_program *p)
+{
+   p->utemp_flag = ~0x7;
+}
+
+
+GLuint
+i915_emit_decl(struct i915_fragment_program *p,
+               GLuint type, GLuint nr, GLuint d0_flags)
+{
+   GLuint reg = UREG(type, nr);
+
+   if (type == REG_TYPE_T) {
+      if (p->decl_t & (1 << nr))
+         return reg;
+
+      p->decl_t |= (1 << nr);
+   }
+   else if (type == REG_TYPE_S) {
+      if (p->decl_s & (1 << nr))
+         return reg;
+
+      p->decl_s |= (1 << nr);
+   }
+   else
+      return reg;
+
+   *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags);
+   *(p->decl++) = D1_MBZ;
+   *(p->decl++) = D2_MBZ;
+
+   p->nr_decl_insn++;
+   return reg;
+}
+
+GLuint
+i915_emit_arith(struct i915_fragment_program * p,
+                GLuint op,
+                GLuint dest,
+                GLuint mask,
+                GLuint saturate, GLuint src0, GLuint src1, GLuint src2)
+{
+   GLuint c[3];
+   GLuint nr_const = 0;
+
+   assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
+   dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
+   assert(dest);
+
+   if (GET_UREG_TYPE(src0) == REG_TYPE_CONST)
+      c[nr_const++] = 0;
+   if (GET_UREG_TYPE(src1) == REG_TYPE_CONST)
+      c[nr_const++] = 1;
+   if (GET_UREG_TYPE(src2) == REG_TYPE_CONST)
+      c[nr_const++] = 2;
+
+   /* Recursively call this function to MOV additional const values
+    * into temporary registers.  Use utemp registers for this -
+    * currently shouldn't be possible to run out, but keep an eye on
+    * this.
+    */
+   if (nr_const > 1) {
+      GLuint s[3], first, i, old_utemp_flag;
+
+      s[0] = src0;
+      s[1] = src1;
+      s[2] = src2;
+      old_utemp_flag = p->utemp_flag;
+
+      first = GET_UREG_NR(s[c[0]]);
+      for (i = 1; i < nr_const; i++) {
+         if (GET_UREG_NR(s[c[i]]) != first) {
+            GLuint tmp = i915_get_utemp(p);
+
+            i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0,
+                            s[c[i]], 0, 0);
+            s[c[i]] = tmp;
+         }
+      }
+
+      src0 = s[0];
+      src1 = s[1];
+      src2 = s[2];
+      p->utemp_flag = old_utemp_flag;   /* restore */
+   }
+
+   *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
+   *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1));
+   *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2));
+
+   p->nr_alu_insn++;
+   return dest;
+}
+
+GLuint i915_emit_texld( struct i915_fragment_program *p,
+                       GLuint dest,
+                       GLuint destmask,
+                       GLuint sampler,
+                       GLuint coord,
+                       GLuint op )
+{
+   if (coord != UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord))) {
+      /* No real way to work around this in the general case - need to
+       * allocate and declare a new temporary register (a utemp won't
+       * do).  Will fallback for now.
+       */
+      i915_program_error(p, "Can't (yet) swizzle TEX arguments");
+      return 0;
+   }
+
+   /* Don't worry about saturate as we only support  
+    */
+   if (destmask != A0_DEST_CHANNEL_ALL) {
+      GLuint tmp = i915_get_utemp(p);
+      i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op );
+      i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 );
+      return dest;
+   }
+   else {
+      assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
+      assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
+
+      if (GET_UREG_TYPE(coord) != REG_TYPE_T) {
+        p->nr_tex_indirect++;
+      }
+
+      *(p->csr++) = (op | 
+                    T0_DEST( dest ) |
+                    T0_SAMPLER( sampler ));
+
+      *(p->csr++) = T1_ADDRESS_REG( coord );
+      *(p->csr++) = T2_MBZ;
+
+      p->nr_tex_insn++;
+      return dest;
+   }
+}
+
+
+GLuint
+i915_emit_const1f(struct i915_fragment_program * p, GLfloat c0)
+{
+   GLint reg, idx;
+
+   if (c0 == 0.0)
+      return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO);
+   if (c0 == 1.0)
+      return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE);
+
+   for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+      if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
+         continue;
+      for (idx = 0; idx < 4; idx++) {
+         if (!(p->constant_flags[reg] & (1 << idx)) ||
+             p->constant[reg][idx] == c0) {
+            p->constant[reg][idx] = c0;
+            p->constant_flags[reg] |= 1 << idx;
+            if (reg + 1 > p->nr_constants)
+               p->nr_constants = reg + 1;
+            return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE);
+         }
+      }
+   }
+
+   fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
+   p->error = 1;
+   return 0;
+}
+
+GLuint
+i915_emit_const2f(struct i915_fragment_program * p, GLfloat c0, GLfloat c1)
+{
+   GLint reg, idx;
+
+   if (c0 == 0.0)
+      return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W);
+   if (c0 == 1.0)
+      return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W);
+
+   if (c1 == 0.0)
+      return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W);
+   if (c1 == 1.0)
+      return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W);
+
+   for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+      if (p->constant_flags[reg] == 0xf ||
+          p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
+         continue;
+      for (idx = 0; idx < 3; idx++) {
+         if (!(p->constant_flags[reg] & (3 << idx))) {
+            p->constant[reg][idx] = c0;
+            p->constant[reg][idx + 1] = c1;
+            p->constant_flags[reg] |= 3 << idx;
+            if (reg + 1 > p->nr_constants)
+               p->nr_constants = reg + 1;
+            return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO,
+                           ONE);
+         }
+      }
+   }
+
+   fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
+   p->error = 1;
+   return 0;
+}
+
+
+
+GLuint
+i915_emit_const4f(struct i915_fragment_program * p,
+                  GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3)
+{
+   GLint reg;
+
+   for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+      if (p->constant_flags[reg] == 0xf &&
+          p->constant[reg][0] == c0 &&
+          p->constant[reg][1] == c1 &&
+          p->constant[reg][2] == c2 && p->constant[reg][3] == c3) {
+         return UREG(REG_TYPE_CONST, reg);
+      }
+      else if (p->constant_flags[reg] == 0) {
+         p->constant[reg][0] = c0;
+         p->constant[reg][1] = c1;
+         p->constant[reg][2] = c2;
+         p->constant[reg][3] = c3;
+         p->constant_flags[reg] = 0xf;
+         if (reg + 1 > p->nr_constants)
+            p->nr_constants = reg + 1;
+         return UREG(REG_TYPE_CONST, reg);
+      }
+   }
+
+   fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
+   p->error = 1;
+   return 0;
+}
+
+
+GLuint
+i915_emit_const4fv(struct i915_fragment_program * p, const GLfloat * c)
+{
+   return i915_emit_const4f(p, c[0], c[1], c[2], c[3]);
+}
+
+
+GLuint
+i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values)
+{
+   GLint reg, i;
+
+   for (i = 0; i < p->nr_params; i++) {
+      if (p->param[i].values == values)
+         return UREG(REG_TYPE_CONST, p->param[i].reg);
+   }
+
+
+   for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
+      if (p->constant_flags[reg] == 0) {
+         p->constant_flags[reg] = I915_CONSTFLAG_PARAM;
+         i = p->nr_params++;
+
+         p->param[i].values = values;
+         p->param[i].reg = reg;
+         p->params_uptodate = 0;
+
+         if (reg + 1 > p->nr_constants)
+            p->nr_constants = reg + 1;
+         return UREG(REG_TYPE_CONST, reg);
+      }
+   }
+
+   fprintf(stderr, "%s: out of constants\n", __FUNCTION__);
+   p->error = 1;
+   return 0;
+}
+
+
+
+
+void
+i915_program_error(struct i915_fragment_program *p, const char *msg)
+{
+   /* XXX we shouldn't print anything to stdout, record GL error or
+    * call _mesa_problem()
+    */
+   fprintf(stderr, "%s\n", msg);
+   p->error = 1;
+}
+
+void
+i915_init_program(struct i915_context *i915, struct i915_fragment_program *p)
+{
+   GLcontext *ctx = &i915->intel.ctx;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   p->translated = 0;
+   p->params_uptodate = 0;
+   p->on_hardware = 0;
+   p->error = 0;
+
+   p->nr_tex_indirect = 1;      /* correct? */
+   p->nr_tex_insn = 0;
+   p->nr_alu_insn = 0;
+   p->nr_decl_insn = 0;
+
+   p->ctx = ctx;
+   memset(p->constant_flags, 0, sizeof(p->constant_flags));
+
+   p->nr_constants = 0;
+   p->csr = p->program;
+   p->decl = p->declarations;
+   p->decl_s = 0;
+   p->decl_t = 0;
+   p->temp_flag = 0xffff000;
+   p->utemp_flag = ~0x7;
+   p->wpos_tex = -1;
+   p->depth_written = 0;
+   p->nr_params = 0;
+
+   p->src_texture = UREG_BAD;
+   p->src_previous = UREG(REG_TYPE_T, T_DIFFUSE);
+   p->last_tex_stage = 0;
+   p->VB = &tnl->vb;
+
+   *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM;
+}
+
+
+void
+i915_fini_program(struct i915_fragment_program *p)
+{
+   GLuint program_size = p->csr - p->program;
+   GLuint decl_size = p->decl - p->declarations;
+
+   if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT)
+      i915_program_error(p, "Exceeded max nr indirect texture lookups");
+
+   if (p->nr_tex_insn > I915_MAX_TEX_INSN)
+      i915_program_error(p, "Exceeded max TEX instructions");
+
+   if (p->nr_alu_insn > I915_MAX_ALU_INSN)
+      i915_program_error(p, "Exceeded max ALU instructions");
+
+   if (p->nr_decl_insn > I915_MAX_DECL_INSN)
+      i915_program_error(p, "Exceeded max DECL instructions");
+
+   if (p->error) {
+      p->FragProg.Base.NumNativeInstructions = 0;
+      p->FragProg.NumNativeAluInstructions = 0;
+      p->FragProg.NumNativeTexInstructions = 0;
+      p->FragProg.NumNativeTexIndirections = 0;
+   }
+   else {
+      p->FragProg.Base.NumNativeInstructions = (p->nr_alu_insn +
+                                                p->nr_tex_insn +
+                                                p->nr_decl_insn);
+      p->FragProg.NumNativeAluInstructions = p->nr_alu_insn;
+      p->FragProg.NumNativeTexInstructions = p->nr_tex_insn;
+      p->FragProg.NumNativeTexIndirections = p->nr_tex_indirect;
+   }
+
+   p->declarations[0] |= program_size + decl_size - 2;
+}
+
+void
+i915_upload_program(struct i915_context *i915,
+                    struct i915_fragment_program *p)
+{
+   GLuint program_size = p->csr - p->program;
+   GLuint decl_size = p->decl - p->declarations;
+
+   FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, p->error);
+
+   /* Could just go straight to the batchbuffer from here:
+    */
+   if (i915->state.ProgramSize != (program_size + decl_size) ||
+       memcmp(i915->state.Program + decl_size, p->program,
+              program_size * sizeof(int)) != 0) {
+      I915_STATECHANGE(i915, I915_UPLOAD_PROGRAM);
+      memcpy(i915->state.Program, p->declarations, decl_size * sizeof(int));
+      memcpy(i915->state.Program + decl_size, p->program,
+             program_size * sizeof(int));
+      i915->state.ProgramSize = decl_size + program_size;
+   }
+
+   /* Always seemed to get a failure if I used memcmp() to
+    * shortcircuit this state upload.  Needs further investigation?
+    */
+   if (p->nr_constants) {
+      GLuint nr = p->nr_constants;
+
+      I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1);
+      I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS);
+
+      i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4);
+      i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1);
+
+      memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr));
+      i915->state.ConstantSize = 2 + (nr) * 4;
+
+      if (0) {
+         GLuint i;
+         for (i = 0; i < nr; i++) {
+            fprintf(stderr, "const[%d]: %f %f %f %f\n", i,
+                    p->constant[i][0],
+                    p->constant[i][1], p->constant[i][2], p->constant[i][3]);
+         }
+      }
+   }
+   else {
+      I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0);
+   }
+
+   p->on_hardware = 1;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_program.h b/src/mesa/drivers/dri/i915tex/i915_program.h
new file mode 100644 (file)
index 0000000..3c12b34
--- /dev/null
@@ -0,0 +1,160 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef I915_PROGRAM_H
+#define I915_PROGRAM_H
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+
+
+/* Having zero and one in here makes the definition of swizzle a lot
+ * easier.
+ */
+#define UREG_TYPE_SHIFT               29
+#define UREG_NR_SHIFT                 24
+#define UREG_CHANNEL_X_NEGATE_SHIFT   23
+#define UREG_CHANNEL_X_SHIFT          20
+#define UREG_CHANNEL_Y_NEGATE_SHIFT   19
+#define UREG_CHANNEL_Y_SHIFT          16
+#define UREG_CHANNEL_Z_NEGATE_SHIFT   15
+#define UREG_CHANNEL_Z_SHIFT          12
+#define UREG_CHANNEL_W_NEGATE_SHIFT   11
+#define UREG_CHANNEL_W_SHIFT          8
+#define UREG_CHANNEL_ZERO_NEGATE_MBZ  5
+#define UREG_CHANNEL_ZERO_SHIFT       4
+#define UREG_CHANNEL_ONE_NEGATE_MBZ   1
+#define UREG_CHANNEL_ONE_SHIFT        0
+
+#define UREG_BAD          0xffffffff    /* not a valid ureg */
+
+#define X    SRC_X
+#define Y    SRC_Y
+#define Z    SRC_Z
+#define W    SRC_W
+#define ZERO SRC_ZERO
+#define ONE  SRC_ONE
+
+/* Construct a ureg:
+ */
+#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) |         \
+                         ((nr)  << UREG_NR_SHIFT) |            \
+                         (X     << UREG_CHANNEL_X_SHIFT) |     \
+                         (Y     << UREG_CHANNEL_Y_SHIFT) |     \
+                         (Z     << UREG_CHANNEL_Z_SHIFT) |     \
+                         (W     << UREG_CHANNEL_W_SHIFT) |     \
+                         (ZERO  << UREG_CHANNEL_ZERO_SHIFT) |  \
+                         (ONE   << UREG_CHANNEL_ONE_SHIFT))
+
+#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20))
+#define CHANNEL_SRC( src, channel ) (src>>(channel*4))
+
+#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)&REG_TYPE_MASK)
+#define GET_UREG_NR(reg)   (((reg)>>UREG_NR_SHIFT)&REG_NR_MASK)
+
+
+
+#define UREG_XYZW_CHANNEL_MASK 0x00ffff00
+
+/* One neat thing about the UREG representation:  
+ */
+static INLINE int
+swizzle(int reg, int x, int y, int z, int w)
+{
+   return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
+           CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) |
+           CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) |
+           CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) |
+           CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3));
+}
+
+/* Another neat thing about the UREG representation:  
+ */
+static INLINE int
+negate(int reg, int x, int y, int z, int w)
+{
+   return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) |
+                 ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) |
+                 ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) |
+                 ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT));
+}
+
+
+extern GLuint i915_get_temp(struct i915_fragment_program *p);
+extern GLuint i915_get_utemp(struct i915_fragment_program *p);
+extern void i915_release_utemps(struct i915_fragment_program *p);
+
+
+extern GLuint i915_emit_texld(struct i915_fragment_program *p,
+                              GLuint dest,
+                              GLuint destmask,
+                              GLuint sampler, GLuint coord, GLuint op);
+
+extern GLuint i915_emit_arith(struct i915_fragment_program *p,
+                              GLuint op,
+                              GLuint dest,
+                              GLuint mask,
+                              GLuint saturate,
+                              GLuint src0, GLuint src1, GLuint src2);
+
+extern GLuint i915_emit_decl(struct i915_fragment_program *p,
+                             GLuint type, GLuint nr, GLuint d0_flags);
+
+
+extern GLuint i915_emit_const1f(struct i915_fragment_program *p, GLfloat c0);
+
+extern GLuint i915_emit_const2f(struct i915_fragment_program *p,
+                                GLfloat c0, GLfloat c1);
+
+extern GLuint i915_emit_const4fv(struct i915_fragment_program *p,
+                                 const GLfloat * c);
+
+extern GLuint i915_emit_const4f(struct i915_fragment_program *p,
+                                GLfloat c0, GLfloat c1,
+                                GLfloat c2, GLfloat c3);
+
+
+extern GLuint i915_emit_param4fv(struct i915_fragment_program *p,
+                                 const GLfloat * values);
+
+extern void i915_program_error(struct i915_fragment_program *p,
+                               const char *msg);
+
+extern void i915_init_program(struct i915_context *i915,
+                              struct i915_fragment_program *p);
+
+extern void i915_upload_program(struct i915_context *i915,
+                                struct i915_fragment_program *p);
+
+extern void i915_fini_program(struct i915_fragment_program *p);
+
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/i915_reg.h b/src/mesa/drivers/dri/i915tex/i915_reg.h
new file mode 100644 (file)
index 0000000..04b1999
--- /dev/null
@@ -0,0 +1,841 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef _I915_REG_H_
+#define _I915_REG_H_
+
+
+#include "intel_reg.h"
+
+#define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value)
+
+#define CMD_3D (0x3<<29)
+
+#define PRIM3D_INLINE          (CMD_3D | (0x1f<<24))
+#define PRIM3D_TRILIST         (0x0<<18)
+#define PRIM3D_TRISTRIP        (0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE  (0x2<<18)
+#define PRIM3D_TRIFAN          (0x3<<18)
+#define PRIM3D_POLY            (0x4<<18)
+#define PRIM3D_LINELIST        (0x5<<18)
+#define PRIM3D_LINESTRIP       (0x6<<18)
+#define PRIM3D_RECTLIST        (0x7<<18)
+#define PRIM3D_POINTLIST       (0x8<<18)
+#define PRIM3D_DIB             (0x9<<18)
+#define PRIM3D_CLEAR_RECT      (0xa<<18)
+#define PRIM3D_ZONE_INIT       (0xd<<18)
+#define PRIM3D_MASK            (0x1f<<18)
+
+/* p137 */
+#define _3DSTATE_AA_CMD                        (CMD_3D | (0x06<<24))
+#define AA_LINE_ECAAR_WIDTH_ENABLE     (1<<16)
+#define AA_LINE_ECAAR_WIDTH_0_5        0
+#define AA_LINE_ECAAR_WIDTH_1_0                (1<<14)
+#define AA_LINE_ECAAR_WIDTH_2_0        (2<<14)
+#define AA_LINE_ECAAR_WIDTH_4_0        (3<<14)
+#define AA_LINE_REGION_WIDTH_ENABLE    (1<<8)
+#define AA_LINE_REGION_WIDTH_0_5       0
+#define AA_LINE_REGION_WIDTH_1_0       (1<<6)
+#define AA_LINE_REGION_WIDTH_2_0       (2<<6)
+#define AA_LINE_REGION_WIDTH_4_0       (3<<6)
+
+/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/
+#define _3DSTATE_BACKFACE_STENCIL_OPS    (CMD_3D | (0x8<<24))
+#define BFO_ENABLE_STENCIL_REF          (1<<23)
+#define BFO_STENCIL_REF_SHIFT           15
+#define BFO_STENCIL_REF_MASK            (0xff<<15)
+#define BFO_ENABLE_STENCIL_FUNCS        (1<<14)
+#define BFO_STENCIL_TEST_SHIFT          11
+#define BFO_STENCIL_TEST_MASK           (0x7<<11)
+#define BFO_STENCIL_FAIL_SHIFT          8
+#define BFO_STENCIL_FAIL_MASK           (0x7<<8)
+#define BFO_STENCIL_PASS_Z_FAIL_SHIFT   5
+#define BFO_STENCIL_PASS_Z_FAIL_MASK    (0x7<<5)
+#define BFO_STENCIL_PASS_Z_PASS_SHIFT   2
+#define BFO_STENCIL_PASS_Z_PASS_MASK    (0x7<<2)
+#define BFO_ENABLE_STENCIL_TWO_SIDE     (1<<1)
+#define BFO_STENCIL_TWO_SIDE            (1<<0)
+
+
+/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */
+#define _3DSTATE_BACKFACE_STENCIL_MASKS    (CMD_3D | (0x9<<24))
+#define BFM_ENABLE_STENCIL_TEST_MASK      (1<<17)
+#define BFM_ENABLE_STENCIL_WRITE_MASK     (1<<16)
+#define BFM_STENCIL_TEST_MASK_SHIFT       8
+#define BFM_STENCIL_TEST_MASK_MASK        (0xff<<8)
+#define BFM_STENCIL_WRITE_MASK_SHIFT      0
+#define BFM_STENCIL_WRITE_MASK_MASK       (0xff<<0)
+
+
+
+/* 3DSTATE_BIN_CONTROL p141 */
+
+/* p143 */
+#define _3DSTATE_BUF_INFO_CMD  (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1)
+/* Dword 1 */
+#define BUF_3D_ID_COLOR_BACK   (0x3<<24)
+#define BUF_3D_ID_DEPTH        (0x7<<24)
+#define BUF_3D_USE_FENCE       (1<<23)
+#define BUF_3D_TILED_SURFACE   (1<<22)
+#define BUF_3D_TILE_WALK_X     0
+#define BUF_3D_TILE_WALK_Y     (1<<21)
+#define BUF_3D_PITCH(x)         (((x)/4)<<2)
+/* Dword 2 */
+#define BUF_3D_ADDR(x)         ((x) & ~0x3)
+
+
+/* 3DSTATE_CHROMA_KEY */
+
+/* 3DSTATE_CLEAR_PARAMETERS, p150 */
+
+/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */
+#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16))
+
+
+
+/* 3DSTATE_COORD_SET_BINDINGS, p154 */
+#define _3DSTATE_COORD_SET_BINDINGS      (CMD_3D | (0x16<<24))
+#define CSB_TCB(iunit, eunit)           ((eunit)<<(iunit*3))
+
+/* p156 */
+#define _3DSTATE_DFLT_DIFFUSE_CMD      (CMD_3D | (0x1d<<24) | (0x99<<16))
+
+/* p157 */
+#define _3DSTATE_DFLT_SPEC_CMD         (CMD_3D | (0x1d<<24) | (0x9a<<16))
+
+/* p158 */
+#define _3DSTATE_DFLT_Z_CMD            (CMD_3D | (0x1d<<24) | (0x98<<16))
+
+
+/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */
+#define _3DSTATE_DEPTH_OFFSET_SCALE       (CMD_3D | (0x1d<<24) | (0x97<<16))
+/* scale in dword 1 */
+
+
+/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */
+#define _3DSTATE_DEPTH_SUBRECT_DISABLE    (CMD_3D | (0x1c<<24) | (0x11<19) | 0x2)
+
+/* p161 */
+#define _3DSTATE_DST_BUF_VARS_CMD      (CMD_3D | (0x1d<<24) | (0x85<<16))
+/* Dword 1 */
+#define TEX_DEFAULT_COLOR_OGL           (0<<30)
+#define TEX_DEFAULT_COLOR_D3D           (1<<30)
+#define ZR_EARLY_DEPTH                  (1<<29)
+#define LOD_PRECLAMP_OGL                (1<<28)
+#define LOD_PRECLAMP_D3D                (0<<28)
+#define DITHER_FULL_ALWAYS              (0<<26)
+#define DITHER_FULL_ON_FB_BLEND         (1<<26)
+#define DITHER_CLAMPED_ALWAYS           (2<<26)
+#define LINEAR_GAMMA_BLEND_32BPP        (1<<25)
+#define DEBUG_DISABLE_ENH_DITHER        (1<<24)
+#define DSTORG_HORT_BIAS(x)            ((x)<<20)
+#define DSTORG_VERT_BIAS(x)            ((x)<<16)
+#define COLOR_4_2_2_CHNL_WRT_ALL       0
+#define COLOR_4_2_2_CHNL_WRT_Y         (1<<12)
+#define COLOR_4_2_2_CHNL_WRT_CR                (2<<12)
+#define COLOR_4_2_2_CHNL_WRT_CB                (3<<12)
+#define COLOR_4_2_2_CHNL_WRT_CRCB      (4<<12)
+#define COLR_BUF_8BIT                  0
+#define COLR_BUF_RGB555                (1<<8)
+#define COLR_BUF_RGB565                (2<<8)
+#define COLR_BUF_ARGB8888              (3<<8)
+#define DEPTH_FRMT_16_FIXED            0
+#define DEPTH_FRMT_16_FLOAT            (1<<2)
+#define DEPTH_FRMT_24_FIXED_8_OTHER    (2<<2)
+#define VERT_LINE_STRIDE_1             (1<<1)
+#define VERT_LINE_STRIDE_0             (0<<1)
+#define VERT_LINE_STRIDE_OFS_1         1
+#define VERT_LINE_STRIDE_OFS_0         0
+
+/* p166 */
+#define _3DSTATE_DRAW_RECT_CMD         (CMD_3D|(0x1d<<24)|(0x80<<16)|3)
+/* Dword 1 */
+#define DRAW_RECT_DIS_DEPTH_OFS        (1<<30)
+#define DRAW_DITHER_OFS_X(x)           ((x)<<26)
+#define DRAW_DITHER_OFS_Y(x)           ((x)<<24)
+/* Dword 2 */
+#define DRAW_YMIN(x)                   ((x)<<16)
+#define DRAW_XMIN(x)                   (x)
+/* Dword 3 */
+#define DRAW_YMAX(x)                   ((x)<<16)
+#define DRAW_XMAX(x)                   (x)
+/* Dword 4 */
+#define DRAW_YORG(x)                   ((x)<<16)
+#define DRAW_XORG(x)                   (x)
+
+
+/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */
+
+/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */
+
+
+/* _3DSTATE_FOG_COLOR, p173 */
+#define _3DSTATE_FOG_COLOR_CMD         (CMD_3D|(0x15<<24))
+#define FOG_COLOR_RED(x)               ((x)<<16)
+#define FOG_COLOR_GREEN(x)             ((x)<<8)
+#define FOG_COLOR_BLUE(x)              (x)
+
+/* _3DSTATE_FOG_MODE, p174 */
+#define _3DSTATE_FOG_MODE_CMD          (CMD_3D|(0x1d<<24)|(0x89<<16)|2)
+/* Dword 1 */
+#define FMC1_FOGFUNC_MODIFY_ENABLE     (1<<31)
+#define FMC1_FOGFUNC_VERTEX            (0<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP         (1<<28)
+#define FMC1_FOGFUNC_PIXEL_EXP2                (2<<28)
+#define FMC1_FOGFUNC_PIXEL_LINEAR      (3<<28)
+#define FMC1_FOGFUNC_MASK              (3<<28)
+#define FMC1_FOGINDEX_MODIFY_ENABLE     (1<<27)
+#define FMC1_FOGINDEX_Z                        (0<<25)
+#define FMC1_FOGINDEX_W                (1<<25)
+#define FMC1_C1_C2_MODIFY_ENABLE       (1<<24)
+#define FMC1_DENSITY_MODIFY_ENABLE     (1<<23)
+#define FMC1_C1_ONE                    (1<<13)
+#define FMC1_C1_MASK                   (0xffff<<4)
+/* Dword 2 */
+#define FMC2_C2_ONE                    (1<<16)
+/* Dword 3 */
+#define FMC3_D_ONE                     (1<<16)
+
+
+
+/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */
+#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD   (CMD_3D|(0x0b<<24))
+#define IAB_MODIFY_ENABLE              (1<<23)
+#define IAB_ENABLE                     (1<<22)
+#define IAB_MODIFY_FUNC                (1<<21)
+#define IAB_FUNC_SHIFT                 16
+#define IAB_MODIFY_SRC_FACTOR          (1<<11)
+#define IAB_SRC_FACTOR_SHIFT           6
+#define IAB_SRC_FACTOR_MASK            (BLENDFACT_MASK<<6)
+#define IAB_MODIFY_DST_FACTOR          (1<<5)
+#define IAB_DST_FACTOR_SHIFT           0
+#define IAB_DST_FACTOR_MASK            (BLENDFACT_MASK<<0)
+
+
+#define BLENDFUNC_ADD                  0x0
+#define BLENDFUNC_SUBTRACT             0x1
+#define BLENDFUNC_REVERSE_SUBTRACT     0x2
+#define BLENDFUNC_MIN                  0x3
+#define BLENDFUNC_MAX                  0x4
+#define BLENDFUNC_MASK                 0x7
+
+/* 3DSTATE_LOAD_INDIRECT, p180 */
+
+#define _3DSTATE_LOAD_INDIRECT         (CMD_3D|(0x1d<<24)|(0x7<<16))
+#define LI0_STATE_STATIC_INDIRECT       (0x01<<8)
+#define LI0_STATE_DYNAMIC_INDIRECT      (0x02<<8)
+#define LI0_STATE_SAMPLER               (0x04<<8)
+#define LI0_STATE_MAP                   (0x08<<8)
+#define LI0_STATE_PROGRAM               (0x10<<8)
+#define LI0_STATE_CONSTANTS             (0x20<<8)
+
+#define SIS0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define SIS0_FORCE_LOAD                 (1<<1)
+#define SIS0_BUFFER_VALID               (1<<0)
+#define SIS1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define DIS0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define DIS0_BUFFER_RESET               (1<<1)
+#define DIS0_BUFFER_VALID               (1<<0)
+
+#define SSB0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define SSB0_FORCE_LOAD                 (1<<1)
+#define SSB0_BUFFER_VALID               (1<<0)
+#define SSB1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define MSB0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define MSB0_FORCE_LOAD                 (1<<1)
+#define MSB0_BUFFER_VALID               (1<<0)
+#define MSB1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define PSP0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define PSP0_FORCE_LOAD                 (1<<1)
+#define PSP0_BUFFER_VALID               (1<<0)
+#define PSP1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+#define PSC0_BUFFER_ADDRESS(x)          ((x)&~0x3)
+#define PSC0_FORCE_LOAD                 (1<<1)
+#define PSC0_BUFFER_VALID               (1<<0)
+#define PSC1_BUFFER_LENGTH(x)           ((x)&0xff)
+
+
+
+
+
+/* _3DSTATE_RASTERIZATION_RULES */
+#define _3DSTATE_RASTER_RULES_CMD      (CMD_3D|(0x07<<24))
+#define ENABLE_POINT_RASTER_RULE       (1<<15)
+#define OGL_POINT_RASTER_RULE          (1<<13)
+#define ENABLE_TEXKILL_3D_4D            (1<<10)
+#define TEXKILL_3D                      (0<<9)
+#define TEXKILL_4D                      (1<<9)
+#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8)
+#define ENABLE_TRI_FAN_PROVOKE_VRTX    (1<<5)
+#define LINE_STRIP_PROVOKE_VRTX(x)     ((x)<<6)
+#define TRI_FAN_PROVOKE_VRTX(x)        ((x)<<3)
+
+/* _3DSTATE_SCISSOR_ENABLE, p256 */
+#define _3DSTATE_SCISSOR_ENABLE_CMD    (CMD_3D|(0x1c<<24)|(0x10<<19))
+#define ENABLE_SCISSOR_RECT            ((1<<1) | 1)
+#define DISABLE_SCISSOR_RECT           (1<<1)
+
+/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */
+#define _3DSTATE_SCISSOR_RECT_0_CMD    (CMD_3D|(0x1d<<24)|(0x81<<16)|1)
+/* Dword 1 */
+#define SCISSOR_RECT_0_YMIN(x)         ((x)<<16)
+#define SCISSOR_RECT_0_XMIN(x)         (x)
+/* Dword 2 */
+#define SCISSOR_RECT_0_YMAX(x)         ((x)<<16)
+#define SCISSOR_RECT_0_XMAX(x)         (x)
+
+/* p189 */
+#define _3DSTATE_LOAD_STATE_IMMEDIATE_1   ((0x3<<29)|(0x1d<<24)|(0x04<<16))
+#define I1_LOAD_S(n)                      (1<<(4+n))
+
+#define S0_VB_OFFSET_MASK              0xffffffc
+#define S0_AUTO_CACHE_INV_DISABLE      (1<<0)
+
+#define S1_VERTEX_WIDTH_SHIFT          24
+#define S1_VERTEX_WIDTH_MASK           (0x3f<<24)
+#define S1_VERTEX_PITCH_SHIFT          16
+#define S1_VERTEX_PITCH_MASK           (0x3f<<16)
+
+#define TEXCOORDFMT_2D                 0x0
+#define TEXCOORDFMT_3D                 0x1
+#define TEXCOORDFMT_4D                 0x2
+#define TEXCOORDFMT_1D                 0x3
+#define TEXCOORDFMT_2D_16              0x4
+#define TEXCOORDFMT_4D_16              0x5
+#define TEXCOORDFMT_NOT_PRESENT        0xf
+#define S2_TEXCOORD_FMT0_MASK            0xf
+#define S2_TEXCOORD_FMT1_SHIFT           4
+#define S2_TEXCOORD_FMT(unit, type)    ((type)<<(unit*4))
+#define S2_TEXCOORD_NONE               (~0)
+
+/* S3 not interesting */
+
+#define S4_POINT_WIDTH_SHIFT           23
+#define S4_POINT_WIDTH_MASK            (0x1ff<<23)
+#define S4_LINE_WIDTH_SHIFT            19
+#define S4_LINE_WIDTH_ONE              (0x2<<19)
+#define S4_LINE_WIDTH_MASK             (0xf<<19)
+#define S4_FLATSHADE_ALPHA             (1<<18)
+#define S4_FLATSHADE_FOG               (1<<17)
+#define S4_FLATSHADE_SPECULAR          (1<<16)
+#define S4_FLATSHADE_COLOR             (1<<15)
+#define S4_CULLMODE_BOTH              (0<<13)
+#define S4_CULLMODE_NONE              (1<<13)
+#define S4_CULLMODE_CW                (2<<13)
+#define S4_CULLMODE_CCW                       (3<<13)
+#define S4_CULLMODE_MASK              (3<<13)
+#define S4_VFMT_POINT_WIDTH            (1<<12)
+#define S4_VFMT_SPEC_FOG               (1<<11)
+#define S4_VFMT_COLOR                  (1<<10)
+#define S4_VFMT_DEPTH_OFFSET           (1<<9)
+#define S4_VFMT_XYZ                   (1<<6)
+#define S4_VFMT_XYZW                  (2<<6)
+#define S4_VFMT_XY                            (3<<6)
+#define S4_VFMT_XYW                   (4<<6)
+#define S4_VFMT_XYZW_MASK              (7<<6)
+#define S4_FORCE_DEFAULT_DIFFUSE       (1<<5)
+#define S4_FORCE_DEFAULT_SPECULAR      (1<<4)
+#define S4_LOCAL_DEPTH_OFFSET_ENABLE   (1<<3)
+#define S4_VFMT_FOG_PARAM              (1<<2)
+#define S4_SPRITE_POINT_ENABLE         (1<<1)
+#define S4_LINE_ANTIALIAS_ENABLE       (1<<0)
+
+#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH   |  \
+                     S4_VFMT_SPEC_FOG      |   \
+                     S4_VFMT_COLOR         |   \
+                     S4_VFMT_DEPTH_OFFSET  |   \
+                     S4_VFMT_XYZW_MASK     |   \
+                     S4_VFMT_FOG_PARAM)
+
+
+#define S5_WRITEDISABLE_ALPHA          (1<<31)
+#define S5_WRITEDISABLE_RED            (1<<30)
+#define S5_WRITEDISABLE_GREEN          (1<<29)
+#define S5_WRITEDISABLE_BLUE           (1<<28)
+#define S5_WRITEDISABLE_MASK           (0xf<<28)
+#define S5_FORCE_DEFAULT_POINT_SIZE    (1<<27)
+#define S5_LAST_PIXEL_ENABLE           (1<<26)
+#define S5_GLOBAL_DEPTH_OFFSET_ENABLE  (1<<25)
+#define S5_FOG_ENABLE                  (1<<24)
+#define S5_STENCIL_REF_SHIFT           16
+#define S5_STENCIL_REF_MASK            (0xff<<16)
+#define S5_STENCIL_TEST_FUNC_SHIFT     13
+#define S5_STENCIL_TEST_FUNC_MASK      (0x7<<13)
+#define S5_STENCIL_FAIL_SHIFT          10
+#define S5_STENCIL_FAIL_MASK           (0x7<<10)
+#define S5_STENCIL_PASS_Z_FAIL_SHIFT   7
+#define S5_STENCIL_PASS_Z_FAIL_MASK    (0x7<<7)
+#define S5_STENCIL_PASS_Z_PASS_SHIFT   4
+#define S5_STENCIL_PASS_Z_PASS_MASK    (0x7<<4)
+#define S5_STENCIL_WRITE_ENABLE        (1<<3)
+#define S5_STENCIL_TEST_ENABLE         (1<<2)
+#define S5_COLOR_DITHER_ENABLE         (1<<1)
+#define S5_LOGICOP_ENABLE              (1<<0)
+
+
+#define S6_ALPHA_TEST_ENABLE           (1<<31)
+#define S6_ALPHA_TEST_FUNC_SHIFT       28
+#define S6_ALPHA_TEST_FUNC_MASK        (0x7<<28)
+#define S6_ALPHA_REF_SHIFT             20
+#define S6_ALPHA_REF_MASK              (0xff<<20)
+#define S6_DEPTH_TEST_ENABLE           (1<<19)
+#define S6_DEPTH_TEST_FUNC_SHIFT       16
+#define S6_DEPTH_TEST_FUNC_MASK        (0x7<<16)
+#define S6_CBUF_BLEND_ENABLE           (1<<15)
+#define S6_CBUF_BLEND_FUNC_SHIFT       12
+#define S6_CBUF_BLEND_FUNC_MASK        (0x7<<12)
+#define S6_CBUF_SRC_BLEND_FACT_SHIFT   8
+#define S6_CBUF_SRC_BLEND_FACT_MASK    (0xf<<8)
+#define S6_CBUF_DST_BLEND_FACT_SHIFT   4
+#define S6_CBUF_DST_BLEND_FACT_MASK    (0xf<<4)
+#define S6_DEPTH_WRITE_ENABLE          (1<<3)
+#define S6_COLOR_WRITE_ENABLE          (1<<2)
+#define S6_TRISTRIP_PV_SHIFT           0
+#define S6_TRISTRIP_PV_MASK            (0x3<<0)
+
+#define S7_DEPTH_OFFSET_CONST_MASK     ~0
+
+/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */
+
+/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
+#define _3DSTATE_MAP_PALETTE_LOAD_32    (CMD_3D|(0x1d<<24)|(0x8f<<16))
+/* subsequent dwords up to length (max 16) are ARGB8888 color values */
+
+/* _3DSTATE_MODES_4, p218 */
+#define _3DSTATE_MODES_4_CMD           (CMD_3D|(0x0d<<24))
+#define ENABLE_LOGIC_OP_FUNC           (1<<23)
+#define LOGIC_OP_FUNC(x)               ((x)<<18)
+#define LOGICOP_MASK                   (0xf<<18)
+#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
+#define ENABLE_STENCIL_TEST_MASK       (1<<17)
+#define STENCIL_TEST_MASK(x)           (((x)&0xff)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK        ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK      (1<<16)
+#define STENCIL_WRITE_MASK(x)          ((x)&0xff)
+
+/* _3DSTATE_MODES_5, p220 */
+#define _3DSTATE_MODES_5_CMD           (CMD_3D|(0x0c<<24))
+#define PIPELINE_FLUSH_RENDER_CACHE    (1<<18)
+#define PIPELINE_FLUSH_TEXTURE_CACHE   (1<<16)
+
+
+/* p221 */
+#define _3DSTATE_PIXEL_SHADER_CONSTANTS  (CMD_3D|(0x1d<<24)|(0x6<<16))
+#define PS1_REG(n)                      (1<<(n))
+#define PS2_CONST_X(n)                  (n)
+#define PS3_CONST_Y(n)                  (n)
+#define PS4_CONST_Z(n)                  (n)
+#define PS5_CONST_W(n)                  (n)
+
+/* p222 */
+
+
+#define I915_MAX_TEX_INDIRECT 4
+#define I915_MAX_TEX_INSN     32
+#define I915_MAX_ALU_INSN     64
+#define I915_MAX_DECL_INSN    27
+#define I915_MAX_TEMPORARY    16
+
+
+/* Each instruction is 3 dwords long, though most don't require all
+ * this space.  Maximum of 123 instructions.  Smaller maxes per insn
+ * type.
+ */
+#define _3DSTATE_PIXEL_SHADER_PROGRAM    (CMD_3D|(0x1d<<24)|(0x5<<16))
+
+#define REG_TYPE_R                 0    /* temporary regs, no need to
+                                         * dcl, must be written before
+                                         * read -- Preserved between
+                                         * phases. 
+                                         */
+#define REG_TYPE_T                 1    /* Interpolated values, must be
+                                         * dcl'ed before use.
+                                         *
+                                         * 0..7: texture coord,
+                                         * 8: diffuse spec,
+                                         * 9: specular color,
+                                         * 10: fog parameter in w.
+                                         */
+#define REG_TYPE_CONST             2    /* Restriction: only one const
+                                         * can be referenced per
+                                         * instruction, though it may be
+                                         * selected for multiple inputs.
+                                         * Constants not initialized
+                                         * default to zero.
+                                         */
+#define REG_TYPE_S                 3    /* sampler */
+#define REG_TYPE_OC                4    /* output color (rgba) */
+#define REG_TYPE_OD                5    /* output depth (w), xyz are
+                                         * temporaries.  If not written,
+                                         * interpolated depth is used?
+                                         */
+#define REG_TYPE_U                 6    /* unpreserved temporaries */
+#define REG_TYPE_MASK              0x7
+#define REG_NR_MASK                0xf
+
+
+/* REG_TYPE_T:
+ */
+#define T_TEX0     0
+#define T_TEX1     1
+#define T_TEX2     2
+#define T_TEX3     3
+#define T_TEX4     4
+#define T_TEX5     5
+#define T_TEX6     6
+#define T_TEX7     7
+#define T_DIFFUSE  8
+#define T_SPECULAR 9
+#define T_FOG_W    10           /* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww 
+ */
+#define A0_NOP    (0x0<<24)     /* no operation */
+#define A0_ADD    (0x1<<24)     /* dst = src0 + src1 */
+#define A0_MOV    (0x2<<24)     /* dst = src0 */
+#define A0_MUL    (0x3<<24)     /* dst = src0 * src1 */
+#define A0_MAD    (0x4<<24)     /* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24)     /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3    (0x6<<24)     /* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4    (0x7<<24)     /* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC    (0x8<<24)     /* dst = src0 - floor(src0) */
+#define A0_RCP    (0x9<<24)     /* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ    (0xa<<24)     /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP    (0xb<<24)     /* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG    (0xc<<24)     /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP    (0xd<<24)     /* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN    (0xe<<24)     /* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX    (0xf<<24)     /* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR    (0x10<<24)    /* dst = floor(src0) */
+#define A0_MOD    (0x11<<24)    /* dst = src0 fmod 1.0 */
+#define A0_TRC    (0x12<<24)    /* dst = int(src0) */
+#define A0_SGE    (0x13<<24)    /* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT    (0x14<<24)    /* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE                 (1<<22)
+#define A0_DEST_TYPE_SHIFT                19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT                 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X                (1<<10)
+#define A0_DEST_CHANNEL_Y                (2<<10)
+#define A0_DEST_CHANNEL_Z                (4<<10)
+#define A0_DEST_CHANNEL_W                (8<<10)
+#define A0_DEST_CHANNEL_ALL              (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT            10
+#define A0_SRC0_TYPE_SHIFT               7
+#define A0_SRC0_NR_SHIFT                 2
+
+#define A0_DEST_CHANNEL_XY              (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ             (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+
+#define SRC_X        0
+#define SRC_Y        1
+#define SRC_Z        2
+#define SRC_W        3
+#define SRC_ZERO     4
+#define SRC_ONE      5
+
+#define A1_SRC0_CHANNEL_X_NEGATE         (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT          28
+#define A1_SRC0_CHANNEL_Y_NEGATE         (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT          24
+#define A1_SRC0_CHANNEL_Z_NEGATE         (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT          20
+#define A1_SRC0_CHANNEL_W_NEGATE         (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT          16
+#define A1_SRC1_TYPE_SHIFT               13
+#define A1_SRC1_NR_SHIFT                 8
+#define A1_SRC1_CHANNEL_X_NEGATE         (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT          4
+#define A1_SRC1_CHANNEL_Y_NEGATE         (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT          0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE         (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT          28
+#define A2_SRC1_CHANNEL_W_NEGATE         (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT          24
+#define A2_SRC2_TYPE_SHIFT               21
+#define A2_SRC2_NR_SHIFT                 16
+#define A2_SRC2_CHANNEL_X_NEGATE         (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT          12
+#define A2_SRC2_CHANNEL_Y_NEGATE         (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT          8
+#define A2_SRC2_CHANNEL_Z_NEGATE         (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT          4
+#define A2_SRC2_CHANNEL_W_NEGATE         (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT          0
+
+
+
+/* Texture instructions */
+#define T0_TEXLD     (0x15<<24) /* Sample texture using predeclared
+                                 * sampler and address, and output
+                                 * filtered texel data to destination
+                                 * register */
+#define T0_TEXLDP    (0x16<<24) /* Same as texld but performs a
+                                 * perspective divide of the texture
+                                 * coordinate .xyz values by .w before
+                                 * sampling. */
+#define T0_TEXLDB    (0x17<<24) /* Same as texld but biases the
+                                 * computed LOD by w.  Only S4.6 two's
+                                 * comp is used.  This implies that a
+                                 * float to fixed conversion is
+                                 * done. */
+#define T0_TEXKILL   (0x18<<24) /* Does not perform a sampling
+                                 * operation.  Simply kills the pixel
+                                 * if any channel of the address
+                                 * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT                19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback) 
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction). 
+ */
+#define T0_DEST_NR_SHIFT                 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT              0      /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK               (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT        24     /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT          17
+#define T2_MBZ                           0
+
+/* Declaration instructions */
+#define D0_DCL       (0x19<<24) /* Declare a t (interpolated attrib)
+                                 * register or an s (sampler)
+                                 * register. */
+#define D0_SAMPLE_TYPE_SHIFT              22
+#define D0_SAMPLE_TYPE_2D                 (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE               (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME             (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK               (0x3<<22)
+
+#define D0_TYPE_SHIFT                19
+/* Allow: T, S */
+#define D0_NR_SHIFT                  14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X                (1<<10)
+#define D0_CHANNEL_Y                (2<<10)
+#define D0_CHANNEL_Z                (4<<10)
+#define D0_CHANNEL_W                (8<<10)
+#define D0_CHANNEL_ALL              (0xf<<10)
+#define D0_CHANNEL_NONE             (0<<10)
+
+#define D0_CHANNEL_XY               (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ              (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations. 
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) 
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ                          0
+#define D2_MBZ                          0
+
+
+
+/* p207 */
+#define _3DSTATE_MAP_STATE               (CMD_3D|(0x1d<<24)|(0x0<<16))
+
+#define MS1_MAPMASK_SHIFT               0
+#define MS1_MAPMASK_MASK                (0x8fff<<0)
+
+#define MS2_UNTRUSTED_SURFACE           (1<<31)
+#define MS2_ADDRESS_MASK                0xfffffffc
+#define MS2_VERTICAL_LINE_STRIDE        (1<<1)
+#define MS2_VERTICAL_OFFSET             (1<<1)
+
+#define MS3_HEIGHT_SHIFT              21
+#define MS3_WIDTH_SHIFT               10
+#define MS3_PALETTE_SELECT            (1<<9)
+#define MS3_MAPSURF_FORMAT_SHIFT      7
+#define MS3_MAPSURF_FORMAT_MASK       (0x7<<7)
+#define    MAPSURF_8BIT                           (1<<7)
+#define    MAPSURF_16BIT                  (2<<7)
+#define    MAPSURF_32BIT                  (3<<7)
+#define    MAPSURF_422                    (5<<7)
+#define    MAPSURF_COMPRESSED             (6<<7)
+#define    MAPSURF_4BIT_INDEXED                   (7<<7)
+#define MS3_MT_FORMAT_MASK         (0x7 << 3)
+#define MS3_MT_FORMAT_SHIFT        3
+#define    MT_4BIT_IDX_ARGB8888                   (7<<3)       /* SURFACE_4BIT_INDEXED */
+#define    MT_8BIT_I8                     (0<<3)       /* SURFACE_8BIT */
+#define    MT_8BIT_L8                     (1<<3)
+#define    MT_8BIT_A8                     (4<<3)
+#define    MT_8BIT_MONO8                  (5<<3)
+#define    MT_16BIT_RGB565                (0<<3)       /* SURFACE_16BIT */
+#define    MT_16BIT_ARGB1555              (1<<3)
+#define    MT_16BIT_ARGB4444              (2<<3)
+#define    MT_16BIT_AY88                  (3<<3)
+#define    MT_16BIT_88DVDU                (5<<3)
+#define    MT_16BIT_BUMP_655LDVDU         (6<<3)
+#define    MT_16BIT_I16                           (7<<3)
+#define    MT_16BIT_L16                           (8<<3)
+#define    MT_16BIT_A16                           (9<<3)
+#define    MT_32BIT_ARGB8888              (0<<3)       /* SURFACE_32BIT */
+#define    MT_32BIT_ABGR8888              (1<<3)
+#define    MT_32BIT_XRGB8888              (2<<3)
+#define    MT_32BIT_XBGR8888              (3<<3)
+#define    MT_32BIT_QWVU8888              (4<<3)
+#define    MT_32BIT_AXVU8888              (5<<3)
+#define    MT_32BIT_LXVU8888              (6<<3)
+#define    MT_32BIT_XLVU8888              (7<<3)
+#define    MT_32BIT_ARGB2101010                   (8<<3)
+#define    MT_32BIT_ABGR2101010                   (9<<3)
+#define    MT_32BIT_AWVU2101010                   (0xA<<3)
+#define    MT_32BIT_GR1616                (0xB<<3)
+#define    MT_32BIT_VU1616                (0xC<<3)
+#define    MT_32BIT_xI824                 (0xD<<3)
+#define    MT_32BIT_xA824                 (0xE<<3)
+#define    MT_32BIT_xL824                 (0xF<<3)
+#define    MT_422_YCRCB_SWAPY             (0<<3)       /* SURFACE_422 */
+#define    MT_422_YCRCB_NORMAL            (1<<3)
+#define    MT_422_YCRCB_SWAPUV            (2<<3)
+#define    MT_422_YCRCB_SWAPUVY                   (3<<3)
+#define    MT_COMPRESS_DXT1               (0<<3)       /* SURFACE_COMPRESSED */
+#define    MT_COMPRESS_DXT2_3             (1<<3)
+#define    MT_COMPRESS_DXT4_5             (2<<3)
+#define    MT_COMPRESS_FXT1               (3<<3)
+#define    MT_COMPRESS_DXT1_RGB                   (4<<3)
+#define MS3_USE_FENCE_REGS              (1<<2)
+#define MS3_TILED_SURFACE             (1<<1)
+#define MS3_TILE_WALK                 (1<<0)
+
+#define MS4_PITCH_SHIFT                 21
+#define MS4_CUBE_FACE_ENA_NEGX          (1<<20)
+#define MS4_CUBE_FACE_ENA_POSX          (1<<19)
+#define MS4_CUBE_FACE_ENA_NEGY          (1<<18)
+#define MS4_CUBE_FACE_ENA_POSY          (1<<17)
+#define MS4_CUBE_FACE_ENA_NEGZ          (1<<16)
+#define MS4_CUBE_FACE_ENA_POSZ          (1<<15)
+#define MS4_CUBE_FACE_ENA_MASK          (0x3f<<15)
+#define MS4_MAX_LOD_SHIFT              9
+#define MS4_MAX_LOD_MASK               (0x3f<<9)
+#define MS4_MIP_LAYOUT_LEGACY           (0<<8)
+#define MS4_MIP_LAYOUT_BELOW_LPT        (0<<8)
+#define MS4_MIP_LAYOUT_RIGHT_LPT        (1<<8)
+#define MS4_VOLUME_DEPTH_SHIFT          0
+#define MS4_VOLUME_DEPTH_MASK           (0xff<<0)
+
+/* p244 */
+#define _3DSTATE_SAMPLER_STATE         (CMD_3D|(0x1d<<24)|(0x1<<16))
+
+#define SS1_MAPMASK_SHIFT               0
+#define SS1_MAPMASK_MASK                (0x8fff<<0)
+
+#define SS2_REVERSE_GAMMA_ENABLE        (1<<31)
+#define SS2_PACKED_TO_PLANAR_ENABLE     (1<<30)
+#define SS2_COLORSPACE_CONVERSION       (1<<29)
+#define SS2_CHROMAKEY_SHIFT             27
+#define SS2_BASE_MIP_LEVEL_SHIFT        22
+#define SS2_BASE_MIP_LEVEL_MASK         (0x1f<<22)
+#define SS2_MIP_FILTER_SHIFT            20
+#define SS2_MIP_FILTER_MASK             (0x3<<20)
+#define   MIPFILTER_NONE               0
+#define   MIPFILTER_NEAREST    1
+#define   MIPFILTER_LINEAR     3
+#define SS2_MAG_FILTER_SHIFT          17
+#define SS2_MAG_FILTER_MASK           (0x7<<17)
+#define   FILTER_NEAREST       0
+#define   FILTER_LINEAR                1
+#define   FILTER_ANISOTROPIC   2
+#define   FILTER_4X4_1         3
+#define   FILTER_4X4_2         4
+#define   FILTER_4X4_FLAT      5
+#define   FILTER_6X5_MONO      6       /* XXX - check */
+#define SS2_MIN_FILTER_SHIFT          14
+#define SS2_MIN_FILTER_MASK           (0x7<<14)
+#define SS2_LOD_BIAS_SHIFT            5
+#define SS2_LOD_BIAS_ONE              (0x10<<5)
+#define SS2_LOD_BIAS_MASK             (0x1ff<<5)
+/* Shadow requires:
+ *  MT_X8{I,L,A}24 or MT_{I,L,A}16 texture format
+ *  FILTER_4X4_x  MIN and MAG filters
+ */
+#define SS2_SHADOW_ENABLE             (1<<4)
+#define SS2_MAX_ANISO_MASK            (1<<3)
+#define SS2_MAX_ANISO_2               (0<<3)
+#define SS2_MAX_ANISO_4               (1<<3)
+#define SS2_SHADOW_FUNC_SHIFT         0
+#define SS2_SHADOW_FUNC_MASK          (0x7<<0)
+/* SS2_SHADOW_FUNC values: see COMPAREFUNC_* */
+
+#define SS3_MIN_LOD_SHIFT            24
+#define SS3_MIN_LOD_ONE              (0x10<<24)
+#define SS3_MIN_LOD_MASK             (0xff<<24)
+#define SS3_KILL_PIXEL_ENABLE        (1<<17)
+#define SS3_TCX_ADDR_MODE_SHIFT      12
+#define SS3_TCX_ADDR_MODE_MASK       (0x7<<12)
+#define   TEXCOORDMODE_WRAP            0
+#define   TEXCOORDMODE_MIRROR          1
+#define   TEXCOORDMODE_CLAMP_EDGE      2
+#define   TEXCOORDMODE_CUBE            3
+#define   TEXCOORDMODE_CLAMP_BORDER    4
+#define   TEXCOORDMODE_MIRROR_ONCE      5
+#define SS3_TCY_ADDR_MODE_SHIFT      9
+#define SS3_TCY_ADDR_MODE_MASK       (0x7<<9)
+#define SS3_TCZ_ADDR_MODE_SHIFT      6
+#define SS3_TCZ_ADDR_MODE_MASK       (0x7<<6)
+#define SS3_NORMALIZED_COORDS        (1<<5)
+#define SS3_TEXTUREMAP_INDEX_SHIFT   1
+#define SS3_TEXTUREMAP_INDEX_MASK    (0xf<<1)
+#define SS3_DEINTERLACER_ENABLE      (1<<0)
+
+#define SS4_BORDER_COLOR_MASK        (~0)
+
+/* 3DSTATE_SPAN_STIPPLE, p258
+ */
+#define _3DSTATE_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE               (1<<16)
+#define ST1_MASK                 (0xffff)
+
+#define _3DSTATE_DEFAULT_Z          ((0x3<<29)|(0x1d<<24)|(0x98<<16))
+#define _3DSTATE_DEFAULT_DIFFUSE    ((0x3<<29)|(0x1d<<24)|(0x99<<16))
+#define _3DSTATE_DEFAULT_SPECULAR   ((0x3<<29)|(0x1d<<24)|(0x9a<<16))
+
+
+#define MI_FLUSH                   ((0<<29)|(4<<23))
+#define FLUSH_MAP_CACHE            (1<<0)
+#define INHIBIT_FLUSH_RENDER_CACHE (1<<2)
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/i915_state.c b/src/mesa/drivers/dri/i915tex/i915_state.c
new file mode 100644 (file)
index 0000000..d68801d
--- /dev/null
@@ -0,0 +1,1019 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "enums.h"
+#include "dd.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+#include "texmem.h"
+
+#include "intel_fbo.h"
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+#define FILE_DEBUG_FLAG DEBUG_STATE
+
+static void
+i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
+                        GLuint mask)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int test = intel_translate_compare_func(func);
+
+   mask = mask & 0xff;
+
+   DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(func), ref, mask);
+
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+   i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
+                                           STENCIL_TEST_MASK(mask));
+
+   i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
+                                          S5_STENCIL_TEST_FUNC_MASK);
+
+   i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) |
+                                         (test <<
+                                          S5_STENCIL_TEST_FUNC_SHIFT));
+}
+
+static void
+i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
+   
+   mask = mask & 0xff;
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
+   i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
+                                           STENCIL_WRITE_MASK(mask));
+}
+
+
+static void
+i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail,
+                      GLenum zpass)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int fop = intel_translate_stencil_op(fail);
+   int dfop = intel_translate_stencil_op(zfail);
+   int dpop = intel_translate_stencil_op(zpass);
+
+
+   DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(fail),
+       _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass));
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+
+   i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
+                                          S5_STENCIL_PASS_Z_FAIL_MASK |
+                                          S5_STENCIL_PASS_Z_PASS_MASK);
+
+   i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) |
+                                         (dfop <<
+                                          S5_STENCIL_PASS_Z_FAIL_SHIFT) |
+                                         (dpop <<
+                                          S5_STENCIL_PASS_Z_PASS_SHIFT));
+}
+
+static void
+i915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int test = intel_translate_compare_func(func);
+   GLubyte refByte;
+
+   UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK |
+                                          S6_ALPHA_REF_MASK);
+   i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) |
+                                         (((GLuint) refByte) <<
+                                          S6_ALPHA_REF_SHIFT));
+}
+
+/* This function makes sure that the proper enables are
+ * set for LogicOp, Independant Alpha Blend, and Blending.
+ * It needs to be called from numerous places where we
+ * could change the LogicOp or Independant Alpha Blend without subsequent
+ * calls to glEnable.
+ */
+static void
+i915EvalLogicOpBlendState(GLcontext * ctx)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+
+   if (ctx->Color._LogicOpEnabled) {
+      i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE;
+      i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
+   }
+   else {
+      i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE;
+
+      if (ctx->Color.BlendEnabled) {
+         i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE;
+      }
+      else {
+         i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
+      }
+   }
+}
+
+static void
+i915BlendColor(GLcontext * ctx, const GLfloat color[4])
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLubyte r, g, b, a;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]);
+   UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]);
+   UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]);
+   UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]);
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] =
+      (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+
+#define DST_BLND_FACT(f) ((f)<<S6_CBUF_DST_BLEND_FACT_SHIFT)
+#define SRC_BLND_FACT(f) ((f)<<S6_CBUF_SRC_BLEND_FACT_SHIFT)
+#define DST_ABLND_FACT(f) ((f)<<IAB_DST_FACTOR_SHIFT)
+#define SRC_ABLND_FACT(f) ((f)<<IAB_SRC_FACTOR_SHIFT)
+
+
+
+static GLuint
+translate_blend_equation(GLenum mode)
+{
+   switch (mode) {
+   case GL_FUNC_ADD:
+      return BLENDFUNC_ADD;
+   case GL_MIN:
+      return BLENDFUNC_MIN;
+   case GL_MAX:
+      return BLENDFUNC_MAX;
+   case GL_FUNC_SUBTRACT:
+      return BLENDFUNC_SUBTRACT;
+   case GL_FUNC_REVERSE_SUBTRACT:
+      return BLENDFUNC_REVERSE_SUBTRACT;
+   default:
+      return 0;
+   }
+}
+
+static void
+i915UpdateBlendState(GLcontext * ctx)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
+                 ~(IAB_SRC_FACTOR_MASK |
+                   IAB_DST_FACTOR_MASK |
+                   (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE));
+
+   GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] &
+                  ~(S6_CBUF_SRC_BLEND_FACT_MASK |
+                    S6_CBUF_DST_BLEND_FACT_MASK | S6_CBUF_BLEND_FUNC_MASK));
+
+   GLuint eqRGB = ctx->Color.BlendEquationRGB;
+   GLuint eqA = ctx->Color.BlendEquationA;
+   GLuint srcRGB = ctx->Color.BlendSrcRGB;
+   GLuint dstRGB = ctx->Color.BlendDstRGB;
+   GLuint srcA = ctx->Color.BlendSrcA;
+   GLuint dstA = ctx->Color.BlendDstA;
+
+   if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
+      srcRGB = dstRGB = GL_ONE;
+   }
+
+   if (eqA == GL_MIN || eqA == GL_MAX) {
+      srcA = dstA = GL_ONE;
+   }
+
+   lis6 |= SRC_BLND_FACT(intel_translate_blend_factor(srcRGB));
+   lis6 |= DST_BLND_FACT(intel_translate_blend_factor(dstRGB));
+   lis6 |= translate_blend_equation(eqRGB) << S6_CBUF_BLEND_FUNC_SHIFT;
+
+   iab |= SRC_ABLND_FACT(intel_translate_blend_factor(srcA));
+   iab |= DST_ABLND_FACT(intel_translate_blend_factor(dstA));
+   iab |= translate_blend_equation(eqA) << IAB_FUNC_SHIFT;
+
+   if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
+      iab |= IAB_ENABLE;
+
+   if (iab != i915->state.Ctx[I915_CTXREG_IAB] ||
+       lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      i915->state.Ctx[I915_CTXREG_IAB] = iab;
+      i915->state.Ctx[I915_CTXREG_LIS6] = lis6;
+   }
+
+   /* This will catch a logicop blend equation */
+   i915EvalLogicOpBlendState(ctx);
+}
+
+
+static void
+i915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB,
+                      GLenum dstRGB, GLenum srcA, GLenum dstA)
+{
+   i915UpdateBlendState(ctx);
+}
+
+
+static void
+i915BlendEquationSeparate(GLcontext * ctx, GLenum eqRGB, GLenum eqA)
+{
+   i915UpdateBlendState(ctx);
+}
+
+
+static void
+i915DepthFunc(GLcontext * ctx, GLenum func)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int test = intel_translate_compare_func(func);
+
+   DBG("%s\n", __FUNCTION__);
+   
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
+   i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT;
+}
+
+static void
+i915DepthMask(GLcontext * ctx, GLboolean flag)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   DBG("%s flag (%d)\n", __FUNCTION__, flag);
+   
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+
+   if (flag && ctx->Depth.Test)
+      i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE;
+   else
+      i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE;
+}
+
+/* =============================================================
+ * Polygon stipple
+ *
+ * The i915 supports a 4x4 stipple natively, GL wants 32x32.
+ * Fortunately stipple is usually a repeating pattern.
+ */
+static void
+i915PolygonStipple(GLcontext * ctx, const GLubyte * mask)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   const GLubyte *m = mask;
+   GLubyte p[4];
+   int i, j, k;
+   int active = (ctx->Polygon.StippleFlag &&
+                 i915->intel.reduced_primitive == GL_TRIANGLES);
+   GLuint newMask;
+
+   if (active) {
+      I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
+      i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE;
+   }
+
+   p[0] = mask[12] & 0xf;
+   p[0] |= p[0] << 4;
+   p[1] = mask[8] & 0xf;
+   p[1] |= p[1] << 4;
+   p[2] = mask[4] & 0xf;
+   p[2] |= p[2] << 4;
+   p[3] = mask[0] & 0xf;
+   p[3] |= p[3] << 4;
+
+   for (k = 0; k < 8; k++)
+      for (j = 3; j >= 0; j--)
+         for (i = 0; i < 4; i++, m++)
+            if (*m != p[j]) {
+               i915->intel.hw_stipple = 0;
+               return;
+            }
+
+   newMask = (((p[0] & 0xf) << 0) |
+              ((p[1] & 0xf) << 4) |
+              ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12));
+
+
+   if (newMask == 0xffff || newMask == 0x0) {
+      /* this is needed to make conform pass */
+      i915->intel.hw_stipple = 0;
+      return;
+   }
+
+   i915->state.Stipple[I915_STPREG_ST1] &= ~0xffff;
+   i915->state.Stipple[I915_STPREG_ST1] |= newMask;
+   i915->intel.hw_stipple = 1;
+
+   if (active)
+      i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE;
+}
+
+
+/* =============================================================
+ * Hardware clipping
+ */
+static void
+i915Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int x1, y1, x2, y2;
+
+   if (!ctx->DrawBuffer)
+      return;
+
+   DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h);
+
+   if (ctx->DrawBuffer->Name == 0) {
+      x1 = x;
+      y1 = ctx->DrawBuffer->Height - (y + h);
+      x2 = x + w - 1;
+      y2 = y1 + h - 1;
+      DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2);
+   }
+   else {
+      /* FBO - not inverted
+       */
+      x1 = x;
+      y1 = y;
+      x2 = x + w - 1;
+      y2 = y + h - 1;
+      DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2);
+   }
+   
+   x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
+   y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
+   x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
+   y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
+   
+   DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2);
+
+   I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
+   i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
+   i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
+}
+
+static void
+i915LogicOp(GLcontext * ctx, GLenum opcode)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int tmp = intel_translate_logic_op(opcode);
+
+   DBG("%s\n", __FUNCTION__);
+   
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK;
+   i915->state.Ctx[I915_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp);
+}
+
+
+
+static void
+i915CullFaceFrontFace(GLcontext * ctx, GLenum unused)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLuint mode;
+
+   DBG("%s %d\n", __FUNCTION__,
+       ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0);
+
+   if (!ctx->Polygon.CullFlag) {
+      mode = S4_CULLMODE_NONE;
+   }
+   else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
+      mode = S4_CULLMODE_CW;
+
+      if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
+         mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
+      if (ctx->Polygon.CullFaceMode == GL_FRONT)
+         mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
+      if (ctx->Polygon.FrontFace != GL_CCW)
+         mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
+   }
+   else {
+      mode = S4_CULLMODE_BOTH;
+   }
+
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+   i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK;
+   i915->state.Ctx[I915_CTXREG_LIS4] |= mode;
+}
+
+static void
+i915LineWidth(GLcontext * ctx, GLfloat widthf)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
+   int width;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   width = (int) (widthf * 2);
+   CLAMP_SELF(width, 1, 0xf);
+   lis4 |= width << S4_LINE_WIDTH_SHIFT;
+
+   if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      i915->state.Ctx[I915_CTXREG_LIS4] = lis4;
+   }
+}
+
+static void
+i915PointSize(GLcontext * ctx, GLfloat size)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
+   GLint point_size = (int) size;
+
+   DBG("%s\n", __FUNCTION__);
+   
+   CLAMP_SELF(point_size, 1, 255);
+   lis4 |= point_size << S4_POINT_WIDTH_SHIFT;
+
+   if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      i915->state.Ctx[I915_CTXREG_LIS4] = lis4;
+   }
+}
+
+
+/* =============================================================
+ * Color masks
+ */
+
+static void
+i915ColorMask(GLcontext * ctx,
+              GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK;
+
+   DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b,
+       a);
+
+   if (!r)
+      tmp |= S5_WRITEDISABLE_RED;
+   if (!g)
+      tmp |= S5_WRITEDISABLE_GREEN;
+   if (!b)
+      tmp |= S5_WRITEDISABLE_BLUE;
+   if (!a)
+      tmp |= S5_WRITEDISABLE_ALPHA;
+
+   if (tmp != i915->state.Ctx[I915_CTXREG_LIS5]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      i915->state.Ctx[I915_CTXREG_LIS5] = tmp;
+   }
+}
+
+static void
+update_specular(GLcontext * ctx)
+{
+   /* A hack to trigger the rebuild of the fragment program.
+    */
+   intel_context(ctx)->NewGLState |= _NEW_TEXTURE;
+   I915_CONTEXT(ctx)->tex_program.translated = 0;
+}
+
+static void
+i915LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
+{
+   DBG("%s\n", __FUNCTION__);
+   
+   if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+      update_specular(ctx);
+   }
+}
+
+static void
+i915ShadeModel(GLcontext * ctx, GLenum mode)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+
+   if (mode == GL_SMOOTH) {
+      i915->state.Ctx[I915_CTXREG_LIS4] &= ~(S4_FLATSHADE_ALPHA |
+                                             S4_FLATSHADE_COLOR |
+                                             S4_FLATSHADE_SPECULAR);
+   }
+   else {
+      i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA |
+                                            S4_FLATSHADE_COLOR |
+                                            S4_FLATSHADE_SPECULAR);
+   }
+}
+
+/* =============================================================
+ * Fog
+ */
+void
+i915_update_fog(GLcontext * ctx)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+   GLenum mode;
+   GLboolean enabled;
+   GLboolean try_pixel_fog;
+
+   if (ctx->FragmentProgram._Active) {
+      /* Pull in static fog state from program */
+
+      mode = ctx->FragmentProgram._Current->FogOption;
+      enabled = (mode != GL_NONE);
+      try_pixel_fog = 0;
+   }
+   else {
+      enabled = ctx->Fog.Enabled;
+      mode = ctx->Fog.Mode;
+
+      try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && ctx->Hint.Fog == GL_NICEST && 0);       /* XXX - DISABLE -- Need ortho fallback */
+   }
+
+   if (!enabled) {
+      i915->vertex_fog = I915_FOG_NONE;
+   }
+   else if (try_pixel_fog) {
+
+      I915_STATECHANGE(i915, I915_UPLOAD_FOG);
+      i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK;
+      i915->vertex_fog = I915_FOG_PIXEL;
+
+      switch (mode) {
+      case GL_LINEAR:
+         if (ctx->Fog.End <= ctx->Fog.Start) {
+            /* XXX - this won't work with fragment programs.  Need to
+             * either fallback or append fog instructions to end of
+             * program in the case of linear fog.
+             */
+            i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX;
+            i915->vertex_fog = I915_FOG_VERTEX;
+         }
+         else {
+            GLfloat c1 = ctx->Fog.End / (ctx->Fog.End - ctx->Fog.Start);
+            GLfloat c2 = 1.0 / (ctx->Fog.End - ctx->Fog.Start);
+
+            i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_C1_MASK;
+            i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_LINEAR;
+            i915->state.Fog[I915_FOGREG_MODE1] |=
+               ((GLuint) (c1 * FMC1_C1_ONE)) & FMC1_C1_MASK;
+
+            if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) {
+               i915->state.Fog[I915_FOGREG_MODE2] =
+                  (GLuint) (c2 * FMC2_C2_ONE);
+            }
+            else {
+               union
+               {
+                  float f;
+                  int i;
+               } fi;
+               fi.f = c2;
+               i915->state.Fog[I915_FOGREG_MODE2] = fi.i;
+            }
+         }
+         break;
+      case GL_EXP:
+         i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_EXP;
+         break;
+      case GL_EXP2:
+         i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_EXP2;
+         break;
+      default:
+         break;
+      }
+   }
+   else {                       /* if (i915->vertex_fog != I915_FOG_VERTEX) */
+
+      I915_STATECHANGE(i915, I915_UPLOAD_FOG);
+      i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK;
+      i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX;
+      i915->vertex_fog = I915_FOG_VERTEX;
+   }
+
+   {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      I915_ACTIVESTATE(i915, I915_UPLOAD_FOG, enabled);
+      if (enabled)
+         i915->state.Ctx[I915_CTXREG_LIS5] |= S5_FOG_ENABLE;
+      else
+         i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_FOG_ENABLE;
+   }
+
+   if (enabled) {
+      _tnl_allow_vertex_fog(ctx, (i915->vertex_fog == I915_FOG_VERTEX));
+      _tnl_allow_pixel_fog(ctx, (i915->vertex_fog != I915_FOG_VERTEX));
+   }
+}
+
+static void
+i915Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   switch (pname) {
+   case GL_FOG_COORDINATE_SOURCE_EXT:
+   case GL_FOG_MODE:
+   case GL_FOG_START:
+   case GL_FOG_END:
+      break;
+
+   case GL_FOG_DENSITY:
+      I915_STATECHANGE(i915, I915_UPLOAD_FOG);
+
+      if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) {
+         i915->state.Fog[I915_FOGREG_MODE3] = (GLuint) (ctx->Fog.Density *
+                                                        FMC3_D_ONE);
+      }
+      else {
+         union
+         {
+            float f;
+            int i;
+         } fi;
+         fi.f = ctx->Fog.Density;
+         i915->state.Fog[I915_FOGREG_MODE3] = fi.i;
+      }
+      break;
+
+   case GL_FOG_COLOR:
+      I915_STATECHANGE(i915, I915_UPLOAD_FOG);
+      i915->state.Fog[I915_FOGREG_COLOR] =
+         (_3DSTATE_FOG_COLOR_CMD |
+          ((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) |
+          ((GLubyte) (ctx->Fog.Color[1] * 255.0F) << 8) |
+          ((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0));
+      break;
+
+   default:
+      break;
+   }
+}
+
+static void
+i915Hint(GLcontext * ctx, GLenum target, GLenum state)
+{
+   switch (target) {
+   case GL_FOG_HINT:
+      break;
+   default:
+      break;
+   }
+}
+
+/* =============================================================
+ */
+
+static void
+i915Enable(GLcontext * ctx, GLenum cap, GLboolean state)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   switch (cap) {
+   case GL_TEXTURE_2D:
+      break;
+
+   case GL_LIGHTING:
+   case GL_COLOR_SUM:
+      update_specular(ctx);
+      break;
+
+   case GL_ALPHA_TEST:
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      if (state)
+         i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE;
+      else
+         i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_ALPHA_TEST_ENABLE;
+      break;
+
+   case GL_BLEND:
+      i915EvalLogicOpBlendState(ctx);
+      break;
+
+   case GL_COLOR_LOGIC_OP:
+      i915EvalLogicOpBlendState(ctx);
+
+      /* Logicop doesn't seem to work at 16bpp:
+       */
+      if (i915->intel.intelScreen->cpp == 2)    /* XXX FBO fix */
+         FALLBACK(&i915->intel, I915_FALLBACK_LOGICOP, state);
+      break;
+
+   case GL_FRAGMENT_PROGRAM_ARB:
+      break;
+
+   case GL_DITHER:
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      if (state)
+         i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
+      else
+         i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_COLOR_DITHER_ENABLE;
+      break;
+
+   case GL_DEPTH_TEST:
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      if (state)
+         i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE;
+      else
+         i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE;
+
+      i915DepthMask(ctx, ctx->Depth.Mask);
+      break;
+
+   case GL_SCISSOR_TEST:
+      I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
+      if (state)
+         i915->state.Buffer[I915_DESTREG_SENABLE] =
+            (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT);
+      else
+         i915->state.Buffer[I915_DESTREG_SENABLE] =
+            (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+      break;
+
+   case GL_LINE_SMOOTH:
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      if (state)
+         i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE;
+      else
+         i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_LINE_ANTIALIAS_ENABLE;
+      break;
+
+   case GL_FOG:
+      break;
+
+   case GL_CULL_FACE:
+      i915CullFaceFrontFace(ctx, 0);
+      break;
+
+   case GL_STENCIL_TEST:
+      {
+         GLboolean hw_stencil = GL_FALSE;
+         if (ctx->DrawBuffer) {
+            struct intel_renderbuffer *irbStencil
+               = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
+            hw_stencil = (irbStencil && irbStencil->region);
+         }
+         if (hw_stencil) {
+            I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+            if (state)
+               i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
+                                                     S5_STENCIL_WRITE_ENABLE);
+            else
+               i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
+                                                      S5_STENCIL_WRITE_ENABLE);
+         }
+         else {
+            FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state);
+         }
+      }
+      break;
+
+   case GL_POLYGON_STIPPLE:
+      /* The stipple command worked on my 855GM box, but not my 845G.
+       * I'll do more testing later to find out exactly which hardware
+       * supports it.  Disabled for now.
+       */
+      if (i915->intel.hw_stipple &&
+          i915->intel.reduced_primitive == GL_TRIANGLES) {
+         I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
+         if (state)
+            i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE;
+         else
+            i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE;
+      }
+      break;
+
+   case GL_POLYGON_SMOOTH:
+      break;
+
+   case GL_POINT_SMOOTH:
+      break;
+
+   default:
+      ;
+   }
+}
+
+
+static void
+i915_init_packets(struct i915_context *i915)
+{
+   intelScreenPrivate *screen = i915->intel.intelScreen;
+
+   /* Zero all state */
+   memset(&i915->state, 0, sizeof(i915->state));
+
+
+   {
+      I915_STATECHANGE(i915, I915_UPLOAD_CTX);
+      /* Probably don't want to upload all this stuff every time one 
+       * piece changes.
+       */
+      i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+                                         I1_LOAD_S(2) |
+                                         I1_LOAD_S(4) |
+                                         I1_LOAD_S(5) | I1_LOAD_S(6) | (4));
+      i915->state.Ctx[I915_CTXREG_LIS2] = 0;
+      i915->state.Ctx[I915_CTXREG_LIS4] = 0;
+      i915->state.Ctx[I915_CTXREG_LIS5] = 0;
+
+      if (screen->cpp == 2)     /* XXX FBO fix */
+         i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
+
+
+      i915->state.Ctx[I915_CTXREG_LIS6] = (S6_COLOR_WRITE_ENABLE |
+                                           (2 << S6_TRISTRIP_PV_SHIFT));
+
+      i915->state.Ctx[I915_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD |
+                                             ENABLE_LOGIC_OP_FUNC |
+                                             LOGIC_OP_FUNC(LOGICOP_COPY) |
+                                             ENABLE_STENCIL_TEST_MASK |
+                                             STENCIL_TEST_MASK(0xff) |
+                                             ENABLE_STENCIL_WRITE_MASK |
+                                             STENCIL_WRITE_MASK(0xff));
+
+      i915->state.Ctx[I915_CTXREG_IAB] =
+         (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE |
+          IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR);
+
+      i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] =
+         _3DSTATE_CONST_BLEND_COLOR_CMD;
+      i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
+
+   }
+
+   {
+      I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
+      i915->state.Stipple[I915_STPREG_ST0] = _3DSTATE_STIPPLE;
+   }
+
+
+   {
+      I915_STATECHANGE(i915, I915_UPLOAD_FOG);
+      i915->state.Fog[I915_FOGREG_MODE0] = _3DSTATE_FOG_MODE_CMD;
+      i915->state.Fog[I915_FOGREG_MODE1] = (FMC1_FOGFUNC_MODIFY_ENABLE |
+                                            FMC1_FOGFUNC_VERTEX |
+                                            FMC1_FOGINDEX_MODIFY_ENABLE |
+                                            FMC1_FOGINDEX_W |
+                                            FMC1_C1_C2_MODIFY_ENABLE |
+                                            FMC1_DENSITY_MODIFY_ENABLE);
+      i915->state.Fog[I915_FOGREG_COLOR] = _3DSTATE_FOG_COLOR_CMD;
+   }
+
+
+   {
+      I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
+      /* color buffer offset/stride */
+      i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+      /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */
+      i915->state.Buffer[I915_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(screen->front.pitch) |  /* pitch in bytes */
+                                                    BUF_3D_USE_FENCE);
+
+      i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+      /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */
+      i915->state.Buffer[I915_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | BUF_3D_PITCH(screen->depth.pitch) |       /* pitch in bytes */
+                                                    BUF_3D_USE_FENCE);
+
+      i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
+
+      /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */
+#if 0                           /* seems we don't need this */
+      switch (screen->fbFormat) {
+      case DV_PF_565:
+         i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |        /* .5 */
+                                                 DSTORG_VERT_BIAS(0x8) |        /* .5 */
+                                                 LOD_PRECLAMP_OGL |
+                                                 TEX_DEFAULT_COLOR_OGL |
+                                                 DITHER_FULL_ALWAYS |
+                                                 screen->fbFormat |
+                                                 DEPTH_FRMT_16_FIXED);
+         break;
+      case DV_PF_8888:
+         i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |        /* .5 */
+                                                 DSTORG_VERT_BIAS(0x8) |        /* .5 */
+                                                 LOD_PRECLAMP_OGL |
+                                                 TEX_DEFAULT_COLOR_OGL |
+                                                 screen->fbFormat |
+                                                 DEPTH_FRMT_24_FIXED_8_OTHER);
+         break;
+      }
+#endif
+
+
+      /* scissor */
+      i915->state.Buffer[I915_DESTREG_SENABLE] =
+         (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+      i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD;
+      i915->state.Buffer[I915_DESTREG_SR1] = 0;
+      i915->state.Buffer[I915_DESTREG_SR2] = 0;
+   }
+
+
+#if 0
+   {
+      I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS);
+      i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE;
+      i915->state.Default[I915_DEFREG_C1] = 0;
+      i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR;
+      i915->state.Default[I915_DEFREG_S1] = 0;
+      i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z;
+      i915->state.Default[I915_DEFREG_Z1] = 0;
+   }
+#endif
+
+
+   /* These will be emitted every at the head of every buffer, unless
+    * we get hardware contexts working.
+    */
+   i915->state.active = (I915_UPLOAD_PROGRAM |
+                         I915_UPLOAD_STIPPLE |
+                         I915_UPLOAD_CTX |
+                         I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT);
+}
+
+void
+i915InitStateFunctions(struct dd_function_table *functions)
+{
+   functions->AlphaFunc = i915AlphaFunc;
+   functions->BlendColor = i915BlendColor;
+   functions->BlendEquationSeparate = i915BlendEquationSeparate;
+   functions->BlendFuncSeparate = i915BlendFuncSeparate;
+   functions->ColorMask = i915ColorMask;
+   functions->CullFace = i915CullFaceFrontFace;
+   functions->DepthFunc = i915DepthFunc;
+   functions->DepthMask = i915DepthMask;
+   functions->Enable = i915Enable;
+   functions->Fogfv = i915Fogfv;
+   functions->FrontFace = i915CullFaceFrontFace;
+   functions->Hint = i915Hint;
+   functions->LightModelfv = i915LightModelfv;
+   functions->LineWidth = i915LineWidth;
+   functions->LogicOpcode = i915LogicOp;
+   functions->PointSize = i915PointSize;
+   functions->PolygonStipple = i915PolygonStipple;
+   functions->Scissor = i915Scissor;
+   functions->ShadeModel = i915ShadeModel;
+   functions->StencilFuncSeparate = i915StencilFuncSeparate;
+   functions->StencilMaskSeparate = i915StencilMaskSeparate;
+   functions->StencilOpSeparate = i915StencilOpSeparate;
+}
+
+
+void
+i915InitState(struct i915_context *i915)
+{
+   GLcontext *ctx = &i915->intel.ctx;
+
+   i915_init_packets(i915);
+
+   intelInitState(ctx);
+
+   memcpy(&i915->initial, &i915->state, sizeof(i915->state));
+   i915->current = &i915->state;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_tex.c b/src/mesa/drivers/dri/i915tex/i915_tex.c
new file mode 100644 (file)
index 0000000..a53abe9
--- /dev/null
@@ -0,0 +1,113 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "image.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "texmem.h"
+#include "swrast/swrast.h"
+
+#include "mm.h"
+
+#include "intel_ioctl.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+
+
+static void
+i915TexEnv(GLcontext * ctx, GLenum target,
+           GLenum pname, const GLfloat * param)
+{
+   struct i915_context *i915 = I915_CONTEXT(ctx);
+
+   switch (pname) {
+   case GL_TEXTURE_ENV_COLOR:  /* Should be a tracked param */
+   case GL_TEXTURE_ENV_MODE:
+   case GL_COMBINE_RGB:
+   case GL_COMBINE_ALPHA:
+   case GL_SOURCE0_RGB:
+   case GL_SOURCE1_RGB:
+   case GL_SOURCE2_RGB:
+   case GL_SOURCE0_ALPHA:
+   case GL_SOURCE1_ALPHA:
+   case GL_SOURCE2_ALPHA:
+   case GL_OPERAND0_RGB:
+   case GL_OPERAND1_RGB:
+   case GL_OPERAND2_RGB:
+   case GL_OPERAND0_ALPHA:
+   case GL_OPERAND1_ALPHA:
+   case GL_OPERAND2_ALPHA:
+   case GL_RGB_SCALE:
+   case GL_ALPHA_SCALE:
+      i915->tex_program.translated = 0;
+      break;
+
+   case GL_TEXTURE_LOD_BIAS:{
+         GLuint unit = ctx->Texture.CurrentUnit;
+         GLint b = (int) ((*param) * 16.0);
+         if (b > 255)
+            b = 255;
+         if (b < -256)
+            b = -256;
+         I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
+         i915->lodbias_ss2[unit] =
+            ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
+         break;
+      }
+
+   default:
+      break;
+   }
+}
+
+
+static void
+i915BindTexture(GLcontext * ctx, GLenum target,
+                struct gl_texture_object *texobj)
+{
+   /* Need this if image format changes between bound textures.
+    * Could try and shortcircuit by checking for differences in
+    * state between incoming and outgoing textures:
+    */
+   I915_CONTEXT(ctx)->tex_program.translated = 0;
+}
+
+
+
+void
+i915InitTextureFuncs(struct dd_function_table *functions)
+{
+   functions->BindTexture = i915BindTexture;
+   functions->TexEnv = i915TexEnv;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_tex_layout.c b/src/mesa/drivers/dri/i915tex/i915_tex_layout.c
new file mode 100644 (file)
index 0000000..e9360ec
--- /dev/null
@@ -0,0 +1,380 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/* Code to layout images in a mipmap tree for i915 and i945
+ * respectively.
+ */
+
+#include "intel_mipmap_tree.h"
+#include "macros.h"
+#include "intel_context.h"
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+static GLint initial_offsets[6][2] = { {0, 0},
+{0, 2},
+{1, 0},
+{1, 2},
+{1, 1},
+{1, 3}
+};
+
+
+static GLint step_offsets[6][2] = { {0, 2},
+{0, 2},
+{-1, 2},
+{-1, 2},
+{-1, 1},
+{-1, 1}
+};
+
+static GLuint
+minify(GLuint d)
+{
+   return MAX2(1, d >> 1);
+}
+
+GLboolean
+i915_miptree_layout(struct intel_mipmap_tree * mt)
+{
+   GLint level;
+
+   switch (mt->target) {
+   case GL_TEXTURE_CUBE_MAP:{
+         const GLuint dim = mt->width0;
+         GLuint face;
+
+         /* double pitch for cube layouts */
+         mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
+         mt->total_height = dim * 4;
+
+         for (level = mt->first_level; level <= mt->last_level; level++)
+            intel_miptree_set_level_info(mt, level, 6,
+                                         0, 0,
+                                         mt->pitch, mt->total_height, 1);
+
+         for (face = 0; face < 6; face++) {
+            GLuint x = initial_offsets[face][0] * dim;
+            GLuint y = initial_offsets[face][1] * dim;
+            GLuint d = dim;
+
+            for (level = mt->first_level; level <= mt->last_level; level++) {
+               intel_miptree_set_image_offset(mt, level, face, x, y);
+
+               if (d == 0)
+                  _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
+                               face, level, mt->first_level, mt->last_level);
+
+               d >>= 1;
+               x += step_offsets[face][0] * d;
+               y += step_offsets[face][1] * d;
+            }
+         }
+         break;
+      }
+   case GL_TEXTURE_3D:{
+         GLuint width = mt->width0;
+         GLuint height = mt->height0;
+         GLuint depth = mt->depth0;
+         GLuint stack_height = 0;
+
+         /* Calculate the size of a single slice. 
+          */
+         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+
+         /* XXX: hardware expects/requires 9 levels at minimum.
+          */
+         for (level = mt->first_level; level <= MAX2(8, mt->last_level);
+              level++) {
+            intel_miptree_set_level_info(mt, level, 1, 0, mt->total_height,
+                                         width, height, depth);
+
+
+            stack_height += MAX2(2, height);
+
+            width = minify(width);
+            height = minify(height);
+            depth = minify(depth);
+         }
+
+         /* Fixup depth image_offsets: 
+          */
+         depth = mt->depth0;
+         for (level = mt->first_level; level <= mt->last_level; level++) {
+            GLuint i;
+            for (i = 0; i < depth; i++) 
+               intel_miptree_set_image_offset(mt, level, i,
+                                              0, i * stack_height);
+
+            depth = minify(depth);
+         }
+
+
+         /* Multiply slice size by texture depth for total size.  It's
+          * remarkable how wasteful of memory the i915 texture layouts
+          * are.  They are largely fixed in the i945.
+          */
+         mt->total_height = stack_height * mt->depth0;
+         break;
+      }
+
+   default:{
+         GLuint width = mt->width0;
+         GLuint height = mt->height0;
+        GLuint img_height;
+
+         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+         mt->total_height = 0;
+
+         for (level = mt->first_level; level <= mt->last_level; level++) {
+            intel_miptree_set_level_info(mt, level, 1,
+                                         0, mt->total_height,
+                                         width, height, 1);
+
+            if (mt->compressed)
+               img_height = MAX2(1, height / 4);
+            else
+               img_height = MAX2(2, height);
+
+           mt->total_height += img_height;
+           mt->total_height += 1;
+           mt->total_height &= ~1;
+
+            width = minify(width);
+            height = minify(height);
+         }
+         break;
+      }
+   }
+   DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
+       mt->pitch,
+       mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp);
+
+   return GL_TRUE;
+}
+
+
+GLboolean
+i945_miptree_layout(struct intel_mipmap_tree * mt)
+{
+   GLint level;
+
+   switch (mt->target) {
+   case GL_TEXTURE_CUBE_MAP:{
+         const GLuint dim = mt->width0;
+         GLuint face;
+
+         /* Depending on the size of the largest images, pitch can be
+          * determined either by the old-style packing of cubemap faces,
+          * or the final row of 4x4, 2x2 and 1x1 faces below this. 
+          */
+         if (dim > 32)
+            mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
+         else
+            mt->pitch = 14 * 8;
+
+         mt->total_height = dim * 4 + 4;
+
+         /* Set all the levels to effectively occupy the whole rectangular region. 
+          */
+         for (level = mt->first_level; level <= mt->last_level; level++)
+            intel_miptree_set_level_info(mt, level, 6,
+                                         0, 0,
+                                         mt->pitch, mt->total_height, 1);
+
+
+
+         for (face = 0; face < 6; face++) {
+            GLuint x = initial_offsets[face][0] * dim;
+            GLuint y = initial_offsets[face][1] * dim;
+            GLuint d = dim;
+
+            if (dim == 4 && face >= 4) {
+               y = mt->total_height - 4;
+               x = (face - 4) * 8;
+            }
+            else if (dim < 4) {
+               y = mt->total_height - 4;
+               x = face * 8;
+            }
+
+            for (level = mt->first_level; level <= mt->last_level; level++) {
+               intel_miptree_set_image_offset(mt, level, face, x, y);
+
+               d >>= 1;
+
+               switch (d) {
+               case 4:
+                  switch (face) {
+                  case FACE_POS_X:
+                  case FACE_NEG_X:
+                     x += step_offsets[face][0] * d;
+                     y += step_offsets[face][1] * d;
+                     break;
+                  case FACE_POS_Y:
+                  case FACE_NEG_Y:
+                     y += 12;
+                     x -= 8;
+                     break;
+                  case FACE_POS_Z:
+                  case FACE_NEG_Z:
+                     y = mt->total_height - 4;
+                     x = (face - 4) * 8;
+                     break;
+                  }
+
+               case 2:
+                  y = mt->total_height - 4;
+                  x = 16 + face * 8;
+                  break;
+
+               case 1:
+                  x += 48;
+                  break;
+
+               default:
+                  x += step_offsets[face][0] * d;
+                  y += step_offsets[face][1] * d;
+                  break;
+               }
+            }
+         }
+         break;
+      }
+   case GL_TEXTURE_3D:{
+         GLuint width = mt->width0;
+         GLuint height = mt->height0;
+         GLuint depth = mt->depth0;
+         GLuint pack_x_pitch, pack_x_nr;
+         GLuint pack_y_pitch;
+         GLuint level;
+
+         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+         mt->total_height = 0;
+
+         pack_y_pitch = MAX2(mt->height0, 2);
+         pack_x_pitch = mt->pitch;
+         pack_x_nr = 1;
+
+         for (level = mt->first_level; level <= mt->last_level; level++) {
+            GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
+            GLint x = 0;
+            GLint y = 0;
+            GLint q, j;
+
+            intel_miptree_set_level_info(mt, level, nr_images,
+                                         0, mt->total_height,
+                                         width, height, depth);
+
+            for (q = 0; q < nr_images;) {
+               for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
+                  intel_miptree_set_image_offset(mt, level, q, x, y);
+                  x += pack_x_pitch;
+               }
+
+               x = 0;
+               y += pack_y_pitch;
+            }
+
+
+            mt->total_height += y;
+
+            if (pack_x_pitch > 4) {
+               pack_x_pitch >>= 1;
+               pack_x_nr <<= 1;
+               assert(pack_x_pitch * pack_x_nr <= mt->pitch);
+            }
+
+            if (pack_y_pitch > 2) {
+               pack_y_pitch >>= 1;
+            }
+
+            width = minify(width);
+            height = minify(height);
+            depth = minify(depth);
+         }
+         break;
+      }
+
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_RECTANGLE_ARB:{
+         GLuint x = 0;
+         GLuint y = 0;
+         GLuint width = mt->width0;
+         GLuint height = mt->height0;
+        GLint align_h = 2;
+
+         mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+         mt->total_height = 0;
+
+         for (level = mt->first_level; level <= mt->last_level; level++) {
+           GLuint img_height;
+
+            intel_miptree_set_level_info(mt, level, 1,
+                                         x, y, 
+                                        width, 
+                                        mt->compressed ? height/4 : height, 1);
+
+
+           if (mt->compressed)
+               img_height = MAX2(1, height / 4);
+            else
+               img_height = MAX2(align_h, height);
+
+            /* LPT change: step right after second mipmap.
+             */
+            if (level == mt->first_level + 1) {
+               x += mt->pitch / 2;
+              x = (x + 3) & ~3;
+           }
+            else {
+              y += img_height;
+              y += align_h - 1;
+              y &= ~(align_h - 1);
+           }
+
+            /* Because the images are packed better, the final offset
+             * might not be the maximal one:
+             */
+            mt->total_height = MAX2(mt->total_height, y);
+
+            width = minify(width);
+            height = minify(height);
+         }
+         break;
+      }
+   default:
+      _mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
+   }
+
+   DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
+       mt->pitch,
+       mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp);
+
+   return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_texstate.c b/src/mesa/drivers/dri/i915tex/i915_texstate.c
new file mode 100644 (file)
index 0000000..e0ecdfd
--- /dev/null
@@ -0,0 +1,338 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "mtypes.h"
+#include "enums.h"
+#include "texformat.h"
+#include "dri_bufmgr.h"
+
+#include "intel_mipmap_tree.h"
+#include "intel_tex.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+
+static GLuint
+translate_texture_format(GLuint mesa_format)
+{
+   switch (mesa_format) {
+   case MESA_FORMAT_L8:
+      return MAPSURF_8BIT | MT_8BIT_L8;
+   case MESA_FORMAT_I8:
+      return MAPSURF_8BIT | MT_8BIT_I8;
+   case MESA_FORMAT_A8:
+      return MAPSURF_8BIT | MT_8BIT_A8;
+   case MESA_FORMAT_AL88:
+      return MAPSURF_16BIT | MT_16BIT_AY88;
+   case MESA_FORMAT_RGB565:
+      return MAPSURF_16BIT | MT_16BIT_RGB565;
+   case MESA_FORMAT_ARGB1555:
+      return MAPSURF_16BIT | MT_16BIT_ARGB1555;
+   case MESA_FORMAT_ARGB4444:
+      return MAPSURF_16BIT | MT_16BIT_ARGB4444;
+   case MESA_FORMAT_ARGB8888:
+      return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+   case MESA_FORMAT_YCBCR_REV:
+      return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
+   case MESA_FORMAT_YCBCR:
+      return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
+   case MESA_FORMAT_RGB_FXT1:
+   case MESA_FORMAT_RGBA_FXT1:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
+   case MESA_FORMAT_Z16:
+      return (MAPSURF_16BIT | MT_16BIT_L16);
+   case MESA_FORMAT_RGBA_DXT1:
+   case MESA_FORMAT_RGB_DXT1:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
+   case MESA_FORMAT_RGBA_DXT3:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
+   case MESA_FORMAT_RGBA_DXT5:
+      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
+   case MESA_FORMAT_Z24_S8:
+      return (MAPSURF_32BIT | MT_32BIT_xL824);
+   default:
+      fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
+      abort();
+      return 0;
+   }
+}
+
+
+
+
+/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
+ * Intel drivers for "other operating systems" implement GL_CLAMP as
+ * GL_CLAMP_TO_EDGE, so the same is done here.
+ */
+static GLuint
+translate_wrap_mode(GLenum wrap)
+{
+   switch (wrap) {
+   case GL_REPEAT:
+      return TEXCOORDMODE_WRAP;
+   case GL_CLAMP:
+      return TEXCOORDMODE_CLAMP_EDGE;   /* not quite correct */
+   case GL_CLAMP_TO_EDGE:
+      return TEXCOORDMODE_CLAMP_EDGE;
+   case GL_CLAMP_TO_BORDER:
+      return TEXCOORDMODE_CLAMP_BORDER;
+   case GL_MIRRORED_REPEAT:
+      return TEXCOORDMODE_MIRROR;
+   default:
+      return TEXCOORDMODE_WRAP;
+   }
+}
+
+
+
+/* Recalculate all state from scratch.  Perhaps not the most
+ * efficient, but this has gotten complex enough that we need
+ * something which is understandable and reliable.
+ */
+static GLboolean
+i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
+{
+   GLcontext *ctx = &intel->ctx;
+   struct i915_context *i915 = i915_context(ctx);
+   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
+   struct intel_texture_object *intelObj = intel_texture_object(tObj);
+   struct gl_texture_image *firstImage;
+   GLuint *state = i915->state.Tex[unit];
+
+   memset(state, 0, sizeof(state));
+
+   /*We need to refcount these. */
+
+   if (i915->state.tex_buffer[unit] != NULL) {
+       driBOUnReference(i915->state.tex_buffer[unit]);
+       i915->state.tex_buffer[unit] = NULL;
+   }
+
+   if (!intel_finalize_mipmap_tree(intel, unit))
+      return GL_FALSE;
+
+   /* Get first image here, since intelObj->firstLevel will get set in
+    * the intel_finalize_mipmap_tree() call above.
+    */
+   firstImage = tObj->Image[0][intelObj->firstLevel];
+
+   i915->state.tex_buffer[unit] = driBOReference(intelObj->mt->region->buffer);
+   i915->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0,
+                                                             intelObj->
+                                                             firstLevel);
+
+   state[I915_TEXREG_MS3] =
+      (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
+       ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) |
+       translate_texture_format(firstImage->TexFormat->MesaFormat) |
+       MS3_USE_FENCE_REGS);
+
+   state[I915_TEXREG_MS4] =
+      (((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) -
+         1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK |
+       ((((intelObj->lastLevel -
+           intelObj->firstLevel) *
+          4)) << MS4_MAX_LOD_SHIFT) | ((firstImage->Depth -
+                                        1) << MS4_VOLUME_DEPTH_SHIFT));
+
+
+   {
+      GLuint minFilt, mipFilt, magFilt;
+
+      switch (tObj->MinFilter) {
+      case GL_NEAREST:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_NONE;
+         break;
+      case GL_LINEAR:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_NONE;
+         break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_NEAREST;
+         break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_NEAREST;
+         break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+         minFilt = FILTER_NEAREST;
+         mipFilt = MIPFILTER_LINEAR;
+         break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+         minFilt = FILTER_LINEAR;
+         mipFilt = MIPFILTER_LINEAR;
+         break;
+      default:
+         return GL_FALSE;
+      }
+
+      if (tObj->MaxAnisotropy > 1.0) {
+         minFilt = FILTER_ANISOTROPIC;
+         magFilt = FILTER_ANISOTROPIC;
+      }
+      else {
+         switch (tObj->MagFilter) {
+         case GL_NEAREST:
+            magFilt = FILTER_NEAREST;
+            break;
+         case GL_LINEAR:
+            magFilt = FILTER_LINEAR;
+            break;
+         default:
+            return GL_FALSE;
+         }
+      }
+
+      state[I915_TEXREG_SS2] = i915->lodbias_ss2[unit];
+
+      /* YUV conversion:
+       */
+      if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
+          firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
+         state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION;
+
+      /* Shadow:
+       */
+      if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
+          tObj->Target != GL_TEXTURE_3D) {
+
+         state[I915_TEXREG_SS2] |=
+            (SS2_SHADOW_ENABLE |
+             intel_translate_compare_func(tObj->CompareFunc));
+
+         minFilt = FILTER_4X4_FLAT;
+         magFilt = FILTER_4X4_FLAT;
+      }
+
+      state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
+                                 (mipFilt << SS2_MIP_FILTER_SHIFT) |
+                                 (magFilt << SS2_MAG_FILTER_SHIFT));
+   }
+
+   {
+      GLenum ws = tObj->WrapS;
+      GLenum wt = tObj->WrapT;
+      GLenum wr = tObj->WrapR;
+
+
+      /* 3D textures don't seem to respect the border color.
+       * Fallback if there's ever a danger that they might refer to
+       * it.  
+       * 
+       * Effectively this means fallback on 3D clamp or
+       * clamp_to_border.
+       */
+      if (tObj->Target == GL_TEXTURE_3D &&
+          (tObj->MinFilter != GL_NEAREST ||
+           tObj->MagFilter != GL_NEAREST) &&
+          (ws == GL_CLAMP ||
+           wt == GL_CLAMP ||
+           wr == GL_CLAMP ||
+           ws == GL_CLAMP_TO_BORDER ||
+           wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
+         return GL_FALSE;
+
+
+      state[I915_TEXREG_SS3] = ss3;     /* SS3_NORMALIZED_COORDS */
+
+      state[I915_TEXREG_SS3] |=
+         ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
+          (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
+          (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
+
+      state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
+   }
+
+
+   state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
+                                                tObj->_BorderChan[1],
+                                                tObj->_BorderChan[2],
+                                                tObj->_BorderChan[3]);
+
+
+   I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
+   /* memcmp was already disabled, but definitely won't work as the
+    * region might now change and that wouldn't be detected:
+    */
+   I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
+
+
+#if 0
+   DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]);
+   DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]);
+   DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]);
+   DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]);
+   DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]);
+   DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
+#endif
+
+   return GL_TRUE;
+}
+
+
+
+
+void
+i915UpdateTextureState(struct intel_context *intel)
+{
+   GLboolean ok = GL_TRUE;
+   GLuint i;
+
+   for (i = 0; i < I915_TEX_UNITS && ok; i++) {
+      switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
+      case TEXTURE_1D_BIT:
+      case TEXTURE_2D_BIT:
+      case TEXTURE_CUBE_BIT:
+      case TEXTURE_3D_BIT:
+         ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS);
+         break;
+      case TEXTURE_RECT_BIT:
+         ok = i915_update_tex_unit(intel, i, 0);
+         break;
+      case 0:{
+            struct i915_context *i915 = i915_context(&intel->ctx);
+            if (i915->state.active & I915_UPLOAD_TEX(i))
+               I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE);
+
+           if (i915->state.tex_buffer[i] != NULL) {
+              driBOUnReference(i915->state.tex_buffer[i]);
+              i915->state.tex_buffer[i] = NULL;
+           }
+
+            break;
+         }
+      default:
+         ok = GL_FALSE;
+         break;
+      }
+   }
+
+   FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok);
+}
diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c
new file mode 100644 (file)
index 0000000..827990d
--- /dev/null
@@ -0,0 +1,549 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "tnl/t_context.h"
+#include "tnl/t_vertex.h"
+
+#include "intel_batchbuffer.h"
+#include "intel_tex.h"
+#include "intel_regions.h"
+
+#include "i915_reg.h"
+#include "i915_context.h"
+
+static void
+i915_render_start(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+
+   i915ValidateFragmentProgram(i915);
+}
+
+
+static void
+i915_reduced_primitive_state(struct intel_context *intel, GLenum rprim)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
+
+   st1 &= ~ST1_ENABLE;
+
+   switch (rprim) {
+   case GL_TRIANGLES:
+      if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple)
+         st1 |= ST1_ENABLE;
+      break;
+   case GL_LINES:
+   case GL_POINTS:
+   default:
+      break;
+   }
+
+   i915->intel.reduced_primitive = rprim;
+
+   if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
+      INTEL_FIREVERTICES(intel);
+
+      I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
+      i915->state.Stipple[I915_STPREG_ST1] = st1;
+   }
+}
+
+
+/* Pull apart the vertex format registers and figure out how large a
+ * vertex is supposed to be. 
+ */
+static GLboolean
+i915_check_vertex_size(struct intel_context *intel, GLuint expected)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   int lis2 = i915->current->Ctx[I915_CTXREG_LIS2];
+   int lis4 = i915->current->Ctx[I915_CTXREG_LIS4];
+   int i, sz = 0;
+
+   switch (lis4 & S4_VFMT_XYZW_MASK) {
+   case S4_VFMT_XY:
+      sz = 2;
+      break;
+   case S4_VFMT_XYZ:
+      sz = 3;
+      break;
+   case S4_VFMT_XYW:
+      sz = 3;
+      break;
+   case S4_VFMT_XYZW:
+      sz = 4;
+      break;
+   default:
+      fprintf(stderr, "no xyzw specified\n");
+      return 0;
+   }
+
+   if (lis4 & S4_VFMT_SPEC_FOG)
+      sz++;
+   if (lis4 & S4_VFMT_COLOR)
+      sz++;
+   if (lis4 & S4_VFMT_DEPTH_OFFSET)
+      sz++;
+   if (lis4 & S4_VFMT_POINT_WIDTH)
+      sz++;
+   if (lis4 & S4_VFMT_FOG_PARAM)
+      sz++;
+
+   for (i = 0; i < 8; i++) {
+      switch (lis2 & S2_TEXCOORD_FMT0_MASK) {
+      case TEXCOORDFMT_2D:
+         sz += 2;
+         break;
+      case TEXCOORDFMT_3D:
+         sz += 3;
+         break;
+      case TEXCOORDFMT_4D:
+         sz += 4;
+         break;
+      case TEXCOORDFMT_1D:
+         sz += 1;
+         break;
+      case TEXCOORDFMT_2D_16:
+         sz += 1;
+         break;
+      case TEXCOORDFMT_4D_16:
+         sz += 2;
+         break;
+      case TEXCOORDFMT_NOT_PRESENT:
+         break;
+      default:
+         fprintf(stderr, "bad texcoord fmt %d\n", i);
+         return GL_FALSE;
+      }
+      lis2 >>= S2_TEXCOORD_FMT1_SHIFT;
+   }
+
+   if (sz != expected)
+      fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected);
+
+   return sz == expected;
+}
+
+
+static void
+i915_emit_invarient_state(struct intel_context *intel)
+{
+   BATCH_LOCALS;
+
+   BEGIN_BATCH(200, 0);
+
+   OUT_BATCH(_3DSTATE_AA_CMD |
+             AA_LINE_ECAAR_WIDTH_ENABLE |
+             AA_LINE_ECAAR_WIDTH_1_0 |
+             AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
+
+   OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
+   OUT_BATCH(0);
+
+   OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
+   OUT_BATCH(0);
+
+   OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
+   OUT_BATCH(0);
+
+   /* Don't support texture crossbar yet */
+   OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS |
+             CSB_TCB(0, 0) |
+             CSB_TCB(1, 1) |
+             CSB_TCB(2, 2) |
+             CSB_TCB(3, 3) |
+             CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
+
+   OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
+             ENABLE_POINT_RASTER_RULE |
+             OGL_POINT_RASTER_RULE |
+             ENABLE_LINE_STRIP_PROVOKE_VRTX |
+             ENABLE_TRI_FAN_PROVOKE_VRTX |
+             LINE_STRIP_PROVOKE_VRTX(1) |
+             TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
+
+   /* Need to initialize this to zero.
+    */
+   OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (1));
+   OUT_BATCH(0);
+
+   /* XXX: Use this */
+   OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
+
+   OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
+   OUT_BATCH(0);
+   OUT_BATCH(0);
+
+   OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
+
+   OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0);       /* disable indirect state */
+   OUT_BATCH(0);
+
+
+   /* Don't support twosided stencil yet */
+   OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
+
+   ADVANCE_BATCH();
+}
+
+
+#define emit(intel, state, size )                   \
+   intel_batchbuffer_data(intel->batch, state, size, 0 )
+
+static GLuint
+get_dirty(struct i915_hw_state *state)
+{
+   GLuint dirty;
+
+   /* Workaround the multitex hang - if one texture unit state is
+    * modified, emit all texture units.
+    */
+   dirty = state->active & ~state->emitted;
+   if (dirty & I915_UPLOAD_TEX_ALL)
+      state->emitted &= ~I915_UPLOAD_TEX_ALL;
+   dirty = state->active & ~state->emitted;
+   return dirty;
+}
+
+
+static GLuint
+get_state_size(struct i915_hw_state *state)
+{
+   GLuint dirty = get_dirty(state);
+   GLuint i;
+   GLuint sz = 0;
+
+   if (dirty & I915_UPLOAD_CTX)
+      sz += sizeof(state->Ctx);
+
+   if (dirty & I915_UPLOAD_BUFFERS)
+      sz += sizeof(state->Buffer);
+
+   if (dirty & I915_UPLOAD_STIPPLE)
+      sz += sizeof(state->Stipple);
+
+   if (dirty & I915_UPLOAD_FOG)
+      sz += sizeof(state->Fog);
+
+   if (dirty & I915_UPLOAD_TEX_ALL) {
+      int nr = 0;
+      for (i = 0; i < I915_TEX_UNITS; i++)
+         if (dirty & I915_UPLOAD_TEX(i))
+            nr++;
+
+      sz += (2 + nr * 3) * sizeof(GLuint) * 2;
+   }
+
+   if (dirty & I915_UPLOAD_CONSTANTS)
+      sz += state->ConstantSize * sizeof(GLuint);
+
+   if (dirty & I915_UPLOAD_PROGRAM)
+      sz += state->ProgramSize * sizeof(GLuint);
+
+   return sz;
+}
+
+
+/* Push the state into the sarea and/or texture memory.
+ */
+static void
+i915_emit_state(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   struct i915_hw_state *state = i915->current;
+   int i;
+   GLuint dirty;
+   BATCH_LOCALS;
+
+   /* We don't hold the lock at this point, so want to make sure that
+    * there won't be a buffer wrap.  
+    *
+    * It might be better to talk about explicit places where
+    * scheduling is allowed, rather than assume that it is whenever a
+    * batchbuffer fills up.
+    */
+   intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
+
+   /* Do this here as we may have flushed the batchbuffer above,
+    * causing more state to be dirty!
+    */
+   dirty = get_dirty(state);
+
+   if (INTEL_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
+
+   if (dirty & I915_UPLOAD_INVARIENT) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");
+      i915_emit_invarient_state(intel);
+   }
+
+   if (dirty & I915_UPLOAD_CTX) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_CTX:\n");
+      emit(intel, state->Ctx, sizeof(state->Ctx));
+   }
+
+   if (dirty & I915_UPLOAD_BUFFERS) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
+      BEGIN_BATCH(I915_DEST_SETUP_SIZE + 2, 0);
+      OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]);
+      OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]);
+      OUT_RELOC(state->draw_region->buffer,
+                DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
+                state->draw_region->draw_offset);
+
+      if (state->depth_region) {
+         OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]);
+         OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
+         OUT_RELOC(state->depth_region->buffer,
+                   DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                   DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
+                   state->depth_region->draw_offset);
+      }
+
+      OUT_BATCH(state->Buffer[I915_DESTREG_DV0]);
+      OUT_BATCH(state->Buffer[I915_DESTREG_DV1]);
+      OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]);
+      OUT_BATCH(state->Buffer[I915_DESTREG_SR0]);
+      OUT_BATCH(state->Buffer[I915_DESTREG_SR1]);
+      OUT_BATCH(state->Buffer[I915_DESTREG_SR2]);
+      ADVANCE_BATCH();
+   }
+
+   if (dirty & I915_UPLOAD_STIPPLE) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
+      emit(intel, state->Stipple, sizeof(state->Stipple));
+   }
+
+   if (dirty & I915_UPLOAD_FOG) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_FOG:\n");
+      emit(intel, state->Fog, sizeof(state->Fog));
+   }
+
+   /* Combine all the dirty texture state into a single command to
+    * avoid lockups on I915 hardware. 
+    */
+   if (dirty & I915_UPLOAD_TEX_ALL) {
+      int nr = 0;
+
+      for (i = 0; i < I915_TEX_UNITS; i++)
+         if (dirty & I915_UPLOAD_TEX(i))
+            nr++;
+
+      BEGIN_BATCH(2 + nr * 3, 0);
+      OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr));
+      OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
+      for (i = 0; i < I915_TEX_UNITS; i++)
+         if (dirty & I915_UPLOAD_TEX(i)) {
+
+            if (state->tex_buffer[i]) {
+               OUT_RELOC(state->tex_buffer[i],
+                         DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                         DRM_BO_MASK_MEM | DRM_BO_FLAG_READ,
+                         state->tex_offset[i]);
+            }
+            else {
+               assert(i == 0);
+               assert(state == &i915->meta);
+               OUT_BATCH(0);
+            }
+
+            OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
+            OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
+         }
+      ADVANCE_BATCH();
+
+      BEGIN_BATCH(2 + nr * 3, 0);
+      OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr));
+      OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
+      for (i = 0; i < I915_TEX_UNITS; i++)
+         if (dirty & I915_UPLOAD_TEX(i)) {
+            OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]);
+            OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]);
+            OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]);
+         }
+      ADVANCE_BATCH();
+   }
+
+   if (dirty & I915_UPLOAD_CONSTANTS) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
+      emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint));
+   }
+
+   if (dirty & I915_UPLOAD_PROGRAM) {
+      if (INTEL_DEBUG & DEBUG_STATE)
+         fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
+
+      assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize);
+
+      emit(intel, state->Program, state->ProgramSize * sizeof(GLuint));
+      if (INTEL_DEBUG & DEBUG_STATE)
+         i915_disassemble_program(state->Program, state->ProgramSize);
+   }
+
+   state->emitted |= dirty;
+}
+
+static void
+i915_destroy_context(struct intel_context *intel)
+{
+   _tnl_free_vertices(&intel->ctx);
+}
+
+
+/**
+ * Set the drawing regions for the color and depth/stencil buffers.
+ * This involves setting the pitch, cpp and buffer ID/location.
+ * Also set pixel format for color and Z rendering
+ * Used for setting both regular and meta state.
+ */
+void
+i915_state_draw_region(struct intel_context *intel,
+                       struct i915_hw_state *state,
+                       struct intel_region *color_region,
+                       struct intel_region *depth_region)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   GLuint value;
+
+   ASSERT(state == &i915->state || state == &i915->meta);
+
+   if (state->draw_region != color_region) {
+      intel_region_release(&state->draw_region);
+      intel_region_reference(&state->draw_region, color_region);
+   }
+   if (state->depth_region != depth_region) {
+      intel_region_release(&state->depth_region);
+      intel_region_reference(&state->depth_region, depth_region);
+   }
+
+   /*
+    * Set stride/cpp values
+    */
+   if (color_region) {
+      state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+      state->Buffer[I915_DESTREG_CBUFADDR1] =
+         (BUF_3D_ID_COLOR_BACK |
+          BUF_3D_PITCH(color_region->pitch * color_region->cpp) |
+          BUF_3D_USE_FENCE);
+   }
+
+   if (depth_region) {
+      state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+      state->Buffer[I915_DESTREG_DBUFADDR1] =
+         (BUF_3D_ID_DEPTH |
+          BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) |
+          BUF_3D_USE_FENCE);
+   }
+
+   /*
+    * Compute/set I915_DESTREG_DV1 value
+    */
+   value = (DSTORG_HORT_BIAS(0x8) |     /* .5 */
+            DSTORG_VERT_BIAS(0x8) |     /* .5 */
+            LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL);
+   if (color_region && color_region->cpp == 4) {
+      value |= DV_PF_8888;
+   }
+   else {
+      value |= (DITHER_FULL_ALWAYS | DV_PF_565);
+   }
+   if (depth_region && depth_region->cpp == 4) {
+      value |= DEPTH_FRMT_24_FIXED_8_OTHER;
+   }
+   else {
+      value |= DEPTH_FRMT_16_FIXED;
+   }
+   state->Buffer[I915_DESTREG_DV1] = value;
+
+   I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
+}
+
+
+static void
+i915_set_draw_region(struct intel_context *intel,
+                     struct intel_region *color_region,
+                     struct intel_region *depth_region)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   i915_state_draw_region(intel, &i915->state, color_region, depth_region);
+}
+
+
+
+static void
+i915_lost_hardware(struct intel_context *intel)
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   i915->state.emitted = 0;
+}
+
+static GLuint
+i915_flush_cmd(void)
+{
+   return MI_FLUSH | FLUSH_MAP_CACHE;
+}
+
+static void 
+i915_assert_not_dirty( struct intel_context *intel )
+{
+   struct i915_context *i915 = i915_context(&intel->ctx);
+   struct i915_hw_state *state = i915->current;
+   GLuint dirty = get_dirty(state);
+   assert(!dirty);
+}
+
+
+void
+i915InitVtbl(struct i915_context *i915)
+{
+   i915->intel.vtbl.check_vertex_size = i915_check_vertex_size;
+   i915->intel.vtbl.destroy = i915_destroy_context;
+   i915->intel.vtbl.emit_state = i915_emit_state;
+   i915->intel.vtbl.lost_hardware = i915_lost_hardware;
+   i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state;
+   i915->intel.vtbl.render_start = i915_render_start;
+   i915->intel.vtbl.set_draw_region = i915_set_draw_region;
+   i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
+   i915->intel.vtbl.flush_cmd = i915_flush_cmd;
+   i915->intel.vtbl.assert_not_dirty = i915_assert_not_dirty;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.c
new file mode 100644 (file)
index 0000000..b4e0b74
--- /dev/null
@@ -0,0 +1,342 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "intel_batchbuffer.h"
+#include "intel_ioctl.h"
+
+/* Relocations in kernel space:
+ *    - pass dma buffer seperately
+ *    - memory manager knows how to patch
+ *    - pass list of dependent buffers
+ *    - pass relocation list
+ *
+ * Either:
+ *    - get back an offset for buffer to fire
+ *    - memory manager knows how to fire buffer
+ *
+ * Really want the buffer to be AGP and pinned.
+ *
+ */
+
+/* Cliprect fence: The highest fence protecting a dma buffer
+ * containing explicit cliprect information.  Like the old drawable
+ * lock but irq-driven.  X server must wait for this fence to expire
+ * before changing cliprects [and then doing sw rendering?].  For
+ * other dma buffers, the scheduler will grab current cliprect info
+ * and mix into buffer.  X server must hold the lock while changing
+ * cliprects???  Make per-drawable.  Need cliprects in shared memory
+ * -- beats storing them with every cmd buffer in the queue.
+ *
+ * ==> X server must wait for this fence to expire before touching the
+ * framebuffer with new cliprects.
+ *
+ * ==> Cliprect-dependent buffers associated with a
+ * cliprect-timestamp.  All of the buffers associated with a timestamp
+ * must go to hardware before any buffer with a newer timestamp.
+ *
+ * ==> Dma should be queued per-drawable for correct X/GL
+ * synchronization.  Or can fences be used for this?
+ *
+ * Applies to: Blit operations, metaops, X server operations -- X
+ * server automatically waits on its own dma to complete before
+ * modifying cliprects ???
+ */
+
+static void
+intel_dump_batchbuffer(GLuint offset, GLuint * ptr, GLuint count)
+{
+   int i;
+   fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4);
+   for (i = 0; i < count / 4; i += 4)
+      fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",
+              offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]);
+   fprintf(stderr, "END BATCH\n\n\n");
+}
+
+void
+intel_batchbuffer_reset(struct intel_batchbuffer *batch)
+{
+
+   int i;
+
+   /*
+    * Get a new, free batchbuffer.
+    */
+
+   batch->size =  batch->intel->intelScreen->maxBatchSize;
+   driBOData(batch->buffer, batch->size, NULL, 0);
+
+   driBOResetList(&batch->list);
+
+   /*
+    * Unreference buffers previously on the relocation list.
+    */
+
+   for (i = 0; i < batch->nr_relocs; i++) {
+      struct buffer_reloc *r = &batch->reloc[i];
+      driBOUnReference(r->buf);
+   }
+
+   batch->list_count = 0;
+   batch->nr_relocs = 0;
+   batch->flags = 0;
+
+   /*
+    * We don't refcount the batchbuffer itself since we can't destroy it
+    * while it's on the list.
+    */
+
+
+   driBOAddListItem(&batch->list, batch->buffer,
+                    DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE,
+                    DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE);
+
+
+   batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
+   batch->ptr = batch->map;
+}
+
+/*======================================================================
+ * Public functions
+ */
+struct intel_batchbuffer *
+intel_batchbuffer_alloc(struct intel_context *intel)
+{
+   struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
+
+   batch->intel = intel;
+
+   driGenBuffers(intel->intelScreen->batchPool, "batchbuffer", 1,
+                 &batch->buffer, 4096,
+                 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0);
+   batch->last_fence = NULL;
+   driBOCreateList(20, &batch->list);
+   intel_batchbuffer_reset(batch);
+   return batch;
+}
+
+void
+intel_batchbuffer_free(struct intel_batchbuffer *batch)
+{
+   if (batch->last_fence) {
+      driFenceFinish(batch->last_fence,
+      DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
+      driFenceUnReference(batch->last_fence);
+      batch->last_fence = NULL;
+   }
+   if (batch->map) {
+      driBOUnmap(batch->buffer);
+      batch->map = NULL;
+   }
+   driBOUnReference(batch->buffer);
+   batch->buffer = NULL;
+   free(batch);
+}
+
+/* TODO: Push this whole function into bufmgr.
+ */
+static void
+do_flush_locked(struct intel_batchbuffer *batch,
+                GLuint used,
+                GLboolean ignore_cliprects, GLboolean allow_unlock)
+{
+   GLuint *ptr;
+   GLuint i;
+   struct intel_context *intel = batch->intel;
+   unsigned fenceFlags;
+   struct _DriFenceObject *fo;
+
+   driBOValidateList(batch->intel->driFd, &batch->list);
+
+   /* Apply the relocations.  This nasty map indicates to me that the
+    * whole task should be done internally by the memory manager, and
+    * that dma buffers probably need to be pinned within agp space.
+    */
+   ptr = (GLuint *) driBOMap(batch->buffer, DRM_BO_FLAG_WRITE,
+                             DRM_BO_HINT_ALLOW_UNFENCED_MAP);
+
+
+   for (i = 0; i < batch->nr_relocs; i++) {
+      struct buffer_reloc *r = &batch->reloc[i];
+
+      ptr[r->offset / 4] = driBOOffset(r->buf) + r->delta;
+   }
+
+   if (INTEL_DEBUG & DEBUG_BATCH)
+      intel_dump_batchbuffer(0, ptr, used);
+
+   driBOUnmap(batch->buffer);
+   batch->map = NULL;
+
+   /* Throw away non-effective packets.  Won't work once we have
+    * hardware contexts which would preserve statechanges beyond a
+    * single buffer.
+    */
+
+   if (!(intel->numClipRects == 0 && !ignore_cliprects)) {
+      intel_batch_ioctl(batch->intel,
+                        driBOOffset(batch->buffer),
+                        used, ignore_cliprects, allow_unlock);
+   }
+
+
+   /*
+    * Kernel fencing. The flags tells the kernel that we've 
+    * programmed an MI_FLUSH.
+    */
+   
+   fenceFlags = DRM_I915_FENCE_FLAG_FLUSHED;
+   fo = driFenceBuffers(batch->intel->driFd,
+                       "Batch fence", fenceFlags);
+
+   /*
+    * User space fencing.
+    */
+
+   driBOFence(batch->buffer, fo);
+
+   if (driFenceType(fo) == DRM_FENCE_TYPE_EXE) {
+
+     /*
+      * Oops. We only validated a batch buffer. This means we
+      * didn't do any proper rendering. Discard this fence object.
+      */
+
+      driFenceUnReference(fo);
+   } else {
+      driFenceUnReference(batch->last_fence);
+      batch->last_fence = fo;
+      for (i = 0; i < batch->nr_relocs; i++) {
+       struct buffer_reloc *r = &batch->reloc[i];
+       driBOFence(r->buf, fo);
+      }
+   }
+
+   if (intel->numClipRects == 0 && !ignore_cliprects) {
+      if (allow_unlock) {
+         UNLOCK_HARDWARE(intel);
+         sched_yield();
+         LOCK_HARDWARE(intel);
+      }
+      intel->vtbl.lost_hardware(intel);
+   }
+}
+
+
+struct _DriFenceObject *
+intel_batchbuffer_flush(struct intel_batchbuffer *batch)
+{
+   struct intel_context *intel = batch->intel;
+   GLuint used = batch->ptr - batch->map;
+
+   if (used == 0)
+      return batch->last_fence;
+
+   /* Add the MI_BATCH_BUFFER_END.  Always add an MI_FLUSH - this is a
+    * performance drain that we would like to avoid.
+    */
+   if (used & 4) {
+      ((int *) batch->ptr)[0] = intel->vtbl.flush_cmd();
+      ((int *) batch->ptr)[1] = 0;
+      ((int *) batch->ptr)[2] = MI_BATCH_BUFFER_END;
+      used += 12;
+   }
+   else {
+      ((int *) batch->ptr)[0] = intel->vtbl.flush_cmd();
+      ((int *) batch->ptr)[1] = MI_BATCH_BUFFER_END;
+      used += 8;
+   }
+
+   driBOUnmap(batch->buffer);
+   batch->ptr = NULL;
+   batch->map = NULL;
+
+   /* TODO: Just pass the relocation list and dma buffer up to the
+    * kernel.
+    */
+   if (!intel->locked) {
+      assert(!(batch->flags & INTEL_BATCH_NO_CLIPRECTS));
+
+      LOCK_HARDWARE(intel);
+      do_flush_locked(batch, used, GL_FALSE, GL_TRUE);
+      UNLOCK_HARDWARE(intel);
+   }
+   else {
+      GLboolean ignore_cliprects = !(batch->flags & INTEL_BATCH_CLIPRECTS);
+      do_flush_locked(batch, used, ignore_cliprects, GL_FALSE);
+   }
+
+   /* Reset the buffer:
+    */
+   intel_batchbuffer_reset(batch);
+   return batch->last_fence;
+}
+
+void
+intel_batchbuffer_finish(struct intel_batchbuffer *batch)
+{
+   struct _DriFenceObject *fence = intel_batchbuffer_flush(batch);
+   driFenceReference(fence);
+   driFenceFinish(fence, 3, GL_FALSE);
+   driFenceUnReference(fence);
+}
+
+
+/*  This is the only way buffers get added to the validate list.
+ */
+GLboolean
+intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+                             struct _DriBufferObject *buffer,
+                             GLuint flags, GLuint mask, GLuint delta)
+{
+   assert(batch->nr_relocs <= MAX_RELOCS);
+
+   driBOAddListItem(&batch->list, buffer, flags, mask);
+
+   {
+      struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
+      driBOReference(buffer);
+      r->buf = buffer;
+      r->offset = batch->ptr - batch->map;
+      r->delta = delta;
+   }
+
+   batch->ptr += 4;
+   return GL_TRUE;
+}
+
+
+
+void
+intel_batchbuffer_data(struct intel_batchbuffer *batch,
+                       const void *data, GLuint bytes, GLuint flags)
+{
+   assert((bytes & 3) == 0);
+   intel_batchbuffer_require_space(batch, bytes, flags);
+   __memcpy(batch->ptr, data, bytes);
+   batch->ptr += bytes;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h b/src/mesa/drivers/dri/i915tex/intel_batchbuffer.h
new file mode 100644 (file)
index 0000000..a83dbf4
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef INTEL_BATCHBUFFER_H
+#define INTEL_BATCHBUFFER_H
+
+#include "mtypes.h"
+#include "dri_bufmgr.h"
+
+struct intel_context;
+
+#define BATCH_SZ 16384
+#define BATCH_RESERVED 16
+
+#define MAX_RELOCS 100
+
+#define INTEL_BATCH_NO_CLIPRECTS 0x1
+#define INTEL_BATCH_CLIPRECTS    0x2
+
+struct buffer_reloc
+{
+   struct _DriBufferObject *buf;
+   GLuint offset;
+   GLuint delta;                /* not needed? */
+};
+
+struct intel_batchbuffer
+{
+   struct bufmgr *bm;
+   struct intel_context *intel;
+
+   struct _DriBufferObject *buffer;
+   struct _DriFenceObject *last_fence;
+   GLuint flags;
+
+   drmBOList list;
+   GLuint list_count;
+   GLubyte *map;
+   GLubyte *ptr;
+
+   struct buffer_reloc reloc[MAX_RELOCS];
+   GLuint nr_relocs;
+   GLuint size;
+};
+
+struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
+                                                  *intel);
+
+void intel_batchbuffer_free(struct intel_batchbuffer *batch);
+
+
+void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
+
+struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer
+                                                *batch);
+
+void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
+
+
+/* Unlike bmBufferData, this currently requires the buffer be mapped.
+ * Consider it a convenience function wrapping multple
+ * intel_buffer_dword() calls.
+ */
+void intel_batchbuffer_data(struct intel_batchbuffer *batch,
+                            const void *data, GLuint bytes, GLuint flags);
+
+void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
+                                     GLuint bytes);
+
+GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+                                       struct _DriBufferObject *buffer,
+                                       GLuint flags,
+                                       GLuint mask, GLuint offset);
+
+/* Inline functions - might actually be better off with these
+ * non-inlined.  Certainly better off switching all command packets to
+ * be passed as structs rather than dwords, but that's a little bit of
+ * work...
+ */
+static INLINE GLuint
+intel_batchbuffer_space(struct intel_batchbuffer *batch)
+{
+   return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
+}
+
+
+static INLINE void
+intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
+{
+   assert(batch->map);
+   assert(intel_batchbuffer_space(batch) >= 4);
+   *(GLuint *) (batch->ptr) = dword;
+   batch->ptr += 4;
+}
+
+static INLINE void
+intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
+                                GLuint sz, GLuint flags)
+{
+   assert(sz < batch->size - 8);
+   if (intel_batchbuffer_space(batch) < sz ||
+       (batch->flags != 0 && flags != 0 && batch->flags != flags))
+      intel_batchbuffer_flush(batch);
+
+   batch->flags |= flags;
+}
+
+/* Here are the crusty old macros, to be removed:
+ */
+#define BATCH_LOCALS
+
+#define BEGIN_BATCH(n, flags) do {                             \
+   assert(!intel->prim.flush);                                 \
+   intel_batchbuffer_require_space(intel->batch, (n)*4, flags);        \
+} while (0)
+
+#define OUT_BATCH(d)  intel_batchbuffer_emit_dword(intel->batch, d)
+
+#define OUT_RELOC(buf,flags,mask,delta) do {                           \
+   assert((delta) >= 0);                                                       \
+   intel_batchbuffer_emit_reloc(intel->batch, buf, flags, mask, delta);        \
+} while (0)
+
+#define ADVANCE_BATCH() do { } while(0)
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_batchpool.c b/src/mesa/drivers/dri/i915tex/intel_batchpool.c
new file mode 100644 (file)
index 0000000..3c17c50
--- /dev/null
@@ -0,0 +1,418 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <xf86drm.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "imports.h"
+#include "glthread.h"
+#include "dri_bufpool.h"
+#include "dri_bufmgr.h"
+#include "intel_screen.h"
+
+typedef struct
+{
+   drmMMListHead head;
+   struct _BPool *parent;
+   struct _DriFenceObject *fence;
+   unsigned long start;
+   int unfenced;
+   int mapped;
+} BBuf;
+
+typedef struct _BPool
+{
+   _glthread_Mutex mutex;
+   unsigned long bufSize;
+   unsigned poolSize;
+   unsigned numFree;
+   unsigned numTot;
+   unsigned numDelayed;
+   unsigned checkDelayed;
+   drmMMListHead free;
+   drmMMListHead delayed;
+   drmMMListHead head;
+   drmBO kernelBO;
+   void *virtual;
+   BBuf *bufs;
+} BPool;
+
+
+static BPool *
+createBPool(int fd, unsigned long bufSize, unsigned numBufs, unsigned flags,
+            unsigned checkDelayed)
+{
+   BPool *p = (BPool *) malloc(sizeof(*p));
+   BBuf *buf;
+   int i;
+
+   if (!p)
+      return NULL;
+
+   p->bufs = (BBuf *) malloc(numBufs * sizeof(*p->bufs));
+   if (!p->bufs) {
+      free(p);
+      return NULL;
+   }
+
+   DRMINITLISTHEAD(&p->free);
+   DRMINITLISTHEAD(&p->head);
+   DRMINITLISTHEAD(&p->delayed);
+
+   p->numTot = numBufs;
+   p->numFree = numBufs;
+   p->bufSize = bufSize;
+   p->numDelayed = 0;
+   p->checkDelayed = checkDelayed;
+
+   _glthread_INIT_MUTEX(p->mutex);
+
+   if (drmBOCreate(fd, 0, numBufs * bufSize, 0, NULL, drm_bo_type_dc,
+                   flags, 0, &p->kernelBO)) {
+      free(p->bufs);
+      free(p);
+      return NULL;
+   }
+   if (drmBOMap(fd, &p->kernelBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0,
+                &p->virtual)) {
+      drmBODestroy(fd, &p->kernelBO);
+      free(p->bufs);
+      free(p);
+      return NULL;
+   }
+
+   /*
+    * We unmap the buffer so that we can validate it later. Note that this is
+    * just a synchronizing operation. The buffer will have a virtual mapping
+    * until it is destroyed.
+    */
+
+   drmBOUnmap(fd, &p->kernelBO);
+
+   buf = p->bufs;
+   for (i = 0; i < numBufs; ++i) {
+      buf->parent = p;
+      buf->fence = NULL;
+      buf->start = i * bufSize;
+      buf->mapped = 0;
+      buf->unfenced = 0;
+      DRMLISTADDTAIL(&buf->head, &p->free);
+      buf++;
+   }
+
+   return p;
+}
+
+
+static void
+pool_checkFree(BPool * p, int wait)
+{
+   drmMMListHead *list, *prev;
+   BBuf *buf;
+   int signaled = 0;
+   int i;
+
+   list = p->delayed.next;
+
+   if (p->numDelayed > 3) {
+      for (i = 0; i < p->numDelayed; i += 3) {
+         list = list->next;
+      }
+   }
+
+   prev = list->prev;
+   for (; list != &p->delayed; list = prev, prev = list->prev) {
+
+      buf = DRMLISTENTRY(BBuf, list, head);
+
+      if (!signaled) {
+         if (wait) {
+            driFenceFinish(buf->fence, DRM_FENCE_TYPE_EXE, 1);
+            signaled = 1;
+         }
+         else {
+            signaled = driFenceSignaled(buf->fence, DRM_FENCE_TYPE_EXE);
+         }
+      }
+
+      if (!signaled)
+         break;
+
+      driFenceUnReference(buf->fence);
+      buf->fence = NULL;
+      DRMLISTDEL(list);
+      p->numDelayed--;
+      DRMLISTADD(list, &p->free);
+      p->numFree++;
+   }
+}
+
+static void *
+pool_create(struct _DriBufferPool *pool,
+            unsigned long size, unsigned flags, unsigned hint,
+            unsigned alignment)
+{
+   BPool *p = (BPool *) pool->data;
+
+   drmMMListHead *item;
+
+   if (alignment && (alignment != 4096))
+      return NULL;
+
+   _glthread_LOCK_MUTEX(p->mutex);
+
+   if (p->numFree == 0)
+      pool_checkFree(p, GL_TRUE);
+
+   if (p->numFree == 0) {
+      fprintf(stderr, "Out of fixed size buffer objects\n");
+      BM_CKFATAL(-ENOMEM);
+   }
+
+   item = p->free.next;
+
+   if (item == &p->free) {
+      fprintf(stderr, "Fixed size buffer pool corruption\n");
+   }
+
+   DRMLISTDEL(item);
+   --p->numFree;
+
+   _glthread_UNLOCK_MUTEX(p->mutex);
+   return (void *) DRMLISTENTRY(BBuf, item, head);
+}
+
+
+static int
+pool_destroy(struct _DriBufferPool *pool, void *private)
+{
+   BBuf *buf = (BBuf *) private;
+   BPool *p = buf->parent;
+
+   _glthread_LOCK_MUTEX(p->mutex);
+
+   if (buf->fence) {
+      DRMLISTADDTAIL(&buf->head, &p->delayed);
+      p->numDelayed++;
+   }
+   else {
+      buf->unfenced = 0;
+      DRMLISTADD(&buf->head, &p->free);
+      p->numFree++;
+   }
+
+   if ((p->numDelayed % p->checkDelayed) == 0)
+      pool_checkFree(p, 0);
+
+   _glthread_UNLOCK_MUTEX(p->mutex);
+   return 0;
+}
+
+
+static int
+pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
+         int hint, void **virtual)
+{
+
+   BBuf *buf = (BBuf *) private;
+   BPool *p = buf->parent;
+
+   _glthread_LOCK_MUTEX(p->mutex);
+
+   /*
+    * Currently Mesa doesn't have any condition variables to resolve this
+    * cleanly in a multithreading environment.
+    * We bail out instead.
+    */
+
+   if (buf->mapped) {
+      fprintf(stderr, "Trying to map already mapped buffer object\n");
+      BM_CKFATAL(-EINVAL);
+   }
+
+#if 0
+   if (buf->unfenced && !(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) {
+      fprintf(stderr, "Trying to map an unfenced buffer object 0x%08x"
+              " 0x%08x %d\n", hint, flags, buf->start);
+      BM_CKFATAL(-EINVAL);
+   }
+
+#endif
+
+   if (buf->fence) {
+      _glthread_UNLOCK_MUTEX(p->mutex);
+      return -EBUSY;
+   }
+
+   buf->mapped = GL_TRUE;
+   *virtual = (unsigned char *) p->virtual + buf->start;
+   _glthread_UNLOCK_MUTEX(p->mutex);
+   return 0;
+}
+
+static int
+pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
+{
+   BBuf *buf = (BBuf *) private;
+   driFenceFinish(buf->fence, 0, lazy);
+   return 0;
+}
+
+static int
+pool_unmap(struct _DriBufferPool *pool, void *private)
+{
+   BBuf *buf = (BBuf *) private;
+
+   buf->mapped = 0;
+   return 0;
+}
+
+static unsigned long
+pool_offset(struct _DriBufferPool *pool, void *private)
+{
+   BBuf *buf = (BBuf *) private;
+   BPool *p = buf->parent;
+
+   return p->kernelBO.offset + buf->start;
+}
+
+static unsigned
+pool_flags(struct _DriBufferPool *pool, void *private)
+{
+   BPool *p = (BPool *) pool->data;
+
+   return p->kernelBO.flags;
+}
+
+static unsigned long
+pool_size(struct _DriBufferPool *pool, void *private)
+{
+   BPool *p = (BPool *) pool->data;
+
+   return p->bufSize;
+}
+
+
+static int
+pool_fence(struct _DriBufferPool *pool, void *private,
+           struct _DriFenceObject *fence)
+{
+   BBuf *buf = (BBuf *) private;
+   BPool *p = buf->parent;
+
+   _glthread_LOCK_MUTEX(p->mutex);
+   if (buf->fence) {
+      driFenceUnReference(buf->fence);
+   }
+   buf->fence = fence;
+   buf->unfenced = 0;
+   driFenceReference(buf->fence);
+   _glthread_UNLOCK_MUTEX(p->mutex);
+
+   return 0;
+}
+
+static drmBO *
+pool_kernel(struct _DriBufferPool *pool, void *private)
+{
+   BBuf *buf = (BBuf *) private;
+   BPool *p = buf->parent;
+
+   return &p->kernelBO;
+}
+
+static int
+pool_validate(struct _DriBufferPool *pool, void *private)
+{
+   BBuf *buf = (BBuf *) private;
+   BPool *p = buf->parent;
+   _glthread_LOCK_MUTEX(p->mutex);
+   buf->unfenced = GL_TRUE;
+   _glthread_UNLOCK_MUTEX(p->mutex);
+   return 0;
+}
+
+static void
+pool_takedown(struct _DriBufferPool *pool)
+{
+   BPool *p = (BPool *) pool->data;
+
+   /*
+    * Wait on outstanding fences. 
+    */
+
+   _glthread_LOCK_MUTEX(p->mutex);
+   while ((p->numFree < p->numTot) && p->numDelayed) {
+      _glthread_UNLOCK_MUTEX(p->mutex);
+      sched_yield();
+      pool_checkFree(p, GL_TRUE);
+      _glthread_LOCK_MUTEX(p->mutex);
+   }
+
+   drmBODestroy(pool->fd, &p->kernelBO);
+   free(p->bufs);
+   _glthread_UNLOCK_MUTEX(p->mutex);
+   free(p);
+   free(pool);
+}
+
+
+struct _DriBufferPool *
+driBatchPoolInit(int fd, unsigned flags,
+                 unsigned long bufSize,
+                 unsigned numBufs, unsigned checkDelayed)
+{
+   struct _DriBufferPool *pool;
+
+   pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
+   if (!pool)
+      return NULL;
+
+   pool->data = createBPool(fd, bufSize, numBufs, flags, checkDelayed);
+   if (!pool->data)
+      return NULL;
+
+   pool->fd = fd;
+   pool->map = &pool_map;
+   pool->unmap = &pool_unmap;
+   pool->destroy = &pool_destroy;
+   pool->offset = &pool_offset;
+   pool->flags = &pool_flags;
+   pool->size = &pool_size;
+   pool->create = &pool_create;
+   pool->fence = &pool_fence;
+   pool->kernel = &pool_kernel;
+   pool->validate = &pool_validate;
+   pool->waitIdle = &pool_waitIdle;
+   pool->setstatic = NULL;
+   pool->takeDown = &pool_takedown;
+   return pool;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c
new file mode 100644 (file)
index 0000000..b6b6543
--- /dev/null
@@ -0,0 +1,552 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "mtypes.h"
+#include "context.h"
+#include "enums.h"
+
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_context.h"
+#include "intel_fbo.h"
+#include "intel_reg.h"
+#include "intel_regions.h"
+#include "vblank.h"
+
+#define FILE_DEBUG_FLAG DEBUG_BLIT
+
+/**
+ * Copy the back color buffer to the front color buffer. 
+ * Used for SwapBuffers().
+ */
+void
+intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
+                const drm_clip_rect_t * rect)
+{
+
+   struct intel_context *intel;
+   const intelScreenPrivate *intelScreen;
+   GLboolean missed_target;
+   int64_t ust;
+
+   DBG("%s\n", __FUNCTION__);
+
+   assert(dPriv);
+
+   intel = intelScreenContext(dPriv->driScreenPriv->private);
+   if (!intel)
+      return;
+
+   intelScreen = intel->intelScreen;
+
+   if (!rect && !intel->swap_scheduled && intelScreen->drmMinor >= 6 &&
+       !(intel->vblank_flags & VBLANK_FLAG_NO_IRQ) &&
+       intelScreen->current_rotation == 0) {
+      unsigned int interval = driGetVBlankInterval(dPriv, intel->vblank_flags);
+      unsigned int target;
+      drm_i915_vblank_swap_t swap;
+      swap.drawable = dPriv->hHWDrawable;
+      swap.seqtype = DRM_VBLANK_ABSOLUTE;
+      target = swap.sequence = intel->vbl_seq + interval;
+
+      if (intel->vblank_flags & VBLANK_FLAG_SYNC) {
+        swap.seqtype |= DRM_VBLANK_NEXTONMISS;
+      } else if (interval == 0) {
+        goto noschedule;
+      }
+
+      if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) {
+        swap.seqtype |= DRM_VBLANK_SECONDARY;
+      }
+
+      intel_batchbuffer_flush(intel->batch);
+
+      if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap,
+                              sizeof(swap))) {
+        intel->swap_scheduled = 1;
+        intel->vbl_seq = swap.sequence;
+        swap.sequence -= target;
+        missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23);
+      }
+   } else {
+      intel->swap_scheduled = 0;
+   }
+noschedule:
+  
+   if (intel->last_swap_fence) {
+      driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
+      driFenceUnReference(intel->last_swap_fence);
+      intel->last_swap_fence = NULL;
+   }
+   intel->last_swap_fence = intel->first_swap_fence;
+   intel->first_swap_fence = NULL;
+
+   if (!intel->swap_scheduled) {
+      if (!rect) {
+        driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags,
+                         &missed_target);
+      }
+
+
+      /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets
+       * should work regardless.
+       */
+      LOCK_HARDWARE(intel);
+
+      if (intel->driDrawable && intel->driDrawable->numClipRects) {
+        const intelScreenPrivate *intelScreen = intel->intelScreen;
+        struct gl_framebuffer *fb
+           = (struct gl_framebuffer *) dPriv->driverPrivate;
+        const struct intel_region *frontRegion
+           = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+        const struct intel_region *backRegion
+           = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
+        const int nbox = dPriv->numClipRects;
+        const drm_clip_rect_t *pbox = dPriv->pClipRects;
+        const int pitch = frontRegion->pitch;
+        const int cpp = frontRegion->cpp;
+        int BR13, CMD;
+        int i;
+
+        ASSERT(fb);
+        ASSERT(fb->Name == 0);    /* Not a user-created FBO */
+        ASSERT(frontRegion);
+        ASSERT(backRegion);
+        ASSERT(frontRegion->pitch == backRegion->pitch);
+        ASSERT(frontRegion->cpp == backRegion->cpp);
+
+        if (cpp == 2) {
+           BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
+           CMD = XY_SRC_COPY_BLT_CMD;
+        }
+        else {
+           BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
+           CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+                  XY_SRC_COPY_BLT_WRITE_RGB);
+        }
+
+        for (i = 0; i < nbox; i++, pbox++) {
+           drm_clip_rect_t box;
+
+           if (pbox->x1 > pbox->x2 ||
+               pbox->y1 > pbox->y2 ||
+               pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height)
+              continue;
+
+           box = *pbox;
+
+           if (rect) {
+              if (rect->x1 > box.x1)
+                 box.x1 = rect->x1;
+              if (rect->y1 > box.y1)
+                 box.y1 = rect->y1;
+              if (rect->x2 < box.x2)
+                 box.x2 = rect->x2;
+              if (rect->y2 < box.y2)
+                 box.y2 = rect->y2;
+
+              if (box.x1 > box.x2 || box.y1 > box.y2)
+                 continue;
+           }
+
+           BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
+           OUT_BATCH(CMD);
+           OUT_BATCH(BR13);
+           OUT_BATCH((pbox->y1 << 16) | pbox->x1);
+           OUT_BATCH((pbox->y2 << 16) | pbox->x2);
+
+           if (intel->sarea->pf_current_page == 0)
+              OUT_RELOC(frontRegion->buffer,
+                        DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                        DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
+           else
+              OUT_RELOC(backRegion->buffer,
+                        DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                        DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
+           OUT_BATCH((pbox->y1 << 16) | pbox->x1);
+           OUT_BATCH(BR13 & 0xffff);
+
+           if (intel->sarea->pf_current_page == 0)
+              OUT_RELOC(backRegion->buffer,
+                        DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                        DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
+           else
+              OUT_RELOC(frontRegion->buffer,
+                        DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                        DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
+
+           ADVANCE_BATCH();
+        }
+
+        if (intel->first_swap_fence)
+           driFenceUnReference(intel->first_swap_fence);
+        intel->first_swap_fence = intel_batchbuffer_flush(intel->batch);
+        driFenceReference(intel->first_swap_fence);
+      }
+
+      UNLOCK_HARDWARE(intel);
+   }
+
+   if (!rect) {
+      intel->swap_count++;
+      (*dri_interface->getUST) (&ust);
+      if (missed_target) {
+         intel->swap_missed_count++;
+         intel->swap_missed_ust = ust - intel->swap_ust;
+      }
+
+      intel->swap_ust = ust;
+   }
+}
+
+
+
+
+void
+intelEmitFillBlit(struct intel_context *intel,
+                  GLuint cpp,
+                  GLshort dst_pitch,
+                  struct _DriBufferObject *dst_buffer,
+                  GLuint dst_offset,
+                  GLshort x, GLshort y, GLshort w, GLshort h, GLuint color)
+{
+   GLuint BR13, CMD;
+   BATCH_LOCALS;
+
+   dst_pitch *= cpp;
+
+   switch (cpp) {
+   case 1:
+   case 2:
+   case 3:
+      BR13 = dst_pitch | (0xF0 << 16) | (1 << 24);
+      CMD = XY_COLOR_BLT_CMD;
+      break;
+   case 4:
+      BR13 = dst_pitch | (0xF0 << 16) | (1 << 24) | (1 << 25);
+      CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
+             XY_COLOR_BLT_WRITE_RGB);
+      break;
+   default:
+      return;
+   }
+
+   DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
+       __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h);
+
+
+   BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
+   OUT_BATCH(CMD);
+   OUT_BATCH(BR13);
+   OUT_BATCH((y << 16) | x);
+   OUT_BATCH(((y + h) << 16) | (x + w));
+   OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+             DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset);
+   OUT_BATCH(color);
+   ADVANCE_BATCH();
+}
+
+
+/* Copy BitBlt
+ */
+void
+intelEmitCopyBlit(struct intel_context *intel,
+                  GLuint cpp,
+                  GLshort src_pitch,
+                  struct _DriBufferObject *src_buffer,
+                  GLuint src_offset,
+                  GLshort dst_pitch,
+                  struct _DriBufferObject *dst_buffer,
+                  GLuint dst_offset,
+                  GLshort src_x, GLshort src_y,
+                  GLshort dst_x, GLshort dst_y, GLshort w, GLshort h)
+{
+   GLuint CMD, BR13;
+   int dst_y2 = dst_y + h;
+   int dst_x2 = dst_x + w;
+   BATCH_LOCALS;
+
+
+   DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
+       __FUNCTION__,
+       src_buffer, src_pitch, src_offset, src_x, src_y,
+       dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
+
+   src_pitch *= cpp;
+   dst_pitch *= cpp;
+
+   switch (cpp) {
+   case 1:
+   case 2:
+   case 3:
+      BR13 = (((GLint) dst_pitch) & 0xffff) | (0xCC << 16) | (1 << 24);
+      CMD = XY_SRC_COPY_BLT_CMD;
+      break;
+   case 4:
+      BR13 =
+         (((GLint) dst_pitch) & 0xffff) | (0xCC << 16) | (1 << 24) | (1 <<
+                                                                      25);
+      CMD =
+         (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+          XY_SRC_COPY_BLT_WRITE_RGB);
+      break;
+   default:
+      return;
+   }
+
+   if (dst_y2 < dst_y || dst_x2 < dst_x) {
+      return;
+   }
+
+   /* Initial y values don't seem to work with negative pitches.  If
+    * we adjust the offsets manually (below), it seems to work fine.
+    *
+    * On the other hand, if we always adjust, the hardware doesn't
+    * know which blit directions to use, so overlapping copypixels get
+    * the wrong result.
+    */
+   if (dst_pitch > 0 && src_pitch > 0) {
+      BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
+      OUT_BATCH(CMD);
+      OUT_BATCH(BR13);
+      OUT_BATCH((dst_y << 16) | dst_x);
+      OUT_BATCH((dst_y2 << 16) | dst_x2);
+      OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset);
+      OUT_BATCH((src_y << 16) | src_x);
+      OUT_BATCH(((GLint) src_pitch & 0xffff));
+      OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, src_offset);
+      ADVANCE_BATCH();
+   }
+   else {
+      BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
+      OUT_BATCH(CMD);
+      OUT_BATCH(BR13);
+      OUT_BATCH((0 << 16) | dst_x);
+      OUT_BATCH((h << 16) | dst_x2);
+      OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
+                dst_offset + dst_y * dst_pitch);
+      OUT_BATCH((0 << 16) | src_x);
+      OUT_BATCH(((GLint) src_pitch & 0xffff));
+      OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                DRM_BO_MASK_MEM | DRM_BO_FLAG_READ,
+                src_offset + src_y * src_pitch);
+      ADVANCE_BATCH();
+   }
+}
+
+
+/**
+ * Use blitting to clear the renderbuffers named by 'flags'.
+ * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field
+ * since that might include software renderbuffers or renderbuffers
+ * which we're clearing with triangles.
+ * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
+ */
+void
+intelClearWithBlit(GLcontext * ctx, GLbitfield mask)
+{
+   struct intel_context *intel = intel_context(ctx);
+   GLuint clear_depth;
+   GLbitfield skipBuffers = 0;
+   BATCH_LOCALS;
+
+   DBG("%s %x\n", __FUNCTION__, mask);
+
+   /*
+    * Compute values for clearing the buffers.
+    */
+   clear_depth = 0;
+   if (mask & BUFFER_BIT_DEPTH) {
+      clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear);
+   }
+   if (mask & BUFFER_BIT_STENCIL) {
+      clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
+   }
+
+   /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
+    * the loop below.
+    */
+   if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
+      skipBuffers = BUFFER_BIT_STENCIL;
+   }
+
+   /* XXX Move this flush/lock into the following conditional? */
+   intelFlush(&intel->ctx);
+   LOCK_HARDWARE(intel);
+
+   if (intel->numClipRects) {
+      GLint cx, cy, cw, ch;
+      drm_clip_rect_t clear;
+      int i;
+
+      /* Get clear bounds after locking */
+      cx = ctx->DrawBuffer->_Xmin;
+      cy = ctx->DrawBuffer->_Ymin;
+      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+
+      if (intel->ctx.DrawBuffer->Name == 0) {
+         /* clearing a window */
+
+         /* flip top to bottom */
+         clear.x1 = cx + intel->drawX;
+         clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
+         clear.x2 = clear.x1 + cw;
+         clear.y2 = clear.y1 + ch;
+
+         /* adjust for page flipping */
+         if (intel->sarea->pf_current_page == 1) {
+            const GLuint tmp = mask;
+            mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
+            if (tmp & BUFFER_BIT_FRONT_LEFT)
+               mask |= BUFFER_BIT_BACK_LEFT;
+            if (tmp & BUFFER_BIT_BACK_LEFT)
+               mask |= BUFFER_BIT_FRONT_LEFT;
+         }
+      }
+      else {
+         /* clearing FBO */
+         assert(intel->numClipRects == 1);
+         assert(intel->pClipRects == &intel->fboRect);
+         clear.x1 = cx;
+         clear.y1 = cy;
+         clear.x2 = clear.x1 + cw;
+         clear.y2 = clear.y1 + ch;
+         /* no change to mask */
+      }
+
+      for (i = 0; i < intel->numClipRects; i++) {
+         const drm_clip_rect_t *box = &intel->pClipRects[i];
+         drm_clip_rect_t b;
+         GLuint buf;
+         GLuint clearMask = mask;      /* use copy, since we modify it below */
+         GLboolean all = (cw == ctx->DrawBuffer->Width &&
+                          ch == ctx->DrawBuffer->Height);
+
+         if (!all) {
+            intel_intersect_cliprects(&b, &clear, box);
+         }
+         else {
+            b = *box;
+         }
+
+         if (0)
+            _mesa_printf("clear %d,%d..%d,%d, mask %x\n",
+                         b.x1, b.y1, b.x2, b.y2, mask);
+
+         /* Loop over all renderbuffers */
+         for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
+            const GLbitfield bufBit = 1 << buf;
+            if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
+               /* OK, clear this renderbuffer */
+               const struct intel_renderbuffer *irb
+                  = intel_renderbuffer(ctx->DrawBuffer->
+                                       Attachment[buf].Renderbuffer);
+               struct _DriBufferObject *write_buffer =
+                  intel_region_buffer(intel->intelScreen, irb->region,
+                                      all ? INTEL_WRITE_FULL :
+                                      INTEL_WRITE_PART);
+
+               GLuint clearVal;
+               GLint pitch, cpp;
+               GLuint BR13, CMD;
+
+               ASSERT(irb);
+               ASSERT(irb->region);
+
+               pitch = irb->region->pitch;
+               cpp = irb->region->cpp;
+
+               DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
+                   __FUNCTION__,
+                   irb->region->buffer, (pitch * cpp),
+                   irb->region->draw_offset,
+                   b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1);
+
+
+               /* Setup the blit command */
+               if (cpp == 4) {
+                  BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
+                  if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
+                     CMD = XY_COLOR_BLT_CMD;
+                     if (clearMask & BUFFER_BIT_DEPTH)
+                        CMD |= XY_COLOR_BLT_WRITE_RGB;
+                     if (clearMask & BUFFER_BIT_STENCIL)
+                        CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+                  }
+                  else {
+                     /* clearing RGBA */
+                     CMD = (XY_COLOR_BLT_CMD |
+                            XY_COLOR_BLT_WRITE_ALPHA |
+                            XY_COLOR_BLT_WRITE_RGB);
+                  }
+               }
+               else {
+                  ASSERT(cpp == 2 || cpp == 0);
+                  BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
+                  CMD = XY_COLOR_BLT_CMD;
+               }
+
+               if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
+                  clearVal = clear_depth;
+               }
+               else {
+                  clearVal = (cpp == 4)
+                     ? intel->ClearColor8888 : intel->ClearColor565;
+               }
+               /*
+                  _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
+                  buf, irb->Base.Name);
+                */
+               BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
+               OUT_BATCH(CMD);
+               OUT_BATCH(BR13);
+               OUT_BATCH((b.y1 << 16) | b.x1);
+               OUT_BATCH((b.y2 << 16) | b.x2);
+               OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                         DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
+                         irb->region->draw_offset);
+               OUT_BATCH(clearVal);
+               ADVANCE_BATCH();
+               clearMask &= ~bufBit;    /* turn off bit, for faster loop exit */
+            }
+         }
+      }
+      intel_batchbuffer_flush(intel->batch);
+   }
+
+   UNLOCK_HARDWARE(intel);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.h b/src/mesa/drivers/dri/i915tex/intel_blit.h
new file mode 100644 (file)
index 0000000..ee85c62
--- /dev/null
@@ -0,0 +1,61 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_BLIT_H
+#define INTEL_BLIT_H
+
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "dri_bufmgr.h"
+
+extern void intelCopyBuffer(const __DRIdrawablePrivate * dpriv,
+                            const drm_clip_rect_t * rect);
+
+extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask);
+
+extern void intelEmitCopyBlit(struct intel_context *intel,
+                              GLuint cpp,
+                              GLshort src_pitch,
+                              struct _DriBufferObject *src_buffer,
+                              GLuint src_offset,
+                              GLshort dst_pitch,
+                              struct _DriBufferObject *dst_buffer,
+                              GLuint dst_offset,
+                              GLshort srcx, GLshort srcy,
+                              GLshort dstx, GLshort dsty,
+                              GLshort w, GLshort h);
+
+extern void intelEmitFillBlit(struct intel_context *intel,
+                              GLuint cpp,
+                              GLshort dst_pitch,
+                              struct _DriBufferObject *dst_buffer,
+                              GLuint dst_offset,
+                              GLshort x, GLshort y,
+                              GLshort w, GLshort h, GLuint color);
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_buffer_objects.c b/src/mesa/drivers/dri/i915tex/intel_buffer_objects.c
new file mode 100644 (file)
index 0000000..31c41d8
--- /dev/null
@@ -0,0 +1,250 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "imports.h"
+#include "mtypes.h"
+#include "bufferobj.h"
+
+#include "intel_context.h"
+#include "intel_buffer_objects.h"
+#include "intel_regions.h"
+#include "dri_bufmgr.h"
+
+/**
+ * There is some duplication between mesa's bufferobjects and our
+ * bufmgr buffers.  Both have an integer handle and a hashtable to
+ * lookup an opaque structure.  It would be nice if the handles and
+ * internal structure where somehow shared.
+ */
+static struct gl_buffer_object *
+intel_bufferobj_alloc(GLcontext * ctx, GLuint name, GLenum target)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object);
+
+   _mesa_initialize_buffer_object(&obj->Base, name, target);
+
+   driGenBuffers(intel->intelScreen->regionPool,
+                 "bufferobj", 1, &obj->buffer, 64, 0, 0);
+
+   return &obj->Base;
+}
+
+
+/* Break the COW tie to the region.  The region gets to keep the data.
+ */
+void
+intel_bufferobj_release_region(struct intel_context *intel,
+                               struct intel_buffer_object *intel_obj)
+{
+   assert(intel_obj->region->buffer == intel_obj->buffer);
+   intel_obj->region->pbo = NULL;
+   intel_obj->region = NULL;
+   driBOUnReference(intel_obj->buffer);
+   intel_obj->buffer = NULL;
+
+   /* This leads to a large number of buffer deletion/creation events.
+    * Currently the drm doesn't like that:
+    */
+   driGenBuffers(intel->intelScreen->regionPool,
+                 "buffer object", 1, &intel_obj->buffer, 64, 0, 0);
+   driBOData(intel_obj->buffer, intel_obj->Base.Size, NULL, 0);
+}
+
+/* Break the COW tie to the region.  Both the pbo and the region end
+ * up with a copy of the data.
+ */
+void
+intel_bufferobj_cow(struct intel_context *intel,
+                    struct intel_buffer_object *intel_obj)
+{
+   assert(intel_obj->region);
+   intel_region_cow(intel->intelScreen, intel_obj->region);
+}
+
+
+/**
+ * Deallocate/free a vertex/pixel buffer object.
+ * Called via glDeleteBuffersARB().
+ */
+static void
+intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+   assert(intel_obj);
+
+   if (intel_obj->region) {
+      intel_bufferobj_release_region(intel, intel_obj);
+   }
+   else if (intel_obj->buffer) {
+      driDeleteBuffers(1, &intel_obj->buffer);
+   }
+
+   _mesa_free(intel_obj);
+}
+
+
+
+/**
+ * Allocate space for and store data in a buffer object.  Any data that was
+ * previously stored in the buffer object is lost.  If data is NULL,
+ * memory will be allocated, but no copy will occur.
+ * Called via glBufferDataARB().
+ */
+static void
+intel_bufferobj_data(GLcontext * ctx,
+                     GLenum target,
+                     GLsizeiptrARB size,
+                     const GLvoid * data,
+                     GLenum usage, struct gl_buffer_object *obj)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+   intel_obj->Base.Size = size;
+   intel_obj->Base.Usage = usage;
+
+   if (intel_obj->region)
+      intel_bufferobj_release_region(intel, intel_obj);
+
+   driBOData(intel_obj->buffer, size, data, 0);
+}
+
+
+/**
+ * Replace data in a subrange of buffer object.  If the data range
+ * specified by size + offset extends beyond the end of the buffer or
+ * if data is NULL, no copy is performed.
+ * Called via glBufferSubDataARB().
+ */
+static void
+intel_bufferobj_subdata(GLcontext * ctx,
+                        GLenum target,
+                        GLintptrARB offset,
+                        GLsizeiptrARB size,
+                        const GLvoid * data, struct gl_buffer_object *obj)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+   assert(intel_obj);
+
+   if (intel_obj->region)
+      intel_bufferobj_cow(intel, intel_obj);
+
+   driBOSubData(intel_obj->buffer, offset, size, data);
+}
+
+
+/**
+ * Called via glGetBufferSubDataARB().
+ */
+static void
+intel_bufferobj_get_subdata(GLcontext * ctx,
+                            GLenum target,
+                            GLintptrARB offset,
+                            GLsizeiptrARB size,
+                            GLvoid * data, struct gl_buffer_object *obj)
+{
+   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+   assert(intel_obj);
+   driBOGetSubData(intel_obj->buffer, offset, size, data);
+}
+
+
+
+/**
+ * Called via glMapBufferARB().
+ */
+static void *
+intel_bufferobj_map(GLcontext * ctx,
+                    GLenum target,
+                    GLenum access, struct gl_buffer_object *obj)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+   /* XXX: Translate access to flags arg below:
+    */
+   assert(intel_obj);
+
+   if (intel_obj->region)
+      intel_bufferobj_cow(intel, intel_obj);
+
+   obj->Pointer = driBOMap(intel_obj->buffer,
+                           DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+   return obj->Pointer;
+}
+
+
+/**
+ * Called via glMapBufferARB().
+ */
+static GLboolean
+intel_bufferobj_unmap(GLcontext * ctx,
+                      GLenum target, struct gl_buffer_object *obj)
+{
+   struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
+
+   assert(intel_obj);
+   assert(obj->Pointer);
+   driBOUnmap(intel_obj->buffer);
+   obj->Pointer = NULL;
+   return GL_TRUE;
+}
+
+struct _DriBufferObject *
+intel_bufferobj_buffer(struct intel_context *intel,
+                       struct intel_buffer_object *intel_obj, GLuint flag)
+{
+   if (intel_obj->region) {
+      if (flag == INTEL_WRITE_PART)
+         intel_bufferobj_cow(intel, intel_obj);
+      else if (flag == INTEL_WRITE_FULL)
+         intel_bufferobj_release_region(intel, intel_obj);
+   }
+
+   return intel_obj->buffer;
+}
+
+void
+intel_bufferobj_init(struct intel_context *intel)
+{
+   GLcontext *ctx = &intel->ctx;
+
+   ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
+   ctx->Driver.DeleteBuffer = intel_bufferobj_free;
+   ctx->Driver.BufferData = intel_bufferobj_data;
+   ctx->Driver.BufferSubData = intel_bufferobj_subdata;
+   ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
+   ctx->Driver.MapBuffer = intel_bufferobj_map;
+   ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_buffer_objects.h b/src/mesa/drivers/dri/i915tex/intel_buffer_objects.h
new file mode 100644 (file)
index 0000000..afe9b2f
--- /dev/null
@@ -0,0 +1,86 @@
+ /**************************************************************************
+ * 
+ * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_BUFFEROBJ_H
+#define INTEL_BUFFEROBJ_H
+
+#include "mtypes.h"
+
+struct intel_context;
+struct intel_region;
+struct gl_buffer_object;
+
+
+/**
+ * Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object.
+ */
+struct intel_buffer_object
+{
+   struct gl_buffer_object Base;
+   struct _DriBufferObject *buffer;     /* the low-level buffer manager's buffer handle */
+
+   struct intel_region *region; /* Is there a zero-copy texture
+                                   associated with this (pixel)
+                                   buffer object? */
+};
+
+
+/* Get the bm buffer associated with a GL bufferobject:
+ */
+struct _DriBufferObject *intel_bufferobj_buffer(struct intel_context *intel,
+                                                struct intel_buffer_object
+                                                *obj, GLuint flag);
+
+/* Hook the bufferobject implementation into mesa: 
+ */
+void intel_bufferobj_init(struct intel_context *intel);
+
+
+
+/* Are the obj->Name tests necessary?  Unfortunately yes, mesa
+ * allocates a couple of gl_buffer_object structs statically, and
+ * the Name == 0 test is the only way to identify them and avoid
+ * casting them erroneously to our structs.
+ */
+static INLINE struct intel_buffer_object *
+intel_buffer_object(struct gl_buffer_object *obj)
+{
+   if (obj->Name)
+      return (struct intel_buffer_object *) obj;
+   else
+      return NULL;
+}
+
+/* Helpers for zerocopy image uploads.  See also intel_regions.h:
+ */
+void intel_bufferobj_cow(struct intel_context *intel,
+                         struct intel_buffer_object *intel_obj);
+void intel_bufferobj_release_region(struct intel_context *intel,
+                                    struct intel_buffer_object *intel_obj);
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c
new file mode 100644 (file)
index 0000000..d3925bb
--- /dev/null
@@ -0,0 +1,956 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_depthstencil.h"
+#include "intel_fbo.h"
+#include "intel_tris.h"
+#include "intel_regions.h"
+#include "intel_batchbuffer.h"
+#include "context.h"
+#include "utils.h"
+#include "framebuffer.h"
+#include "swrast/swrast.h"
+#include "vblank.h"
+
+
+/**
+ * XXX move this into a new dri/common/cliprects.c file.
+ */
+GLboolean
+intel_intersect_cliprects(drm_clip_rect_t * dst,
+                          const drm_clip_rect_t * a,
+                          const drm_clip_rect_t * b)
+{
+   GLint bx = b->x1;
+   GLint by = b->y1;
+   GLint bw = b->x2 - bx;
+   GLint bh = b->y2 - by;
+
+   if (bx < a->x1)
+      bw -= a->x1 - bx, bx = a->x1;
+   if (by < a->y1)
+      bh -= a->y1 - by, by = a->y1;
+   if (bx + bw > a->x2)
+      bw = a->x2 - bx;
+   if (by + bh > a->y2)
+      bh = a->y2 - by;
+   if (bw <= 0)
+      return GL_FALSE;
+   if (bh <= 0)
+      return GL_FALSE;
+
+   dst->x1 = bx;
+   dst->y1 = by;
+   dst->x2 = bx + bw;
+   dst->y2 = by + bh;
+
+   return GL_TRUE;
+}
+
+/**
+ * Return pointer to current color drawing region, or NULL.
+ */
+struct intel_region *
+intel_drawbuf_region(struct intel_context *intel)
+{
+   struct intel_renderbuffer *irbColor =
+      intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
+   if (irbColor)
+      return irbColor->region;
+   else
+      return NULL;
+}
+
+/**
+ * Return pointer to current color reading region, or NULL.
+ */
+struct intel_region *
+intel_readbuf_region(struct intel_context *intel)
+{
+   struct intel_renderbuffer *irb
+      = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
+   if (irb)
+      return irb->region;
+   else
+      return NULL;
+}
+
+
+
+static void
+intelBufferSize(GLframebuffer * buffer, GLuint * width, GLuint * height)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
+   /* Need to lock to make sure the driDrawable is uptodate.  This
+    * information is used to resize Mesa's software buffers, so it has
+    * to be correct.
+    */
+   /* XXX This isn't 100% correct, the given buffer might not be
+    * bound to the current context!
+    */
+   LOCK_HARDWARE(intel);
+   if (intel->driDrawable) {
+      *width = intel->driDrawable->w;
+      *height = intel->driDrawable->h;
+   }
+   else {
+      *width = 0;
+      *height = 0;
+   }
+   UNLOCK_HARDWARE(intel);
+}
+
+
+
+/**
+ * Update the following fields for rendering to a user-created FBO:
+ *   intel->numClipRects
+ *   intel->pClipRects
+ *   intel->drawX
+ *   intel->drawY
+ */
+static void
+intelSetRenderbufferClipRects(struct intel_context *intel)
+{
+   assert(intel->ctx.DrawBuffer->Width > 0);
+   assert(intel->ctx.DrawBuffer->Height > 0);
+   intel->fboRect.x1 = 0;
+   intel->fboRect.y1 = 0;
+   intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
+   intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
+   intel->numClipRects = 1;
+   intel->pClipRects = &intel->fboRect;
+   intel->drawX = 0;
+   intel->drawY = 0;
+}
+
+
+/**
+ * As above, but for rendering to front buffer of a window.
+ * \sa intelSetRenderbufferClipRects
+ */
+static void
+intelSetFrontClipRects(struct intel_context *intel)
+{
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+   if (!dPriv)
+      return;
+
+   intel->numClipRects = dPriv->numClipRects;
+   intel->pClipRects = dPriv->pClipRects;
+   intel->drawX = dPriv->x;
+   intel->drawY = dPriv->y;
+}
+
+
+/**
+ * As above, but for rendering to back buffer of a window.
+ */
+static void
+intelSetBackClipRects(struct intel_context *intel)
+{
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+   if (!dPriv)
+      return;
+
+   if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
+      /* use the front clip rects */
+      intel->numClipRects = dPriv->numClipRects;
+      intel->pClipRects = dPriv->pClipRects;
+      intel->drawX = dPriv->x;
+      intel->drawY = dPriv->y;
+   }
+   else {
+      /* use the back clip rects */
+      intel->numClipRects = dPriv->numBackClipRects;
+      intel->pClipRects = dPriv->pBackClipRects;
+      intel->drawX = dPriv->backX;
+      intel->drawY = dPriv->backY;
+   }
+}
+
+
+/**
+ * This will be called whenever the currently bound window is moved/resized.
+ * XXX: actually, it seems to NOT be called when the window is only moved (BP).
+ */
+void
+intelWindowMoved(struct intel_context *intel)
+{
+   GLcontext *ctx = &intel->ctx;
+
+   if (!intel->ctx.DrawBuffer) {
+      /* when would this happen? -BP */
+      intelSetFrontClipRects(intel);
+   }
+   else if (intel->ctx.DrawBuffer->Name != 0) {
+      /* drawing to user-created FBO - do nothing */
+      /* Cliprects would be set from intelDrawBuffer() */
+   }
+   else {
+      /* drawing to a window */
+      switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
+      case BUFFER_BIT_FRONT_LEFT:
+         intelSetFrontClipRects(intel);
+         break;
+      case BUFFER_BIT_BACK_LEFT:
+         intelSetBackClipRects(intel);
+         break;
+      default:
+         /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
+         intelSetFrontClipRects(intel);
+      }
+   }
+
+   /* this update Mesa's notion of window size */
+   if (ctx->WinSysDrawBuffer) {
+      _mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer,
+                               intel->driDrawable->w, intel->driDrawable->h);
+   }
+
+   if (intel->intelScreen->driScrnPriv->ddxMinor >= 7 && intel->driDrawable) {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      drmI830Sarea *sarea = intel->sarea;
+      drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
+                                  .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
+      drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y,
+                                    .x2 = sarea->pipeA_x + sarea->pipeA_w,
+                                    .y2 = sarea->pipeA_y + sarea->pipeA_h };
+      drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y,
+                                    .x2 = sarea->pipeB_x + sarea->pipeB_w,
+                                    .y2 = sarea->pipeB_y + sarea->pipeB_h };
+      GLint areaA = driIntersectArea( drw_rect, pipeA_rect );
+      GLint areaB = driIntersectArea( drw_rect, pipeB_rect );
+      GLuint flags = intel->vblank_flags;
+
+      if (areaB > areaA || (areaA == areaB && areaB > 0)) {
+        flags = intel->vblank_flags | VBLANK_FLAG_SECONDARY;
+      } else {
+        flags = intel->vblank_flags & ~VBLANK_FLAG_SECONDARY;
+      }
+
+      if (flags != intel->vblank_flags) {
+        intel->vblank_flags = flags;
+        driGetCurrentVBlank(dPriv, intel->vblank_flags, &intel->vbl_seq);
+      }
+   } else {
+      intel->vblank_flags &= ~VBLANK_FLAG_SECONDARY;
+   }
+
+   /* Update hardware scissor */
+   ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                       ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+
+
+/* A true meta version of this would be very simple and additionally
+ * machine independent.  Maybe we'll get there one day.
+ */
+static void
+intelClearWithTris(struct intel_context *intel, GLbitfield mask)
+{
+   GLcontext *ctx = &intel->ctx;
+   drm_clip_rect_t clear;
+
+   if (INTEL_DEBUG & DEBUG_BLIT)
+      _mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
+
+   LOCK_HARDWARE(intel);
+
+   /* XXX FBO: was: intel->driDrawable->numClipRects */
+   if (intel->numClipRects) {
+      GLint cx, cy, cw, ch;
+      GLuint buf;
+
+      intel->vtbl.install_meta_state(intel);
+
+      /* Get clear bounds after locking */
+      cx = ctx->DrawBuffer->_Xmin;
+      cy = ctx->DrawBuffer->_Ymin;
+      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+
+      /* note: regardless of 'all', cx, cy, cw, ch are now correct */
+      clear.x1 = cx;
+      clear.y1 = cy;
+      clear.x2 = cx + cw;
+      clear.y2 = cy + ch;
+
+      /* Back and stencil cliprects are the same.  Try and do both
+       * buffers at once:
+       */
+      if (mask &
+          (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {
+         struct intel_region *backRegion =
+            intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT);
+         struct intel_region *depthRegion =
+            intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH);
+         const GLuint clearColor = (backRegion && backRegion->cpp == 4)
+            ? intel->ClearColor8888 : intel->ClearColor565;
+
+         intel->vtbl.meta_draw_region(intel, backRegion, depthRegion);
+
+         if (mask & BUFFER_BIT_BACK_LEFT)
+            intel->vtbl.meta_color_mask(intel, GL_TRUE);
+         else
+            intel->vtbl.meta_color_mask(intel, GL_FALSE);
+
+         if (mask & BUFFER_BIT_STENCIL)
+            intel->vtbl.meta_stencil_replace(intel,
+                                             intel->ctx.Stencil.WriteMask[0],
+                                             intel->ctx.Stencil.Clear);
+         else
+            intel->vtbl.meta_no_stencil_write(intel);
+
+         if (mask & BUFFER_BIT_DEPTH)
+            intel->vtbl.meta_depth_replace(intel);
+         else
+            intel->vtbl.meta_no_depth_write(intel);
+
+         /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
+          * drawing origin may not be correctly emitted.
+          */
+         intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0);   /* texcoords */
+
+         mask &=
+            ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
+      }
+
+      /* clear the remaining (color) renderbuffers */
+      for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
+         const GLuint bufBit = 1 << buf;
+         if (mask & bufBit) {
+            struct intel_renderbuffer *irbColor =
+               intel_renderbuffer(ctx->DrawBuffer->
+                                  Attachment[buf].Renderbuffer);
+            GLuint color = (irbColor->region->cpp == 4)
+               ? intel->ClearColor8888 : intel->ClearColor565;
+
+            ASSERT(irbColor);
+
+            intel->vtbl.meta_no_depth_write(intel);
+            intel->vtbl.meta_no_stencil_write(intel);
+            intel->vtbl.meta_color_mask(intel, GL_TRUE);
+            intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
+
+            /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
+             * drawing origin may not be correctly emitted.
+             */
+            intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, 0,      /* depth clear val */
+                                 color, 0, 0, 0, 0);    /* texcoords */
+
+            mask &= ~bufBit;
+         }
+      }
+
+      intel->vtbl.leave_meta_state(intel);
+      intel_batchbuffer_flush(intel->batch);
+   }
+   UNLOCK_HARDWARE(intel);
+}
+
+
+
+
+/**
+ * Copy the window contents named by dPriv to the rotated (or reflected)
+ * color buffer.
+ * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
+ */
+void
+intelRotateWindow(struct intel_context *intel,
+                  __DRIdrawablePrivate * dPriv, GLuint srcBuf)
+{
+   intelScreenPrivate *screen = intel->intelScreen;
+   drm_clip_rect_t fullRect;
+   struct intel_region *src;
+   const drm_clip_rect_t *clipRects;
+   int numClipRects;
+   int i;
+   GLenum format, type;
+
+   int xOrig, yOrig;
+   int origNumClipRects;
+   drm_clip_rect_t *origRects;
+
+   /*
+    * set up hardware state
+    */
+   intelFlush(&intel->ctx);
+
+   LOCK_HARDWARE(intel);
+
+   if (!intel->numClipRects) {
+      UNLOCK_HARDWARE(intel);
+      return;
+   }
+
+   intel->vtbl.install_meta_state(intel);
+
+   intel->vtbl.meta_no_depth_write(intel);
+   intel->vtbl.meta_no_stencil_write(intel);
+   intel->vtbl.meta_color_mask(intel, GL_FALSE);
+
+
+   /* save current drawing origin and cliprects (restored at end) */
+   xOrig = intel->drawX;
+   yOrig = intel->drawY;
+   origNumClipRects = intel->numClipRects;
+   origRects = intel->pClipRects;
+
+   /*
+    * set drawing origin, cliprects for full-screen access to rotated screen
+    */
+   fullRect.x1 = 0;
+   fullRect.y1 = 0;
+   fullRect.x2 = screen->rotatedWidth;
+   fullRect.y2 = screen->rotatedHeight;
+   intel->drawX = 0;
+   intel->drawY = 0;
+   intel->numClipRects = 1;
+   intel->pClipRects = &fullRect;
+
+   intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL);    /* ? */
+
+   if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
+      src = intel->intelScreen->front_region;
+      clipRects = dPriv->pClipRects;
+      numClipRects = dPriv->numClipRects;
+   }
+   else {
+      src = intel->intelScreen->back_region;
+      clipRects = dPriv->pBackClipRects;
+      numClipRects = dPriv->numBackClipRects;
+   }
+
+   if (src->cpp == 4) {
+      format = GL_BGRA;
+      type = GL_UNSIGNED_BYTE;
+   }
+   else {
+      format = GL_BGR;
+      type = GL_UNSIGNED_SHORT_5_6_5_REV;
+   }
+
+   /* set the whole screen up as a texture to avoid alignment issues */
+   intel->vtbl.meta_tex_rect_source(intel,
+                                    src->buffer,
+                                    screen->width,
+                                    screen->height, src->pitch, format, type);
+
+   intel->vtbl.meta_texture_blend_replace(intel);
+
+   /*
+    * loop over the source window's cliprects
+    */
+   for (i = 0; i < numClipRects; i++) {
+      int srcX0 = clipRects[i].x1;
+      int srcY0 = clipRects[i].y1;
+      int srcX1 = clipRects[i].x2;
+      int srcY1 = clipRects[i].y2;
+      GLfloat verts[4][2], tex[4][2];
+      int j;
+
+      /* build vertices for four corners of clip rect */
+      verts[0][0] = srcX0;
+      verts[0][1] = srcY0;
+      verts[1][0] = srcX1;
+      verts[1][1] = srcY0;
+      verts[2][0] = srcX1;
+      verts[2][1] = srcY1;
+      verts[3][0] = srcX0;
+      verts[3][1] = srcY1;
+
+      /* .. and texcoords */
+      tex[0][0] = srcX0;
+      tex[0][1] = srcY0;
+      tex[1][0] = srcX1;
+      tex[1][1] = srcY0;
+      tex[2][0] = srcX1;
+      tex[2][1] = srcY1;
+      tex[3][0] = srcX0;
+      tex[3][1] = srcY1;
+
+      /* transform coords to rotated screen coords */
+
+      for (j = 0; j < 4; j++) {
+         matrix23TransformCoordf(&screen->rotMatrix,
+                                 &verts[j][0], &verts[j][1]);
+      }
+
+      /* draw polygon to map source image to dest region */
+      intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
+
+   }                            /* cliprect loop */
+
+   intel->vtbl.leave_meta_state(intel);
+   intel_batchbuffer_flush(intel->batch);
+
+   /* restore original drawing origin and cliprects */
+   intel->drawX = xOrig;
+   intel->drawY = yOrig;
+   intel->numClipRects = origNumClipRects;
+   intel->pClipRects = origRects;
+
+   UNLOCK_HARDWARE(intel);
+}
+
+
+/**
+ * Called by ctx->Driver.Clear.
+ */
+static void
+intelClear(GLcontext *ctx, GLbitfield mask)
+{
+   struct intel_context *intel = intel_context(ctx);
+   const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask);
+   GLbitfield tri_mask = 0;
+   GLbitfield blit_mask = 0;
+   GLbitfield swrast_mask = 0;
+   GLuint i;
+
+   if (0)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* HW color buffers (front, back, aux, generic FBO, etc) */
+   if (colorMask == ~0) {
+      /* clear all R,G,B,A */
+      /* XXX FBO: need to check if colorbuffers are software RBOs! */
+      blit_mask |= (mask & BUFFER_BITS_COLOR);
+   }
+   else {
+      /* glColorMask in effect */
+      tri_mask |= (mask & BUFFER_BITS_COLOR);
+   }
+
+   /* HW stencil */
+   if (mask & BUFFER_BIT_STENCIL) {
+      const struct intel_region *stencilRegion
+         = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL);
+      if (stencilRegion) {
+         /* have hw stencil */
+         if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
+            /* not clearing all stencil bits, so use triangle clearing */
+            tri_mask |= BUFFER_BIT_STENCIL;
+         }
+         else {
+            /* clearing all stencil bits, use blitting */
+            blit_mask |= BUFFER_BIT_STENCIL;
+         }
+      }
+   }
+
+   /* HW depth */
+   if (mask & BUFFER_BIT_DEPTH) {
+      /* clear depth with whatever method is used for stencil (see above) */
+      if (tri_mask & BUFFER_BIT_STENCIL)
+         tri_mask |= BUFFER_BIT_DEPTH;
+      else
+         blit_mask |= BUFFER_BIT_DEPTH;
+   }
+
+   /* SW fallback clearing */
+   swrast_mask = mask & ~tri_mask & ~blit_mask;
+
+   for (i = 0; i < BUFFER_COUNT; i++) {
+      GLuint bufBit = 1 << i;
+      if ((blit_mask | tri_mask) & bufBit) {
+         if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
+            blit_mask &= ~bufBit;
+            tri_mask &= ~bufBit;
+            swrast_mask |= bufBit;
+         }
+      }
+   }
+
+
+   intelFlush(ctx);             /* XXX intelClearWithBlit also does this */
+
+   if (blit_mask)
+      intelClearWithBlit(ctx, blit_mask);
+
+   if (tri_mask)
+      intelClearWithTris(intel, tri_mask);
+
+   if (swrast_mask)
+      _swrast_Clear(ctx, swrast_mask);
+}
+
+
+
+/* Flip the front & back buffers
+ */
+static void
+intelPageFlip(const __DRIdrawablePrivate * dPriv)
+{
+#if 0
+   struct intel_context *intel;
+   int tmp, ret;
+
+   if (INTEL_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
+
+   intelFlush(&intel->ctx);
+   LOCK_HARDWARE(intel);
+
+   if (dPriv->pClipRects) {
+      *(drm_clip_rect_t *) intel->sarea->boxes = dPriv->pClipRects[0];
+      intel->sarea->nbox = 1;
+   }
+
+   ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
+   if (ret) {
+      fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
+      UNLOCK_HARDWARE(intel);
+      exit(1);
+   }
+
+   tmp = intel->sarea->last_enqueue;
+   intelRefillBatchLocked(intel);
+   UNLOCK_HARDWARE(intel);
+
+
+   intelSetDrawBuffer(&intel->ctx, intel->ctx.Color.DriverDrawBuffer);
+#endif
+}
+
+#if 0
+void
+intelSwapBuffers(__DRIdrawablePrivate * dPriv)
+{
+   if (dPriv->driverPrivate) {
+      const struct gl_framebuffer *fb
+         = (struct gl_framebuffer *) dPriv->driverPrivate;
+      if (fb->Visual.doubleBufferMode) {
+         GET_CURRENT_CONTEXT(ctx);
+         if (ctx && ctx->DrawBuffer == fb) {
+            _mesa_notifySwapBuffers(ctx);       /* flush pending rendering */
+         }
+         if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */
+            intelPageFlip(dPriv);
+         }
+         else {
+            intelCopyBuffer(dPriv);
+         }
+      }
+   }
+   else {
+      _mesa_problem(NULL,
+                    "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
+   }
+}
+#else
+/* Trunk version:
+ */
+void
+intelSwapBuffers(__DRIdrawablePrivate * dPriv)
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      GET_CURRENT_CONTEXT(ctx);
+      struct intel_context *intel;
+
+      if (ctx == NULL)
+        return;
+
+      intel = intel_context(ctx);
+
+      if (ctx->Visual.doubleBufferMode) {
+         intelScreenPrivate *screen = intel->intelScreen;
+         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
+         if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */
+            intelPageFlip(dPriv);
+         }
+         else {
+            intelCopyBuffer(dPriv, NULL);
+         }
+         if (screen->current_rotation != 0) {
+            intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
+         }
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+   }
+}
+#endif
+
+void
+intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      struct intel_context *intel =
+         (struct intel_context *) dPriv->driContextPriv->driverPrivate;
+      GLcontext *ctx = &intel->ctx;
+
+      if (ctx->Visual.doubleBufferMode) {
+         drm_clip_rect_t rect;
+         rect.x1 = x + dPriv->x;
+         rect.y1 = (dPriv->h - y - h) + dPriv->y;
+         rect.x2 = rect.x1 + w;
+         rect.y2 = rect.y1 + h;
+         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
+         intelCopyBuffer(dPriv, &rect);
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+   }
+}
+
+
+/**
+ * Update the hardware state for drawing into a window or framebuffer object.
+ *
+ * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
+ * places within the driver.
+ *
+ * Basically, this needs to be called any time the current framebuffer
+ * changes, the renderbuffers change, or we need to draw into different
+ * color buffers.
+ */
+void
+intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *colorRegion, *depthRegion = NULL;
+   struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
+   int front = 0;               /* drawing to front color buffer? */
+
+   if (!fb) {
+      /* this can happen during the initial context initialization */
+      return;
+   }
+
+   /* Do this here, note core Mesa, since this function is called from
+    * many places within the driver.
+    */
+   if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
+      /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
+      _mesa_update_framebuffer(ctx);
+      /* this updates the DrawBuffer's Width/Height if it's a FBO */
+      _mesa_update_draw_buffer_bounds(ctx);
+   }
+
+   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      /* this may occur when we're called by glBindFrameBuffer() during
+       * the process of someone setting up renderbuffers, etc.
+       */
+      /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
+      return;
+   }
+
+   if (fb->Name)
+      intel_validate_paired_depth_stencil(ctx, fb);
+
+   /*
+    * How many color buffers are we drawing into?
+    */
+   if (fb->_NumColorDrawBuffers[0] != 1
+#if 0
+       /* XXX FBO temporary - always use software rendering */
+       || 1
+#endif
+      ) {
+      /* writing to 0 or 2 or 4 color buffers */
+      /*_mesa_debug(ctx, "Software rendering\n");*/
+      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
+      front = 1;                /* might not have back color buffer */
+   }
+   else {
+      /* draw to exactly one color buffer */
+      /*_mesa_debug(ctx, "Hardware rendering\n");*/
+      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
+      if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
+         front = 1;
+      }
+   }
+
+   /*
+    * Get the intel_renderbuffer for the colorbuffer we're drawing into.
+    * And set up cliprects.
+    */
+   if (fb->Name == 0) {
+      /* drawing to window system buffer */
+      if (intel->sarea->pf_current_page == 1) {
+         /* page flipped back/front */
+         front ^= 1;
+      }
+      if (front) {
+         intelSetFrontClipRects(intel);
+         colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+      }
+      else {
+         intelSetBackClipRects(intel);
+         colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
+      }
+   }
+   else {
+      /* drawing to user-created FBO */
+      struct intel_renderbuffer *irb;
+      intelSetRenderbufferClipRects(intel);
+      irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
+      colorRegion = (irb && irb->region) ? irb->region : NULL;
+   }
+
+   /* Update culling direction which changes depending on the
+    * orientation of the buffer:
+    */
+   if (ctx->Driver.FrontFace)
+      ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+   else
+      ctx->NewState |= _NEW_POLYGON;
+
+   if (!colorRegion) {
+      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
+   }
+   else {
+      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
+   }
+
+   /***
+    *** Get depth buffer region and check if we need a software fallback.
+    *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
+    ***/
+   if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
+      irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
+      if (irbDepth->region) {
+         FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
+         depthRegion = irbDepth->region;
+      }
+      else {
+         FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
+         depthRegion = NULL;
+      }
+   }
+   else {
+      /* not using depth buffer */
+      FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
+      depthRegion = NULL;
+   }
+
+   /***
+    *** Stencil buffer
+    *** This can only be hardware accelerated if we're using a
+    *** combined DEPTH_STENCIL buffer (for now anyway).
+    ***/
+   if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
+      irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
+      if (irbStencil && irbStencil->region) {
+         ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+         FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
+         /* need to re-compute stencil hw state */
+         ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+         if (!depthRegion)
+            depthRegion = irbStencil->region;
+      }
+      else {
+         FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
+      }
+   }
+   else {
+      /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
+      FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
+      /* need to re-compute stencil hw state */
+      ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+   }
+
+
+   /**
+    ** Release old regions, reference new regions
+    **/
+#if 0                           /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
+   if (intel->draw_region != colorRegion) {
+      intel_region_release(&intel->draw_region);
+      intel_region_reference(&intel->draw_region, colorRegion);
+   }
+   if (intel->intelScreen->depth_region != depthRegion) {
+      intel_region_release(&intel->intelScreen->depth_region);
+      intel_region_reference(&intel->intelScreen->depth_region, depthRegion);
+   }
+#endif
+
+   intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
+
+   /* update viewport since it depends on window size */
+   ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
+                        ctx->Viewport.Width, ctx->Viewport.Height);
+
+   /* Update hardware scissor */
+   ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                       ctx->Scissor.Width, ctx->Scissor.Height);
+}
+
+
+static void
+intelDrawBuffer(GLcontext * ctx, GLenum mode)
+{
+   intel_draw_buffer(ctx, ctx->DrawBuffer);
+}
+
+
+static void
+intelReadBuffer(GLcontext * ctx, GLenum mode)
+{
+   if (ctx->ReadBuffer == ctx->DrawBuffer) {
+      /* This will update FBO completeness status.
+       * A framebuffer will be incomplete if the GL_READ_BUFFER setting
+       * refers to a missing renderbuffer.  Calling glReadBuffer can set
+       * that straight and can make the drawing buffer complete.
+       */
+      intel_draw_buffer(ctx, ctx->DrawBuffer);
+   }
+   /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
+    * reference ctx->ReadBuffer and do appropriate state checks.
+    */
+}
+
+
+void
+intelInitBufferFuncs(struct dd_function_table *functions)
+{
+   functions->Clear = intelClear;
+   functions->GetBufferSize = intelBufferSize;
+   functions->ResizeBuffers = _mesa_resize_framebuffer;
+   functions->DrawBuffer = intelDrawBuffer;
+   functions->ReadBuffer = intelReadBuffer;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.h b/src/mesa/drivers/dri/i915tex/intel_buffers.h
new file mode 100644 (file)
index 0000000..0faf055
--- /dev/null
@@ -0,0 +1,56 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_BUFFERS_H
+#define INTEL_BUFFERS_H
+
+
+struct intel_context;
+
+
+extern GLboolean
+intel_intersect_cliprects(drm_clip_rect_t * dest,
+                          const drm_clip_rect_t * a,
+                          const drm_clip_rect_t * b);
+
+extern struct intel_region *intel_readbuf_region(struct intel_context *intel);
+
+extern struct intel_region *intel_drawbuf_region(struct intel_context *intel);
+
+extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
+
+extern void intelWindowMoved(struct intel_context *intel);
+
+extern void intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb);
+
+extern void intelInitBufferFuncs(struct dd_function_table *functions);
+
+extern void
+intelRotateWindow(struct intel_context *intel,
+                  __DRIdrawablePrivate * dPriv, GLuint srcBuf);
+
+#endif /* INTEL_BUFFERS_H */
diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c
new file mode 100644 (file)
index 0000000..3d51a63
--- /dev/null
@@ -0,0 +1,707 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "glheader.h"
+#include "context.h"
+#include "matrix.h"
+#include "simple_list.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "imports.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "array_cache/acache.h"
+
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vertex.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#include "intel_screen.h"
+
+#include "i830_dri.h"
+
+#include "intel_buffers.h"
+#include "intel_tex.h"
+#include "intel_span.h"
+#include "intel_tris.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_pixel.h"
+#include "intel_regions.h"
+#include "intel_buffer_objects.h"
+#include "intel_fbo.h"
+
+#include "vblank.h"
+#include "utils.h"
+#include "xmlpool.h"            /* for symbolic values of enum-type options */
+#ifndef INTEL_DEBUG
+int INTEL_DEBUG = (0);
+#endif
+
+#define need_GL_ARB_multisample
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_cull_vertex
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_secondary_color
+#define need_GL_NV_vertex_program
+#include "extension_helper.h"
+
+
+#define DRIVER_DATE                     "20060929"
+
+_glthread_Mutex lockMutex;
+static GLboolean lockMutexInit = GL_FALSE;
+
+
+static const GLubyte *
+intelGetString(GLcontext * ctx, GLenum name)
+{
+   const char *chipset;
+   static char buffer[128];
+
+   switch (name) {
+   case GL_VENDOR:
+      return (GLubyte *) "Tungsten Graphics, Inc";
+      break;
+
+   case GL_RENDERER:
+      switch (intel_context(ctx)->intelScreen->deviceID) {
+      case PCI_CHIP_845_G:
+         chipset = "Intel(R) 845G";
+         break;
+      case PCI_CHIP_I830_M:
+         chipset = "Intel(R) 830M";
+         break;
+      case PCI_CHIP_I855_GM:
+         chipset = "Intel(R) 852GM/855GM";
+         break;
+      case PCI_CHIP_I865_G:
+         chipset = "Intel(R) 865G";
+         break;
+      case PCI_CHIP_I915_G:
+         chipset = "Intel(R) 915G";
+         break;
+      case PCI_CHIP_I915_GM:
+         chipset = "Intel(R) 915GM";
+         break;
+      case PCI_CHIP_I945_G:
+         chipset = "Intel(R) 945G";
+         break;
+      case PCI_CHIP_I945_GM:
+         chipset = "Intel(R) 945GM";
+         break;
+      default:
+         chipset = "Unknown Intel Chipset";
+         break;
+      }
+
+      (void) driGetRendererString(buffer, chipset, DRIVER_DATE, 0);
+      return (GLubyte *) buffer;
+
+   default:
+      return NULL;
+   }
+}
+
+
+/**
+ * Extension strings exported by the intel driver.
+ *
+ * \note
+ * It appears that ARB_texture_env_crossbar has "disappeared" compared to the
+ * old i830-specific driver.
+ */
+const struct dri_extension card_extensions[] = {
+   {"GL_ARB_multisample", GL_ARB_multisample_functions},
+   {"GL_ARB_multitexture", NULL},
+   {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
+   {"GL_ARB_texture_border_clamp", NULL},
+   {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
+   {"GL_ARB_texture_cube_map", NULL},
+   {"GL_ARB_texture_env_add", NULL},
+   {"GL_ARB_texture_env_combine", NULL},
+   {"GL_ARB_texture_env_dot3", NULL},
+   {"GL_ARB_texture_mirrored_repeat", NULL},
+   {"GL_ARB_texture_rectangle", NULL},
+   {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
+   {"GL_ARB_pixel_buffer_object", NULL},
+   {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
+   {"GL_ARB_window_pos", GL_ARB_window_pos_functions},
+   {"GL_EXT_blend_color", GL_EXT_blend_color_functions},
+   {"GL_EXT_blend_equation_separate",
+    GL_EXT_blend_equation_separate_functions},
+   {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
+   {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
+   {"GL_EXT_blend_subtract", NULL},
+   {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
+   {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
+   {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
+   {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
+#if 1                           /* XXX FBO temporary? */
+   {"GL_EXT_packed_depth_stencil", NULL},
+#endif
+   {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
+   {"GL_EXT_stencil_wrap", NULL},
+   {"GL_EXT_texture_edge_clamp", NULL},
+   {"GL_EXT_texture_env_combine", NULL},
+   {"GL_EXT_texture_env_dot3", NULL},
+   {"GL_EXT_texture_filter_anisotropic", NULL},
+   {"GL_EXT_texture_lod_bias", NULL},
+   {"GL_3DFX_texture_compression_FXT1", NULL},
+   {"GL_APPLE_client_storage", NULL},
+   {"GL_MESA_pack_invert", NULL},
+   {"GL_MESA_ycbcr_texture", NULL},
+   {"GL_NV_blend_square", NULL},
+   {"GL_NV_vertex_program", GL_NV_vertex_program_functions},
+   {"GL_NV_vertex_program1_1", NULL},
+/*     { "GL_SGIS_generate_mipmap",           NULL }, */
+   {NULL, NULL}
+};
+
+extern const struct tnl_pipeline_stage _intel_render_stage;
+
+static const struct tnl_pipeline_stage *intel_pipeline[] = {
+   &_tnl_vertex_transform_stage,
+   &_tnl_vertex_cull_stage,
+   &_tnl_normal_transform_stage,
+   &_tnl_lighting_stage,
+   &_tnl_fog_coordinate_stage,
+   &_tnl_texgen_stage,
+   &_tnl_texture_transform_stage,
+   &_tnl_point_attenuation_stage,
+   &_tnl_arb_vertex_program_stage,
+   &_tnl_vertex_program_stage,
+#if 1
+   &_intel_render_stage,        /* ADD: unclipped rastersetup-to-dma */
+#endif
+   &_tnl_render_stage,
+   0,
+};
+
+
+static const struct dri_debug_control debug_control[] = {
+   {"tex", DEBUG_TEXTURE},
+   {"state", DEBUG_STATE},
+   {"ioctl", DEBUG_IOCTL},
+   {"blit", DEBUG_BLIT},
+   {"mip", DEBUG_MIPTREE},
+   {"fall", DEBUG_FALLBACKS},
+   {"verb", DEBUG_VERBOSE},
+   {"bat", DEBUG_BATCH},
+   {"pix", DEBUG_PIXEL},
+   {"buf", DEBUG_BUFMGR},
+   {"reg", DEBUG_REGION},
+   {"fbo", DEBUG_FBO},
+   {"lock", DEBUG_LOCK},
+   {NULL, 0}
+};
+
+
+static void
+intelInvalidateState(GLcontext * ctx, GLuint new_state)
+{
+   _swrast_InvalidateState(ctx, new_state);
+   _swsetup_InvalidateState(ctx, new_state);
+   _ac_InvalidateState(ctx, new_state);
+   _tnl_InvalidateState(ctx, new_state);
+   _tnl_invalidate_vertex_state(ctx, new_state);
+   intel_context(ctx)->NewGLState |= new_state;
+}
+
+
+void
+intelFlush(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   if (intel->Fallback)
+      _swrast_flush(ctx);
+
+   INTEL_FIREVERTICES(intel);
+
+   if (intel->batch->map != intel->batch->ptr)
+      intel_batchbuffer_flush(intel->batch);
+
+   /* XXX: Need to do an MI_FLUSH here.
+    */
+}
+
+
+/**
+ * Check if we need to rotate/warp the front color buffer to the
+ * rotated screen.  We generally need to do this when we get a glFlush
+ * or glFinish after drawing to the front color buffer.
+ */
+static void
+intelCheckFrontRotate(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+   if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] ==
+       BUFFER_BIT_FRONT_LEFT) {
+      intelScreenPrivate *screen = intel->intelScreen;
+      if (screen->current_rotation != 0) {
+         __DRIdrawablePrivate *dPriv = intel->driDrawable;
+         intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
+      }
+   }
+}
+
+
+/**
+ * Called via glFlush.
+ */
+static void
+intelglFlush(GLcontext * ctx)
+{
+   intelFlush(ctx);
+   intelCheckFrontRotate(ctx);
+}
+
+void
+intelFinish(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+   intelFlush(ctx);
+   if (intel->batch->last_fence) {
+      driFenceFinish(intel->batch->last_fence,
+                     0, GL_FALSE);
+      driFenceUnReference(intel->batch->last_fence);
+      intel->batch->last_fence = NULL;
+   }
+   intelCheckFrontRotate(ctx);
+}
+
+
+void
+intelInitDriverFunctions(struct dd_function_table *functions)
+{
+   _mesa_init_driver_functions(functions);
+
+   functions->Flush = intelglFlush;
+   functions->Finish = intelFinish;
+   functions->GetString = intelGetString;
+   functions->UpdateState = intelInvalidateState;
+   functions->CopyColorTable = _swrast_CopyColorTable;
+   functions->CopyColorSubTable = _swrast_CopyColorSubTable;
+   functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+   functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+   intelInitTextureFuncs(functions);
+   intelInitPixelFuncs(functions);
+   intelInitStateFuncs(functions);
+   intelInitBufferFuncs(functions);
+}
+
+
+GLboolean
+intelInitContext(struct intel_context *intel,
+                 const __GLcontextModes * mesaVis,
+                 __DRIcontextPrivate * driContextPriv,
+                 void *sharedContextPrivate,
+                 struct dd_function_table *functions)
+{
+   GLcontext *ctx = &intel->ctx;
+   GLcontext *shareCtx = (GLcontext *) sharedContextPrivate;
+   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
+   drmI830Sarea *saPriv = (drmI830Sarea *)
+      (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
+   int fthrottle_mode;
+
+   if (!_mesa_initialize_context(&intel->ctx,
+                                 mesaVis, shareCtx,
+                                 functions, (void *) intel))
+      return GL_FALSE;
+
+   driContextPriv->driverPrivate = intel;
+   intel->intelScreen = intelScreen;
+   intel->driScreen = sPriv;
+   intel->sarea = saPriv;
+
+   if (!lockMutexInit) {
+      lockMutexInit = GL_TRUE;
+      _glthread_INIT_MUTEX(lockMutex);
+   }
+
+   driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
+                       intel->driScreen->myNum, "i915");
+
+   ctx->Const.MaxTextureMaxAnisotropy = 2.0;
+
+   /* This doesn't yet catch all non-conformant rendering, but it's a
+    * start.
+    */
+   if (getenv("INTEL_STRICT_CONFORMANCE")) {
+      intel->strict_conformance = 1;
+   }
+
+   ctx->Const.MinLineWidth = 1.0;
+   ctx->Const.MinLineWidthAA = 1.0;
+   ctx->Const.MaxLineWidth = 3.0;
+   ctx->Const.MaxLineWidthAA = 3.0;
+   ctx->Const.LineWidthGranularity = 1.0;
+
+   ctx->Const.MinPointSize = 1.0;
+   ctx->Const.MinPointSizeAA = 1.0;
+   ctx->Const.MaxPointSize = 255.0;
+   ctx->Const.MaxPointSizeAA = 3.0;
+   ctx->Const.PointSizeGranularity = 1.0;
+
+   ctx->Const.MaxColorAttachments = 4;  /* XXX FBO: review this */
+
+   /* Initialize the software rasterizer and helper modules. */
+   _swrast_CreateContext(ctx);
+   _ac_CreateContext(ctx);
+   _tnl_CreateContext(ctx);
+   _swsetup_CreateContext(ctx);
+
+   /* Install the customized pipeline: */
+   _tnl_destroy_pipeline(ctx);
+   _tnl_install_pipeline(ctx, intel_pipeline);
+
+   /* Configure swrast to match hardware characteristics: */
+   _swrast_allow_pixel_fog(ctx, GL_FALSE);
+   _swrast_allow_vertex_fog(ctx, GL_TRUE);
+
+   /* Dri stuff */
+   intel->hHWContext = driContextPriv->hHWContext;
+   intel->driFd = sPriv->fd;
+   intel->driHwLock = (drmLock *) & sPriv->pSAREA->lock;
+
+   intel->hw_stipple = 1;
+
+   /* XXX FBO: this doesn't seem to be used anywhere */
+   switch (mesaVis->depthBits) {
+   case 0:                     /* what to do in this case? */
+   case 16:
+      intel->polygon_offset_scale = 1.0 / 0xffff;
+      break;
+   case 24:
+      intel->polygon_offset_scale = 2.0 / 0xffffff;     /* req'd to pass glean */
+      break;
+   default:
+      assert(0);
+      break;
+   }
+
+   /* Initialize swrast, tnl driver tables: */
+   intelInitSpanFuncs(ctx);
+   intelInitTriFuncs(ctx);
+
+
+   intel->RenderIndex = ~0;
+
+   fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode");
+   intel->iw.irq_seq = -1;
+   intel->irqsEmitted = 0;
+
+   intel->do_irqs = (intel->intelScreen->irq_active &&
+                     fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS);
+
+   intel->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
+
+   intel->vblank_flags = (intel->intelScreen->irq_active != 0)
+      ? driGetDefaultVBlankFlags(&intel->optionCache) : VBLANK_FLAG_NO_IRQ;
+
+   (*dri_interface->getUST) (&intel->swap_ust);
+   _math_matrix_ctr(&intel->ViewportMatrix);
+
+   /* Disable imaging extension until convolution is working in
+    * teximage paths:
+    */
+   driInitExtensions(ctx, card_extensions,
+/*                   GL_TRUE, */
+                     GL_FALSE);
+
+
+   intel->batch = intel_batchbuffer_alloc(intel);
+   intel->last_swap_fence = NULL;
+   intel->first_swap_fence = NULL;
+
+   intel_bufferobj_init(intel);
+   intel_fbo_init(intel);
+
+   if (intel->ctx.Mesa_DXTn) {
+      _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+      _mesa_enable_extension(ctx, "GL_S3_s3tc");
+   }
+   else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) {
+      _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+   }
+
+   intel->prim.primitive = ~0;
+
+
+#if DO_DEBUG
+   INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control);
+#endif
+
+   if (getenv("INTEL_NO_RAST")) {
+      fprintf(stderr, "disabling 3D rasterization\n");
+      FALLBACK(intel, INTEL_FALLBACK_USER, 1);
+   }
+
+   return GL_TRUE;
+}
+
+void
+intelDestroyContext(__DRIcontextPrivate * driContextPriv)
+{
+   struct intel_context *intel =
+      (struct intel_context *) driContextPriv->driverPrivate;
+
+   assert(intel);               /* should never be null */
+   if (intel) {
+      GLboolean release_texture_heaps;
+
+      INTEL_FIREVERTICES(intel);
+
+      intel->vtbl.destroy(intel);
+
+      release_texture_heaps = (intel->ctx.Shared->RefCount == 1);
+      _swsetup_DestroyContext(&intel->ctx);
+      _tnl_DestroyContext(&intel->ctx);
+      _ac_DestroyContext(&intel->ctx);
+
+      _swrast_DestroyContext(&intel->ctx);
+      intel->Fallback = 0;      /* don't call _swrast_Flush later */
+
+      intel_batchbuffer_free(intel->batch);
+
+      if (intel->last_swap_fence) {
+        driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
+        driFenceUnReference(intel->last_swap_fence);
+        intel->last_swap_fence = NULL;
+      }
+      if (intel->first_swap_fence) {
+        driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
+        driFenceUnReference(intel->first_swap_fence);
+        intel->first_swap_fence = NULL;
+      }
+
+
+      if (release_texture_heaps) {
+         /* This share group is about to go away, free our private
+          * texture object data.
+          */
+         if (INTEL_DEBUG & DEBUG_TEXTURE)
+            fprintf(stderr, "do something to free texture heaps\n");
+      }
+
+      /* free the Mesa context */
+      _mesa_free_context_data(&intel->ctx);
+   }
+}
+
+GLboolean
+intelUnbindContext(__DRIcontextPrivate * driContextPriv)
+{
+   return GL_TRUE;
+}
+
+GLboolean
+intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
+                 __DRIdrawablePrivate * driDrawPriv,
+                 __DRIdrawablePrivate * driReadPriv)
+{
+
+   if (driContextPriv) {
+      struct intel_context *intel =
+         (struct intel_context *) driContextPriv->driverPrivate;
+      GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate;
+      GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate;
+
+
+      /* XXX FBO temporary fix-ups! */
+      /* if the renderbuffers don't have regions, init them from the context */
+      {
+         struct intel_renderbuffer *irbFront
+            = intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT);
+         struct intel_renderbuffer *irbBack
+            = intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT);
+         struct intel_renderbuffer *irbDepth
+            = intel_get_renderbuffer(drawFb, BUFFER_DEPTH);
+         struct intel_renderbuffer *irbStencil
+            = intel_get_renderbuffer(drawFb, BUFFER_STENCIL);
+
+         if (irbFront && !irbFront->region) {
+            intel_region_reference(&irbFront->region, intel->intelScreen->front_region);
+         }
+         if (irbBack && !irbBack->region) {
+            intel_region_reference(&irbBack->region, intel->intelScreen->back_region);
+         }
+         if (irbDepth && !irbDepth->region) {
+            intel_region_reference(&irbDepth->region, intel->intelScreen->depth_region);
+         }
+         if (irbStencil && !irbStencil->region) {
+            intel_region_reference(&irbStencil->region, intel->intelScreen->depth_region);
+         }
+      }
+
+      _mesa_make_current(&intel->ctx, drawFb, readFb);
+
+      /* The drawbuffer won't always be updated by _mesa_make_current: 
+       */
+      if (intel->ctx.DrawBuffer == drawFb) {
+
+        if (intel->driDrawable != driDrawPriv) {
+           driDrawableInitVBlank(driDrawPriv, intel->vblank_flags, &intel->vbl_seq);       
+           intel->driDrawable = driDrawPriv;
+           intelWindowMoved(intel);
+        }
+
+        intel_draw_buffer(&intel->ctx, drawFb);
+      }
+   }
+   else {
+      _mesa_make_current(NULL, NULL, NULL);
+   }
+
+   return GL_TRUE;
+}
+
+static void
+intelContendedLock(struct intel_context *intel, GLuint flags)
+{
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   __DRIscreenPrivate *sPriv = intel->driScreen;
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
+   drmI830Sarea *sarea = intel->sarea;
+
+   drmGetLock(intel->driFd, intel->hHWContext, flags);
+
+   if (INTEL_DEBUG & DEBUG_LOCK)
+      _mesa_printf("%s - got contended lock\n", __progname);
+
+   /* If the window moved, may need to set a new cliprect now.
+    *
+    * NOTE: This releases and regains the hw lock, so all state
+    * checking must be done *after* this call:
+    */
+   if (dPriv)
+      DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+
+   if (sarea->width != intelScreen->width ||
+       sarea->height != intelScreen->height ||
+       sarea->rotation != intelScreen->current_rotation) {
+
+      intelUpdateScreenRotation(sPriv, sarea);
+
+      /* 
+       * This will drop the outstanding batchbuffer on the floor
+       * FIXME: This should be done for all contexts?
+       */
+
+      intel_batchbuffer_reset(intel->batch);
+
+      /* lose all primitives */
+      intel->prim.primitive = ~0;
+      intel->prim.start_ptr = 0;
+      intel->prim.flush = 0;
+
+      /* re-emit all state */
+      intel->vtbl.lost_hardware(intel);
+
+      /* force window update */
+      intel->lastStamp = 0;
+   }
+
+
+   /* Drawable changed?
+    */
+   if (dPriv && intel->lastStamp != dPriv->lastStamp) {
+      intelWindowMoved(intel);
+      intel->lastStamp = dPriv->lastStamp;
+   }
+}
+
+
+extern _glthread_Mutex lockMutex;
+
+
+/* Lock the hardware and validate our state.  
+ */
+void LOCK_HARDWARE( struct intel_context *intel )
+{
+    char __ret=0;
+
+    _glthread_LOCK_MUTEX(lockMutex);
+    assert(!intel->locked);
+
+    if (intel->swap_scheduled) {
+       drmVBlank vbl;
+       vbl.request.type = DRM_VBLANK_ABSOLUTE;
+       if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) {
+           vbl.request.type |= DRM_VBLANK_SECONDARY;
+       }
+       vbl.request.sequence = intel->vbl_seq;
+       drmWaitVBlank(intel->driFd, &vbl);
+       intel->swap_scheduled = 0;
+    }
+
+    DRM_CAS(intel->driHwLock, intel->hHWContext,
+        (DRM_LOCK_HELD|intel->hHWContext), __ret);
+
+    if (__ret)
+        intelContendedLock( intel, 0 );
+
+    if (INTEL_DEBUG & DEBUG_LOCK)
+      _mesa_printf("%s - locked\n", __progname);
+
+    intel->locked = 1;
+}
+
+
+  /* Unlock the hardware using the global current context 
+   */
+void UNLOCK_HARDWARE( struct intel_context *intel )
+{
+   intel->locked = 0;
+
+   DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
+
+   _glthread_UNLOCK_MUTEX(lockMutex);
+
+   if (INTEL_DEBUG & DEBUG_LOCK)
+      _mesa_printf("%s - unlocked\n", __progname);
+} 
+
diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h
new file mode 100644 (file)
index 0000000..fa3cf58
--- /dev/null
@@ -0,0 +1,502 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTELCONTEXT_INC
+#define INTELCONTEXT_INC
+
+
+
+#include "mtypes.h"
+#include "drm.h"
+#include "mm.h"
+#include "texmem.h"
+
+#include "intel_screen.h"
+#include "i915_drm.h"
+#include "i830_common.h"
+#include "tnl/t_vertex.h"
+
+#define TAG(x) intel##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+#define DV_PF_555  (1<<8)
+#define DV_PF_565  (2<<8)
+#define DV_PF_8888 (3<<8)
+
+struct intel_region;
+struct intel_context;
+struct _DriBufferObject;
+
+typedef void (*intel_tri_func) (struct intel_context *, intelVertex *,
+                                intelVertex *, intelVertex *);
+typedef void (*intel_line_func) (struct intel_context *, intelVertex *,
+                                 intelVertex *);
+typedef void (*intel_point_func) (struct intel_context *, intelVertex *);
+
+#define INTEL_FALLBACK_DRAW_BUFFER      0x1
+#define INTEL_FALLBACK_READ_BUFFER      0x2
+#define INTEL_FALLBACK_DEPTH_BUFFER      0x4
+#define INTEL_FALLBACK_STENCIL_BUFFER    0x8
+#define INTEL_FALLBACK_USER             0x10
+#define INTEL_FALLBACK_RENDERMODE       0x20
+
+extern void intelFallback(struct intel_context *intel, GLuint bit,
+                          GLboolean mode);
+#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
+
+
+#define INTEL_WRITE_PART  0x1
+#define INTEL_WRITE_FULL  0x2
+#define INTEL_READ        0x4
+
+struct intel_texture_object
+{
+   struct gl_texture_object base;       /* The "parent" object */
+
+   /* The mipmap tree must include at least these levels once
+    * validated:
+    */
+   GLuint firstLevel;
+   GLuint lastLevel;
+
+   /* Offset for firstLevel image:
+    */
+   GLuint textureOffset;
+
+   /* On validation any active images held in main memory or in other
+    * regions will be copied to this region and the old storage freed.
+    */
+   struct intel_mipmap_tree *mt;
+};
+
+
+
+struct intel_texture_image
+{
+   struct gl_texture_image base;
+
+   /* These aren't stored in gl_texture_image 
+    */
+   GLuint level;
+   GLuint face;
+
+   /* If intelImage->mt != NULL, image data is stored here.
+    * Else if intelImage->base.Data != NULL, image is stored there.
+    * Else there is no image data.
+    */
+   struct intel_mipmap_tree *mt;
+};
+
+
+#define INTEL_MAX_FIXUP 64
+
+struct intel_context
+{
+   GLcontext ctx;               /* the parent class */
+
+   struct
+   {
+      void (*destroy) (struct intel_context * intel);
+      void (*emit_state) (struct intel_context * intel);
+      void (*lost_hardware) (struct intel_context * intel);
+      void (*update_texture_state) (struct intel_context * intel);
+
+      void (*render_start) (struct intel_context * intel);
+      void (*set_draw_region) (struct intel_context * intel,
+                               struct intel_region * draw_region,
+                               struct intel_region * depth_region);
+
+        GLuint(*flush_cmd) (void);
+
+      void (*reduced_primitive_state) (struct intel_context * intel,
+                                       GLenum rprim);
+
+        GLboolean(*check_vertex_size) (struct intel_context * intel,
+                                       GLuint expected);
+
+
+      /* Metaops: 
+       */
+      void (*install_meta_state) (struct intel_context * intel);
+      void (*leave_meta_state) (struct intel_context * intel);
+
+      void (*meta_draw_region) (struct intel_context * intel,
+                                struct intel_region * draw_region,
+                                struct intel_region * depth_region);
+
+      void (*meta_color_mask) (struct intel_context * intel, GLboolean);
+
+      void (*meta_stencil_replace) (struct intel_context * intel,
+                                    GLuint mask, GLuint clear);
+
+      void (*meta_depth_replace) (struct intel_context * intel);
+
+      void (*meta_texture_blend_replace) (struct intel_context * intel);
+
+      void (*meta_no_stencil_write) (struct intel_context * intel);
+      void (*meta_no_depth_write) (struct intel_context * intel);
+      void (*meta_no_texture) (struct intel_context * intel);
+
+      void (*meta_import_pixel_state) (struct intel_context * intel);
+
+        GLboolean(*meta_tex_rect_source) (struct intel_context * intel,
+                                          struct _DriBufferObject * buffer,
+                                          GLuint offset,
+                                          GLuint pitch,
+                                          GLuint height,
+                                          GLenum format, GLenum type);
+      void (*rotate_window) (struct intel_context * intel,
+                             __DRIdrawablePrivate * dPriv, GLuint srcBuf);
+
+      void (*assert_not_dirty) (struct intel_context *intel);
+
+   } vtbl;
+
+   GLint refcount;
+   GLuint Fallback;
+   GLuint NewGLState;
+
+   struct _DriFenceObject *last_swap_fence;
+   struct _DriFenceObject *first_swap_fence;
+
+   struct intel_batchbuffer *batch;
+
+   struct
+   {
+      GLuint id;
+      GLuint primitive;
+      GLubyte *start_ptr;
+      void (*flush) (struct intel_context *);
+   } prim;
+
+   GLboolean locked;
+   char *prevLockFile;
+   int prevLockLine;
+
+   GLuint ClearColor565;
+   GLuint ClearColor8888;
+
+   /* Offsets of fields within the current vertex:
+    */
+   GLuint coloroffset;
+   GLuint specoffset;
+   GLuint wpos_offset;
+   GLuint wpos_size;
+
+   struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
+   GLuint vertex_attr_count;
+
+   GLfloat polygon_offset_scale;        /* dependent on depth_scale, bpp */
+
+   GLboolean hw_stipple;
+   GLboolean strict_conformance;
+
+   /* AGP memory buffer manager:
+    */
+   struct bufmgr *bm;
+
+
+   /* State for intelvb.c and inteltris.c.
+    */
+   GLuint RenderIndex;
+   GLmatrix ViewportMatrix;
+   GLenum render_primitive;
+   GLenum reduced_primitive;
+   GLuint vertex_size;
+   GLubyte *verts;              /* points to tnl->clipspace.vertex_buf */
+
+#if 0
+   struct intel_region *front_region;   /* XXX FBO: obsolete */
+   struct intel_region *rotated_region; /* XXX FBO: obsolete */
+   struct intel_region *back_region;    /* XXX FBO: obsolete */
+   struct intel_region *draw_region;    /* XXX FBO: rename to color_region */
+   struct intel_region *depth_region;   /**< currently bound depth/Z region */
+#endif
+
+   /* Fallback rasterization functions 
+    */
+   intel_point_func draw_point;
+   intel_line_func draw_line;
+   intel_tri_func draw_tri;
+
+   /* These refer to the current drawing buffer:
+    */
+   int drawX, drawY;            /**< origin of drawing area within region */
+   GLuint numClipRects;         /**< cliprects for drawing */
+   drm_clip_rect_t *pClipRects;
+   drm_clip_rect_t fboRect;     /**< cliprect for FBO rendering */
+
+   int perf_boxes;
+
+   GLuint do_usleeps;
+   int do_irqs;
+   GLuint irqsEmitted;
+   drm_i915_irq_wait_t iw;
+
+   drm_context_t hHWContext;
+   drmLock *driHwLock;
+   int driFd;
+
+   __DRIdrawablePrivate *driDrawable;
+   __DRIscreenPrivate *driScreen;
+   intelScreenPrivate *intelScreen;
+   drmI830Sarea *sarea;
+
+   GLuint lastStamp;
+
+   /**
+    * Configuration cache
+    */
+   driOptionCache optionCache;
+
+   /* VBI
+    */
+   GLuint vbl_seq;
+   GLuint vblank_flags;
+
+   int64_t swap_ust;
+   int64_t swap_missed_ust;
+
+   GLuint swap_count;
+   GLuint swap_missed_count;
+
+   GLuint swap_scheduled;
+};
+
+/* These are functions now:
+ */
+void LOCK_HARDWARE( struct intel_context *intel );
+void UNLOCK_HARDWARE( struct intel_context *intel );
+
+extern char *__progname;
+
+
+#define SUBPIXEL_X 0.125
+#define SUBPIXEL_Y 0.125
+
+#define INTEL_FIREVERTICES(intel)              \
+do {                                           \
+   if ((intel)->prim.flush)                    \
+      (intel)->prim.flush(intel);              \
+} while (0)
+
+/* ================================================================
+ * Color packing:
+ */
+
+#define INTEL_PACKCOLOR4444(r,g,b,a) \
+  ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+#define INTEL_PACKCOLOR1555(r,g,b,a) \
+  ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+    ((a) ? 0x8000 : 0))
+
+#define INTEL_PACKCOLOR565(r,g,b) \
+  ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+#define INTEL_PACKCOLOR8888(r,g,b,a) \
+  ((a<<24) | (r<<16) | (g<<8) | b)
+
+
+
+/* ================================================================
+ * From linux kernel i386 header files, copes with odd sizes better
+ * than COPY_DWORDS would:
+ * XXX Put this in src/mesa/main/imports.h ???
+ */
+#if defined(i386) || defined(__i386__)
+static INLINE void *
+__memcpy(void *to, const void *from, size_t n)
+{
+   int d0, d1, d2;
+   __asm__ __volatile__("rep ; movsl\n\t"
+                        "testb $2,%b4\n\t"
+                        "je 1f\n\t"
+                        "movsw\n"
+                        "1:\ttestb $1,%b4\n\t"
+                        "je 2f\n\t"
+                        "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
+                        :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
+                        :"memory");
+   return (to);
+}
+#else
+#define __memcpy(a,b,c) memcpy(a,b,c)
+#endif
+
+
+
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG               1
+#if DO_DEBUG
+extern int INTEL_DEBUG;
+#else
+#define INTEL_DEBUG            0
+#endif
+
+#define DEBUG_TEXTURE  0x1
+#define DEBUG_STATE    0x2
+#define DEBUG_IOCTL    0x4
+#define DEBUG_BLIT     0x8
+#define DEBUG_MIPTREE   0x10
+#define DEBUG_FALLBACKS        0x20
+#define DEBUG_VERBOSE  0x40
+#define DEBUG_BATCH     0x80
+#define DEBUG_PIXEL     0x100
+#define DEBUG_BUFMGR    0x200
+#define DEBUG_REGION    0x400
+#define DEBUG_FBO       0x800
+#define DEBUG_LOCK      0x1000
+
+#define DBG(...)  do { if (INTEL_DEBUG & FILE_DEBUG_FLAG) _mesa_printf(__VA_ARGS__); } while(0)
+
+
+#define PCI_CHIP_845_G                 0x2562
+#define PCI_CHIP_I830_M                        0x3577
+#define PCI_CHIP_I855_GM               0x3582
+#define PCI_CHIP_I865_G                        0x2572
+#define PCI_CHIP_I915_G                        0x2582
+#define PCI_CHIP_I915_GM               0x2592
+#define PCI_CHIP_I945_G                        0x2772
+#define PCI_CHIP_I945_GM               0x27A2
+
+
+/* ================================================================
+ * intel_context.c:
+ */
+
+extern GLboolean intelInitContext(struct intel_context *intel,
+                                  const __GLcontextModes * mesaVis,
+                                  __DRIcontextPrivate * driContextPriv,
+                                  void *sharedContextPrivate,
+                                  struct dd_function_table *functions);
+
+extern void intelGetLock(struct intel_context *intel, GLuint flags);
+
+extern void intelInitState(GLcontext * ctx);
+extern void intelFinish(GLcontext * ctx);
+extern void intelFlush(GLcontext * ctx);
+
+extern void intelInitDriverFunctions(struct dd_function_table *functions);
+
+
+/* ================================================================
+ * intel_state.c:
+ */
+extern void intelInitStateFuncs(struct dd_function_table *functions);
+
+#define COMPAREFUNC_ALWAYS             0
+#define COMPAREFUNC_NEVER              0x1
+#define COMPAREFUNC_LESS               0x2
+#define COMPAREFUNC_EQUAL              0x3
+#define COMPAREFUNC_LEQUAL             0x4
+#define COMPAREFUNC_GREATER            0x5
+#define COMPAREFUNC_NOTEQUAL           0x6
+#define COMPAREFUNC_GEQUAL             0x7
+
+#define STENCILOP_KEEP                 0
+#define STENCILOP_ZERO                 0x1
+#define STENCILOP_REPLACE              0x2
+#define STENCILOP_INCRSAT              0x3
+#define STENCILOP_DECRSAT              0x4
+#define STENCILOP_INCR                 0x5
+#define STENCILOP_DECR                 0x6
+#define STENCILOP_INVERT               0x7
+
+#define LOGICOP_CLEAR                  0
+#define LOGICOP_NOR                    0x1
+#define LOGICOP_AND_INV                0x2
+#define LOGICOP_COPY_INV               0x3
+#define LOGICOP_AND_RVRSE              0x4
+#define LOGICOP_INV                    0x5
+#define LOGICOP_XOR                    0x6
+#define LOGICOP_NAND                   0x7
+#define LOGICOP_AND                    0x8
+#define LOGICOP_EQUIV                  0x9
+#define LOGICOP_NOOP                   0xa
+#define LOGICOP_OR_INV                 0xb
+#define LOGICOP_COPY                   0xc
+#define LOGICOP_OR_RVRSE               0xd
+#define LOGICOP_OR                     0xe
+#define LOGICOP_SET                    0xf
+
+#define BLENDFACT_ZERO                 0x01
+#define BLENDFACT_ONE                  0x02
+#define BLENDFACT_SRC_COLR             0x03
+#define BLENDFACT_INV_SRC_COLR                 0x04
+#define BLENDFACT_SRC_ALPHA            0x05
+#define BLENDFACT_INV_SRC_ALPHA        0x06
+#define BLENDFACT_DST_ALPHA            0x07
+#define BLENDFACT_INV_DST_ALPHA        0x08
+#define BLENDFACT_DST_COLR             0x09
+#define BLENDFACT_INV_DST_COLR         0x0a
+#define BLENDFACT_SRC_ALPHA_SATURATE   0x0b
+#define BLENDFACT_CONST_COLOR          0x0c
+#define BLENDFACT_INV_CONST_COLOR      0x0d
+#define BLENDFACT_CONST_ALPHA          0x0e
+#define BLENDFACT_INV_CONST_ALPHA      0x0f
+#define BLENDFACT_MASK                 0x0f
+
+#define MI_BATCH_BUFFER_END    (0xA<<23)
+
+
+extern int intel_translate_compare_func(GLenum func);
+extern int intel_translate_stencil_op(GLenum op);
+extern int intel_translate_blend_factor(GLenum factor);
+extern int intel_translate_logic_op(GLenum opcode);
+
+
+/*======================================================================
+ * Inline conversion functions.  
+ * These are better-typed than the macros used previously:
+ */
+static INLINE struct intel_context *
+intel_context(GLcontext * ctx)
+{
+   return (struct intel_context *) ctx;
+}
+
+static INLINE struct intel_texture_object *
+intel_texture_object(struct gl_texture_object *obj)
+{
+   return (struct intel_texture_object *) obj;
+}
+
+static INLINE struct intel_texture_image *
+intel_texture_image(struct gl_texture_image *img)
+{
+   return (struct intel_texture_image *) img;
+}
+
+extern struct intel_renderbuffer *intel_renderbuffer(struct gl_renderbuffer
+                                                     *rb);
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_depthstencil.c b/src/mesa/drivers/dri/i915tex/intel_depthstencil.c
new file mode 100644 (file)
index 0000000..d269a85
--- /dev/null
@@ -0,0 +1,282 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "depthstencil.h"
+#include "fbobject.h"
+#include "framebuffer.h"
+#include "hash.h"
+#include "mtypes.h"
+#include "renderbuffer.h"
+
+#include "intel_context.h"
+#include "intel_fbo.h"
+#include "intel_depthstencil.h"
+#include "intel_regions.h"
+
+
+/**
+ * The GL_EXT_framebuffer_object allows the user to create their own
+ * framebuffer objects consisting of color renderbuffers (0 or more),
+ * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
+ *
+ * The spec considers depth and stencil renderbuffers to be totally independent
+ * buffers.  In reality, most graphics hardware today uses a combined
+ * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
+ *
+ * This causes difficulty because the user may create some number of depth
+ * renderbuffers and some number of stencil renderbuffers and bind them
+ * together in framebuffers in any combination.
+ *
+ * This code manages all that.
+ *
+ * 1. Depth renderbuffers are always allocated in hardware as 32bpp
+ *    GL_DEPTH24_STENCIL8 buffers.
+ *
+ * 2. Stencil renderbuffers are initially allocated in software as 8bpp
+ *    GL_STENCIL_INDEX8 buffers.
+ *
+ * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
+ *    fields (respectively) to indicate if the buffer's currently paired
+ *    with another stencil or depth buffer (respectively).
+ *
+ * 4. When a depth and stencil buffer are initially both attached to the
+ *    current framebuffer, we merge the stencil buffer values into the
+ *    depth buffer (really a depth+stencil buffer).  The then hardware uses
+ *    the combined buffer.
+ *
+ * 5. Whenever a depth or stencil buffer is reallocated (with
+ *    glRenderbufferStorage) we undo the pairing and copy the stencil values
+ *    from the combined depth/stencil buffer back to the stencil-only buffer.
+ *
+ * 6. We also undo the pairing when we find a change in buffer bindings.
+ *
+ * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
+ *    just use the combined depth/stencil buffer and ignore the stencil values.
+ *
+ * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
+ *    to promote the 8bpp software stencil buffer to a 32bpp hardware
+ *    depth+stencil buffer.
+ *
+ */
+
+
+
+static void
+map_regions(GLcontext * ctx,
+            struct intel_renderbuffer *depthRb,
+            struct intel_renderbuffer *stencilRb)
+{
+   struct intel_context *intel = intel_context(ctx);
+   if (depthRb && depthRb->region) {
+      intel_region_map(intel->intelScreen, depthRb->region);
+      depthRb->pfMap = depthRb->region->map;
+      depthRb->pfPitch = depthRb->region->pitch;
+   }
+   if (stencilRb && stencilRb->region) {
+      intel_region_map(intel->intelScreen, stencilRb->region);
+      stencilRb->pfMap = stencilRb->region->map;
+      stencilRb->pfPitch = stencilRb->region->pitch;
+   }
+}
+
+static void
+unmap_regions(GLcontext * ctx,
+              struct intel_renderbuffer *depthRb,
+              struct intel_renderbuffer *stencilRb)
+{
+   struct intel_context *intel = intel_context(ctx);
+   if (depthRb && depthRb->region) {
+      intel_region_unmap(intel->intelScreen, depthRb->region);
+      depthRb->pfMap = NULL;
+      depthRb->pfPitch = 0;
+   }
+   if (stencilRb && stencilRb->region) {
+      intel_region_unmap(intel->intelScreen, stencilRb->region);
+      stencilRb->pfMap = NULL;
+      stencilRb->pfPitch = 0;
+   }
+}
+
+
+
+/**
+ * Undo the pairing/interleaving between depth and stencil buffers.
+ * irb should be a depth/stencil or stencil renderbuffer.
+ */
+void
+intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb)
+{
+   if (irb->PairedStencil) {
+      /* irb is a depth/stencil buffer */
+      struct gl_renderbuffer *stencilRb;
+      struct intel_renderbuffer *stencilIrb;
+
+      ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+
+      stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
+      stencilIrb = intel_renderbuffer(stencilRb);
+      if (stencilIrb) {
+         /* need to extract stencil values from the depth buffer */
+         ASSERT(stencilIrb->PairedDepth == irb->Base.Name);
+         map_regions(ctx, irb, stencilIrb);
+         _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base);
+         unmap_regions(ctx, irb, stencilIrb);
+         stencilIrb->PairedDepth = 0;
+      }
+      irb->PairedStencil = 0;
+   }
+   else if (irb->PairedDepth) {
+      /* irb is a stencil buffer */
+      struct gl_renderbuffer *depthRb;
+      struct intel_renderbuffer *depthIrb;
+
+      ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
+             irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+
+      depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
+      depthIrb = intel_renderbuffer(depthRb);
+      if (depthIrb) {
+         /* need to extract stencil values from the depth buffer */
+         ASSERT(depthIrb->PairedStencil == irb->Base.Name);
+         map_regions(ctx, depthIrb, irb);
+         _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base);
+         unmap_regions(ctx, depthIrb, irb);
+         depthIrb->PairedStencil = 0;
+      }
+      irb->PairedDepth = 0;
+   }
+   else {
+      _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
+   }
+
+   ASSERT(irb->PairedStencil == 0);
+   ASSERT(irb->PairedDepth == 0);
+}
+
+
+/**
+ * Examine the depth and stencil renderbuffers which are attached to the
+ * framebuffer.  If both depth and stencil are attached, make sure that the
+ * renderbuffers are 'paired' (combined).  If only depth or only stencil is
+ * attached, undo any previous pairing.
+ *
+ * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
+ * change, for example).
+ */
+void
+intel_validate_paired_depth_stencil(GLcontext * ctx,
+                                    struct gl_framebuffer *fb)
+{
+   struct intel_renderbuffer *depthRb, *stencilRb;
+
+   depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
+   stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+   if (depthRb && stencilRb) {
+      if (depthRb == stencilRb) {
+         /* Using a user-created combined depth/stencil buffer.
+          * Nothing to do.
+          */
+         ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
+         ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+      }
+      else {
+         /* Separate depth/stencil buffers, need to interleave now */
+         ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT);
+         ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX);
+         /* may need to interleave depth/stencil now */
+         if (depthRb->PairedStencil == stencilRb->Base.Name) {
+            /* OK, the depth and stencil buffers are already interleaved */
+            ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
+         }
+         else {
+            /* need to setup new pairing/interleaving */
+            if (depthRb->PairedStencil) {
+               intel_unpair_depth_stencil(ctx, depthRb);
+            }
+            if (stencilRb->PairedDepth) {
+               intel_unpair_depth_stencil(ctx, stencilRb);
+            }
+
+            ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+            ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
+                   stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+
+            /* establish new pairing: interleave stencil into depth buffer */
+            map_regions(ctx, depthRb, stencilRb);
+            _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
+            unmap_regions(ctx, depthRb, stencilRb);
+            depthRb->PairedStencil = stencilRb->Base.Name;
+            stencilRb->PairedDepth = depthRb->Base.Name;
+         }
+
+      }
+   }
+   else if (depthRb) {
+      /* Depth buffer but no stencil buffer.
+       * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
+       */
+      /* can't assert this until storage is allocated:
+         ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+       */
+      /* intel_undo any previous pairing */
+      if (depthRb->PairedStencil) {
+         intel_unpair_depth_stencil(ctx, depthRb);
+      }
+   }
+   else if (stencilRb) {
+      /* Stencil buffer but no depth buffer.
+       * Since h/w doesn't typically support just 8bpp stencil w/out Z,
+       * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
+       */
+      /* undo any previous pairing */
+      if (stencilRb->PairedDepth) {
+         intel_unpair_depth_stencil(ctx, stencilRb);
+      }
+      if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
+         /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
+         _mesa_promote_stencil(ctx, &stencilRb->Base);
+         ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
+      }
+   }
+
+   /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
+   _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
+   if (depthRb && depthRb->PairedStencil)
+      _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH);
+   else
+      _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
+
+
+   /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
+    * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
+    * if present.
+    */
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_depthstencil.h b/src/mesa/drivers/dri/i915tex/intel_depthstencil.h
new file mode 100644 (file)
index 0000000..2d3fc48
--- /dev/null
@@ -0,0 +1,14 @@
+
+#ifndef INTEL_DEPTH_STENCIL_H
+#define INTEL_DEPTH_STENCIL_H
+
+
+extern void
+intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb);
+
+extern void
+intel_validate_paired_depth_stencil(GLcontext * ctx,
+                                    struct gl_framebuffer *fb);
+
+
+#endif /* INTEL_DEPTH_STENCIL_H */
diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c
new file mode 100644 (file)
index 0000000..ab0e569
--- /dev/null
@@ -0,0 +1,622 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "imports.h"
+#include "mtypes.h"
+#include "fbobject.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "context.h"
+#include "texformat.h"
+#include "texrender.h"
+
+#include "intel_context.h"
+#include "intel_buffers.h"
+#include "intel_depthstencil.h"
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
+#include "intel_span.h"
+
+
+#define FILE_DEBUG_FLAG DEBUG_FBO
+
+#define INTEL_RB_CLASS 0x12345678
+
+
+/* XXX FBO: move this to intel_context.h (inlined) */
+/**
+ * Return a gl_renderbuffer ptr casted to intel_renderbuffer.
+ * NULL will be returned if the rb isn't really an intel_renderbuffer.
+ * This is determiend by checking the ClassID.
+ */
+struct intel_renderbuffer *
+intel_renderbuffer(struct gl_renderbuffer *rb)
+{
+   struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
+   if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
+      /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
+      return irb;
+   }
+   else
+      return NULL;
+}
+
+
+struct intel_renderbuffer *
+intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)
+{
+   return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
+}
+
+
+struct intel_region *
+intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
+{
+   struct intel_renderbuffer *irb
+      = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
+   if (irb)
+      return irb->region;
+   else
+      return NULL;
+}
+
+
+
+/**
+ * Create a new framebuffer object.
+ */
+static struct gl_framebuffer *
+intel_new_framebuffer(GLcontext * ctx, GLuint name)
+{
+   /* there's no intel_framebuffer at this time, just use Mesa's class */
+   return _mesa_new_framebuffer(ctx, name);
+}
+
+
+static void
+intel_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+
+   ASSERT(irb);
+
+   if (irb->PairedStencil || irb->PairedDepth) {
+      intel_unpair_depth_stencil(ctx, irb);
+   }
+
+   if (intel && irb->region) {
+      intel_region_release(&irb->region);
+   }
+
+   _mesa_free(irb);
+}
+
+
+
+/**
+ * Return a pointer to a specific pixel in a renderbuffer.
+ */
+static void *
+intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
+                  GLint x, GLint y)
+{
+   /* By returning NULL we force all software rendering to go through
+    * the span routines.
+    */
+   return NULL;
+}
+
+
+
+/**
+ * Called via glRenderbufferStorageEXT() to set the format and allocate
+ * storage for a user-created renderbuffer.
+ */
+static GLboolean
+intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+                                 GLenum internalFormat,
+                                 GLuint width, GLuint height)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+   GLboolean softwareBuffer = GL_FALSE;
+   int cpp;
+
+   ASSERT(rb->Name != 0);
+
+   switch (internalFormat) {
+   case GL_R3_G3_B2:
+   case GL_RGB4:
+   case GL_RGB5:
+      rb->_ActualFormat = GL_RGB5;
+      rb->DataType = GL_UNSIGNED_BYTE;
+      rb->RedBits = 5;
+      rb->GreenBits = 6;
+      rb->BlueBits = 5;
+      cpp = 2;
+      break;
+   case GL_RGB:
+   case GL_RGB8:
+   case GL_RGB10:
+   case GL_RGB12:
+   case GL_RGB16:
+   case GL_RGBA:
+   case GL_RGBA2:
+   case GL_RGBA4:
+   case GL_RGB5_A1:
+   case GL_RGBA8:
+   case GL_RGB10_A2:
+   case GL_RGBA12:
+   case GL_RGBA16:
+      rb->_ActualFormat = GL_RGBA8;
+      rb->DataType = GL_UNSIGNED_BYTE;
+      rb->RedBits = 8;
+      rb->GreenBits = 8;
+      rb->BlueBits = 8;
+      rb->AlphaBits = 8;
+      cpp = 4;
+      break;
+   case GL_STENCIL_INDEX:
+   case GL_STENCIL_INDEX1_EXT:
+   case GL_STENCIL_INDEX4_EXT:
+   case GL_STENCIL_INDEX8_EXT:
+   case GL_STENCIL_INDEX16_EXT:
+      /* alloc a depth+stencil buffer */
+      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+      rb->StencilBits = 8;
+      cpp = 4;
+      break;
+   case GL_DEPTH_COMPONENT16:
+      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
+      rb->DataType = GL_UNSIGNED_SHORT;
+      rb->DepthBits = 16;
+      cpp = 2;
+      break;
+   case GL_DEPTH_COMPONENT:
+   case GL_DEPTH_COMPONENT24:
+   case GL_DEPTH_COMPONENT32:
+      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+      rb->DepthBits = 24;
+      cpp = 4;
+      break;
+   case GL_DEPTH_STENCIL_EXT:
+   case GL_DEPTH24_STENCIL8_EXT:
+      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
+      rb->DepthBits = 24;
+      rb->StencilBits = 8;
+      cpp = 4;
+      break;
+   default:
+      _mesa_problem(ctx,
+                    "Unexpected format in intel_alloc_renderbuffer_storage");
+      return GL_FALSE;
+   }
+
+   intelFlush(ctx);
+
+   /* free old region */
+   if (irb->region) {
+      intel_region_release(&irb->region);
+   }
+
+   /* allocate new memory region/renderbuffer */
+   if (softwareBuffer) {
+      return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
+                                             width, height);
+   }
+   else {
+      /* Choose a pitch to match hardware requirements:
+       */
+      GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
+
+      /* alloc hardware renderbuffer */
+      DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
+         height, pitch);
+
+      irb->region = intel_region_alloc(intel->intelScreen, cpp, pitch, height);
+      if (!irb->region)
+         return GL_FALSE;       /* out of memory? */
+
+      ASSERT(irb->region->buffer);
+
+      rb->Width = width;
+      rb->Height = height;
+
+      /* This sets the Get/PutRow/Value functions */
+      intel_set_span_functions(&irb->Base);
+
+      return GL_TRUE;
+   }
+}
+
+
+
+/**
+ * Called for each hardware renderbuffer when a _window_ is resized.
+ * Just update fields.
+ * Not used for user-created renderbuffers!
+ */
+static GLboolean
+intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+                           GLenum internalFormat, GLuint width, GLuint height)
+{
+   ASSERT(rb->Name == 0);
+   rb->Width = width;
+   rb->Height = height;
+   rb->_ActualFormat = internalFormat;
+   return GL_TRUE;
+}
+
+
+static GLboolean
+intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
+                        GLenum internalFormat, GLuint width, GLuint height)
+{
+   _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
+   return GL_FALSE;
+}
+
+
+
+/**
+ * Create a new intel_renderbuffer which corresponds to an on-screen window,
+ * not a user-created renderbuffer.
+ * \param width  the screen width
+ * \param height  the screen height
+ */
+struct intel_renderbuffer *
+intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
+                          int offset, int pitch, int cpp, void *map)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   struct intel_renderbuffer *irb;
+   const GLuint name = 0;
+
+   irb = CALLOC_STRUCT(intel_renderbuffer);
+   if (!irb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
+      return NULL;
+   }
+
+   _mesa_init_renderbuffer(&irb->Base, name);
+   irb->Base.ClassID = INTEL_RB_CLASS;
+
+   switch (intFormat) {
+   case GL_RGB5:
+      irb->Base._ActualFormat = GL_RGB5;
+      irb->Base._BaseFormat = GL_RGBA;
+      irb->Base.RedBits = 5;
+      irb->Base.GreenBits = 6;
+      irb->Base.BlueBits = 5;
+      irb->Base.DataType = GL_UNSIGNED_BYTE;
+      cpp = 2;
+      break;
+   case GL_RGBA8:
+      irb->Base._ActualFormat = GL_RGBA8;
+      irb->Base._BaseFormat = GL_RGBA;
+      irb->Base.RedBits = 8;
+      irb->Base.GreenBits = 8;
+      irb->Base.BlueBits = 8;
+      irb->Base.AlphaBits = 8;
+      irb->Base.DataType = GL_UNSIGNED_BYTE;
+      cpp = 4;
+      break;
+   case GL_STENCIL_INDEX8_EXT:
+      irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
+      irb->Base._BaseFormat = GL_STENCIL_INDEX;
+      irb->Base.StencilBits = 8;
+      irb->Base.DataType = GL_UNSIGNED_BYTE;
+      cpp = 1;
+      break;
+   case GL_DEPTH_COMPONENT16:
+      irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
+      irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      irb->Base.DepthBits = 16;
+      irb->Base.DataType = GL_UNSIGNED_SHORT;
+      cpp = 2;
+      break;
+   case GL_DEPTH_COMPONENT24:
+      irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+      irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      irb->Base.DepthBits = 24;
+      irb->Base.DataType = GL_UNSIGNED_INT;
+      cpp = 4;
+      break;
+   case GL_DEPTH24_STENCIL8_EXT:
+      irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
+      irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
+      irb->Base.DepthBits = 24;
+      irb->Base.StencilBits = 8;
+      irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+      cpp = 4;
+      break;
+   default:
+      _mesa_problem(NULL,
+                    "Unexpected intFormat in intel_create_renderbuffer");
+      return NULL;
+   }
+
+   irb->Base.InternalFormat = intFormat;
+
+   /* intel-specific methods */
+   irb->Base.Delete = intel_delete_renderbuffer;
+   irb->Base.AllocStorage = intel_alloc_window_storage;
+   irb->Base.GetPointer = intel_get_pointer;
+   /* This sets the Get/PutRow/Value functions */
+   intel_set_span_functions(&irb->Base);
+
+   irb->pfMap = map;
+   irb->pfPitch = pitch / cpp; /* in pixels */
+
+#if 00
+   irb->region = intel_region_create_static(intel,
+                                            DRM_MM_TT,
+                                            offset, map, cpp, width, height);
+#endif
+
+   return irb;
+}
+
+
+/**
+ * Create a new renderbuffer object.
+ * Typically called via glBindRenderbufferEXT().
+ */
+static struct gl_renderbuffer *
+intel_new_renderbuffer(GLcontext * ctx, GLuint name)
+{
+   /*struct intel_context *intel = intel_context(ctx); */
+   struct intel_renderbuffer *irb;
+
+   irb = CALLOC_STRUCT(intel_renderbuffer);
+   if (!irb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
+      return NULL;
+   }
+
+   _mesa_init_renderbuffer(&irb->Base, name);
+   irb->Base.ClassID = INTEL_RB_CLASS;
+
+   /* intel-specific methods */
+   irb->Base.Delete = intel_delete_renderbuffer;
+   irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
+   irb->Base.GetPointer = intel_get_pointer;
+   /* span routines set in alloc_storage function */
+
+   return &irb->Base;
+}
+
+
+/**
+ * Called via glBindFramebufferEXT().
+ */
+static void
+intel_bind_framebuffer(GLcontext * ctx, GLenum target,
+                       struct gl_framebuffer *fb)
+{
+   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
+      intel_draw_buffer(ctx, fb);
+      /* Integer depth range depends on depth buffer bits */
+      ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
+   }
+   else {
+      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
+   }
+}
+
+
+/**
+ * Called via glFramebufferRenderbufferEXT().
+ */
+static void
+intel_framebuffer_renderbuffer(GLcontext * ctx,
+                               struct gl_framebuffer *fb,
+                               GLenum attachment, struct gl_renderbuffer *rb)
+{
+   DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
+
+   intelFlush(ctx);
+
+   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
+   intel_draw_buffer(ctx, fb);
+}
+
+
+/**
+ * When glFramebufferTexture[123]D is called this function sets up the
+ * gl_renderbuffer wrapp around the texture image.
+ * This will have the region info needed for hardware rendering.
+ */
+static struct intel_renderbuffer *
+intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
+{
+   const GLuint name = ~0;      /* not significant, but distinct for debugging */
+   struct intel_renderbuffer *irb;
+
+   /* make an intel_renderbuffer to wrap the texture image */
+   irb = CALLOC_STRUCT(intel_renderbuffer);
+   if (!irb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
+      return NULL;
+   }
+
+   _mesa_init_renderbuffer(&irb->Base, name);
+   irb->Base.ClassID = INTEL_RB_CLASS;
+
+   if (texImage->TexFormat == &_mesa_texformat_argb8888) {
+      irb->Base._ActualFormat = GL_RGBA8;
+      irb->Base._BaseFormat = GL_RGBA;
+      DBG("Render to RGBA8 texture OK\n");
+   }
+   else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
+      irb->Base._ActualFormat = GL_RGB5;
+      irb->Base._BaseFormat = GL_RGB;
+      DBG("Render to RGB5 texture OK\n");
+   }
+   else if (texImage->TexFormat == &_mesa_texformat_z16) {
+      irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
+      irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      DBG("Render to DEPTH16 texture OK\n");
+   }
+   else {
+      DBG("Render to texture BAD FORMAT %d\n",
+         texImage->TexFormat->MesaFormat);
+      _mesa_free(irb);
+      return NULL;
+   }
+
+   irb->Base.InternalFormat = irb->Base._ActualFormat;
+   irb->Base.Width = texImage->Width;
+   irb->Base.Height = texImage->Height;
+   irb->Base.DataType = GL_UNSIGNED_BYTE;       /* FBO XXX fix */
+   irb->Base.RedBits = texImage->TexFormat->RedBits;
+   irb->Base.GreenBits = texImage->TexFormat->GreenBits;
+   irb->Base.BlueBits = texImage->TexFormat->BlueBits;
+   irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
+   irb->Base.DepthBits = texImage->TexFormat->DepthBits;
+
+   irb->Base.Delete = intel_delete_renderbuffer;
+   irb->Base.AllocStorage = intel_nop_alloc_storage;
+   intel_set_span_functions(&irb->Base);
+
+   irb->RenderToTexture = GL_TRUE;
+
+   return irb;
+}
+
+
+/**
+ * Called by glFramebufferTexture[123]DEXT() (and other places) to
+ * prepare for rendering into texture memory.  This might be called
+ * many times to choose different texture levels, cube faces, etc
+ * before intel_finish_render_texture() is ever called.
+ */
+static void
+intel_render_texture(GLcontext * ctx,
+                     struct gl_framebuffer *fb,
+                     struct gl_renderbuffer_attachment *att)
+{
+   struct gl_texture_image *newImage
+      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
+   struct intel_texture_image *intel_image;
+   GLuint imageOffset;
+
+   (void) fb;
+
+   ASSERT(newImage);
+
+   if (!irb) {
+      irb = intel_wrap_texture(ctx, newImage);
+      if (irb) {
+         /* bind the wrapper to the attachment point */
+         att->Renderbuffer = &irb->Base;
+      }
+      else {
+         /* fallback to software rendering */
+         _mesa_render_texture(ctx, fb, att);
+         return;
+      }
+   }
+
+   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
+       _glthread_GetID(),
+       att->Texture->Name, newImage->Width, newImage->Height,
+       irb->Base.RefCount);
+
+   /* point the renderbufer's region to the texture image region */
+   intel_image = intel_texture_image(newImage);
+   if (irb->region != intel_image->mt->region) {
+      if (irb->region)
+        intel_region_release(&irb->region);
+      intel_region_reference(&irb->region, intel_image->mt->region);
+   }
+
+   /* compute offset of the particular 2D image within the texture region */
+   imageOffset = intel_miptree_image_offset(intel_image->mt,
+                                            att->CubeMapFace,
+                                            att->TextureLevel);
+
+   if (att->Texture->Target == GL_TEXTURE_3D) {
+      const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
+                                                          att->TextureLevel);
+      imageOffset += offsets[att->Zoffset];
+   }
+
+   /* store that offset in the region */
+   intel_image->mt->region->draw_offset = imageOffset;
+
+   /* update drawing region, etc */
+   intel_draw_buffer(ctx, fb);
+}
+
+
+/**
+ * Called by Mesa when rendering to a texture is done.
+ */
+static void
+intel_finish_render_texture(GLcontext * ctx,
+                            struct gl_renderbuffer_attachment *att)
+{
+   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
+
+   DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name);
+
+   if (irb) {
+      /* just release the region */
+      intel_region_release(&irb->region);
+   }
+   else if (att->Renderbuffer) {
+      /* software fallback */
+      _mesa_finish_render_texture(ctx, att);
+      /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
+   }
+}
+
+
+/**
+ * Do one-time context initializations related to GL_EXT_framebuffer_object.
+ * Hook in device driver functions.
+ */
+void
+intel_fbo_init(struct intel_context *intel)
+{
+   intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
+   intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
+   intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
+   intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
+   intel->ctx.Driver.RenderTexture = intel_render_texture;
+   intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.h b/src/mesa/drivers/dri/i915tex/intel_fbo.h
new file mode 100644 (file)
index 0000000..221f09b
--- /dev/null
@@ -0,0 +1,80 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_FBO_H
+#define INTEL_FBO_H
+
+
+struct intel_context;
+struct intel_region;
+
+
+/**
+ * Intel renderbuffer, derived from gl_renderbuffer.
+ * Note: The PairedDepth and PairedStencil fields use renderbuffer IDs,
+ * not pointers because in some circumstances a deleted renderbuffer could
+ * result in a dangling pointer here.
+ */
+struct intel_renderbuffer
+{
+   struct gl_renderbuffer Base;
+   struct intel_region *region;
+   void *pfMap;                 /* possibly paged flipped map pointer */
+   GLuint pfPitch;              /* possibly paged flipped pitch */
+   GLboolean RenderToTexture;   /* RTT? */
+
+   GLuint PairedDepth;   /**< only used if this is a depth renderbuffer */
+   GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */
+};
+
+
+extern struct intel_renderbuffer *intel_create_renderbuffer(GLenum intFormat,
+                                                            GLsizei width,
+                                                            GLsizei height,
+                                                            int offset,
+                                                            int pitch,
+                                                            int cpp,
+                                                            void *map);
+
+
+extern void intel_fbo_init(struct intel_context *intel);
+
+
+/* XXX make inline or macro */
+extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer
+                                                         *fb,
+                                                         GLuint attIndex);
+
+
+/* XXX make inline or macro */
+extern struct intel_region *intel_get_rb_region(struct gl_framebuffer *fb,
+                                                GLuint attIndex);
+
+
+
+
+#endif /* INTEL_FBO_H */
diff --git a/src/mesa/drivers/dri/i915tex/intel_ioctl.c b/src/mesa/drivers/dri/i915tex/intel_ioctl.c
new file mode 100644 (file)
index 0000000..3250c6b
--- /dev/null
@@ -0,0 +1,138 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+
+#include "mtypes.h"
+#include "context.h"
+#include "swrast/swrast.h"
+
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_regions.h"
+#include "drm.h"
+
+#define FILE_DEBUG_FLAG DEBUG_IOCTL
+
+int
+intelEmitIrqLocked(struct intel_context *intel)
+{
+   drmI830IrqEmit ie;
+   int ret, seq;
+
+   assert(((*(int *) intel->driHwLock) & ~DRM_LOCK_CONT) ==
+          (DRM_LOCK_HELD | intel->hHWContext));
+
+   ie.irq_seq = &seq;
+
+   ret = drmCommandWriteRead(intel->driFd, DRM_I830_IRQ_EMIT,
+                             &ie, sizeof(ie));
+   if (ret) {
+      fprintf(stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret);
+      exit(1);
+   }
+
+   DBG("%s -->  %d\n", __FUNCTION__, seq);
+
+   return seq;
+}
+
+void
+intelWaitIrq(struct intel_context *intel, int seq)
+{
+   int ret;
+
+   DBG("%s %d\n", __FUNCTION__, seq);
+
+   intel->iw.irq_seq = seq;
+
+   do {
+      ret =
+         drmCommandWrite(intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw,
+                         sizeof(intel->iw));
+   } while (ret == -EAGAIN || ret == -EINTR);
+
+   if (ret) {
+      fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret);
+      exit(1);
+   }
+}
+
+
+void
+intel_batch_ioctl(struct intel_context *intel,
+                  GLuint start_offset,
+                  GLuint used,
+                  GLboolean ignore_cliprects, GLboolean allow_unlock)
+{
+   drmI830BatchBuffer batch;
+
+   assert(intel->locked);
+   assert(used);
+
+   DBG("%s used %d offset %x..%x ignore_cliprects %d\n",
+       __FUNCTION__,
+       used, start_offset, start_offset + used, ignore_cliprects);
+
+   /* Throw away non-effective packets.  Won't work once we have
+    * hardware contexts which would preserve statechanges beyond a
+    * single buffer.
+    */
+
+
+
+   batch.start = start_offset;
+   batch.used = used;
+   batch.cliprects = intel->pClipRects;
+   batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
+   batch.DR1 = 0;
+   batch.DR4 = ((((GLuint) intel->drawX) & 0xffff) |
+                (((GLuint) intel->drawY) << 16));
+
+   DBG("%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
+       __FUNCTION__,
+       batch.start,
+       batch.start + batch.used * 4, batch.DR4, batch.num_cliprects);
+
+   if (drmCommandWrite(intel->driFd, DRM_I830_BATCHBUFFER, &batch,
+                       sizeof(batch))) {
+      fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
+      UNLOCK_HARDWARE(intel);
+      exit(1);
+   }
+
+   /* FIXME: use hardware contexts to avoid 'losing' hardware after
+    * each buffer flush.
+    */
+   intel->vtbl.lost_hardware(intel);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_ioctl.h b/src/mesa/drivers/dri/i915tex/intel_ioctl.h
new file mode 100644 (file)
index 0000000..e8d07de
--- /dev/null
@@ -0,0 +1,40 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_IOCTL_H
+#define INTEL_IOCTL_H
+
+#include "intel_context.h"
+
+void intelWaitIrq(struct intel_context *intel, int seq);
+int intelEmitIrqLocked(struct intel_context *intel);
+
+void intel_batch_ioctl(struct intel_context *intel,
+                       GLuint start_offset,
+                       GLuint used,
+                       GLboolean ignore_cliprects, GLboolean allow_unlock);
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.c
new file mode 100644 (file)
index 0000000..2ebe3ae
--- /dev/null
@@ -0,0 +1,341 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "intel_context.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
+#include "enums.h"
+
+#define FILE_DEBUG_FLAG DEBUG_MIPTREE
+
+static GLenum
+target_to_target(GLenum target)
+{
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+      return GL_TEXTURE_CUBE_MAP_ARB;
+   default:
+      return target;
+   }
+}
+
+struct intel_mipmap_tree *
+intel_miptree_create(struct intel_context *intel,
+                     GLenum target,
+                     GLenum internal_format,
+                     GLuint first_level,
+                     GLuint last_level,
+                     GLuint width0,
+                     GLuint height0,
+                     GLuint depth0, GLuint cpp, GLboolean compressed)
+{
+   GLboolean ok;
+   struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
+
+   DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(target),
+       _mesa_lookup_enum_by_nr(internal_format), first_level, last_level);
+
+   mt->target = target_to_target(target);
+   mt->internal_format = internal_format;
+   mt->first_level = first_level;
+   mt->last_level = last_level;
+   mt->width0 = width0;
+   mt->height0 = height0;
+   mt->depth0 = depth0;
+   mt->cpp = compressed ? 2 : cpp;
+   mt->compressed = compressed;
+   mt->refcount = 1; 
+
+   switch (intel->intelScreen->deviceID) {
+   case PCI_CHIP_I945_G:
+   case PCI_CHIP_I945_GM:
+      ok = i945_miptree_layout(mt);
+      break;
+   case PCI_CHIP_I915_G:
+   case PCI_CHIP_I915_GM:
+   case PCI_CHIP_I830_M:
+   case PCI_CHIP_I855_GM:
+   case PCI_CHIP_I865_G:
+   default:
+      /* All the i830 chips and the i915 use this layout:
+       */
+      ok = i915_miptree_layout(mt);
+      break;
+   }
+
+   if (ok)
+      mt->region = intel_region_alloc(intel->intelScreen,
+                                      mt->cpp, mt->pitch, mt->total_height);
+
+   if (!mt->region) {
+      free(mt);
+      return NULL;
+   }
+
+   return mt;
+}
+
+
+void
+intel_miptree_reference(struct intel_mipmap_tree **dst,
+                        struct intel_mipmap_tree *src)
+{
+   src->refcount++;
+   *dst = src;
+   DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount);
+}
+
+void
+intel_miptree_release(struct intel_context *intel,
+                      struct intel_mipmap_tree **mt)
+{
+   if (!*mt)
+      return;
+
+   DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1);
+   if (--(*mt)->refcount <= 0) {
+      GLuint i;
+
+      DBG("%s deleting %p\n", __FUNCTION__, *mt);
+
+      intel_region_release(&((*mt)->region));
+
+      for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
+         if ((*mt)->level[i].image_offset)
+            free((*mt)->level[i].image_offset);
+
+      free(*mt);
+   }
+   *mt = NULL;
+}
+
+
+
+
+/* Can the image be pulled into a unified mipmap tree.  This mirrors
+ * the completeness test in a lot of ways.
+ *
+ * Not sure whether I want to pass gl_texture_image here.
+ */
+GLboolean
+intel_miptree_match_image(struct intel_mipmap_tree *mt,
+                          struct gl_texture_image *image,
+                          GLuint face, GLuint level)
+{
+   /* Images with borders are never pulled into mipmap trees. 
+    */
+   if (image->Border) 
+      return GL_FALSE;
+
+   if (image->InternalFormat != mt->internal_format ||
+       image->IsCompressed != mt->compressed)
+      return GL_FALSE;
+
+   /* Test image dimensions against the base level image adjusted for
+    * minification.  This will also catch images not present in the
+    * tree, changed targets, etc.
+    */
+   if (image->Width != mt->level[level].width ||
+       image->Height != mt->level[level].height ||
+       image->Depth != mt->level[level].depth)
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+
+void
+intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
+                             GLuint level,
+                             GLuint nr_images,
+                             GLuint x, GLuint y, GLuint w, GLuint h, GLuint d)
+{
+
+   mt->level[level].width = w;
+   mt->level[level].height = h;
+   mt->level[level].depth = d;
+   mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp;
+   mt->level[level].nr_images = nr_images;
+
+   DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
+       level, w, h, d, x, y, mt->level[level].level_offset);
+
+   /* Not sure when this would happen, but anyway: 
+    */
+   if (mt->level[level].image_offset) {
+      free(mt->level[level].image_offset);
+      mt->level[level].image_offset = NULL;
+   }
+
+   assert(nr_images);
+
+   mt->level[level].image_offset = malloc(nr_images * sizeof(GLuint));
+   mt->level[level].image_offset[0] = 0;
+}
+
+
+
+void
+intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+                               GLuint level, GLuint img, GLuint x, GLuint y)
+{
+   if (img == 0 && level == 0)
+      assert(x == 0 && y == 0);
+
+   assert(img < mt->level[level].nr_images);
+
+   mt->level[level].image_offset[img] = (x + y * mt->pitch);
+
+   DBG("%s level %d img %d pos %d,%d image_offset %x\n",
+       __FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
+}
+
+
+/* Although we use the image_offset[] array to store relative offsets
+ * to cube faces, Mesa doesn't know anything about this and expects
+ * each cube face to be treated as a separate image.
+ *
+ * These functions present that view to mesa:
+ */
+const GLuint *
+intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, GLuint level)
+{
+   static const GLuint zero = 0;
+
+   if (mt->target != GL_TEXTURE_3D || mt->level[level].nr_images == 1)
+      return &zero;
+   else
+      return mt->level[level].image_offset;
+}
+
+
+GLuint
+intel_miptree_image_offset(struct intel_mipmap_tree * mt,
+                           GLuint face, GLuint level)
+{
+   if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
+      return (mt->level[level].level_offset +
+              mt->level[level].image_offset[face] * mt->cpp);
+   else
+      return mt->level[level].level_offset;
+}
+
+
+
+/**
+ * Map a teximage in a mipmap tree.
+ * \param row_stride  returns row stride in bytes
+ * \param image_stride  returns image stride in bytes (for 3D textures).
+ * \return address of mapping
+ */
+GLubyte *
+intel_miptree_image_map(struct intel_context * intel,
+                        struct intel_mipmap_tree * mt,
+                        GLuint face,
+                        GLuint level,
+                        GLuint * row_stride, GLuint * image_offsets)
+{
+   DBG("%s \n", __FUNCTION__);
+
+   if (row_stride)
+      *row_stride = mt->pitch * mt->cpp;
+
+   if (image_offsets)
+      memcpy(image_offsets, mt->level[level].image_offset,
+             mt->level[level].depth * sizeof(GLuint));
+
+   return (intel_region_map(intel->intelScreen, mt->region) +
+           intel_miptree_image_offset(mt, face, level));
+}
+
+void
+intel_miptree_image_unmap(struct intel_context *intel,
+                          struct intel_mipmap_tree *mt)
+{
+   DBG("%s\n", __FUNCTION__);
+   intel_region_unmap(intel->intelScreen, mt->region);
+}
+
+
+
+/* Upload data for a particular image.
+ */
+void
+intel_miptree_image_data(struct intel_context *intel,
+                         struct intel_mipmap_tree *dst,
+                         GLuint face,
+                         GLuint level,
+                         void *src,
+                         GLuint src_row_pitch, GLuint src_image_pitch)
+{
+   GLuint depth = dst->level[level].depth;
+   GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
+   const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
+   GLuint i;
+
+   DBG("%s\n", __FUNCTION__);
+   for (i = 0; i < depth; i++) {
+      intel_region_data(intel->intelScreen, dst->region, dst_offset + dst_depth_offset[i], 0, 0, src, src_row_pitch, 0, 0,   /* source x,y */
+                        dst->level[level].width, dst->level[level].height);
+
+      src += src_image_pitch;
+   }
+}
+
+/* Copy mipmap image between trees
+ */
+void
+intel_miptree_image_copy(struct intel_context *intel,
+                         struct intel_mipmap_tree *dst,
+                         GLuint face, GLuint level,
+                         struct intel_mipmap_tree *src)
+{
+   GLuint width = src->level[level].width;
+   GLuint height = src->level[level].height;
+   GLuint depth = src->level[level].depth;
+   GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
+   GLuint src_offset = intel_miptree_image_offset(src, face, level);
+   const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
+   const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level);
+   GLuint i;
+
+   for (i = 0; i < depth; i++) {
+      intel_region_copy(intel->intelScreen,
+                        dst->region, dst_offset + dst_depth_offset[i],
+                        0,
+                        0,
+                        src->region, src_offset + src_depth_offset[i],
+                        0, 0, width, height);
+   }
+
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915tex/intel_mipmap_tree.h
new file mode 100644 (file)
index 0000000..e6dd5bb
--- /dev/null
@@ -0,0 +1,198 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_MIPMAP_TREE_H
+#define INTEL_MIPMAP_TREE_H
+
+#include "intel_regions.h"
+
+/* A layer on top of the intel_regions code which adds:
+ *
+ * - Code to size and layout a region to hold a set of mipmaps.
+ * - Query to determine if a new image fits in an existing tree.
+ * - More refcounting 
+ *     - maybe able to remove refcounting from intel_region?
+ * - ?
+ *
+ * The fixed mipmap layout of intel hardware where one offset
+ * specifies the position of all images in a mipmap hierachy
+ * complicates the implementation of GL texture image commands,
+ * compared to hardware where each image is specified with an
+ * independent offset.
+ *
+ * In an ideal world, each texture object would be associated with a
+ * single bufmgr buffer or 2d intel_region, and all the images within
+ * the texture object would slot into the tree as they arrive.  The
+ * reality can be a little messier, as images can arrive from the user
+ * with sizes that don't fit in the existing tree, or in an order
+ * where the tree layout cannot be guessed immediately.  
+ * 
+ * This structure encodes an idealized mipmap tree.  The GL image
+ * commands build these where possible, otherwise store the images in
+ * temporary system buffers.
+ */
+
+
+/**
+ * Describes the location of each texture image within a texture region.
+ */
+struct intel_mipmap_level
+{
+   GLuint level_offset;
+   GLuint width;
+   GLuint height;
+   GLuint depth;
+   GLuint nr_images;
+
+   /* Explicitly store the offset of each image for each cube face or
+    * depth value.  Pretty much have to accept that hardware formats
+    * are going to be so diverse that there is no unified way to
+    * compute the offsets of depth/cube images within a mipmap level,
+    * so have to store them as a lookup table:
+    */
+   GLuint *image_offset;
+};
+
+struct intel_mipmap_tree
+{
+   /* Effectively the key:
+    */
+   GLenum target;
+   GLenum internal_format;
+
+   GLuint first_level;
+   GLuint last_level;
+
+   GLuint width0, height0, depth0; /**< Level zero image dimensions */
+   GLuint cpp;
+   GLboolean compressed;
+
+   /* Derived from the above:
+    */
+   GLuint pitch;
+   GLuint depth_pitch;          /* per-image on i945? */
+   GLuint total_height;
+
+   /* Includes image offset tables:
+    */
+   struct intel_mipmap_level level[MAX_TEXTURE_LEVELS];
+
+   /* The data is held here:
+    */
+   struct intel_region *region;
+
+   /* These are also refcounted:
+    */
+   GLuint refcount;
+};
+
+
+
+struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
+                                               GLenum target,
+                                               GLenum internal_format,
+                                               GLuint first_level,
+                                               GLuint last_level,
+                                               GLuint width0,
+                                               GLuint height0,
+                                               GLuint depth0,
+                                               GLuint cpp,
+                                               GLboolean compressed);
+
+void intel_miptree_reference(struct intel_mipmap_tree **dst,
+                             struct intel_mipmap_tree *src);
+
+void intel_miptree_release(struct intel_context *intel,
+                           struct intel_mipmap_tree **mt);
+
+/* Check if an image fits an existing mipmap tree layout
+ */
+GLboolean intel_miptree_match_image(struct intel_mipmap_tree *mt,
+                                    struct gl_texture_image *image,
+                                    GLuint face, GLuint level);
+
+/* Return a pointer to an image within a tree.  Return image stride as
+ * well.
+ */
+GLubyte *intel_miptree_image_map(struct intel_context *intel,
+                                 struct intel_mipmap_tree *mt,
+                                 GLuint face,
+                                 GLuint level,
+                                 GLuint * row_stride, GLuint * image_stride);
+
+void intel_miptree_image_unmap(struct intel_context *intel,
+                               struct intel_mipmap_tree *mt);
+
+
+/* Return the linear offset of an image relative to the start of the
+ * tree:
+ */
+GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
+                                  GLuint face, GLuint level);
+
+/* Return pointers to each 2d slice within an image.  Indexed by depth
+ * value.
+ */
+const GLuint *intel_miptree_depth_offsets(struct intel_mipmap_tree *mt,
+                                          GLuint level);
+
+
+void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
+                                  GLuint level,
+                                  GLuint nr_images,
+                                  GLuint x, GLuint y,
+                                  GLuint w, GLuint h, GLuint d);
+
+void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+                                    GLuint level,
+                                    GLuint img, GLuint x, GLuint y);
+
+
+/* Upload an image into a tree
+ */
+void intel_miptree_image_data(struct intel_context *intel,
+                              struct intel_mipmap_tree *dst,
+                              GLuint face,
+                              GLuint level,
+                              void *src,
+                              GLuint src_row_pitch, GLuint src_image_pitch);
+
+/* Copy an image between two trees
+ */
+void intel_miptree_image_copy(struct intel_context *intel,
+                              struct intel_mipmap_tree *dst,
+                              GLuint face, GLuint level,
+                              struct intel_mipmap_tree *src);
+
+/* i915_mipmap_tree.c:
+ */
+GLboolean i915_miptree_layout(struct intel_mipmap_tree *mt);
+GLboolean i945_miptree_layout(struct intel_mipmap_tree *mt);
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel.c b/src/mesa/drivers/dri/i915tex/intel_pixel.c
new file mode 100644 (file)
index 0000000..4fe128d
--- /dev/null
@@ -0,0 +1,119 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portionsalloc
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "enums.h"
+#include "state.h"
+#include "swrast/swrast.h"
+
+#include "intel_context.h"
+#include "intel_pixel.h"
+#include "intel_regions.h"
+
+
+/**
+ * Check if any fragment operations are in effect which might effect
+ * glDraw/CopyPixels.
+ */
+GLboolean
+intel_check_blit_fragment_ops(GLcontext * ctx)
+{
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   /* XXX Note: Scissor could be done with the blitter:
+    */
+   return !(ctx->_ImageTransferState ||
+            ctx->Color.AlphaEnabled ||
+            ctx->Depth.Test ||
+            ctx->Fog.Enabled ||
+            ctx->Scissor.Enabled ||
+            ctx->Stencil.Enabled ||
+            !ctx->Color.ColorMask[0] ||
+            !ctx->Color.ColorMask[1] ||
+            !ctx->Color.ColorMask[2] ||
+            !ctx->Color.ColorMask[3] ||
+            ctx->Color.ColorLogicOpEnabled ||
+            ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
+}
+
+
+GLboolean
+intel_check_meta_tex_fragment_ops(GLcontext * ctx)
+{
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   /* Some of _ImageTransferState (scale, bias) could be done with
+    * fragment programs on i915.
+    */
+   return !(ctx->_ImageTransferState || ctx->Fog.Enabled ||     /* not done yet */
+            ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
+}
+
+/* The intel_region struct doesn't really do enough to capture the
+ * format of the pixels in the region.  For now this code assumes that
+ * the region is a display surface and hence is either ARGB8888 or
+ * RGB565.
+ * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
+ * know the buffer's pixel format.
+ *
+ * \param format  as given to glDraw/ReadPixels
+ * \param type  as given to glDraw/ReadPixels
+ */
+GLboolean
+intel_check_blit_format(struct intel_region * region,
+                        GLenum format, GLenum type)
+{
+   if (region->cpp == 4 &&
+       (type == GL_UNSIGNED_INT_8_8_8_8_REV ||
+        type == GL_UNSIGNED_BYTE) && format == GL_BGRA) {
+      return GL_TRUE;
+   }
+
+   if (region->cpp == 2 &&
+       type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) {
+      return GL_TRUE;
+   }
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
+              __FUNCTION__, region->cpp,
+              _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
+
+   return GL_FALSE;
+}
+
+
+void
+intelInitPixelFuncs(struct dd_function_table *functions)
+{
+   functions->Accum = _swrast_Accum;
+   functions->Bitmap = _swrast_Bitmap;
+   functions->CopyPixels = intelCopyPixels;
+   functions->ReadPixels = intelReadPixels;
+   functions->DrawPixels = intelDrawPixels;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel.h b/src/mesa/drivers/dri/i915tex/intel_pixel.h
new file mode 100644 (file)
index 0000000..a6fcf90
--- /dev/null
@@ -0,0 +1,63 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_PIXEL_H
+#define INTEL_PIXEL_H
+
+#include "mtypes.h"
+
+void intelInitPixelFuncs(struct dd_function_table *functions);
+
+GLboolean intel_check_blit_fragment_ops(GLcontext * ctx);
+
+GLboolean intel_check_meta_tex_fragment_ops(GLcontext * ctx);
+
+GLboolean intel_check_blit_format(struct intel_region *region,
+                                  GLenum format, GLenum type);
+
+
+void intelReadPixels(GLcontext * ctx,
+                     GLint x, GLint y,
+                     GLsizei width, GLsizei height,
+                     GLenum format, GLenum type,
+                     const struct gl_pixelstore_attrib *pack,
+                     GLvoid * pixels);
+
+void intelDrawPixels(GLcontext * ctx,
+                     GLint x, GLint y,
+                     GLsizei width, GLsizei height,
+                     GLenum format,
+                     GLenum type,
+                     const struct gl_pixelstore_attrib *unpack,
+                     const GLvoid * pixels);
+
+void intelCopyPixels(GLcontext * ctx,
+                     GLint srcx, GLint srcy,
+                     GLsizei width, GLsizei height,
+                     GLint destx, GLint desty, GLenum type);
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel_bitmap.c b/src/mesa/drivers/dri/i915tex/intel_pixel_bitmap.c
new file mode 100644 (file)
index 0000000..65bf338
--- /dev/null
@@ -0,0 +1,350 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portionsalloc
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "image.h"
+#include "colormac.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "bufferobj.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_regions.h"
+#include "intel_buffer_objects.h"
+
+
+
+#define FILE_DEBUG_FLAG DEBUG_PIXEL
+
+
+/* Unlike the other intel_pixel_* functions, the expectation here is
+ * that the incoming data is not in a PBO.  With the XY_TEXT blit
+ * method, there's no benefit haveing it in a PBO, but we could
+ * implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit
+ * PBO bitmaps.  I think they are probably pretty rare though - I
+ * wonder if Xgl uses them?
+ */
+static const GLubyte *map_pbo( GLcontext *ctx,
+                              GLsizei width, GLsizei height,
+                              const struct gl_pixelstore_attrib *unpack,
+                              const GLubyte *bitmap )
+{
+   GLubyte *buf;
+
+   if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+                                 GL_COLOR_INDEX, GL_BITMAP,
+                                 (GLvoid *) bitmap)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)");
+      return NULL;
+   }
+
+   buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                          GL_READ_ONLY_ARB,
+                                          unpack->BufferObj);
+   if (!buf) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
+      return NULL;
+   }
+
+   return ADD_POINTERS(buf, bitmap);
+}
+
+static GLboolean test_bit( const GLubyte *src,
+                           GLuint bit )
+{
+   return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0;
+}
+
+static void set_bit( GLubyte *dest,
+                         GLuint bit )
+{
+   dest[bit/8] |= 1 << (bit % 8);
+}
+
+static int align(int x, int align)
+{
+   return (x + align - 1) & ~(align - 1);
+}
+
+/* Extract a rectangle's worth of data from the bitmap.  Called
+ * per-cliprect.
+ */
+static GLuint get_bitmap_rect(GLsizei width, GLsizei height,
+                             const struct gl_pixelstore_attrib *unpack,
+                             const GLubyte *bitmap,
+                             GLuint x, GLuint y, 
+                             GLuint w, GLuint h,
+                             GLubyte *dest,
+                             GLuint row_align,
+                             GLboolean invert)
+{
+   GLuint src_offset = (x + unpack->SkipPixels) & 0x7;
+   GLuint mask = unpack->LsbFirst ? 0 : 7;
+   GLuint bit = 0;
+   GLint row, col;
+   GLint first, last;
+   GLint incr;
+   GLuint count = 0;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n",
+                  __FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask);
+
+   if (invert) {
+      first = h-1;
+      last = 0;
+      incr = -1;
+   }
+   else {
+      first = 0;
+      last = h-1;
+      incr = 1;
+   }
+
+   /* Require that dest be pre-zero'd.
+    */
+   for (row = first; row != (last+incr); row += incr) {
+      const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap, 
+                                                   width, height, 
+                                                   GL_COLOR_INDEX, GL_BITMAP, 
+                                                   y + row, x);
+
+      for (col = 0; col < w; col++, bit++) {
+        if (test_bit(rowsrc, (col + src_offset) ^ mask)) {
+           set_bit(dest, bit ^ 7);
+           count++;
+        }
+      }
+
+      if (row_align)
+        bit = (bit + row_align - 1) & ~(row_align - 1);
+   }
+
+   return count;
+}
+
+
+
+
+/*
+ * Render a bitmap.
+ */
+static GLboolean
+do_blit_bitmap( GLcontext *ctx, 
+               GLint dstx, GLint dsty,
+               GLsizei width, GLsizei height,
+               const struct gl_pixelstore_attrib *unpack,
+               const GLubyte *bitmap )
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *dst = intel_drawbuf_region(intel);
+   
+   union {
+      GLuint ui;
+      GLubyte ub[4];
+   } color;
+
+
+   if (unpack->BufferObj->Name) {
+      bitmap = map_pbo(ctx, width, height, unpack, bitmap);
+      if (bitmap == NULL)
+        return GL_TRUE;        /* even though this is an error, we're done */
+   }
+
+   UNCLAMPED_FLOAT_TO_CHAN(color.ub[0], ctx->Current.RasterColor[2]);
+   UNCLAMPED_FLOAT_TO_CHAN(color.ub[1], ctx->Current.RasterColor[1]);
+   UNCLAMPED_FLOAT_TO_CHAN(color.ub[2], ctx->Current.RasterColor[0]);
+   UNCLAMPED_FLOAT_TO_CHAN(color.ub[3], ctx->Current.RasterColor[3]);
+
+   /* Does zoom apply to bitmaps?
+    */
+   if (!intel_check_blit_fragment_ops(ctx) ||
+       ctx->Pixel.ZoomX != 1.0F || 
+       ctx->Pixel.ZoomY != 1.0F)
+      return GL_FALSE;
+
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      drm_clip_rect_t *box = dPriv->pClipRects;
+      drm_clip_rect_t dest_rect;
+      GLint nbox = dPriv->numClipRects;
+      GLint srcx = 0, srcy = 0;
+      GLint orig_screen_x1, orig_screen_y2;
+      GLuint i;
+
+
+      orig_screen_x1 = dPriv->x + dstx;
+      orig_screen_y2 = dPriv->y + (dPriv->h - dsty);
+
+      /* Do scissoring in GL coordinates:
+       */
+x      if (ctx->Scissor.Enabled)
+      {
+        GLint x = ctx->Scissor.X;
+        GLint y = ctx->Scissor.Y;
+        GLuint w = ctx->Scissor.Width;
+        GLuint h = ctx->Scissor.Height;
+
+         if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
+            goto out;
+      }
+
+      /* Convert from GL to hardware coordinates:
+       */
+      dsty = dPriv->y + (dPriv->h - dsty - height);  
+      dstx = dPriv->x + dstx;
+
+      dest_rect.x1 = dstx;
+      dest_rect.y1 = dsty;
+      dest_rect.x2 = dstx + width;
+      dest_rect.y2 = dsty + height;
+
+      for (i = 0; i < nbox; i++) {
+         drm_clip_rect_t rect;
+        int box_w, box_h;
+        GLint px, py;
+        GLuint stipple[32];  
+
+         if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
+            continue;
+
+        /* Now go back to GL coordinates to figure out what subset of
+         * the bitmap we are uploading for this cliprect:
+         */
+        box_w = rect.x2 - rect.x1;
+        box_h = rect.y2 - rect.y1;
+        srcx = rect.x1 - orig_screen_x1;
+        srcy = orig_screen_y2 - rect.y2;
+
+
+#define DY 32
+#define DX 32
+
+        /* Then, finally, chop it all into chunks that can be
+         * digested by hardware:
+         */
+        for (py = 0; py < box_h; py += DY) { 
+           for (px = 0; px < box_w; px += DX) { 
+              int h = MIN2(DY, box_h - py);
+              int w = MIN2(DX, box_w - px); 
+              GLuint sz = align(align(w,8) * h, 64)/8;
+           
+              assert(sz <= sizeof(stipple));
+              memset(stipple, 0, sz);
+
+              /* May need to adjust this when padding has been introduced in
+               * sz above:
+               */
+              if (get_bitmap_rect(width, height, unpack, 
+                                  bitmap,
+                                  srcx + px, srcy + py, w, h,
+                                  (GLubyte *)stipple,
+                                  8,
+                                  GL_TRUE) == 0)
+                 continue;
+
+              /* 
+               */
+              intelEmitImmediateColorExpandBlit( intel,
+                                                 dst->cpp,
+                                                 (GLubyte *)stipple, 
+                                                 sz,
+                                                 color.ui,
+                                                 dst->pitch,
+                                                 dst->buffer,
+                                                 0,
+                                                 dst->tiled,
+                                                 rect.x1 + px,
+                                                 rect.y2 - (py + h),
+                                                 w, h);
+           } 
+        } 
+      }
+      intel->need_flush = GL_TRUE;
+   out:
+      intel_batchbuffer_flush(intel->batch);
+   }
+   UNLOCK_HARDWARE(intel);
+
+
+   if (unpack->BufferObj->Name) {
+      /* done with PBO so unmap it now */
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              unpack->BufferObj);
+   }
+
+   return GL_TRUE;
+}
+
+
+
+
+
+/* There are a large number of possible ways to implement bitmap on
+ * this hardware, most of them have some sort of drawback.  Here are a
+ * few that spring to mind:
+ * 
+ * Blit:
+ *    - XY_MONO_SRC_BLT_CMD
+ *         - use XY_SETUP_CLIP_BLT for cliprect clipping.
+ *    - XY_TEXT_BLT
+ *    - XY_TEXT_IMMEDIATE_BLT
+ *         - blit per cliprect, subject to maximum immediate data size.
+ *    - XY_COLOR_BLT 
+ *         - per pixel or run of pixels
+ *    - XY_PIXEL_BLT
+ *         - good for sparse bitmaps
+ *
+ * 3D engine:
+ *    - Point per pixel
+ *    - Translate bitmap to an alpha texture and render as a quad
+ *    - Chop bitmap up into 32x32 squares and render w/polygon stipple.
+ */
+void
+intelBitmap(GLcontext * ctx,
+           GLint x, GLint y,
+           GLsizei width, GLsizei height,
+           const struct gl_pixelstore_attrib *unpack,
+           const GLubyte * pixels)
+{
+   if (do_blit_bitmap(ctx, x, y, width, height,
+                          unpack, pixels))
+      return;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+
+   _swrast_Bitmap(ctx, x, y, width, height, unpack, pixels);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel_copy.c b/src/mesa/drivers/dri/i915tex/intel_pixel_copy.c
new file mode 100644 (file)
index 0000000..5eb021f
--- /dev/null
@@ -0,0 +1,380 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "image.h"
+#include "state.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_buffers.h"
+#include "intel_blit.h"
+#include "intel_regions.h"
+#include "intel_tris.h"
+#include "intel_pixel.h"
+
+#define FILE_DEBUG_FLAG DEBUG_PIXEL
+
+static struct intel_region *
+copypix_src_region(struct intel_context *intel, GLenum type)
+{
+   switch (type) {
+   case GL_COLOR:
+      return intel_readbuf_region(intel);
+   case GL_DEPTH:
+      /* Don't think this is really possible execpt at 16bpp, when we have no stencil.
+       */
+      if (intel->intelScreen->depth_region && 
+         intel->intelScreen->depth_region->cpp == 2)
+         return intel->intelScreen->depth_region;
+   case GL_STENCIL:
+      /* Don't think this is really possible. 
+       */
+      break;
+   case GL_DEPTH_STENCIL_EXT:
+      /* Does it matter whether it is stencil/depth or depth/stencil?
+       */
+      return intel->intelScreen->depth_region;
+   default:
+      break;
+   }
+
+   return NULL;
+}
+
+
+/**
+ * Check if any fragment operations are in effect which might effect
+ * glCopyPixels.  Differs from intel_check_blit_fragment_ops in that
+ * we allow Scissor.
+ */
+static GLboolean
+intel_check_copypixel_blit_fragment_ops(GLcontext * ctx)
+{
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   /* Could do logicop with the blitter: 
+    */
+   return !(ctx->_ImageTransferState ||
+            ctx->Color.AlphaEnabled ||
+            ctx->Depth.Test ||
+            ctx->Fog.Enabled ||
+            ctx->Stencil.Enabled ||
+            !ctx->Color.ColorMask[0] ||
+            !ctx->Color.ColorMask[1] ||
+            !ctx->Color.ColorMask[2] ||
+            !ctx->Color.ColorMask[3] ||
+            ctx->Color.ColorLogicOpEnabled ||
+            ctx->Texture._EnabledUnits ||
+           ctx->FragmentProgram._Enabled);
+}
+
+/* Doesn't work for overlapping regions.  Could do a double copy or
+ * just fallback.
+ */
+static GLboolean
+do_texture_copypixels(GLcontext * ctx,
+                      GLint srcx, GLint srcy,
+                      GLsizei width, GLsizei height,
+                      GLint dstx, GLint dsty, GLenum type)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *dst = intel_drawbuf_region(intel);
+   struct intel_region *src = copypix_src_region(intel, type);
+   GLenum src_format;
+   GLenum src_type;
+
+   DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__, 
+       srcx, srcy, width, height, dstx, dsty);
+
+   if (!src || !dst || type != GL_COLOR)
+      return GL_FALSE;
+
+   /* Can't handle overlapping regions.  Don't have sufficient control
+    * over rasterization to pull it off in-place.  Punt on these for
+    * now.
+    * 
+    * XXX: do a copy to a temporary. 
+    */
+   if (src->buffer == dst->buffer) {
+      drm_clip_rect_t srcbox;
+      drm_clip_rect_t dstbox;
+      drm_clip_rect_t tmp;
+
+      srcbox.x1 = srcx;
+      srcbox.y1 = srcy;
+      srcbox.x2 = srcx + width;
+      srcbox.y2 = srcy + height;
+
+      dstbox.x1 = dstx;
+      dstbox.y1 = dsty;
+      dstbox.x2 = dstx + width * ctx->Pixel.ZoomX;
+      dstbox.y2 = dsty + height * ctx->Pixel.ZoomY;
+
+      DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2);
+      DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2,
+         width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+
+      if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) {
+         DBG("%s: regions overlap\n", __FUNCTION__);
+         return GL_FALSE;
+      }
+   }
+
+   intelFlush(&intel->ctx);
+
+   intel->vtbl.install_meta_state(intel);
+
+   /* Is this true?  Also will need to turn depth testing on according
+    * to state:
+    */
+   intel->vtbl.meta_no_stencil_write(intel);
+   intel->vtbl.meta_no_depth_write(intel);
+
+   /* Set the 3d engine to draw into the destination region:
+    */
+   intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region);
+
+   intel->vtbl.meta_import_pixel_state(intel);
+
+   if (src->cpp == 2) {
+      src_format = GL_RGB;
+      src_type = GL_UNSIGNED_SHORT_5_6_5;
+   }
+   else {
+      src_format = GL_BGRA;
+      src_type = GL_UNSIGNED_BYTE;
+   }
+
+   /* Set the frontbuffer up as a large rectangular texture.
+    */
+   if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, 0,
+                                         src->pitch,
+                                         src->height, src_format, src_type)) {
+      intel->vtbl.leave_meta_state(intel);
+      return GL_FALSE;
+   }
+
+
+   intel->vtbl.meta_texture_blend_replace(intel);
+
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+
+      srcy = dPriv->h - srcy - height;  /* convert from gl to hardware coords */
+
+      srcx += dPriv->x;
+      srcy += dPriv->y;
+
+      /* Clip against the source region.  This is the only source
+       * clipping we do.  XXX: Just set the texcord wrap mode to clamp
+       * or similar.
+       *
+       */
+      if (0) {
+         GLint orig_x = srcx;
+         GLint orig_y = srcy;
+
+         if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
+                                   &srcx, &srcy, &width, &height))
+            goto out;
+
+         dstx += srcx - orig_x;
+         dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
+      }
+
+      /* Just use the regular cliprect mechanism...  Does this need to
+       * even hold the lock???
+       */
+      intel_meta_draw_quad(intel, 
+                          dstx, 
+                          dstx + width * ctx->Pixel.ZoomX, 
+                          dPriv->h - (dsty + height * ctx->Pixel.ZoomY), 
+                          dPriv->h - (dsty), 0,   /* XXX: what z value? */
+                           0x00ff00ff,
+                           srcx, srcx + width, srcy, srcy + height);
+
+    out:
+      intel->vtbl.leave_meta_state(intel);
+      intel_batchbuffer_flush(intel->batch);
+   }
+   UNLOCK_HARDWARE(intel);
+
+   DBG("%s: success\n", __FUNCTION__);
+   return GL_TRUE;
+}
+
+
+
+
+
+/**
+ * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc.
+ */
+static GLboolean
+do_blit_copypixels(GLcontext * ctx,
+                   GLint srcx, GLint srcy,
+                   GLsizei width, GLsizei height,
+                   GLint dstx, GLint dsty, GLenum type)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *dst = intel_drawbuf_region(intel);
+   struct intel_region *src = copypix_src_region(intel, type);
+
+   /* Copypixels can be more than a straight copy.  Ensure all the
+    * extra operations are disabled:
+    */
+   if (!intel_check_copypixel_blit_fragment_ops(ctx) ||
+       ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+      return GL_FALSE;
+
+   if (!src || !dst)
+      return GL_FALSE;
+
+
+
+   intelFlush(&intel->ctx);
+
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      drm_clip_rect_t *box = dPriv->pClipRects;
+      drm_clip_rect_t dest_rect;
+      GLint nbox = dPriv->numClipRects;
+      GLint delta_x = 0;
+      GLint delta_y = 0;
+      GLuint i;
+
+      /* Do scissoring in GL coordinates:
+       */
+      if (ctx->Scissor.Enabled)
+      {
+        GLint x = ctx->Scissor.X;
+        GLint y = ctx->Scissor.Y;
+        GLuint w = ctx->Scissor.Width;
+        GLuint h = ctx->Scissor.Height;
+        GLint dx = dstx - srcx;
+         GLint dy = dsty - srcy;
+
+         if (!_mesa_clip_to_region(x, y, x+w-1, y+h-1, &dstx, &dsty, &width, &height))
+            goto out;
+        
+         srcx = dstx - dx;
+         srcy = dsty - dy;
+      }
+
+      /* Convert from GL to hardware coordinates:
+       */
+      dsty = dPriv->h - dsty - height;  
+      srcy = dPriv->h - srcy - height;  
+      dstx += dPriv->x;
+      dsty += dPriv->y;
+      srcx += dPriv->x;
+      srcy += dPriv->y;
+
+      /* Clip against the source region.  This is the only source
+       * clipping we do.  Dst is clipped with cliprects below.
+       */
+      {
+         delta_x = srcx - dstx;
+         delta_y = srcy - dsty;
+
+         if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
+                                   &srcx, &srcy, &width, &height))
+            goto out;
+
+         dstx = srcx - delta_x;
+         dsty = srcy - delta_y;
+      }
+
+      dest_rect.x1 = dstx;
+      dest_rect.y1 = dsty;
+      dest_rect.x2 = dstx + width;
+      dest_rect.y2 = dsty + height;
+
+      /* Could do slightly more clipping: Eg, take the intersection of
+       * the existing set of cliprects and those cliprects translated
+       * by delta_x, delta_y:
+       * 
+       * This code will not overwrite other windows, but will
+       * introduce garbage when copying from obscured window regions.
+       */
+      for (i = 0; i < nbox; i++) {
+         drm_clip_rect_t rect;
+
+         if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
+            continue;
+
+
+         intelEmitCopyBlit(intel, dst->cpp, 
+                          src->pitch, src->buffer, 0, 
+                          dst->pitch, dst->buffer, 0, 
+                          rect.x1 + delta_x, rect.y1 + delta_y,       /* srcx, srcy */
+                           rect.x1, rect.y1,    /* dstx, dsty */
+                           rect.x2 - rect.x1, rect.y2 - rect.y1);
+      }
+
+    out:
+      intel_batchbuffer_flush(intel->batch);
+   }
+   UNLOCK_HARDWARE(intel);
+
+   DBG("%s: success\n", __FUNCTION__);
+   return GL_TRUE;
+}
+
+
+void
+intelCopyPixels(GLcontext * ctx,
+                GLint srcx, GLint srcy,
+                GLsizei width, GLsizei height,
+                GLint destx, GLint desty, GLenum type)
+{
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
+      return;
+
+   if (do_texture_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
+      return;
+
+   DBG("fallback to _swrast_CopyPixels\n");
+
+   _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel_draw.c b/src/mesa/drivers/dri/i915tex/intel_pixel_draw.c
new file mode 100644 (file)
index 0000000..616101a
--- /dev/null
@@ -0,0 +1,365 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portionsalloc
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "image.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "bufferobj.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_regions.h"
+#include "intel_pixel.h"
+#include "intel_buffer_objects.h"
+#include "intel_tris.h"
+
+
+
+static GLboolean
+do_texture_drawpixels(GLcontext * ctx,
+                      GLint x, GLint y,
+                      GLsizei width, GLsizei height,
+                      GLenum format, GLenum type,
+                      const struct gl_pixelstore_attrib *unpack,
+                      const GLvoid * pixels)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *dst = intel_drawbuf_region(intel);
+   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
+   GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
+   GLuint src_offset;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   intelFlush(&intel->ctx);
+   intel->vtbl.render_start(intel);
+   intel->vtbl.emit_state(intel);
+
+   if (!dst)
+      return GL_FALSE;
+
+   if (src) {
+      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+                                     format, type, pixels)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
+         return GL_TRUE;
+      }
+   }
+   else {
+      /* PBO only for now:
+       */
+/*       _mesa_printf("%s - not PBO\n", __FUNCTION__); */
+      return GL_FALSE;
+   }
+
+   /* There are a couple of things we can't do yet, one of which is
+    * set the correct state for pixel operations when GL texturing is
+    * enabled.  That's a pretty rare state and probably not worth the
+    * effort.  A completely device-independent version of this may do
+    * more.
+    *
+    * Similarly, we make no attempt to merge metaops processing with
+    * an enabled fragment program, though it would certainly be
+    * possible.
+    */
+   if (!intel_check_meta_tex_fragment_ops(ctx)) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad GL fragment state for metaops texture\n",
+                      __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   intel->vtbl.install_meta_state(intel);
+
+
+   /* Is this true?  Also will need to turn depth testing on according
+    * to state:
+    */
+   intel->vtbl.meta_no_stencil_write(intel);
+   intel->vtbl.meta_no_depth_write(intel);
+
+   /* Set the 3d engine to draw into the destination region:
+    */
+   intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region);
+
+   intel->vtbl.meta_import_pixel_state(intel);
+
+   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
+                                             format, type, 0, 0, 0);
+
+
+   /* Setup the pbo up as a rectangular texture, if possible.
+    *
+    * TODO: This is almost always possible if the i915 fragment
+    * program is adjusted to correctly swizzle the sampled colors.
+    * The major exception is any 24bit texture, like RGB888, for which
+    * there is no hardware support.  
+    */
+   if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset,
+                                         rowLength, height, format, type)) {
+      intel->vtbl.leave_meta_state(intel);
+      return GL_FALSE;
+   }
+
+   intel->vtbl.meta_texture_blend_replace(intel);
+
+
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      GLint srcx, srcy;
+      GLint dstx, dsty;
+
+      dstx = x;
+      dsty = dPriv->h - (y + height);
+
+      srcx = 0;                 /* skiprows/pixels already done */
+      srcy = 0;
+
+      if (0) {
+         const GLint orig_x = dstx;
+         const GLint orig_y = dsty;
+
+         if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
+                                   &dstx, &dsty, &width, &height))
+            goto out;
+
+         srcx += dstx - orig_x;
+         srcy += dsty - orig_y;
+      }
+
+
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height);
+
+      /* Must use the regular cliprect mechanism in order to get the
+       * drawing origin set correctly.  Otherwise scissor state is in
+       * incorrect coordinate space.  Does this even need to hold the
+       * lock???
+       */
+      intel_meta_draw_quad(intel,
+                           dstx, dstx + width * ctx->Pixel.ZoomX,
+                           dPriv->h - (y + height * ctx->Pixel.ZoomY),
+                           dPriv->h - (y),
+                           -ctx->Current.RasterPos[2] * .5,
+                           0x00ff00ff,
+                           srcx, srcx + width, srcy + height, srcy);
+    out:
+      intel->vtbl.leave_meta_state(intel);
+      intel_batchbuffer_flush(intel->batch);
+   }
+   UNLOCK_HARDWARE(intel);
+   return GL_TRUE;
+}
+
+
+
+
+
+/* Pros:  
+ *   - no waiting for idle before updating framebuffer.
+ *   
+ * Cons:
+ *   - if upload is by memcpy, this may actually be slower than fallback path.
+ *   - uploads the whole image even if destination is clipped
+ *   
+ * Need to benchmark.
+ *
+ * Given the questions about performance, implement for pbo's only.
+ * This path is definitely a win if the pbo is already in agp.  If it
+ * turns out otherwise, we can add the code necessary to upload client
+ * data to agp space before performing the blit.  (Though it may turn
+ * out to be better/simpler just to use the texture engine).
+ */
+static GLboolean
+do_blit_drawpixels(GLcontext * ctx,
+                   GLint x, GLint y,
+                   GLsizei width, GLsizei height,
+                   GLenum format, GLenum type,
+                   const struct gl_pixelstore_attrib *unpack,
+                   const GLvoid * pixels)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *dest = intel_drawbuf_region(intel);
+   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
+   GLuint src_offset;
+   GLuint rowLength;
+   struct _DriFenceObject *fence = NULL;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s\n", __FUNCTION__);
+
+
+   if (!dest) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - no dest\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (src) {
+      /* This validation should be done by core mesa:
+       */
+      if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
+                                     format, type, pixels)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
+         return GL_TRUE;
+      }
+   }
+   else {
+      /* PBO only for now:
+       */
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - not PBO\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (!intel_check_blit_format(dest, format, type)) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (!intel_check_meta_tex_fragment_ops(ctx)) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad GL fragment state for meta tex\n",
+                      __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (ctx->Pixel.ZoomX != 1.0F) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+
+   if (unpack->RowLength > 0)
+      rowLength = unpack->RowLength;
+   else
+      rowLength = width;
+
+   if (ctx->Pixel.ZoomY == -1.0F) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
+      return GL_FALSE;          /* later */
+      y -= height;
+   }
+   else if (ctx->Pixel.ZoomY == 1.0F) {
+      rowLength = -rowLength;
+   }
+   else {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
+                                             format, type, 0, 0, 0);
+
+   intelFlush(&intel->ctx);
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      int nbox = dPriv->numClipRects;
+      drm_clip_rect_t *box = dPriv->pClipRects;
+      drm_clip_rect_t rect;
+      drm_clip_rect_t dest_rect;
+      struct _DriBufferObject *src_buffer =
+         intel_bufferobj_buffer(intel, src, INTEL_READ);
+      int i;
+
+      dest_rect.x1 = dPriv->x + x;
+      dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
+      dest_rect.x2 = dest_rect.x1 + width;
+      dest_rect.y2 = dest_rect.y1 + height;
+
+      for (i = 0; i < nbox; i++) {
+         if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
+            continue;
+
+         intelEmitCopyBlit(intel,
+                           dest->cpp,
+                           rowLength,
+                           src_buffer, src_offset,
+                           dest->pitch,
+                           dest->buffer, 0,
+                           rect.x1 - dest_rect.x1,
+                           rect.y2 - dest_rect.y2,
+                           rect.x1,
+                           rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1);
+      }
+      fence = intel_batchbuffer_flush(intel->batch);
+      driFenceReference(fence);
+   }
+   UNLOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects)
+      driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
+
+   driFenceUnReference(fence);
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s - DONE\n", __FUNCTION__);
+
+   return GL_TRUE;
+}
+
+
+
+void
+intelDrawPixels(GLcontext * ctx,
+                GLint x, GLint y,
+                GLsizei width, GLsizei height,
+                GLenum format,
+                GLenum type,
+                const struct gl_pixelstore_attrib *unpack,
+                const GLvoid * pixels)
+{
+   if (do_blit_drawpixels(ctx, x, y, width, height, format, type,
+                          unpack, pixels))
+      return;
+
+   if (do_texture_drawpixels(ctx, x, y, width, height, format, type,
+                             unpack, pixels))
+      return;
+
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+
+   _swrast_DrawPixels(ctx, x, y, width, height, format, type, unpack, pixels);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_pixel_read.c b/src/mesa/drivers/dri/i915tex/intel_pixel_read.c
new file mode 100644 (file)
index 0000000..c1cc656
--- /dev/null
@@ -0,0 +1,317 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "image.h"
+#include "bufferobj.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "intel_blit.h"
+#include "intel_buffers.h"
+#include "intel_regions.h"
+#include "intel_pixel.h"
+#include "intel_buffer_objects.h"
+
+/* For many applications, the new ability to pull the source buffers
+ * back out of the GTT and then do the packing/conversion operations
+ * in software will be as much of an improvement as trying to get the
+ * blitter and/or texture engine to do the work. 
+ *
+ * This step is gated on private backbuffers.
+ * 
+ * Obviously the frontbuffer can't be pulled back, so that is either
+ * an argument for blit/texture readpixels, or for blitting to a
+ * temporary and then pulling that back.
+ *
+ * When the destination is a pbo, however, it's not clear if it is
+ * ever going to be pulled to main memory (though the access param
+ * will be a good hint).  So it sounds like we do want to be able to
+ * choose between blit/texture implementation on the gpu and pullback
+ * and cpu-based copying.
+ *
+ * Unless you can magically turn client memory into a PBO for the
+ * duration of this call, there will be a cpu-based copying step in
+ * any case.
+ */
+
+
+static GLboolean
+do_texture_readpixels(GLcontext * ctx,
+                      GLint x, GLint y, GLsizei width, GLsizei height,
+                      GLenum format, GLenum type,
+                      const struct gl_pixelstore_attrib *pack,
+                      struct intel_region *dest_region)
+{
+#if 0
+   struct intel_context *intel = intel_context(ctx);
+   intelScreenPrivate *screen = intel->intelScreen;
+   GLint pitch = pack->RowLength ? pack->RowLength : width;
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   int textureFormat;
+   GLenum glTextureFormat;
+   int destFormat, depthFormat, destPitch;
+   drm_clip_rect_t tmp;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+   if (ctx->_ImageTransferState ||
+       pack->SwapBytes || pack->LsbFirst || !pack->Invert) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
+
+   if (!intel->vtbl.meta_render_dest(intel, dest_region, type, format)) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         fprintf(stderr, "%s: couldn't set dest %s/%s\n",
+                 __FUNCTION__,
+                 _mesa_lookup_enum_by_nr(type),
+                 _mesa_lookup_enum_by_nr(format));
+      return GL_FALSE;
+   }
+
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      intel->vtbl.install_meta_state(intel);
+      intel->vtbl.meta_no_depth_write(intel);
+      intel->vtbl.meta_no_stencil_write(intel);
+
+      if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
+         UNLOCK_HARDWARE(intel);
+         SET_STATE(i830, state);
+         if (INTEL_DEBUG & DEBUG_PIXEL)
+            fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
+         return GL_TRUE;
+      }
+
+      y = dPriv->h - y - height;
+      x += dPriv->x;
+      y += dPriv->y;
+
+
+      /* Set the frontbuffer up as a large rectangular texture.
+       */
+      intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat);
+
+
+      intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat);
+
+
+      /* Set the 3d engine to draw into the destination region:
+       */
+
+      intel->vtbl.meta_draw_region(intel, dest_region);
+      intel->vtbl.meta_draw_format(intel, destFormat, depthFormat);     /* ?? */
+
+
+      /* Draw a single quad, no cliprects:
+       */
+      intel->vtbl.meta_disable_cliprects(intel);
+
+      intel->vtbl.draw_quad(intel,
+                            0, width, 0, height,
+                            0x00ff00ff, x, x + width, y, y + height);
+
+      intel->vtbl.leave_meta_state(intel);
+   }
+   UNLOCK_HARDWARE(intel);
+
+   intel_region_wait_fence(ctx, dest_region);   /* required by GL */
+   return GL_TRUE;
+#endif
+
+   return GL_FALSE;
+}
+
+
+
+
+static GLboolean
+do_blit_readpixels(GLcontext * ctx,
+                   GLint x, GLint y, GLsizei width, GLsizei height,
+                   GLenum format, GLenum type,
+                   const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_region *src = intel_readbuf_region(intel);
+   struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
+   GLuint dst_offset;
+   GLuint rowLength;
+   struct _DriFenceObject *fence = NULL;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s\n", __FUNCTION__);
+
+   if (!src)
+      return GL_FALSE;
+
+   if (dst) {
+      /* XXX This validation should be done by core mesa:
+       */
+      if (!_mesa_validate_pbo_access(2, pack, width, height, 1,
+                                     format, type, pixels)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
+         return GL_TRUE;
+      }
+   }
+   else {
+      /* PBO only for now:
+       */
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - not PBO\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+
+   if (ctx->_ImageTransferState ||
+       !intel_check_blit_format(src, format, type)) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s: bad packing params\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (pack->RowLength > 0)
+      rowLength = pack->RowLength;
+   else
+      rowLength = width;
+
+   if (pack->Invert) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+         _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+   else {
+      rowLength = -rowLength;
+   }
+
+   /* XXX 64-bit cast? */
+   dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height,
+                                             format, type, 0, 0, 0);
+
+
+   /* Although the blits go on the command buffer, need to do this and
+    * fire with lock held to guarentee cliprects are correct.
+    */
+   intelFlush(&intel->ctx);
+   LOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects) {
+      GLboolean all = (width * height * src->cpp == dst->Base.Size &&
+                       x == 0 && dst_offset == 0);
+
+      struct _DriBufferObject *dst_buffer =
+         intel_bufferobj_buffer(intel, dst, all ? INTEL_WRITE_FULL :
+                                INTEL_WRITE_PART);
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      int nbox = dPriv->numClipRects;
+      drm_clip_rect_t *box = dPriv->pClipRects;
+      drm_clip_rect_t rect;
+      drm_clip_rect_t src_rect;
+      int i;
+
+      src_rect.x1 = dPriv->x + x;
+      src_rect.y1 = dPriv->y + dPriv->h - (y + height);
+      src_rect.x2 = src_rect.x1 + width;
+      src_rect.y2 = src_rect.y1 + height;
+
+
+
+      for (i = 0; i < nbox; i++) {
+         if (!intel_intersect_cliprects(&rect, &src_rect, &box[i]))
+            continue;
+
+         intelEmitCopyBlit(intel,
+                           src->cpp,
+                           src->pitch, src->buffer, 0,
+                           rowLength,
+                           dst_buffer, dst_offset,
+                           rect.x1,
+                           rect.y1,
+                           rect.x1 - src_rect.x1,
+                           rect.y2 - src_rect.y2,
+                           rect.x2 - rect.x1, rect.y2 - rect.y1);
+      }
+
+      fence = intel_batchbuffer_flush(intel->batch);
+      driFenceReference(fence);
+
+   }
+   UNLOCK_HARDWARE(intel);
+
+   if (intel->driDrawable->numClipRects)
+      driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, 
+                    GL_FALSE);
+
+   driFenceUnReference(fence);
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s - DONE\n", __FUNCTION__);
+
+   return GL_TRUE;
+}
+
+void
+intelReadPixels(GLcontext * ctx,
+                GLint x, GLint y, GLsizei width, GLsizei height,
+                GLenum format, GLenum type,
+                const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
+{
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   intelFlush(ctx);
+
+   if (do_blit_readpixels
+       (ctx, x, y, width, height, format, type, pack, pixels))
+      return;
+
+   if (do_texture_readpixels
+       (ctx, x, y, width, height, format, type, pack, pixels))
+      return;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+
+   _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_reg.h b/src/mesa/drivers/dri/i915tex/intel_reg.h
new file mode 100644 (file)
index 0000000..1ec1532
--- /dev/null
@@ -0,0 +1,84 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#ifndef _INTEL_REG_H_
+#define _INTEL_REG_H_
+
+
+
+#define CMD_3D (0x3<<29)
+
+
+#define _3DPRIMITIVE         ((0x3<<29)|(0x1f<<24))
+#define PRIM_INDIRECT            (1<<23)
+#define PRIM_INLINE              (0<<23)
+#define PRIM_INDIRECT_SEQUENTIAL (0<<17)
+#define PRIM_INDIRECT_ELTS       (1<<17)
+
+#define PRIM3D_TRILIST         (0x0<<18)
+#define PRIM3D_TRISTRIP        (0x1<<18)
+#define PRIM3D_TRISTRIP_RVRSE  (0x2<<18)
+#define PRIM3D_TRIFAN          (0x3<<18)
+#define PRIM3D_POLY            (0x4<<18)
+#define PRIM3D_LINELIST        (0x5<<18)
+#define PRIM3D_LINESTRIP       (0x6<<18)
+#define PRIM3D_RECTLIST        (0x7<<18)
+#define PRIM3D_POINTLIST       (0x8<<18)
+#define PRIM3D_DIB             (0x9<<18)
+#define PRIM3D_MASK            (0x1f<<18)
+
+#define I915PACKCOLOR4444(r,g,b,a) \
+  ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+#define I915PACKCOLOR1555(r,g,b,a) \
+  ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+    ((a) ? 0x8000 : 0))
+
+#define I915PACKCOLOR565(r,g,b) \
+  ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+#define I915PACKCOLOR8888(r,g,b,a) \
+  ((a<<24) | (r<<16) | (g<<8) | b)
+
+
+
+
+#define BR00_BITBLT_CLIENT   0x40000000
+#define BR00_OP_COLOR_BLT    0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN   0x80000000
+
+#define XY_COLOR_BLT_CMD               ((2<<29)|(0x50<<22)|0x4)
+#define XY_COLOR_BLT_WRITE_ALPHA       (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB         (1<<20)
+
+#define XY_SRC_COPY_BLT_CMD             ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_regions.c b/src/mesa/drivers/dri/i915tex/intel_regions.c
new file mode 100644 (file)
index 0000000..064a34c
--- /dev/null
@@ -0,0 +1,466 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/* Provide additional functionality on top of bufmgr buffers:
+ *   - 2d semantics and blit operations
+ *   - refcounting of buffers for multiple images in a buffer.
+ *   - refcounting of buffer mappings.
+ *   - some logic for moving the buffers to the best memory pools for
+ *     given operations.
+ *
+ * Most of this is to make it easier to implement the fixed-layout
+ * mipmap tree required by intel hardware in the face of GL's
+ * programming interface where each image can be specifed in random
+ * order and it isn't clear what layout the tree should have until the
+ * last moment.
+ */
+
+#include "intel_context.h"
+#include "intel_regions.h"
+#include "intel_blit.h"
+#include "intel_buffer_objects.h"
+#include "dri_bufmgr.h"
+#include "intel_batchbuffer.h"
+
+#define FILE_DEBUG_FLAG DEBUG_REGION
+
+void
+intel_region_idle(intelScreenPrivate *intelScreen, struct intel_region *region)
+{
+   DBG("%s\n", __FUNCTION__);
+   if (region && region->buffer)
+      driBOWaitIdle(region->buffer, GL_FALSE);
+}
+
+/* XXX: Thread safety?
+ */
+GLubyte *
+intel_region_map(intelScreenPrivate *intelScreen, struct intel_region *region)
+{
+   DBG("%s\n", __FUNCTION__);
+   if (!region->map_refcount++) {
+      if (region->pbo)
+         intel_region_cow(intelScreen, region);
+
+      region->map = driBOMap(region->buffer,
+                             DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+   }
+
+   return region->map;
+}
+
+void
+intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *region)
+{
+   DBG("%s\n", __FUNCTION__);
+   if (!--region->map_refcount) {
+      driBOUnmap(region->buffer);
+      region->map = NULL;
+   }
+}
+
+#undef TEST_CACHED_TEXTURES
+
+struct intel_region *
+intel_region_alloc(intelScreenPrivate *intelScreen,
+                   GLuint cpp, GLuint pitch, GLuint height)
+{
+   struct intel_region *region = calloc(sizeof(*region), 1);
+
+   DBG("%s\n", __FUNCTION__);
+
+   region->cpp = cpp;
+   region->pitch = pitch;
+   region->height = height;     /* needed? */
+   region->refcount = 1;
+
+   driGenBuffers(intelScreen->regionPool,
+                 "region", 1, &region->buffer, 64,
+#ifdef TEST_CACHED_TEXTURES             
+                DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_BIND_CACHED |
+                DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 
+#else
+                0,
+#endif
+                0);
+   driBOData(region->buffer, pitch * cpp * height, NULL, 0);
+   return region;
+}
+
+void
+intel_region_reference(struct intel_region **dst, struct intel_region *src)
+{
+   assert(*dst == NULL);
+   if (src) {
+      src->refcount++;
+      *dst = src;
+   }
+}
+
+void
+intel_region_release(struct intel_region **region)
+{
+   if (!*region)
+      return;
+
+   DBG("%s %d\n", __FUNCTION__, (*region)->refcount - 1);
+
+   ASSERT((*region)->refcount > 0);
+   (*region)->refcount--;
+
+   if ((*region)->refcount == 0) {
+      assert((*region)->map_refcount == 0);
+
+      if ((*region)->pbo)
+        (*region)->pbo->region = NULL;
+      (*region)->pbo = NULL;
+      driBOUnReference((*region)->buffer);
+      free(*region);
+   }
+   *region = NULL;
+}
+
+
+struct intel_region *
+intel_region_create_static(intelScreenPrivate *intelScreen,
+                           GLuint mem_type,
+                           GLuint offset,
+                           void *virtual,
+                           GLuint cpp, GLuint pitch, GLuint height)
+{
+   struct intel_region *region = calloc(sizeof(*region), 1);
+   DBG("%s\n", __FUNCTION__);
+
+   region->cpp = cpp;
+   region->pitch = pitch;
+   region->height = height;     /* needed? */
+   region->refcount = 1;
+
+   /*
+    * We use a "shared" buffer type to indicate buffers created and
+    * shared by others.
+    */
+
+   driGenBuffers(intelScreen->staticPool, "static region", 1,
+                 &region->buffer, 64,
+                 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
+                 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+   driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0);
+
+   return region;
+}
+
+
+
+void
+intel_region_update_static(intelScreenPrivate *intelScreen,
+                          struct intel_region *region,
+                           GLuint mem_type,
+                           GLuint offset,
+                           void *virtual,
+                           GLuint cpp, GLuint pitch, GLuint height)
+{
+   DBG("%s\n", __FUNCTION__);
+
+   region->cpp = cpp;
+   region->pitch = pitch;
+   region->height = height;     /* needed? */
+
+   /*
+    * We use a "shared" buffer type to indicate buffers created and
+    * shared by others.
+    */
+
+   driDeleteBuffers(1, &region->buffer);
+   driGenBuffers(intelScreen->staticPool, "static region", 1,
+                 &region->buffer, 64,
+                 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
+                 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+   driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0);
+
+}
+
+
+
+/*
+ * XXX Move this into core Mesa?
+ */
+static void
+_mesa_copy_rect(GLubyte * dst,
+                GLuint cpp,
+                GLuint dst_pitch,
+                GLuint dst_x,
+                GLuint dst_y,
+                GLuint width,
+                GLuint height,
+                GLubyte * src, GLuint src_pitch, GLuint src_x, GLuint src_y)
+{
+   GLuint i;
+
+   dst_pitch *= cpp;
+   src_pitch *= cpp;
+   dst += dst_x * cpp;
+   src += src_x * cpp;
+   dst += dst_y * dst_pitch;
+   src += src_y * dst_pitch;
+   width *= cpp;
+
+   if (width == dst_pitch && width == src_pitch)
+      memcpy(dst, src, height * width);
+   else {
+      for (i = 0; i < height; i++) {
+         memcpy(dst, src, width);
+         dst += dst_pitch;
+         src += src_pitch;
+      }
+   }
+}
+
+
+/* Upload data to a rectangular sub-region.  Lots of choices how to do this:
+ *
+ * - memcpy by span to current destination
+ * - upload data as new buffer and blit
+ *
+ * Currently always memcpy.
+ */
+void
+intel_region_data(intelScreenPrivate *intelScreen,
+                  struct intel_region *dst,
+                  GLuint dst_offset,
+                  GLuint dstx, GLuint dsty,
+                  void *src, GLuint src_pitch,
+                  GLuint srcx, GLuint srcy, GLuint width, GLuint height)
+{
+   struct intel_context *intel = intelScreenContext(intelScreen);
+
+   DBG("%s\n", __FUNCTION__);
+
+   if (intel == NULL)
+      return;
+
+   if (dst->pbo) {
+      if (dstx == 0 &&
+          dsty == 0 && width == dst->pitch && height == dst->height)
+         intel_region_release_pbo(intelScreen, dst);
+      else
+         intel_region_cow(intelScreen, dst);
+   }
+
+
+   LOCK_HARDWARE(intel);
+
+   _mesa_copy_rect(intel_region_map(intelScreen, dst) + dst_offset,
+                   dst->cpp,
+                   dst->pitch,
+                   dstx, dsty, width, height, src, src_pitch, srcx, srcy);
+
+   intel_region_unmap(intelScreen, dst);
+
+   UNLOCK_HARDWARE(intel);
+
+}
+
+/* Copy rectangular sub-regions. Need better logic about when to
+ * push buffers into AGP - will currently do so whenever possible.
+ */
+void
+intel_region_copy(intelScreenPrivate *intelScreen,
+                  struct intel_region *dst,
+                  GLuint dst_offset,
+                  GLuint dstx, GLuint dsty,
+                  struct intel_region *src,
+                  GLuint src_offset,
+                  GLuint srcx, GLuint srcy, GLuint width, GLuint height)
+{
+   struct intel_context *intel = intelScreenContext(intelScreen);
+
+   DBG("%s\n", __FUNCTION__);
+
+   if (intel == NULL)
+      return;
+
+   if (dst->pbo) {
+      if (dstx == 0 &&
+          dsty == 0 && width == dst->pitch && height == dst->height)
+         intel_region_release_pbo(intelScreen, dst);
+      else
+         intel_region_cow(intelScreen, dst);
+   }
+
+   assert(src->cpp == dst->cpp);
+
+   intelEmitCopyBlit(intel,
+                     dst->cpp,
+                     src->pitch, src->buffer, src_offset,
+                     dst->pitch, dst->buffer, dst_offset,
+                     srcx, srcy, dstx, dsty, width, height);
+}
+
+/* Fill a rectangular sub-region.  Need better logic about when to
+ * push buffers into AGP - will currently do so whenever possible.
+ */
+void
+intel_region_fill(intelScreenPrivate *intelScreen,
+                  struct intel_region *dst,
+                  GLuint dst_offset,
+                  GLuint dstx, GLuint dsty,
+                  GLuint width, GLuint height, GLuint color)
+{
+   struct intel_context *intel = intelScreenContext(intelScreen);
+
+   DBG("%s\n", __FUNCTION__);
+
+   if (intel == NULL)
+      return;   
+
+   if (dst->pbo) {
+      if (dstx == 0 &&
+          dsty == 0 && width == dst->pitch && height == dst->height)
+         intel_region_release_pbo(intelScreen, dst);
+      else
+         intel_region_cow(intelScreen, dst);
+   }
+
+   intelEmitFillBlit(intel,
+                     dst->cpp,
+                     dst->pitch, dst->buffer, dst_offset,
+                     dstx, dsty, width, height, color);
+}
+
+/* Attach to a pbo, discarding our data.  Effectively zero-copy upload
+ * the pbo's data.
+ */
+void
+intel_region_attach_pbo(intelScreenPrivate *intelScreen,
+                        struct intel_region *region,
+                        struct intel_buffer_object *pbo)
+{
+   if (region->pbo == pbo)
+      return;
+
+   /* If there is already a pbo attached, break the cow tie now.
+    * Don't call intel_region_release_pbo() as that would
+    * unnecessarily allocate a new buffer we would have to immediately
+    * discard.
+    */
+   if (region->pbo) {
+      region->pbo->region = NULL;
+      region->pbo = NULL;
+   }
+
+   if (region->buffer) {
+      driDeleteBuffers(1, &region->buffer);
+      region->buffer = NULL;
+   }
+
+   region->pbo = pbo;
+   region->pbo->region = region;
+   region->buffer = driBOReference(pbo->buffer);
+}
+
+
+/* Break the COW tie to the pbo.  The pbo gets to keep the data.
+ */
+void
+intel_region_release_pbo(intelScreenPrivate *intelScreen,
+                         struct intel_region *region)
+{
+   assert(region->buffer == region->pbo->buffer);
+   region->pbo->region = NULL;
+   region->pbo = NULL;
+   driBOUnReference(region->buffer);
+   region->buffer = NULL;
+
+   driGenBuffers(intelScreen->regionPool,
+                 "region", 1, &region->buffer, 64, 0, 0);
+   driBOData(region->buffer,
+             region->cpp * region->pitch * region->height, NULL, 0);
+}
+
+/* Break the COW tie to the pbo.  Both the pbo and the region end up
+ * with a copy of the data.
+ */
+void
+intel_region_cow(intelScreenPrivate *intelScreen, struct intel_region *region)
+{
+   struct intel_context *intel = intelScreenContext(intelScreen);
+   struct intel_buffer_object *pbo = region->pbo;
+
+   if (intel == NULL)
+      return;
+
+   intel_region_release_pbo(intelScreen, region);
+
+   assert(region->cpp * region->pitch * region->height == pbo->Base.Size);
+
+   DBG("%s (%d bytes)\n", __FUNCTION__, pbo->Base.Size);
+
+   /* Now blit from the texture buffer to the new buffer: 
+    */
+
+   intel_batchbuffer_flush(intel->batch);
+
+   if (!intel->locked) {
+      LOCK_HARDWARE(intel);
+      intelEmitCopyBlit(intel,
+                       region->cpp,
+                       region->pitch,
+                       region->buffer, 0,
+                       region->pitch,
+                       pbo->buffer, 0,
+                       0, 0, 0, 0, region->pitch, region->height);
+      
+      intel_batchbuffer_flush(intel->batch);
+      UNLOCK_HARDWARE(intel);
+   }
+   else {
+      intelEmitCopyBlit(intel,
+                       region->cpp,
+                       region->pitch,
+                       region->buffer, 0,
+                       region->pitch,
+                       pbo->buffer, 0,
+                       0, 0, 0, 0, region->pitch, region->height);
+      
+      intel_batchbuffer_flush(intel->batch);
+   }
+}
+
+struct _DriBufferObject *
+intel_region_buffer(intelScreenPrivate *intelScreen,
+                    struct intel_region *region, GLuint flag)
+{
+   if (region->pbo) {
+      if (flag == INTEL_WRITE_PART)
+         intel_region_cow(intelScreen, region);
+      else if (flag == INTEL_WRITE_FULL)
+         intel_region_release_pbo(intelScreen, region);
+   }
+
+   return region->buffer;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_regions.h b/src/mesa/drivers/dri/i915tex/intel_regions.h
new file mode 100644 (file)
index 0000000..1415bac
--- /dev/null
@@ -0,0 +1,141 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_REGIONS_H
+#define INTEL_REGIONS_H
+
+#include "mtypes.h"
+#include "intel_screen.h"
+
+struct intel_context;
+struct intel_buffer_object;
+
+/**
+ * A layer on top of the bufmgr buffers that adds a few useful things:
+ *
+ * - Refcounting for local buffer references.
+ * - Refcounting for buffer maps
+ * - Buffer dimensions - pitch and height.
+ * - Blitter commands for copying 2D regions between buffers. (really???)
+ */
+struct intel_region
+{
+   struct _DriBufferObject *buffer;   /**< buffer manager's buffer ID */
+   GLuint refcount; /**< Reference count for region */
+   GLuint cpp;      /**< bytes per pixel */
+   GLuint pitch;    /**< in pixels */
+   GLuint height;   /**< in pixels */
+   GLubyte *map;    /**< only non-NULL when region is actually mapped */
+   GLuint map_refcount;  /**< Reference count for mapping */
+
+   GLuint draw_offset; /**< Offset of drawing address within the region */
+
+   struct intel_buffer_object *pbo;     /* zero-copy uploads */
+};
+
+
+/* Allocate a refcounted region.  Pointers to regions should only be
+ * copied by calling intel_reference_region().
+ */
+struct intel_region *intel_region_alloc(intelScreenPrivate *intelScreen,
+                                        GLuint cpp,
+                                        GLuint pitch, GLuint height);
+
+void intel_region_reference(struct intel_region **dst,
+                            struct intel_region *src);
+
+void intel_region_release(struct intel_region **ib);
+
+extern struct intel_region 
+*intel_region_create_static(intelScreenPrivate *intelScreen,
+                           GLuint mem_type,
+                           GLuint offset,
+                           void *virtual,
+                           GLuint cpp,
+                           GLuint pitch, GLuint height);
+extern void 
+intel_region_update_static(intelScreenPrivate *intelScreen,
+                          struct intel_region *region,
+                          GLuint mem_type,
+                          GLuint offset,
+                          void *virtual,
+                          GLuint cpp, GLuint pitch, GLuint height);
+
+
+void intel_region_idle(intelScreenPrivate *intelScreen,
+                      struct intel_region *ib);
+
+/* Map/unmap regions.  This is refcounted also: 
+ */
+GLubyte *intel_region_map(intelScreenPrivate *intelScreen,
+                          struct intel_region *ib);
+
+void intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *ib);
+
+
+/* Upload data to a rectangular sub-region
+ */
+void intel_region_data(intelScreenPrivate *intelScreen,
+                       struct intel_region *dest,
+                       GLuint dest_offset,
+                       GLuint destx, GLuint desty,
+                       void *src, GLuint src_stride,
+                       GLuint srcx, GLuint srcy, GLuint width, GLuint height);
+
+/* Copy rectangular sub-regions
+ */
+void intel_region_copy(intelScreenPrivate *intelScreen,
+                       struct intel_region *dest,
+                       GLuint dest_offset,
+                       GLuint destx, GLuint desty,
+                       struct intel_region *src,
+                       GLuint src_offset,
+                       GLuint srcx, GLuint srcy, GLuint width, GLuint height);
+
+/* Fill a rectangular sub-region
+ */
+void intel_region_fill(intelScreenPrivate *intelScreen,
+                       struct intel_region *dest,
+                       GLuint dest_offset,
+                       GLuint destx, GLuint desty,
+                       GLuint width, GLuint height, GLuint color);
+
+/* Helpers for zerocopy uploads, particularly texture image uploads:
+ */
+void intel_region_attach_pbo(intelScreenPrivate *intelScreen,
+                             struct intel_region *region,
+                             struct intel_buffer_object *pbo);
+void intel_region_release_pbo(intelScreenPrivate *intelScreen,
+                              struct intel_region *region);
+void intel_region_cow(intelScreenPrivate *intelScreen,
+                      struct intel_region *region);
+
+struct _DriBufferObject *intel_region_buffer(intelScreenPrivate *intelScreen,
+                                             struct intel_region *region,
+                                             GLuint flag);
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_render.c b/src/mesa/drivers/dri/i915tex/intel_render.c
new file mode 100644 (file)
index 0000000..f9fa550
--- /dev/null
@@ -0,0 +1,242 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers.  Use strip/fan hardware acceleration where possible.
+ *
+ */
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "enums.h"
+
+#include "tnl/t_context.h"
+#include "tnl/t_vertex.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_tris.h"
+#include "intel_batchbuffer.h"
+#include "intel_reg.h"
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers.  Use strip/fan hardware primitives where possible.
+ * Try to simulate missing primitives with indexed vertices.
+ */
+#define HAVE_POINTS      0      /* Has it, but can't use because subpixel has to
+                                 * be adjusted for points on the INTEL/I845G
+                                 */
+#define HAVE_LINES       1
+#define HAVE_LINE_STRIPS 1
+#define HAVE_TRIANGLES   1
+#define HAVE_TRI_STRIPS  1
+#define HAVE_TRI_STRIP_1 0      /* has it, template can't use it yet */
+#define HAVE_TRI_FANS    1
+#define HAVE_POLYGONS    1
+#define HAVE_QUADS       0
+#define HAVE_QUAD_STRIPS 0
+
+#define HAVE_ELTS        0
+
+static GLuint hw_prim[GL_POLYGON + 1] = {
+   0,
+   PRIM3D_LINELIST,
+   PRIM3D_LINESTRIP,
+   PRIM3D_LINESTRIP,
+   PRIM3D_TRILIST,
+   PRIM3D_TRISTRIP,
+   PRIM3D_TRIFAN,
+   0,
+   0,
+   PRIM3D_POLY
+};
+
+static const GLenum reduced_prim[GL_POLYGON + 1] = {
+   GL_POINTS,
+   GL_LINES,
+   GL_LINES,
+   GL_LINES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES
+};
+
+static const int scale_prim[GL_POLYGON + 1] = {
+   0,                           /* fallback case */
+   1,
+   2,
+   2,
+   1,
+   3,
+   3,
+   0,                           /* fallback case */
+   0,                           /* fallback case */
+   3
+};
+
+
+static void
+intelDmaPrimitive(struct intel_context *intel, GLenum prim)
+{
+   if (0)
+      fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
+   INTEL_FIREVERTICES(intel);
+   intel->vtbl.reduced_primitive_state(intel, reduced_prim[prim]);
+   intelStartInlinePrimitive(intel, hw_prim[prim], INTEL_BATCH_CLIPRECTS);
+}
+
+
+#define LOCAL_VARS struct intel_context *intel = intel_context(ctx)
+#define INIT( prim )                           \
+do {                                           \
+   intelDmaPrimitive( intel, prim );           \
+} while (0)
+
+#define FLUSH() INTEL_FIREVERTICES(intel)
+
+#define GET_SUBSEQUENT_VB_MAX_VERTS() \
+  ((intel->batch->size - 1500) / (intel->vertex_size*4))
+#define GET_CURRENT_VB_MAX_VERTS() GET_SUBSEQUENT_VB_MAX_VERTS()
+
+#define ALLOC_VERTS( nr ) \
+   intelExtendInlinePrimitive( intel, (nr) * intel->vertex_size )
+
+#define EMIT_VERTS( ctx, j, nr, buf ) \
+  _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf )
+
+#define TAG(x) intel_##x
+#include "tnl_dd/t_dd_dmatmp.h"
+
+
+/**********************************************************************/
+/*                          Render pipeline stage                     */
+/**********************************************************************/
+
+/* Heuristic to choose between the two render paths:  
+ */
+static GLboolean
+choose_render(struct intel_context *intel, struct vertex_buffer *VB)
+{
+   int vertsz = intel->vertex_size;
+   int cost_render = 0;
+   int cost_fallback = 0;
+   int nr_prims = 0;
+   int nr_rprims = 0;
+   int nr_rverts = 0;
+   int rprim = intel->reduced_primitive;
+   int i = 0;
+
+   for (i = 0; i < VB->PrimitiveCount; i++) {
+      GLuint prim = VB->Primitive[i].mode;
+      GLuint length = VB->Primitive[i].count;
+
+      if (!length)
+         continue;
+
+      nr_prims++;
+      nr_rverts += length * scale_prim[prim & PRIM_MODE_MASK];
+
+      if (reduced_prim[prim & PRIM_MODE_MASK] != rprim) {
+         nr_rprims++;
+         rprim = reduced_prim[prim & PRIM_MODE_MASK];
+      }
+   }
+
+   /* One point for each generated primitive:
+    */
+   cost_render = nr_prims;
+   cost_fallback = nr_rprims;
+
+   /* One point for every 1024 dwords (4k) of dma:
+    */
+   cost_render += (vertsz * i) / 1024;
+   cost_fallback += (vertsz * nr_rverts) / 1024;
+
+   if (0)
+      fprintf(stderr, "cost render: %d fallback: %d\n",
+              cost_render, cost_fallback);
+
+   if (cost_render > cost_fallback)
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+
+static GLboolean
+intel_run_render(GLcontext * ctx, struct tnl_pipeline_stage *stage)
+{
+   struct intel_context *intel = intel_context(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i;
+
+   /* Don't handle clipping or indexed vertices.
+    */
+   if (intel->RenderIndex != 0 ||
+       !intel_validate_render(ctx, VB) || !choose_render(intel, VB)) {
+      return GL_TRUE;
+   }
+
+   tnl->clipspace.new_inputs |= VERT_BIT_POS;
+
+   tnl->Driver.Render.Start(ctx);
+
+   for (i = 0; i < VB->PrimitiveCount; i++) {
+      GLuint prim = VB->Primitive[i].mode;
+      GLuint start = VB->Primitive[i].start;
+      GLuint length = VB->Primitive[i].count;
+
+      if (!length)
+         continue;
+
+      intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start,
+                                                     start + length, prim);
+   }
+
+   tnl->Driver.Render.Finish(ctx);
+
+   INTEL_FIREVERTICES(intel);
+
+   return GL_FALSE;             /* finished the pipe */
+}
+
+const struct tnl_pipeline_stage _intel_render_stage = {
+   "intel render",
+   NULL,
+   NULL,
+   NULL,
+   NULL,
+   intel_run_render             /* run */
+};
diff --git a/src/mesa/drivers/dri/i915tex/intel_rotate.c b/src/mesa/drivers/dri/i915tex/intel_rotate.c
new file mode 100644 (file)
index 0000000..12d98c4
--- /dev/null
@@ -0,0 +1,237 @@
+
+/**
+ * Routines for simple 2D->2D transformations for rotated, flipped screens.
+ *
+ * XXX This code is not intel-specific.  Move it into a common/utility
+ * someday.
+ */
+
+#include "intel_rotate.h"
+
+#define MIN2(A, B)   ( ((A) < (B)) ? (A) : (B) )
+
+#define ABS(A)  ( ((A) < 0) ? -(A) : (A) )
+
+
+void
+matrix23Set(struct matrix23 *m,
+            int m00, int m01, int m02, int m10, int m11, int m12)
+{
+   m->m00 = m00;
+   m->m01 = m01;
+   m->m02 = m02;
+   m->m10 = m10;
+   m->m11 = m11;
+   m->m12 = m12;
+}
+
+
+/*
+ * Transform (x,y) coordinate by the given matrix.
+ */
+void
+matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y)
+{
+   const float x0 = *x;
+   const float y0 = *y;
+
+   *x = m->m00 * x0 + m->m01 * y0 + m->m02;
+   *y = m->m10 * x0 + m->m11 * y0 + m->m12;
+}
+
+
+void
+matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y)
+{
+   const int x0 = *x;
+   const int y0 = *y;
+
+   *x = m->m00 * x0 + m->m01 * y0 + m->m02;
+   *y = m->m10 * x0 + m->m11 * y0 + m->m12;
+}
+
+
+/*
+ * Transform a width and height by the given matrix.
+ * XXX this could be optimized quite a bit.
+ */
+void
+matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist)
+{
+   int x0 = 0, y0 = 0;
+   int x1 = *xDist, y1 = 0;
+   int x2 = 0, y2 = *yDist;
+   matrix23TransformCoordi(m, &x0, &y0);
+   matrix23TransformCoordi(m, &x1, &y1);
+   matrix23TransformCoordi(m, &x2, &y2);
+
+   *xDist = (x1 - x0) + (x2 - x0);
+   *yDist = (y1 - y0) + (y2 - y0);
+
+   if (*xDist < 0)
+      *xDist = -*xDist;
+   if (*yDist < 0)
+      *yDist = -*yDist;
+}
+
+
+/**
+ * Transform the rect defined by (x, y, w, h) by m.
+ */
+void
+matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w,
+                      int *h)
+{
+   int x0 = *x, y0 = *y;
+   int x1 = *x + *w, y1 = *y;
+   int x2 = *x + *w, y2 = *y + *h;
+   int x3 = *x, y3 = *y + *h;
+   matrix23TransformCoordi(m, &x0, &y0);
+   matrix23TransformCoordi(m, &x1, &y1);
+   matrix23TransformCoordi(m, &x2, &y2);
+   matrix23TransformCoordi(m, &x3, &y3);
+   *w = ABS(x1 - x0) + ABS(x2 - x1);
+   /**w = ABS(*w);*/
+   *h = ABS(y1 - y0) + ABS(y2 - y1);
+   /**h = ABS(*h);*/
+   *x = MIN2(x0, x1);
+   *x = MIN2(*x, x2);
+   *y = MIN2(y0, y1);
+   *y = MIN2(*y, y2);
+}
+
+
+/*
+ * Make rotation matrix for width X height screen.
+ */
+void
+matrix23Rotate(struct matrix23 *m, int width, int height, int angle)
+{
+   switch (angle) {
+   case 0:
+      matrix23Set(m, 1, 0, 0, 0, 1, 0);
+      break;
+   case 90:
+      matrix23Set(m, 0, 1, 0, -1, 0, width);
+      break;
+   case 180:
+      matrix23Set(m, -1, 0, width, 0, -1, height);
+      break;
+   case 270:
+      matrix23Set(m, 0, -1, height, 1, 0, 0);
+      break;
+   default:
+      /*abort() */ ;
+   }
+}
+
+
+/*
+ * Make flip/reflection matrix for width X height screen.
+ */
+void
+matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip)
+{
+   if (xflip) {
+      m->m00 = -1;
+      m->m01 = 0;
+      m->m02 = width - 1;
+   }
+   else {
+      m->m00 = 1;
+      m->m01 = 0;
+      m->m02 = 0;
+   }
+   if (yflip) {
+      m->m10 = 0;
+      m->m11 = -1;
+      m->m12 = height - 1;
+   }
+   else {
+      m->m10 = 0;
+      m->m11 = 1;
+      m->m12 = 0;
+   }
+}
+
+
+/*
+ * result = a * b
+ */
+void
+matrix23Multiply(struct matrix23 *result,
+                 const struct matrix23 *a, const struct matrix23 *b)
+{
+   result->m00 = a->m00 * b->m00 + a->m01 * b->m10;
+   result->m01 = a->m00 * b->m01 + a->m01 * b->m11;
+   result->m02 = a->m00 * b->m02 + a->m01 * b->m12 + a->m02;
+
+   result->m10 = a->m10 * b->m00 + a->m11 * b->m10;
+   result->m11 = a->m10 * b->m01 + a->m11 * b->m11;
+   result->m12 = a->m10 * b->m02 + a->m11 * b->m12 + a->m12;
+}
+
+
+#if 000
+
+#include <stdio.h>
+
+int
+main(int argc, char *argv[])
+{
+   int width = 500, height = 400;
+   int rot;
+   int fx = 0, fy = 0;          /* flip x and/or y ? */
+   int coords[4][2];
+
+   /* four corner coords to test with */
+   coords[0][0] = 0;
+   coords[0][1] = 0;
+   coords[1][0] = width - 1;
+   coords[1][1] = 0;
+   coords[2][0] = width - 1;
+   coords[2][1] = height - 1;
+   coords[3][0] = 0;
+   coords[3][1] = height - 1;
+
+
+   for (rot = 0; rot < 360; rot += 90) {
+      struct matrix23 rotate, flip, m;
+      int i;
+
+      printf("Rot %d, xFlip %d, yFlip %d:\n", rot, fx, fy);
+
+      /* make transformation matrix 'm' */
+      matrix23Rotate(&rotate, width, height, rot);
+      matrix23Flip(&flip, width, height, fx, fy);
+      matrix23Multiply(&m, &rotate, &flip);
+
+      /* xform four coords */
+      for (i = 0; i < 4; i++) {
+         int x = coords[i][0];
+         int y = coords[i][1];
+         matrix23TransformCoordi(&m, &x, &y);
+         printf("  %d, %d  -> %d %d\n", coords[i][0], coords[i][1], x, y);
+      }
+
+      /* xform width, height */
+      {
+         int x = width;
+         int y = height;
+         matrix23TransformDistance(&m, &x, &y);
+         printf("  %d x %d -> %d x %d\n", width, height, x, y);
+      }
+
+      /* xform rect */
+      {
+         int x = 50, y = 10, w = 200, h = 100;
+         matrix23TransformRect(&m, &x, &y, &w, &h);
+         printf("  %d,%d %d x %d -> %d, %d %d x %d\n", 50, 10, 200, 100,
+                x, y, w, h);
+      }
+
+   }
+
+   return 0;
+}
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_rotate.h b/src/mesa/drivers/dri/i915tex/intel_rotate.h
new file mode 100644 (file)
index 0000000..9c8802c
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef INTEL_ROTATE_H
+#define INTEL_ROTATE_H 1
+
+struct matrix23
+{
+   int m00, m01, m02;
+   int m10, m11, m12;
+};
+
+
+
+extern void
+matrix23Set(struct matrix23 *m,
+            int m00, int m01, int m02, int m10, int m11, int m12);
+
+extern void matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y);
+
+extern void
+matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y);
+
+extern void
+matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist);
+
+extern void
+matrix23TransformRect(const struct matrix23 *m,
+                      int *x, int *y, int *w, int *h);
+
+extern void
+matrix23Rotate(struct matrix23 *m, int width, int height, int angle);
+
+extern void
+matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip);
+
+extern void
+matrix23Multiply(struct matrix23 *result,
+                 const struct matrix23 *a, const struct matrix23 *b);
+
+
+#endif /* INTEL_ROTATE_H */
diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c
new file mode 100644 (file)
index 0000000..9bbfabb
--- /dev/null
@@ -0,0 +1,864 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "context.h"
+#include "framebuffer.h"
+#include "matrix.h"
+#include "renderbuffer.h"
+#include "simple_list.h"
+#include "utils.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+
+#include "intel_screen.h"
+
+#include "intel_buffers.h"
+#include "intel_tex.h"
+#include "intel_span.h"
+#include "intel_tris.h"
+#include "intel_ioctl.h"
+#include "intel_fbo.h"
+
+#include "i830_dri.h"
+#include "dri_bufpool.h"
+#include "intel_regions.h"
+#include "intel_batchbuffer.h"
+
+PUBLIC const char __driConfigOptions[] =
+   DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
+   DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
+   DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
+   DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
+   DRI_CONF_FORCE_S3TC_ENABLE(false)
+   DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+   DRI_CONF_SECTION_END DRI_CONF_END;
+     const GLuint __driNConfigOptions = 4;
+
+#ifdef USE_NEW_INTERFACE
+     static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
+#endif /*USE_NEW_INTERFACE */
+
+     extern const struct dri_extension card_extensions[];
+
+/**
+ * Map all the memory regions described by the screen.
+ * \return GL_TRUE if success, GL_FALSE if error.
+ */
+GLboolean
+intelMapScreenRegions(__DRIscreenPrivate * sPriv)
+{
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
+
+   if (intelScreen->front.handle) {
+      if (drmMap(sPriv->fd,
+                 intelScreen->front.handle,
+                 intelScreen->front.size,
+                 (drmAddress *) & intelScreen->front.map) != 0) {
+         _mesa_problem(NULL, "drmMap(frontbuffer) failed!");
+         return GL_FALSE;
+      }
+   }
+   else {
+      _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
+   }
+
+   if (0)
+      _mesa_printf("Back 0x%08x ", intelScreen->back.handle);
+   if (drmMap(sPriv->fd,
+              intelScreen->back.handle,
+              intelScreen->back.size,
+              (drmAddress *) & intelScreen->back.map) != 0) {
+      intelUnmapScreenRegions(intelScreen);
+      return GL_FALSE;
+   }
+
+   if (0)
+      _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
+   if (drmMap(sPriv->fd,
+              intelScreen->depth.handle,
+              intelScreen->depth.size,
+              (drmAddress *) & intelScreen->depth.map) != 0) {
+      intelUnmapScreenRegions(intelScreen);
+      return GL_FALSE;
+   }
+
+#if 0
+   _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
+   if (drmMap(sPriv->fd,
+              intelScreen->tex.handle,
+              intelScreen->tex.size,
+              (drmAddress *) & intelScreen->tex.map) != 0) {
+      intelUnmapScreenRegions(intelScreen);
+      return GL_FALSE;
+   }
+#endif
+   if (0)
+      printf("Mappings:  front: %p  back: %p  depth: %p  tex: %p\n",
+             intelScreen->front.map,
+             intelScreen->back.map,
+             intelScreen->depth.map, intelScreen->tex.map);
+   return GL_TRUE;
+}
+
+
+static struct intel_region *
+intel_recreate_static(intelScreenPrivate *intelScreen,
+                     struct intel_region *region,
+                     GLuint mem_type,
+                     GLuint offset,
+                     void *virtual,
+                     GLuint cpp, GLuint pitch, GLuint height)
+{
+  if (region) {
+    intel_region_update_static(intelScreen, region, mem_type, offset,
+                              virtual, cpp, pitch, height);
+  } else {
+    region = intel_region_create_static(intelScreen, mem_type, offset,
+                                       virtual, cpp, pitch, height);
+  }
+  return region;
+}
+    
+
+/* Create intel_region structs to describe the static front,back,depth
+ * buffers created by the xserver. 
+ *
+ * Although FBO's mean we now no longer use these as render targets in
+ * all circumstances, they won't go away until the back and depth
+ * buffers become private, and the front and rotated buffers will
+ * remain even then.
+ *
+ * Note that these don't allocate video memory, just describe
+ * allocations alread made by the X server.
+ */
+static void
+intel_recreate_static_regions(intelScreenPrivate *intelScreen)
+{
+   intelScreen->front_region =
+      intel_recreate_static(intelScreen,
+                           intelScreen->front_region,
+                           DRM_BO_FLAG_MEM_TT,
+                           intelScreen->front.offset,
+                           intelScreen->front.map,
+                           intelScreen->cpp,
+                           intelScreen->front.pitch / intelScreen->cpp,
+                           intelScreen->height);
+
+   intelScreen->rotated_region =
+      intel_recreate_static(intelScreen,
+                           intelScreen->rotated_region,
+                           DRM_BO_FLAG_MEM_TT,
+                           intelScreen->rotated.offset,
+                           intelScreen->rotated.map,
+                           intelScreen->cpp,
+                           intelScreen->rotated.pitch /
+                           intelScreen->cpp, intelScreen->height);
+
+
+   intelScreen->back_region =
+      intel_recreate_static(intelScreen,
+                           intelScreen->back_region,
+                           DRM_BO_FLAG_MEM_TT,
+                           intelScreen->back.offset,
+                           intelScreen->back.map,
+                           intelScreen->cpp,
+                           intelScreen->back.pitch / intelScreen->cpp,
+                           intelScreen->height);
+
+   /* Still assuming front.cpp == depth.cpp
+    */
+   intelScreen->depth_region =
+      intel_recreate_static(intelScreen,
+                           intelScreen->depth_region,
+                           DRM_BO_FLAG_MEM_TT,
+                           intelScreen->depth.offset,
+                           intelScreen->depth.map,
+                           intelScreen->cpp,
+                           intelScreen->depth.pitch / intelScreen->cpp,
+                           intelScreen->height);
+}
+
+/**
+ * Use the information in the sarea to update the screen parameters
+ * related to screen rotation. Needs to be called locked.
+ */
+void
+intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
+{
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
+
+   intelUnmapScreenRegions(intelScreen);
+   intelUpdateScreenFromSAREA(intelScreen, sarea);
+   if (!intelMapScreenRegions(sPriv)) {
+      fprintf(stderr, "ERROR Remapping screen regions!!!\n");
+   }
+   intel_recreate_static_regions(intelScreen);
+}
+
+
+void
+intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
+{
+#define REALLY_UNMAP 1
+   if (intelScreen->front.map) {
+#if REALLY_UNMAP
+      if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0)
+         printf("drmUnmap front failed!\n");
+#endif
+      intelScreen->front.map = NULL;
+   }
+   if (intelScreen->back.map) {
+#if REALLY_UNMAP
+      if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0)
+         printf("drmUnmap back failed!\n");
+#endif
+      intelScreen->back.map = NULL;
+   }
+   if (intelScreen->depth.map) {
+#if REALLY_UNMAP
+      drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
+      intelScreen->depth.map = NULL;
+#endif
+   }
+   if (intelScreen->tex.map) {
+#if REALLY_UNMAP
+      drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
+      intelScreen->tex.map = NULL;
+#endif
+   }
+}
+
+
+static void
+intelPrintDRIInfo(intelScreenPrivate * intelScreen,
+                  __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
+{
+   fprintf(stderr, "*** Front size:   0x%x  offset: 0x%x  pitch: %d\n",
+           intelScreen->front.size, intelScreen->front.offset,
+           intelScreen->front.pitch);
+   fprintf(stderr, "*** Back size:    0x%x  offset: 0x%x  pitch: %d\n",
+           intelScreen->back.size, intelScreen->back.offset,
+           intelScreen->back.pitch);
+   fprintf(stderr, "*** Depth size:   0x%x  offset: 0x%x  pitch: %d\n",
+           intelScreen->depth.size, intelScreen->depth.offset,
+           intelScreen->depth.pitch);
+   fprintf(stderr, "*** Rotated size: 0x%x  offset: 0x%x  pitch: %d\n",
+           intelScreen->rotated.size, intelScreen->rotated.offset,
+           intelScreen->rotated.pitch);
+   fprintf(stderr, "*** Texture size: 0x%x  offset: 0x%x\n",
+           intelScreen->tex.size, intelScreen->tex.offset);
+   fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
+}
+
+
+static void
+intelPrintSAREA(const drmI830Sarea * sarea)
+{
+   fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width,
+           sarea->height);
+   fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
+   fprintf(stderr,
+           "SAREA: front offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
+           sarea->front_offset, sarea->front_size,
+           (unsigned) sarea->front_handle);
+   fprintf(stderr,
+           "SAREA: back  offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
+           sarea->back_offset, sarea->back_size,
+           (unsigned) sarea->back_handle);
+   fprintf(stderr, "SAREA: depth offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
+           sarea->depth_offset, sarea->depth_size,
+           (unsigned) sarea->depth_handle);
+   fprintf(stderr, "SAREA: tex   offset: 0x%08x  size: 0x%x  handle: 0x%x\n",
+           sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
+   fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
+   fprintf(stderr,
+           "SAREA: rotated offset: 0x%08x  size: 0x%x\n",
+           sarea->rotated_offset, sarea->rotated_size);
+   fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
+}
+
+
+/**
+ * A number of the screen parameters are obtained/computed from
+ * information in the SAREA.  This function updates those parameters.
+ */
+void
+intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
+                           drmI830Sarea * sarea)
+{
+   intelScreen->width = sarea->width;
+   intelScreen->height = sarea->height;
+
+   intelScreen->front.offset = sarea->front_offset;
+   intelScreen->front.pitch = sarea->pitch * intelScreen->cpp;
+   intelScreen->front.handle = sarea->front_handle;
+   intelScreen->front.size = sarea->front_size;
+
+   intelScreen->back.offset = sarea->back_offset;
+   intelScreen->back.pitch = sarea->pitch * intelScreen->cpp;
+   intelScreen->back.handle = sarea->back_handle;
+   intelScreen->back.size = sarea->back_size;
+
+   intelScreen->depth.offset = sarea->depth_offset;
+   intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp;
+   intelScreen->depth.handle = sarea->depth_handle;
+   intelScreen->depth.size = sarea->depth_size;
+
+   intelScreen->tex.offset = sarea->tex_offset;
+   intelScreen->logTextureGranularity = sarea->log_tex_granularity;
+   intelScreen->tex.handle = sarea->tex_handle;
+   intelScreen->tex.size = sarea->tex_size;
+
+   intelScreen->rotated.offset = sarea->rotated_offset;
+   intelScreen->rotated.pitch = sarea->rotated_pitch * intelScreen->cpp;
+   intelScreen->rotated.size = sarea->rotated_size;
+   intelScreen->current_rotation = sarea->rotation;
+   matrix23Rotate(&intelScreen->rotMatrix,
+                  sarea->width, sarea->height, sarea->rotation);
+   intelScreen->rotatedWidth = sarea->virtualX;
+   intelScreen->rotatedHeight = sarea->virtualY;
+
+   if (0)
+      intelPrintSAREA(sarea);
+}
+
+
+static GLboolean
+intelInitDriver(__DRIscreenPrivate * sPriv)
+{
+   intelScreenPrivate *intelScreen;
+   I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
+   drmI830Sarea *sarea;
+   unsigned batchPoolSize = 1024*1024;
+
+   PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
+      (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
+                                      getProcAddress("glxEnableExtension"));
+   void *const psc = sPriv->psc->screenConfigs;
+
+   if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
+      fprintf(stderr,
+              "\nERROR!  sizeof(I830DRIRec) does not match passed size from device driver\n");
+      return GL_FALSE;
+   }
+
+   /* Allocate the private area */
+   intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
+   if (!intelScreen) {
+      fprintf(stderr, "\nERROR!  Allocating private area failed\n");
+      return GL_FALSE;
+   }
+   /* parse information in __driConfigOptions */
+   driParseOptionInfo(&intelScreen->optionCache,
+                      __driConfigOptions, __driNConfigOptions);
+
+   intelScreen->driScrnPriv = sPriv;
+   sPriv->private = (void *) intelScreen;
+   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
+   sarea = (drmI830Sarea *)
+      (((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
+
+   intelScreen->maxBatchSize = BATCH_SZ;
+   intelScreen->deviceID = gDRIPriv->deviceID;
+   if (intelScreen->deviceID == PCI_CHIP_I865_G)
+      intelScreen->maxBatchSize = 4096;
+   batchPoolSize /= intelScreen->maxBatchSize;
+
+   intelScreen->mem = gDRIPriv->mem;
+   intelScreen->cpp = gDRIPriv->cpp;
+
+   switch (gDRIPriv->bitsPerPixel) {
+   case 16:
+      intelScreen->fbFormat = DV_PF_565;
+      break;
+   case 32:
+      intelScreen->fbFormat = DV_PF_8888;
+      break;
+   default:
+      exit(1);
+      break;
+   }
+
+   intelUpdateScreenFromSAREA(intelScreen, sarea);
+
+   if (!intelMapScreenRegions(sPriv)) {
+      fprintf(stderr, "\nERROR!  mapping regions\n");
+      _mesa_free(intelScreen);
+      sPriv->private = NULL;
+      return GL_FALSE;
+   }
+
+#if 0
+
+   /*
+    * FIXME: Remove this code and its references.
+    */
+
+   intelScreen->tex.offset = gDRIPriv->textureOffset;
+   intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
+   intelScreen->tex.handle = gDRIPriv->textures;
+   intelScreen->tex.size = gDRIPriv->textureSize;
+
+#else
+   intelScreen->tex.offset = 0;
+   intelScreen->logTextureGranularity = 0;
+   intelScreen->tex.handle = 0;
+   intelScreen->tex.size = 0;
+#endif
+
+   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
+
+   if (0)
+      intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
+
+   intelScreen->drmMinor = sPriv->drmMinor;
+
+   /* Determine if IRQs are active? */
+   {
+      int ret;
+      drmI830GetParam gp;
+
+      gp.param = I830_PARAM_IRQ_ACTIVE;
+      gp.value = &intelScreen->irq_active;
+
+      ret = drmCommandWriteRead(sPriv->fd, DRM_I830_GETPARAM,
+                                &gp, sizeof(gp));
+      if (ret) {
+         fprintf(stderr, "drmI830GetParam: %d\n", ret);
+         return GL_FALSE;
+      }
+   }
+
+   /* Determine if batchbuffers are allowed */
+   {
+      int ret;
+      drmI830GetParam gp;
+
+      gp.param = I830_PARAM_ALLOW_BATCHBUFFER;
+      gp.value = &intelScreen->allow_batchbuffer;
+
+      ret = drmCommandWriteRead(sPriv->fd, DRM_I830_GETPARAM,
+                                &gp, sizeof(gp));
+      if (ret) {
+         fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret);
+         return GL_FALSE;
+      }
+   }
+
+   if (glx_enable_extension != NULL) {
+      (*glx_enable_extension) (psc, "GLX_SGI_swap_control");
+      (*glx_enable_extension) (psc, "GLX_SGI_video_sync");
+      (*glx_enable_extension) (psc, "GLX_MESA_swap_control");
+      (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
+      (*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
+   }
+
+   intelScreen->regionPool = driDRMPoolInit(sPriv->fd);
+
+   if (!intelScreen->regionPool)
+      return GL_FALSE;
+
+   intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
+
+   if (!intelScreen->staticPool)
+      return GL_FALSE;
+
+   intelScreen->texPool = intelScreen->regionPool;
+
+   intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
+                                             DRM_BO_FLAG_EXE |
+                                             DRM_BO_FLAG_MEM_TT |
+                                             DRM_BO_FLAG_MEM_LOCAL,
+                                             intelScreen->maxBatchSize, 
+                                            batchPoolSize, 5);
+   if (!intelScreen->batchPool) {
+      fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
+      return GL_FALSE;
+   }
+
+   intel_recreate_static_regions(intelScreen);
+
+   return GL_TRUE;
+}
+
+
+static void
+intelDestroyScreen(__DRIscreenPrivate * sPriv)
+{
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
+
+   intelUnmapScreenRegions(intelScreen);
+
+   driPoolTakeDown(intelScreen->regionPool);
+   driPoolTakeDown(intelScreen->staticPool);
+   driPoolTakeDown(intelScreen->batchPool);
+   FREE(intelScreen);
+   sPriv->private = NULL;
+}
+
+
+/**
+ * This is called when we need to set up GL rendering to a new X window.
+ */
+static GLboolean
+intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
+                  __DRIdrawablePrivate * driDrawPriv,
+                  const __GLcontextModes * mesaVis, GLboolean isPixmap)
+{
+   intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
+
+   if (isPixmap) {
+      return GL_FALSE;          /* not implemented */
+   }
+   else {
+      GLboolean swStencil = (mesaVis->stencilBits > 0 &&
+                             mesaVis->depthBits != 24);
+      GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
+
+      struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
+
+      /* setup the hardware-based renderbuffers */
+      {
+         struct intel_renderbuffer *frontRb
+            = intel_create_renderbuffer(rgbFormat,
+                                        screen->width, screen->height,
+                                        screen->front.offset,
+                                        screen->front.pitch,
+                                        screen->cpp,
+                                        screen->front.map);
+         intel_set_span_functions(&frontRb->Base);
+         _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
+      }
+
+      if (mesaVis->doubleBufferMode) {
+         struct intel_renderbuffer *backRb
+            = intel_create_renderbuffer(rgbFormat,
+                                        screen->width, screen->height,
+                                        screen->back.offset,
+                                        screen->back.pitch,
+                                        screen->cpp,
+                                        screen->back.map);
+         intel_set_span_functions(&backRb->Base);
+         _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
+      }
+
+      if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
+         /* combined depth/stencil buffer */
+         struct intel_renderbuffer *depthStencilRb
+            = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT,
+                                        screen->width, screen->height,
+                                        screen->depth.offset,
+                                        screen->depth.pitch,
+                                        screen->cpp,    /* 4! */
+                                        screen->depth.map);
+         intel_set_span_functions(&depthStencilRb->Base);
+         /* note: bind RB to two attachment points */
+         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base);
+         _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base);
+      }
+      else if (mesaVis->depthBits == 16) {
+         /* just 16-bit depth buffer, no hw stencil */
+         struct intel_renderbuffer *depthRb
+            = intel_create_renderbuffer(GL_DEPTH_COMPONENT16,
+                                        screen->width, screen->height,
+                                        screen->depth.offset,
+                                        screen->depth.pitch,
+                                        screen->cpp,    /* 2! */
+                                        screen->depth.map);
+         intel_set_span_functions(&depthRb->Base);
+         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+      }
+
+      /* now add any/all software-based renderbuffers we may need */
+      _mesa_add_soft_renderbuffers(fb, GL_FALSE,        /* never sw color */
+                                   GL_FALSE,    /* never sw depth */
+                                   swStencil, mesaVis->accumRedBits > 0, GL_FALSE,      /* never sw alpha */
+                                   GL_FALSE /* never sw aux */ );
+      driDrawPriv->driverPrivate = (void *) fb;
+
+      return (driDrawPriv->driverPrivate != NULL);
+   }
+}
+
+static void
+intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
+{
+   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
+{
+   struct intel_context *intel;
+
+   if ((dPriv == NULL) || (dPriv->driContextPriv == NULL)
+       || (dPriv->driContextPriv->driverPrivate == NULL)
+       || (sInfo == NULL)) {
+      return -1;
+   }
+
+   intel = dPriv->driContextPriv->driverPrivate;
+   sInfo->swap_count = intel->swap_count;
+   sInfo->swap_ust = intel->swap_ust;
+   sInfo->swap_missed_count = intel->swap_missed_count;
+
+   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
+      ? driCalculateSwapUsage(dPriv, 0, intel->swap_missed_ust)
+      : 0.0;
+
+   return 0;
+}
+
+
+/* There are probably better ways to do this, such as an
+ * init-designated function to register chipids and createcontext
+ * functions.
+ */
+extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
+                                   __DRIcontextPrivate * driContextPriv,
+                                   void *sharedContextPrivate);
+
+extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
+                                   __DRIcontextPrivate * driContextPriv,
+                                   void *sharedContextPrivate);
+
+
+
+
+static GLboolean
+intelCreateContext(const __GLcontextModes * mesaVis,
+                   __DRIcontextPrivate * driContextPriv,
+                   void *sharedContextPrivate)
+{
+   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
+
+   switch (intelScreen->deviceID) {
+      /* Don't deal with i830 until texture work complete:
+       */
+   case PCI_CHIP_845_G:
+   case PCI_CHIP_I830_M:
+   case PCI_CHIP_I855_GM:
+   case PCI_CHIP_I865_G:
+      return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
+
+   case PCI_CHIP_I915_G:
+   case PCI_CHIP_I915_GM:
+   case PCI_CHIP_I945_G:
+   case PCI_CHIP_I945_GM:
+      return i915CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
+
+   default:
+      fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
+      return GL_FALSE;
+   }
+}
+
+
+static const struct __DriverAPIRec intelAPI = {
+   .InitDriver = intelInitDriver,
+   .DestroyScreen = intelDestroyScreen,
+   .CreateContext = intelCreateContext,
+   .DestroyContext = intelDestroyContext,
+   .CreateBuffer = intelCreateBuffer,
+   .DestroyBuffer = intelDestroyBuffer,
+   .SwapBuffers = intelSwapBuffers,
+   .MakeCurrent = intelMakeCurrent,
+   .UnbindContext = intelUnbindContext,
+   .GetSwapInfo = intelGetSwapInfo,
+   .GetMSC = driGetMSC32,
+   .WaitForMSC = driWaitForMSC32,
+   .WaitForSBC = NULL,
+   .SwapBuffersMSC = NULL,
+   .CopySubBuffer = intelCopySubBuffer
+};
+
+
+static __GLcontextModes *
+intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
+                 unsigned stencil_bits, GLboolean have_back_buffer)
+{
+   __GLcontextModes *modes;
+   __GLcontextModes *m;
+   unsigned num_modes;
+   unsigned depth_buffer_factor;
+   unsigned back_buffer_factor;
+   GLenum fb_format;
+   GLenum fb_type;
+
+   /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+    * support pageflipping at all.
+    */
+   static const GLenum back_buffer_modes[] = {
+      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+   };
+
+   u_int8_t depth_bits_array[3];
+   u_int8_t stencil_bits_array[3];
+
+
+   depth_bits_array[0] = 0;
+   depth_bits_array[1] = depth_bits;
+   depth_bits_array[2] = depth_bits;
+
+   /* Just like with the accumulation buffer, always provide some modes
+    * with a stencil buffer.  It will be a sw fallback, but some apps won't
+    * care about that.
+    */
+   stencil_bits_array[0] = 0;
+   stencil_bits_array[1] = 0;
+   stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
+   back_buffer_factor = (have_back_buffer) ? 3 : 1;
+
+   num_modes = depth_buffer_factor * back_buffer_factor * 4;
+
+   if (pixel_bits == 16) {
+      fb_format = GL_RGB;
+      fb_type = GL_UNSIGNED_SHORT_5_6_5;
+   }
+   else {
+      fb_format = GL_BGRA;
+      fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+   }
+
+   modes =
+      (*dri_interface->createContextModes) (num_modes,
+                                            sizeof(__GLcontextModes));
+   m = modes;
+   if (!driFillInModes(&m, fb_format, fb_type,
+                       depth_bits_array, stencil_bits_array,
+                       depth_buffer_factor, back_buffer_modes,
+                       back_buffer_factor, GLX_TRUE_COLOR)) {
+      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+              __LINE__);
+      return NULL;
+   }
+   if (!driFillInModes(&m, fb_format, fb_type,
+                       depth_bits_array, stencil_bits_array,
+                       depth_buffer_factor, back_buffer_modes,
+                       back_buffer_factor, GLX_DIRECT_COLOR)) {
+      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
+              __LINE__);
+      return NULL;
+   }
+
+   /* Mark the visual as slow if there are "fake" stencil bits.
+    */
+   for (m = modes; m != NULL; m = m->next) {
+      if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
+         m->visualRating = GLX_SLOW_CONFIG;
+      }
+   }
+
+   return modes;
+}
+
+
+/**
+ * This is the bootstrap function for the driver.  libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c __GLcontextModes that the driver can support for windows or
+ * pbuffers.
+ * 
+ * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on 
+ *         failure.
+ */
+PUBLIC void *
+__driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
+                              __DRIscreen * psc,
+                              const __GLcontextModes * modes,
+                              const __DRIversion * ddx_version,
+                              const __DRIversion * dri_version,
+                              const __DRIversion * drm_version,
+                              const __DRIframebuffer * frame_buffer,
+                              drmAddress pSAREA, int fd,
+                              int internal_api_version,
+                              const __DRIinterfaceMethods * interface,
+                              __GLcontextModes ** driver_modes)
+{
+   __DRIscreenPrivate *psp;
+   static const __DRIversion ddx_expected = { 1, 5, 0 };
+   static const __DRIversion dri_expected = { 4, 0, 0 };
+   static const __DRIversion drm_expected = { 1, 7, 0 };
+
+   dri_interface = interface;
+
+   if (!driCheckDriDdxDrmVersions2("i915",
+                                   dri_version, &dri_expected,
+                                   ddx_version, &ddx_expected,
+                                   drm_version, &drm_expected)) {
+      return NULL;
+   }
+
+   psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+                                  ddx_version, dri_version, drm_version,
+                                  frame_buffer, pSAREA, fd,
+                                  internal_api_version, &intelAPI);
+   if (psp != NULL) {
+      I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
+      *driver_modes = intelFillInModes(dri_priv->cpp * 8,
+                                       (dri_priv->cpp == 2) ? 16 : 24,
+                                       (dri_priv->cpp == 2) ? 0 : 8, 1);
+
+      /* Calling driInitExtensions here, with a NULL context pointer, does not actually
+       * enable the extensions.  It just makes sure that all the dispatch offsets for all
+       * the extensions that *might* be enables are known.  This is needed because the
+       * dispatch offsets need to be known when _mesa_context_create is called, but we can't
+       * enable the extensions until we have a context pointer.
+       *
+       * Hello chicken.  Hello egg.  How are you two today?
+       */
+      driInitExtensions(NULL, card_extensions, GL_FALSE);
+   }
+
+   return (void *) psp;
+}
+
+struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
+{
+  /*
+   * This should probably change to have the screen allocate a dummy
+   * context at screen creation. For now just use the current context.
+   */
+
+  GET_CURRENT_CONTEXT(ctx);
+  if (ctx == NULL) {
+     _mesa_problem(NULL, "No current context in intelScreenContext\n");
+     return NULL;
+  }
+  return intel_context(ctx);
+}
+
diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h
new file mode 100644 (file)
index 0000000..1769877
--- /dev/null
@@ -0,0 +1,132 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef _INTEL_INIT_H_
+#define _INTEL_INIT_H_
+
+#include <sys/time.h>
+#include "dri_util.h"
+#include "intel_rotate.h"
+#include "i830_common.h"
+#include "xmlconfig.h"
+#include "dri_bufpool.h"
+
+/* XXX: change name or eliminate to avoid conflict with "struct
+ * intel_region"!!!
+ */
+typedef struct
+{
+   drm_handle_t handle;
+   drmSize size;                /* region size in bytes */
+   char *map;                   /* memory map */
+   int offset;                  /* from start of video mem, in bytes */
+   int pitch;                   /* row stride, in bytes */
+} intelRegion;
+
+typedef struct
+{
+   intelRegion front;
+   intelRegion back;
+   intelRegion rotated;
+   intelRegion depth;
+   intelRegion tex;
+
+   struct intel_region *front_region;
+   struct intel_region *back_region;
+   struct intel_region *depth_region;
+   struct intel_region *rotated_region;
+
+   int deviceID;
+   int width;
+   int height;
+   int mem;                     /* unused */
+
+   int cpp;                     /* for front and back buffers */
+/*    int bitsPerPixel;   */
+   int fbFormat;                /* XXX FBO: this is obsolete - remove after i830 updates */
+
+   int logTextureGranularity;
+
+   __DRIscreenPrivate *driScrnPriv;
+   unsigned int sarea_priv_offset;
+
+   int drmMinor;
+
+   int irq_active;
+   int allow_batchbuffer;
+
+   struct matrix23 rotMatrix;
+
+   int current_rotation;        /* 0, 90, 180 or 270 */
+   int rotatedWidth, rotatedHeight;
+
+   /**
+   * Configuration cache with default values for all contexts
+   */
+   driOptionCache optionCache;
+   struct _DriBufferPool *batchPool;
+   struct _DriBufferPool *texPool;
+   struct _DriBufferPool *regionPool;
+   struct _DriBufferPool *staticPool;
+   unsigned int maxBatchSize;
+} intelScreenPrivate;
+
+
+
+extern GLboolean intelMapScreenRegions(__DRIscreenPrivate * sPriv);
+
+extern void intelUnmapScreenRegions(intelScreenPrivate * intelScreen);
+
+extern void
+intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
+                           drmI830Sarea * sarea);
+
+extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv);
+
+extern GLboolean intelUnbindContext(__DRIcontextPrivate * driContextPriv);
+
+extern GLboolean
+intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
+                 __DRIdrawablePrivate * driDrawPriv,
+                 __DRIdrawablePrivate * driReadPriv);
+
+extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
+
+extern void
+intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h);
+
+extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags,
+                                               unsigned long bufSize,
+                                               unsigned numBufs,
+                                               unsigned checkDelayed);
+
+extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen);
+
+extern void
+intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea);
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_span.c b/src/mesa/drivers/dri/i915tex/intel_span.c
new file mode 100644 (file)
index 0000000..ab0874e
--- /dev/null
@@ -0,0 +1,409 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "colormac.h"
+
+#include "intel_fbo.h"
+#include "intel_screen.h"
+#include "intel_span.h"
+#include "intel_regions.h"
+#include "intel_ioctl.h"
+#include "intel_tex.h"
+
+#include "swrast/swrast.h"
+
+/*
+  break intelWriteRGBASpan_ARGB8888
+*/
+
+#undef DBG
+#define DBG 0
+
+#define LOCAL_VARS                                                     \
+   struct intel_context *intel = intel_context(ctx);                   \
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);            \
+   const GLint yScale = irb->RenderToTexture ? 1 : -1;                 \
+   const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;        \
+   GLubyte *buf = (GLubyte *) irb->pfMap                               \
+      + (intel->drawY * irb->pfPitch + intel->drawX) * irb->region->cpp;\
+   GLuint p;                                                           \
+   assert(irb->pfMap);\
+   (void) p;
+
+/* XXX FBO: this is identical to the macro in spantmp2.h except we get
+ * the cliprect info from the context, not the driDrawable.
+ * Move this into spantmp2.h someday.
+ */
+#define HW_CLIPLOOP()                                                  \
+   do {                                                                        \
+      int _nc = intel->numClipRects;                                   \
+      while ( _nc-- ) {                                                        \
+        int minx = intel->pClipRects[_nc].x1 - intel->drawX;           \
+        int miny = intel->pClipRects[_nc].y1 - intel->drawY;           \
+        int maxx = intel->pClipRects[_nc].x2 - intel->drawX;           \
+        int maxy = intel->pClipRects[_nc].y2 - intel->drawY;
+
+
+
+
+#define Y_FLIP(_y) ((_y) * yScale + yBias)
+
+#define HW_LOCK()
+
+#define HW_UNLOCK()
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_RGB
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
+
+#define TAG(x)    intel##x##_RGB565
+#define TAG2(x,y) intel##x##_RGB565##y
+#define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 2)
+#include "spantmp2.h"
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+
+#define TAG(x)    intel##x##_ARGB8888
+#define TAG2(x,y) intel##x##_ARGB8888##y
+#define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 4)
+#include "spantmp2.h"
+
+
+#define LOCAL_DEPTH_VARS                                               \
+   struct intel_context *intel = intel_context(ctx);                   \
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);            \
+   const GLuint pitch = irb->pfPitch/***XXX region->pitch*/; /* in pixels */ \
+   const GLint yScale = irb->RenderToTexture ? 1 : -1;                 \
+   const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;        \
+   char *buf = (char *) irb->pfMap/*XXX use region->map*/ +             \
+      (intel->drawY * pitch + intel->drawX) * irb->region->cpp;
+
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
+
+/**
+ ** 16-bit depthbuffer functions.
+ **/
+#define WRITE_DEPTH( _x, _y, d ) \
+   ((GLushort *)buf)[(_x) + (_y) * pitch] = d;
+
+#define READ_DEPTH( d, _x, _y )        \
+   d = ((GLushort *)buf)[(_x) + (_y) * pitch];
+
+
+#define TAG(x) intel##x##_z16
+#include "depthtmp.h"
+
+
+/**
+ ** 24/8-bit interleaved depth/stencil functions
+ ** Note: we're actually reading back combined depth+stencil values.
+ ** The wrappers in main/depthstencil.c are used to extract the depth
+ ** and stencil values.
+ **/
+/* Change ZZZS -> SZZZ */
+#define WRITE_DEPTH( _x, _y, d ) {                             \
+   GLuint tmp = ((d) >> 8) | ((d) << 24);                      \
+   ((GLuint *)buf)[(_x) + (_y) * pitch] = tmp;                 \
+}
+
+/* Change SZZZ -> ZZZS */
+#define READ_DEPTH( d, _x, _y ) {                              \
+   GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch];          \
+   d = (tmp << 8) | (tmp >> 24);                               \
+}
+
+#define TAG(x) intel##x##_z24_s8
+#include "depthtmp.h"
+
+
+/**
+ ** 8-bit stencil function (XXX FBO: This is obsolete)
+ **/
+#define WRITE_STENCIL( _x, _y, d ) {                           \
+   GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch];          \
+   tmp &= 0xffffff;                                            \
+   tmp |= ((d) << 24);                                         \
+   ((GLuint *) buf)[(_x) + (_y) * pitch] = tmp;                        \
+}
+
+#define READ_STENCIL( d, _x, _y )                              \
+   d = ((GLuint *)buf)[(_x) + (_y) * pitch] >> 24;
+
+#define TAG(x) intel##x##_z24_s8
+#include "stenciltmp.h"
+
+
+
+/**
+ * Map or unmap all the renderbuffers which we may need during
+ * software rendering.
+ * XXX in the future, we could probably convey extra information to
+ * reduce the number of mappings needed.  I.e. if doing a glReadPixels
+ * from the depth buffer, we really only need one mapping.
+ *
+ * XXX Rewrite this function someday.
+ * We can probably just loop over all the renderbuffer attachments,
+ * map/unmap all of them, and not worry about the _ColorDrawBuffers
+ * _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
+ */
+static void
+intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
+{
+   GLcontext *ctx = &intel->ctx;
+   GLuint i, j;
+   struct intel_renderbuffer *irb;
+
+   /* color draw buffers */
+   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+      for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) {
+         struct gl_renderbuffer *rb =
+            ctx->DrawBuffer->_ColorDrawBuffers[i][j];
+         irb = intel_renderbuffer(rb);
+         if (irb) {
+            /* this is a user-created intel_renderbuffer */
+            if (irb->region) {
+               if (map)
+                  intel_region_map(intel->intelScreen, irb->region);
+               else
+                  intel_region_unmap(intel->intelScreen, irb->region);
+            }
+            irb->pfMap = irb->region->map;
+            irb->pfPitch = irb->region->pitch;
+         }
+      }
+   }
+
+   /* check for render to textures */
+   for (i = 0; i < BUFFER_COUNT; i++) {
+      struct gl_renderbuffer_attachment *att =
+         ctx->DrawBuffer->Attachment + i;
+      struct gl_texture_object *tex = att->Texture;
+      if (tex) {
+         /* render to texture */
+         ASSERT(att->Renderbuffer);
+         if (map) {
+            struct gl_texture_image *texImg;
+            texImg = tex->Image[att->CubeMapFace][att->TextureLevel];
+            intel_tex_map_images(intel, intel_texture_object(tex));
+         }
+         else {
+            intel_tex_unmap_images(intel, intel_texture_object(tex));
+         }
+      }
+   }
+
+   /* color read buffers */
+   irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+   if (irb && irb->region) {
+      if (map)
+         intel_region_map(intel->intelScreen, irb->region);
+      else
+         intel_region_unmap(intel->intelScreen, irb->region);
+      irb->pfMap = irb->region->map;
+      irb->pfPitch = irb->region->pitch;
+   }
+
+   /* Account for front/back color page flipping.
+    * The span routines use the pfMap and pfPitch fields which will
+    * swap the front/back region map/pitch if we're page flipped.
+    * Do this after mapping, above, so the map field is valid.
+    */
+#if 0
+   if (map && ctx->DrawBuffer->Name == 0) {
+      struct intel_renderbuffer *irbFront
+         = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_FRONT_LEFT);
+      struct intel_renderbuffer *irbBack
+         = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_BACK_LEFT);
+      if (irbBack) {
+         /* double buffered */
+         if (intel->sarea->pf_current_page == 0) {
+            irbFront->pfMap = irbFront->region->map;
+            irbFront->pfPitch = irbFront->region->pitch;
+            irbBack->pfMap = irbBack->region->map;
+            irbBack->pfPitch = irbBack->region->pitch;
+         }
+         else {
+            irbFront->pfMap = irbBack->region->map;
+            irbFront->pfPitch = irbBack->region->pitch;
+            irbBack->pfMap = irbFront->region->map;
+            irbBack->pfPitch = irbFront->region->pitch;
+         }
+      }
+   }
+#endif
+
+   /* depth buffer (Note wrapper!) */
+   if (ctx->DrawBuffer->_DepthBuffer) {
+      irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped);
+      if (irb && irb->region && irb->Base.Name != 0) {
+         if (map) {
+            intel_region_map(intel->intelScreen, irb->region);
+            irb->pfMap = irb->region->map;
+            irb->pfPitch = irb->region->pitch;
+         }
+         else {
+            intel_region_unmap(intel->intelScreen, irb->region);
+            irb->pfMap = NULL;
+            irb->pfPitch = 0;
+         }
+      }
+   }
+
+   /* stencil buffer (Note wrapper!) */
+   if (ctx->DrawBuffer->_StencilBuffer) {
+      irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped);
+      if (irb && irb->region && irb->Base.Name != 0) {
+         if (map) {
+            intel_region_map(intel->intelScreen, irb->region);
+            irb->pfMap = irb->region->map;
+            irb->pfPitch = irb->region->pitch;
+         }
+         else {
+            intel_region_unmap(intel->intelScreen, irb->region);
+            irb->pfMap = NULL;
+            irb->pfPitch = 0;
+         }
+      }
+   }
+}
+
+
+
+/**
+ * Prepare for softare rendering.  Map current read/draw framebuffers'
+ * renderbuffes and all currently bound texture objects.
+ *
+ * Old note: Moved locking out to get reasonable span performance.
+ */
+void
+intelSpanRenderStart(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+   GLuint i;
+
+   intelFinish(&intel->ctx);
+   LOCK_HARDWARE(intel);
+
+#if 0
+   /* Just map the framebuffer and all textures.  Bufmgr code will
+    * take care of waiting on the necessary fences:
+    */
+   intel_region_map(intel->intelScreen, intel->front_region);
+   intel_region_map(intel->intelScreen, intel->back_region);
+   intel_region_map(intel->intelScreen, intel->intelScreen->depth_region);
+#endif
+
+   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+      if (ctx->Texture.Unit[i]._ReallyEnabled) {
+         struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
+         intel_tex_map_images(intel, intel_texture_object(texObj));
+      }
+   }
+
+   intel_map_unmap_buffers(intel, GL_TRUE);
+}
+
+/**
+ * Called when done softare rendering.  Unmap the buffers we mapped in
+ * the above function.
+ */
+void
+intelSpanRenderFinish(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+   GLuint i;
+
+   _swrast_flush(ctx);
+
+   /* Now unmap the framebuffer:
+    */
+#if 0
+   intel_region_unmap(intel, intel->front_region);
+   intel_region_unmap(intel, intel->back_region);
+   intel_region_unmap(intel, intel->intelScreen->depth_region);
+#endif
+
+   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+      if (ctx->Texture.Unit[i]._ReallyEnabled) {
+         struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
+         intel_tex_unmap_images(intel, intel_texture_object(texObj));
+      }
+   }
+
+   intel_map_unmap_buffers(intel, GL_FALSE);
+
+   UNLOCK_HARDWARE(intel);
+}
+
+
+void
+intelInitSpanFuncs(GLcontext * ctx)
+{
+   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+   swdd->SpanRenderStart = intelSpanRenderStart;
+   swdd->SpanRenderFinish = intelSpanRenderFinish;
+}
+
+
+/**
+ * Plug in appropriate span read/write functions for the given renderbuffer.
+ * These are used for the software fallbacks.
+ */
+void
+intel_set_span_functions(struct gl_renderbuffer *rb)
+{
+   if (rb->_ActualFormat == GL_RGB5) {
+      /* 565 RGB */
+      intelInitPointers_RGB565(rb);
+   }
+   else if (rb->_ActualFormat == GL_RGBA8) {
+      /* 8888 RGBA */
+      intelInitPointers_ARGB8888(rb);
+   }
+   else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) {
+      intelInitDepthPointers_z16(rb);
+   }
+   else if (rb->_ActualFormat == GL_DEPTH_COMPONENT24 ||        /* XXX FBO remove */
+            rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
+      intelInitDepthPointers_z24_s8(rb);
+   }
+   else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {       /* XXX FBO remove */
+      intelInitStencilPointers_z24_s8(rb);
+   }
+   else {
+      _mesa_problem(NULL,
+                    "Unexpected _ActualFormat in intelSetSpanFunctions");
+   }
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_span.h b/src/mesa/drivers/dri/i915tex/intel_span.h
new file mode 100644 (file)
index 0000000..5201f6d
--- /dev/null
@@ -0,0 +1,38 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef _INTEL_SPAN_H
+#define _INTEL_SPAN_H
+
+extern void intelInitSpanFuncs(GLcontext * ctx);
+
+extern void intelSpanRenderFinish(GLcontext * ctx);
+extern void intelSpanRenderStart(GLcontext * ctx);
+
+extern void intel_set_span_functions(struct gl_renderbuffer *rb);
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_state.c b/src/mesa/drivers/dri/i915tex/intel_state.c
new file mode 100644 (file)
index 0000000..f85d8ef
--- /dev/null
@@ -0,0 +1,363 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "enums.h"
+#include "colormac.h"
+#include "dd.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_fbo.h"
+#include "intel_regions.h"
+#include "swrast/swrast.h"
+
+int
+intel_translate_compare_func(GLenum func)
+{
+   switch (func) {
+   case GL_NEVER:
+      return COMPAREFUNC_NEVER;
+   case GL_LESS:
+      return COMPAREFUNC_LESS;
+   case GL_LEQUAL:
+      return COMPAREFUNC_LEQUAL;
+   case GL_GREATER:
+      return COMPAREFUNC_GREATER;
+   case GL_GEQUAL:
+      return COMPAREFUNC_GEQUAL;
+   case GL_NOTEQUAL:
+      return COMPAREFUNC_NOTEQUAL;
+   case GL_EQUAL:
+      return COMPAREFUNC_EQUAL;
+   case GL_ALWAYS:
+      return COMPAREFUNC_ALWAYS;
+   }
+
+   fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func);
+   return COMPAREFUNC_ALWAYS;
+}
+
+int
+intel_translate_stencil_op(GLenum op)
+{
+   switch (op) {
+   case GL_KEEP:
+      return STENCILOP_KEEP;
+   case GL_ZERO:
+      return STENCILOP_ZERO;
+   case GL_REPLACE:
+      return STENCILOP_REPLACE;
+   case GL_INCR:
+      return STENCILOP_INCRSAT;
+   case GL_DECR:
+      return STENCILOP_DECRSAT;
+   case GL_INCR_WRAP:
+      return STENCILOP_INCR;
+   case GL_DECR_WRAP:
+      return STENCILOP_DECR;
+   case GL_INVERT:
+      return STENCILOP_INVERT;
+   default:
+      return STENCILOP_ZERO;
+   }
+}
+
+int
+intel_translate_blend_factor(GLenum factor)
+{
+   switch (factor) {
+   case GL_ZERO:
+      return BLENDFACT_ZERO;
+   case GL_SRC_ALPHA:
+      return BLENDFACT_SRC_ALPHA;
+   case GL_ONE:
+      return BLENDFACT_ONE;
+   case GL_SRC_COLOR:
+      return BLENDFACT_SRC_COLR;
+   case GL_ONE_MINUS_SRC_COLOR:
+      return BLENDFACT_INV_SRC_COLR;
+   case GL_DST_COLOR:
+      return BLENDFACT_DST_COLR;
+   case GL_ONE_MINUS_DST_COLOR:
+      return BLENDFACT_INV_DST_COLR;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      return BLENDFACT_INV_SRC_ALPHA;
+   case GL_DST_ALPHA:
+      return BLENDFACT_DST_ALPHA;
+   case GL_ONE_MINUS_DST_ALPHA:
+      return BLENDFACT_INV_DST_ALPHA;
+   case GL_SRC_ALPHA_SATURATE:
+      return BLENDFACT_SRC_ALPHA_SATURATE;
+   case GL_CONSTANT_COLOR:
+      return BLENDFACT_CONST_COLOR;
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+      return BLENDFACT_INV_CONST_COLOR;
+   case GL_CONSTANT_ALPHA:
+      return BLENDFACT_CONST_ALPHA;
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+      return BLENDFACT_INV_CONST_ALPHA;
+   }
+
+   fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, factor);
+   return BLENDFACT_ZERO;
+}
+
+int
+intel_translate_logic_op(GLenum opcode)
+{
+   switch (opcode) {
+   case GL_CLEAR:
+      return LOGICOP_CLEAR;
+   case GL_AND:
+      return LOGICOP_AND;
+   case GL_AND_REVERSE:
+      return LOGICOP_AND_RVRSE;
+   case GL_COPY:
+      return LOGICOP_COPY;
+   case GL_COPY_INVERTED:
+      return LOGICOP_COPY_INV;
+   case GL_AND_INVERTED:
+      return LOGICOP_AND_INV;
+   case GL_NOOP:
+      return LOGICOP_NOOP;
+   case GL_XOR:
+      return LOGICOP_XOR;
+   case GL_OR:
+      return LOGICOP_OR;
+   case GL_OR_INVERTED:
+      return LOGICOP_OR_INV;
+   case GL_NOR:
+      return LOGICOP_NOR;
+   case GL_EQUIV:
+      return LOGICOP_EQUIV;
+   case GL_INVERT:
+      return LOGICOP_INV;
+   case GL_OR_REVERSE:
+      return LOGICOP_OR_RVRSE;
+   case GL_NAND:
+      return LOGICOP_NAND;
+   case GL_SET:
+      return LOGICOP_SET;
+   default:
+      return LOGICOP_SET;
+   }
+}
+
+
+static void
+intelClearColor(GLcontext * ctx, const GLfloat color[4])
+{
+   struct intel_context *intel = intel_context(ctx);
+   GLubyte clear[4];
+
+   CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
+   CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
+   CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
+   CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
+
+   /* compute both 32 and 16-bit clear values */
+   intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1],
+                                               clear[2], clear[3]);
+   intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]);
+}
+
+
+/**
+ * Update the viewport transformation matrix.  Depends on:
+ *  - viewport pos/size
+ *  - depthrange
+ *  - window pos/size or FBO size
+ */
+static void
+intelCalcViewport(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+   const GLfloat *v = ctx->Viewport._WindowMap.m;
+   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+   GLfloat *m = intel->ViewportMatrix.m;
+   GLfloat yScale, yBias;
+
+   if (ctx->DrawBuffer->Name) {
+      /* User created FBO */
+      struct intel_renderbuffer *irb
+         = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
+      if (irb && !irb->RenderToTexture) {
+         /* y=0=top */
+         yScale = -1.0;
+         yBias = irb->Base.Height;
+      }
+      else {
+         /* y=0=bottom */
+         yScale = 1.0;
+         yBias = 0.0;
+      }
+   }
+   else {
+      /* window buffer, y=0=top */
+      yScale = -1.0;
+      yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
+   }
+
+   m[MAT_SX] = v[MAT_SX];
+   m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
+
+   m[MAT_SY] = v[MAT_SY] * yScale;
+   m[MAT_TY] = v[MAT_TY] * yScale + yBias + SUBPIXEL_Y;
+
+   m[MAT_SZ] = v[MAT_SZ] * depthScale;
+   m[MAT_TZ] = v[MAT_TZ] * depthScale;
+}
+
+static void
+intelViewport(GLcontext * ctx,
+              GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   intelCalcViewport(ctx);
+}
+
+static void
+intelDepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
+{
+   intelCalcViewport(ctx);
+}
+
+/* Fallback to swrast for select and feedback.
+ */
+static void
+intelRenderMode(GLcontext * ctx, GLenum mode)
+{
+   struct intel_context *intel = intel_context(ctx);
+   FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER));
+}
+
+
+void
+intelInitStateFuncs(struct dd_function_table *functions)
+{
+   functions->RenderMode = intelRenderMode;
+   functions->Viewport = intelViewport;
+   functions->DepthRange = intelDepthRange;
+   functions->ClearColor = intelClearColor;
+}
+
+
+
+
+void
+intelInitState(GLcontext * ctx)
+{
+   /* Mesa should do this for us:
+    */
+   ctx->Driver.AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef);
+
+   ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor);
+
+   ctx->Driver.BlendEquationSeparate(ctx,
+                                     ctx->Color.BlendEquationRGB,
+                                     ctx->Color.BlendEquationA);
+
+   ctx->Driver.BlendFuncSeparate(ctx,
+                                 ctx->Color.BlendSrcRGB,
+                                 ctx->Color.BlendDstRGB,
+                                 ctx->Color.BlendSrcA, ctx->Color.BlendDstA);
+
+   ctx->Driver.ColorMask(ctx,
+                         ctx->Color.ColorMask[RCOMP],
+                         ctx->Color.ColorMask[GCOMP],
+                         ctx->Color.ColorMask[BCOMP],
+                         ctx->Color.ColorMask[ACOMP]);
+
+   ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode);
+   ctx->Driver.DepthFunc(ctx, ctx->Depth.Func);
+   ctx->Driver.DepthMask(ctx, ctx->Depth.Mask);
+
+   ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled);
+   ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled);
+   ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled);
+   ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled);
+   ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag);
+   ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
+   ctx->Driver.Enable(ctx, GL_DITHER, ctx->Color.DitherFlag);
+   ctx->Driver.Enable(ctx, GL_FOG, ctx->Fog.Enabled);
+   ctx->Driver.Enable(ctx, GL_LIGHTING, ctx->Light.Enabled);
+   ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag);
+   ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag);
+   ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled);
+   ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+   ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE);
+   ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE);
+   ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE);
+   ctx->Driver.Enable(ctx, GL_TEXTURE_3D, GL_FALSE);
+   ctx->Driver.Enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE);
+
+   ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color);
+   ctx->Driver.Fogfv(ctx, GL_FOG_MODE, 0);
+   ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density);
+   ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start);
+   ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End);
+
+   ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
+
+   {
+      GLfloat f = (GLfloat) ctx->Light.Model.ColorControl;
+      ctx->Driver.LightModelfv(ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f);
+   }
+
+   ctx->Driver.LineWidth(ctx, ctx->Line.Width);
+   ctx->Driver.LogicOpcode(ctx, ctx->Color.LogicOp);
+   ctx->Driver.PointSize(ctx, ctx->Point.Size);
+   ctx->Driver.PolygonStipple(ctx, (const GLubyte *) ctx->PolygonStipple);
+   ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                       ctx->Scissor.Width, ctx->Scissor.Height);
+   ctx->Driver.ShadeModel(ctx, ctx->Light.ShadeModel);
+   ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT,
+                                   ctx->Stencil.Function[0],
+                                   ctx->Stencil.Ref[0],
+                                   ctx->Stencil.ValueMask[0]);
+   ctx->Driver.StencilFuncSeparate(ctx, GL_BACK,
+                                   ctx->Stencil.Function[1],
+                                   ctx->Stencil.Ref[1],
+                                   ctx->Stencil.ValueMask[1]);
+   ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT, ctx->Stencil.WriteMask[0]);
+   ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, ctx->Stencil.WriteMask[1]);
+   ctx->Driver.StencilOpSeparate(ctx, GL_FRONT,
+                                 ctx->Stencil.FailFunc[0],
+                                 ctx->Stencil.ZFailFunc[0],
+                                 ctx->Stencil.ZPassFunc[0]);
+   ctx->Driver.StencilOpSeparate(ctx, GL_BACK,
+                                 ctx->Stencil.FailFunc[1],
+                                 ctx->Stencil.ZFailFunc[1],
+                                 ctx->Stencil.ZPassFunc[1]);
+
+
+   /* XXX this isn't really needed */
+   ctx->Driver.DrawBuffer(ctx, ctx->Color.DrawBuffer[0]);
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_structs.h b/src/mesa/drivers/dri/i915tex/intel_structs.h
new file mode 100644 (file)
index 0000000..522e3bd
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef INTEL_STRUCTS_H
+#define INTEL_STRUCTS_H
+
+struct br0 {
+   GLuint length:8;
+   GLuint pad0:3;
+   GLuint dst_tiled:1;
+   GLuint pad1:8;
+   GLuint write_rgb:1;
+   GLuint write_alpha:1;
+   GLuint opcode:7;
+   GLuint client:3;
+};
+
+   
+struct br13 {
+   GLint dest_pitch:16;
+   GLuint rop:8;
+   GLuint color_depth:2;
+   GLuint pad1:3;
+   GLuint mono_source_transparency:1;
+   GLuint clipping_enable:1;
+   GLuint pad0:1;
+};
+
+
+
+/* This is an attempt to move some of the 2D interaction in this
+ * driver to using structs for packets rather than a bunch of #defines
+ * and dwords.
+ */
+struct xy_color_blit {
+   struct br0 br0;
+   struct br13 br13;
+
+   struct {
+      GLuint dest_x1:16;
+      GLuint dest_y1:16;
+   } dw2;
+
+   struct {
+      GLuint dest_x2:16;
+      GLuint dest_y2:16;
+   } dw3;
+   
+   GLuint dest_base_addr;
+   GLuint color;
+};
+
+struct xy_src_copy_blit {
+   struct br0 br0;
+   struct br13 br13;
+
+   struct {
+      GLuint dest_x1:16;
+      GLuint dest_y1:16;
+   } dw2;
+
+   struct {
+      GLuint dest_x2:16;
+      GLuint dest_y2:16;
+   } dw3;
+   
+   GLuint dest_base_addr;
+
+   struct {
+      GLuint src_x1:16;
+      GLuint src_y1:16;
+   } dw5;
+
+   struct {
+      GLint src_pitch:16;
+      GLuint pad:16;
+   } dw6;
+   
+   GLuint src_base_addr;
+};
+
+struct xy_setup_blit {
+   struct br0 br0;
+   struct br13 br13;
+
+   struct {
+      GLuint clip_x1:16;
+      GLuint clip_y1:16;
+   } dw2;
+
+   struct {
+      GLuint clip_x2:16;
+      GLuint clip_y2:16;
+   } dw3;
+      
+   GLuint dest_base_addr;
+   GLuint background_color;
+   GLuint foreground_color;
+   GLuint pattern_base_addr;
+};
+
+
+struct xy_text_immediate_blit {
+   struct {
+      GLuint length:8;
+      GLuint pad2:3;
+      GLuint dst_tiled:1;
+      GLuint pad1:4;
+      GLuint byte_packed:1;
+      GLuint pad0:5;
+      GLuint opcode:7;
+      GLuint client:3;
+   } dw0;
+
+   struct {
+      GLuint dest_x1:16;
+      GLuint dest_y1:16;
+   } dw1;
+
+   struct {
+      GLuint dest_x2:16;
+      GLuint dest_y2:16;
+   } dw2;   
+
+   /* Src bitmap data follows as inline dwords.
+    */
+};
+
+
+#define CLIENT_2D 0x2
+#define OPCODE_XY_SETUP_BLT 0x1
+#define OPCODE_XY_COLOR_BLT 0x50
+#define OPCODE_XY_TEXT_IMMEDIATE_BLT 0x31
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex.c b/src/mesa/drivers/dri/i915tex/intel_tex.c
new file mode 100644 (file)
index 0000000..51875ab
--- /dev/null
@@ -0,0 +1,182 @@
+#include "texobj.h"
+#include "intel_context.h"
+#include "intel_mipmap_tree.h"
+#include "intel_tex.h"
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+static GLboolean
+intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj)
+{
+#if 0
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_texture_object *intelObj = intel_texture_object(texObj);
+
+   return
+      intelObj->mt &&
+      intelObj->mt->region &&
+      intel_is_region_resident(intel, intelObj->mt->region);
+#endif
+   return 1;
+}
+
+
+
+static struct gl_texture_image *
+intelNewTextureImage(GLcontext * ctx)
+{
+   DBG("%s\n", __FUNCTION__);
+   (void) ctx;
+   return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image);
+}
+
+
+static struct gl_texture_object *
+intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
+{
+   struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
+
+   DBG("%s\n", __FUNCTION__);
+   _mesa_initialize_texture_object(&obj->base, name, target);
+
+   return &obj->base;
+}
+
+static void 
+intelDeleteTextureObject(GLcontext *ctx,
+                        struct gl_texture_object *texObj)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_texture_object *intelObj = intel_texture_object(texObj);
+
+   if (intelObj->mt)
+      intel_miptree_release(intel, &intelObj->mt);
+
+   _mesa_delete_texture_object(ctx, texObj);
+}
+
+
+static void
+intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_texture_image *intelImage = intel_texture_image(texImage);
+
+   DBG("%s\n", __FUNCTION__);
+
+   if (intelImage->mt) {
+      intel_miptree_release(intel, &intelImage->mt);
+   }
+
+   if (texImage->Data) {
+      free(texImage->Data);
+      texImage->Data = NULL;
+   }
+}
+
+
+#ifndef __x86_64__
+static unsigned
+fastrdtsc(void)
+{
+   unsigned eax;
+   __asm__ volatile ("\t"
+                     "pushl  %%ebx\n\t"
+                     "cpuid\n\t" ".byte 0x0f, 0x31\n\t"
+                     "popl %%ebx\n":"=a" (eax)
+                     :"0"(0)
+                     :"ecx", "edx", "cc");
+
+   return eax;
+}
+#else
+static unsigned
+fastrdtsc(void)
+{
+   unsigned eax;
+   __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax)
+                     :"0"(0)
+                     :"ecx", "edx", "ebx", "cc");
+
+   return eax;
+}
+#endif
+
+static unsigned
+time_diff(unsigned t, unsigned t2)
+{
+   return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
+}
+
+
+/* The system memcpy (at least on ubuntu 5.10) has problems copying
+ * to agp (writecombined) memory from a source which isn't 64-byte
+ * aligned - there is a 4x performance falloff.
+ *
+ * The x86 __memcpy is immune to this but is slightly slower
+ * (10%-ish) than the system memcpy.
+ *
+ * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
+ * isn't much faster than x86_memcpy for agp copies.
+ * 
+ * TODO: switch dynamically.
+ */
+static void *
+do_memcpy(void *dest, const void *src, size_t n)
+{
+   if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
+      return __memcpy(dest, src, n);
+   }
+   else
+      return memcpy(dest, src, n);
+}
+
+
+static void *
+timed_memcpy(void *dest, const void *src, size_t n)
+{
+   void *ret;
+   unsigned t1, t2;
+   double rate;
+
+   if ((((unsigned) src) & 63) || (((unsigned) dest) & 63))
+      _mesa_printf("Warning - non-aligned texture copy!\n");
+
+   t1 = fastrdtsc();
+   ret = do_memcpy(dest, src, n);
+   t2 = fastrdtsc();
+
+   rate = time_diff(t1, t2);
+   rate /= (double) n;
+   _mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);
+   return ret;
+}
+
+
+void
+intelInitTextureFuncs(struct dd_function_table *functions)
+{
+   functions->ChooseTextureFormat = intelChooseTextureFormat;
+   functions->TexImage1D = intelTexImage1D;
+   functions->TexImage2D = intelTexImage2D;
+   functions->TexImage3D = intelTexImage3D;
+   functions->TexSubImage1D = intelTexSubImage1D;
+   functions->TexSubImage2D = intelTexSubImage2D;
+   functions->TexSubImage3D = intelTexSubImage3D;
+   functions->CopyTexImage1D = intelCopyTexImage1D;
+   functions->CopyTexImage2D = intelCopyTexImage2D;
+   functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
+   functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
+   functions->GetTexImage = intelGetTexImage;
+   functions->NewTextureObject = intelNewTextureObject;
+   functions->NewTextureImage = intelNewTextureImage;
+   functions->DeleteTexture = intelDeleteTextureObject;
+   functions->FreeTexImageData = intelFreeTextureImageData;
+   functions->UpdateTexturePalette = 0;
+   functions->IsTextureResident = intelIsTextureResident;
+
+   if (INTEL_DEBUG & DEBUG_BUFMGR)
+      functions->TextureMemCpy = timed_memcpy;
+   else
+      functions->TextureMemCpy = do_memcpy;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex.h b/src/mesa/drivers/dri/i915tex/intel_tex.h
new file mode 100644 (file)
index 0000000..2f3d4ec
--- /dev/null
@@ -0,0 +1,134 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTELTEX_INC
+#define INTELTEX_INC
+
+#include "mtypes.h"
+#include "intel_context.h"
+#include "texmem.h"
+
+
+void intelInitTextureFuncs(struct dd_function_table *functions);
+
+const struct gl_texture_format *intelChooseTextureFormat(GLcontext * ctx,
+                                                         GLint internalFormat,
+                                                         GLenum format,
+                                                         GLenum type);
+
+
+void intelTexImage3D(GLcontext * ctx,
+                     GLenum target, GLint level,
+                     GLint internalFormat,
+                     GLint width, GLint height, GLint depth,
+                     GLint border,
+                     GLenum format, GLenum type, const void *pixels,
+                     const struct gl_pixelstore_attrib *packing,
+                     struct gl_texture_object *texObj,
+                     struct gl_texture_image *texImage);
+
+void intelTexSubImage3D(GLcontext * ctx,
+                        GLenum target,
+                        GLint level,
+                        GLint xoffset, GLint yoffset, GLint zoffset,
+                        GLsizei width, GLsizei height, GLsizei depth,
+                        GLenum format, GLenum type,
+                        const GLvoid * pixels,
+                        const struct gl_pixelstore_attrib *packing,
+                        struct gl_texture_object *texObj,
+                        struct gl_texture_image *texImage);
+
+void intelTexImage2D(GLcontext * ctx,
+                     GLenum target, GLint level,
+                     GLint internalFormat,
+                     GLint width, GLint height, GLint border,
+                     GLenum format, GLenum type, const void *pixels,
+                     const struct gl_pixelstore_attrib *packing,
+                     struct gl_texture_object *texObj,
+                     struct gl_texture_image *texImage);
+
+void intelTexSubImage2D(GLcontext * ctx,
+                        GLenum target,
+                        GLint level,
+                        GLint xoffset, GLint yoffset,
+                        GLsizei width, GLsizei height,
+                        GLenum format, GLenum type,
+                        const GLvoid * pixels,
+                        const struct gl_pixelstore_attrib *packing,
+                        struct gl_texture_object *texObj,
+                        struct gl_texture_image *texImage);
+
+void intelTexImage1D(GLcontext * ctx,
+                     GLenum target, GLint level,
+                     GLint internalFormat,
+                     GLint width, GLint border,
+                     GLenum format, GLenum type, const void *pixels,
+                     const struct gl_pixelstore_attrib *packing,
+                     struct gl_texture_object *texObj,
+                     struct gl_texture_image *texImage);
+
+void intelTexSubImage1D(GLcontext * ctx,
+                        GLenum target,
+                        GLint level,
+                        GLint xoffset,
+                        GLsizei width,
+                        GLenum format, GLenum type,
+                        const GLvoid * pixels,
+                        const struct gl_pixelstore_attrib *packing,
+                        struct gl_texture_object *texObj,
+                        struct gl_texture_image *texImage);
+
+void intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+                         GLenum internalFormat,
+                         GLint x, GLint y, GLsizei width, GLint border);
+
+void intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+                         GLenum internalFormat,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLint border);
+
+void intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+                            GLint xoffset, GLint x, GLint y, GLsizei width);
+
+void intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+                            GLint xoffset, GLint yoffset,
+                            GLint x, GLint y, GLsizei width, GLsizei height);
+
+void intelGetTexImage(GLcontext * ctx, GLenum target, GLint level,
+                      GLenum format, GLenum type, GLvoid * pixels,
+                      struct gl_texture_object *texObj,
+                      struct gl_texture_image *texImage);
+
+GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit);
+
+void intel_tex_map_images(struct intel_context *intel,
+                          struct intel_texture_object *intelObj);
+
+void intel_tex_unmap_images(struct intel_context *intel,
+                            struct intel_texture_object *intelObj);
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex_copy.c b/src/mesa/drivers/dri/i915tex/intel_tex_copy.c
new file mode 100644 (file)
index 0000000..88b62e7
--- /dev/null
@@ -0,0 +1,301 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "mtypes.h"
+#include "enums.h"
+#include "image.h"
+#include "teximage.h"
+#include "swrast/swrast.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_batchbuffer.h"
+#include "intel_buffers.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
+#include "intel_fbo.h"
+#include "intel_tex.h"
+#include "intel_blit.h"
+#include "intel_pixel.h"
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+/**
+ * Get the intel_region which is the source for any glCopyTex[Sub]Image call.
+ *
+ * Do the best we can using the blitter.  A future project is to use
+ * the texture engine and fragment programs for these copies.
+ */
+static const struct intel_region *
+get_teximage_source(struct intel_context *intel, GLenum internalFormat)
+{
+   struct intel_renderbuffer *irb;
+
+   DBG("%s %s\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(internalFormat));
+
+   switch (internalFormat) {
+   case GL_DEPTH_COMPONENT:
+   case GL_DEPTH_COMPONENT16_ARB:
+      irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
+      if (irb && irb->region && irb->region->cpp == 2)
+         return irb->region;
+      return NULL;
+   case GL_DEPTH24_STENCIL8_EXT:
+   case GL_DEPTH_STENCIL_EXT:
+      irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
+      if (irb && irb->region && irb->region->cpp == 4)
+         return irb->region;
+      return NULL;
+   case GL_RGBA:
+   case GL_RGBA8:
+      return intel_readbuf_region(intel);
+   case GL_RGB:
+      if (intel->intelScreen->cpp == 2)
+         return intel_readbuf_region(intel);
+      return NULL;
+   default:
+      return NULL;
+   }
+}
+
+
+static GLboolean
+do_copy_texsubimage(struct intel_context *intel,
+                    struct intel_texture_image *intelImage,
+                    GLenum internalFormat,
+                    GLint dstx, GLint dsty,
+                    GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   GLcontext *ctx = &intel->ctx;
+   const struct intel_region *src =
+      get_teximage_source(intel, internalFormat);
+
+   if (!intelImage->mt || !src) {
+      DBG("%s fail %p %p\n", __FUNCTION__, intelImage->mt, src);
+      return GL_FALSE;
+   }
+
+   intelFlush(ctx);
+   LOCK_HARDWARE(intel);
+   {
+      GLuint image_offset = intel_miptree_image_offset(intelImage->mt,
+                                                       intelImage->face,
+                                                       intelImage->level);
+      const GLint orig_x = x;
+      const GLint orig_y = y;
+      const struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+      if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax,
+                               &x, &y, &width, &height)) {
+         /* Update dst for clipped src.  Need to also clip the source rect.
+          */
+         dstx += x - orig_x;
+         dsty += y - orig_y;
+
+         if (ctx->ReadBuffer->Name == 0) {
+            /* reading from a window, adjust x, y */
+            __DRIdrawablePrivate *dPriv = intel->driDrawable;
+            GLuint window_y;
+            /* window_y = position of window on screen if y=0=bottom */
+            window_y = intel->intelScreen->height - (dPriv->y + dPriv->h);
+            y = window_y + y;
+            x += dPriv->x;
+         }
+         else {
+            /* reading from a FBO */
+            /* invert Y */
+            y = ctx->ReadBuffer->Height - y - 1;
+         }
+
+
+         /* A bit of fiddling to get the blitter to work with -ve
+          * pitches.  But we get a nice inverted blit this way, so it's
+          * worth it:
+          */
+         intelEmitCopyBlit(intel,
+                           intelImage->mt->cpp,
+                           -src->pitch,
+                           src->buffer,
+                           src->height * src->pitch * src->cpp,
+                           intelImage->mt->pitch,
+                           intelImage->mt->region->buffer,
+                           image_offset,
+                           x, y + height, dstx, dsty, width, height);
+
+         intel_batchbuffer_flush(intel->batch);
+      }
+   }
+
+
+   UNLOCK_HARDWARE(intel);
+
+#if 0
+   /* GL_SGIS_generate_mipmap -- this can be accelerated now.
+    * XXX Add a ctx->Driver.GenerateMipmaps() function?
+    */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      intel_generate_mipmap(ctx, target,
+                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
+                            texObj);
+   }
+#endif
+
+   return GL_TRUE;
+}
+
+
+
+
+
+void
+intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+                    GLenum internalFormat,
+                    GLint x, GLint y, GLsizei width, GLint border)
+{
+   struct gl_texture_unit *texUnit =
+      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_object *texObj =
+      _mesa_select_tex_object(ctx, texUnit, target);
+   struct gl_texture_image *texImage =
+      _mesa_select_tex_image(ctx, texObj, target, level);
+
+   if (border)
+      goto fail;
+
+   /* Setup or redefine the texture object, mipmap tree and texture
+    * image.  Don't populate yet.  
+    */
+   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+                          width, border,
+                          GL_RGBA, CHAN_TYPE, NULL,
+                          &ctx->DefaultPacking, texObj, texImage);
+
+   if (!do_copy_texsubimage(intel_context(ctx),
+                            intel_texture_image(texImage),
+                            internalFormat, 0, 0, x, y, width, 1))
+      goto fail;
+
+   return;
+
+ fail:
+   _swrast_copy_teximage1d(ctx, target, level, internalFormat, x, y,
+                           width, border);
+}
+
+void
+intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+                    GLenum internalFormat,
+                    GLint x, GLint y, GLsizei width, GLsizei height,
+                    GLint border)
+{
+   struct gl_texture_unit *texUnit =
+      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_object *texObj =
+      _mesa_select_tex_object(ctx, texUnit, target);
+   struct gl_texture_image *texImage =
+      _mesa_select_tex_image(ctx, texObj, target, level);
+
+   if (border)
+      goto fail;
+
+   /* Setup or redefine the texture object, mipmap tree and texture
+    * image.  Don't populate yet.  
+    */
+   ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+                          width, height, border,
+                          GL_RGBA, CHAN_TYPE, NULL,
+                          &ctx->DefaultPacking, texObj, texImage);
+
+
+   if (!do_copy_texsubimage(intel_context(ctx),
+                            intel_texture_image(texImage),
+                            internalFormat, 0, 0, x, y, width, height))
+      goto fail;
+
+   return;
+
+ fail:
+   _swrast_copy_teximage2d(ctx, target, level, internalFormat, x, y,
+                           width, height, border);
+}
+
+
+void
+intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+                       GLint xoffset, GLint x, GLint y, GLsizei width)
+{
+   struct gl_texture_unit *texUnit =
+      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_object *texObj =
+      _mesa_select_tex_object(ctx, texUnit, target);
+   struct gl_texture_image *texImage =
+      _mesa_select_tex_image(ctx, texObj, target, level);
+   GLenum internalFormat = texImage->InternalFormat;
+
+   /* XXX need to check <border> as in above function? */
+
+   /* Need to check texture is compatible with source format. 
+    */
+
+   if (!do_copy_texsubimage(intel_context(ctx),
+                            intel_texture_image(texImage),
+                            internalFormat, xoffset, 0, x, y, width, 1)) {
+      _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width);
+   }
+}
+
+
+
+void
+intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+                       GLint xoffset, GLint yoffset,
+                       GLint x, GLint y, GLsizei width, GLsizei height)
+{
+   struct gl_texture_unit *texUnit =
+      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+   struct gl_texture_object *texObj =
+      _mesa_select_tex_object(ctx, texUnit, target);
+   struct gl_texture_image *texImage =
+      _mesa_select_tex_image(ctx, texObj, target, level);
+   GLenum internalFormat = texImage->InternalFormat;
+
+
+   /* Need to check texture is compatible with source format. 
+    */
+
+   if (!do_copy_texsubimage(intel_context(ctx),
+                            intel_texture_image(texImage),
+                            internalFormat,
+                            xoffset, yoffset, x, y, width, height)) {
+
+      DBG("%s - fallback to swrast\n", __FUNCTION__);
+
+      _swrast_copy_texsubimage2d(ctx, target, level,
+                                 xoffset, yoffset, x, y, width, height);
+   }
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex_format.c b/src/mesa/drivers/dri/i915tex/intel_tex_format.c
new file mode 100644 (file)
index 0000000..d7612dc
--- /dev/null
@@ -0,0 +1,146 @@
+#include "intel_context.h"
+#include "intel_tex.h"
+#include "texformat.h"
+#include "enums.h"
+
+/* It works out that this function is fine for all the supported
+ * hardware.  However, there is still a need to map the formats onto
+ * hardware descriptors.
+ */
+/* Note that the i915 can actually support many more formats than
+ * these if we take the step of simply swizzling the colors
+ * immediately after sampling...
+ */
+const struct gl_texture_format *
+intelChooseTextureFormat(GLcontext * ctx, GLint internalFormat,
+                         GLenum format, GLenum type)
+{
+   struct intel_context *intel = intel_context(ctx);
+   const GLboolean do32bpt = (intel->intelScreen->cpp == 4);
+
+   switch (internalFormat) {
+   case 4:
+   case GL_RGBA:
+   case GL_COMPRESSED_RGBA:
+      if (format == GL_BGRA) {
+         if (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) {
+            return &_mesa_texformat_argb8888;
+         }
+         else if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
+            return &_mesa_texformat_argb4444;
+         }
+         else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
+            return &_mesa_texformat_argb1555;
+         }
+      }
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+
+   case 3:
+   case GL_RGB:
+   case GL_COMPRESSED_RGB:
+      if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
+         return &_mesa_texformat_rgb565;
+      }
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+
+   case GL_RGBA8:
+   case GL_RGB10_A2:
+   case GL_RGBA12:
+   case GL_RGBA16:
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+
+   case GL_RGBA4:
+   case GL_RGBA2:
+      return &_mesa_texformat_argb4444;
+
+   case GL_RGB5_A1:
+      return &_mesa_texformat_argb1555;
+
+   case GL_RGB8:
+   case GL_RGB10:
+   case GL_RGB12:
+   case GL_RGB16:
+      return &_mesa_texformat_argb8888;
+
+   case GL_RGB5:
+   case GL_RGB4:
+   case GL_R3_G3_B2:
+      return &_mesa_texformat_rgb565;
+
+   case GL_ALPHA:
+   case GL_ALPHA4:
+   case GL_ALPHA8:
+   case GL_ALPHA12:
+   case GL_ALPHA16:
+   case GL_COMPRESSED_ALPHA:
+      return &_mesa_texformat_a8;
+
+   case 1:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE4:
+   case GL_LUMINANCE8:
+   case GL_LUMINANCE12:
+   case GL_LUMINANCE16:
+   case GL_COMPRESSED_LUMINANCE:
+      return &_mesa_texformat_l8;
+
+   case 2:
+   case GL_LUMINANCE_ALPHA:
+   case GL_LUMINANCE4_ALPHA4:
+   case GL_LUMINANCE6_ALPHA2:
+   case GL_LUMINANCE8_ALPHA8:
+   case GL_LUMINANCE12_ALPHA4:
+   case GL_LUMINANCE12_ALPHA12:
+   case GL_LUMINANCE16_ALPHA16:
+   case GL_COMPRESSED_LUMINANCE_ALPHA:
+      return &_mesa_texformat_al88;
+
+   case GL_INTENSITY:
+   case GL_INTENSITY4:
+   case GL_INTENSITY8:
+   case GL_INTENSITY12:
+   case GL_INTENSITY16:
+   case GL_COMPRESSED_INTENSITY:
+      return &_mesa_texformat_i8;
+
+   case GL_YCBCR_MESA:
+      if (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE)
+         return &_mesa_texformat_ycbcr;
+      else
+         return &_mesa_texformat_ycbcr_rev;
+
+   case GL_COMPRESSED_RGB_FXT1_3DFX:
+      return &_mesa_texformat_rgb_fxt1;
+   case GL_COMPRESSED_RGBA_FXT1_3DFX:
+      return &_mesa_texformat_rgba_fxt1;
+
+   case GL_RGB_S3TC:
+   case GL_RGB4_S3TC:
+   case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+      return &_mesa_texformat_rgb_dxt1;
+
+   case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+      return &_mesa_texformat_rgba_dxt1;
+
+   case GL_RGBA_S3TC:
+   case GL_RGBA4_S3TC:
+   case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+      return &_mesa_texformat_rgba_dxt3;
+
+   case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+      return &_mesa_texformat_rgba_dxt5;
+
+   case GL_DEPTH_COMPONENT:
+   case GL_DEPTH_COMPONENT16:
+   case GL_DEPTH_COMPONENT24:
+   case GL_DEPTH_COMPONENT32:
+      return &_mesa_texformat_z16;
+
+   default:
+      fprintf(stderr, "unexpected texture format %s in %s\n",
+              _mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__);
+      return NULL;
+   }
+
+   return NULL;                 /* never get here */
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex_image.c b/src/mesa/drivers/dri/i915tex/intel_tex_image.c
new file mode 100644 (file)
index 0000000..48c2f35
--- /dev/null
@@ -0,0 +1,626 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "enums.h"
+#include "colortab.h"
+#include "convolve.h"
+#include "context.h"
+#include "simple_list.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "texobj.h"
+#include "texstore.h"
+
+#include "intel_context.h"
+#include "intel_mipmap_tree.h"
+#include "intel_buffer_objects.h"
+#include "intel_batchbuffer.h"
+#include "intel_tex.h"
+#include "intel_ioctl.h"
+#include "intel_blit.h"
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+/* Functions to store texture images.  Where possible, mipmap_tree's
+ * will be created or further instantiated with image data, otherwise
+ * images will be stored in malloc'd memory.  A validation step is
+ * required to pull those images into a mipmap tree, or otherwise
+ * decide a fallback is required.
+ */
+
+
+static int
+logbase2(int n)
+{
+   GLint i = 1;
+   GLint log2 = 0;
+
+   while (n > i) {
+      i *= 2;
+      log2++;
+   }
+
+   return log2;
+}
+
+
+/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
+ * 1).
+ *    
+ * Otherwise, if max_level >= level >= min_level, create tree with
+ * space for textures from min_level down to max_level.
+ *
+ * Otherwise, create tree with space for textures from (level
+ * 0)..(1x1).  Consider pruning this tree at a validation if the
+ * saving is worth it.
+ */
+static void
+guess_and_alloc_mipmap_tree(struct intel_context *intel,
+                            struct intel_texture_object *intelObj,
+                            struct intel_texture_image *intelImage)
+{
+   GLuint firstLevel;
+   GLuint lastLevel;
+   GLuint width = intelImage->base.Width;
+   GLuint height = intelImage->base.Height;
+   GLuint depth = intelImage->base.Depth;
+   GLuint l2width, l2height, l2depth;
+   GLuint i;
+
+   DBG("%s\n", __FUNCTION__);
+
+   if (intelImage->base.Border)
+      return;
+
+   if (intelImage->level > intelObj->base.BaseLevel &&
+       (intelImage->base.Width == 1 ||
+        (intelObj->base.Target != GL_TEXTURE_1D &&
+         intelImage->base.Height == 1) ||
+        (intelObj->base.Target == GL_TEXTURE_3D &&
+         intelImage->base.Depth == 1)))
+      return;
+
+   /* If this image disrespects BaseLevel, allocate from level zero.
+    * Usually BaseLevel == 0, so it's unlikely to happen.
+    */
+   if (intelImage->level < intelObj->base.BaseLevel)
+      firstLevel = 0;
+   else
+      firstLevel = intelObj->base.BaseLevel;
+
+
+   /* Figure out image dimensions at start level. 
+    */
+   for (i = intelImage->level; i > firstLevel; i--) {
+      width <<= 1;
+      if (height != 1)
+         height <<= 1;
+      if (depth != 1)
+         depth <<= 1;
+   }
+
+   /* Guess a reasonable value for lastLevel.  This is probably going
+    * to be wrong fairly often and might mean that we have to look at
+    * resizable buffers, or require that buffers implement lazy
+    * pagetable arrangements.
+    */
+   if ((intelObj->base.MinFilter == GL_NEAREST ||
+        intelObj->base.MinFilter == GL_LINEAR) &&
+       intelImage->level == firstLevel) {
+      lastLevel = firstLevel;
+   }
+   else {
+      l2width = logbase2(width);
+      l2height = logbase2(height);
+      l2depth = logbase2(depth);
+      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
+   }
+
+   assert(!intelObj->mt);
+   intelObj->mt = intel_miptree_create(intel,
+                                       intelObj->base.Target,
+                                       intelImage->base.InternalFormat,
+                                       firstLevel,
+                                       lastLevel,
+                                       width,
+                                       height,
+                                       depth,
+                                       intelImage->base.TexFormat->TexelBytes,
+                                       intelImage->base.IsCompressed);
+
+   DBG("%s - success\n", __FUNCTION__);
+}
+
+
+
+
+static GLuint
+target_to_face(GLenum target)
+{
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+      return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
+   default:
+      return 0;
+   }
+}
+
+/* There are actually quite a few combinations this will work for,
+ * more than what I've listed here.
+ */
+static GLboolean
+check_pbo_format(GLint internalFormat,
+                 GLenum format, GLenum type,
+                 const struct gl_texture_format *mesa_format)
+{
+   switch (internalFormat) {
+   case 4:
+   case GL_RGBA:
+      return (format == GL_BGRA &&
+              (type == GL_UNSIGNED_BYTE ||
+               type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
+              mesa_format == &_mesa_texformat_argb8888);
+   case 3:
+   case GL_RGB:
+      return (format == GL_RGB &&
+              type == GL_UNSIGNED_SHORT_5_6_5 &&
+              mesa_format == &_mesa_texformat_rgb565);
+   case GL_YCBCR_MESA:
+      return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE);
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+/* XXX: Do this for TexSubImage also:
+ */
+static GLboolean
+try_pbo_upload(struct intel_context *intel,
+               struct intel_texture_image *intelImage,
+               const struct gl_pixelstore_attrib *unpack,
+               GLint internalFormat,
+               GLint width, GLint height,
+               GLenum format, GLenum type, const void *pixels)
+{
+   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
+   GLuint src_offset, src_stride;
+   GLuint dst_offset, dst_stride;
+
+   if (!pbo ||
+       intel->ctx._ImageTransferState ||
+       unpack->SkipPixels || unpack->SkipRows) {
+      _mesa_printf("%s: failure 1\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   src_offset = (GLuint) pixels;
+
+   if (unpack->RowLength > 0)
+      src_stride = unpack->RowLength;
+   else
+      src_stride = width;
+
+   dst_offset = intel_miptree_image_offset(intelImage->mt,
+                                           intelImage->face,
+                                           intelImage->level);
+
+   dst_stride = intelImage->mt->pitch;
+
+   intelFlush(&intel->ctx);
+   LOCK_HARDWARE(intel);
+   {
+      struct _DriBufferObject *src_buffer =
+         intel_bufferobj_buffer(intel, pbo, INTEL_READ);
+      struct _DriBufferObject *dst_buffer =
+         intel_region_buffer(intel->intelScreen, intelImage->mt->region,
+                             INTEL_WRITE_FULL);
+
+
+      intelEmitCopyBlit(intel,
+                        intelImage->mt->cpp,
+                        src_stride, src_buffer, src_offset,
+                        dst_stride, dst_buffer, dst_offset,
+                        0, 0, 0, 0, width, height);
+
+      intel_batchbuffer_flush(intel->batch);
+   }
+   UNLOCK_HARDWARE(intel);
+
+   return GL_TRUE;
+}
+
+
+
+static GLboolean
+try_pbo_zcopy(struct intel_context *intel,
+              struct intel_texture_image *intelImage,
+              const struct gl_pixelstore_attrib *unpack,
+              GLint internalFormat,
+              GLint width, GLint height,
+              GLenum format, GLenum type, const void *pixels)
+{
+   struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
+   GLuint src_offset, src_stride;
+   GLuint dst_offset, dst_stride;
+
+   if (!pbo ||
+       intel->ctx._ImageTransferState ||
+       unpack->SkipPixels || unpack->SkipRows) {
+      _mesa_printf("%s: failure 1\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   src_offset = (GLuint) pixels;
+
+   if (unpack->RowLength > 0)
+      src_stride = unpack->RowLength;
+   else
+      src_stride = width;
+
+   dst_offset = intel_miptree_image_offset(intelImage->mt,
+                                           intelImage->face,
+                                           intelImage->level);
+
+   dst_stride = intelImage->mt->pitch;
+
+   if (src_stride != dst_stride || dst_offset != 0 || src_offset != 0) {
+      _mesa_printf("%s: failure 2\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   intel_region_attach_pbo(intel->intelScreen, intelImage->mt->region, pbo);
+
+   return GL_TRUE;
+}
+
+
+
+
+
+
+static void
+intelTexImage(GLcontext * ctx,
+              GLint dims,
+              GLenum target, GLint level,
+              GLint internalFormat,
+              GLint width, GLint height, GLint depth,
+              GLint border,
+              GLenum format, GLenum type, const void *pixels,
+              const struct gl_pixelstore_attrib *unpack,
+              struct gl_texture_object *texObj,
+              struct gl_texture_image *texImage)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_texture_object *intelObj = intel_texture_object(texObj);
+   struct intel_texture_image *intelImage = intel_texture_image(texImage);
+   GLint postConvWidth = width;
+   GLint postConvHeight = height;
+   GLint texelBytes, sizeInBytes;
+   GLuint dstRowStride;
+
+
+   DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
+
+   intelFlush(ctx);
+
+   intelImage->face = target_to_face(target);
+   intelImage->level = level;
+
+   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
+                                         &postConvHeight);
+   }
+
+   /* choose the texture format */
+   texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,
+                                                  format, type);
+
+   assert(texImage->TexFormat);
+
+   switch (dims) {
+   case 1:
+      texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
+      texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
+      break;
+   case 2:
+      texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
+      texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
+      break;
+   case 3:
+      texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
+      texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
+      break;
+   default:
+      assert(0);
+      break;
+   }
+
+   texelBytes = texImage->TexFormat->TexelBytes;
+
+
+   /* Minimum pitch of 32 bytes */
+   if (postConvWidth * texelBytes < 32) {
+      postConvWidth = 32 / texelBytes;
+      texImage->RowStride = postConvWidth;
+   }
+
+   assert(texImage->RowStride == postConvWidth);
+
+   /* Release the reference to a potentially orphaned buffer.   
+    * Release any old malloced memory.
+    */
+   if (intelImage->mt) {
+      intel_miptree_release(intel, &intelImage->mt);
+      assert(!texImage->Data);
+   }
+   else if (texImage->Data) {
+      _mesa_align_free(texImage->Data);
+   }
+
+   /* If this is the only texture image in the tree, could call
+    * bmBufferData with NULL data to free the old block and avoid
+    * waiting on any outstanding fences.
+    */
+   if (intelObj->mt &&
+       intelObj->mt->first_level == level &&
+       intelObj->mt->last_level == level &&
+       intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
+       !intel_miptree_match_image(intelObj->mt, &intelImage->base,
+                                  intelImage->face, intelImage->level)) {
+
+      DBG("release it\n");
+      intel_miptree_release(intel, &intelObj->mt);
+      assert(!intelObj->mt);
+   }
+
+   if (!intelObj->mt) {
+      guess_and_alloc_mipmap_tree(intel, intelObj, intelImage);
+      if (!intelObj->mt) {
+        DBG("guess_and_alloc_mipmap_tree: failed\n");
+      }
+   }
+
+
+   assert(!intelImage->mt);
+
+   if (intelObj->mt &&
+       intel_miptree_match_image(intelObj->mt, &intelImage->base,
+                                 intelImage->face, intelImage->level)) {
+
+      intel_miptree_reference(&intelImage->mt, intelObj->mt);
+      assert(intelImage->mt);
+   }
+
+   if (!intelImage->mt)
+      DBG("XXX: Image did not fit into tree - storing in local memory!\n");
+
+   /* PBO fastpaths:
+    */
+   if (dims <= 2 &&
+       intelImage->mt &&
+       intel_buffer_object(unpack->BufferObj) &&
+       check_pbo_format(internalFormat, format,
+                        type, intelImage->base.TexFormat)) {
+
+      DBG("trying pbo upload\n");
+
+      /* Attempt to texture directly from PBO data (zero copy upload).
+       *
+       * Currently disable as it can lead to worse as well as better
+       * performance (in particular when intel_region_cow() is
+       * required).
+       */
+      if (intelObj->mt == intelImage->mt &&
+          intelObj->mt->first_level == level &&
+          intelObj->mt->last_level == level) {
+
+         if (try_pbo_zcopy(intel, intelImage, unpack,
+                           internalFormat,
+                           width, height, format, type, pixels)) {
+
+            DBG("pbo zcopy upload succeeded\n");
+            return;
+         }
+      }
+
+
+      /* Otherwise, attempt to use the blitter for PBO image uploads.
+       */
+      if (try_pbo_upload(intel, intelImage, unpack,
+                         internalFormat,
+                         width, height, format, type, pixels)) {
+         DBG("pbo upload succeeded\n");
+         return;
+      }
+
+      DBG("pbo upload failed\n");
+   }
+
+
+
+   /* intelCopyTexImage calls this function with pixels == NULL, with
+    * the expectation that the mipmap tree will be set up but nothing
+    * more will be done.  This is where those calls return:
+    */
+   pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
+                                        format, type,
+                                        pixels, unpack, "glTexImage");
+   if (!pixels)
+      return;
+
+
+   if (intelImage->mt)
+      intel_region_idle(intel->intelScreen, intelImage->mt->region);
+
+   LOCK_HARDWARE(intel);
+
+   if (intelImage->mt) {
+      texImage->Data = intel_miptree_image_map(intel,
+                                               intelImage->mt,
+                                               intelImage->face,
+                                               intelImage->level,
+                                               &dstRowStride,
+                                               intelImage->base.ImageOffsets);
+   }
+   else {
+      /* Allocate regular memory and store the image there temporarily.   */
+      if (texImage->IsCompressed) {
+         sizeInBytes = texImage->CompressedSize;
+         dstRowStride =
+            _mesa_compressed_row_stride(texImage->InternalFormat, width);
+         assert(dims != 3);
+      }
+      else {
+         dstRowStride = postConvWidth * texelBytes;
+         sizeInBytes = depth * dstRowStride * postConvHeight;
+      }
+
+      texImage->Data = malloc(sizeInBytes);
+   }
+
+   DBG("Upload image %dx%dx%d row_len %x "
+       "pitch %x\n",
+       width, height, depth, width * texelBytes, dstRowStride);
+
+   /* Copy data.  Would like to know when it's ok for us to eg. use
+    * the blitter to copy.  Or, use the hardware to do the format
+    * conversion and copy:
+    */
+   if (!texImage->TexFormat->StoreImage(ctx, dims, 
+                                       texImage->_BaseFormat, 
+                                       texImage->TexFormat, 
+                                       texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
+                                        dstRowStride,
+                                        texImage->ImageOffsets,
+                                        width, height, depth,
+                                        format, type, pixels, unpack)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
+   }
+
+   _mesa_unmap_teximage_pbo(ctx, unpack);
+
+   if (intelImage->mt) {
+      intel_miptree_image_unmap(intel, intelImage->mt);
+      texImage->Data = NULL;
+   }
+
+   UNLOCK_HARDWARE(intel);
+
+#if 0
+   /* GL_SGIS_generate_mipmap -- this can be accelerated now.
+    */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      intel_generate_mipmap(ctx, target,
+                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
+                            texObj);
+   }
+#endif
+}
+
+void
+intelTexImage3D(GLcontext * ctx,
+                GLenum target, GLint level,
+                GLint internalFormat,
+                GLint width, GLint height, GLint depth,
+                GLint border,
+                GLenum format, GLenum type, const void *pixels,
+                const struct gl_pixelstore_attrib *unpack,
+                struct gl_texture_object *texObj,
+                struct gl_texture_image *texImage)
+{
+   intelTexImage(ctx, 3, target, level,
+                 internalFormat, width, height, depth, border,
+                 format, type, pixels, unpack, texObj, texImage);
+}
+
+
+void
+intelTexImage2D(GLcontext * ctx,
+                GLenum target, GLint level,
+                GLint internalFormat,
+                GLint width, GLint height, GLint border,
+                GLenum format, GLenum type, const void *pixels,
+                const struct gl_pixelstore_attrib *unpack,
+                struct gl_texture_object *texObj,
+                struct gl_texture_image *texImage)
+{
+   intelTexImage(ctx, 2, target, level,
+                 internalFormat, width, height, 1, border,
+                 format, type, pixels, unpack, texObj, texImage);
+}
+
+void
+intelTexImage1D(GLcontext * ctx,
+                GLenum target, GLint level,
+                GLint internalFormat,
+                GLint width, GLint border,
+                GLenum format, GLenum type, const void *pixels,
+                const struct gl_pixelstore_attrib *unpack,
+                struct gl_texture_object *texObj,
+                struct gl_texture_image *texImage)
+{
+   intelTexImage(ctx, 1, target, level,
+                 internalFormat, width, 1, 1, border,
+                 format, type, pixels, unpack, texObj, texImage);
+}
+
+
+
+/**
+ * Need to map texture image into memory before copying image data,
+ * then unmap it.
+ */
+void
+intelGetTexImage(GLcontext * ctx, GLenum target, GLint level,
+                 GLenum format, GLenum type, GLvoid * pixels,
+                 struct gl_texture_object *texObj,
+                 struct gl_texture_image *texImage)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_texture_image *intelImage = intel_texture_image(texImage);
+
+   /* Map */
+   if (intelImage->mt) {
+      /* Image is stored in hardware format in a buffer managed by the
+       * kernel.  Need to explicitly map and unmap it.
+       */
+      intelImage->base.Data =
+         intel_miptree_image_map(intel,
+                                 intelImage->mt,
+                                 intelImage->face,
+                                 intelImage->level,
+                                 &intelImage->base.RowStride,
+                                 intelImage->base.ImageOffsets);
+   }
+   else {
+      /* Otherwise, the image should actually be stored in
+       * intelImage->base.Data.  This is pretty confusing for
+       * everybody, I'd much prefer to separate the two functions of
+       * texImage->Data - storage for texture images in main memory
+       * and access (ie mappings) of images.  In other words, we'd
+       * create a new texImage->Map field and leave Data simply for
+       * storage.
+       */
+      assert(intelImage->base.Data);
+   }
+
+   _mesa_get_teximage(ctx, target, level, format, type, pixels,
+                      texObj, texImage);
+
+   /* Unmap */
+   if (intelImage->mt) {
+      intel_miptree_image_unmap(intel, intelImage->mt);
+      intelImage->base.Data = NULL;
+   }
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex_subimage.c b/src/mesa/drivers/dri/i915tex/intel_tex_subimage.c
new file mode 100644 (file)
index 0000000..25a2dca
--- /dev/null
@@ -0,0 +1,183 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "mtypes.h"
+#include "texobj.h"
+#include "texstore.h"
+#include "enums.h"
+
+#include "intel_context.h"
+#include "intel_tex.h"
+#include "intel_mipmap_tree.h"
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+static void
+intelTexSubimage(GLcontext * ctx,
+                 GLint dims,
+                 GLenum target, GLint level,
+                 GLint xoffset, GLint yoffset, GLint zoffset,
+                 GLint width, GLint height, GLint depth,
+                 GLenum format, GLenum type, const void *pixels,
+                 const struct gl_pixelstore_attrib *packing,
+                 struct gl_texture_object *texObj,
+                 struct gl_texture_image *texImage)
+{
+   struct intel_context *intel = intel_context(ctx);
+   struct intel_texture_image *intelImage = intel_texture_image(texImage);
+   GLuint dstImageStride;
+   GLuint dstRowStride;
+
+   DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
+       _mesa_lookup_enum_by_nr(target),
+       level, xoffset, yoffset, width, height);
+
+   intelFlush(ctx);
+
+   pixels =
+      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
+                                  type, pixels, packing, "glTexSubImage2D");
+   if (!pixels)
+      return;
+
+   if (intelImage->mt)
+      intel_region_idle(intel->intelScreen, intelImage->mt->region);
+
+   LOCK_HARDWARE(intel);
+
+   /* Map buffer if necessary.  Need to lock to prevent other contexts
+    * from uploading the buffer under us.
+    */
+   if (intelImage->mt) 
+      texImage->Data = intel_miptree_image_map(intel,
+                                               intelImage->mt,
+                                               intelImage->face,
+                                               intelImage->level,
+                                               &dstRowStride,
+                                               &dstImageStride);
+
+   assert(dstRowStride);
+
+   if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
+                                        texImage->TexFormat,
+                                        texImage->Data,
+                                        xoffset, yoffset, zoffset,
+                                        dstRowStride,
+                                        texImage->ImageOffsets,
+                                        width, height, depth,
+                                        format, type, pixels, packing)) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
+   }
+
+#if 0
+   /* GL_SGIS_generate_mipmap */
+   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+      _mesa_generate_mipmap(ctx, target,
+                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
+                            texObj);
+   }
+#endif
+
+   _mesa_unmap_teximage_pbo(ctx, packing);
+
+   if (intelImage->mt) {
+      intel_miptree_image_unmap(intel, intelImage->mt);
+      texImage->Data = NULL;
+   }
+
+   UNLOCK_HARDWARE(intel);
+}
+
+
+
+
+
+void
+intelTexSubImage3D(GLcontext * ctx,
+                   GLenum target,
+                   GLint level,
+                   GLint xoffset, GLint yoffset, GLint zoffset,
+                   GLsizei width, GLsizei height, GLsizei depth,
+                   GLenum format, GLenum type,
+                   const GLvoid * pixels,
+                   const struct gl_pixelstore_attrib *packing,
+                   struct gl_texture_object *texObj,
+                   struct gl_texture_image *texImage)
+{
+
+   intelTexSubimage(ctx, 3,
+                    target, level,
+                    xoffset, yoffset, zoffset,
+                    width, height, depth,
+                    format, type, pixels, packing, texObj, texImage);
+
+}
+
+
+
+void
+intelTexSubImage2D(GLcontext * ctx,
+                   GLenum target,
+                   GLint level,
+                   GLint xoffset, GLint yoffset,
+                   GLsizei width, GLsizei height,
+                   GLenum format, GLenum type,
+                   const GLvoid * pixels,
+                   const struct gl_pixelstore_attrib *packing,
+                   struct gl_texture_object *texObj,
+                   struct gl_texture_image *texImage)
+{
+
+   intelTexSubimage(ctx, 2,
+                    target, level,
+                    xoffset, yoffset, 0,
+                    width, height, 1,
+                    format, type, pixels, packing, texObj, texImage);
+
+}
+
+
+void
+intelTexSubImage1D(GLcontext * ctx,
+                   GLenum target,
+                   GLint level,
+                   GLint xoffset,
+                   GLsizei width,
+                   GLenum format, GLenum type,
+                   const GLvoid * pixels,
+                   const struct gl_pixelstore_attrib *packing,
+                   struct gl_texture_object *texObj,
+                   struct gl_texture_image *texImage)
+{
+   intelTexSubimage(ctx, 1,
+                    target, level,
+                    xoffset, 0, 0,
+                    width, 1, 1,
+                    format, type, pixels, packing, texObj, texImage);
+
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tex_validate.c b/src/mesa/drivers/dri/i915tex/intel_tex_validate.c
new file mode 100644 (file)
index 0000000..e273716
--- /dev/null
@@ -0,0 +1,252 @@
+#include "mtypes.h"
+#include "macros.h"
+
+#include "intel_context.h"
+#include "intel_mipmap_tree.h"
+#include "intel_tex.h"
+
+#define FILE_DEBUG_FLAG DEBUG_TEXTURE
+
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+static void
+intel_calculate_first_last_level(struct intel_texture_object *intelObj)
+{
+   struct gl_texture_object *tObj = &intelObj->base;
+   const struct gl_texture_image *const baseImage =
+      tObj->Image[0][tObj->BaseLevel];
+
+   /* These must be signed values.  MinLod and MaxLod can be negative numbers,
+    * and having firstLevel and lastLevel as signed prevents the need for
+    * extra sign checks.
+    */
+   int firstLevel;
+   int lastLevel;
+
+   /* Yes, this looks overly complicated, but it's all needed.
+    */
+   switch (tObj->Target) {
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_3D:
+   case GL_TEXTURE_CUBE_MAP:
+      if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+          */
+         firstLevel = lastLevel = tObj->BaseLevel;
+      }
+      else {
+         firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+         firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+         lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+         lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+         lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+         lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+         lastLevel = MAX2(firstLevel, lastLevel);       /* need at least one level */
+      }
+      break;
+   case GL_TEXTURE_RECTANGLE_NV:
+   case GL_TEXTURE_4D_SGIS:
+      firstLevel = lastLevel = 0;
+      break;
+   default:
+      return;
+   }
+
+   /* save these values */
+   intelObj->firstLevel = firstLevel;
+   intelObj->lastLevel = lastLevel;
+}
+
+static void
+copy_image_data_to_tree(struct intel_context *intel,
+                        struct intel_texture_object *intelObj,
+                        struct intel_texture_image *intelImage)
+{
+   if (intelImage->mt) {
+      /* Copy potentially with the blitter:
+       */
+      intel_miptree_image_copy(intel,
+                               intelObj->mt,
+                               intelImage->face,
+                               intelImage->level, intelImage->mt);
+
+      intel_miptree_release(intel, &intelImage->mt);
+   }
+   else {
+      assert(intelImage->base.Data != NULL);
+
+      /* More straightforward upload.  
+       */
+      intel_miptree_image_data(intel,
+                               intelObj->mt,
+                               intelImage->face,
+                               intelImage->level,
+                               intelImage->base.Data,
+                               intelImage->base.RowStride,
+                               intelImage->base.RowStride *
+                               intelImage->base.Height);
+      _mesa_align_free(intelImage->base.Data);
+      intelImage->base.Data = NULL;
+   }
+
+   intel_miptree_reference(&intelImage->mt, intelObj->mt);
+}
+
+
+/*  
+ */
+GLuint
+intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
+{
+   struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
+   struct intel_texture_object *intelObj = intel_texture_object(tObj);
+
+   GLuint face, i;
+   GLuint nr_faces = 0;
+   struct intel_texture_image *firstImage;
+
+   /* We know/require this is true by now: 
+    */
+   assert(intelObj->base.Complete);
+
+   /* What levels must the tree include at a minimum?
+    */
+   intel_calculate_first_last_level(intelObj);
+   firstImage =
+      intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
+
+   /* Fallback case:
+    */
+   if (firstImage->base.Border) {
+      if (intelObj->mt) {
+         intel_miptree_release(intel, &intelObj->mt);
+      }
+      return GL_FALSE;
+   }
+
+
+   /* If both firstImage and intelObj have a tree which can contain
+    * all active images, favour firstImage.  Note that because of the
+    * completeness requirement, we know that the image dimensions
+    * will match.
+    */
+   if (firstImage->mt &&
+       firstImage->mt != intelObj->mt &&
+       firstImage->mt->first_level <= intelObj->firstLevel &&
+       firstImage->mt->last_level >= intelObj->lastLevel) {
+
+      if (intelObj->mt)
+         intel_miptree_release(intel, &intelObj->mt);
+
+      intel_miptree_reference(&intelObj->mt, firstImage->mt);
+   }
+
+   /* Check tree can hold all active levels.  Check tree matches
+    * target, imageFormat, etc.
+    * 
+    * XXX: For some layouts (eg i945?), the test might have to be
+    * first_level == firstLevel, as the tree isn't valid except at the
+    * original start level.  Hope to get around this by
+    * programming minLod, maxLod, baseLevel into the hardware and
+    * leaving the tree alone.
+    */
+   if (intelObj->mt &&
+       ((intelObj->mt->first_level > intelObj->firstLevel) ||
+        (intelObj->mt->last_level < intelObj->lastLevel) ||
+        (intelObj->mt->internal_format != firstImage->base.InternalFormat))) {
+      intel_miptree_release(intel, &intelObj->mt);
+   }
+
+
+   /* May need to create a new tree:
+    */
+   if (!intelObj->mt) {
+      intelObj->mt = intel_miptree_create(intel,
+                                          intelObj->base.Target,
+                                          firstImage->base.InternalFormat,
+                                          intelObj->firstLevel,
+                                          intelObj->lastLevel,
+                                          firstImage->base.Width,
+                                          firstImage->base.Height,
+                                          firstImage->base.Depth,
+                                          firstImage->base.TexFormat->
+                                          TexelBytes,
+                                          firstImage->base.IsCompressed);
+   }
+
+   /* Pull in any images not in the object's tree:
+    */
+   nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+   for (face = 0; face < nr_faces; face++) {
+      for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
+         struct intel_texture_image *intelImage =
+            intel_texture_image(intelObj->base.Image[face][i]);
+
+         /* Need to import images in main memory or held in other trees.
+          */
+         if (intelObj->mt != intelImage->mt) {
+            copy_image_data_to_tree(intel, intelObj, intelImage);
+         }
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
+
+void
+intel_tex_map_images(struct intel_context *intel,
+                     struct intel_texture_object *intelObj)
+{
+   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+   GLuint face, i;
+
+   DBG("%s\n", __FUNCTION__);
+
+   for (face = 0; face < nr_faces; face++) {
+      for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
+         struct intel_texture_image *intelImage =
+            intel_texture_image(intelObj->base.Image[face][i]);
+
+         if (intelImage->mt) {
+            intelImage->base.Data =
+               intel_miptree_image_map(intel,
+                                       intelImage->mt,
+                                       intelImage->face,
+                                       intelImage->level,
+                                       &intelImage->base.RowStride,
+                                       intelImage->base.ImageOffsets);
+            /* convert stride to texels, not bytes */
+            intelImage->base.RowStride /= intelImage->mt->cpp;
+/*             intelImage->base.ImageStride /= intelImage->mt->cpp; */
+         }
+      }
+   }
+}
+
+
+
+void
+intel_tex_unmap_images(struct intel_context *intel,
+                       struct intel_texture_object *intelObj)
+{
+   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+   GLuint face, i;
+
+   for (face = 0; face < nr_faces; face++) {
+      for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
+         struct intel_texture_image *intelImage =
+            intel_texture_image(intelObj->base.Image[face][i]);
+
+         if (intelImage->mt) {
+            intel_miptree_image_unmap(intel, intelImage->mt);
+            intelImage->base.Data = NULL;
+         }
+      }
+   }
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.c b/src/mesa/drivers/dri/i915tex/intel_tris.c
new file mode 100644 (file)
index 0000000..1ba49d8
--- /dev/null
@@ -0,0 +1,1149 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "enums.h"
+#include "texobj.h"
+#include "state.h"
+#include "dd.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_vertex.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_tris.h"
+#include "intel_batchbuffer.h"
+#include "intel_reg.h"
+#include "intel_span.h"
+#include "intel_tex.h"
+
+static void intelRenderPrimitive(GLcontext * ctx, GLenum prim);
+static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim,
+                                 GLuint hwprim);
+
+/*
+ */
+static void
+intel_flush_inline_primitive(struct intel_context *intel)
+{
+   GLuint used = intel->batch->ptr - intel->prim.start_ptr;
+
+   assert(intel->prim.primitive != ~0);
+
+/*    _mesa_printf("/\n"); */
+
+   if (used < 8)
+      goto do_discard;
+
+   *(int *) intel->prim.start_ptr = (_3DPRIMITIVE |
+                                     intel->prim.primitive | (used / 4 - 2));
+
+   goto finished;
+
+ do_discard:
+   intel->batch->ptr -= used;
+
+ finished:
+   intel->prim.primitive = ~0;
+   intel->prim.start_ptr = 0;
+   intel->prim.flush = 0;
+}
+
+
+/* Emit a primitive referencing vertices in a vertex buffer.
+ */
+void
+intelStartInlinePrimitive(struct intel_context *intel,
+                          GLuint prim, GLuint batch_flags)
+{
+   BATCH_LOCALS;
+
+   intel->vtbl.emit_state(intel);
+
+   /* Need to make sure at the very least that we don't wrap
+    * batchbuffers in BEGIN_BATCH below, otherwise the primitive will
+    * be emitted to a batchbuffer missing the required full-state
+    * preamble.
+    */
+   if (intel_batchbuffer_space(intel->batch) < 100) {
+      intel_batchbuffer_flush(intel->batch);
+      intel->vtbl.emit_state(intel);
+   }
+
+/*    _mesa_printf("%s *", __progname); */
+
+   /* Emit a slot which will be filled with the inline primitive
+    * command later.
+    */
+   BEGIN_BATCH(2, batch_flags);
+   OUT_BATCH(0);
+
+   intel->prim.start_ptr = intel->batch->ptr;
+   intel->prim.primitive = prim;
+   intel->prim.flush = intel_flush_inline_primitive;
+
+   OUT_BATCH(0);
+   ADVANCE_BATCH();
+
+/*    _mesa_printf(">"); */
+}
+
+
+void
+intelWrapInlinePrimitive(struct intel_context *intel)
+{
+   GLuint prim = intel->prim.primitive;
+   GLuint batchflags = intel->batch->flags;
+
+   intel_flush_inline_primitive(intel);
+   intel_batchbuffer_flush(intel->batch);
+   intelStartInlinePrimitive(intel, prim, batchflags);  /* ??? */
+}
+
+GLuint *
+intelExtendInlinePrimitive(struct intel_context *intel, GLuint dwords)
+{
+   GLuint sz = dwords * sizeof(GLuint);
+   GLuint *ptr;
+
+   assert(intel->prim.flush == intel_flush_inline_primitive);
+
+   if (intel_batchbuffer_space(intel->batch) < sz)
+      intelWrapInlinePrimitive(intel);
+
+/*    _mesa_printf("."); */
+
+   intel->vtbl.assert_not_dirty(intel);
+
+   ptr = (GLuint *) intel->batch->ptr;
+   intel->batch->ptr += sz;
+
+   return ptr;
+}
+
+
+
+/***********************************************************************
+ *                    Emit primitives as inline vertices               *
+ ***********************************************************************/
+
+#ifdef __i386__
+#define COPY_DWORDS( j, vb, vertsize, v )                      \
+do {                                                           \
+   int __tmp;                                                  \
+   __asm__ __volatile__( "rep ; movsl"                         \
+                        : "=%c" (j), "=D" (vb), "=S" (__tmp)   \
+                        : "0" (vertsize),                      \
+                        "D" ((long)vb),                        \
+                        "S" ((long)v) );                       \
+} while (0)
+#else
+#define COPY_DWORDS( j, vb, vertsize, v )      \
+do {                                           \
+   for ( j = 0 ; j < vertsize ; j++ ) {                \
+      vb[j] = ((GLuint *)v)[j];                        \
+   }                                           \
+   vb += vertsize;                             \
+} while (0)
+#endif
+
+static void
+intel_draw_quad(struct intel_context *intel,
+                intelVertexPtr v0,
+                intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3)
+{
+   GLuint vertsize = intel->vertex_size;
+   GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize);
+   int j;
+
+   COPY_DWORDS(j, vb, vertsize, v0);
+   COPY_DWORDS(j, vb, vertsize, v1);
+
+   /* If smooth shading, draw like a trifan which gives better
+    * rasterization.  Otherwise draw as two triangles with provoking
+    * vertex in third position as required for flat shading.
+    */
+   if (intel->ctx.Light.ShadeModel == GL_FLAT) {
+      COPY_DWORDS(j, vb, vertsize, v3);
+      COPY_DWORDS(j, vb, vertsize, v1);
+   }
+   else {
+      COPY_DWORDS(j, vb, vertsize, v2);
+      COPY_DWORDS(j, vb, vertsize, v0);
+   }
+
+   COPY_DWORDS(j, vb, vertsize, v2);
+   COPY_DWORDS(j, vb, vertsize, v3);
+}
+
+static void
+intel_draw_triangle(struct intel_context *intel,
+                    intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
+{
+   GLuint vertsize = intel->vertex_size;
+   GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize);
+   int j;
+
+   COPY_DWORDS(j, vb, vertsize, v0);
+   COPY_DWORDS(j, vb, vertsize, v1);
+   COPY_DWORDS(j, vb, vertsize, v2);
+}
+
+
+static void
+intel_draw_line(struct intel_context *intel,
+                intelVertexPtr v0, intelVertexPtr v1)
+{
+   GLuint vertsize = intel->vertex_size;
+   GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize);
+   int j;
+
+   COPY_DWORDS(j, vb, vertsize, v0);
+   COPY_DWORDS(j, vb, vertsize, v1);
+}
+
+
+static void
+intel_draw_point(struct intel_context *intel, intelVertexPtr v0)
+{
+   GLuint vertsize = intel->vertex_size;
+   GLuint *vb = intelExtendInlinePrimitive(intel, vertsize);
+   int j;
+
+   /* Adjust for sub pixel position -- still required for conform. */
+   *(float *) &vb[0] = v0->v.x - 0.125;
+   *(float *) &vb[1] = v0->v.y - 0.125;
+   for (j = 2; j < vertsize; j++)
+      vb[j] = v0->ui[j];
+}
+
+
+
+/***********************************************************************
+ *                Fixup for ARB_point_parameters                       *
+ ***********************************************************************/
+
+/* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly
+ * represented in the fragment program InputsRead field.
+ */
+static void
+intel_atten_point(struct intel_context *intel, intelVertexPtr v0)
+{
+   GLcontext *ctx = &intel->ctx;
+   GLfloat psz[4], col[4], restore_psz, restore_alpha;
+
+   _tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
+   _tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
+
+   restore_psz = psz[0];
+   restore_alpha = col[3];
+
+   if (psz[0] >= ctx->Point.Threshold) {
+      psz[0] = MIN2(psz[0], ctx->Point.MaxSize);
+   }
+   else {
+      GLfloat dsize = psz[0] / ctx->Point.Threshold;
+      psz[0] = MAX2(ctx->Point.Threshold, ctx->Point.MinSize);
+      col[3] *= dsize * dsize;
+   }
+
+   if (psz[0] < 1.0)
+      psz[0] = 1.0;
+
+   if (restore_psz != psz[0] || restore_alpha != col[3]) {
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
+
+      intel_draw_point(intel, v0);
+
+      psz[0] = restore_psz;
+      col[3] = restore_alpha;
+
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
+      _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
+   }
+   else
+      intel_draw_point(intel, v0);
+}
+
+
+
+
+
+/***********************************************************************
+ *                Fixup for I915 WPOS texture coordinate                *
+ ***********************************************************************/
+
+
+
+static void
+intel_wpos_triangle(struct intel_context *intel,
+                    intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
+{
+   GLuint offset = intel->wpos_offset;
+   GLuint size = intel->wpos_size;
+
+   __memcpy(((char *) v0) + offset, v0, size);
+   __memcpy(((char *) v1) + offset, v1, size);
+   __memcpy(((char *) v2) + offset, v2, size);
+
+   intel_draw_triangle(intel, v0, v1, v2);
+}
+
+
+static void
+intel_wpos_line(struct intel_context *intel,
+                intelVertexPtr v0, intelVertexPtr v1)
+{
+   GLuint offset = intel->wpos_offset;
+   GLuint size = intel->wpos_size;
+
+   __memcpy(((char *) v0) + offset, v0, size);
+   __memcpy(((char *) v1) + offset, v1, size);
+
+   intel_draw_line(intel, v0, v1);
+}
+
+
+static void
+intel_wpos_point(struct intel_context *intel, intelVertexPtr v0)
+{
+   GLuint offset = intel->wpos_offset;
+   GLuint size = intel->wpos_size;
+
+   __memcpy(((char *) v0) + offset, v0, size);
+
+   intel_draw_point(intel, v0);
+}
+
+
+
+
+
+
+/***********************************************************************
+ *          Macros for t_dd_tritmp.h to draw basic primitives          *
+ ***********************************************************************/
+
+#define TRI( a, b, c )                         \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      intel->draw_tri( intel, a, b, c );       \
+   else                                                \
+      intel_draw_triangle( intel, a, b, c );   \
+} while (0)
+
+#define QUAD( a, b, c, d )                     \
+do {                                           \
+   if (DO_FALLBACK) {                          \
+      intel->draw_tri( intel, a, b, d );       \
+      intel->draw_tri( intel, b, c, d );       \
+   } else                                      \
+      intel_draw_quad( intel, a, b, c, d );    \
+} while (0)
+
+#define LINE( v0, v1 )                         \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      intel->draw_line( intel, v0, v1 );       \
+   else                                                \
+      intel_draw_line( intel, v0, v1 );                \
+} while (0)
+
+#define POINT( v0 )                            \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      intel->draw_point( intel, v0 );          \
+   else                                                \
+      intel_draw_point( intel, v0 );           \
+} while (0)
+
+
+/***********************************************************************
+ *              Build render functions from dd templates               *
+ ***********************************************************************/
+
+#define INTEL_OFFSET_BIT       0x01
+#define INTEL_TWOSIDE_BIT      0x02
+#define INTEL_UNFILLED_BIT     0x04
+#define INTEL_FALLBACK_BIT     0x08
+#define INTEL_MAX_TRIFUNC      0x10
+
+
+static struct
+{
+   tnl_points_func points;
+   tnl_line_func line;
+   tnl_triangle_func triangle;
+   tnl_quad_func quad;
+} rast_tab[INTEL_MAX_TRIFUNC];
+
+
+#define DO_FALLBACK (IND & INTEL_FALLBACK_BIT)
+#define DO_OFFSET   (IND & INTEL_OFFSET_BIT)
+#define DO_UNFILLED (IND & INTEL_UNFILLED_BIT)
+#define DO_TWOSIDE  (IND & INTEL_TWOSIDE_BIT)
+#define DO_FLAT      0
+#define DO_TRI       1
+#define DO_QUAD      1
+#define DO_LINE      1
+#define DO_POINTS    1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA         1
+#define HAVE_SPEC         1
+#define HAVE_BACK_COLORS  0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX            intelVertex
+#define TAB               rast_tab
+
+/* Only used to pull back colors into vertices (ie, we know color is
+ * floating point).
+ */
+#define INTEL_COLOR( dst, src )                                \
+do {                                                   \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]);       \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]);       \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]);       \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]);       \
+} while (0)
+
+#define INTEL_SPEC( dst, src )                         \
+do {                                                   \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]);       \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]);       \
+   UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]);       \
+} while (0)
+
+
+#define DEPTH_SCALE intel->polygon_offset_scale
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW( a ) (a > 0)
+#define GET_VERTEX(e) (intel->verts + (e * intel->vertex_size * sizeof(GLuint)))
+
+#define VERT_SET_RGBA( v, c )    if (coloroffset) INTEL_COLOR( v->ub4[coloroffset], c )
+#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset]
+#define VERT_SAVE_RGBA( idx )    if (coloroffset) color[idx] = v[idx]->ui[coloroffset]
+#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx]
+
+#define VERT_SET_SPEC( v, c )    if (specoffset) INTEL_SPEC( v->ub4[specoffset], c )
+#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
+#define VERT_SAVE_SPEC( idx )    if (specoffset) spec[idx] = v[idx]->ui[specoffset]
+#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
+
+#define LOCAL_VARS(n)                                                  \
+   struct intel_context *intel = intel_context(ctx);                           \
+   GLuint color[n], spec[n];                                           \
+   GLuint coloroffset = intel->coloroffset;            \
+   GLboolean specoffset = intel->specoffset;                   \
+   (void) color; (void) spec; (void) coloroffset; (void) specoffset;
+
+
+/***********************************************************************
+ *                Helpers for rendering unfilled primitives            *
+ ***********************************************************************/
+
+static const GLuint hw_prim[GL_POLYGON + 1] = {
+   PRIM3D_POINTLIST,
+   PRIM3D_LINELIST,
+   PRIM3D_LINELIST,
+   PRIM3D_LINELIST,
+   PRIM3D_TRILIST,
+   PRIM3D_TRILIST,
+   PRIM3D_TRILIST,
+   PRIM3D_TRILIST,
+   PRIM3D_TRILIST,
+   PRIM3D_TRILIST
+};
+
+#define RASTERIZE(x) intelRasterPrimitive( ctx, x, hw_prim[x] )
+#define RENDER_PRIMITIVE intel->render_primitive
+#define TAG(x) x
+#define IND INTEL_FALLBACK_BIT
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+/***********************************************************************
+ *                      Generate GL render functions                   *
+ ***********************************************************************/
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT| \
+            INTEL_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void
+init_rast_tab(void)
+{
+   init();
+   init_offset();
+   init_twoside();
+   init_twoside_offset();
+   init_unfilled();
+   init_offset_unfilled();
+   init_twoside_unfilled();
+   init_twoside_offset_unfilled();
+   init_fallback();
+   init_offset_fallback();
+   init_twoside_fallback();
+   init_twoside_offset_fallback();
+   init_unfilled_fallback();
+   init_offset_unfilled_fallback();
+   init_twoside_unfilled_fallback();
+   init_twoside_offset_unfilled_fallback();
+}
+
+
+/***********************************************************************
+ *                    Rasterization fallback helpers                   *
+ ***********************************************************************/
+
+
+/* This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+static void
+intel_fallback_tri(struct intel_context *intel,
+                   intelVertex * v0, intelVertex * v1, intelVertex * v2)
+{
+   GLcontext *ctx = &intel->ctx;
+   SWvertex v[3];
+
+   if (0)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   INTEL_FIREVERTICES(intel);
+
+   _swsetup_Translate(ctx, v0, &v[0]);
+   _swsetup_Translate(ctx, v1, &v[1]);
+   _swsetup_Translate(ctx, v2, &v[2]);
+   intelSpanRenderStart(ctx);
+   _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
+   intelSpanRenderFinish(ctx);
+}
+
+
+static void
+intel_fallback_line(struct intel_context *intel,
+                    intelVertex * v0, intelVertex * v1)
+{
+   GLcontext *ctx = &intel->ctx;
+   SWvertex v[2];
+
+   if (0)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   INTEL_FIREVERTICES(intel);
+
+   _swsetup_Translate(ctx, v0, &v[0]);
+   _swsetup_Translate(ctx, v1, &v[1]);
+   intelSpanRenderStart(ctx);
+   _swrast_Line(ctx, &v[0], &v[1]);
+   intelSpanRenderFinish(ctx);
+}
+
+static void
+intel_fallback_point(struct intel_context *intel,
+                    intelVertex * v0)
+{
+   GLcontext *ctx = &intel->ctx;
+   SWvertex v[1];
+
+   if (0)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   INTEL_FIREVERTICES(intel);
+
+   _swsetup_Translate(ctx, v0, &v[0]);
+   intelSpanRenderStart(ctx);
+   _swrast_Point(ctx, &v[0]);
+   intelSpanRenderFinish(ctx);
+}
+
+
+/**********************************************************************/
+/*               Render unclipped begin/end objects                   */
+/**********************************************************************/
+
+#define IND 0
+#define V(x) (intelVertex *)(vertptr + ((x)*vertsize*sizeof(GLuint)))
+#define RENDER_POINTS( start, count )  \
+   for ( ; start < count ; start++) POINT( V(ELT(start)) );
+#define RENDER_LINE( v0, v1 )         LINE( V(v0), V(v1) )
+#define RENDER_TRI(  v0, v1, v2 )     TRI(  V(v0), V(v1), V(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
+#define INIT(x) intelRenderPrimitive( ctx, x )
+#undef LOCAL_VARS
+#define LOCAL_VARS                                             \
+    struct intel_context *intel = intel_context(ctx);                  \
+    GLubyte *vertptr = (GLubyte *)intel->verts;                        \
+    const GLuint vertsize = intel->vertex_size;        \
+    const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;      \
+    (void) elt;
+#define RESET_STIPPLE
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) x
+#define TAG(x) intel_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) intel_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+/**********************************************************************/
+/*                   Render clipped primitives                        */
+/**********************************************************************/
+
+
+
+static void
+intelRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n)
+{
+   struct intel_context *intel = intel_context(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLuint prim = intel->render_primitive;
+
+   /* Render the new vertices as an unclipped polygon.
+    */
+   {
+      GLuint *tmp = VB->Elts;
+      VB->Elts = (GLuint *) elts;
+      tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n,
+                                                  PRIM_BEGIN | PRIM_END);
+      VB->Elts = tmp;
+   }
+
+   /* Restore the render primitive
+    */
+   if (prim != GL_POLYGON)
+      tnl->Driver.Render.PrimitiveNotify(ctx, prim);
+}
+
+static void
+intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   tnl->Driver.Render.Line(ctx, ii, jj);
+}
+
+static void
+intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n)
+{
+   struct intel_context *intel = intel_context(ctx);
+   const GLuint vertsize = intel->vertex_size;
+   GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize);
+   GLubyte *vertptr = (GLubyte *) intel->verts;
+   const GLuint *start = (const GLuint *) V(elts[0]);
+   int i, j;
+
+   for (i = 2; i < n; i++) {
+      COPY_DWORDS(j, vb, vertsize, V(elts[i - 1]));
+      COPY_DWORDS(j, vb, vertsize, V(elts[i]));
+      COPY_DWORDS(j, vb, vertsize, start);
+   }
+}
+
+/**********************************************************************/
+/*                    Choose render functions                         */
+/**********************************************************************/
+
+
+
+
+#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN | DD_POINT_SMOOTH | DD_TRI_SMOOTH)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
+
+void
+intelChooseRenderState(GLcontext * ctx)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct intel_context *intel = intel_context(ctx);
+   GLuint flags = ctx->_TriangleCaps;
+   const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
+   GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
+   GLuint index = 0;
+
+   if (INTEL_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) {
+
+      if (flags & ANY_RASTER_FLAGS) {
+         if (flags & DD_TRI_LIGHT_TWOSIDE)
+            index |= INTEL_TWOSIDE_BIT;
+         if (flags & DD_TRI_OFFSET)
+            index |= INTEL_OFFSET_BIT;
+         if (flags & DD_TRI_UNFILLED)
+            index |= INTEL_UNFILLED_BIT;
+      }
+
+      if (have_wpos) {
+         intel->draw_point = intel_wpos_point;
+         intel->draw_line = intel_wpos_line;
+         intel->draw_tri = intel_wpos_triangle;
+
+         /* Make sure these get called:
+          */
+         index |= INTEL_FALLBACK_BIT;
+      }
+      else {
+         intel->draw_point = intel_draw_point;
+         intel->draw_line = intel_draw_line;
+         intel->draw_tri = intel_draw_triangle;
+      }
+
+      /* Hook in fallbacks for specific primitives.
+       */
+      if (flags & ANY_FALLBACK_FLAGS) {
+         if (flags & DD_LINE_STIPPLE)
+            intel->draw_line = intel_fallback_line;
+
+         if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
+            intel->draw_tri = intel_fallback_tri;
+
+         if (flags & DD_TRI_SMOOTH) {
+           if (intel->strict_conformance)
+              intel->draw_tri = intel_fallback_tri;
+        }
+
+         if (flags & DD_POINT_ATTEN) {
+           if (0)
+              intel->draw_point = intel_atten_point;
+           else
+              intel->draw_point = intel_fallback_point;
+        }
+
+        if (flags & DD_POINT_SMOOTH) {
+           if (intel->strict_conformance)
+              intel->draw_point = intel_fallback_point;
+        }
+
+         index |= INTEL_FALLBACK_BIT;
+      }
+   }
+
+   if (intel->RenderIndex != index) {
+      intel->RenderIndex = index;
+
+      tnl->Driver.Render.Points = rast_tab[index].points;
+      tnl->Driver.Render.Line = rast_tab[index].line;
+      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+      tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+      if (index == 0) {
+         tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts;
+         tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
+         tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
+         tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
+      }
+      else {
+         tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+         tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+         tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
+         tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly;
+      }
+   }
+}
+
+static const GLenum reduced_prim[GL_POLYGON + 1] = {
+   GL_POINTS,
+   GL_LINES,
+   GL_LINES,
+   GL_LINES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES
+};
+
+
+/**********************************************************************/
+/*                 High level hooks for t_vb_render.c                 */
+/**********************************************************************/
+
+
+
+
+static void
+intelRunPipeline(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   _mesa_lock_context_textures(ctx);
+   
+   if (ctx->NewState)
+      _mesa_update_state_locked(ctx);
+
+   if (intel->NewGLState) {
+      if (intel->NewGLState & _NEW_TEXTURE) {
+         intel->vtbl.update_texture_state(intel);
+      }
+
+      if (!intel->Fallback) {
+         if (intel->NewGLState & _INTEL_NEW_RENDERSTATE)
+            intelChooseRenderState(ctx);
+      }
+
+      intel->NewGLState = 0;
+   }
+
+   _tnl_run_pipeline(ctx);
+
+   _mesa_unlock_context_textures(ctx);
+}
+
+static void
+intelRenderStart(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   intel->vtbl.render_start(intel_context(ctx));
+   intel->vtbl.emit_state(intel);
+}
+
+static void
+intelRenderFinish(GLcontext * ctx)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   if (intel->RenderIndex & INTEL_FALLBACK_BIT)
+      _swrast_flush(ctx);
+
+   INTEL_FIREVERTICES(intel);
+}
+
+
+
+
+ /* System to flush dma and emit state changes based on the rasterized
+  * primitive.
+  */
+static void
+intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   if (0)
+      fprintf(stderr, "%s %s %x\n", __FUNCTION__,
+              _mesa_lookup_enum_by_nr(rprim), hwprim);
+
+   intel->vtbl.reduced_primitive_state(intel, rprim);
+
+   /* Start a new primitive.  Arrange to have it flushed later on.
+    */
+   if (hwprim != intel->prim.primitive) {
+      INTEL_FIREVERTICES(intel);
+
+      intelStartInlinePrimitive(intel, hwprim, INTEL_BATCH_CLIPRECTS);
+   }
+}
+
+
+ /* 
+  */
+static void
+intelRenderPrimitive(GLcontext * ctx, GLenum prim)
+{
+   struct intel_context *intel = intel_context(ctx);
+
+   if (0)
+      fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
+
+   /* Let some clipping routines know which primitive they're dealing
+    * with.
+    */
+   intel->render_primitive = prim;
+
+   /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
+    * triangles.  The rasterized primitive will always be reset by
+    * lower level functions in that case, potentially pingponging the
+    * state:
+    */
+   if (reduced_prim[prim] == GL_TRIANGLES &&
+       (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+      return;
+
+   /* Set some primitive-dependent state and Start? a new primitive.
+    */
+   intelRasterPrimitive(ctx, reduced_prim[prim], hw_prim[prim]);
+}
+
+
+ /**********************************************************************/
+ /*           Transition to/from hardware rasterization.               */
+ /**********************************************************************/
+
+static char *fallbackStrings[] = {
+   [0] = "Draw buffer",
+   [1] = "Read buffer",
+   [2] = "Depth buffer",
+   [3] = "Stencil buffer",
+   [4] = "User disable",
+   [5] = "Render mode",
+
+   [12] = "Texture",
+   [13] = "Color mask",
+   [14] = "Stencil",
+   [15] = "Stipple",
+   [16] = "Program",
+   [17] = "Logic op",
+   [18] = "Smooth polygon",
+   [19] = "Smooth point",
+};
+
+
+static char *
+getFallbackString(GLuint bit)
+{
+   int i = 0;
+   while (bit > 1) {
+      i++;
+      bit >>= 1;
+   }
+   return fallbackStrings[i];
+}
+
+
+
+void
+intelFallback(struct intel_context *intel, GLuint bit, GLboolean mode)
+{
+   GLcontext *ctx = &intel->ctx;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint oldfallback = intel->Fallback;
+
+   if (mode) {
+      intel->Fallback |= bit;
+      if (oldfallback == 0) {
+         intelFlush(ctx);
+         if (INTEL_DEBUG & DEBUG_FALLBACKS)
+            fprintf(stderr, "ENTER FALLBACK %x: %s\n",
+                    bit, getFallbackString(bit));
+         _swsetup_Wakeup(ctx);
+         intel->RenderIndex = ~0;
+      }
+   }
+   else {
+      intel->Fallback &= ~bit;
+      if (oldfallback == bit) {
+         _swrast_flush(ctx);
+         if (INTEL_DEBUG & DEBUG_FALLBACKS)
+            fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit));
+         tnl->Driver.Render.Start = intelRenderStart;
+         tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
+         tnl->Driver.Render.Finish = intelRenderFinish;
+         tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+         tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+         tnl->Driver.Render.Interp = _tnl_interp;
+
+         _tnl_invalidate_vertex_state(ctx, ~0);
+         _tnl_invalidate_vertices(ctx, ~0);
+         _tnl_install_attrs(ctx,
+                            intel->vertex_attrs,
+                            intel->vertex_attr_count,
+                            intel->ViewportMatrix.m, 0);
+
+         intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
+      }
+   }
+}
+
+union fi
+{
+   GLfloat f;
+   GLint i;
+};
+
+
+/**********************************************************************/
+/*             Used only with the metaops callbacks.                  */
+/**********************************************************************/
+void
+intel_meta_draw_poly(struct intel_context *intel,
+                     GLuint n,
+                     GLfloat xy[][2],
+                     GLfloat z, GLuint color, GLfloat tex[][2])
+{
+   union fi *vb;
+   GLint i;
+
+   /* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS,
+    * otherwise the drawing origin (DR4) might not be set correctly.
+    */
+   intelStartInlinePrimitive(intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS);
+   vb = (union fi *) intelExtendInlinePrimitive(intel, n * 6);
+
+   for (i = 0; i < n; i++) {
+      vb[0].f = xy[i][0];
+      vb[1].f = xy[i][1];
+      vb[2].f = z;
+      vb[3].i = color;
+      vb[4].f = tex[i][0];
+      vb[5].f = tex[i][1];
+      vb += 6;
+   }
+
+   INTEL_FIREVERTICES(intel);
+}
+
+void
+intel_meta_draw_quad(struct intel_context *intel,
+                     GLfloat x0, GLfloat x1,
+                     GLfloat y0, GLfloat y1,
+                     GLfloat z,
+                     GLuint color,
+                     GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1)
+{
+   GLfloat xy[4][2];
+   GLfloat tex[4][2];
+
+   xy[0][0] = x0;
+   xy[0][1] = y0;
+   xy[1][0] = x1;
+   xy[1][1] = y0;
+   xy[2][0] = x1;
+   xy[2][1] = y1;
+   xy[3][0] = x0;
+   xy[3][1] = y1;
+
+   tex[0][0] = s0;
+   tex[0][1] = t0;
+   tex[1][0] = s1;
+   tex[1][1] = t0;
+   tex[2][0] = s1;
+   tex[2][1] = t1;
+   tex[3][0] = s0;
+   tex[3][1] = t1;
+
+   intel_meta_draw_poly(intel, 4, xy, z, color, tex);
+}
+
+
+
+/**********************************************************************/
+/*                            Initialization.                         */
+/**********************************************************************/
+
+
+void
+intelInitTriFuncs(GLcontext * ctx)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   static int firsttime = 1;
+
+   if (firsttime) {
+      init_rast_tab();
+      firsttime = 0;
+   }
+
+   tnl->Driver.RunPipeline = intelRunPipeline;
+   tnl->Driver.Render.Start = intelRenderStart;
+   tnl->Driver.Render.Finish = intelRenderFinish;
+   tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
+   tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+   tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
+   tnl->Driver.Render.CopyPV = _tnl_copy_pv;
+   tnl->Driver.Render.Interp = _tnl_interp;
+}
diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.h b/src/mesa/drivers/dri/i915tex/intel_tris.h
new file mode 100644 (file)
index 0000000..b7bae8c
--- /dev/null
@@ -0,0 +1,69 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#ifndef INTELTRIS_INC
+#define INTELTRIS_INC
+
+#include "mtypes.h"
+
+
+
+#define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |         \
+                              _DD_NEW_TRI_UNFILLED |           \
+                              _DD_NEW_TRI_LIGHT_TWOSIDE |      \
+                              _DD_NEW_TRI_OFFSET |             \
+                              _DD_NEW_TRI_STIPPLE |            \
+                              _NEW_PROGRAM |           \
+                              _NEW_POLYGONSTIPPLE)
+
+extern void intelInitTriFuncs(GLcontext * ctx);
+
+extern void intelChooseRenderState(GLcontext * ctx);
+
+extern void intelStartInlinePrimitive(struct intel_context *intel,
+                                      GLuint prim, GLuint flags);
+extern void intelWrapInlinePrimitive(struct intel_context *intel);
+
+GLuint *intelExtendInlinePrimitive(struct intel_context *intel,
+                                   GLuint dwords);
+
+
+void intel_meta_draw_quad(struct intel_context *intel,
+                          GLfloat x0, GLfloat x1,
+                          GLfloat y0, GLfloat y1,
+                          GLfloat z,
+                          GLuint color,
+                          GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1);
+
+void intel_meta_draw_poly(struct intel_context *intel,
+                          GLuint n,
+                          GLfloat xy[][2],
+                          GLfloat z, GLuint color, GLfloat tex[][2]);
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/server/i830_common.h b/src/mesa/drivers/dri/i915tex/server/i830_common.h
new file mode 100644 (file)
index 0000000..fb6ceaa
--- /dev/null
@@ -0,0 +1,212 @@
+/**************************************************************************
+
+Copyright 2001 VA Linux Systems Inc., Fremont, California.
+Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.1 2002/09/11 00:29:32 dawes Exp $ */
+
+#ifndef _I830_COMMON_H_
+#define _I830_COMMON_H_
+
+
+#define I830_NR_TEX_REGIONS 255        /* maximum due to use of chars for next/prev */
+#define I830_LOG_MIN_TEX_REGION_SIZE 14
+
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_I830_INIT                     0x00
+#define DRM_I830_FLUSH                    0x01
+#define DRM_I830_FLIP                     0x02
+#define DRM_I830_BATCHBUFFER              0x03
+#define DRM_I830_IRQ_EMIT                 0x04
+#define DRM_I830_IRQ_WAIT                 0x05
+#define DRM_I830_GETPARAM                 0x06
+#define DRM_I830_SETPARAM                 0x07
+#define DRM_I830_ALLOC                    0x08
+#define DRM_I830_FREE                     0x09
+#define DRM_I830_INIT_HEAP                0x0a
+#define DRM_I830_CMDBUFFER                0x0b
+#define DRM_I830_DESTROY_HEAP             0x0c
+
+typedef struct {
+   enum {
+      I830_INIT_DMA = 0x01,
+      I830_CLEANUP_DMA = 0x02,
+      I830_RESUME_DMA = 0x03
+   } func;
+   unsigned int mmio_offset;
+   int sarea_priv_offset;
+   unsigned int ring_start;
+   unsigned int ring_end;
+   unsigned int ring_size;
+   unsigned int front_offset;
+   unsigned int back_offset;
+   unsigned int depth_offset;
+   unsigned int w;
+   unsigned int h;
+   unsigned int pitch;
+   unsigned int pitch_bits;
+   unsigned int back_pitch;
+   unsigned int depth_pitch;
+   unsigned int cpp;
+   unsigned int chipset;
+} drmI830Init;
+
+typedef struct {
+       drmTextureRegion texList[I830_NR_TEX_REGIONS+1];
+        int last_upload;       /* last time texture was uploaded */
+        int last_enqueue;      /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int ctxOwner;           /* last context to upload state */
+       int texAge;
+        int pf_enabled;                /* is pageflipping allowed? */
+        int pf_active;               
+        int pf_current_page;   /* which buffer is being displayed? */
+        int perf_boxes;                /* performance boxes to be displayed */   
+       int width, height;      /* screen size in pixels */
+
+       drm_handle_t front_handle;
+       int front_offset;
+       int front_size;
+
+       drm_handle_t back_handle;
+       int back_offset;
+       int back_size;
+
+       drm_handle_t depth_handle;
+       int depth_offset;
+       int depth_size;
+
+       drm_handle_t tex_handle;
+       int tex_offset;
+       int tex_size;
+       int log_tex_granularity;
+       int pitch;
+       int rotation;           /* 0, 90, 180 or 270 */
+       int rotated_offset;
+       int rotated_size;
+       int rotated_pitch;
+       int virtualX, virtualY;
+
+       unsigned int front_tiled;
+       unsigned int back_tiled;
+       unsigned int depth_tiled;
+       unsigned int rotated_tiled;
+       unsigned int rotated2_tiled;
+
+       int pipeA_x;
+       int pipeA_y;
+       int pipeA_w;
+       int pipeA_h;
+       int pipeB_x;
+       int pipeB_y;
+       int pipeB_w;
+       int pipeB_h;
+} drmI830Sarea;
+
+/* Flags for perf_boxes
+ */
+#define I830_BOX_RING_EMPTY    0x1 /* populated by kernel */
+#define I830_BOX_FLIP          0x2 /* populated by kernel */
+#define I830_BOX_WAIT          0x4 /* populated by kernel & client */
+#define I830_BOX_TEXTURE_LOAD  0x8 /* populated by kernel */
+#define I830_BOX_LOST_CONTEXT  0x10 /* populated by client */
+
+
+typedef struct {
+       int start;              /* agp offset */
+       int used;               /* nr bytes in use */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+        int DR4;               /* window origin for GFX_OP_DRAWRECT_INFO*/
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+        drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */
+} drmI830BatchBuffer;
+
+typedef struct {
+       char *buf;              /* agp offset */
+       int sz;                 /* nr bytes in use */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+        int DR4;               /* window origin for GFX_OP_DRAWRECT_INFO*/
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+        drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */
+} drmI830CmdBuffer;
+typedef struct {
+       int *irq_seq;
+} drmI830IrqEmit;
+
+typedef struct {
+       int irq_seq;
+} drmI830IrqWait;
+
+typedef struct {
+       int param;
+       int *value;
+} drmI830GetParam;
+
+#define I830_PARAM_IRQ_ACTIVE     1
+#define I830_PARAM_ALLOW_BATCHBUFFER   2 
+
+typedef struct {
+       int param;
+       int value;
+} drmI830SetParam;
+
+#define I830_SETPARAM_USE_MI_BATCHBUFFER_START  1
+#define I830_SETPARAM_TEX_LRU_LOG_GRANULARITY   2
+#define I830_SETPARAM_ALLOW_BATCHBUFFER         3
+
+
+/* A memory manager for regions of shared memory:
+ */
+#define I830_MEM_REGION_AGP 1
+
+typedef struct {
+       int region;
+       int alignment;
+       int size;
+       int *region_offset;     /* offset from start of fb or agp */
+} drmI830MemAlloc;
+
+typedef struct {
+       int region;
+       int region_offset;
+} drmI830MemFree;
+
+typedef struct {
+       int region;
+       int size;
+       int start;      
+} drmI830MemInitHeap;
+
+typedef struct {
+       int region;
+} drmI830MemDestroyHeap;
+
+
+#endif /* _I830_DRM_H_ */
diff --git a/src/mesa/drivers/dri/i915tex/server/i830_dri.h b/src/mesa/drivers/dri/i915tex/server/i830_dri.h
new file mode 100644 (file)
index 0000000..6c9a709
--- /dev/null
@@ -0,0 +1,73 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.h,v 1.4 2002/10/30 12:52:18 alanh Exp $ */
+
+#ifndef _I830_DRI_H
+#define _I830_DRI_H
+
+#include "xf86drm.h"
+#include "i830_common.h"
+
+#define I830_MAX_DRAWABLES 256
+
+#define I830_MAJOR_VERSION 1
+#define I830_MINOR_VERSION 3
+#define I830_PATCHLEVEL 0
+
+#define I830_REG_SIZE 0x80000
+
+typedef struct _I830DRIRec {
+   drm_handle_t regs;
+   drmSize regsSize;
+
+   drmSize backbufferSize;
+   drm_handle_t backbuffer;
+
+   drmSize depthbufferSize;
+   drm_handle_t depthbuffer;
+
+   drmSize rotatedSize;
+   drm_handle_t rotatedbuffer;
+
+   drm_handle_t textures;
+   int textureSize;
+
+   drm_handle_t agp_buffers;
+   drmSize agp_buf_size;
+
+   int deviceID;
+   int width;
+   int height;
+   int mem;
+   int cpp;
+   int bitsPerPixel;
+
+   int fbOffset;
+   int fbStride;
+
+   int backOffset;
+   int backPitch;
+
+   int depthOffset;
+   int depthPitch;
+
+   int rotatedOffset;
+   int rotatedPitch;
+
+   int logTextureGranularity;
+   int textureOffset;
+
+   int irq;
+   int sarea_priv_offset;
+} I830DRIRec, *I830DRIPtr;
+
+typedef struct {
+   /* Nothing here yet */
+   int dummy;
+} I830ConfigPrivRec, *I830ConfigPrivPtr;
+
+typedef struct {
+   /* Nothing here yet */
+   int dummy;
+} I830DRIContextRec, *I830DRIContextPtr;
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/server/intel.h b/src/mesa/drivers/dri/i915tex/server/intel.h
new file mode 100644 (file)
index 0000000..d7858a2
--- /dev/null
@@ -0,0 +1,328 @@
+#ifndef _INTEL_H_
+#define _INTEL_H_
+
+#include "xf86drm.h"           /* drm_handle_t, etc */
+
+/* Intel */
+#ifndef PCI_CHIP_I810
+#define PCI_CHIP_I810              0x7121
+#define PCI_CHIP_I810_DC100        0x7123
+#define PCI_CHIP_I810_E            0x7125
+#define PCI_CHIP_I815              0x1132
+#define PCI_CHIP_I810_BRIDGE       0x7120
+#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
+#define PCI_CHIP_I810_E_BRIDGE     0x7124
+#define PCI_CHIP_I815_BRIDGE       0x1130
+#endif
+
+#define PCI_CHIP_845_G                 0x2562
+#define PCI_CHIP_I830_M                        0x3577
+
+#ifndef PCI_CHIP_I855_GM
+#define PCI_CHIP_I855_GM          0x3582
+#define PCI_CHIP_I855_GM_BRIDGE           0x3580
+#endif
+
+#ifndef PCI_CHIP_I865_G
+#define PCI_CHIP_I865_G                   0x2572
+#define PCI_CHIP_I865_G_BRIDGE    0x2570
+#endif
+
+#ifndef PCI_CHIP_I915_G
+#define PCI_CHIP_I915_G                   0x2582
+#define PCI_CHIP_I915_G_BRIDGE    0x2580
+#endif
+
+#ifndef PCI_CHIP_I915_GM
+#define PCI_CHIP_I915_GM          0x2592
+#define PCI_CHIP_I915_GM_BRIDGE           0x2590
+#endif
+
+#ifndef PCI_CHIP_E7221_G
+#define PCI_CHIP_E7221_G          0x258A
+/* Same as I915_G_BRIDGE */
+#define PCI_CHIP_E7221_G_BRIDGE           0x2580
+#endif
+
+#ifndef PCI_CHIP_I945_G
+#define PCI_CHIP_I945_G        0x2772
+#define PCI_CHIP_I945_G_BRIDGE 0x2770
+#endif
+
+#ifndef PCI_CHIP_I945_GM
+#define PCI_CHIP_I945_GM        0x27A2
+#define PCI_CHIP_I945_GM_BRIDGE 0x27A0
+#endif
+
+#define IS_I810(pI810) (pI810->Chipset == PCI_CHIP_I810 ||     \
+                       pI810->Chipset == PCI_CHIP_I810_DC100 || \
+                       pI810->Chipset == PCI_CHIP_I810_E)
+#define IS_I815(pI810) (pI810->Chipset == PCI_CHIP_I815)
+#define IS_I830(pI810) (pI810->Chipset == PCI_CHIP_I830_M)
+#define IS_845G(pI810) (pI810->Chipset == PCI_CHIP_845_G)
+#define IS_I85X(pI810)  (pI810->Chipset == PCI_CHIP_I855_GM)
+#define IS_I852(pI810)  (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
+#define IS_I855(pI810)  (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
+#define IS_I865G(pI810) (pI810->Chipset == PCI_CHIP_I865_G)
+
+#define IS_I915G(pI810) (pI810->Chipset == PCI_CHIP_I915_G || pI810->Chipset == PCI_CHIP_E7221_G)
+#define IS_I915GM(pI810) (pI810->Chipset == PCI_CHIP_I915_GM)
+#define IS_I945G(pI810) (pI810->Chipset == PCI_CHIP_I945_G)
+#define IS_I945GM(pI810) (pI810->Chipset == PCI_CHIP_I945_GM)
+#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810))
+
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
+
+#define I830_GMCH_CTRL         0x52
+
+
+#define I830_GMCH_GMS_MASK                     0x70
+#define I830_GMCH_GMS_DISABLED         0x00
+#define I830_GMCH_GMS_LOCAL                    0x10
+#define I830_GMCH_GMS_STOLEN_512       0x20
+#define I830_GMCH_GMS_STOLEN_1024      0x30
+#define I830_GMCH_GMS_STOLEN_8192      0x40
+
+#define I855_GMCH_GMS_MASK                     (0x7 << 4)
+#define I855_GMCH_GMS_DISABLED                 0x00
+#define I855_GMCH_GMS_STOLEN_1M                        (0x1 << 4)
+#define I855_GMCH_GMS_STOLEN_4M                        (0x2 << 4)
+#define I855_GMCH_GMS_STOLEN_8M                        (0x3 << 4)
+#define I855_GMCH_GMS_STOLEN_16M               (0x4 << 4)
+#define I855_GMCH_GMS_STOLEN_32M               (0x5 << 4)
+#define I915G_GMCH_GMS_STOLEN_48M              (0x6 << 4)
+#define I915G_GMCH_GMS_STOLEN_64M              (0x7 << 4)
+
+typedef unsigned char Bool;
+#define TRUE 1
+#define FALSE 0
+
+#define PIPE_NONE      0<<0
+#define PIPE_CRT       1<<0
+#define PIPE_TV                1<<1
+#define PIPE_DFP       1<<2
+#define PIPE_LFP       1<<3
+#define PIPE_CRT2      1<<4
+#define PIPE_TV2       1<<5
+#define PIPE_DFP2      1<<6
+#define PIPE_LFP2      1<<7
+
+typedef struct _I830MemPool *I830MemPoolPtr;
+typedef struct _I830MemRange *I830MemRangePtr;
+typedef struct _I830MemRange {
+   long Start;
+   long End;
+   long Size;
+   unsigned long Physical;
+   unsigned long Offset;               /* Offset of AGP-allocated portion */
+   unsigned long Alignment;
+   drm_handle_t Key;
+   unsigned long Pitch; // add pitch
+   I830MemPoolPtr Pool;
+} I830MemRange;
+
+typedef struct _I830MemPool {
+   I830MemRange Total;
+   I830MemRange Free;
+   I830MemRange Fixed;
+   I830MemRange Allocated;
+} I830MemPool;
+
+typedef struct {
+   int tail_mask;
+   I830MemRange mem;
+   unsigned char *virtual_start;
+   int head;
+   int tail;
+   int space;
+} I830RingBuffer;
+
+typedef struct _I830Rec {
+   unsigned char *MMIOBase;
+   unsigned char *FbBase;
+   int cpp;
+
+   unsigned int bios_version;
+
+   /* These are set in PreInit and never changed. */
+   long FbMapSize;
+   long TotalVideoRam;
+   I830MemRange StolenMemory;          /* pre-allocated memory */
+   long BIOSMemorySize;                        /* min stolen pool size */
+   int BIOSMemSizeLoc;
+
+   /* These change according to what has been allocated. */
+   long FreeMemory;
+   I830MemRange MemoryAperture;
+   I830MemPool StolenPool;
+   long allocatedMemory;
+
+   /* Regions allocated either from the above pools, or from agpgart. */
+   /* for single and dual head configurations */
+   I830MemRange FrontBuffer;
+   I830MemRange FrontBuffer2;
+   I830MemRange Scratch;
+   I830MemRange Scratch2;
+
+   I830RingBuffer *LpRing;
+
+   I830MemRange BackBuffer;
+   I830MemRange DepthBuffer;
+   I830MemRange TexMem;
+   int TexGranularity;
+   I830MemRange ContextMem;
+   int drmMinor;
+   Bool have3DWindows;
+
+   Bool NeedRingBufferLow;
+   Bool allowPageFlip;
+   Bool disableTiling;
+
+   int Chipset;
+   unsigned long LinearAddr;
+   unsigned long MMIOAddr;
+
+   drmSize           registerSize;     /**< \brief MMIO register map size */
+   drm_handle_t         registerHandle;   /**< \brief MMIO register map handle */
+  //   IOADDRESS ioBase;
+   int               irq;              /**< \brief IRQ number */
+   int GttBound;
+
+   drm_handle_t ring_map;
+   unsigned int Fence[8];
+
+} I830Rec;
+
+/*
+ * 12288 is set as the maximum, chosen because it is enough for
+ * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare.
+ */
+#define I830_MAXIMUM_VBIOS_MEM         12288
+#define I830_DEFAULT_VIDEOMEM_2D       (MB(32) / 1024)
+#define I830_DEFAULT_VIDEOMEM_3D       (MB(64) / 1024)
+
+/* Flags for memory allocation function */
+#define FROM_ANYWHERE                  0x00000000
+#define FROM_POOL_ONLY                 0x00000001
+#define FROM_NEW_ONLY                  0x00000002
+#define FROM_MASK                      0x0000000f
+
+#define ALLOCATE_AT_TOP                        0x00000010
+#define ALLOCATE_AT_BOTTOM             0x00000020
+#define FORCE_GAPS                     0x00000040
+
+#define NEED_PHYSICAL_ADDR             0x00000100
+#define ALIGN_BOTH_ENDS                        0x00000200
+#define FORCE_LOW                      0x00000400
+
+#define ALLOC_NO_TILING                        0x00001000
+#define ALLOC_INITIAL                  0x00002000
+
+#define ALLOCATE_DRY_RUN               0x80000000
+
+/* Chipset registers for VIDEO BIOS memory RW access */
+#define _855_DRAM_RW_CONTROL 0x58
+#define _845_DRAM_RW_CONTROL 0x90
+#define DRAM_WRITE    0x33330000
+
+#define KB(x) ((x) * 1024)
+#define MB(x) ((x) * KB(1024))
+
+#define GTT_PAGE_SIZE                  KB(4)
+#define ROUND_TO(x, y)                 (((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y)            ((x) / (y) * (y))
+#define ROUND_TO_PAGE(x)               ROUND_TO((x), GTT_PAGE_SIZE)
+#define ROUND_TO_MB(x)                 ROUND_TO((x), MB(1))
+#define PRIMARY_RINGBUFFER_SIZE                KB(128)
+
+
+/* Ring buffer registers, p277, overview p19
+ */
+#define LP_RING     0x2030
+#define HP_RING     0x2040
+
+#define RING_TAIL      0x00
+#define TAIL_ADDR           0x000FFFF8
+#define I830_TAIL_MASK     0x001FFFF8
+
+#define RING_HEAD      0x04
+#define HEAD_WRAP_COUNT     0xFFE00000
+#define HEAD_WRAP_ONE       0x00200000
+#define HEAD_ADDR           0x001FFFFC
+#define I830_HEAD_MASK      0x001FFFFC
+
+#define RING_START     0x08
+#define START_ADDR          0x03FFFFF8
+#define I830_RING_START_MASK   0xFFFFF000
+
+#define RING_LEN       0x0C
+#define RING_NR_PAGES       0x001FF000 
+#define I830_RING_NR_PAGES     0x001FF000
+#define RING_REPORT_MASK    0x00000006
+#define RING_REPORT_64K     0x00000002
+#define RING_REPORT_128K    0x00000004
+#define RING_NO_REPORT      0x00000000
+#define RING_VALID_MASK     0x00000001
+#define RING_VALID          0x00000001
+#define RING_INVALID        0x00000000
+
+
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE            0x2000
+#define FENCE_NR         8
+
+#define I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK  0x07f80000
+
+#define FENCE_START_MASK    0x03F80000
+#define FENCE_X_MAJOR       0x00000000
+#define FENCE_Y_MAJOR       0x00001000
+#define FENCE_SIZE_MASK     0x00000700
+#define FENCE_SIZE_512K     0x00000000
+#define FENCE_SIZE_1M       0x00000100
+#define FENCE_SIZE_2M       0x00000200
+#define FENCE_SIZE_4M       0x00000300
+#define FENCE_SIZE_8M       0x00000400
+#define FENCE_SIZE_16M      0x00000500
+#define FENCE_SIZE_32M      0x00000600
+#define FENCE_SIZE_64M     0x00000700
+#define I915G_FENCE_SIZE_1M       0x00000000
+#define I915G_FENCE_SIZE_2M       0x00000100
+#define I915G_FENCE_SIZE_4M       0x00000200
+#define I915G_FENCE_SIZE_8M       0x00000300
+#define I915G_FENCE_SIZE_16M      0x00000400
+#define I915G_FENCE_SIZE_32M      0x00000500
+#define I915G_FENCE_SIZE_64M   0x00000600
+#define I915G_FENCE_SIZE_128M  0x00000700
+#define FENCE_PITCH_1       0x00000000
+#define FENCE_PITCH_2       0x00000010
+#define FENCE_PITCH_4       0x00000020
+#define FENCE_PITCH_8       0x00000030
+#define FENCE_PITCH_16      0x00000040
+#define FENCE_PITCH_32      0x00000050
+#define FENCE_PITCH_64     0x00000060
+#define FENCE_VALID         0x00000001
+
+#include <mmio.h>
+
+#  define MMIO_IN8(base, offset) \
+       *(volatile unsigned char *)(((unsigned char*)(base)) + (offset))
+#  define MMIO_IN32(base, offset) \
+       read_MMIO_LE32(base, offset)
+#  define MMIO_OUT8(base, offset, val) \
+       *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val)
+#  define MMIO_OUT32(base, offset, val) \
+       *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = CPU_TO_LE32(val)
+
+
+                               /* Memory mapped register access macros */
+#define INREG8(addr)        MMIO_IN8(MMIO, addr)
+#define INREG(addr)         MMIO_IN32(MMIO, addr)
+#define OUTREG8(addr, val)  MMIO_OUT8(MMIO, addr, val)
+#define OUTREG(addr, val)   MMIO_OUT32(MMIO, addr, val)
+
+#define DSPABASE               0x70184
+
+#endif
diff --git a/src/mesa/drivers/dri/i915tex/server/intel_dri.c b/src/mesa/drivers/dri/i915tex/server/intel_dri.c
new file mode 100644 (file)
index 0000000..169fdbe
--- /dev/null
@@ -0,0 +1,1282 @@
+/**
+ * \file server/intel_dri.c
+ * \brief File to perform the device-specific initialization tasks typically
+ * done in the X server.
+ *
+ * Here they are converted to run in the client (or perhaps a standalone
+ * process), and to work with the frame buffer device rather than the X
+ * server infrastructure.
+ * 
+ * Copyright (C) 2006 Dave Airlie (airlied@linux.ie)
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sub license, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial portions
+ of the Software.
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "driver.h"
+#include "drm.h"
+
+#include "intel.h"
+#include "i830_dri.h"
+
+#include "memops.h"
+#include "pciaccess.h"
+
+static size_t drm_page_size;
+static int nextTile = 0;
+#define xf86DrvMsg(...) do {} while(0)
+
+static const int pitches[] = {
+  128 * 8,
+  128 * 16,
+  128 * 32,
+  128 * 64,
+  0
+};
+
+static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
+
+static unsigned long
+GetBestTileAlignment(unsigned long size)
+{
+   unsigned long i;
+
+   for (i = KB(512); i < size; i <<= 1)
+      ;
+
+   if (i > MB(64))
+      i = MB(64);
+
+   return i;
+}
+
+static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  int i;
+  unsigned char *MMIO = ctx->MMIOAddress;
+
+  for (i = 0; i < 8; i++) {
+    OUTREG(FENCE + i * 4, pI830->Fence[i]);
+    //    if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+    fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]);
+  }
+}
+
+/* Tiled memory is good... really, really good...
+ *
+ * Need to make it less likely that we miss out on this - probably
+ * need to move the frontbuffer away from the 'guarenteed' alignment
+ * of the first memory segment, or perhaps allocate a discontigous
+ * framebuffer to get more alignment 'sweet spots'.
+ */
+static void
+SetFence(const DRIDriverContext *ctx, I830Rec *pI830,
+        int nr, unsigned int start, unsigned int pitch,
+         unsigned int size)
+{
+   unsigned int val;
+   unsigned int fence_mask = 0;
+   unsigned int fence_pitch;
+
+   if (nr < 0 || nr > 7) {
+      fprintf(stderr,
+                "SetFence: fence %d out of range\n",nr);
+      return;
+   }
+
+   pI830->Fence[nr] = 0;
+
+   if (IS_I9XX(pI830))
+       fence_mask = ~I915G_FENCE_START_MASK;
+   else
+       fence_mask = ~I830_FENCE_START_MASK;
+
+   if (start & fence_mask) {
+      fprintf(stderr,
+                "SetFence: %d: start (0x%08x) is not %s aligned\n",
+                nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
+      return;
+   }
+
+   if (start % size) {
+      fprintf(stderr,
+                "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
+                nr, start, size / 1024);
+      return;
+   }
+
+   if (pitch & 127) {
+      fprintf(stderr,
+                "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+                nr, pitch);
+      return;
+   }
+
+   val = (start | FENCE_X_MAJOR | FENCE_VALID);
+
+   if (IS_I9XX(pI830)) {
+       switch (size) {
+          case MB(1):
+               val |= I915G_FENCE_SIZE_1M;
+               break;
+          case MB(2):
+               val |= I915G_FENCE_SIZE_2M;
+               break;
+          case MB(4):
+               val |= I915G_FENCE_SIZE_4M;
+               break;
+          case MB(8):
+               val |= I915G_FENCE_SIZE_8M;
+               break;
+          case MB(16):
+               val |= I915G_FENCE_SIZE_16M;
+               break;
+          case MB(32):
+               val |= I915G_FENCE_SIZE_32M;
+               break;
+          case MB(64):
+               val |= I915G_FENCE_SIZE_64M;
+               break;
+          default:
+               fprintf(stderr,
+                "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+               return;
+       }
+    } else {
+       switch (size) {
+          case KB(512):
+               val |= FENCE_SIZE_512K;
+               break;
+          case MB(1):
+               val |= FENCE_SIZE_1M;
+               break;
+          case MB(2):
+               val |= FENCE_SIZE_2M;
+               break;
+          case MB(4):
+               val |= FENCE_SIZE_4M;
+               break;
+          case MB(8):
+               val |= FENCE_SIZE_8M;
+               break;
+          case MB(16):
+               val |= FENCE_SIZE_16M;
+               break;
+          case MB(32):
+               val |= FENCE_SIZE_32M;
+               break;
+          case MB(64):
+               val |= FENCE_SIZE_64M;
+               break;
+          default:
+               fprintf(stderr,
+                "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+               return;
+       }
+   }
+
+   if (IS_I9XX(pI830))
+       fence_pitch = pitch / 512;
+   else
+       fence_pitch = pitch / 128;
+
+   switch (fence_pitch) {
+   case 1:
+      val |= FENCE_PITCH_1;
+      break;
+   case 2:
+      val |= FENCE_PITCH_2;
+      break;
+   case 4:
+      val |= FENCE_PITCH_4;
+      break;
+   case 8:
+      val |= FENCE_PITCH_8;
+      break;
+   case 16:
+      val |= FENCE_PITCH_16;
+      break;
+   case 32:
+      val |= FENCE_PITCH_32;
+      break;
+   case 64:
+      val |= FENCE_PITCH_64;
+      break;
+   default:
+      fprintf(stderr,
+                "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+      return;
+   }
+
+   pI830->Fence[nr] = val;
+}
+
+static Bool
+MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem)
+{
+   int pitch, ntiles, i;
+
+   pitch = pMem->Pitch * ctx->cpp;
+   /*
+    * Simply try to break the region up into at most four pieces of size
+    * equal to the alignment.
+    */
+   ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
+   if (ntiles >= 4) {
+      return FALSE;
+   }
+
+   for (i = 0; i < ntiles; i++, nextTile++) {
+     SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment,
+              pitch, pMem->Alignment);
+   }
+   return TRUE;
+}
+
+static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  int i;
+
+  /* Clear out */
+  for (i = 0; i < 8; i++)
+    pI830->Fence[i] = 0;
+  
+  nextTile = 0;
+
+  if (pI830->BackBuffer.Alignment >= KB(512)) {
+    if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) {
+      fprintf(stderr,
+                "Activating tiled memory for the back buffer.\n");
+    } else {
+      fprintf(stderr,
+                "MakeTiles failed for the back buffer.\n");
+      pI830->allowPageFlip = FALSE;
+    }
+  }
+  
+  if (pI830->DepthBuffer.Alignment >= KB(512)) {
+    if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) {
+      fprintf(stderr,
+                "Activating tiled memory for the depth buffer.\n");
+    } else {
+      fprintf(stderr,
+                "MakeTiles failed for the depth buffer.\n");
+    }
+  }
+
+  return;
+}
+
+static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  struct pci_device host_bridge;
+  uint32_t gmch_ctrl;
+  int memsize = 0;
+  int range;
+
+  memset(&host_bridge, 0, sizeof(host_bridge));
+
+  pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL);
+  
+  /* We need to reduce the stolen size, by the GTT and the popup.
+   * The GTT varying according the the FbMapSize and the popup is 4KB */
+  range = (ctx->shared.fbSize / (1024*1024)) + 4;
+
+   if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
+      switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+      case I855_GMCH_GMS_STOLEN_1M:
+        memsize = MB(1) - KB(range);
+        break;
+      case I855_GMCH_GMS_STOLEN_4M:
+        memsize = MB(4) - KB(range);
+        break;
+      case I855_GMCH_GMS_STOLEN_8M:
+        memsize = MB(8) - KB(range);
+        break;
+      case I855_GMCH_GMS_STOLEN_16M:
+        memsize = MB(16) - KB(range);
+        break;
+      case I855_GMCH_GMS_STOLEN_32M:
+        memsize = MB(32) - KB(range);
+        break;
+      case I915G_GMCH_GMS_STOLEN_48M:
+        if (IS_I9XX(pI830))
+           memsize = MB(48) - KB(range);
+        break;
+      case I915G_GMCH_GMS_STOLEN_64M:
+        if (IS_I9XX(pI830))
+           memsize = MB(64) - KB(range);
+        break;
+      }
+   } else {
+      switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+      case I830_GMCH_GMS_STOLEN_512:
+        memsize = KB(512) - KB(range);
+        break;
+      case I830_GMCH_GMS_STOLEN_1024:
+        memsize = MB(1) - KB(range);
+        break;
+      case I830_GMCH_GMS_STOLEN_8192:
+        memsize = MB(8) - KB(range);
+        break;
+      case I830_GMCH_GMS_LOCAL:
+        memsize = 0;
+        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+                   "Local memory found, but won't be used.\n");
+        break;
+      }
+   }
+   if (memsize > 0) {
+     fprintf(stderr,
+                "detected %d kB stolen memory.\n", memsize / 1024);
+   } else {
+     fprintf(stderr,
+                "no video memory detected.\n");
+   }
+   return memsize;
+}
+
+static int AgpInit(const DRIDriverContext *ctx, I830Rec *info)
+{
+  unsigned long mode = 0x4;
+
+  if (drmAgpAcquire(ctx->drmFD) < 0) {
+    fprintf(stderr, "[gart] AGP not available\n");
+    return 0;
+  }
+  
+  if (drmAgpEnable(ctx->drmFD, mode) < 0) {
+    fprintf(stderr, "[gart] AGP not enabled\n");
+    drmAgpRelease(ctx->drmFD);
+    return 0;
+  }
+  else
+    fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode);
+
+  return 1;
+}
+
+/*
+ * Allocate memory from the given pool.  Grow the pool if needed and if
+ * possible.
+ */
+static unsigned long
+AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830, 
+             I830MemRange *result, I830MemPool *pool,
+             long size, unsigned long alignment, int flags)
+{
+   long needed, start, end;
+
+   if (!result || !pool || !size)
+      return 0;
+
+   /* Calculate how much space is needed. */
+   if (alignment <= GTT_PAGE_SIZE)
+      needed = size;
+   else {
+        start = ROUND_TO(pool->Free.Start, alignment);
+        end = ROUND_TO(start + size, alignment);
+        needed = end - pool->Free.Start;
+   }
+   if (needed > pool->Free.Size) {
+     return 0;
+   }
+
+   result->Start = ROUND_TO(pool->Free.Start, alignment);
+   pool->Free.Start += needed;
+   result->End = pool->Free.Start;
+
+   pool->Free.Size = pool->Free.End - pool->Free.Start;
+   result->Size = result->End - result->Start;
+   result->Pool = pool;
+   result->Alignment = alignment;
+   return needed;
+}
+
+static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange  *result)
+{
+   unsigned long start, end;
+   unsigned long newApStart, newApEnd;
+   int ret;
+   if (!result || !size)
+      return 0;
+   
+   if (!alignment)
+     alignment = 4;
+
+   start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
+   end = ROUND_TO(start + size, alignment);
+   newApStart = end;
+   newApEnd = pI830->MemoryAperture.End;
+
+   ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key));
+   
+   if (ret)
+   {
+     fprintf(stderr,"drmAgpAlloc failed %d\n", ret);
+     return 0;
+   }
+   pI830->allocatedMemory += size;
+   pI830->MemoryAperture.Start = newApStart;
+   pI830->MemoryAperture.End = newApEnd;
+   pI830->MemoryAperture.Size = newApEnd - newApStart;
+   //   pI830->FreeMemory -= size;
+   result->Start = start;
+   result->End = start + size;
+   result->Size = size;
+   result->Offset = start;
+   result->Alignment = alignment;
+   result->Pool = NULL;
+  
+   return size;
+}
+
+unsigned long
+I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags)
+{
+  int ret;
+
+  if (!result)
+    return 0;
+
+   /* Make sure these are initialised. */
+   result->Size = 0;
+   result->Key = -1;
+
+   if (!size) {
+      return 0;
+   }
+
+   if (pool->Free.Size < size)
+     return AllocFromAGP(ctx, pI830, size, alignment, result);
+   else
+   {
+     ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
+
+     if (ret==0)
+       return AllocFromAGP(ctx, pI830, size, alignment, result);
+     return ret;
+   }
+}
+
+static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
+{
+  if (!mem)
+    return FALSE;
+  
+  if (mem->Key == -1)
+    return TRUE;
+
+  return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
+}
+
+/* simple memory allocation routines needed */
+/* put ring buffer in low memory */
+/* need to allocate front, back, depth buffers aligned correctly,
+   allocate ring buffer, 
+*/
+
+/* */
+static Bool
+I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  unsigned long size, ret;
+  unsigned long lines, lineSize, align;
+
+  /* allocate ring buffer */
+  memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
+  pI830->LpRing->mem.Key = -1;
+
+  size = PRIMARY_RINGBUFFER_SIZE;
+  
+  ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
+  
+  if (ret != size)
+  {
+    fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
+    return FALSE;
+  }
+
+  pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
+
+  
+  /* allocate front buffer */
+  memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
+  pI830->FrontBuffer.Key = -1;
+  pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
+
+  align = KB(512);  
+
+  lineSize = ctx->shared.virtualWidth * ctx->cpp;
+  lines = (ctx->shared.virtualHeight + 15) / 16 * 16;
+  size = lineSize * lines;
+  size = ROUND_TO_PAGE(size);
+
+  align = GetBestTileAlignment(size);
+
+  ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
+  if (ret < size)
+  {
+    fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
+    return FALSE;
+  }
+
+  memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
+  pI830->BackBuffer.Key = -1;
+  pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
+
+  ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
+  if (ret < size)
+  {
+    fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
+    return FALSE;
+  }
+  
+  memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
+  pI830->DepthBuffer.Key = -1;
+  pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
+
+  ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
+  if (ret < size)
+  {
+    fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
+    return FALSE;
+  }
+
+  memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
+  pI830->ContextMem.Key = -1;
+  size = KB(32);
+
+  ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
+  if (ret < size)
+  {
+    fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
+    return FALSE;
+  }
+  
+  memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
+  pI830->TexMem.Key = -1;
+
+  size = 32768 * 1024;
+  ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
+  if (ret < size)
+  {
+    fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static Bool
+I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  if (!BindAgpRange(ctx, &pI830->LpRing->mem))
+    return FALSE;
+  if (!BindAgpRange(ctx, &pI830->FrontBuffer))
+    return FALSE;
+  if (!BindAgpRange(ctx, &pI830->BackBuffer))
+    return FALSE;
+  if (!BindAgpRange(ctx, &pI830->DepthBuffer))
+    return FALSE;
+  if (!BindAgpRange(ctx, &pI830->ContextMem))
+    return FALSE;
+  if (!BindAgpRange(ctx, &pI830->TexMem))
+    return FALSE;
+
+  return TRUE;
+}
+
+static Bool
+I830CleanupDma(const DRIDriverContext *ctx)
+{
+   drmI830Init info;
+
+   memset(&info, 0, sizeof(drmI830Init));
+   info.func = I830_CLEANUP_DMA;
+
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
+                      &info, sizeof(drmI830Init))) {
+     fprintf(stderr, "I830 Dma Cleanup Failed\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static Bool
+I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+   I830RingBuffer *ring = pI830->LpRing;
+   drmI830Init info;
+
+   memset(&info, 0, sizeof(drmI830Init));
+   info.func = I830_INIT_DMA;
+
+   info.ring_start = ring->mem.Start + pI830->LinearAddr;
+   info.ring_end = ring->mem.End + pI830->LinearAddr;
+   info.ring_size = ring->mem.Size;
+
+   info.mmio_offset = (unsigned int)ctx->MMIOStart;
+
+   info.sarea_priv_offset = sizeof(drm_sarea_t);
+
+   info.front_offset = pI830->FrontBuffer.Start;
+   info.back_offset = pI830->BackBuffer.Start;
+   info.depth_offset = pI830->DepthBuffer.Start;
+   info.w = ctx->shared.virtualWidth;
+   info.h = ctx->shared.virtualHeight;
+   info.pitch = ctx->shared.virtualWidth;
+   info.back_pitch = pI830->BackBuffer.Pitch;
+   info.depth_pitch = pI830->DepthBuffer.Pitch;
+   info.cpp = ctx->cpp;
+
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
+                      &info, sizeof(drmI830Init))) {
+      fprintf(stderr,
+                "I830 Dma Initialization Failed\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static int I830CheckDRMVersion( const DRIDriverContext *ctx,
+                                 I830Rec *pI830 )
+{
+   drmVersionPtr  version;
+
+   version = drmGetVersion(ctx->drmFD);
+
+   if (version) {
+     int req_minor, req_patch;
+
+     req_minor = 4;
+     req_patch = 0;    
+
+     if (version->version_major != 1 ||
+        version->version_minor < req_minor ||
+        (version->version_minor == req_minor && 
+         version->version_patchlevel < req_patch)) {
+       /* Incompatible drm version */
+       fprintf(stderr,
+              "[dri] I830DRIScreenInit failed because of a version "
+              "mismatch.\n"
+              "[dri] i915.o kernel module version is %d.%d.%d "
+              "but version 1.%d.%d or newer is needed.\n"
+              "[dri] Disabling DRI.\n",
+              version->version_major,
+              version->version_minor,
+              version->version_patchlevel,
+              req_minor,
+              req_patch);
+       drmFreeVersion(version);
+       return 0;
+     }
+     
+     pI830->drmMinor = version->version_minor;
+     drmFreeVersion(version);
+   }
+   return 1;
+}
+
+static void
+I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+  unsigned int itemp;
+  unsigned char *MMIO = ctx->MMIOAddress;
+
+   OUTREG(LP_RING + RING_LEN, 0);
+   OUTREG(LP_RING + RING_TAIL, 0);
+   OUTREG(LP_RING + RING_HEAD, 0);
+
+   if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
+       pI830->LpRing->mem.Start) {
+      fprintf(stderr,
+                "I830SetRingRegs: Ring buffer start (%lx) violates its "
+                "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
+   }
+   /* Don't care about the old value.  Reserved bits must be zero anyway. */
+   itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
+   OUTREG(LP_RING + RING_START, itemp);
+
+   if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
+       pI830->LpRing->mem.Size - 4096) {
+      fprintf(stderr,
+                "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
+                "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
+                I830_RING_NR_PAGES);
+   }
+   /* Don't care about the old value.  Reserved bits must be zero anyway. */
+   itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
+   itemp |= (RING_NO_REPORT | RING_VALID);
+   OUTREG(LP_RING + RING_LEN, itemp);
+
+   pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
+   pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
+   pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
+   if (pI830->LpRing->space < 0)
+      pI830->LpRing->space += pI830->LpRing->mem.Size;
+
+   SetFenceRegs(ctx, pI830);
+   
+   /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
+      hacky hacky */
+   OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
+
+}
+
+static Bool
+I830SetParam(const DRIDriverContext *ctx, int param, int value)
+{
+   drmI830SetParam sp;
+
+   memset(&sp, 0, sizeof(sp));
+   sp.param = param;
+   sp.value = value;
+
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
+      fprintf(stderr, "I830 SetParam Failed\n");
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static Bool
+I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+   fprintf(stderr,
+              "[drm] Mapping front buffer\n");
+
+   if (drmAddMap(ctx->drmFD,
+                 (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
+                 sarea->front_size,
+                 DRM_FRAME_BUFFER,  /*DRM_AGP,*/
+                 0,
+                 &sarea->front_handle) < 0) {
+     fprintf(stderr,
+            "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   ctx->shared.hFrameBuffer = sarea->front_handle;
+   ctx->shared.fbSize = sarea->front_size;
+   fprintf(stderr, "[drm] Front Buffer = 0x%08x\n",
+          sarea->front_handle);
+
+   if (drmAddMap(ctx->drmFD,
+                 (drm_handle_t)(sarea->back_offset),
+                 sarea->back_size, DRM_AGP, 0,
+                 &sarea->back_handle) < 0) {
+      fprintf(stderr,
+                 "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
+              sarea->back_handle);
+
+   if (drmAddMap(ctx->drmFD,
+                 (drm_handle_t)sarea->depth_offset,
+                 sarea->depth_size, DRM_AGP, 0,
+                 &sarea->depth_handle) < 0) {
+      fprintf(stderr,
+                 "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
+              sarea->depth_handle);
+
+   if (drmAddMap(ctx->drmFD,
+                (drm_handle_t)sarea->tex_offset,
+                sarea->tex_size, DRM_AGP, 0,
+                &sarea->tex_handle) < 0) {
+      fprintf(stderr,
+                "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
+      return FALSE;
+   }
+   fprintf(stderr, "[drm] textures = 0x%08x\n",
+             sarea->tex_handle);
+
+   return TRUE;
+}
+
+
+static void
+I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+#if 1
+   if (sarea->front_handle) {
+      drmRmMap(ctx->drmFD, sarea->front_handle);
+      sarea->front_handle = 0;
+   }
+#endif
+   if (sarea->back_handle) {
+      drmRmMap(ctx->drmFD, sarea->back_handle);
+      sarea->back_handle = 0;
+   }
+   if (sarea->depth_handle) {
+      drmRmMap(ctx->drmFD, sarea->depth_handle);
+      sarea->depth_handle = 0;
+   }
+   if (sarea->tex_handle) {
+      drmRmMap(ctx->drmFD, sarea->tex_handle);
+      sarea->tex_handle = 0;
+   }
+}
+
+static void
+I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+   /* Start up the simple memory manager for agp space */
+   drmI830MemInitHeap drmHeap;
+   drmHeap.region = I830_MEM_REGION_AGP;
+   drmHeap.start  = 0;
+   drmHeap.size   = sarea->tex_size;
+      
+   if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP,
+                         &drmHeap, sizeof(drmHeap))) {
+      fprintf(stderr,
+                   "[drm] Failed to initialized agp heap manager\n");
+   } else {
+      fprintf(stderr,
+                   "[drm] Initialized kernel agp heap manager, %d\n",
+                   sarea->tex_size);
+
+      I830SetParam(ctx, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, 
+                     sarea->log_tex_granularity);
+   }
+}
+
+static Bool
+I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+  if (drmAddMap(ctx->drmFD,
+               (drm_handle_t)pI830->LpRing->mem.Start,
+               pI830->LpRing->mem.Size, DRM_AGP, 0,
+               &pI830->ring_map) < 0) {
+    fprintf(stderr,
+           "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
+    return FALSE;
+  }
+  fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
+         pI830->ring_map);
+
+  if (I830InitDma(ctx, pI830) == FALSE) {
+    return FALSE;
+  }
+  
+   /* init to zero to be safe */
+
+  I830DRIMapScreenRegions(ctx, pI830, sarea);
+  I830InitTextureHeap(ctx, pI830, sarea);
+
+   if (ctx->pciDevice != PCI_CHIP_845_G &&
+       ctx->pciDevice != PCI_CHIP_I830_M) {
+      I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
+   }
+
+   /* Okay now initialize the dma engine */
+   {
+      pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
+                                           ctx->pciBus,
+                                           ctx->pciDevice,
+                                           ctx->pciFunc);
+
+      if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
+        fprintf(stderr,
+                   "[drm] failure adding irq handler\n");
+        pI830->irq = 0;
+        return FALSE;
+      }
+      else
+        fprintf(stderr,
+                   "[drm] dma control initialized, using IRQ %d\n",
+                   pI830->irq);
+   }
+
+   fprintf(stderr, "[dri] visual configs initialized\n");
+
+   return TRUE;
+}
+
+static Bool
+I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+  /* need to drmMap front and back buffers and zero them */
+  drmAddress map_addr;
+  int ret;
+
+  ret = drmMap(ctx->drmFD,
+              sarea->front_handle,
+              sarea->front_size,
+              &map_addr);
+
+  if (ret)
+  {
+    fprintf(stderr, "Unable to map front buffer\n");
+    return FALSE;
+  }
+
+  drimemsetio((char *)map_addr,
+             0,
+             sarea->front_size);
+  drmUnmap(map_addr, sarea->front_size);
+
+
+  ret = drmMap(ctx->drmFD,
+              sarea->back_handle,
+              sarea->back_size,
+              &map_addr);
+
+  if (ret)
+  {
+    fprintf(stderr, "Unable to map back buffer\n");
+    return FALSE;
+  }
+
+  drimemsetio((char *)map_addr,
+             0,
+             sarea->back_size);
+  drmUnmap(map_addr, sarea->back_size);
+
+  return TRUE;
+}
+
+static Bool
+I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
+                 
+{
+   I830DRIPtr pI830DRI;
+   drmI830Sarea *pSAREAPriv;
+   int err;
+      
+   drm_page_size = getpagesize();   
+
+   pI830->registerSize = ctx->MMIOSize;
+   /* This is a hack for now.  We have to have more than a 4k page here
+    * because of the size of the state.  However, the state should be
+    * in a per-context mapping.  This will be added in the Mesa 3.5 port
+    * of the I830 driver.
+    */
+   ctx->shared.SAREASize = SAREA_MAX;
+
+   /* Note that drmOpen will try to load the kernel module, if needed. */
+   ctx->drmFD = drmOpen("i915", NULL );
+   if (ctx->drmFD < 0) {
+      fprintf(stderr, "[drm] drmOpen failed\n");
+      return 0;
+   }
+
+   if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
+      fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
+             ctx->drmFD, ctx->pciBusID, strerror(-err));
+      return 0;
+   }
+
+   if (drmAddMap( ctx->drmFD,
+                 0,
+                 ctx->shared.SAREASize,
+                 DRM_SHM,
+                 DRM_CONTAINS_LOCK,
+                 &ctx->shared.hSAREA) < 0)
+   {
+     fprintf(stderr, "[drm] drmAddMap failed\n");
+     return 0;
+   }
+
+   fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n",
+          ctx->shared.SAREASize, ctx->shared.hSAREA);
+   
+   if (drmMap( ctx->drmFD,
+              ctx->shared.hSAREA,
+              ctx->shared.SAREASize,
+              (drmAddressPtr)(&ctx->pSAREA)) < 0)
+   {
+      fprintf(stderr, "[drm] drmMap failed\n");
+      return 0;
+   
+   }
+   
+   memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
+   fprintf(stderr, "[drm] mapped SAREA 0x%08x to %p, size %d\n",
+          ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
+   
+
+   if (drmAddMap(ctx->drmFD, 
+                ctx->MMIOStart,
+                ctx->MMIOSize,
+                DRM_REGISTERS, 
+                DRM_READ_ONLY, 
+                &pI830->registerHandle) < 0) {
+      fprintf(stderr, "[drm] drmAddMap mmio failed\n");        
+      return 0;
+   }
+   fprintf(stderr,
+          "[drm] register handle = 0x%08x\n", pI830->registerHandle);
+
+
+   if (!I830CheckDRMVersion(ctx, pI830)) {
+     return FALSE;
+   }
+
+   /* Create a 'server' context so we can grab the lock for
+    * initialization ioctls.
+    */
+   if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
+      fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
+      return 0;
+   }
+
+   DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); 
+
+   /* Initialize the SAREA private data structure */
+   pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
+                                sizeof(drm_sarea_t));
+   memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+   pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
+   pI830->StolenMemory.Start = 0;
+   pI830->StolenMemory.End = pI830->StolenMemory.Size;
+
+   pI830->MemoryAperture.Start = pI830->StolenMemory.End;
+   pI830->MemoryAperture.End = KB(40000);
+   pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
+
+   pI830->StolenPool.Fixed = pI830->StolenMemory;
+   pI830->StolenPool.Total = pI830->StolenMemory;
+   pI830->StolenPool.Free = pI830->StolenPool.Total;
+   pI830->FreeMemory = pI830->StolenPool.Total.Size;
+
+   if (!AgpInit(ctx, pI830))
+     return FALSE;
+
+   if (I830AllocateMemory(ctx, pI830) == FALSE)
+   {
+     return FALSE;
+   }
+
+   if (I830BindMemory(ctx, pI830) == FALSE)
+   {
+     return FALSE;
+   }
+
+   pSAREAPriv->front_offset = pI830->FrontBuffer.Start;
+   pSAREAPriv->front_size = pI830->FrontBuffer.Size;
+   pSAREAPriv->width = ctx->shared.virtualWidth;
+   pSAREAPriv->height = ctx->shared.virtualHeight;
+   pSAREAPriv->pitch = ctx->shared.virtualWidth;
+   pSAREAPriv->virtualX = ctx->shared.virtualWidth;
+   pSAREAPriv->virtualY = ctx->shared.virtualHeight;
+   pSAREAPriv->back_offset = pI830->BackBuffer.Start;
+   pSAREAPriv->back_size = pI830->BackBuffer.Size;
+   pSAREAPriv->depth_offset = pI830->DepthBuffer.Start;
+   pSAREAPriv->depth_size = pI830->DepthBuffer.Size;
+   pSAREAPriv->tex_offset = pI830->TexMem.Start;
+   pSAREAPriv->tex_size = pI830->TexMem.Size;
+   pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
+
+   ctx->driverClientMsg = malloc(sizeof(I830DRIRec));
+   ctx->driverClientMsgSize = sizeof(I830DRIRec);
+   pI830DRI = (I830DRIPtr)ctx->driverClientMsg;
+   pI830DRI->deviceID = pI830->Chipset;
+   pI830DRI->regsSize = I830_REG_SIZE;
+   pI830DRI->width = ctx->shared.virtualWidth;
+   pI830DRI->height = ctx->shared.virtualHeight;
+   pI830DRI->mem = ctx->shared.fbSize;
+   pI830DRI->cpp = ctx->cpp;
+   pI830DRI->backOffset = pI830->BackBuffer.Start;
+   pI830DRI->backPitch = pI830->BackBuffer.Pitch; 
+
+   pI830DRI->depthOffset = pI830->DepthBuffer.Start;
+   pI830DRI->depthPitch = pI830->DepthBuffer.Pitch; 
+
+   pI830DRI->fbOffset = pI830->FrontBuffer.Start;
+   pI830DRI->fbStride = pI830->FrontBuffer.Pitch;
+
+   pI830DRI->bitsPerPixel = ctx->bpp;
+   pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
+   
+   err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
+   if (err == FALSE)
+       return FALSE;
+
+   I830SetupMemoryTiling(ctx, pI830);
+
+   /* Quick hack to clear the front & back buffers.  Could also use
+    * the clear ioctl to do this, but would need to setup hw state
+    * first.
+    */
+   I830ClearScreen(ctx, pI830, pSAREAPriv);
+
+   I830SetRingRegs(ctx, pI830);
+
+   return TRUE;
+}
+
+
+/**
+ * \brief Validate the fbdev mode.
+ * 
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Saves some registers and returns 1.
+ *
+ * \sa radeonValidateMode().
+ */
+static int i830ValidateMode( const DRIDriverContext *ctx )
+{
+  return 1;
+}
+
+/**
+ * \brief Examine mode returned by fbdev.
+ * 
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Restores registers that fbdev has clobbered and returns 1.
+ *
+ * \sa i810ValidateMode().
+ */
+static int i830PostValidateMode( const DRIDriverContext *ctx )
+{
+  I830Rec *pI830 = ctx->driverPrivate;
+
+  I830SetRingRegs(ctx, pI830);
+  return 1;
+}
+
+
+/**
+ * \brief Initialize the framebuffer device mode
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Fills in \p info with some default values and some information from \p ctx
+ * and then calls I810ScreenInit() for the screen initialization.
+ * 
+ * Before exiting clears the framebuffer memory accessing it directly.
+ */
+static int i830InitFBDev( DRIDriverContext *ctx )
+{
+  I830Rec *pI830 = calloc(1, sizeof(I830Rec));
+  int i;
+
+   {
+      int  dummy = ctx->shared.virtualWidth;
+
+      switch (ctx->bpp / 8) {
+      case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
+      case 2: dummy = (ctx->shared.virtualWidth +  31) &  ~31; break;
+      case 3:
+      case 4: dummy = (ctx->shared.virtualWidth +  15) &  ~15; break;
+      }
+
+      ctx->shared.virtualWidth = dummy;
+      ctx->shared.Width = ctx->shared.virtualWidth;
+   }
+
+
+   for (i = 0; pitches[i] != 0; i++) {
+     if (pitches[i] >= ctx->shared.virtualWidth) {
+       ctx->shared.virtualWidth = pitches[i];
+       break;
+     }
+   }
+
+   ctx->driverPrivate = (void *)pI830;
+   
+   pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
+   pI830->Chipset = ctx->chipset;
+   pI830->LinearAddr = ctx->FBStart;
+
+   if (!I830ScreenInit( ctx, pI830 ))
+      return 0;
+
+   
+   return 1;
+}
+
+
+/**
+ * \brief The screen is being closed, so clean up any state and free any
+ * resources used by the DRI.
+ *
+ * \param ctx display handle.
+ *
+ * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
+ * private data.
+ */
+static void i830HaltFBDev( DRIDriverContext *ctx )
+{
+  drmI830Sarea *pSAREAPriv;
+  I830Rec *pI830 = ctx->driverPrivate;
+
+   if (pI830->irq) {
+       drmCtlUninstHandler(ctx->drmFD);
+       pI830->irq = 0;   }
+
+   I830CleanupDma(ctx);
+
+  pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) + 
+                               sizeof(drm_sarea_t));
+
+  I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
+  drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
+  drmClose(ctx->drmFD);
+  
+  if (ctx->driverPrivate) {
+    free(ctx->driverPrivate);
+    ctx->driverPrivate = 0;
+  }
+}
+
+
+extern void i810NotifyFocus( int );
+
+/**
+ * \brief Exported driver interface for Mini GLX.
+ *
+ * \sa DRIDriverRec.
+ */
+const struct DRIDriverRec __driDriver = {
+   i830ValidateMode,
+   i830PostValidateMode,
+   i830InitFBDev,
+   i830HaltFBDev,
+   NULL,//I830EngineShutdown,
+   NULL, //I830EngineRestore,  
+#ifndef _EMBEDDED
+   0,
+#else
+   i810NotifyFocus, 
+#endif
+};
index e501f5e6609e511e27ef0a4c2286b391a4d91c83..0974f1f80ad462b062e50409e0e98e2599e64cd4 100644 (file)
@@ -322,14 +322,14 @@ void intelEmitCopyBlit( struct intel_context *intel,
 
 
 
-void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
-                     GLint cx1, GLint cy1, GLint cw, GLint ch)
+void intelClearWithBlit(GLcontext *ctx, GLbitfield flags)
 {
    struct intel_context *intel = intel_context( ctx );
    intelScreenPrivate *intelScreen = intel->intelScreen;
    GLuint clear_depth, clear_color;
-   GLint cx, cy;
+   GLint cx, cy, cw, ch;
    GLint cpp = intelScreen->cpp;
+   GLboolean all;
    GLint i;
    struct intel_region *front = intel->front_region;
    struct intel_region *back = intel->back_region;
@@ -376,21 +376,16 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
    intelFlush( &intel->ctx );
    LOCK_HARDWARE( intel );
    {
-      /* Refresh the cx/y/w/h values as they may have been invalidated
-       * by a new window position or size picked up when we did
-       * LOCK_HARDWARE above.  The values passed by mesa are not
-       * reliable.
-       */
-      {
-         cx = ctx->DrawBuffer->_Xmin;
-         cy = ctx->DrawBuffer->_Ymin;
-         ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
-         cw  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
-      }
+      /* get clear bounds after locking */
+      cx = ctx->DrawBuffer->_Xmin;
+      cy = ctx->DrawBuffer->_Ymin;
+      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+      all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);
 
       /* flip top to bottom */
-      cy = intel->driDrawable->h-cy1-ch;
-      cx = cx1 + intel->drawX;
+      cy = intel->driDrawable->h - cy - ch;
+      cx = cx + intel->drawX;
       cy += intel->drawY;
 
       /* adjust for page flipping */
index 71ce8307784c6b381ac72a88e5c5168be68faba8..b15fb1c2b7f59bbb34d0d679a95850dde1401475 100644 (file)
@@ -35,8 +35,7 @@ struct buffer;
 
 extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv,
                             const drm_clip_rect_t *rect );
-extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                            GLint cx1, GLint cy1, GLint cw, GLint ch);
+extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask);
 
 extern void intelEmitCopyBlit( struct intel_context *intel,
                               GLuint cpp,
index dc5b9c0bc42e4a5906900d5e470635270eb7506a..d155c039d77872017e943b20df8ce262e5ed0249 100644 (file)
@@ -224,12 +224,11 @@ void intelWindowMoved( struct intel_context *intel )
  * machine independent.  Maybe we'll get there one day.
  */
 static void intelClearWithTris(struct intel_context *intel, 
-                              GLbitfield mask,
-                              GLboolean all,
-                              GLint cx, GLint cy, 
-                              GLint cw, GLint ch)
+                              GLbitfield mask)
 {
+   GLcontext *ctx = &intel->ctx;
    drm_clip_rect_t clear;
+   GLint cx, cy, cw, ch;
 
    if (INTEL_DEBUG & DEBUG_DRI)
       _mesa_printf("%s %x\n", __FUNCTION__, mask);
@@ -238,18 +237,11 @@ static void intelClearWithTris(struct intel_context *intel,
 
       intel->vtbl.install_meta_state(intel);
 
-      /* Refresh the cx/y/w/h values as they may have been invalidated
-       * by a new window position or size picked up when we did
-       * LOCK_HARDWARE above.  The values passed by mesa are not
-       * reliable.
-       */
-      {
-        GLcontext *ctx = &intel->ctx;
-        cx = ctx->DrawBuffer->_Xmin;
-        cy = ctx->DrawBuffer->_Ymin;
-        ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
-        cw  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
-      }
+      /* Get clear bounds after locking */
+      cx = ctx->DrawBuffer->_Xmin;
+      cy = ctx->DrawBuffer->_Ymin;
+      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
 
       clear.x1 = cx;
       clear.y1 = cy;
@@ -327,11 +319,7 @@ static void intelClearWithTris(struct intel_context *intel,
 
 
 
-static void intelClear(GLcontext *ctx, 
-                      GLbitfield mask, 
-                      GLboolean all,
-                      GLint cx, GLint cy, 
-                      GLint cw, GLint ch)
+static void intelClear(GLcontext *ctx, GLbitfield mask)
 {
    struct intel_context *intel = intel_context( ctx );
    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
@@ -340,8 +328,7 @@ static void intelClear(GLcontext *ctx,
    GLbitfield swrast_mask = 0;
 
    if (INTEL_DEBUG & DEBUG_DRI)
-      fprintf(stderr, "%s %x all %d dims %d,%d %dx%d\n", __FUNCTION__,
-             mask, all, cx, cy, cw, ch);
+      fprintf(stderr, "%s %x\n", __FUNCTION__, mask);
 
 
    if (mask & BUFFER_BIT_FRONT_LEFT) {
@@ -392,13 +379,13 @@ static void intelClear(GLcontext *ctx,
    intelFlush( ctx );
 
    if (blit_mask)
-      intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
+      intelClearWithBlit( ctx, blit_mask );
 
    if (tri_mask) 
-      intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch);
+      intelClearWithTris( intel, tri_mask );
 
    if (swrast_mask)
-      _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
+      _swrast_Clear( ctx, swrast_mask );
 }
 
 
index 30a45ad034cabca75d960d531d534195664bcd54..36e7d3c5d3defc56ccaea4d50c856d0b77aa6143 100644 (file)
@@ -665,8 +665,7 @@ void mach64PerformanceBoxesLocked( mach64ContextPtr mmesa )
  * Buffer clear
  */
 
-static void mach64DDClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                          GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
+static void mach64DDClear( GLcontext *ctx, GLbitfield mask )
 {
    mach64ContextPtr mmesa = MACH64_CONTEXT( ctx );
    __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
@@ -713,7 +712,7 @@ static void mach64DDClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    }
 
    if ( mask )
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
 
    if ( !flags )
       return;
index 32cfbc6a1c562fd98ff192fb5a8e28779de7b4ea..f024f73eb6af30429c9472d12ee3f994e47fed8e 100644 (file)
@@ -883,7 +883,6 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
         mmesa->driDrawable = driDrawPriv;
         mmesa->dirty = ~0; 
         mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK); 
-        mmesa->mesa_drawable = driDrawPriv;
       }
 
       mmesa->driReadable = driReadPriv;
index 81348b6c7f9169562bc407dc111f304f9c24c51a..2124006ade600b7b6d470aaa6487d864c7270139 100644 (file)
@@ -303,13 +303,6 @@ struct mga_context_t {
    __DRIdrawablePrivate *driDrawable;
    __DRIdrawablePrivate *driReadable;
 
-   /**
-    * Drawable used by Mesa for software fallbacks for reading and
-    * writing.  It is set by Mesa's \c SetBuffer callback, and will always be
-    * either \c mga_context_t::driDrawable or \c mga_context_t::driReadable.
-    */
-   __DRIdrawablePrivate *mesa_drawable;
-
    __DRIscreenPrivate *driScreen;
    struct mga_screen_private_s *mgaScreen;
    drm_mga_sarea_t *sarea;
index faf46f31392d8fce3524896dd55ce9dcb946ac0c..b1d5e0c48fc11cec5fda020425392b811bd62f43 100644 (file)
@@ -41,7 +41,7 @@
 #include "mga_xmesa.h"
 #include "utils.h"
 
-#define DRIVER_DATE    "20050609"
+#define DRIVER_DATE    "20061030"
 
 
 /***************************************
@@ -74,24 +74,7 @@ static const GLubyte *mgaGetString( GLcontext *ctx, GLenum name )
 }
 
 
-static void mgaBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
-{
-   GET_CURRENT_CONTEXT(ctx);
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
-   /* Need to lock to make sure the driDrawable is uptodate.  This
-    * information is used to resize Mesa's software buffers, so it has
-    * to be correct.
-    */
-   LOCK_HARDWARE( mmesa );
-   *width = mmesa->driDrawable->w;
-   *height = mmesa->driDrawable->h;
-   UNLOCK_HARDWARE( mmesa );
-}
-
-
 void mgaInitDriverFuncs( struct dd_function_table *functions )
 {
-   functions->GetBufferSize = mgaBufferSize;
    functions->GetString = mgaGetString;
 }
index c9fa9d1294064835ffde734a03b1fd38b39425b2..f8587fc541ee8f50b3a930c416f1522b4c6bba44 100644 (file)
@@ -204,8 +204,7 @@ drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa )
 
 
 static void
-mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-          GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
+mgaClear( GLcontext *ctx, GLbitfield mask )
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
@@ -334,7 +333,7 @@ mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    }
 
    if (mask) 
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
 }
 
 
index dbc7fc884ceabae2da95ee753475424086c09f8b..05dcbb852639efbcbc94043d7fad8cc915dd2932 100644 (file)
@@ -36,9 +36,9 @@
 
 #define LOCAL_VARS                                     \
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);             \
-   __DRIdrawablePrivate *dPriv = mmesa->mesa_drawable; \
    __DRIscreenPrivate *sPriv = mmesa->driScreen;       \
    driRenderbuffer *drb = (driRenderbuffer *) rb;      \
+   const __DRIdrawablePrivate *dPriv = drb->dPriv;     \
    GLuint pitch = drb->pitch;                          \
    GLuint height = dPriv->h;                           \
    char *buf = (char *)(sPriv->pFB +                   \
@@ -52,9 +52,9 @@
 
 #define LOCAL_DEPTH_VARS                                               \
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);                             \
-   __DRIdrawablePrivate *dPriv = mmesa->mesa_drawable;                 \
    __DRIscreenPrivate *sPriv = mmesa->driScreen;                       \
    driRenderbuffer *drb = (driRenderbuffer *) rb;                      \
+   const __DRIdrawablePrivate *dPriv = drb->dPriv;                     \
    GLuint pitch = drb->pitch;                                          \
    GLuint height = dPriv->h;                                           \
    char *buf = (char *)(sPriv->pFB +                                   \
index 69f85d62a5e9da0a71e85f464d3ac55d5e31431f..f7e07c330ae9cba8e535a2a907b78a4b336c485f 100644 (file)
@@ -744,32 +744,12 @@ static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
 }
 
 
-static void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa )
+static void mga_set_cliprects(mgaContextPtr mmesa)
 {
    __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
 
-   if (driDrawable->numClipRects == 0) {
-       static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
-       mmesa->numClipRects = 1;
-       mmesa->pClipRects = &zeroareacliprect;
-   } else {
-       mmesa->numClipRects = driDrawable->numClipRects;
-       mmesa->pClipRects = driDrawable->pClipRects;
-   }
-   mmesa->drawX = driDrawable->x;
-   mmesa->drawY = driDrawable->y;
-
-   mmesa->setup.dstorg = mmesa->drawOffset;
-   mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
-}
-
-
-static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa )
-{
-   __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
-
-   if (driDrawable->numBackClipRects == 0)
-   {
+   if ((mmesa->draw_buffer != MGA_FRONT)
+       || (driDrawable->numBackClipRects == 0)) {
       if (driDrawable->numClipRects == 0) {
          static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
          mmesa->numClipRects = 1;
@@ -794,25 +774,25 @@ static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa )
 
 void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
 {
-   __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+   __DRIdrawablePrivate *const driDrawable = mmesa->driDrawable;
+   __DRIdrawablePrivate *const driReadable = mmesa->driReadable;
    drm_mga_sarea_t *sarea = mmesa->sarea;
 
 
-   DRI_VALIDATE_DRAWABLE_INFO(mmesa->driScreen, driDrawable); 
    mmesa->dirty_cliprects = 0; 
 
-   if (mmesa->draw_buffer == MGA_FRONT)
-      mgaXMesaSetFrontClipRects( mmesa );
-   else
-      mgaXMesaSetBackClipRects( mmesa );
+   driUpdateFramebufferSize(mmesa->glCtx, driDrawable);
+   if (driDrawable != driReadable) {
+      driUpdateFramebufferSize(mmesa->glCtx, driReadable);
+   }
+
+   mga_set_cliprects(mmesa);
 
    sarea->req_drawable = driDrawable->draw;
    sarea->req_draw_buffer = mmesa->draw_buffer;
 
    mgaUpdateClipping( mmesa->glCtx );
    mgaCalcViewport( mmesa->glCtx );
-
-   mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
 }
 
 
@@ -828,23 +808,21 @@ static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
    case BUFFER_BIT_FRONT_LEFT:
       mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
-      mmesa->dirty |= MGA_UPLOAD_CONTEXT;
       mmesa->draw_buffer = MGA_FRONT;
-      mgaXMesaSetFrontClipRects( mmesa );
-      FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
       break;
    case BUFFER_BIT_BACK_LEFT:
       mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
       mmesa->draw_buffer = MGA_BACK;
-      mmesa->dirty |= MGA_UPLOAD_CONTEXT;
-      mgaXMesaSetBackClipRects( mmesa );
-      FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
       break;
    default:
       /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
       FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
       return;
    }
+
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+   mga_set_cliprects(mmesa);
+   FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE);
 }
 
 
index 7dbb5e5ddab97640bfb61374c09a4fd53dd7d8ca..b0dba7d04e12d81eca8f9fcaa82138730b972637 100644 (file)
@@ -399,8 +399,7 @@ void r128PageFlip( const __DRIdrawablePrivate *dPriv )
  * Buffer clear
  */
 
-static void r128Clear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                       GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
+static void r128Clear( GLcontext *ctx, GLbitfield mask )
 {
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
@@ -541,7 +540,7 @@ static void r128Clear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    }
 
    if ( mask )
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
 }
 
 
index efa0b64ed2557b2875e43fc0bfdde354d0d616a8..463bd64415b7f32f8b36ba8467f1cc0c4187a6f5 100644 (file)
@@ -605,8 +605,7 @@ void r200PageFlip( const __DRIdrawablePrivate *dPriv )
 /* ================================================================
  * Buffer clear
  */
-static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                       GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
+static void r200Clear( GLcontext *ctx, GLbitfield mask )
 {
    r200ContextPtr rmesa = R200_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
@@ -653,7 +652,7 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    if ( mask ) {
       if (R200_DEBUG & DEBUG_FALLBACKS)
         fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
    }
 
    if ( !flags ) 
index 2d947dea3af159ea29544deb34aaf4f9f3d8a163..91ec4f855c20fc306a70dbc202199e547443ed2d 100644 (file)
@@ -82,7 +82,8 @@ static const struct {
        { "LG2", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_LG2 },
        { "RCP", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_RCP },
        { "RSQ", 1, R300_FPI0_OUTC_REPL_ALPHA, R300_FPI2_OUTA_RSQ },
-       { "REPL_ALPHA", 1, R300_FPI0_OUTC_REPL_ALPHA, PFS_INVAL }
+       { "REPL_ALPHA", 1, R300_FPI0_OUTC_REPL_ALPHA, PFS_INVAL },
+       { "CMPH", 3, R300_FPI0_OUTC_CMPH, PFS_INVAL },
 };
 
 #define MAKE_SWZ3(x, y, z) (MAKE_SWIZZLE4(SWIZZLE_##x, \
@@ -180,7 +181,7 @@ static const pfs_reg_t undef = {
        valid: GL_FALSE
 };
 
-/* constant zero source */
+/* constant one source */
 static const pfs_reg_t pfs_one = {
        type: REG_TYPE_CONST,
        index: 0,
@@ -189,7 +190,16 @@ static const pfs_reg_t pfs_one = {
        valid: GL_TRUE
 };
 
-/* constant one source */
+/* constant half source */
+static const pfs_reg_t pfs_half = {
+       type: REG_TYPE_CONST,
+       index: 0,
+       v_swz: SWIZZLE_HHH,
+       s_swz: SWIZZLE_HALF,
+       valid: GL_TRUE
+};
+
+/* constant zero source */
 static const pfs_reg_t pfs_zero = {
        type: REG_TYPE_CONST,
        index: 0,
@@ -319,7 +329,6 @@ static pfs_reg_t emit_param4fv(struct r300_fragment_program *rp,
        return r;
 }
 
-#if 0
 static pfs_reg_t emit_const4fv(struct r300_fragment_program *rp, GLfloat *cp)
 { 
        pfs_reg_t r = undef;
@@ -330,13 +339,11 @@ static pfs_reg_t emit_const4fv(struct r300_fragment_program *rp, GLfloat *cp)
                ERROR("Out of hw constants!\n");
                return r;
        }
-       
-       COPY_4V(rp->constant[r.index], cp);
 
+       COPY_4V(rp->constant[r.index], cp);
        r.valid = GL_TRUE;
        return r;
 }
-#endif
 
 static __inline pfs_reg_t negate(pfs_reg_t r)
 {
@@ -773,13 +780,15 @@ static void emit_tex(struct r300_fragment_program *rp,
                cs->dest_in_node = 0;
        }
        
-       if (rp->cur_node == 0) rp->first_node_has_tex = 1;
+       if (rp->cur_node == 0)
+               rp->first_node_has_tex = 1;
 
-    rp->tex.inst[rp->tex.length++] = 0
-        | (hwsrc << R300_FPITX_SRC_SHIFT)
-        | (hwdest << R300_FPITX_DST_SHIFT)
-        | (unit << R300_FPITX_IMAGE_SHIFT)
-        | (opcode << R300_FPITX_OPCODE_SHIFT); /* not entirely sure about this */
+       rp->tex.inst[rp->tex.length++] = 0
+               | (hwsrc << R300_FPITX_SRC_SHIFT)
+               | (hwdest << R300_FPITX_DST_SHIFT)
+               | (unit << R300_FPITX_IMAGE_SHIFT)
+               /* not entirely sure about this */
+               | (opcode << R300_FPITX_OPCODE_SHIFT);
 
        cs->dest_in_node |= (1 << hwdest); 
        if (coord.type != REG_TYPE_CONST)
@@ -884,7 +893,7 @@ static void emit_arith(struct r300_fragment_program *rp, int op,
 
        vop = r300_fpop[op].v_op;
        sop = r300_fpop[op].s_op;
-       argc = r300_fpop[op].argc;      
+       argc = r300_fpop[op].argc;
 
        if ((mask & WRITEMASK_XYZ) || vop == R300_FPI0_OUTC_DP3)
                emit_vop = GL_TRUE;
@@ -1039,7 +1048,9 @@ static GLboolean parse_program(struct r300_fragment_program *rp)
        const struct prog_instruction *inst = mp->Base.Instructions;
        struct prog_instruction *fpi;
        pfs_reg_t src[3], dest, temp;
+       pfs_reg_t cnst;
        int flags, mask = 0;
+       GLfloat cnstv[4] = {0.0, 0.0, 0.0, 0.0};
 
        if (!inst || inst[0].Opcode == OPCODE_END) {
                ERROR("empty program?\n");
@@ -1179,7 +1190,66 @@ static GLboolean parse_program(struct r300_fragment_program *rp)
                                   flags);
                        break;
                case OPCODE_LIT:
-                       ERROR("LIT not implemented\n");
+                       /* LIT
+                        * if (s.x < 0) t.x = 0; else t.x = s.x;
+                        * if (s.y < 0) t.y = 0; else t.y = s.y;
+                        * if (s.w >  128.0) t.w =  128.0; else t.w = s.w;
+                        * if (s.w < -128.0) t.w = -128.0; else t.w = s.w;
+                        * r.x = 1.0
+                        * if (t.x > 0) r.y = pow(t.y, t.w); else r.y = 0;
+                        * Also r.y = 0 if t.y < 0
+                        * For the t.x > 0 FGLRX use the CMPH opcode which
+                        * change the compare to (t.x + 0.5) > 0.5 we may
+                        * save one instruction by doing CMP -t.x 
+                        */
+                       cnstv[0] = cnstv[1] = cnstv[2] = cnstv[4] = 0.50001;
+                       src[0] = t_src(rp, fpi->SrcReg[0]);
+                       temp = get_temp_reg(rp);
+                       cnst = emit_const4fv(rp, cnstv);
+                       emit_arith(rp, PFS_OP_CMP, temp,
+                                  WRITEMASK_X | WRITEMASK_Y,
+                                  src[0], pfs_zero, src[0], flags);
+                       emit_arith(rp, PFS_OP_MIN, temp, WRITEMASK_Z,
+                                  swizzle(keep(src[0]), W, W, W, W),
+                                  cnst, undef, flags);
+                       emit_arith(rp, PFS_OP_LG2, temp, WRITEMASK_W,
+                                  swizzle(temp, Y, Y, Y, Y),
+                                  undef, undef, flags);
+                       emit_arith(rp, PFS_OP_MAX, temp, WRITEMASK_Z,
+                                  temp, negate(cnst), undef, flags);
+                       emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_W,
+                                  temp, swizzle(temp, Z, Z, Z, Z),
+                                  pfs_zero, flags);
+                       emit_arith(rp, PFS_OP_EX2, temp, WRITEMASK_W,
+                                  temp, undef, undef, flags);
+                       emit_arith(rp, PFS_OP_MAD, dest, WRITEMASK_Y,
+                                  swizzle(keep(temp), X, X, X, X),
+                                  pfs_one, pfs_zero, flags);
+#if 0
+                       emit_arith(rp, PFS_OP_MAD, temp, WRITEMASK_X,
+                                  temp, pfs_one, pfs_half, flags);
+                       emit_arith(rp, PFS_OP_CMPH, temp, WRITEMASK_Z,
+                                  swizzle(keep(temp), W, W, W, W),
+                                  pfs_zero, swizzle(keep(temp), X, X, X, X),
+                                  flags);
+#else
+                       emit_arith(rp, PFS_OP_CMP, temp, WRITEMASK_Z,
+                                  pfs_zero,
+                                  swizzle(keep(temp), W, W, W, W),
+                                  negate(swizzle(keep(temp), X, X, X, X)),
+                                  flags);
+#endif
+                       emit_arith(rp, PFS_OP_CMP, dest, WRITEMASK_Z,
+                                  pfs_zero, temp,
+                                  negate(swizzle(keep(temp), Y, Y, Y, Y)),
+                                  flags);
+                       emit_arith(rp, PFS_OP_MAD, dest,
+                                  WRITEMASK_X | WRITEMASK_W,
+                                  pfs_one,
+                                  pfs_one,
+                                  pfs_zero,
+                                  flags);
+                       free_temp(rp, temp);
                        break;
                case OPCODE_LRP:
                        src[0] = t_src(rp, fpi->SrcReg[0]);
@@ -1345,7 +1415,7 @@ static GLboolean parse_program(struct r300_fragment_program *rp)
                        return GL_FALSE;
 
        }
-       
+
        return GL_TRUE;
 }
 
index e7dbaf973e293c9219808021bea83926077e8266..4bbaa07e01271173bb4fa47a8241a520f01bbd37 100644 (file)
@@ -78,7 +78,8 @@ typedef struct r300_fragment_program_swizzle {
 #define PFS_OP_RCP 9
 #define PFS_OP_RSQ 10
 #define PFS_OP_REPL_ALPHA 11
-#define MAX_PFS_OP 11
+#define PFS_OP_CMPH 12
+#define MAX_PFS_OP 12
 
 #define PFS_FLAG_SAT   (1 << 0)
 #define PFS_FLAG_ABS   (1 << 1)
index 7775ca96e4b856a3194e168d3923aab03b1f2e11..87276a11aed6335c0c18de26a4746480d23240cb 100644 (file)
@@ -477,8 +477,7 @@ static void r300EmitClearState(GLcontext * ctx)
 /**
  * Buffer clear
  */
-static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean allFoo,
-                     GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
+static void r300Clear(GLcontext * ctx, GLbitfield mask)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
@@ -520,7 +519,7 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean allFoo,
                if (RADEON_DEBUG & DEBUG_FALLBACKS)
                        fprintf(stderr, "%s: swrast clear, mask: %x\n",
                                __FUNCTION__, mask);
-               _swrast_Clear(ctx, mask, 0, 0, 0, 0, 0);
+               _swrast_Clear(ctx, mask);
        }
 
        swapped = r300->radeon.doPageFlip && (r300->radeon.sarea->pfCurrentPage == 1);
index f3d8fa60f5bbbb90b2fc20089b5369f343d5a3e0..9f636ec1d2e0aa1d0e8f6d075b03297511f12ae4 100644 (file)
@@ -1001,6 +1001,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  *  - DP4: Use OUTC_DP4, OUTA_DP4
  *  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
  *  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+ *  - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
  *  - CMP: If ARG2 < 0, return ARG1, else return ARG0
  *  - FLR: use FRC+MAD
  *  - XPD: use MAD+MAD
@@ -1138,6 +1139,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_FPI0_OUTC_DP4                (2 << 23)
 #       define R300_FPI0_OUTC_MIN                (4 << 23)
 #       define R300_FPI0_OUTC_MAX                (5 << 23)
+#       define R300_FPI0_OUTC_CMPH               (7 << 23)
 #       define R300_FPI0_OUTC_CMP                (8 << 23)
 #       define R300_FPI0_OUTC_FRC                (9 << 23)
 #       define R300_FPI0_OUTC_REPL_ALPHA         (10 << 23)
index 5a98226300f89a66698c2c2d4d6b2af18ec77273..6aff04fd27fed2449083e4ab71d44968055c62c3 100644 (file)
@@ -460,7 +460,6 @@ static void update_depth(GLcontext* ctx)
 static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
 {
        r300ContextPtr r300 = R300_CONTEXT(ctx);
-       uint32_t newval;
 
        if (RADEON_DEBUG & DEBUG_STATE)
                fprintf(stderr, "%s( %s = %s )\n", __FUNCTION__,
index 1d78918a2b011d93df9429c350eefa9506d3ced4..cc356afb2301b9fa717947f46bb2177bed7f045b 100644 (file)
@@ -171,7 +171,6 @@ static void r300SetTexImages(r300ContextPtr rmesa,
        GLint i, texelBytes;
        GLint numLevels;
        GLint log2Width, log2Height, log2Depth;
-       const GLuint ui = 1;
 
        /* Set the hardware texture format
         */
index 09321126d69c64a1ed72d2cf766b63caf26a8ed5..62a6e1e5f79877527d5bce9b6139ffbc68e3eb5f 100644 (file)
@@ -98,27 +98,11 @@ static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
        }
 }
 
-
-/* Return the width and height of the given buffer.
- */
-static void radeonGetBufferSize(GLframebuffer * buffer,
-                               GLuint * width, GLuint * height)
-{
-       GET_CURRENT_CONTEXT(ctx);
-       radeonContextPtr radeon = RADEON_CONTEXT(ctx);
-
-       LOCK_HARDWARE(radeon);
-       *width = radeon->dri.drawable->w;
-       *height = radeon->dri.drawable->h;
-       UNLOCK_HARDWARE(radeon);
-}
-
-
 /* Initialize the driver's misc functions.
  */
 static void radeonInitDriverFuncs(struct dd_function_table *functions)
 {
-       functions->GetBufferSize = radeonGetBufferSize;
+       functions->GetBufferSize = NULL;
        functions->GetString = radeonGetString;
 }
 
@@ -158,7 +142,8 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
        /* DRI fields */
        radeon->dri.context = driContextPriv;
        radeon->dri.screen = sPriv;
-       radeon->dri.drawable = NULL;    /* Set by XMesaMakeCurrent */
+       radeon->dri.drawable = NULL;
+       radeon->dri.readable = NULL;
        radeon->dri.hwContext = driContextPriv->hHWContext;
        radeon->dri.hwLock = &sPriv->pSAREA->lock;
        radeon->dri.fd = sPriv->fd;
@@ -282,12 +267,15 @@ GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
                        fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
                                radeon->glCtx);
 
-               if (radeon->dri.drawable != driDrawPriv) {
+               if ( (radeon->dri.drawable != driDrawPriv)
+                    || (radeon->dri.readable != driReadPriv) ) {
+
                        driDrawableInitVBlank(driDrawPriv,
                                              radeon->vblank_flags,
                                              &radeon->vbl_seq);
                        radeon->dri.drawable = driDrawPriv;
-                       
+                       radeon->dri.readable = driReadPriv;
+
                        r300UpdateWindow(radeon->glCtx);
                        r300UpdateViewportOffset(radeon->glCtx);
                }
index 0ec6466e441778fd5938a1d4606e46ab990885b4..07a0c7cbd6d4dbae33a398c97e56f00205116609 100644 (file)
@@ -120,7 +120,15 @@ extern void radeonTclFallback(GLcontext * ctx, GLuint bit, GLboolean mode);
 struct radeon_dri_mirror {
        __DRIcontextPrivate *context;   /* DRI context */
        __DRIscreenPrivate *screen;     /* DRI screen */
-       __DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */
+       /**
+        * DRI drawable bound to this context for drawing.
+        */
+       __DRIdrawablePrivate    *drawable;      
+
+       /**
+        * DRI drawable bound to this context for reading.
+        */
+       __DRIdrawablePrivate    *readable;
 
        drm_context_t hwContext;
        drm_hw_lock_t *hwLock;
index 0e1e6512dbf199ae54c9e30e6cab7f37653d4cff..a00da6c8bc371efb4ffcef3daec30adc84f21f2b 100644 (file)
@@ -75,34 +75,30 @@ static void radeonUpdatePageFlipping(radeonContextPtr radeon)
  * Called by radeonGetLock() after the lock has been obtained.
  */
 static void r300RegainedLock(radeonContextPtr radeon)
-{
-       __DRIdrawablePrivate *dPriv = radeon->dri.drawable;
+{      
        int i;
+       __DRIdrawablePrivate *const drawable = radeon->dri.drawable;
        r300ContextPtr r300 = (r300ContextPtr)radeon;
+       drm_radeon_sarea_t *sarea = radeon->sarea;
 
-       if (radeon->lastStamp != dPriv->lastStamp) {
-               _mesa_resize_framebuffer(radeon->glCtx,
-                       (GLframebuffer*)dPriv->driverPrivate,
-                       dPriv->w, dPriv->h);
-
+       if ( radeon->lastStamp != drawable->lastStamp ) {
                radeonUpdatePageFlipping(radeon);
-
-               if (radeon->glCtx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT)
-                       radeonSetCliprects(radeon, GL_BACK_LEFT);
-               else
-                       radeonSetCliprects(radeon, GL_FRONT_LEFT);
-
+               radeonSetCliprects(radeon);
 #if 1
                r300UpdateViewportOffset( radeon->glCtx );
-               driUpdateFramebufferSize(radeon->glCtx, dPriv);
+               driUpdateFramebufferSize(radeon->glCtx, drawable);
 #else
                radeonUpdateScissor(radeon->glCtx);
 #endif
-               radeon->lastStamp = dPriv->lastStamp;
+               radeon->lastStamp = drawable->lastStamp;
        }
 
-       for (i = 0; i < r300->nr_heaps; i++) {
-               DRI_AGE_TEXTURES(r300->texture_heaps[i]);
+       if (sarea->ctx_owner != radeon->dri.hwContext) {
+               sarea->ctx_owner = radeon->dri.hwContext;
+
+               for (i = 0; i < r300->nr_heaps; i++) {
+                       DRI_AGE_TEXTURES(r300->texture_heaps[i]);
+               }
        }
 }
 
@@ -116,11 +112,11 @@ static void r300RegainedLock(radeonContextPtr radeon)
  */
 void radeonGetLock(radeonContextPtr radeon, GLuint flags)
 {
-       __DRIdrawablePrivate *dPriv = radeon->dri.drawable;
+       __DRIdrawablePrivate *const drawable = radeon->dri.drawable;
+       __DRIdrawablePrivate *const readable = radeon->dri.readable;
        __DRIscreenPrivate *sPriv = radeon->dri.screen;
-       drm_radeon_sarea_t *sarea = radeon->sarea;
        
-       assert (dPriv != NULL);
+       assert (drawable != NULL);
 
        drmGetLock(radeon->dri.fd, radeon->dri.hwContext, flags);
 
@@ -132,10 +128,10 @@ void radeonGetLock(radeonContextPtr radeon, GLuint flags)
         * Since the hardware state depends on having the latest drawable
         * clip rects, all state checking must be done _after_ this call.
         */
-       DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
-
-       if (sarea->ctx_owner != radeon->dri.hwContext)
-               sarea->ctx_owner = radeon->dri.hwContext;
+       DRI_VALIDATE_DRAWABLE_INFO( sPriv, drawable );
+       if (drawable != readable) {
+               DRI_VALIDATE_DRAWABLE_INFO( sPriv, readable );
+       }
 
        if (IS_R300_CLASS(radeon->radeonScreen))
                r300RegainedLock(radeon);
index 7726c22f4277173be406a1ea4816dff268b85687..1b1ec3df3ce97b04c1dedc1d1f505177aadac193 100644 (file)
@@ -49,7 +49,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_ioctl.h"
 #include "radeon_state.h"
 #include "r300_ioctl.h"
-
+#include "framebuffer.h"
 
 /* =============================================================
  * Scissoring
@@ -137,7 +137,6 @@ static void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h
        if (ctx->Scissor.Enabled) {
                /* We don't pipeline cliprect changes */
                r300Flush(ctx);
-
                radeonUpdateScissor(ctx);
        }
 }
@@ -146,31 +145,46 @@ static void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h
 /**
  * Update cliprects and scissors.
  */
-void radeonSetCliprects(radeonContextPtr radeon, GLenum mode)
+void radeonSetCliprects(radeonContextPtr radeon)
 {
-       __DRIdrawablePrivate *dPriv = radeon->dri.drawable;
-
-       switch (mode) {
-       case GL_FRONT_LEFT:
-               radeon->numClipRects = dPriv->numClipRects;
-               radeon->pClipRects = dPriv->pClipRects;
-               break;
-       case GL_BACK_LEFT:
-               /* Can't ignore 2d windows if we are page flipping.
-                */
-               if (dPriv->numBackClipRects == 0 || radeon->doPageFlip) {
-                       radeon->numClipRects = dPriv->numClipRects;
-                       radeon->pClipRects = dPriv->pClipRects;
+       __DRIdrawablePrivate *const drawable = radeon->dri.drawable;
+       __DRIdrawablePrivate *const readable = radeon->dri.readable;
+       GLframebuffer *const draw_fb = (GLframebuffer*)drawable->driverPrivate;
+       GLframebuffer *const read_fb = (GLframebuffer*)readable->driverPrivate;
+
+       if (draw_fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
+               /* Can't ignore 2d windows if we are page flipping. */
+               if (drawable->numBackClipRects == 0 || radeon->doPageFlip) {
+                       radeon->numClipRects = drawable->numClipRects;
+                       radeon->pClipRects = drawable->pClipRects;
                } else {
-                       radeon->numClipRects = dPriv->numBackClipRects;
-                       radeon->pClipRects = dPriv->pBackClipRects;
+                       radeon->numClipRects = drawable->numBackClipRects;
+                       radeon->pClipRects = drawable->pBackClipRects;
+               }
+       } else {
+               /* front buffer (or none, or multiple buffers */
+               radeon->numClipRects = drawable->numClipRects;
+               radeon->pClipRects = drawable->pClipRects;
+       }
+
+       if ((draw_fb->Width != drawable->w) ||
+           (draw_fb->Height != drawable->h)) {
+               printf("w,h %d %d\n",
+                      radeon->glCtx->DrawBuffer->Width,
+                      radeon->glCtx->DrawBuffer->Height);
+
+               _mesa_resize_framebuffer(radeon->glCtx, draw_fb,
+                                        drawable->w, drawable->h);
+               draw_fb->Initialized = GL_TRUE;
+       }
+
+       if (drawable != readable) {
+               if ((read_fb->Width != readable->w) ||
+                   (read_fb->Height != readable->h)) {
+                       _mesa_resize_framebuffer(radeon->glCtx, read_fb,
+                                                readable->w, readable->h);
+                       read_fb->Initialized = GL_TRUE;
                }
-               break;
-       default:
-               fprintf(stderr, "bad mode in radeonSetCliprects\n");
-               radeon->numClipRects = 0;
-               radeon->pClipRects = 0;
-               return;
        }
 
        if (radeon->state.scissor.enabled)
index 636bf5d0086a7a7494c08657cc42fd34f3fce8c6..c2d041eb4aecf62e5e53757ba0f91022d8eb99f9 100644 (file)
@@ -34,7 +34,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_context.h"
 
 extern void radeonRecalcScissorRects(radeonContextPtr radeon);
-extern void radeonSetCliprects(radeonContextPtr radeon, GLenum mode);
+extern void radeonSetCliprects(radeonContextPtr radeon);
 extern void radeonUpdateScissor(GLcontext* ctx);
 
 extern void radeonEnable(GLcontext* ctx, GLenum cap, GLboolean state);
index d9eec622f34cd15068295dd27fb5ee2ac82d100d..737490fcde0143b2eb7e27bbdd0a5229b3cf7786 100644 (file)
@@ -1021,8 +1021,7 @@ void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
  */
 #define RADEON_MAX_CLEARS      256
 
-static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                        GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
+static void radeonClear( GLcontext *ctx, GLbitfield mask )
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
@@ -1071,7 +1070,7 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    if ( mask ) {
       if (RADEON_DEBUG & DEBUG_FALLBACKS)
         fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
    }
 
    if ( !flags ) 
index f1a1728eaab624b2d2f39fbfcc7f651b03d1a6fa..e19202fa44324a956c894e6b58d67c32a6397c84 100644 (file)
@@ -40,6 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "light.h"
 #include "state.h"
 #include "context.h"
+#include "framebuffer.h"
 
 #include "vbo/vbo.h"
 #include "tnl/tnl.h"
@@ -1659,14 +1660,14 @@ void radeonSetCliprects( radeonContextPtr rmesa )
    }
 
    if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
-      _mesa_resize_framebuffer(&rmesa->glCtx, draw_fb,
+      _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
                               drawable->w, drawable->h);
       draw_fb->Initialized = GL_TRUE;
    }
 
    if (drawable != readable) {
       if ((read_fb->Width != readable->w) || (read_fb->Height != readable->h)) {
-        _mesa_resize_framebuffer(&rmesa->glCtx, read_fb,
+        _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
                                  readable->w, readable->h);
         read_fb->Initialized = GL_TRUE;
       }
index 08ce0f565c2adb2c671814844f77e95e98cc019b..b86b618c1172e13895ac844259b139eb0e868ab5 100644 (file)
@@ -73,8 +73,7 @@ static void s3vDDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
  * Buffer clear
  */
 
-static void s3vDDClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                        GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
+static void s3vDDClear( GLcontext *ctx, GLbitfield mask )
 {
        s3vContextPtr vmesa = S3V_CONTEXT(ctx);
        unsigned int _stride;
@@ -163,7 +162,7 @@ static void s3vDDClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
        if ( mask )
                DEBUG(("still masked ;3(\n")); */ /* yes */
 #else
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
 #endif
 }
 
index 7513a07e8523557b8b1b865dae4ff96094ad5a64..4eac1fb3498d49026920f337e0c4f5142a9f0e89 100644 (file)
@@ -327,8 +327,7 @@ static GLuint savageIntersectClipRects(drm_clip_rect_t *dest,
 }
 
 
-static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-                          GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo ) 
+static void savageDDClear( GLcontext *ctx, GLbitfield mask )
 {
    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
    GLuint colorMask, depthMask, clearColor, clearDepth, flags;
@@ -426,7 +425,7 @@ static void savageDDClear( GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    }
 
    if (mask) 
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
+      _swrast_Clear( ctx, mask );
 }
 
 /*
index d8f39b31c7d4bdd0bbfa4884f7f98b7eb6d55a7f..48db19566c663e75baf4759072a14ab72235d54d 100644 (file)
@@ -69,8 +69,7 @@ sis6326UpdateZPattern(sisContextPtr smesa, GLclampd z)
 }
 
 void
-sis6326DDClear(GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
-               GLint xFoo, GLint yFoo, GLint widthFoo, GLint heightFoo)
+sis6326DDClear(GLcontext *ctx, GLbitfield mask)
 {
    sisContextPtr smesa = SIS_CONTEXT(ctx);
    GLint x1, y1, width1, height1;
@@ -110,7 +109,7 @@ sis6326DDClear(GLcontext *ctx, GLbitfield mask, GLboolean allFoo,
    UNLOCK_HARDWARE();
 
    if (mask != 0)
-      _swrast_Clear(ctx, mask, 0, 0, 0, 0, 0);
+      _swrast_Clear(ctx, mask);
 }
 
 
index 64b68708717c22f1b737fda66ff6b2c526c88848..fb92d06c7355db63087531a0da379d5ec12e4abc 100644 (file)
@@ -95,8 +95,7 @@ sisUpdateZStencilPattern( sisContextPtr smesa, GLclampd z, GLint stencil )
 }
 
 void
-sisDDClear( GLcontext * ctx, GLbitfield mask, GLboolean allFoo,
-           GLint xFoo, GLint yFoo, GLint widthFoo, GLint heightFoo )
+sisDDClear( GLcontext * ctx, GLbitfield mask )
 {
    sisContextPtr smesa = SIS_CONTEXT(ctx);
 
@@ -145,7 +144,7 @@ sisDDClear( GLcontext * ctx, GLbitfield mask, GLboolean allFoo,
    UNLOCK_HARDWARE();
 
    if (mask != 0)
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0);
+      _swrast_Clear( ctx, mask);
 }
 
 
@@ -329,9 +328,7 @@ sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x, GLint y,
                        GLint width, GLint height )
 {
    sisContextPtr smesa = SIS_CONTEXT(ctx);
-
    int count;
-   GLuint depth = smesa->bytesPerPixel;
    drm_clip_rect_t *pExtents = NULL;
    GLint xx, yy;
    GLint x0, y0, width0, height0;
@@ -379,8 +376,6 @@ sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x, GLint y,
       if (width <= 0 || height <= 0)
        continue;
 
-      int cmd;
-
       mWait3DCmdQueue (8);
       MMIO(REG_SRC_PITCH, (smesa->bytesPerPixel == 4) ? 
                           BLIT_DEPTH_32 : BLIT_DEPTH_16);
index 4fd692ec240d38e665feb4fe12422b4eaa48f073..8f52cfe098e28d5561bc4836cceeb25d98255f61 100644 (file)
@@ -209,7 +209,7 @@ sisCreateBuffer( __DRIscreenPrivate *driScrnPriv,
                  const __GLcontextModes *mesaVis,
                  GLboolean isPixmap )
 {
-   sisScreenPtr screen = (sisScreenPtr) driScrnPriv->private;
+   /*sisScreenPtr screen = (sisScreenPtr) driScrnPriv->private;*/
    struct gl_framebuffer *fb;
 
    if (isPixmap)
index 580a522bf34b8323dba3bceb67b18098512a9704..8f7e2acb92d150883959ba0de09d819f1aac1454 100644 (file)
@@ -35,15 +35,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "sis_context.h"
 
 /* sis6326_clear.c */
-extern void sis6326DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                           GLint x, GLint y, GLint width, GLint height );
+extern void sis6326DDClear( GLcontext *ctx, GLbitfield mask );
 extern void sis6326DDClearColor( GLcontext * ctx, const GLfloat color[4] );
 extern void sis6326DDClearDepth( GLcontext * ctx, GLclampd d );
 extern void sis6326UpdateZPattern(sisContextPtr smesa, GLclampd z);
 
 /* sis_clear.c */
-extern void sisDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                       GLint x, GLint y, GLint width, GLint height );
+extern void sisDDClear( GLcontext *ctx, GLbitfield mask );
 extern void sisDDClearColor( GLcontext * ctx, const GLfloat color[4] );
 extern void sisDDClearDepth( GLcontext * ctx, GLclampd d );
 extern void sisDDClearStencil( GLcontext * ctx, GLint s );
index 3301d948e115c190dae013327bd34cee88b141e9..f36c97bfebec1c5ed476ce18d4c16b57b4a674e0 100644 (file)
@@ -46,9 +46,7 @@
 
 /* Clear the color and/or depth buffers.
  */
-static void tdfxClear( GLcontext *ctx,
-                       GLbitfield mask, GLboolean all,
-                       GLint xFoo, GLint yFoo, GLint widthFoo, GLint heightFoo)
+static void tdfxClear( GLcontext *ctx, GLbitfield mask )
 {
    tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
    GLbitfield softwareMask = mask & (BUFFER_BIT_ACCUM);
@@ -312,7 +310,7 @@ static void tdfxClear( GLcontext *ctx,
    }
 
    if (softwareMask)
-      _swrast_Clear( ctx, softwareMask, 0, 0, 0, 0, 0);
+      _swrast_Clear(ctx, softwareMask);
 }
 
 
index 3e6011a2ac152013e5543c47f491cf7e118d9de9..c3fe7bebd3e8841fddfc24bfd4b08e61fa5fb39b 100644 (file)
@@ -1404,7 +1404,6 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
          GLint mipWidth, mipHeight;
          tdfxMipMapLevel *mip;
          struct gl_texture_image *mipImage;
-         const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
          const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
    
          assert(!texImage->IsCompressed);
@@ -1425,7 +1424,7 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
                              mipWidth, mipHeight, border,
                              format, type,
                              NULL);
-            mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+            mipImage = _mesa_select_tex_image(ctx, texObj, target, level);
             mip = TDFX_TEXIMAGE_DATA(mipImage);
             _mesa_halve2x2_teximage2d(ctx,
                                       texImage,
@@ -1514,7 +1513,6 @@ tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
       GLint mipWidth, mipHeight;
       tdfxMipMapLevel *mip;
       struct gl_texture_image *mipImage;
-      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
       const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
 
       assert(!texImage->IsCompressed);
@@ -1534,7 +1532,7 @@ tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
             break;
          }
          ++level;
-         mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+         mipImage = _mesa_select_tex_image(ctx, texObj, target, level);
          mip = TDFX_TEXIMAGE_DATA(mipImage);
          _mesa_halve2x2_teximage2d(ctx,
                                    texImage,
index 6cdf23092adf260e51280c483399e86012258d37..5303bd422ed3ca36d2cc9a5cea082fdec5cb9510 100644 (file)
@@ -150,8 +150,7 @@ void tridentCopyBuffer( const __DRIdrawablePrivate *dPriv )
 }
 
 
-static void tridentDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                            GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
+static void tridentDDClear( GLcontext *ctx, GLbitfield mask )
 {
    tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx);
    unsigned char *MMIO = tmesa->tridentScreen->mmio.map;
@@ -297,7 +296,7 @@ if (flags & DRM_TRIDENT_FRONT) {
    UNLOCK_HARDWARE(tmesa);
 
    if ( mask )
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0);
+      _swrast_Clear( ctx, mask );
 }
 
 static void tridentDDShadeModel( GLcontext *ctx, GLenum mode )
index 86077bc4d4eb177f9cc7d640c9b968b515b2c7e6..dd2e93b286f8e3db72351d35ad1958b488d21441 100644 (file)
@@ -202,8 +202,7 @@ static void viaFillBuffer(struct via_context *vmesa,
 
 
 
-static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                     GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo)
+static void viaClear(GLcontext *ctx, GLbitfield mask)
 {
    struct via_context *vmesa = VIA_CONTEXT(ctx);
    __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
@@ -262,6 +261,7 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
       drm_clip_rect_t *boxes, *tmp_boxes = 0;
       int nr = 0;
       GLint cx, cy, cw, ch;
+      GLboolean all;
 
       LOCK_HARDWARE(vmesa);
            
@@ -270,6 +270,7 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
       cy = ctx->DrawBuffer->_Ymin;
       cw = ctx->DrawBuffer->_Xmax - cx;
       ch = ctx->DrawBuffer->_Ymax - cy;
+      all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);
 
       /* flip top to bottom */
       cy = dPriv->h - cy - ch;
@@ -335,7 +336,7 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
    
    if (mask)
-      _swrast_Clear(ctx, mask, 0, 0, 0, 0, 0);
+      _swrast_Clear(ctx, mask);
 }
 
 
index 4fbbe61ab84bd7f4cde2bb6ae940445fc6c1919e..47d7f2bdb9919080007ff087f94a73f1406fd7a4 100644 (file)
@@ -313,10 +313,14 @@ static void gl_ggiSetClearColor(GLcontext *ctx, const GLfloat color[4])
        ggi_ctx->clearcolor = col;
 }
 
-static void gl_ggiClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
-                       GLint x, GLint y, GLint width, GLint height)
+static void gl_ggiClear(GLcontext *ctx, GLbitfield mask)
 {
        ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+        int x = ctx->DrawBuffer->_Xmin;
+        int y = ctx->DrawBuffer->_Ymin;
+        int w = ctx->DrawBuffer->_Xmax - x;
+        int h = ctx->DrawBuffer->_Ymax - y;
+        GLboolean all = (w == ctx->DrawBuffer->Width && h == ctx->DrawBuffer->height)
        
        GGIMESADPRINT_CORE("gl_ggiClear() called\n");
 
@@ -336,7 +340,7 @@ static void gl_ggiClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
 
                mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
        }
-       _swrast_Clear(ctx, mask, all, x, y, width, height);
+       _swrast_Clear(ctx, mask);
        
 }
 
index e218a316aa8ea574f7de80c81a233f9f2ff1ccd2..f49c3889f6659033fa2ec07bbceb88ccb3ac5b5b 100644 (file)
@@ -162,9 +162,7 @@ fxDDClearColor(GLcontext * ctx, const GLfloat color[4])
 
 
 /* Clear the color and/or depth buffers */
-static void fxDDClear( GLcontext *ctx,
-                       GLbitfield mask, GLboolean all,
-                       GLint x, GLint y, GLint width, GLint height )
+static void fxDDClear( GLcontext *ctx, GLbitfield mask )
 {
    fxMesaContext fxMesa = FX_CONTEXT(ctx);
    GLbitfield softwareMask = mask & (BUFFER_BIT_ACCUM);
@@ -173,8 +171,7 @@ static void fxDDClear( GLcontext *ctx,
    const FxU8 clearS = (FxU8) (ctx->Stencil.Clear & 0xff);
 
    if ( TDFX_DEBUG & MESA_VERBOSE ) {
-      fprintf( stderr, "fxDDClear( %d, %d, %d, %d )\n",
-                      (int) x, (int) y, (int) width, (int) height );
+      fprintf( stderr, "fxDDClear\n");
    }
 
    /* we can't clear accum buffers nor stereo */
@@ -389,7 +386,7 @@ static void fxDDClear( GLcontext *ctx,
    grRenderBuffer(fxMesa->currentFB);
 
    if (softwareMask)
-      _swrast_Clear( ctx, softwareMask, all, x, y, width, height );
+      _swrast_Clear( ctx, softwareMask );
 }
 
 
index 54b6c977a7baca8da4ddb828280e3c0ea94be06d..ae5104d0c018b4de54a0484216c753c8329a2cc4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: svgamesa15.c,v 1.11 2002/11/11 18:42:39 brianp Exp $ */
+/* $Id: svgamesa15.c,v 1.11.36.1 2006/11/02 12:02:17 alanh Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -66,10 +66,14 @@ void __clear_color15( GLcontext *ctx, const GLfloat color[4] )
 /*   SVGAMesa->clear_hicolor=(red)<<10 | (green)<<5 | (blue);*/
 }   
 
-void __clear15( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                GLint x, GLint y, GLint width, GLint height )
+void __clear15( GLcontext *ctx, GLbitfield mask )
 {
    int i, j;
+   int x = ctx->DrawBuffer->_Xmin;
+   int y = ctx->DrawBuffer->_Ymin;
+   int width = ctx->DrawBuffer->_Xmax - x;
+   int height = ctx->DrawBuffer->_Ymax - y;
+   GLboolean all = (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->height)
 
    if (mask & DD_FRONT_LEFT_BIT) {
       GLshort *shortBuffer=(void *)SVGABuffer.FrontBuffer;
@@ -105,7 +109,7 @@ void __clear15( GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
 
    if (mask)
-      _swrast_Clear( ctx, mask, all, x, y, width, height );
+      _swrast_Clear( ctx, mask );
 }
 
 void __write_rgba_span15( const GLcontext *ctx, GLuint n, GLint x, GLint y,
index 72ac8183294e87437eeae48443c42a50419c9c27..a59937bfb4b003e67cf9f2368d9c9ff2735137d3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: svgamesa16.c,v 1.11 2002/11/11 18:42:40 brianp Exp $ */
+/* $Id: svgamesa16.c,v 1.11.36.1 2006/11/02 12:02:17 alanh Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -69,10 +69,14 @@ void __clear_color16( GLcontext *ctx, const GLfloat color[4] )
 /*    SVGAMesa->clear_hicolor=(red)<<11 | (green)<<5 | (blue); */
 }   
 
-void __clear16( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                GLint x, GLint y, GLint width, GLint height )
+void __clear16( GLcontext *ctx, GLbitfield mask )
 {
    int i,j;
+   int x = ctx->DrawBuffer->_Xmin;
+   int y = ctx->DrawBuffer->_Ymin;
+   int width = ctx->DrawBuffer->_Xmax - x;
+   int height = ctx->DrawBuffer->_Ymax - y;
+   GLboolean all = (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->height)
 
    if (mask & DD_FRONT_LEFT_BIT) {
       if (all) {
@@ -108,7 +112,7 @@ void __clear16( GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
 
    if (mask)
-      _swrast_Clear( ctx, mask, all, x, y, width, height );
+      _swrast_Clear( ctx, mask );
 }
 
 void __write_rgba_span16( const GLcontext *ctx, GLuint n, GLint x, GLint y,
index 07491cc67ac3f006e739897b31d4b296cbf7a490..dd15bf38db208474abfcc6dcc1de386eff1f1c38 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: svgamesa24.c,v 1.12 2002/11/11 18:42:41 brianp Exp $ */
+/* $Id: svgamesa24.c,v 1.12.36.1 2006/11/02 12:02:17 alanh Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -91,10 +91,14 @@ void __clear_color24( GLcontext *ctx, const GLfloat color[4] )
 /*   SVGAMesa->clear_truecolor = red<<16 | green<<8 | blue; */
 }
 
-void __clear24( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                GLint x, GLint y, GLint width, GLint height )
+void __clear24( GLcontext *ctx, GLbitfield mask )
 {
    int i,j;
+   int x = ctx->DrawBuffer->_Xmin;
+   int y = ctx->DrawBuffer->_Ymin;
+   int width = ctx->DrawBuffer->_Xmax - x;
+   int height = ctx->DrawBuffer->_Ymax - y;
+   GLboolean all = (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->height)
    
    if (mask & DD_FRONT_LEFT_BIT) {
       if (all) {
@@ -140,7 +144,7 @@ void __clear24( GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
 
    if (mask)
-      _swrast_Clear( ctx, mask, all, x, y, width, height );
+      _swrast_Clear( ctx, mask );
 }
 
 void __write_rgba_span24( const GLcontext *ctx, GLuint n, GLint x, GLint y,
index 8a366998d6bb3567ac359d26d5c7254360a02281..4da18795d8ca46a8df084e868cdc3967971e0bc5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: svgamesa32.c,v 1.12 2002/11/11 18:42:42 brianp Exp $ */
+/* $Id: svgamesa32.c,v 1.12.36.1 2006/11/02 12:02:17 alanh Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -85,10 +85,14 @@ void __clear_color32( GLcontext *ctx, const GLfloat color[4] )
    SVGAMesa->clear_truecolor = (col[0] << 16) | (col[1] << 8) | col[2];
 }
 
-void __clear32( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                GLint x, GLint y, GLint width, GLint height )
+void __clear32( GLcontext *ctx, GLbitfield mask )
 {
    int i,j;
+   int x = ctx->DrawBuffer->_Xmin;
+   int y = ctx->DrawBuffer->_Ymin;
+   int width = ctx->DrawBuffer->_Xmax - x;
+   int height = ctx->DrawBuffer->_Ymax - y;
+   GLboolean all = (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->height)
    
    if (mask & DD_FRONT_LEFT_BIT) {
       if (all) {
@@ -124,7 +128,7 @@ void __clear32( GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
 
    if (mask)
-      _swrast_Clear( ctx, mask, all, x, y, width, height );
+      _swrast_Clear( ctx, mask );
 }
 
 void __write_rgba_span32( const GLcontext *ctx, GLuint n, GLint x, GLint y,
index fd880ef85ad3db442bf36e8328d3bfee53324886..4264fcd9599868fb7fea1ddca4db5103205e0ae0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: svgamesa8.c,v 1.9 2005/05/04 20:11:39 brianp Exp $ */
+/* $Id: svgamesa8.c,v 1.9.10.1 2006/11/02 12:02:17 alanh Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -60,10 +60,14 @@ void __clear_index8( GLcontext *ctx, GLuint index )
    SVGAMesa->clear_index = index;
 }
 
-void __clear8( GLcontext *ctx, GLbitfield mask, GLboolean all,
-               GLint x, GLint y, GLint width, GLint height )
+void __clear8( GLcontext *ctx, GLbitfield mask )
 {
    int i,j;
+   int x = ctx->DrawBuffer->_Xmin;
+   int y = ctx->DrawBuffer->_Ymin;
+   int width = ctx->DrawBuffer->_Xmax - x;
+   int height = ctx->DrawBuffer->_Ymax - y;
+   GLboolean all = (width == ctx->DrawBuffer->Width && height == ctx->DrawBuffer->height)
    
    if (mask & DD_FRONT_LEFT_BIT) {
       if (all) { 
@@ -95,7 +99,7 @@ void __clear8( GLcontext *ctx, GLbitfield mask, GLboolean all,
    }
 
    if (mask)
-      _swrast_Clear( ctx, mask, all, x, y, width, height );
+      _swrast_Clear( ctx, mask );
 }
 
 void __write_ci32_span8( const GLcontext *ctx, struct gl_renderbuffer *rb,
index 0dfd7a6b393d9d0f1a650a6eb7e3e155e701ef40..8c3229ab14c83c3e552ab965ed0d765bcb5b1a03 100644 (file)
@@ -281,11 +281,7 @@ static void clear_color(GLcontext *ctx, const GLfloat color[4])
  * Clearing of the other non-color buffers is left to the swrast. 
  */ 
 
-static void clear(GLcontext *ctx, 
-                 GLbitfield mask, 
-                 GLboolean all, 
-                 GLint xFoo, GLint yFoo,
-                 GLint widthFoo, GLint heightFoo) 
+static void clear(GLcontext *ctx, GLbitfield mask)
 {
 #define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
     const GLint x = ctx->DrawBuffer->_Xmin;
@@ -303,7 +299,7 @@ static void clear(GLcontext *ctx,
        ctx->Color.ColorMask[1] != 0xff ||
        ctx->Color.ColorMask[2] != 0xff ||
        ctx->Color.ColorMask[3] != 0xff) {
-       _swrast_Clear(ctx, mask, all, x, y, width, height); 
+       _swrast_Clear(ctx, mask);
        return;
     }
 
@@ -322,7 +318,8 @@ static void clear(GLcontext *ctx,
        
        /* Try for a fast clear - clearing entire buffer with a single
         * byte value. */
-       if (all) { /* entire buffer */
+       if (width == ctx->DrawBuffer->Width &&
+            height == ctx->DrawBuffer->Height) { /* entire buffer */
            /* Now check for an easy clear value */
            switch (bytesPerPixel) {
            case 1:
@@ -435,7 +432,7 @@ static void clear(GLcontext *ctx,
     
     /* Call swrast if there is anything left to clear (like DEPTH) */ 
     if (mask) 
-       _swrast_Clear(ctx, mask, all, x, y, width, height); 
+       _swrast_Clear(ctx, mask);
   
 #undef FLIP
 } 
index 87bd5e4a305e48e89a39a929791a61825ba0e3b8..dbac3b8cdb63020161f701c359e0777bd7dcfec4 100644 (file)
@@ -382,9 +382,7 @@ clear_nbit_ximage(GLcontext *ctx, struct xmesa_renderbuffer *xrb,
 
 
 static void
-clear_buffers( GLcontext *ctx, GLbitfield mask,
-               GLboolean all, GLint xFoo, GLint yFoo,
-               GLint widthFoo, GLint heightFoo )
+clear_buffers(GLcontext *ctx, GLbitfield buffers)
 {
    if (ctx->DrawBuffer->Name == 0) {
       /* this is a window system framebuffer */
@@ -397,33 +395,33 @@ clear_buffers( GLcontext *ctx, GLbitfield mask,
 
       /* we can't handle color or index masking */
       if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
-         if (mask & BUFFER_BIT_FRONT_LEFT) {
+         if (buffers & BUFFER_BIT_FRONT_LEFT) {
             /* clear front color buffer */
             struct gl_renderbuffer *frontRb
                = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
             if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
                /* renderbuffer is not wrapped - great! */
                b->frontxrb->clearFunc(ctx, b->frontxrb, x, y, width, height);
-               mask &= ~BUFFER_BIT_FRONT_LEFT;
+               buffers &= ~BUFFER_BIT_FRONT_LEFT;
             }
             else {
                /* we can't directly clear an alpha-wrapped color buffer */
             }
          }
-         if (mask & BUFFER_BIT_BACK_LEFT) {
+         if (buffers & BUFFER_BIT_BACK_LEFT) {
             /* clear back color buffer */
             struct gl_renderbuffer *backRb
                = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
             if (b->backxrb == xmesa_renderbuffer(backRb)) {
                /* renderbuffer is not wrapped - great! */
                b->backxrb->clearFunc(ctx, b->backxrb, x, y, width, height);
-               mask &= ~BUFFER_BIT_BACK_LEFT;
+               buffers &= ~BUFFER_BIT_BACK_LEFT;
             }
          }
       }
    }
-   if (mask)
-      _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0);
+   if (buffers)
+      _swrast_Clear(ctx, buffers);
 }
 
 
index ef970ad9eb6f35c896df9975f03c79e1d71f51b5..e22edc1bbcfb74c0f8786876baa87ed6ec767cd4 100644 (file)
@@ -337,6 +337,8 @@ _mesa_PushAttrib(GLbitfield mask)
    if (mask & GL_TEXTURE_BIT) {
       struct gl_texture_attrib *attr;
       GLuint u;
+
+      _mesa_lock_context_textures(ctx);
       /* Bump the texture object reference counts so that they don't
        * inadvertantly get deleted.
        */
@@ -362,6 +364,9 @@ _mesa_PushAttrib(GLbitfield mask)
          _mesa_copy_texture_object(&attr->Unit[u].SavedRect,
                                    attr->Unit[u].CurrentRect);
       }
+
+      _mesa_unlock_context_textures(ctx);
+
       newnode = new_attrib_node( GL_TEXTURE_BIT );
       newnode->data = attr;
       newnode->next = head;
index 2710d044545564173c13338165872c9020d27aac..ece53463b332d4e19f62878360a0332d34daf8df 100644 (file)
@@ -141,10 +141,6 @@ _mesa_Clear( GLbitfield mask )
    }
 
    if (ctx->RenderMode == GL_RENDER) {
-      const GLint x = ctx->DrawBuffer->_Xmin;
-      const GLint y = ctx->DrawBuffer->_Ymin;
-      const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
-      const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
       GLbitfield bufferMask;
 
       /* don't clear depth buffer if depth writing disabled */
@@ -177,8 +173,7 @@ _mesa_Clear( GLbitfield mask )
       }
 
       ASSERT(ctx->Driver.Clear);
-      ctx->Driver.Clear( ctx, bufferMask, (GLboolean) !ctx->Scissor.Enabled,
-                        x, y, width, height );
+      ctx->Driver.Clear(ctx, bufferMask);
    }
 }
 
index 15b69db5951af0ecaa9b0dfb2bbf2f66c9e8948f..91f3af3c91106ad872c2972c26b81a1936a89e6d 100644 (file)
@@ -735,6 +735,10 @@ alloc_shared_state( GLcontext *ctx )
    ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS;
    ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS;
 
+   _glthread_INIT_MUTEX(ss->TexMutex);
+   ss->TextureStateStamp = 0;
+
+
 #if FEATURE_EXT_framebuffer_object
    ss->FrameBuffers = _mesa_NewHashTable();
    if (!ss->FrameBuffers)
@@ -1048,6 +1052,7 @@ _mesa_init_constants( GLcontext *ctx )
    ctx->Const.VertexProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
    ctx->Const.VertexProgram.MaxEnvParams = MAX_NV_VERTEX_PROGRAM_PARAMS;
    ctx->Const.VertexProgram.MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+   ctx->Const.VertexProgram.MaxUniformComponents = MAX_VERTEX_UNIFORM_COMPONENTS;
    init_natives(&ctx->Const.VertexProgram);
 #endif
 #if FEATURE_ARB_fragment_program
@@ -1061,6 +1066,7 @@ _mesa_init_constants( GLcontext *ctx )
    ctx->Const.FragmentProgram.MaxLocalParams = MAX_PROGRAM_LOCAL_PARAMS;
    ctx->Const.FragmentProgram.MaxEnvParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
    ctx->Const.FragmentProgram.MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+   ctx->Const.FragmentProgram.MaxUniformComponents = MAX_FRAGMENT_UNIFORM_COMPONENTS;
    init_natives(&ctx->Const.FragmentProgram);
 #endif
    ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
@@ -1087,6 +1093,11 @@ _mesa_init_constants( GLcontext *ctx )
    ctx->Const.MaxRenderbufferSize = MAX_WIDTH;
 #endif
 
+#if FEATURE_ARB_vertex_shader
+   ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+   ctx->Const.MaxVaryingFloats = MAX_VARYING_FLOATS;
+#endif
+
    /* sanity checks */
    ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
                                              ctx->Const.MaxTextureCoordUnits));
index a1999ac76d7f133a0cf9ecfe749562542301c012..1de2542bee2ec3d690065fab063789dc4d96fceb 100644 (file)
@@ -99,39 +99,24 @@ struct dd_function_table {
 
    /**
     * Clear the color/depth/stencil/accum buffer(s).
-    *
-    * \param mask a bitmask of the DD_*_BIT values defined above that indicates
-    * which buffers need to be cleared.
-    * \param all if true then clear the whole buffer, else clear only the
-    * region defined by <tt>(x, y, width, height)</tt>.
-    * 
-    * This function must obey the glColorMask(), glIndexMask() and
-    * glStencilMask() settings!
-    * Software Mesa can do masked clears if the device driver can't.
+    * \param buffers  a bitmask of BUFFER_BIT_* flags indicating which
+    *                 renderbuffers need to be cleared.
     */
-   void (*Clear)( GLcontext *ctx, GLbitfield mask, GLboolean all,
-                 GLint x, GLint y, GLint width, GLint height );
-
+   void (*Clear)( GLcontext *ctx, GLbitfield buffers );
 
-   /**
-    * \name For hardware accumulation buffer
-    */
-   /*@{*/
    /**
     * Execute glAccum command.
     */
    void (*Accum)( GLcontext *ctx, GLenum op, GLfloat value );
-   /*@}*/
 
 
    /**
-    * \name glDraw(), glRead(), glCopyPixels() and glBitmap() functions
+    * \name Image-related functions
     */
    /*@{*/
 
    /**
-    * This is called by glDrawPixels().
-    *
+    * Called by glDrawPixels().
     * \p unpack describes how to unpack the source image data.
     */
    void (*DrawPixels)( GLcontext *ctx,
@@ -150,19 +135,14 @@ struct dd_function_table {
                       GLvoid *dest );
 
    /**
-    * Do a glCopyPixels().  
-    *
-    * This function must respect all rasterization state, glPixelTransfer(),
-    * glPixelZoom(), etc.
+    * Called by glCopyPixels().  
     */
    void (*CopyPixels)( GLcontext *ctx, GLint srcx, GLint srcy,
                        GLsizei width, GLsizei height,
                        GLint dstx, GLint dsty, GLenum type );
 
    /**
-    * This is called by glBitmap().  
-    *
-    * Works the same as dd_function_table::DrawPixels, above.
+    * Called by glBitmap().  
     */
    void (*Bitmap)( GLcontext *ctx,
                   GLint x, GLint y, GLsizei width, GLsizei height,
index 5edf9a7dd6504da609c838b254cdbfa60409c507..39f8e26f57717ef3482fe68832ad485ee0392317 100644 (file)
@@ -135,6 +135,7 @@ static const struct {
    { OFF, "GL_ATI_texture_env_combine3",       F(ATI_texture_env_combine3)},
    { OFF, "GL_ATI_texture_mirror_once",        F(ATI_texture_mirror_once)},
    { OFF, "GL_ATI_fragment_shader",            F(ATI_fragment_shader)},
+   { OFF, "GL_ATI_separate_stencil",           F(ATI_separate_stencil)},
    { OFF, "GL_IBM_multimode_draw_arrays",      F(IBM_multimode_draw_arrays) },
    { ON,  "GL_IBM_rasterpos_clip",             F(IBM_rasterpos_clip) },
    { OFF, "GL_IBM_texture_mirrored_repeat",    F(ARB_texture_mirrored_repeat)},
@@ -222,6 +223,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
 #endif
    ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
    ctx->Extensions.ATI_texture_mirror_once = GL_TRUE;
+   ctx->Extensions.ATI_separate_stencil = GL_TRUE;
    ctx->Extensions.EXT_blend_color = GL_TRUE;
    ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
    ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
@@ -249,7 +251,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
    ctx->Extensions.EXT_secondary_color = GL_TRUE;
    ctx->Extensions.EXT_shared_texture_palette = GL_TRUE;
    ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
-   ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
+   ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* obsolete */
    ctx->Extensions.EXT_texture_env_add = GL_TRUE;
    ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
    ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
@@ -388,7 +390,8 @@ _mesa_enable_2_0_extensions(GLcontext *ctx)
 #if FEATURE_ARB_shading_language_100
    ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
 #endif
-   ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* yes, turn it off */
+   ctx->Extensions.ATI_separate_stencil = GL_TRUE;
+   ctx->Extensions.EXT_stencil_two_side = GL_FALSE; /* obsolete */
 #if FEATURE_ARB_vertex_shader
    ctx->Extensions.ARB_vertex_shader = GL_TRUE;
 #endif
index 2ca10146313f90833698251a06306410a0fdf9bc..cf8de1e0cbe5bdb6de58b48fa203ee5c6117d20d 100644 (file)
@@ -979,7 +979,9 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
    }
 
    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
-
+   if (ctx->Driver.Flush) {  
+      ctx->Driver.Flush(ctx);
+   }
    if (framebuffer) {
       /* Binding a user-created framebuffer object */
       newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
@@ -1548,7 +1550,9 @@ _mesa_GenerateMipmapEXT(GLenum target)
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
 
    /* XXX this might not handle cube maps correctly */
+   _mesa_lock_texture(ctx, texObj);
    _mesa_generate_mipmap(ctx, target, texUnit, texObj);
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
index 3dd1aa18737095a9acf6c0c3cd98b99a32f52449..9f3a8d12cfc59b1b8cbedb46702b71ffec050c89 100644 (file)
@@ -1863,7 +1863,7 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
          break;
       case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
          CHECK_EXT1(ARB_fragment_shader, "GetBooleanv");
-         params[0] = INT_TO_BOOLEAN(MAX_FRAGMENT_UNIFORM_COMPONENTS);
+         params[0] = INT_TO_BOOLEAN(ctx->Const.FragmentProgram.MaxUniformComponents);
          break;
       case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
          CHECK_EXT1(ARB_fragment_shader, "GetBooleanv");
@@ -1871,15 +1871,15 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
          break;
       case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
-         params[0] = INT_TO_BOOLEAN(MAX_VERTEX_UNIFORM_COMPONENTS);
+         params[0] = INT_TO_BOOLEAN(ctx->Const.VertexProgram.MaxUniformComponents);
          break;
       case GL_MAX_VARYING_FLOATS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
-         params[0] = INT_TO_BOOLEAN(MAX_VARYING_FLOATS);
+         params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVaryingFloats);
          break;
       case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
-         params[0] = INT_TO_BOOLEAN(MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+         params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVertexTextureImageUnits);
          break;
       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetBooleanv");
@@ -3687,7 +3687,7 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
          break;
       case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
          CHECK_EXT1(ARB_fragment_shader, "GetFloatv");
-         params[0] = (GLfloat)(MAX_FRAGMENT_UNIFORM_COMPONENTS);
+         params[0] = (GLfloat)(ctx->Const.FragmentProgram.MaxUniformComponents);
          break;
       case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
          CHECK_EXT1(ARB_fragment_shader, "GetFloatv");
@@ -3695,15 +3695,15 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
          break;
       case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
-         params[0] = (GLfloat)(MAX_VERTEX_UNIFORM_COMPONENTS);
+         params[0] = (GLfloat)(ctx->Const.VertexProgram.MaxUniformComponents);
          break;
       case GL_MAX_VARYING_FLOATS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
-         params[0] = (GLfloat)(MAX_VARYING_FLOATS);
+         params[0] = (GLfloat)(ctx->Const.MaxVaryingFloats);
          break;
       case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
-         params[0] = (GLfloat)(MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+         params[0] = (GLfloat)(ctx->Const.MaxVertexTextureImageUnits);
          break;
       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetFloatv");
@@ -5511,7 +5511,7 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
          break;
       case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB:
          CHECK_EXT1(ARB_fragment_shader, "GetIntegerv");
-         params[0] = MAX_FRAGMENT_UNIFORM_COMPONENTS;
+         params[0] = ctx->Const.FragmentProgram.MaxUniformComponents;
          break;
       case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
          CHECK_EXT1(ARB_fragment_shader, "GetIntegerv");
@@ -5519,15 +5519,15 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
          break;
       case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
-         params[0] = MAX_VERTEX_UNIFORM_COMPONENTS;
+         params[0] = ctx->Const.VertexProgram.MaxUniformComponents;
          break;
       case GL_MAX_VARYING_FLOATS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
-         params[0] = MAX_VARYING_FLOATS;
+         params[0] = ctx->Const.MaxVaryingFloats;
          break;
       case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
-         params[0] = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
+         params[0] = ctx->Const.MaxVertexTextureImageUnits;
          break;
       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB:
          CHECK_EXT1(ARB_vertex_shader, "GetIntegerv");
index ec8a192b31a1aec501df3fca7392b786b234ae81..50ff13d2f9fc5577b8ba7d95224348938f87d3f6 100644 (file)
@@ -978,17 +978,19 @@ StateVars = [
 
        # GL_ARB_fragment_shader
        ( "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB", GLint,
-         ["MAX_FRAGMENT_UNIFORM_COMPONENTS"], "", ["ARB_fragment_shader"] ),
+         ["ctx->Const.FragmentProgram.MaxUniformComponents"], "",
+         ["ARB_fragment_shader"] ),
        ( "GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB", GLenum,
          ["ctx->Hint.FragmentShaderDerivative"], "", ["ARB_fragment_shader"] ),
 
        # GL_ARB_vertex_shader
        ( "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB", GLint,
-         ["MAX_VERTEX_UNIFORM_COMPONENTS"], "", ["ARB_vertex_shader"] ),
+         ["ctx->Const.VertexProgram.MaxUniformComponents"], "",
+         ["ARB_vertex_shader"] ),
        ( "GL_MAX_VARYING_FLOATS_ARB", GLint,
-         ["MAX_VARYING_FLOATS"], "", ["ARB_vertex_shader"] ),
+         ["ctx->Const.MaxVaryingFloats"], "", ["ARB_vertex_shader"] ),
        ( "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB", GLint,
-         ["MAX_VERTEX_TEXTURE_IMAGE_UNITS"], "", ["ARB_vertex_shader"] ),
+         ["ctx->Const.MaxVertexTextureImageUnits"], "", ["ARB_vertex_shader"] ),
        ( "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB", GLint,
          ["MAX_COMBINED_TEXTURE_IMAGE_UNITS"], "", ["ARB_vertex_shader"] )
 ]
index a68bf9ff749b0b4300a3d0c7a0d272d619ccee8f..f2989aaefa48a3f1407ca978ef349950c11dd71d 100644 (file)
@@ -54,7 +54,7 @@ _mesa_GetString( GLenum name )
    static const char *version_1_3 = "1.3 Mesa " MESA_VERSION_STRING;
    static const char *version_1_4 = "1.4 Mesa " MESA_VERSION_STRING;
    static const char *version_1_5 = "1.5 Mesa " MESA_VERSION_STRING;
-   static const char *version_2_0 = "1.5 Mesa " MESA_VERSION_STRING;/*XXX FIX*/
+   static const char *version_2_0 = "1.5 Mesa " MESA_VERSION_STRING;
 
 #if FEATURE_ARB_shading_language_100
    static const char *sl_version_110 = "1.10 Mesa " MESA_VERSION_STRING;
@@ -111,7 +111,7 @@ _mesa_GetString( GLenum name )
                   if (ctx->Extensions.ARB_draw_buffers &&
                       ctx->Extensions.ARB_point_sprite &&
                       ctx->Extensions.ARB_texture_non_power_of_two &&
-                      ctx->Extensions.EXT_stencil_two_side) {
+                      ctx->Extensions.ATI_separate_stencil) {
                      return (const GLubyte *) version_2_0;
                   }
                   else {
index 604dea34e0a9c07904b48bc4512dc6f6d688d441..f154bd4651322b9f8531e3bee1bba92864b03fdb 100644 (file)
@@ -883,7 +883,7 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
       GLint border, bytesPerTexel;
 
       /* get src image parameters */
-      srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+      srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
       ASSERT(srcImage);
       srcWidth = srcImage->Width;
       srcHeight = srcImage->Height;
@@ -922,7 +922,7 @@ _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
       }
 
       /* get dest gl_texture_image */
-      dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
+      dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
       if (!dstImage) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
          return;
index bc7c6b8026fc1f6bd957e661dc3bf26fe68a85f7..1d5eb61e0655a3a0d342f0a718482392817d20a0 100644 (file)
@@ -1909,20 +1909,6 @@ struct gl_program_state
 };
 
 
-/**
- * Virtual vertex program machine state.
- * Only used during program execution (may be moved someday):
- */
-struct gl_vertex_program_machine
-{
-   GLfloat Temporaries[MAX_NV_VERTEX_PROGRAM_TEMPS][4];
-   GLfloat Inputs[MAX_NV_VERTEX_PROGRAM_INPUTS][4];
-   GLuint InputsSize[MAX_NV_VERTEX_PROGRAM_INPUTS];
-   GLfloat Outputs[MAX_NV_VERTEX_PROGRAM_OUTPUTS][4];
-   GLint AddressReg[4];
-};
-
-
 /**
  * Context state for vertex programs.
  */
@@ -1939,8 +1925,6 @@ struct gl_vertex_program_state
 
    GLfloat Parameters[MAX_NV_VERTEX_PROGRAM_PARAMS][4]; /**< Env params */
 
-   struct gl_vertex_program_machine Machine;
-
    /* For GL_NV_vertex_program only: */
    GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
    GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4];
@@ -2074,6 +2058,19 @@ struct gl_shared_state
    struct gl_texture_object *DefaultRect;
    /*@}*/
 
+   /**
+    * \name Thread safety and statechange notification for texture
+    * objects. 
+    *
+    * \todo Improve the granularity of locking.
+    */
+   /*@{*/
+   _glthread_Mutex TexMutex;              /**< texobj thread safety */
+   GLuint TextureStateStamp;              /**< state notification for shared tex  */
+   /*@}*/
+
+
+
    /**
     * \name Vertex/fragment programs
     */
@@ -2323,6 +2320,8 @@ struct gl_program_constants
    GLuint MaxNativeTemps;
    GLuint MaxNativeAddressRegs; /* vertex program only, for now */
    GLuint MaxNativeParameters;
+   /* For shaders */
+   GLuint MaxUniformComponents;
 };
 
 
@@ -2372,6 +2371,9 @@ struct gl_constants
    /* GL_EXT_framebuffer_object */
    GLuint MaxColorAttachments;
    GLuint MaxRenderbufferSize;
+   /* GL_ARB_vertex_shader */
+   GLuint MaxVertexTextureImageUnits;
+   GLuint MaxVaryingFloats;
 };
 
 
@@ -2471,6 +2473,7 @@ struct gl_extensions
    GLboolean ATI_texture_mirror_once;
    GLboolean ATI_texture_env_combine3;
    GLboolean ATI_fragment_shader;
+   GLboolean ATI_separate_stencil;
    GLboolean IBM_rasterpos_clip;
    GLboolean IBM_multimode_draw_arrays;
    GLboolean MESA_pack_invert;
@@ -2938,6 +2941,8 @@ struct __GLcontextRec
    GLboolean _ForceEyeCoords; 
    GLenum _CurrentProgram;    /* currently executing program */
 
+   GLuint TextureStateTimestamp; /* detect changes to shared state */
+
    struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */
    struct gl_shine_tab *_ShineTabList;  /**< MRU list of inactive shine tables */
    /**@}*/
index d57217d9c4f69357455fbef66edfb47307057278..06cf5f8698d72a481cded69b14ffc0a6781b57a2 100644 (file)
@@ -1003,7 +1003,7 @@ update_color(GLcontext *ctx)
  * _mesa_update_lighting() and _mesa_update_tnl_spaces().
  */
 void
-_mesa_update_state( GLcontext *ctx )
+_mesa_update_state_locked( GLcontext *ctx )
 {
    GLbitfield new_state = ctx->NewState;
 
@@ -1084,4 +1084,17 @@ _mesa_update_state( GLcontext *ctx )
    ctx->Array.NewState = 0;
 }
 
+
+/* This is the usual entrypoint for state updates:
+ */
+void
+_mesa_update_state( GLcontext *ctx )
+{
+   _mesa_lock_context_textures(ctx);
+   _mesa_update_state_locked(ctx);
+   _mesa_unlock_context_textures(ctx);
+}
+
+
+
 /*@}*/
index 58cfcc414626de1fa99c18e5afb83887fd5f8032..5240d4bf935347c703131e656297f7d60ca23212 100644 (file)
@@ -39,5 +39,11 @@ _mesa_init_exec_table(struct _glapi_table *exec);
 extern void
 _mesa_update_state( GLcontext *ctx );
 
+/* As above but can only be called between _mesa_lock_context_textures() and 
+ * _mesa_unlock_context_textures().
+ */
+extern void
+_mesa_update_state_locked( GLcontext *ctx );
+
 
 #endif
index 9992ec9b6eb849bd0736dab16ef910a402a0cde2..d6be410e76ce573eb564ebf8abc22651b89b1bc1 100644 (file)
@@ -115,23 +115,7 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
 
    ref = CLAMP( ref, 0, stencilMax );
 
-   if (ctx->Extensions.EXT_stencil_two_side) {
-      /* only set active face state */
-      const GLint face = ctx->Stencil.ActiveFace;
-      if (ctx->Stencil.Function[face] == func &&
-          ctx->Stencil.ValueMask[face] == mask &&
-          ctx->Stencil.Ref[face] == ref)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.Function[face] = func;
-      ctx->Stencil.Ref[face] = ref;
-      ctx->Stencil.ValueMask[face] = mask;
-      if (ctx->Driver.StencilFuncSeparate) {
-         ctx->Driver.StencilFuncSeparate(ctx, face ? GL_BACK : GL_FRONT,
-                                         func, ref, mask);
-      }
-   }
-   else {
+   if (ctx->Extensions.ATI_separate_stencil) {
       /* set both front and back state */
       if (ctx->Stencil.Function[0] == func &&
           ctx->Stencil.Function[1] == func &&
@@ -149,6 +133,22 @@ _mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
                                          func, ref, mask);
       }
    }
+   else {
+      /* only set active face state */
+      const GLint face = ctx->Stencil.ActiveFace;
+      if (ctx->Stencil.Function[face] == func &&
+          ctx->Stencil.ValueMask[face] == mask &&
+          ctx->Stencil.Ref[face] == ref)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.Function[face] = func;
+      ctx->Stencil.Ref[face] = ref;
+      ctx->Stencil.ValueMask[face] = mask;
+      if (ctx->Driver.StencilFuncSeparate) {
+         ctx->Driver.StencilFuncSeparate(ctx, face ? GL_BACK : GL_FRONT,
+                                         func, ref, mask);
+      }
+   }
 }
 
 
@@ -169,26 +169,26 @@ _mesa_StencilMask( GLuint mask )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (ctx->Extensions.EXT_stencil_two_side) {
-      /* only set active face state */
-      const GLint face = ctx->Stencil.ActiveFace;
-      if (ctx->Stencil.WriteMask[face] == mask)
+   if (ctx->Extensions.ATI_separate_stencil) {
+      /* set both front and back state */
+      if (ctx->Stencil.WriteMask[0] == mask &&
+          ctx->Stencil.WriteMask[1] == mask)
          return;
       FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.WriteMask[face] = mask;
+      ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
       if (ctx->Driver.StencilMaskSeparate) {
-         ctx->Driver.StencilMaskSeparate(ctx, face ? GL_BACK : GL_FRONT, mask);
+         ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT_AND_BACK, mask);
       }
    }
    else {
-      /* set both front and back state */
-      if (ctx->Stencil.WriteMask[0] == mask &&
-          ctx->Stencil.WriteMask[1] == mask)
+      /* only set active face state */
+      const GLint face = ctx->Stencil.ActiveFace;
+      if (ctx->Stencil.WriteMask[face] == mask)
          return;
       FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.WriteMask[0] = ctx->Stencil.WriteMask[1] = mask;
+      ctx->Stencil.WriteMask[face] = mask;
       if (ctx->Driver.StencilMaskSeparate) {
-         ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT_AND_BACK, mask);
+         ctx->Driver.StencilMaskSeparate(ctx, face ? GL_BACK : GL_FRONT, mask);
       }
    }
 }
@@ -269,23 +269,7 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
          return;
    }
 
-   if (ctx->Extensions.EXT_stencil_two_side) {
-      /* only set active face state */
-      const GLint face = ctx->Stencil.ActiveFace;
-      if (ctx->Stencil.ZFailFunc[face] == zfail &&
-          ctx->Stencil.ZPassFunc[face] == zpass &&
-          ctx->Stencil.FailFunc[face] == fail)
-         return;
-      FLUSH_VERTICES(ctx, _NEW_STENCIL);
-      ctx->Stencil.ZFailFunc[face] = zfail;
-      ctx->Stencil.ZPassFunc[face] = zpass;
-      ctx->Stencil.FailFunc[face] = fail;
-      if (ctx->Driver.StencilOpSeparate) {
-         ctx->Driver.StencilOpSeparate(ctx, face ? GL_BACK : GL_FRONT,
-                                       fail, zfail, zpass);
-      }
-   }
-   else {
+   if (ctx->Extensions.ATI_separate_stencil) {
       /* set both front and back state */
       if (ctx->Stencil.ZFailFunc[0] == zfail &&
           ctx->Stencil.ZFailFunc[1] == zfail &&
@@ -303,6 +287,22 @@ _mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
                                        fail, zfail, zpass);
       }
    }
+   else {
+      /* only set active face state */
+      const GLint face = ctx->Stencil.ActiveFace;
+      if (ctx->Stencil.ZFailFunc[face] == zfail &&
+          ctx->Stencil.ZPassFunc[face] == zpass &&
+          ctx->Stencil.FailFunc[face] == fail)
+         return;
+      FLUSH_VERTICES(ctx, _NEW_STENCIL);
+      ctx->Stencil.ZFailFunc[face] = zfail;
+      ctx->Stencil.ZPassFunc[face] = zpass;
+      ctx->Stencil.FailFunc[face] = fail;
+      if (ctx->Driver.StencilOpSeparate) {
+         ctx->Driver.StencilOpSeparate(ctx, face ? GL_BACK : GL_FRONT,
+                                       fail, zfail, zpass);
+      }
+   }
 }
 
 
@@ -406,17 +406,16 @@ _mesa_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
 
    FLUSH_VERTICES(ctx, _NEW_STENCIL);
 
-   if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+   if (face != GL_BACK) {
       ctx->Stencil.FailFunc[0] = fail;
       ctx->Stencil.ZFailFunc[0] = zfail;
       ctx->Stencil.ZPassFunc[0] = zpass;
    }
-   if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+   if (face != GL_FRONT) {
       ctx->Stencil.FailFunc[1] = fail;
       ctx->Stencil.ZFailFunc[1] = zfail;
       ctx->Stencil.ZPassFunc[1] = zpass;
    }
-
    if (ctx->Driver.StencilOpSeparate) {
       ctx->Driver.StencilOpSeparate(ctx, face, fail, zfail, zpass);
    }
@@ -465,7 +464,6 @@ _mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
       ctx->Stencil.Ref[1] = ref;
       ctx->Stencil.ValueMask[1] = mask;
    }
-
    if (ctx->Driver.StencilFuncSeparate) {
       ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask);
    }
@@ -486,13 +484,12 @@ _mesa_StencilMaskSeparate(GLenum face, GLuint mask)
 
    FLUSH_VERTICES(ctx, _NEW_STENCIL);
 
-   if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
+   if (face != GL_BACK) {
       ctx->Stencil.WriteMask[0] = mask;
    }
-   if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
+   if (face != GL_FRONT) {
       ctx->Stencil.WriteMask[1] = mask;
    }
-
    if (ctx->Driver.StencilMaskSeparate) {
       ctx->Driver.StencilMaskSeparate(ctx, face, mask);
    }
index 65ecaba3a30ac537efee80504e6e7735b8fa3fb2..c71501c5e6b0e7bfdc829eb39f45f5de94d3e0e1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.1
+ * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
@@ -48,6 +48,8 @@
 
 #ifdef __MINGW32__
 #define DXTN_LIBNAME "dxtn.dll"
+#define RTLD_LAZY 0
+#define RTLD_GLOBAL 0
 #elif defined(__DJGPP__)
 #define DXTN_LIBNAME "dxtn.dxe"
 #else
@@ -104,7 +106,7 @@ _mesa_dlsym(void *handle, const char *fname)
 {
 #if USE_EXTERNAL_DXTN_LIB
 #ifdef __MINGW32__
-   return (GenericFunc) GetProcAddress(handle, fname)
+   return (GenericFunc) GetProcAddress(handle, fname);
 #elif defined(__DJGPP__)
    /* need '_' prefix on symbol names */
    char fname2[1000];
index 5f798cc7df47ff7a2487329189d3553cb9ddc28a..c99ff5cdc469bf4bc1820b8822ec17895f56ce52 100644 (file)
 #include "shader/program.h"
 #include "shader/program_instruction.h"
 
-#define MAX_INSTRUCTIONS 100
+/**
+ * According to Glean's texCombine test, no more than 21 instructions
+ * are needed.  Allow a few extra just in case.
+ */
+#define MAX_INSTRUCTIONS 24
 
 #define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
 
@@ -474,7 +478,7 @@ emit_op(struct texenv_fragment_program *p,
    GLuint nr = p->program->Base.NumInstructions++;
    struct prog_instruction *inst = &p->program->Base.Instructions[nr];
       
-   _mesa_init_instruction(inst);
+   _mesa_init_instructions(inst, 1);
    inst->Opcode = op;
    
    emit_arg( &inst->SrcReg[0], src0 );
@@ -988,9 +992,10 @@ load_texunit_sources( struct texenv_fragment_program *p, int unit )
  * current texture env/combine mode.
  */
 static void
-create_new_program(struct state_key *key, GLcontext *ctx,
+create_new_program(GLcontext *ctx, struct state_key *key,
                    struct gl_fragment_program *program)
 {
+   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
    struct texenv_fragment_program p;
    GLuint unit;
    struct ureg cf, out;
@@ -1000,18 +1005,19 @@ create_new_program(struct state_key *key, GLcontext *ctx,
    p.state = key;
    p.program = program;
 
-   p.program->Base.Instructions =
-      (struct prog_instruction*) _mesa_malloc(sizeof(struct prog_instruction) * MAX_INSTRUCTIONS);
-   p.program->Base.NumInstructions = 0;
+   /* During code generation, use locally-allocated instruction buffer,
+    * then alloc dynamic storage below.
+    */
+   p.program->Base.Instructions = instBuffer;
    p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
    p.program->NumTexIndirections = 1;  /* correct? */
    p.program->NumTexInstructions = 0;
    p.program->NumAluInstructions = 0;
    p.program->Base.String = 0;
    p.program->Base.NumInstructions =
-      p.program->Base.NumTemporaries =
-      p.program->Base.NumParameters =
-      p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
+   p.program->Base.NumTemporaries =
+   p.program->Base.NumParameters =
+   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
    p.program->Base.Parameters = _mesa_new_parameter_list();
 
    p.program->Base.InputsRead = 0;
@@ -1088,17 +1094,28 @@ create_new_program(struct state_key *key, GLcontext *ctx,
 
    ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
 
+   /* Allocate final instruction array */
+   program->Base.Instructions
+      = _mesa_alloc_instructions(program->Base.NumInstructions);
+   if (!program->Base.Instructions) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY,
+                  "generating tex env program");
+      return;
+   }
+   _mesa_memcpy(program->Base.Instructions, instBuffer,
+                sizeof(struct prog_instruction)
+                * program->Base.NumInstructions);
+
    /* Notify driver the fragment program has (actually) changed.
     */
-   if (ctx->Driver.ProgramStringNotify || DISASSEM) {
-      if (ctx->Driver.ProgramStringNotify)
-        ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB, 
-                                         &p.program->Base );
-
-      if (DISASSEM) {
-        _mesa_print_program(&p.program->Base);
-        _mesa_printf("\n");
-      }
+   if (ctx->Driver.ProgramStringNotify) {
+      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB, 
+                                       &p.program->Base );
+   }
+
+   if (DISASSEM) {
+      _mesa_print_program(&p.program->Base);
+      _mesa_printf("\n");
    }
 }
 
@@ -1225,7 +1242,7 @@ void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
            (struct gl_fragment_program *) 
            ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
                
-        create_new_program(&key, ctx, ctx->_TexEnvProgram);
+        create_new_program(ctx, &key, ctx->_TexEnvProgram);
 
         cache_item(&ctx->Texture.env_fp_cache, hash, &key, ctx->_TexEnvProgram);
       } else {
index c2ba450cb3fa083d383edb2df7fffcc337ec7ecd..662f697147ded95db6b8a22a239104be13f0fc5c 100644 (file)
@@ -706,9 +706,12 @@ _mesa_free_texture_image_data(GLcontext *ctx,
 void
 _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
 {
-   if (texImage->Data) {
-      ctx->Driver.FreeTexImageData( ctx, texImage );
-   }
+   /* Free texImage->Data and/or any other driver-specific texture
+    * image storage.
+    */
+   ASSERT(ctx->Driver.FreeTexImageData);
+   ctx->Driver.FreeTexImageData( ctx, texImage );
+
    ASSERT(texImage->Data == NULL);
    if (texImage->ImageOffsets)
       _mesa_free(texImage->ImageOffsets);
@@ -801,24 +804,23 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
  * \sa gl_texture_unit.
  */
 struct gl_texture_image *
-_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
-                       GLenum target, GLint level)
+_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
+                      GLenum target, GLint level)
 {
-   ASSERT(texUnit);
-   ASSERT(level < MAX_TEXTURE_LEVELS);
+   ASSERT(texObj);
+
+   if (level < 0 || level >= MAX_TEXTURE_LEVELS) 
+      return NULL;
+
    switch (target) {
       case GL_TEXTURE_1D:
-         return texUnit->Current1D->Image[0][level];
       case GL_PROXY_TEXTURE_1D:
-         return ctx->Texture.Proxy1D->Image[0][level];
       case GL_TEXTURE_2D:
-         return texUnit->Current2D->Image[0][level];
       case GL_PROXY_TEXTURE_2D:
-         return ctx->Texture.Proxy2D->Image[0][level];
       case GL_TEXTURE_3D:
-         return texUnit->Current3D->Image[0][level];
       case GL_PROXY_TEXTURE_3D:
-         return ctx->Texture.Proxy3D->Image[0][level];
+         return texObj->Image[0][level];
+
       case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
@@ -828,33 +830,25 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
          if (ctx->Extensions.ARB_texture_cube_map) {
            GLuint face = ((GLuint) target - 
                           (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
-            return texUnit->CurrentCubeMap->Image[face][level];
+            return texObj->Image[face][level];
         }
          else
             return NULL;
+
       case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
          if (ctx->Extensions.ARB_texture_cube_map)
-            return ctx->Texture.ProxyCubeMap->Image[0][level];
+            return texObj->Image[0][level];
          else
             return NULL;
+
       case GL_TEXTURE_RECTANGLE_NV:
-         if (ctx->Extensions.NV_texture_rectangle) {
-            ASSERT(level == 0);
-            return texUnit->CurrentRect->Image[0][level];
-         }
-         else {
-            return NULL;
-         }
       case GL_PROXY_TEXTURE_RECTANGLE_NV:
-         if (ctx->Extensions.NV_texture_rectangle) {
-            ASSERT(level == 0);
-            return ctx->Texture.ProxyRect->Image[0][level];
-         }
-         else {
+         if (ctx->Extensions.NV_texture_rectangle && level == 0) 
+            return texObj->Image[0][level];
+         else 
             return NULL;
-         }
+
       default:
-         _mesa_problem(ctx, "bad target in _mesa_select_tex_image()");
          return NULL;
    }
 }
@@ -866,22 +860,25 @@ _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
  * out of memory.
  */
 struct gl_texture_image *
-_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
                     GLenum target, GLint level)
 {
    struct gl_texture_image *texImage;
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+
+   if (!texObj)
+      return NULL;
+   
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    if (!texImage) {
-      struct gl_texture_object *texObj;
       texImage = ctx->Driver.NewTextureImage(ctx);
       if (!texImage) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
          return NULL;
       }
-      texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      ASSERT(texObj);
+
       _mesa_set_tex_image(texObj, target, level, texImage);
    }
+
    return texImage;
 }
 
@@ -1584,9 +1581,6 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
                         GLint width, GLint height, GLint depth,
                         GLenum format, GLenum type )
 {
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   struct gl_texture_image *destTex;
-
    /* Check target */
    if (dimensions == 1) {
       if (target != GL_TEXTURE_1D) {
@@ -1602,8 +1596,7 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
             return GL_TRUE;
          }
       }
-      else if (ctx->Extensions.NV_texture_rectangle &&
-               target == GL_TEXTURE_RECTANGLE_NV) {
+      else if (target == GL_TEXTURE_RECTANGLE_NV) {
          if (!ctx->Extensions.NV_texture_rectangle) {
             _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
             return GL_TRUE;
@@ -1647,8 +1640,23 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
-   destTex = _mesa_select_tex_image(ctx, texUnit, target, level);
+   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glTexSubImage%dD(format or type)", dimensions);
+      return GL_TRUE;
+   }
+
+   return GL_FALSE;
+}
 
+static GLboolean
+subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
+                        GLenum target, GLint level,
+                        GLint xoffset, GLint yoffset, GLint zoffset,
+                        GLint width, GLint height, GLint depth,
+                        GLenum format, GLenum type,
+                        const struct gl_texture_image *destTex )
+{
    if (!destTex) {
       /* undefined image level */
       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
@@ -1688,12 +1696,6 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
-   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
-      _mesa_error(ctx, GL_INVALID_ENUM,
-                  "glTexSubImage%dD(format or type)", dimensions);
-      return GL_TRUE;
-   }
-
 #if FEATURE_EXT_texture_sRGB
    if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
        destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
@@ -1709,11 +1711,6 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
 #endif
 
    if (destTex->IsCompressed) {
-      const struct gl_texture_unit *texUnit;
-      const struct gl_texture_image *texImage;
-      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-      texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-
       if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
          /* OK */
       }
@@ -1735,12 +1732,12 @@ subtexture_error_check( GLcontext *ctx, GLuint dimensions,
          return GL_TRUE;
       }
       /* size must be multiple of 4 or equal to whole texture size */
-      if ((width & 3) && (GLuint) width != texImage->Width) {
+      if ((width & 3) && (GLuint) width != destTex->Width) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glTexSubImage%D(width)", dimensions);
          return GL_TRUE;
       }         
-      if ((height & 3) && (GLuint) height != texImage->Height) {
+      if ((height & 3) && (GLuint) height != destTex->Height) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glTexSubImage%D(width)", dimensions);
          return GL_TRUE;
@@ -1781,6 +1778,11 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
 
    /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
    if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glCopyTexImage%dD(level=%d)", dimensions, level);
+      return GL_TRUE;
+   }
+
    /* Check that the source buffer is complete */
    if (ctx->ReadBuffer->Name) {
       _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
@@ -1791,11 +1793,6 @@ copytexture_error_check( GLcontext *ctx, GLuint dimensions,
       }
    }
 
-      _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glCopyTexImage%dD(level=%d)", dimensions, level);
-      return GL_TRUE;
-   }
-
    /* Check border */
    if (border < 0 || border > 1 ||
        ((target == GL_TEXTURE_RECTANGLE_NV ||
@@ -1945,11 +1942,8 @@ static GLboolean
 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
                              GLenum target, GLint level,
                              GLint xoffset, GLint yoffset, GLint zoffset,
-                             GLsizei width, GLsizei height )
+                             GLsizei width, GLsizei height)
 {
-   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   struct gl_texture_image *teximage;
-
    /* Check target */
    /* Check that the source buffer is complete */
    if (ctx->ReadBuffer->Name) {
@@ -2012,7 +2006,16 @@ copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
       return GL_TRUE;
    }
 
-   teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
+   return GL_FALSE;
+}
+
+static GLboolean
+copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
+                             GLenum target, GLint level,
+                             GLint xoffset, GLint yoffset, GLint zoffset,
+                             GLsizei width, GLsizei height,
+                             const struct gl_texture_image *teximage )
+{
    if (!teximage) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glCopyTexSubImage%dD(undefined texture level: %d)",
@@ -2186,59 +2189,66 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
    if (!pixels)
       return;
 
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   if (!texImage) {
-      /* invalid mipmap level, not an error */
-      return;
-   }
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+      if (!texImage) {
+        /* invalid mipmap level, not an error */
+        goto out;
+      }
 
-   /* Make sure the requested image format is compatible with the
-    * texture's format.  Note that a color index texture can be converted
-    * to RGBA so that combo is allowed.
-    */
-   if (is_color_format(format)
-       && !is_color_format(texImage->TexFormat->BaseFormat)
-       && !is_index_format(texImage->TexFormat->BaseFormat)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
-      return;
-   }
-   else if (is_index_format(format)
-       && !is_index_format(texImage->TexFormat->BaseFormat)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
-      return;
-   }
-   else if (is_depth_format(format)
-       && !is_depth_format(texImage->TexFormat->BaseFormat)
-       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
-      return;
-   }
-   else if (is_ycbcr_format(format)
-       && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
-      return;
-   }
-   else if (is_depthstencil_format(format)
-       && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
-      return;
-   }
 
-   if (ctx->Pack.BufferObj->Name) {
-      /* packing texture image into a PBO */
-      const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
-      if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
-                                     texImage->Height, texImage->Depth,
-                                     format, type, pixels)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glGetTexImage(invalid PBO access)");
-         return;
+      /* Make sure the requested image format is compatible with the
+       * texture's format.  Note that a color index texture can be converted
+       * to RGBA so that combo is allowed.
+       */
+      if (is_color_format(format)
+         && !is_color_format(texImage->TexFormat->BaseFormat)
+         && !is_index_format(texImage->TexFormat->BaseFormat)) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+        goto out;
+      }
+      else if (is_index_format(format)
+              && !is_index_format(texImage->TexFormat->BaseFormat)) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+        goto out;
+      }
+      else if (is_depth_format(format)
+              && !is_depth_format(texImage->TexFormat->BaseFormat)
+              && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+        goto out;
+      }
+      else if (is_ycbcr_format(format)
+              && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+        goto out;
+      }
+      else if (is_depthstencil_format(format)
+              && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
+        goto out;
+      }
+
+      if (ctx->Pack.BufferObj->Name) {
+        /* packing texture image into a PBO */
+        const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
+        if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
+                                       texImage->Height, texImage->Depth,
+                                       format, type, pixels)) {
+           _mesa_error(ctx, GL_INVALID_OPERATION,
+                       "glGetTexImage(invalid PBO access)");
+           goto out;
+        }
       }
-   }
 
-   /* typically, this will call _mesa_get_teximage() */
-   ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
-                           texObj, texImage);
+      /* typically, this will call _mesa_get_teximage() */
+      ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
+                             texObj, texImage);
+
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2301,40 +2311,47 @@ _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
          return;   /* error was recorded */
       }
 
-      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-      texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-
-      if (!texImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
-         return;
-      }
-      else if (texImage->Data) {
-        ctx->Driver.FreeTexImageData( ctx, texImage );
-      }
-      ASSERT(texImage->Data == NULL);
-      clear_teximage_fields(texImage); /* not really needed, but helpful */
-      _mesa_init_teximage_fields(ctx, target, texImage,
-                                 postConvWidth, 1, 1,
-                                 border, internalFormat);
-
       if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
-         _mesa_update_state(ctx);
+        _mesa_update_state(ctx);
 
-      ASSERT(ctx->Driver.TexImage1D);
+      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+      texObj = _mesa_select_tex_object(ctx, texUnit, target);
+      _mesa_lock_texture(ctx, texObj);
+      {
+        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+        if (!texImage) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+           goto out;
+        }
+      
+        if (texImage->Data) {
+           ctx->Driver.FreeTexImageData( ctx, texImage );
+        }
 
-      /* Give the texture to the driver!  <pixels> may be null! */
-      (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
-                                width, border, format, type, pixels,
-                                &ctx->Unpack, texObj, texImage);
+        ASSERT(texImage->Data == NULL);
 
-      ASSERT(texImage->TexFormat);
+        clear_teximage_fields(texImage); /* not really needed, but helpful */
+        _mesa_init_teximage_fields(ctx, target, texImage,
+                                   postConvWidth, 1, 1,
+                                   border, internalFormat);
+        
+        ASSERT(ctx->Driver.TexImage1D);
 
-      update_fbo_texture(ctx, texObj, face, level);
+        /* Give the texture to the driver!  <pixels> may be null! */
+        (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
+                                  width, border, format, type, pixels,
+                                  &ctx->Unpack, texObj, texImage);
+        
+        ASSERT(texImage->TexFormat);
 
-      /* state update */
-      texObj->Complete = GL_FALSE;
-      ctx->NewState |= _NEW_TEXTURE;
+        update_fbo_texture(ctx, texObj, face, level);
+        
+        /* state update */
+        texObj->Complete = GL_FALSE;
+        ctx->NewState |= _NEW_TEXTURE;
+      }
+   out:
+      _mesa_unlock_texture(ctx, texObj);
    }
    else if (target == GL_PROXY_TEXTURE_1D) {
       /* Proxy texture: check for errors and update proxy state */
@@ -2396,39 +2413,46 @@ _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
          return;   /* error was recorded */
       }
 
-      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-      texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-      if (!texImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
-      }
-      else if (texImage->Data) {
-        ctx->Driver.FreeTexImageData( ctx, texImage );
-      }
-      ASSERT(texImage->Data == NULL);
-      clear_teximage_fields(texImage); /* not really needed, but helpful */
-      _mesa_init_teximage_fields(ctx, target, texImage,
-                                 postConvWidth, postConvHeight, 1,
-                                 border, internalFormat);
-
       if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
-         _mesa_update_state(ctx);
+        _mesa_update_state(ctx);
 
-      ASSERT(ctx->Driver.TexImage2D);
-
-      /* Give the texture to the driver!  <pixels> may be null! */
-      (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
-                                width, height, border, format, type, pixels,
-                                &ctx->Unpack, texObj, texImage);
-
-      ASSERT(texImage->TexFormat);
-
-      update_fbo_texture(ctx, texObj, face, level);
-
-      /* state update */
-      texObj->Complete = GL_FALSE;
-      ctx->NewState |= _NEW_TEXTURE;
+      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+      texObj = _mesa_select_tex_object(ctx, texUnit, target);
+      _mesa_lock_texture(ctx, texObj);
+      {
+        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+        if (!texImage) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+           goto out;
+        }
+        
+        if (texImage->Data) {
+           ctx->Driver.FreeTexImageData( ctx, texImage );
+        }
+        
+        ASSERT(texImage->Data == NULL);
+        clear_teximage_fields(texImage); /* not really needed, but helpful */
+        _mesa_init_teximage_fields(ctx, target, texImage,
+                                   postConvWidth, postConvHeight, 1,
+                                   border, internalFormat);
+        
+        ASSERT(ctx->Driver.TexImage2D);
+
+        /* Give the texture to the driver!  <pixels> may be null! */
+        (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
+                                  width, height, border, format, type, pixels,
+                                  &ctx->Unpack, texObj, texImage);
+        
+        ASSERT(texImage->TexFormat);
+
+        update_fbo_texture(ctx, texObj, face, level);
+
+        /* state update */
+        texObj->Complete = GL_FALSE;
+        ctx->NewState |= _NEW_TEXTURE;
+      }
+   out:
+      _mesa_unlock_texture(ctx, texObj);
    }
    else if (target == GL_PROXY_TEXTURE_2D ||
             (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
@@ -2486,39 +2510,46 @@ _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
          return;   /* error was recorded */
       }
 
+      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
+        _mesa_update_state(ctx);
+
       texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
       texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-      if (!texImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-         return;
-      }
-      else if (texImage->Data) {
-        ctx->Driver.FreeTexImageData( ctx, texImage );
-      }
-      ASSERT(texImage->Data == NULL);
-      clear_teximage_fields(texImage); /* not really needed, but helpful */
-      _mesa_init_teximage_fields(ctx, target, texImage,
-                                 width, height, depth,
-                                 border, internalFormat);
-
-      if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE)
-         _mesa_update_state(ctx);
+      _mesa_lock_texture(ctx, texObj);
+      {
+        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+        if (!texImage) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
+           goto out;
+        }
+        
+        if (texImage->Data) {
+           ctx->Driver.FreeTexImageData( ctx, texImage );
+        }
+        
+        ASSERT(texImage->Data == NULL);
+        clear_teximage_fields(texImage); /* not really needed, but helpful */
+        _mesa_init_teximage_fields(ctx, target, texImage,
+                                   width, height, depth,
+                                   border, internalFormat);
 
-      ASSERT(ctx->Driver.TexImage3D);
+        ASSERT(ctx->Driver.TexImage3D);
 
-      /* Give the texture to the driver!  <pixels> may be null! */
-      (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
-                                width, height, depth, border, format, type,
-                                pixels, &ctx->Unpack, texObj, texImage);
+        /* Give the texture to the driver!  <pixels> may be null! */
+        (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat,
+                                  width, height, depth, border, format, type,
+                                  pixels, &ctx->Unpack, texObj, texImage);
 
-      ASSERT(texImage->TexFormat);
+        ASSERT(texImage->TexFormat);
 
-      update_fbo_texture(ctx, texObj, face, level);
+        update_fbo_texture(ctx, texObj, face, level);
 
-      /* state update */
-      texObj->Complete = GL_FALSE;
-      ctx->NewState |= _NEW_TEXTURE;
+        /* state update */
+        texObj->Complete = GL_FALSE;
+        ctx->NewState |= _NEW_TEXTURE;
+      }
+   out:
+      _mesa_unlock_texture(ctx, texObj);
    }
    else if (target == GL_PROXY_TEXTURE_3D) {
       /* Proxy texture: check for errors and update proxy state */
@@ -2566,7 +2597,7 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
    GLsizei postConvWidth = width;
    struct gl_texture_unit *texUnit;
    struct gl_texture_object *texObj;
-   struct gl_texture_image *texImage;
+   struct gl_texture_image *texImage = NULL;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
@@ -2579,26 +2610,38 @@ _mesa_TexSubImage1D( GLenum target, GLint level,
    }
 
    if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
-                              postConvWidth, 1, 1, format, type)) {
+                              postConvWidth, 1, 1, format, type)) {
       return;   /* error was detected */
    }
 
+
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   assert(texImage);
+   assert(texObj);
 
-   if (width == 0)
-      return;  /* no-op, not an error */
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
-   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
-   xoffset += texImage->Border;
+      if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
+                                 postConvWidth, 1, 1, format, type, texImage)) {
+        goto out;   /* error was detected */
+      }
+
+      if (width == 0)
+        goto out;  /* no-op, not an error */
+
+      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
+      xoffset += texImage->Border;
 
-   ASSERT(ctx->Driver.TexSubImage1D);
-   (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
-                                format, type, pixels, &ctx->Unpack,
-                                texObj, texImage);
-   ctx->NewState |= _NEW_TEXTURE;
+      ASSERT(ctx->Driver.TexSubImage1D);
+      (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
+                                  format, type, pixels, &ctx->Unpack,
+                                  texObj, texImage);
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2626,27 +2669,37 @@ _mesa_TexSubImage2D( GLenum target, GLint level,
    }
 
    if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
-                             postConvWidth, postConvHeight, 1, format, type)) {
+                             postConvWidth, postConvHeight, 1, format, type)) {
       return;   /* error was detected */
    }
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   assert(texImage);
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
-   if (width == 0 || height == 0)
-      return;  /* no-op, not an error */
+      if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
+                                 postConvWidth, postConvHeight, 1, format, type, 
+                                 texImage)) {
+        goto out;   /* error was detected */
+      }
 
-   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
-   xoffset += texImage->Border;
-   yoffset += texImage->Border;
+      if (width == 0 || height == 0)
+        goto out;  /* no-op, not an error */
 
-   ASSERT(ctx->Driver.TexSubImage2D);
-   (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
-                                width, height, format, type, pixels,
-                                &ctx->Unpack, texObj, texImage);
-   ctx->NewState |= _NEW_TEXTURE;
+      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
+      xoffset += texImage->Border;
+      yoffset += texImage->Border;
+      
+      ASSERT(ctx->Driver.TexSubImage2D);
+      (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset,
+                                  width, height, format, type, pixels,
+                                  &ctx->Unpack, texObj, texImage);
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2674,24 +2727,34 @@ _mesa_TexSubImage3D( GLenum target, GLint level,
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   assert(texImage);
-
-   if (width == 0 || height == 0 || height == 0)
-      return;  /* no-op, not an error */
-
-   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
-   xoffset += texImage->Border;
-   yoffset += texImage->Border;
-   zoffset += texImage->Border;
-
-   ASSERT(ctx->Driver.TexSubImage3D);
-   (*ctx->Driver.TexSubImage3D)(ctx, target, level,
-                                xoffset, yoffset, zoffset,
-                                width, height, depth,
-                                format, type, pixels,
-                                &ctx->Unpack, texObj, texImage );
-   ctx->NewState |= _NEW_TEXTURE;
+
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+      if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset,
+                                 width, height, depth, format, type, texImage)) {
+        goto out;   /* error was detected */
+      }
+
+      if (width == 0 || height == 0 || height == 0)
+        goto out;  /* no-op, not an error */
+
+      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
+      xoffset += texImage->Border;
+      yoffset += texImage->Border;
+      zoffset += texImage->Border;
+
+      ASSERT(ctx->Driver.TexSubImage3D);
+      (*ctx->Driver.TexSubImage3D)(ctx, target, level,
+                                  xoffset, yoffset, zoffset,
+                                  width, height, depth,
+                                  format, type, pixels,
+                                  &ctx->Unpack, texObj, texImage );
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2723,32 +2786,39 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-   if (!texImage) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
-      return;
-   }
-   else if (texImage->Data) {
-      ctx->Driver.FreeTexImageData( ctx, texImage );
-   }
-   ASSERT(texImage->Data == NULL);
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+      if (!texImage) {
+        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
+        goto out;
+      }
+
+      if (texImage->Data) {
+        ctx->Driver.FreeTexImageData( ctx, texImage );
+      }
+      
+      ASSERT(texImage->Data == NULL);
 
-   clear_teximage_fields(texImage); /* not really needed, but helpful */
-   _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
-                              border, internalFormat);
+      clear_teximage_fields(texImage); /* not really needed, but helpful */
+      _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
+                                border, internalFormat);
 
 
-   ASSERT(ctx->Driver.CopyTexImage1D);
-   (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
-                                 x, y, width, border);
+      ASSERT(ctx->Driver.CopyTexImage1D);
+      (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat,
+                                   x, y, width, border);
 
-   ASSERT(texImage->TexFormat);
+      ASSERT(texImage->TexFormat);
 
-   update_fbo_texture(ctx, texObj, face, level);
+      update_fbo_texture(ctx, texObj, face, level);
 
-   /* state update */
-   texObj->Complete = GL_FALSE;
-   ctx->NewState |= _NEW_TEXTURE;
+      /* state update */
+      texObj->Complete = GL_FALSE;
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2780,41 +2850,50 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-   if (!texImage) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
-      return;
-   }
-   else if (texImage->Data) {
-      ctx->Driver.FreeTexImageData( ctx, texImage );
-   }
-   ASSERT(texImage->Data == NULL);
 
-   clear_teximage_fields(texImage); /* not really needed, but helpful */
-   _mesa_init_teximage_fields(ctx, target, texImage,
-                              postConvWidth, postConvHeight, 1,
-                              border, internalFormat);
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_get_tex_image(ctx, texObj, target, level);
 
-   ASSERT(ctx->Driver.CopyTexImage2D);
-   (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
-                                 x, y, width, height, border);
+      if (!texImage) {
+        _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
+        goto out;
+      }
+      
+      if (texImage->Data) {
+        ctx->Driver.FreeTexImageData( ctx, texImage );
+      }
+      
+      ASSERT(texImage->Data == NULL);
 
-   ASSERT(texImage->TexFormat);
+      clear_teximage_fields(texImage); /* not really needed, but helpful */
+      _mesa_init_teximage_fields(ctx, target, texImage,
+                                postConvWidth, postConvHeight, 1,
+                                border, internalFormat);
+      
+      ASSERT(ctx->Driver.CopyTexImage2D);
+      (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat,
+                                   x, y, width, height, border);
+      
+      ASSERT(texImage->TexFormat);
 
-   update_fbo_texture(ctx, texObj, face, level);
+      update_fbo_texture(ctx, texObj, face, level);
 
-   /* state update */
-   texObj->Complete = GL_FALSE;
-   ctx->NewState |= _NEW_TEXTURE;
+      /* state update */
+      texObj->Complete = GL_FALSE;
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
-
 void GLAPIENTRY
 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
                          GLint xoffset, GLint x, GLint y, GLsizei width )
 {
    struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
    GLsizei postConvWidth = width;
    GET_CURRENT_CONTEXT(ctx);
@@ -2831,15 +2910,27 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
       return;
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   ASSERT(texImage);
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+
+      if (copytexsubimage_error_check2(ctx, 1, target, level,
+                                      xoffset, 0, 0, postConvWidth, 1,
+                                      texImage))
+        goto out;
+      
 
-   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
-   xoffset += texImage->Border;
+      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
+      xoffset += texImage->Border;
 
-   ASSERT(ctx->Driver.CopyTexSubImage1D);
-   (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
-   ctx->NewState |= _NEW_TEXTURE;
+      ASSERT(ctx->Driver.CopyTexSubImage1D);
+      (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width);
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2850,6 +2941,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
                          GLint x, GLint y, GLsizei width, GLsizei height )
 {
    struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
    GLsizei postConvWidth = width, postConvHeight = height;
    GET_CURRENT_CONTEXT(ctx);
@@ -2866,17 +2958,27 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
       return;
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   ASSERT(texImage);
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
-   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
-   xoffset += texImage->Border;
-   yoffset += texImage->Border;
+      if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
+                                      postConvWidth, postConvHeight, texImage))
+        goto out;
 
-   ASSERT(ctx->Driver.CopyTexSubImage2D);
-   (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
-                                    xoffset, yoffset, x, y, width, height);
-   ctx->NewState |= _NEW_TEXTURE;
+      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
+      xoffset += texImage->Border;
+      yoffset += texImage->Border;
+      
+      ASSERT(ctx->Driver.CopyTexSubImage2D);
+      (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
+                                      xoffset, yoffset, x, y, width, height);
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -2887,6 +2989,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
                          GLint x, GLint y, GLsizei width, GLsizei height )
 {
    struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
    GLsizei postConvWidth = width, postConvHeight = height;
    GET_CURRENT_CONTEXT(ctx);
@@ -2903,19 +3006,30 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
       return;
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   ASSERT(texImage);
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
 
-   /* If we have a border, xoffset=-1 is legal.  Bias by border width */
-   xoffset += texImage->Border;
-   yoffset += texImage->Border;
-   zoffset += texImage->Border;
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
 
-   ASSERT(ctx->Driver.CopyTexSubImage3D);
-   (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
-                                    xoffset, yoffset, zoffset,
-                                    x, y, width, height);
-   ctx->NewState |= _NEW_TEXTURE;
+      if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
+                                      zoffset, postConvWidth, postConvHeight,
+                                      texImage))
+        goto out;
+
+      /* If we have a border, xoffset=-1 is legal.  Bias by border width */
+      xoffset += texImage->Border;
+      yoffset += texImage->Border;
+      zoffset += texImage->Border;
+      
+      ASSERT(ctx->Driver.CopyTexSubImage3D);
+      (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
+                                      xoffset, yoffset, zoffset,
+                                      x, y, width, height);
+      ctx->NewState |= _NEW_TEXTURE;
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -3136,28 +3250,35 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
 
       texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
       texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-      if (!texImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
-         return;
-      }
-      else if (texImage->Data) {
-        ctx->Driver.FreeTexImageData( ctx, texImage );
-      }
-      ASSERT(texImage->Data == NULL);
 
-      _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
-                                 border, internalFormat);
+      _mesa_lock_texture(ctx, texObj);
+      {
+        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+        if (!texImage) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
+           goto out;
+        }
+        
+        if (texImage->Data) {
+           ctx->Driver.FreeTexImageData( ctx, texImage );
+        }
+        ASSERT(texImage->Data == NULL);
+
+        _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+                                   border, internalFormat);
 
-      ASSERT(ctx->Driver.CompressedTexImage1D);
-      (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
-                                          internalFormat, width, border,
-                                          imageSize, data,
-                                          texObj, texImage);
+        ASSERT(ctx->Driver.CompressedTexImage1D);
+        (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
+                                            internalFormat, width, border,
+                                            imageSize, data,
+                                            texObj, texImage);
 
-      /* state update */
-      texObj->Complete = GL_FALSE;
-      ctx->NewState |= _NEW_TEXTURE;
+        /* state update */
+        texObj->Complete = GL_FALSE;
+        ctx->NewState |= _NEW_TEXTURE;
+      }
+   out:
+      _mesa_unlock_texture(ctx, texObj);
    }
    else if (target == GL_PROXY_TEXTURE_1D) {
       /* Proxy texture: check for errors and update proxy state */
@@ -3179,11 +3300,18 @@ _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
       else {
          /* store the teximage parameters */
          struct gl_texture_unit *texUnit;
+         struct gl_texture_object *texObj;
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
-                                    border, internalFormat);
+        texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+        _mesa_lock_texture(ctx, texObj);
+        {
+           texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+           _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
+                                      border, internalFormat);
+        }
+        _mesa_unlock_texture(ctx, texObj);
       }
    }
    else {
@@ -3219,28 +3347,35 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
 
       texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
       texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-      if (!texImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
-         return;
-      }
-      else if (texImage->Data) {
-        ctx->Driver.FreeTexImageData( ctx, texImage );
-      }
-      ASSERT(texImage->Data == NULL);
 
-      _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                 border, internalFormat);
+      _mesa_lock_texture(ctx, texObj);
+      {
+        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+        if (!texImage) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+           goto out;
+        }
+        
+        if (texImage->Data) {
+           ctx->Driver.FreeTexImageData( ctx, texImage );
+        }
+        ASSERT(texImage->Data == NULL);
 
-      ASSERT(ctx->Driver.CompressedTexImage2D);
-      (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
-                                          internalFormat, width, height,
-                                          border, imageSize, data,
-                                          texObj, texImage);
+        _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+                                   border, internalFormat);
 
-      /* state update */
-      texObj->Complete = GL_FALSE;
-      ctx->NewState |= _NEW_TEXTURE;
+        ASSERT(ctx->Driver.CompressedTexImage2D);
+        (*ctx->Driver.CompressedTexImage2D)(ctx, target, level,
+                                            internalFormat, width, height,
+                                            border, imageSize, data,
+                                            texObj, texImage);
+        
+        /* state update */
+        texObj->Complete = GL_FALSE;
+        ctx->NewState |= _NEW_TEXTURE;
+      }
+   out:
+      _mesa_unlock_texture(ctx, texObj);
    }
    else if (target == GL_PROXY_TEXTURE_2D ||
             (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
@@ -3264,11 +3399,18 @@ _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
       else {
          /* store the teximage parameters */
          struct gl_texture_unit *texUnit;
+         struct gl_texture_object *texObj;
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
-                                    border, internalFormat);
+        texObj = _mesa_select_tex_object(ctx, texUnit, target);
+
+        _mesa_lock_texture(ctx, texObj);
+        {
+           texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+           _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+                                      border, internalFormat);
+        }
+        _mesa_unlock_texture(ctx, texObj);
       }
    }
    else {
@@ -3301,29 +3443,35 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
 
       texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
       texObj = _mesa_select_tex_object(ctx, texUnit, target);
-      texImage = _mesa_get_tex_image(ctx, texUnit, target, level);
-      if (!texImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
-         return;
-      }
-      else if (texImage->Data) {
-        ctx->Driver.FreeTexImageData( ctx, texImage );
-      }
-      ASSERT(texImage->Data == NULL);
-
-      _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
-                                 border, internalFormat);
+      _mesa_lock_texture(ctx, texObj);
+      {
+        texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+        if (!texImage) {
+           _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
+           goto out;
+        }
+        
+        if (texImage->Data) {
+           ctx->Driver.FreeTexImageData( ctx, texImage );
+        }
+        ASSERT(texImage->Data == NULL);
 
-      ASSERT(ctx->Driver.CompressedTexImage3D);
-      (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
-                                          internalFormat,
-                                          width, height, depth,
-                                          border, imageSize, data,
-                                          texObj, texImage);
+        _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth,
+                                   border, internalFormat);
 
-      /* state update */
-      texObj->Complete = GL_FALSE;
-      ctx->NewState |= _NEW_TEXTURE;
+        ASSERT(ctx->Driver.CompressedTexImage3D);
+        (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
+                                            internalFormat,
+                                            width, height, depth,
+                                            border, imageSize, data,
+                                            texObj, texImage);
+        
+        /* state update */
+        texObj->Complete = GL_FALSE;
+        ctx->NewState |= _NEW_TEXTURE;
+      }
+   out:
+      _mesa_unlock_texture(ctx, texObj);
    }
    else if (target == GL_PROXY_TEXTURE_3D) {
       /* Proxy texture: check for errors and update proxy state */
@@ -3345,11 +3493,17 @@ _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
       else {
          /* store the teximage parameters */
          struct gl_texture_unit *texUnit;
+         struct gl_texture_object *texObj;
          struct gl_texture_image *texImage;
          texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-         texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-         _mesa_init_teximage_fields(ctx, target, texImage, width, height,
-                                    depth, border, internalFormat);
+        texObj = _mesa_select_tex_object(ctx, texUnit, target);
+        _mesa_lock_texture(ctx, texObj);
+        {
+           texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+           _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+                                      depth, border, internalFormat);
+        }
+        _mesa_unlock_texture(ctx, texObj);
       }
    }
    else {
@@ -3382,30 +3536,35 @@ _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   assert(texImage);
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+      assert(texImage);
 
-   if ((GLint) format != texImage->InternalFormat) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glCompressedTexSubImage1D(format)");
-      return;
-   }
+      if ((GLint) format != texImage->InternalFormat) {
+        _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "glCompressedTexSubImage1D(format)");
+        goto out;
+      }
 
-   if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
-      return;
-   }
+      if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) {
+        _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)");
+        goto out;
+      }
       
-   if (width == 0)
-      return;  /* no-op, not an error */
+      if (width == 0)
+        goto out;  /* no-op, not an error */
 
-   if (ctx->Driver.CompressedTexSubImage1D) {
-      (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
-                                             xoffset, width,
-                                             format, imageSize, data,
-                                             texObj, texImage);
+      if (ctx->Driver.CompressedTexSubImage1D) {
+        (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
+                                               xoffset, width,
+                                               format, imageSize, data,
+                                               texObj, texImage);
+      }
+      ctx->NewState |= _NEW_TEXTURE;
    }
-   ctx->NewState |= _NEW_TEXTURE;
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -3434,31 +3593,36 @@ _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   assert(texImage);
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+      assert(texImage);
 
-   if ((GLint) format != texImage->InternalFormat) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glCompressedTexSubImage2D(format)");
-      return;
-   }
+      if ((GLint) format != texImage->InternalFormat) {
+        _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "glCompressedTexSubImage2D(format)");
+        goto out;
+      }
 
-   if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
-       ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
-      return;
-   }
+      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
+         ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) {
+        _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)");
+        goto out;
+      }
       
-   if (width == 0 || height == 0)
-      return;  /* no-op, not an error */
+      if (width == 0 || height == 0)
+        goto out;  /* no-op, not an error */
 
-   if (ctx->Driver.CompressedTexSubImage2D) {
-      (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
-                                             xoffset, yoffset, width, height,
-                                             format, imageSize, data,
-                                             texObj, texImage);
+      if (ctx->Driver.CompressedTexSubImage2D) {
+        (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
+                                               xoffset, yoffset, width, height,
+                                               format, imageSize, data,
+                                               texObj, texImage);
+      }
+      ctx->NewState |= _NEW_TEXTURE;
    }
-   ctx->NewState |= _NEW_TEXTURE;
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -3486,33 +3650,38 @@ _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
 
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   assert(texImage);
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+      assert(texImage);
 
-   if ((GLint) format != texImage->InternalFormat) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glCompressedTexSubImage3D(format)");
-      return;
-   }
+      if ((GLint) format != texImage->InternalFormat) {
+        _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "glCompressedTexSubImage3D(format)");
+        goto out;
+      }
 
-   if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
-       ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
-       ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
-      _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
-      return;
-   }
+      if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) ||
+         ((height == 1 || height == 2) && (GLuint) height != texImage->Height) ||
+         ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) {
+        _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)");
+        goto out;
+      }
       
-   if (width == 0 || height == 0 || depth == 0)
-      return;  /* no-op, not an error */
+      if (width == 0 || height == 0 || depth == 0)
+        goto out;  /* no-op, not an error */
 
-   if (ctx->Driver.CompressedTexSubImage3D) {
-      (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
-                                             xoffset, yoffset, zoffset,
-                                             width, height, depth,
-                                             format, imageSize, data,
-                                             texObj, texImage);
+      if (ctx->Driver.CompressedTexSubImage3D) {
+        (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
+                                               xoffset, yoffset, zoffset,
+                                               width, height, depth,
+                                               format, imageSize, data,
+                                               texObj, texImage);
+      }
+      ctx->NewState |= _NEW_TEXTURE;
    }
-   ctx->NewState |= _NEW_TEXTURE;
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -3520,12 +3689,13 @@ void GLAPIENTRY
 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
 {
    const struct gl_texture_unit *texUnit;
-   const struct gl_texture_object *texObj;
+   struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
    GLint maxLevels;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
+
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
    if (!texObj) {
@@ -3546,18 +3716,24 @@ _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
       return;
    }
 
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
-   if (!texImage) {
-      /* probably invalid mipmap level */
-      _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
-      return;
-   }
 
-   if (!texImage->IsCompressed) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
-      return;
-   }
+   _mesa_lock_texture(ctx, texObj);
+   {
+      texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+      if (!texImage) {
+        /* probably invalid mipmap level */
+        _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
+        goto out;
+      }
+
+      if (!texImage->IsCompressed) {
+        _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
+        goto out;
+      }
 
-   /* this typically calls _mesa_get_compressed_teximage() */
-   ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
+      /* this typically calls _mesa_get_compressed_teximage() */
+      ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage);
+   }
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
index 410789fe0463daad2108fc6971136dbda657f8c5..68457f4728c76f8c35881ce626fb4db39df62d0b 100644 (file)
@@ -84,12 +84,12 @@ _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
 
 
 extern struct gl_texture_image *
-_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
                        GLenum target, GLint level);
 
 
 extern struct gl_texture_image *
-_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
+_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
                     GLenum target, GLint level);
 
 
@@ -106,6 +106,23 @@ _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
                          GLint internalFormat, GLenum format, GLenum type,
                          GLint width, GLint height, GLint depth, GLint border);
 
+
+/* Lock a texture for updating.  See also _mesa_lock_context_textures().
+ */
+static INLINE void _mesa_lock_texture(GLcontext *ctx,
+                                     struct gl_texture_object *texObj)
+{
+   _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
+   ctx->Shared->TextureStateStamp++;
+   (void) texObj;
+}
+
+static INLINE void _mesa_unlock_texture(GLcontext *ctx,
+                                       struct gl_texture_object *texObj)
+{
+   _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
+}
+
 /*@}*/
 
 
index 8b42c2a712c695214e7a0bc8bba36c0d655e97a0..1d27cd3f7c69aaedca0496241cf0d3f3197c4711 100644 (file)
@@ -697,7 +697,11 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
       if (textures[i] > 0) {
          struct gl_texture_object *delObj
             = _mesa_lookup_texture(ctx, textures[i]);
+
          if (delObj) {
+           GLboolean delete;
+
+           _mesa_lock_texture(ctx, delObj);
 
             /* Check if texture is bound to any framebuffer objects.
              * If so, unbind.
@@ -724,7 +728,14 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
              * XXX all RefCount accesses should be protected by a mutex.
              */
             delObj->RefCount--;
-            if (delObj->RefCount == 0) {
+           delete = (delObj->RefCount == 0);
+           _mesa_unlock_texture(ctx, delObj);
+
+           /* We know that refcount went to zero above, so this is
+            * the only pointer left to delObj, so we don't have to
+            * worry about locking any more:
+            */
+            if (delete) {
                ASSERT(delObj->Name != 0); /* Never delete default tex objs */
                ASSERT(ctx->Driver.DeleteTexture);
                (*ctx->Driver.DeleteTexture)(ctx, delObj);
@@ -1052,4 +1063,30 @@ _mesa_IsTexture( GLuint texture )
    return t && t->Target;
 }
 
+/* Simplest implementation of texture locking: Grab the a new mutex in
+ * the shared context.  Examine the shared context state timestamp and
+ * if there has been a change, set the appropriate bits in
+ * ctx->NewState.
+ *
+ * See also _mesa_lock/unlock_texture in texobj.h
+ */
+void _mesa_lock_context_textures( GLcontext *ctx )
+{
+   _glthread_LOCK_MUTEX(ctx->Shared->TexMutex);
+
+   if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
+      ctx->NewState |= _NEW_TEXTURE;
+      ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
+   }
+}
+
+
+void _mesa_unlock_context_textures( GLcontext *ctx )
+{
+   assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
+   _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex);
+}
+
 /*@}*/
+
+
index ac66ac69d3cc3001400d659473d9a1c081730ded..ec7cf8cd86e80430d2ba52c82d1fc7a1ba8b073b 100644 (file)
@@ -61,6 +61,9 @@ extern void
 _mesa_test_texobj_completeness( const GLcontext *ctx,
                                 struct gl_texture_object *obj );
 
+extern void _mesa_unlock_context_textures( GLcontext *ctx );
+extern void _mesa_lock_context_textures( GLcontext *ctx );
+
 /*@}*/
 
 
@@ -95,4 +98,5 @@ _mesa_IsTexture( GLuint texture );
 
 /*@}*/
 
+
 #endif
index 0687e5760c9b96303f22cf726c6da41880e95a7b..bcedcafe19e2b303fa3d7f4af62b588db3ee6f76 100644 (file)
@@ -144,6 +144,8 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
       dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
 
       /* copy texture object bindings, not contents of texture objects */
+      _mesa_lock_context_textures(dst);
+
       copy_texture_binding(src, &dst->Texture.Unit[i].Current1D,
                            src->Texture.Unit[i].Current1D);
       copy_texture_binding(src, &dst->Texture.Unit[i].Current2D,
@@ -154,6 +156,8 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
                            src->Texture.Unit[i].CurrentCubeMap);
       copy_texture_binding(src, &dst->Texture.Unit[i].CurrentRect,
                            src->Texture.Unit[i].CurrentRect);
+
+      _mesa_unlock_context_textures(dst);
    }
 }
 
@@ -1700,6 +1704,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                               GLenum pname, GLint *params )
 {
    const struct gl_texture_unit *texUnit;
+   struct gl_texture_object *texObj;
    const struct gl_texture_image *img = NULL;
    GLuint dimensions;
    GLboolean isProxy;
@@ -1734,14 +1739,17 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
       return;
    }
 
-   img = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   _mesa_lock_texture(ctx, texObj);
+
+   img = _mesa_select_tex_image(ctx, texObj, target, level);
    if (!img || !img->TexFormat) {
       /* undefined texture image */
       if (pname == GL_TEXTURE_COMPONENTS)
          *params = 1;
       else
          *params = 0;
-      return;
+      goto out;
    }
 
    isProxy = _mesa_is_proxy_texture(target);
@@ -1749,37 +1757,37 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
    switch (pname) {
       case GL_TEXTURE_WIDTH:
          *params = img->Width;
-         return;
+         break;
       case GL_TEXTURE_HEIGHT:
          *params = img->Height;
-         return;
+         break;
       case GL_TEXTURE_DEPTH:
          *params = img->Depth;
-         return;
+         break;
       case GL_TEXTURE_INTERNAL_FORMAT:
          *params = img->InternalFormat;
-         return;
+         break;
       case GL_TEXTURE_BORDER:
          *params = img->Border;
-         return;
+         break;
       case GL_TEXTURE_RED_SIZE:
          if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->RedBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_GREEN_SIZE:
          if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->GreenBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_BLUE_SIZE:
          if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
             *params = img->TexFormat->BlueBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_ALPHA_SIZE:
          if (img->_BaseFormat == GL_ALPHA ||
              img->_BaseFormat == GL_LUMINANCE_ALPHA ||
@@ -1787,7 +1795,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = img->TexFormat->AlphaBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_INTENSITY_SIZE:
          if (img->_BaseFormat != GL_INTENSITY)
             *params = 0;
@@ -1795,7 +1803,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = img->TexFormat->IntensityBits;
          else /* intensity probably stored as rgb texture */
             *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
-         return;
+         break;
       case GL_TEXTURE_LUMINANCE_SIZE:
          if (img->_BaseFormat != GL_LUMINANCE &&
              img->_BaseFormat != GL_LUMINANCE_ALPHA)
@@ -1804,13 +1812,13 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             *params = img->TexFormat->LuminanceBits;
          else /* luminance probably stored as rgb texture */
             *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
-         return;
+         break;
       case GL_TEXTURE_INDEX_SIZE_EXT:
          if (img->_BaseFormat == GL_COLOR_INDEX)
             *params = img->TexFormat->IndexBits;
          else
             *params = 0;
-         return;
+         break;
       case GL_TEXTURE_DEPTH_SIZE_ARB:
          if (ctx->Extensions.SGIX_depth_texture ||
              ctx->Extensions.ARB_depth_texture)
@@ -1818,7 +1826,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
          else
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
-         return;
+         break;
       case GL_TEXTURE_STENCIL_SIZE_EXT:
          if (ctx->Extensions.EXT_packed_depth_stencil) {
             *params = img->TexFormat->StencilBits;
@@ -1827,7 +1835,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
 
       /* GL_ARB_texture_compression */
       case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
@@ -1849,7 +1857,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_COMPRESSED:
          if (ctx->Extensions.ARB_texture_compression) {
             *params = (GLint) img->IsCompressed;
@@ -1858,7 +1866,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
 
       /* GL_ARB_texture_float */
       case GL_TEXTURE_RED_TYPE_ARB:
@@ -1869,7 +1877,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_GREEN_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
@@ -1878,7 +1886,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_BLUE_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
@@ -1887,7 +1895,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_ALPHA_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
@@ -1896,7 +1904,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_LUMINANCE_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
@@ -1905,7 +1913,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_INTENSITY_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
@@ -1914,7 +1922,7 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
       case GL_TEXTURE_DEPTH_TYPE_ARB:
          if (ctx->Extensions.ARB_texture_float) {
             *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
@@ -1923,12 +1931,15 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
             _mesa_error(ctx, GL_INVALID_ENUM,
                         "glGetTexLevelParameter[if]v(pname)");
          }
-         return;
+         break;
 
       default:
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "glGetTexLevelParameter[if]v(pname)");
    }
+
+ out:
+   _mesa_unlock_texture(ctx, texObj);
 }
 
 
@@ -1938,6 +1949,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
 {
    struct gl_texture_unit *texUnit;
    struct gl_texture_object *obj;
+   GLboolean error = GL_FALSE;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -1955,28 +1967,29 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
       return;
    }
 
+   _mesa_lock_texture(ctx, obj);
    switch (pname) {
       case GL_TEXTURE_MAG_FILTER:
         *params = ENUM_TO_FLOAT(obj->MagFilter);
-        return;
+        break;
       case GL_TEXTURE_MIN_FILTER:
          *params = ENUM_TO_FLOAT(obj->MinFilter);
-         return;
+         break;
       case GL_TEXTURE_WRAP_S:
          *params = ENUM_TO_FLOAT(obj->WrapS);
-         return;
+         break;
       case GL_TEXTURE_WRAP_T:
          *params = ENUM_TO_FLOAT(obj->WrapT);
-         return;
+         break;
       case GL_TEXTURE_WRAP_R:
          *params = ENUM_TO_FLOAT(obj->WrapR);
-         return;
+         break;
       case GL_TEXTURE_BORDER_COLOR:
          params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
          params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
          params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
          params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
-         return;
+         break;
       case GL_TEXTURE_RESIDENT:
          {
             GLboolean resident;
@@ -1986,82 +1999,94 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
                resident = GL_TRUE;
             *params = ENUM_TO_FLOAT(resident);
          }
-         return;
+         break;
       case GL_TEXTURE_PRIORITY:
          *params = obj->Priority;
-         return;
+         break;
       case GL_TEXTURE_MIN_LOD:
          *params = obj->MinLod;
-         return;
+         break;
       case GL_TEXTURE_MAX_LOD:
          *params = obj->MaxLod;
-         return;
+         break;
       case GL_TEXTURE_BASE_LEVEL:
          *params = (GLfloat) obj->BaseLevel;
-         return;
+         break;
       case GL_TEXTURE_MAX_LEVEL:
          *params = (GLfloat) obj->MaxLevel;
-         return;
+         break;
       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
          if (ctx->Extensions.EXT_texture_filter_anisotropic) {
             *params = obj->MaxAnisotropy;
-            return;
          }
+        else
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_SGIX:
          if (ctx->Extensions.SGIX_shadow) {
             *params = (GLfloat) obj->CompareFlag;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
          if (ctx->Extensions.SGIX_shadow) {
             *params = (GLfloat) obj->CompareOperator;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
          if (ctx->Extensions.SGIX_shadow_ambient) {
             *params = obj->ShadowAmbient;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_GENERATE_MIPMAP_SGIS:
          if (ctx->Extensions.SGIS_generate_mipmap) {
             *params = (GLfloat) obj->GenerateMipmap;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_MODE_ARB:
          if (ctx->Extensions.ARB_shadow) {
             *params = (GLfloat) obj->CompareMode;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_COMPARE_FUNC_ARB:
          if (ctx->Extensions.ARB_shadow) {
             *params = (GLfloat) obj->CompareFunc;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_DEPTH_TEXTURE_MODE_ARB:
          if (ctx->Extensions.ARB_depth_texture) {
             *params = (GLfloat) obj->DepthMode;
-            return;
          }
+        else 
+           error = 1;
          break;
       case GL_TEXTURE_LOD_BIAS:
          if (ctx->Extensions.EXT_texture_lod_bias) {
             *params = obj->LodBias;
-            return;
          }
+        else 
+           error = 1;
          break;
       default:
-         ; /* silence warnings */
+        error = 1;
+        break;
    }
-   /* If we get here, pname was an unrecognized enum */
-   _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
-               pname);
+   if (error)
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
+                 pname);
+
+   _mesa_unlock_texture(ctx, obj);
 }
 
 
index b8e5e4bd8aef67d56b6dfeb34c329fc04d9bb6a8..43e3bc183d4d2a7d407f08ba2295184c3e891c4c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.1
+ * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
@@ -2571,8 +2571,6 @@ parse_fp_vector_src_reg(GLcontext * ctx, const GLubyte ** inst,
 
    reg->File = file;
    reg->Index = index;
-   reg->Abs = 0;               /* NV only */
-   reg->NegateAbs = 0;         /* NV only */
    reg->NegateBase = negate;
    reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
    return 0;
@@ -2595,8 +2593,6 @@ parse_fp_dst_reg(GLcontext * ctx, const GLubyte ** inst,
    if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
       return 1;
 
-   reg->CondMask = 0;          /* NV only */
-   reg->CondSwizzle = 0;       /* NV only */
    reg->File = file;
    reg->Index = idx;
    reg->WriteMask = mask;
@@ -2632,8 +2628,6 @@ parse_fp_scalar_src_reg (GLcontext * ctx, const GLubyte ** inst,
 
    reg->File = File;
    reg->Index = Index;
-   reg->Abs = 0;               /* NV only */
-   reg->NegateAbs = 0;         /* NV only */
    reg->NegateBase = Negate;
    reg->Swizzle = (Swizzle[0] << 0);
 
@@ -2656,7 +2650,7 @@ parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
    GLubyte instClass, type, code;
    GLboolean rel;
 
-   _mesa_init_instruction(fp);
+   _mesa_init_instructions(fp, 1);
 
    /* Record the position in the program string for debugging */
    fp->StringPos = Program->Position;
@@ -3148,7 +3142,7 @@ parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
    /* The actual opcode name */
    code = *(*inst)++;
 
-   _mesa_init_instruction(vp);
+   _mesa_init_instructions(vp, 1);
    /* Record the position in the program string for debugging */
    vp->StringPos = Program->Position;
 
@@ -3690,7 +3684,7 @@ parse_instructions(GLcontext * ctx, const GLubyte * inst,
    /* Finally, tag on an OPCODE_END instruction */
    {
       const GLuint numInst = Program->Base.NumInstructions;
-      _mesa_init_instruction(Program->Base.Instructions + numInst);
+      _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
       Program->Base.Instructions[numInst].Opcode = OPCODE_END;
       /* YYY Wrong Position in program, whatever, at least not random -> crash
         Program->Position = parse_position (&inst);
index 49ce220944eba19e923084e2a2aad54d9dea206c..5f3a30b74164d84c097caaa4e487ef9486e41a37 100644 (file)
@@ -1273,7 +1273,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
       GLubyte token[100];
 
       /* Initialize the instruction */
-      _mesa_init_instruction(inst);
+      _mesa_init_instructions(inst, 1);
 
       /* special instructions */
       if (Parse_String(parseState, "DEFINE")) {
index 47d2b61a6289eb3e9a2d3e3349dda553e2b00942..0e9a01dcab8fec96eda7533bfa8dca670d11e015 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.1
+ * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
@@ -77,10 +77,7 @@ _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
       return;
    }
    
-   _mesa_init_vp_per_vertex_registers(ctx);
-   _mesa_init_vp_per_primitive_registers(ctx);
-   COPY_4V(ctx->VertexProgram.Machine.Inputs[VERT_ATTRIB_POS], params);
-   _mesa_exec_vertex_program(ctx, vprog);
+   _mesa_exec_vertex_state_program(ctx, vprog, params);
 }
 
 
index 19855936593b39c9ee7bf906d29da1645be542cb..10962d7e14ac7fc5b46535119c9f22e8f354129e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
@@ -47,23 +47,23 @@ static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
  * per-vertex.
  */
 void
-_mesa_init_vp_per_vertex_registers(GLcontext *ctx)
+_mesa_init_vp_per_vertex_registers(GLcontext *ctx, struct vp_machine *machine)
 {
    /* Input registers get initialized from the current vertex attribs */
-   MEMCPY(ctx->VertexProgram.Machine.Inputs, ctx->Current.Attrib,
+   MEMCPY(machine->Inputs, ctx->Current.Attrib,
           MAX_VERTEX_PROGRAM_ATTRIBS * 4 * sizeof(GLfloat));
 
    if (ctx->VertexProgram.Current->IsNVProgram) {
       GLuint i;
       /* Output/result regs are initialized to [0,0,0,1] */
       for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
-         ASSIGN_4V(ctx->VertexProgram.Machine.Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F);
+         ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F);
       }
       /* Temp regs are initialized to [0,0,0,0] */
       for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
-         ASSIGN_4V(ctx->VertexProgram.Machine.Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
+         ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
       }
-      ASSIGN_4V(ctx->VertexProgram.Machine.AddressReg, 0, 0, 0, 0);
+      ASSIGN_4V(machine->AddressReg, 0, 0, 0, 0);
    }
 }
 
@@ -139,7 +139,7 @@ _mesa_init_vp_per_primitive_registers(GLcontext *ctx)
             continue;
          }
 
-         /* load the matrix */
+         /* load the matrix values into sequential registers */
          if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
             load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
          }
@@ -176,36 +176,37 @@ _mesa_init_vp_per_primitive_registers(GLcontext *ctx)
  * For debugging.  Dump the current vertex program machine registers.
  */
 void
-_mesa_dump_vp_state( const struct gl_vertex_program_state *state )
+_mesa_dump_vp_state( const struct gl_vertex_program_state *state,
+                     const struct vp_machine *machine)
 {
    int i;
    _mesa_printf("VertexIn:\n");
    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_INPUTS; i++) {
       _mesa_printf("%d: %f %f %f %f   ", i,
-                   state->Machine.Inputs[i][0],
-                   state->Machine.Inputs[i][1],
-                   state->Machine.Inputs[i][2],
-                   state->Machine.Inputs[i][3]);
+                   machine->Inputs[i][0],
+                   machine->Inputs[i][1],
+                   machine->Inputs[i][2],
+                   machine->Inputs[i][3]);
    }
    _mesa_printf("\n");
 
    _mesa_printf("VertexOut:\n");
    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
       _mesa_printf("%d: %f %f %f %f   ", i,
-                  state->Machine.Outputs[i][0],
-                  state->Machine.Outputs[i][1],
-                  state->Machine.Outputs[i][2],
-                  state->Machine.Outputs[i][3]);
+                  machine->Outputs[i][0],
+                  machine->Outputs[i][1],
+                  machine->Outputs[i][2],
+                  machine->Outputs[i][3]);
    }
    _mesa_printf("\n");
 
    _mesa_printf("Registers:\n");
    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
       _mesa_printf("%d: %f %f %f %f   ", i,
-                  state->Machine.Temporaries[i][0],
-                  state->Machine.Temporaries[i][1],
-                  state->Machine.Temporaries[i][2],
-                  state->Machine.Temporaries[i][3]);
+                  machine->Temporaries[i][0],
+                  machine->Temporaries[i][1],
+                  machine->Temporaries[i][2],
+                  machine->Temporaries[i][3]);
    }
    _mesa_printf("\n");
 
@@ -227,41 +228,45 @@ _mesa_dump_vp_state( const struct gl_vertex_program_state *state )
  * source register.
  */
 static INLINE const GLfloat *
-get_register_pointer( const struct prog_src_register *source,
-                      const struct gl_vertex_program_state *state )
+get_register_pointer( GLcontext *ctx,
+                      const struct prog_src_register *source,
+                      struct vp_machine *machine,
+                      const struct gl_vertex_program *program )
 {
    if (source->RelAddr) {
-      const GLint reg = source->Index + state->Machine.AddressReg[0];
+      const GLint reg = source->Index + machine->AddressReg[0];
       ASSERT( (source->File == PROGRAM_ENV_PARAM) || 
         (source->File == PROGRAM_STATE_VAR) );
       if (reg < 0 || reg > MAX_NV_VERTEX_PROGRAM_PARAMS)
          return ZeroVec;
       else if (source->File == PROGRAM_ENV_PARAM)
-         return state->Parameters[reg];
-      else
-         return state->Current->Base.Parameters->ParameterValues[reg];
+         return ctx->VertexProgram.Parameters[reg];
+      else {
+         ASSERT(source->File == PROGRAM_LOCAL_PARAM);
+         return program->Base.Parameters->ParameterValues[reg];
+      }
    }
    else {
       switch (source->File) {
          case PROGRAM_TEMPORARY:
             ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_TEMPS);
-            return state->Machine.Temporaries[source->Index];
+            return machine->Temporaries[source->Index];
          case PROGRAM_INPUT:
             ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_INPUTS);
-            return state->Machine.Inputs[source->Index];
+            return machine->Inputs[source->Index];
          case PROGRAM_OUTPUT:
             /* This is only needed for the PRINT instruction */
             ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
-            return state->Machine.Outputs[source->Index];
+            return machine->Outputs[source->Index];
          case PROGRAM_LOCAL_PARAM:
             ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
-            return state->Current->Base.LocalParams[source->Index];
+            return program->Base.LocalParams[source->Index];
          case PROGRAM_ENV_PARAM:
             ASSERT(source->Index < MAX_NV_VERTEX_PROGRAM_PARAMS);
-            return state->Parameters[source->Index];
+            return ctx->VertexProgram.Parameters[source->Index];
          case PROGRAM_STATE_VAR:
-            ASSERT(source->Index < state->Current->Base.Parameters->NumParameters);
-            return state->Current->Base.Parameters->ParameterValues[source->Index];
+            ASSERT(source->Index < program->Base.Parameters->NumParameters);
+            return program->Base.Parameters->ParameterValues[source->Index];
          default:
             _mesa_problem(NULL,
                           "Bad source register file in get_register_pointer");
@@ -277,23 +282,23 @@ get_register_pointer( const struct prog_src_register *source,
  * Apply swizzling and negating as needed.
  */
 static INLINE void
-fetch_vector4( const struct prog_src_register *source,
-               const struct gl_vertex_program_state *state,
+fetch_vector4( GLcontext *ctx, 
+               const struct prog_src_register *source,
+               struct vp_machine *machine,
+               const struct gl_vertex_program *program,
                GLfloat result[4] )
 {
-   const GLfloat *src = get_register_pointer(source, state);
-
+   const GLfloat *src = get_register_pointer(ctx, source, machine, program);
+   ASSERT(src);
+   result[0] = src[GET_SWZ(source->Swizzle, 0)];
+   result[1] = src[GET_SWZ(source->Swizzle, 1)];
+   result[2] = src[GET_SWZ(source->Swizzle, 2)];
+   result[3] = src[GET_SWZ(source->Swizzle, 3)];
    if (source->NegateBase) {
-      result[0] = -src[GET_SWZ(source->Swizzle, 0)];
-      result[1] = -src[GET_SWZ(source->Swizzle, 1)];
-      result[2] = -src[GET_SWZ(source->Swizzle, 2)];
-      result[3] = -src[GET_SWZ(source->Swizzle, 3)];
-   }
-   else {
-      result[0] = src[GET_SWZ(source->Swizzle, 0)];
-      result[1] = src[GET_SWZ(source->Swizzle, 1)];
-      result[2] = src[GET_SWZ(source->Swizzle, 2)];
-      result[3] = src[GET_SWZ(source->Swizzle, 3)];
+      result[0] = -result[0];
+      result[1] = -result[1];
+      result[2] = -result[2];
+      result[3] = -result[3];
    }
 }
 
@@ -303,17 +308,17 @@ fetch_vector4( const struct prog_src_register *source,
  * As above, but only return result[0] element.
  */
 static INLINE void
-fetch_vector1( const struct prog_src_register *source,
-               const struct gl_vertex_program_state *state,
+fetch_vector1( GLcontext *ctx,
+               const struct prog_src_register *source,
+               struct vp_machine *machine,
+               const struct gl_vertex_program *program,
                GLfloat result[4] )
 {
-   const GLfloat *src = get_register_pointer(source, state);
-
+   const GLfloat *src = get_register_pointer(ctx, source, machine, program);
+   ASSERT(src);
+   result[0] = src[GET_SWZ(source->Swizzle, 0)];
    if (source->NegateBase) {
-      result[0] = -src[GET_SWZ(source->Swizzle, 0)];
-   }
-   else {
-      result[0] = src[GET_SWZ(source->Swizzle, 0)];
+      result[0] = -result[0];
    }
 }
 
@@ -322,19 +327,21 @@ fetch_vector1( const struct prog_src_register *source,
  * Store 4 floats into a register.
  */
 static void
-store_vector4( const struct prog_dst_register *dest,
-               struct gl_vertex_program_state *state,
+store_vector4( const struct prog_instruction *inst,
+               struct vp_machine *machine,
                const GLfloat value[4] )
 {
+   const struct prog_dst_register *dest = &(inst->DstReg);
    GLfloat *dst;
    switch (dest->File) {
-      case PROGRAM_TEMPORARY:
-         dst = state->Machine.Temporaries[dest->Index];
-         break;
       case PROGRAM_OUTPUT:
-         dst = state->Machine.Outputs[dest->Index];
+         dst = machine->Outputs[dest->Index];
+         break;
+      case PROGRAM_TEMPORARY:
+         dst = machine->Temporaries[dest->Index];
          break;
       case PROGRAM_ENV_PARAM:
+         /* Only for VP state programs */
          {
             /* a slight hack */
             GET_CURRENT_CONTEXT(ctx);
@@ -379,9 +386,10 @@ store_vector4( const struct prog_dst_register *dest,
  * Execute the given vertex program
  */
 void
-_mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *program)
+_mesa_exec_vertex_program(GLcontext *ctx,
+                          struct vp_machine *machine,
+                          const struct gl_vertex_program *program)
 {
-   struct gl_vertex_program_state *state = &ctx->VertexProgram;
    const struct prog_instruction *inst;
 
    ctx->_CurrentProgram = GL_VERTEX_PROGRAM_ARB; /* or NV, doesn't matter */
@@ -390,9 +398,9 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
     * by the MVP matrix and store in the vertex position result register.
     */
    if (ctx->VertexProgram.Current->IsPositionInvariant) {
-      TRANSFORM_POINT( ctx->VertexProgram.Machine.Outputs[VERT_RESULT_HPOS], 
+      TRANSFORM_POINT( machine->Outputs[VERT_RESULT_HPOS], 
                        ctx->_ModelProjectMatrix.m, 
-                       ctx->VertexProgram.Machine.Inputs[VERT_ATTRIB_POS]);
+                       machine->Inputs[VERT_ATTRIB_POS]);
 
       /* XXX: This could go elsewhere */
       ctx->VertexProgram.Current->Base.OutputsWritten |= VERT_BIT_POS;
@@ -411,15 +419,15 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
          case OPCODE_MOV:
             {
                GLfloat t[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               store_vector4( &inst->DstReg, state, t );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_LIT:
             {
                const GLfloat epsilon = 1.0F / 256.0F; /* per NV spec */
                GLfloat t[4], lit[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
                t[0] = MAX2(t[0], 0.0F);
                t[1] = MAX2(t[1], 0.0F);
                t[3] = CLAMP(t[3], -(128.0F - epsilon), (128.0F - epsilon));
@@ -427,32 +435,32 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
                lit[1] = t[0];
                lit[2] = (t[0] > 0.0) ? (GLfloat) _mesa_pow(t[1], t[3]) : 0.0F;
                lit[3] = 1.0;
-               store_vector4( &inst->DstReg, state, lit );
+               store_vector4( inst, machine, lit );
             }
             break;
          case OPCODE_RCP:
             {
                GLfloat t[4];
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                if (t[0] != 1.0F)
                   t[0] = 1.0F / t[0];  /* div by zero is infinity! */
                t[1] = t[2] = t[3] = t[0];
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_RSQ:
             {
                GLfloat t[4];
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                t[0] = INV_SQRTF(FABSF(t[0]));
                t[1] = t[2] = t[3] = t[0];
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_EXP:
             {
                GLfloat t[4], q[4], floor_t0;
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                floor_t0 = FLOORF(t[0]);
                if (floor_t0 > FLT_MAX_EXP) {
                   SET_POS_INFINITY(q[0]);
@@ -475,13 +483,13 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
                }
                q[1] = t[0] - floor_t0;
                q[3] = 1.0F;
-               store_vector4( &inst->DstReg, state, q );
+               store_vector4( inst, machine, q );
             }
             break;
          case OPCODE_LOG:
             {
                GLfloat t[4], q[4], abs_t0;
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                abs_t0 = FABSF(t[0]);
                if (abs_t0 != 0.0F) {
                   /* Since we really can't handle infinite values on VMS
@@ -512,147 +520,147 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
                   SET_NEG_INFINITY(q[2]);
                }
                q[3] = 1.0;
-               store_vector4( &inst->DstReg, state, q );
+               store_vector4( inst, machine, q );
             }
             break;
          case OPCODE_MUL:
             {
                GLfloat t[4], u[4], prod[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                prod[0] = t[0] * u[0];
                prod[1] = t[1] * u[1];
                prod[2] = t[2] * u[2];
                prod[3] = t[3] * u[3];
-               store_vector4( &inst->DstReg, state, prod );
+               store_vector4( inst, machine, prod );
             }
             break;
          case OPCODE_ADD:
             {
                GLfloat t[4], u[4], sum[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                sum[0] = t[0] + u[0];
                sum[1] = t[1] + u[1];
                sum[2] = t[2] + u[2];
                sum[3] = t[3] + u[3];
-               store_vector4( &inst->DstReg, state, sum );
+               store_vector4( inst, machine, sum );
             }
             break;
          case OPCODE_DP3:
             {
                GLfloat t[4], u[4], dot[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2];
                dot[1] = dot[2] = dot[3] = dot[0];
-               store_vector4( &inst->DstReg, state, dot );
+               store_vector4( inst, machine, dot );
             }
             break;
          case OPCODE_DP4:
             {
                GLfloat t[4], u[4], dot[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2] + t[3] * u[3];
                dot[1] = dot[2] = dot[3] = dot[0];
-               store_vector4( &inst->DstReg, state, dot );
+               store_vector4( inst, machine, dot );
             }
             break;
          case OPCODE_DST:
             {
                GLfloat t[4], u[4], dst[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                dst[0] = 1.0F;
                dst[1] = t[1] * u[1];
                dst[2] = t[2];
                dst[3] = u[3];
-               store_vector4( &inst->DstReg, state, dst );
+               store_vector4( inst, machine, dst );
             }
             break;
          case OPCODE_MIN:
             {
                GLfloat t[4], u[4], min[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                min[0] = (t[0] < u[0]) ? t[0] : u[0];
                min[1] = (t[1] < u[1]) ? t[1] : u[1];
                min[2] = (t[2] < u[2]) ? t[2] : u[2];
                min[3] = (t[3] < u[3]) ? t[3] : u[3];
-               store_vector4( &inst->DstReg, state, min );
+               store_vector4( inst, machine, min );
             }
             break;
          case OPCODE_MAX:
             {
                GLfloat t[4], u[4], max[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                max[0] = (t[0] > u[0]) ? t[0] : u[0];
                max[1] = (t[1] > u[1]) ? t[1] : u[1];
                max[2] = (t[2] > u[2]) ? t[2] : u[2];
                max[3] = (t[3] > u[3]) ? t[3] : u[3];
-               store_vector4( &inst->DstReg, state, max );
+               store_vector4( inst, machine, max );
             }
             break;
          case OPCODE_SLT:
             {
                GLfloat t[4], u[4], slt[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                slt[0] = (t[0] < u[0]) ? 1.0F : 0.0F;
                slt[1] = (t[1] < u[1]) ? 1.0F : 0.0F;
                slt[2] = (t[2] < u[2]) ? 1.0F : 0.0F;
                slt[3] = (t[3] < u[3]) ? 1.0F : 0.0F;
-               store_vector4( &inst->DstReg, state, slt );
+               store_vector4( inst, machine, slt );
             }
             break;
          case OPCODE_SGE:
             {
                GLfloat t[4], u[4], sge[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                sge[0] = (t[0] >= u[0]) ? 1.0F : 0.0F;
                sge[1] = (t[1] >= u[1]) ? 1.0F : 0.0F;
                sge[2] = (t[2] >= u[2]) ? 1.0F : 0.0F;
                sge[3] = (t[3] >= u[3]) ? 1.0F : 0.0F;
-               store_vector4( &inst->DstReg, state, sge );
+               store_vector4( inst, machine, sge );
             }
             break;
          case OPCODE_MAD:
             {
                GLfloat t[4], u[4], v[4], sum[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
-               fetch_vector4( &inst->SrcReg[2], state, v );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
+               fetch_vector4( ctx, &inst->SrcReg[2], machine, program, v );
                sum[0] = t[0] * u[0] + v[0];
                sum[1] = t[1] * u[1] + v[1];
                sum[2] = t[2] * u[2] + v[2];
                sum[3] = t[3] * u[3] + v[3];
-               store_vector4( &inst->DstReg, state, sum );
+               store_vector4( inst, machine, sum );
             }
             break;
          case OPCODE_ARL:
             {
                GLfloat t[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               state->Machine.AddressReg[0] = (GLint) FLOORF(t[0]);
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               machine->AddressReg[0] = (GLint) FLOORF(t[0]);
             }
             break;
          case OPCODE_DPH:
             {
                GLfloat t[4], u[4], dot[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                dot[0] = t[0] * u[0] + t[1] * u[1] + t[2] * u[2] + u[3];
                dot[1] = dot[2] = dot[3] = dot[0];
-               store_vector4( &inst->DstReg, state, dot );
+               store_vector4( inst, machine, dot );
             }
             break;
          case OPCODE_RCC:
             {
                GLfloat t[4], u;
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                if (t[0] == 1.0F)
                   u = 1.0F;
                else
@@ -674,115 +682,120 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
                   }
                }
                t[0] = t[1] = t[2] = t[3] = u;
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_SUB: /* GL_NV_vertex_program1_1 */
             {
                GLfloat t[4], u[4], sum[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                sum[0] = t[0] - u[0];
                sum[1] = t[1] - u[1];
                sum[2] = t[2] - u[2];
                sum[3] = t[3] - u[3];
-               store_vector4( &inst->DstReg, state, sum );
+               store_vector4( inst, machine, sum );
             }
             break;
          case OPCODE_ABS: /* GL_NV_vertex_program1_1 */
             {
                GLfloat t[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
                if (t[0] < 0.0)  t[0] = -t[0];
                if (t[1] < 0.0)  t[1] = -t[1];
                if (t[2] < 0.0)  t[2] = -t[2];
                if (t[3] < 0.0)  t[3] = -t[3];
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_FLR: /* GL_ARB_vertex_program */
             {
                GLfloat t[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
                t[0] = FLOORF(t[0]);
                t[1] = FLOORF(t[1]);
                t[2] = FLOORF(t[2]);
                t[3] = FLOORF(t[3]);
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_FRC: /* GL_ARB_vertex_program */
             {
                GLfloat t[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
                t[0] = t[0] - FLOORF(t[0]);
                t[1] = t[1] - FLOORF(t[1]);
                t[2] = t[2] - FLOORF(t[2]);
                t[3] = t[3] - FLOORF(t[3]);
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_EX2: /* GL_ARB_vertex_program */
             {
                GLfloat t[4];
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                t[0] = t[1] = t[2] = t[3] = (GLfloat)_mesa_pow(2.0, t[0]);
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_LG2: /* GL_ARB_vertex_program */
             {
                GLfloat t[4];
-               fetch_vector1( &inst->SrcReg[0], state, t );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
                t[0] = t[1] = t[2] = t[3] = LOG2(t[0]);
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_POW: /* GL_ARB_vertex_program */
             {
                GLfloat t[4], u[4];
-               fetch_vector1( &inst->SrcReg[0], state, t );
-               fetch_vector1( &inst->SrcReg[1], state, u );
+               fetch_vector1( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector1( ctx, &inst->SrcReg[1], machine, program, u );
                t[0] = t[1] = t[2] = t[3] = (GLfloat)_mesa_pow(t[0], u[0]);
-               store_vector4( &inst->DstReg, state, t );
+               store_vector4( inst, machine, t );
             }
             break;
          case OPCODE_XPD: /* GL_ARB_vertex_program */
             {
                GLfloat t[4], u[4], cross[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
-               fetch_vector4( &inst->SrcReg[1], state, u );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
+               fetch_vector4( ctx, &inst->SrcReg[1], machine, program, u );
                cross[0] = t[1] * u[2] - t[2] * u[1];
                cross[1] = t[2] * u[0] - t[0] * u[2];
                cross[2] = t[0] * u[1] - t[1] * u[0];
-               store_vector4( &inst->DstReg, state, cross );
+               store_vector4( inst, machine, cross );
             }
             break;
          case OPCODE_SWZ: /* GL_ARB_vertex_program */
             {
                const struct prog_src_register *source = &inst->SrcReg[0];
-               const GLfloat *src = get_register_pointer(source, state);
+               const GLfloat *src = get_register_pointer(ctx, source,
+                                                         machine, program);
                GLfloat result[4];
                GLuint i;
 
                /* do extended swizzling here */
                for (i = 0; i < 4; i++) {
-                  if (GET_SWZ(source->Swizzle, i) == SWIZZLE_ZERO)
+                  const GLuint swz = GET_SWZ(source->Swizzle, i);
+                  if (swz == SWIZZLE_ZERO)
                      result[i] = 0.0;
-                  else if (GET_SWZ(source->Swizzle, i) == SWIZZLE_ONE)
+                  else if (swz == SWIZZLE_ONE)
                      result[i] = 1.0;
-                  else
-                     result[i] = src[GET_SWZ(source->Swizzle, i)];
+                  else {
+                     ASSERT(swz >= 0);
+                     ASSERT(swz <= 3);
+                     result[i] = src[swz];
+                  }
                   if (source->NegateBase & (1 << i))
                      result[i] = -result[i];
                }
-               store_vector4( &inst->DstReg, state, result );
+               store_vector4( inst, machine, result );
             }
             break;
          case OPCODE_PRINT:
             if (inst->SrcReg[0].File) {
                GLfloat t[4];
-               fetch_vector4( &inst->SrcReg[0], state, t );
+               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, t );
                _mesa_printf("%s%g, %g, %g, %g\n",
                             (char *) inst->Data, t[0], t[1], t[2], t[3]);
             }
@@ -805,48 +818,18 @@ _mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *progra
 }
 
 
-
 /**
-Thoughts on vertex program optimization:
-
-The obvious thing to do is to compile the vertex program into X86/SSE/3DNow!
-assembly code.  That will probably be a lot of work.
-
-Another approach might be to replace the vp_instruction->Opcode field with
-a pointer to a specialized C function which executes the instruction.
-In particular we can write functions which skip swizzling, negating,
-masking, relative addressing, etc. when they're not needed.
-
-For example:
-
-void simple_add( struct prog_instruction *inst )
+ * Execute a vertex state program.
+ * \sa _mesa_ExecuteProgramNV
+ */
+void
+_mesa_exec_vertex_state_program(GLcontext *ctx,
+                                struct gl_vertex_program *vprog,
+                                const GLfloat *params)
 {
-   GLfloat *sum = machine->Registers[inst->DstReg.Register];
-   GLfloat *a = machine->Registers[inst->SrcReg[0].Register];
-   GLfloat *b = machine->Registers[inst->SrcReg[1].Register];
-   sum[0] = a[0] + b[0];
-   sum[1] = a[1] + b[1];
-   sum[2] = a[2] + b[2];
-   sum[3] = a[3] + b[3];
+   struct vp_machine machine;
+   _mesa_init_vp_per_vertex_registers(ctx, &machine);
+   _mesa_init_vp_per_primitive_registers(ctx);
+   COPY_4V(machine.Inputs[VERT_ATTRIB_POS], params);
+   _mesa_exec_vertex_program(ctx, &machine, vprog);
 }
-
-*/
-
-/*
-
-KW:
-
-A first step would be to 'vectorize' the programs in the same way as
-the normal transformation code in the tnl module.  Thus each opcode
-takes zero or more input vectors (registers) and produces one or more
-output vectors.
-
-These operations would intially be coded in C, with machine-specific
-assembly following, as is currently the case for matrix
-transformations in the math/ directory.  The preprocessing scheme for
-selecting simpler operations Brian describes above would also work
-here.
-
-This should give reasonable performance without excessive effort.
-
-*/
index e0fd46a76620298fab6457f6484e054d9896c165..b1cf31bd3c4430800e10cfb0771ccbd1b76a7cf6 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 #ifndef NVVERTEXEC_H
 #define NVVERTEXEC_H
 
+
+/**
+ * Virtual vertex program machine state.
+ * Only used during program execution.
+ */
+struct vp_machine
+{
+   GLfloat Temporaries[MAX_NV_VERTEX_PROGRAM_TEMPS][4];
+   GLfloat Inputs[MAX_NV_VERTEX_PROGRAM_INPUTS][4];
+   GLuint InputsSize[MAX_NV_VERTEX_PROGRAM_INPUTS];
+   GLfloat Outputs[MAX_NV_VERTEX_PROGRAM_OUTPUTS][4];
+   GLint AddressReg[4];
+};
+
+
+
 extern void
-_mesa_init_vp_per_vertex_registers(GLcontext *ctx);
+_mesa_init_vp_per_vertex_registers(GLcontext *ctx, struct vp_machine *machine);
 
 extern void
 _mesa_init_vp_per_primitive_registers(GLcontext *ctx);
 
 extern void
-_mesa_exec_vertex_program(GLcontext *ctx, const struct gl_vertex_program *program);
+_mesa_exec_vertex_program(GLcontext *ctx,
+                          struct vp_machine *machine,
+                          const struct gl_vertex_program *program);
+
+extern void
+_mesa_exec_vertex_state_program(GLcontext *ctx,
+                                struct gl_vertex_program *vprog,
+                                const GLfloat *params);
 
 extern void
-_mesa_dump_vp_state( const struct gl_vertex_program_state *state );
+_mesa_dump_vp_state( const struct gl_vertex_program_state *state,
+                     const struct vp_machine *machine);
 
 #endif
index f3821d7f43a953666ec8bbde9aab3718baef49a5..ecfe8ec334fbaaa25487cc5df3f2b1840966ff51 100644 (file)
@@ -1143,7 +1143,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
       struct prog_instruction *inst = program + parseState->numInst;
 
       /* Initialize the instruction */
-      _mesa_init_instruction(inst);
+      _mesa_init_instructions(inst, 1);
 
       if (Parse_String(parseState, "MOV")) {
          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV))
index 8ac38ae119979f6394aca9ad16881547bac4e6ec..681584941e79b39d7a5791999b261d2c97dba58a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.1
+ * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
@@ -45,7 +45,7 @@
 static const char *
 make_state_string(const GLint stateTokens[6]);
 
-static GLuint 
+static GLbitfield
 make_state_flags(const GLint state[]);
 
 
@@ -485,8 +485,7 @@ _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
          paramList->Parameters[index].StateIndexes[i]
             = (enum state_index) stateTokens[i];
       }
-      paramList->StateFlags |= 
-           make_state_flags(stateTokens);
+      paramList->StateFlags |= make_state_flags(stateTokens);
    }
 
    /* free name string here since we duplicated it in add_parameter() */
@@ -580,37 +579,29 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
       {
          /* state[1] is either 0=front or 1=back side */
          const GLuint face = (GLuint) state[1];
+         const struct gl_material *mat = &ctx->Light.Material;
+         ASSERT(face == 0 || face == 1);
+         /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
+         ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
+         /* XXX we could get rid of this switch entirely with a little
+          * work in arbprogparse.c's parse_state_single_item().
+          */
          /* state[2] is the material attribute */
          switch (state[2]) {
          case STATE_AMBIENT:
-            if (face == 0)
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
-            else
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT]);
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
             return;
          case STATE_DIFFUSE:
-            if (face == 0)
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE]);
-            else
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE]);
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
             return;
          case STATE_SPECULAR:
-            if (face == 0)
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR]);
-            else
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SPECULAR]);
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
             return;
          case STATE_EMISSION:
-            if (face == 0)
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
-            else
-               COPY_4V(value, ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION]);
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
             return;
          case STATE_SHININESS:
-            if (face == 0)
-               value[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
-            else
-               value[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0];
+            value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
             value[1] = 0.0F;
             value[2] = 0.0F;
             value[3] = 1.0F;
@@ -941,10 +932,14 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[],
 
 
 /**
- * Return a bit mask of the Mesa state flags under which a parameter's
- * value might change.
+ * Return a bitmask of the Mesa state flags (_NEW_* values) which would
+ * indicate that the given context state may have changed.
+ * The bitmask is used during validation to determine if we need to update
+ * vertex/fragment program parameters (like "state.material.color") when
+ * some GL state has changed.
  */
-static GLuint make_state_flags(const GLint state[])
+static GLbitfield
+make_state_flags(const GLint state[])
 {
    switch (state[0]) {
    case STATE_MATERIAL:
@@ -1307,26 +1302,32 @@ _mesa_load_state_parameters(GLcontext *ctx,
 
 /**
  * Initialize program instruction fields to defaults.
+ * \param inst  first instruction to initialize
+ * \param count  number of instructions to initialize
  */
 void
-_mesa_init_instruction(struct prog_instruction *inst)
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count)
 {
-   _mesa_bzero(inst, sizeof(struct prog_instruction));
-
-   inst->SrcReg[0].File = PROGRAM_UNDEFINED;
-   inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
-   inst->SrcReg[1].File = PROGRAM_UNDEFINED;
-   inst->SrcReg[1].Swizzle = SWIZZLE_NOOP;
-   inst->SrcReg[2].File = PROGRAM_UNDEFINED;
-   inst->SrcReg[2].Swizzle = SWIZZLE_NOOP;
-
-   inst->DstReg.File = PROGRAM_UNDEFINED;
-   inst->DstReg.WriteMask = WRITEMASK_XYZW;
-   inst->DstReg.CondMask = COND_TR;
-   inst->DstReg.CondSwizzle = SWIZZLE_NOOP;
-
-   inst->SaturateMode = SATURATE_OFF;
-   inst->Precision = FLOAT32;
+   GLuint i;
+
+   _mesa_bzero(inst, count * sizeof(struct prog_instruction));
+
+   for (i = 0; i < count; i++) {
+      inst[i].SrcReg[0].File = PROGRAM_UNDEFINED;
+      inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP;
+      inst[i].SrcReg[1].File = PROGRAM_UNDEFINED;
+      inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP;
+      inst[i].SrcReg[2].File = PROGRAM_UNDEFINED;
+      inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP;
+
+      inst[i].DstReg.File = PROGRAM_UNDEFINED;
+      inst[i].DstReg.WriteMask = WRITEMASK_XYZW;
+      inst[i].DstReg.CondMask = COND_TR;
+      inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP;
+
+      inst[i].SaturateMode = SATURATE_OFF;
+      inst[i].Precision = FLOAT32;
+   }
 }
 
 
@@ -2102,7 +2103,9 @@ _mesa_GetProgramRegisterfvMESA(GLenum target,
                            "glGetProgramRegisterfvMESA(registerName)");
                return;
             }
-            COPY_4V(v, ctx->VertexProgram.Machine.Temporaries[i]);
+#if 0 /* FIX ME */
+            ctx->Driver.GetVertexProgramRegister(ctx, PROGRAM_TEMPORARY, i, v);
+#endif
          }
          else if (reg[0] == 'v' && reg[1] == '[') {
             /* Vertex Input attribute */
@@ -2113,7 +2116,10 @@ _mesa_GetProgramRegisterfvMESA(GLenum target,
                _mesa_sprintf(number, "%d", i);
                if (_mesa_strncmp(reg + 2, name, 4) == 0 ||
                    _mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) {
-                  COPY_4V(v, ctx->VertexProgram.Machine.Inputs[i]);
+#if 0 /* FIX ME */
+                  ctx->Driver.GetVertexProgramRegister(ctx, PROGRAM_INPUT,
+                                                       i, v);
+#endif
                   return;
                }
             }
index 93bcfc240a9e8a163f1f63588f3c15bdd2b45555..cdec0ceb2a520a795c7069abb483413b776b9a50 100644 (file)
@@ -343,7 +343,7 @@ struct prog_instruction
 
 
 extern void
-_mesa_init_instruction(struct prog_instruction *inst);
+_mesa_init_instructions(struct prog_instruction *inst, GLuint count);
 
 extern GLuint
 _mesa_num_inst_src_regs(enum prog_opcode opcode);
index 55991dcce34e5a416164e92d3e791583e726c9d8..172d373b578ae959a1015913f7ec6bb61a60cb94 100644 (file)
@@ -85,8 +85,8 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
     * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position;
     * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position;
     */
+   _mesa_init_instructions(newInst, 4);
    for (i = 0; i < 4; i++) {
-      _mesa_init_instruction(newInst + i);
       newInst[i].Opcode = OPCODE_DP4;
       newInst[i].DstReg.File = PROGRAM_OUTPUT;
       newInst[i].DstReg.Index = VERT_RESULT_HPOS;
@@ -137,7 +137,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
    GLfloat fogVals[4];
    GLuint fogConsts;                /* constant values for EXP, EXP2 mode */
 
-   if (fprog->FogOption != GL_NONE) {
+   if (fprog->FogOption == GL_NONE) {
       _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program"
                     " with FogOption == GL_NONE");
       return;
@@ -191,8 +191,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
    }
    assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */
 
-   for (i = 0; i < 6; i++)
-      _mesa_init_instruction(inst + i);
+   _mesa_init_instructions(inst, 6);
 
    /* emit instructions to compute fog blending factor */
    if (fprog->FogOption == GL_LINEAR) {
index 9e41d7c673d2b6f2b6f250a533ae0e5de1263924..ee971a36eccebf61482b4a9eeb7802413a83ce10 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.6
  *
  * Copyright (C) 2006  Brian Paul   All Rights Reserved.
  *
@@ -106,6 +106,15 @@ _swrast_exec_arbshader(GLcontext *ctx, SWspan *span)
             (**pro).UpdateFixedVarying(pro, SLANG_FRAGMENT_FIXED_FRAGCOLOR,
                                        vec, 0, 4 * sizeof(GLfloat), GL_FALSE);
             COPY_4V(span->array->color.sz4.rgba[i], vec);
+            
+            (**pro).UpdateFixedVarying(pro, SLANG_FRAGMENT_FIXED_FRAGDEPTH, vec, 0,
+                                       sizeof (GLfloat), GL_FALSE);
+            if (vec[0] <= 0.0f)
+               span->array->z[i] = 0;
+            else if (vec[0] >= 1.0f)
+               span->array->z[i] = ctx->DrawBuffer->_DepthMax;
+            else
+               span->array->z[i] = IROUND(vec[0] * ctx->DrawBuffer->_DepthMaxF);
          }
       }
    }
index bb85ee577754c107d0ee7802372a5c9c8b711080..284ea2b517874e33e999bee3264d7b57d893c735 100644 (file)
@@ -293,18 +293,15 @@ clear_color_buffers(GLcontext *ctx)
 /**
  * Called via the device driver's ctx->Driver.Clear() function if the
  * device driver can't clear one or more of the buffers itself.
- * \param mask  bitfield of BUFER_BIT_* values indicating which renderbuffers
- *              are to be cleared.
+ * \param buffers  bitfield of BUFFER_BIT_* values indicating which
+ *                 renderbuffers are to be cleared.
  * \param all  if GL_TRUE, clear whole buffer, else clear specified region.
  */
 void
-_swrast_Clear(GLcontext *ctx, GLbitfield mask,
-             GLboolean all, GLint x, GLint y, GLint width, GLint height)
+_swrast_Clear(GLcontext *ctx, GLbitfield buffers)
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
-   (void) all; (void) x; (void) y; (void) width; (void) height;
-
 #ifdef DEBUG_FOO
    {
       const GLbitfield legalBits =
@@ -319,25 +316,25 @@ _swrast_Clear(GLcontext *ctx, GLbitfield mask,
          BUFFER_BIT_AUX1 |
          BUFFER_BIT_AUX2 |
          BUFFER_BIT_AUX3;
-      assert((mask & (~legalBits)) == 0);
+      assert((buffers & (~legalBits)) == 0);
    }
 #endif
 
    RENDER_START(swrast,ctx);
 
    /* do software clearing here */
-   if (mask) {
-      if (mask & ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
+   if (buffers) {
+      if (buffers & ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
          clear_color_buffers(ctx);
       }
-      if (mask & BUFFER_BIT_DEPTH) {
+      if (buffers & BUFFER_BIT_DEPTH) {
          _swrast_clear_depth_buffer(ctx, ctx->DrawBuffer->_DepthBuffer);
       }
-      if (mask & BUFFER_BIT_ACCUM) {
+      if (buffers & BUFFER_BIT_ACCUM) {
          _swrast_clear_accum_buffer(ctx,
                        ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
       }
-      if (mask & BUFFER_BIT_STENCIL) {
+      if (buffers & BUFFER_BIT_STENCIL) {
          _swrast_clear_stencil_buffer(ctx, ctx->DrawBuffer->_StencilBuffer);
       }
    }
index 18f5fe497bb539359354ed19e5c504ab48f7606e..62cf6f2f5aed8116cc5c0ac1dd41663e9e3ff548 100644 (file)
@@ -223,11 +223,12 @@ _swrast_update_fog_state( GLcontext *ctx )
  * program parameters with current state values.
  */
 static void
-_swrast_update_fragment_program( GLcontext *ctx )
+_swrast_update_fragment_program(GLcontext *ctx, GLbitfield newState)
 {
    if (ctx->FragmentProgram._Enabled) {
       const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
-      _mesa_load_state_parameters(ctx, fp->Base.Parameters);
+      if (fp->Base.Parameters->StateFlags & newState)
+         _mesa_load_state_parameters(ctx, fp->Base.Parameters);
    }
 }
 
@@ -521,8 +522,18 @@ _swrast_validate_derived( GLcontext *ctx )
       if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM))
          _swrast_update_fog_state( ctx );
 
-      if (swrast->NewState & _NEW_PROGRAM)
-        _swrast_update_fragment_program( ctx );
+      if (swrast->NewState & (_NEW_MODELVIEW |
+                              _NEW_PROJECTION |
+                              _NEW_TEXTURE_MATRIX |
+                              _NEW_FOG |
+                              _NEW_LIGHT |
+                              _NEW_LINE |
+                              _NEW_TEXTURE |
+                              _NEW_TRANSFORM |
+                              _NEW_POINT |
+                              _NEW_VIEWPORT |
+                              _NEW_PROGRAM))
+        _swrast_update_fragment_program( ctx, swrast->NewState );
 
       if (swrast->NewState & _NEW_TEXTURE)
          _swrast_update_texture_samplers( ctx );
index dfca960005cdd844e81061734c1fd93f9681a2c6..7a6785b1d29b860a6a3111ccc7811b33fa8ff744 100644 (file)
 #include "s_span.h"
 
 
-/* if 1, print some debugging info */
+/* See comments below for info about this */
+#define LAMBDA_ZERO 1
+
+/* debug predicate */
 #define DEBUG_FRAG 0
 
 
@@ -178,8 +181,8 @@ get_register_pointer( GLcontext *ctx,
       ASSERT(source->Index < (GLint) program->Base.Parameters->NumParameters);
       return program->Base.Parameters->ParameterValues[source->Index];
    default:
-      _mesa_problem(ctx, "Invalid input register file %d in fetch_vector4",
-                    source->File);
+      _mesa_problem(ctx, "Invalid input register file %d in fp "
+                    "get_register_pointer", source->File);
       return NULL;
    }
 }
@@ -458,7 +461,7 @@ store_vector4( const struct prog_instruction *inst,
          return;
    }
 
-#if DEBUG_FRAG
+#if 0
    if (value[0] > 1.0e10 ||
        IS_INF_OR_NAN(value[0]) ||
        IS_INF_OR_NAN(value[1]) ||
@@ -646,9 +649,9 @@ execute_program( GLcontext *ctx,
 {
    GLuint pc;
 
-#if DEBUG_FRAG
-   printf("execute fragment program --------------------\n");
-#endif
+   if (DEBUG_FRAG) {
+      printf("execute fragment program --------------------\n");
+   }
 
    for (pc = 0; pc < maxInst; pc++) {
       const struct prog_instruction *inst = program->Base.Instructions + pc;
@@ -660,6 +663,10 @@ execute_program( GLcontext *ctx,
                                        ctx->FragmentProgram.CallbackData);
       }
 
+      if (DEBUG_FRAG) {
+         _mesa_print_instruction(inst);
+      }
+
       switch (inst->Opcode) {
          case OPCODE_ABS:
             {
@@ -682,6 +689,12 @@ execute_program( GLcontext *ctx,
                result[2] = a[2] + b[2];
                result[3] = a[3] + b[3];
                store_vector4( inst, machine, result );
+               if (DEBUG_FRAG) {
+                  printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3], 
+                         a[0], a[1], a[2], a[3],
+                         b[0], b[1], b[2], b[3]);
+               }
             }
             break;
          case OPCODE_CMP:
@@ -758,10 +771,10 @@ execute_program( GLcontext *ctx,
                fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
                result[0] = result[1] = result[2] = result[3] = DOT3(a, b);
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("DP3 %g = (%g %g %g) . (%g %g %g)\n",
-                      result[0], a[0], a[1], a[2], b[0], b[1], b[2]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("DP3 %g = (%g %g %g) . (%g %g %g)\n",
+                         result[0], a[0], a[1], a[2], b[0], b[1], b[2]);
+               }
             }
             break;
          case OPCODE_DP4:
@@ -771,10 +784,11 @@ execute_program( GLcontext *ctx,
                fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
                result[0] = result[1] = result[2] = result[3] = DOT4(a,b);
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
-                      result[0], a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n",
+                         result[0], a[0], a[1], a[2], a[3],
+                         b[0], b[1], b[2], b[3]);
+               }
             }
             break;
          case OPCODE_DPH:
@@ -882,6 +896,11 @@ execute_program( GLcontext *ctx,
                }
                result[3] = 1.0F;
                store_vector4( inst, machine, result );
+               if (DEBUG_FRAG) {
+                  printf("LIT (%g %g %g %g) : (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3],
+                         a[0], a[1], a[2], a[3]);
+               }
             }
             break;
          case OPCODE_LRP:
@@ -895,14 +914,14 @@ execute_program( GLcontext *ctx,
                result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2];
                result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3];
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("LRP (%g %g %g %g) = (%g %g %g %g), "
-                      "(%g %g %g %g), (%g %g %g %g)\n",
-                      result[0], result[1], result[2], result[3],
-                      a[0], a[1], a[2], a[3],
-                      b[0], b[1], b[2], b[3],
-                      c[0], c[1], c[2], c[3]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("LRP (%g %g %g %g) = (%g %g %g %g), "
+                         "(%g %g %g %g), (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3],
+                         a[0], a[1], a[2], a[3],
+                         b[0], b[1], b[2], b[3],
+                         c[0], c[1], c[2], c[3]);
+               }
             }
             break;
          case OPCODE_MAD:
@@ -916,6 +935,14 @@ execute_program( GLcontext *ctx,
                result[2] = a[2] * b[2] + c[2];
                result[3] = a[3] * b[3] + c[3];
                store_vector4( inst, machine, result );
+               if (DEBUG_FRAG) {
+                  printf("MAD (%g %g %g %g) = (%g %g %g %g) * "
+                         "(%g %g %g %g) + (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3],
+                         a[0], a[1], a[2], a[3],
+                         b[0], b[1], b[2], b[3],
+                         c[0], c[1], c[2], c[3]);
+               }
             }
             break;
          case OPCODE_MAX:
@@ -928,12 +955,12 @@ execute_program( GLcontext *ctx,
                result[2] = MAX2(a[2], b[2]);
                result[3] = MAX2(a[3], b[3]);
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
-                      result[0], result[1], result[2], result[3], 
-                      a[0], a[1], a[2], a[3],
-                      b[0], b[1], b[2], b[3]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3], 
+                         a[0], a[1], a[2], a[3],
+                         b[0], b[1], b[2], b[3]);
+               }
             }
             break;
          case OPCODE_MIN:
@@ -953,10 +980,10 @@ execute_program( GLcontext *ctx,
                GLfloat result[4];
                fetch_vector4( ctx, &inst->SrcReg[0], machine, program, result );
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("MOV (%g %g %g %g)\n",
-                      result[0], result[1], result[2], result[3]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("MOV (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3]);
+               }
             }
             break;
          case OPCODE_MUL:
@@ -969,12 +996,12 @@ execute_program( GLcontext *ctx,
                result[2] = a[2] * b[2];
                result[3] = a[3] * b[3];
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n",
-                      result[0], result[1], result[2], result[3], 
-                      a[0], a[1], a[2], a[3],
-                      b[0], b[1], b[2], b[3]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3], 
+                         a[0], a[1], a[2], a[3],
+                         b[0], b[1], b[2], b[3]);
+               }
             }
             break;
          case OPCODE_PK2H: /* pack two 16-bit floats in one 32-bit float */
@@ -1056,12 +1083,12 @@ execute_program( GLcontext *ctx,
             {
                GLfloat a[4], result[4];
                fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
-#if DEBUG_FRAG
-               if (a[0] == 0)
-                  printf("RCP(0)\n");
-               else if (IS_INF_OR_NAN(a[0]))
-                  printf("RCP(inf)\n");
-#endif
+               if (DEBUG_FRAG) {
+                  if (a[0] == 0)
+                     printf("RCP(0)\n");
+                  else if (IS_INF_OR_NAN(a[0]))
+                     printf("RCP(inf)\n");
+               }
                result[0] = result[1] = result[2] = result[3] = 1.0F / a[0];
                store_vector4( inst, machine, result );
             }
@@ -1087,9 +1114,9 @@ execute_program( GLcontext *ctx,
                a[0] = FABSF(a[0]);
                result[0] = result[1] = result[2] = result[3] = INV_SQRTF(a[0]);
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]);
+               }
             }
             break;
          case OPCODE_SCS: /* sine and cos */
@@ -1206,11 +1233,11 @@ execute_program( GLcontext *ctx,
                result[2] = a[2] - b[2];
                result[3] = a[3] - b[3];
                store_vector4( inst, machine, result );
-#if DEBUG_FRAG
-               printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n",
-                      result[0], result[1], result[2], result[3],
-                      a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
-#endif
+               if (DEBUG_FRAG) {
+                  printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n",
+                         result[0], result[1], result[2], result[3],
+                         a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]);
+               }
             }
             break;
          case OPCODE_SWZ: /* extended swizzle */
@@ -1240,44 +1267,47 @@ execute_program( GLcontext *ctx,
          case OPCODE_TEX: /* Both ARB and NV frag prog */
             /* Texel lookup */
             {
-               GLfloat texcoord[4], color[4];
-               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
-               /* Note: we pass 0 for LOD.  The ARB extension requires it
-                * while the NV extension says it's implementation dependant.
+               /* Note: only use the precomputed lambda value when we're
+                * sampling texture unit [K] with texcoord[K].
+                * Otherwise, the lambda value may have no relation to the
+                * instruction's texcoord or texture image.  Using the wrong
+                * lambda is usually bad news.
+                * The rest of the time, just use zero (until we get a more
+                * sophisticated way of computing lambda).
                 */
-               /* KW: Previously lambda was passed as zero, but I
-               * believe this is incorrect, the spec seems to
-               * indicate rather that lambda should not be
-               * changed/biased, unlike TXB where texcoord[3] is
-               * added to the lambda calculations.  The lambda should
-               * still be calculated normally for TEX & TXP though,
-               * not set to zero.  Otherwise it's very difficult to
-               * implement normal GL semantics through the fragment
-               * shader.
-               */
-               fetch_texel( ctx, texcoord, 
-                           span->array->lambda[inst->TexSrcUnit][column],
-                           inst->TexSrcUnit, color );
-#if DEBUG_FRAG
-               if (color[3])
-                  printf("color[3] = %f\n", color[3]);
-#endif
+               GLfloat coord[4], color[4], lambda;
+               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
+                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
+                  lambda = span->array->lambda[inst->TexSrcUnit][column];
+               else
+                  lambda = 0.0;
+               fetch_vector4(ctx, &inst->SrcReg[0], machine, program, coord);
+               fetch_texel( ctx, coord, lambda, inst->TexSrcUnit, color );
+               if (DEBUG_FRAG) {
+                  printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g], "
+                         "lod %f\n",
+                         color[0], color[1], color[2], color[3],
+                         inst->TexSrcUnit,
+                         coord[0], coord[1], coord[2], coord[3], lambda);
+               }
                store_vector4( inst, machine, color );
             }
             break;
          case OPCODE_TXB: /* GL_ARB_fragment_program only */
             /* Texel lookup with LOD bias */
             {
-               GLfloat texcoord[4], color[4], bias, lambda;
-
-               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
-               /* texcoord[3] is the bias to add to lambda */
+               GLfloat coord[4], color[4], lambda, bias;
+               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
+                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
+                  lambda = span->array->lambda[inst->TexSrcUnit][column];
+               else
+                  lambda = 0.0;
+               fetch_vector4(ctx, &inst->SrcReg[0], machine, program, coord);
+               /* coord[3] is the bias to add to lambda */
                bias = ctx->Texture.Unit[inst->TexSrcUnit].LodBias
                     + ctx->Texture.Unit[inst->TexSrcUnit]._Current->LodBias
-                    + texcoord[3];
-               lambda = span->array->lambda[inst->TexSrcUnit][column] + bias;
-               fetch_texel( ctx, texcoord, lambda,
-                            inst->TexSrcUnit, color );
+                    + coord[3];
+               fetch_texel(ctx, coord, lambda + bias, inst->TexSrcUnit, color);
                store_vector4( inst, machine, color );
             }
             break;
@@ -1296,8 +1326,13 @@ execute_program( GLcontext *ctx,
          case OPCODE_TXP: /* GL_ARB_fragment_program only */
             /* Texture lookup w/ projective divide */
             {
-               GLfloat texcoord[4], color[4];
-               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
+               GLfloat texcoord[4], color[4], lambda;
+               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
+                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
+                  lambda = span->array->lambda[inst->TexSrcUnit][column];
+               else
+                  lambda = 0.0;
+               fetch_vector4(ctx, &inst->SrcReg[0], machine, program,texcoord);
               /* Not so sure about this test - if texcoord[3] is
                * zero, we'd probably be fine except for an ASSERT in
                * IROUND_POS() which gets triggered by the inf values created.
@@ -1307,34 +1342,27 @@ execute_program( GLcontext *ctx,
                  texcoord[1] /= texcoord[3];
                  texcoord[2] /= texcoord[3];
               }
-               /* KW: Previously lambda was passed as zero, but I
-               * believe this is incorrect, the spec seems to
-               * indicate rather that lambda should not be
-               * changed/biased, unlike TXB where texcoord[3] is
-               * added to the lambda calculations.  The lambda should
-               * still be calculated normally for TEX & TXP though,
-               * not set to zero.
-               */
-               fetch_texel( ctx, texcoord, 
-                           span->array->lambda[inst->TexSrcUnit][column],
-                           inst->TexSrcUnit, color );
+               fetch_texel( ctx, texcoord, lambda, inst->TexSrcUnit, color );
                store_vector4( inst, machine, color );
             }
             break;
          case OPCODE_TXP_NV: /* GL_NV_fragment_program only */
             /* Texture lookup w/ projective divide */
             {
-               GLfloat texcoord[4], color[4];
-               fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
+               GLfloat texcoord[4], color[4], lambda;
+               if (inst->SrcReg[0].File == PROGRAM_INPUT &&
+                   inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0+inst->TexSrcUnit)
+                  lambda = span->array->lambda[inst->TexSrcUnit][column];
+               else
+                  lambda = 0.0;
+               fetch_vector4(ctx, &inst->SrcReg[0], machine, program,texcoord);
                if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX &&
                   texcoord[3] != 0.0) {
                   texcoord[0] /= texcoord[3];
                   texcoord[1] /= texcoord[3];
                   texcoord[2] /= texcoord[3];
                }
-               fetch_texel( ctx, texcoord,
-                            span->array->lambda[inst->TexSrcUnit][column],
-                            inst->TexSrcUnit, color );
+               fetch_texel( ctx, texcoord, lambda, inst->TexSrcUnit, color );
                store_vector4( inst, machine, color );
             }
             break;
@@ -1572,10 +1600,6 @@ _swrast_exec_fragment_program( GLcontext *ctx, SWspan *span )
 
    ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */
 
-   if (program->Base.Parameters) {
-      _mesa_load_state_parameters(ctx, program->Base.Parameters);
-   }   
-
    run_program(ctx, span, 0, span->end);
 
    if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) {
index 2e20f7a2965a846a2fc94f7b7a3805e055b3d9fb..c74b98facfb27446dc7eeb7dfec1cbbcce46f6d9 100644 (file)
@@ -353,32 +353,38 @@ interpolate_specular(SWspan *span)
    case GL_FLOAT:
       {
          GLfloat (*spec)[4] = span->array->color.sz4.spec;
+#if CHAN_BITS <= 16
+         GLfloat r = CHAN_TO_FLOAT(FixedToChan(span->specRed));
+         GLfloat g = CHAN_TO_FLOAT(FixedToChan(span->specGreen));
+         GLfloat b = CHAN_TO_FLOAT(FixedToChan(span->specBlue));
+#else
+         GLfloat r = span->specRed;
+         GLfloat g = span->specGreen;
+         GLfloat b = span->specBlue;
+#endif
+         GLfloat dr, dg, db;
          if (span->interpMask & SPAN_FLAT) {
-            GLfloat color[4];
-            color[RCOMP] = span->specRed;
-            color[GCOMP] = span->specGreen;
-            color[BCOMP] = span->specBlue;
-            color[ACOMP] = 0.0F;
-            for (i = 0; i < n; i++) {
-               COPY_4V(spec[i], color);
-            }
+            dr = dg = db = 0.0;
          }
          else {
-            GLfloat r = span->specRed;
-            GLfloat g = span->specGreen;
-            GLfloat b = span->specBlue;
-            GLfloat dr = span->specRedStep;
-            GLfloat dg = span->specGreenStep;
-            GLfloat db = span->specBlueStep;
-            for (i = 0; i < n; i++) {
-               spec[i][RCOMP] = r;
-               spec[i][GCOMP] = g;
-               spec[i][BCOMP] = b;
-               spec[i][ACOMP] = 0.0F;
-               r += dr;
-               g += dg;
-               b += db;
-            }
+#if CHAN_BITS <= 16
+            dr = CHAN_TO_FLOAT(FixedToChan(span->specRedStep));
+            dg = CHAN_TO_FLOAT(FixedToChan(span->specGreenStep));
+            db = CHAN_TO_FLOAT(FixedToChan(span->specBlueStep));
+#else
+            dr = span->specRedStep;
+            dg = span->specGreenStep;
+            db = span->specBlueStep;
+#endif
+         }
+         for (i = 0; i < n; i++) {
+            spec[i][RCOMP] = r;
+            spec[i][GCOMP] = g;
+            spec[i][BCOMP] = b;
+            spec[i][ACOMP] = 0.0F;
+            r += dr;
+            g += dg;
+            b += db;
          }
       }
       break;
index ddaf7471f597da3073f175deab19c4feb203cb29..3f49b40d9c17536c9a63698b4a9ab3b3020aa21d 100644 (file)
@@ -254,7 +254,7 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
    ASSERT(texObj);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    ASSERT(texImage);
 
    ASSERT(ctx->Driver.TexImage1D);
@@ -331,7 +331,7 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
    ASSERT(texObj);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    ASSERT(texImage);
 
    ASSERT(ctx->Driver.TexImage2D);
@@ -400,7 +400,7 @@ _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
    ASSERT(texObj);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    ASSERT(texImage);
 
    ASSERT(ctx->Driver.TexImage1D);
@@ -474,7 +474,7 @@ _swrast_copy_texsubimage2d( GLcontext *ctx,
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
    ASSERT(texObj);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    ASSERT(texImage);
 
    ASSERT(ctx->Driver.TexImage2D);
@@ -547,7 +547,7 @@ _swrast_copy_texsubimage3d( GLcontext *ctx,
    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
    ASSERT(texObj);
-   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+   texImage = _mesa_select_tex_image(ctx, texObj, target, level);
    ASSERT(texImage);
 
    ASSERT(ctx->Driver.TexImage3D);
index 04bd01a0cdc6868d707f7dce19856063c92d58c9..09686c8380aaf04356f5eb9c38f46e2fb52ffefd 100644 (file)
@@ -130,8 +130,7 @@ _swrast_BlitFramebuffer(GLcontext *ctx,
                         GLbitfield mask, GLenum filter);
 
 extern void
-_swrast_Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
-              GLint x, GLint y, GLint width, GLint height );
+_swrast_Clear(GLcontext *ctx, GLbitfield buffers);
 
 extern void
 _swrast_Accum(GLcontext *ctx, GLenum op, GLfloat value);
index 5d6b6dd97da2dd68f1d7bccf4c737ff18506b961..bd459a77479491e6d728e657f94162c638a95fbb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.2
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
@@ -135,7 +135,8 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
 
    if (ctx->Fog.Enabled ||
        (ctx->FragmentProgram._Active &&
-       ctx->FragmentProgram._Current->FogOption != GL_NONE))
+        (ctx->FragmentProgram._Current->FogOption != GL_NONE ||
+         ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_FOGC)))
       RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
 
    if (ctx->Polygon.FrontMode != GL_FILL || 
index b8828ec36ac3236886e016e674c717c9d573d4a2..f11ac616f16f7cb9005201d1b903b4d802c4f79b 100644 (file)
@@ -76,6 +76,7 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
    struct vp_stage_data *store = VP_STAGE_DATA(stage);
    struct vertex_buffer *VB = &tnl->vb;
    struct gl_vertex_program *program = ctx->VertexProgram.Current;
+   struct vp_machine machine;
    GLuint i;
 
    if (ctx->ShaderObjects._VertexShaderPresent)
@@ -91,7 +92,7 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
    for (i = 0; i < VB->Count; i++) {
       GLuint attr;
 
-      _mesa_init_vp_per_vertex_registers(ctx);
+      _mesa_init_vp_per_vertex_registers(ctx, &machine);
 
 #if 0
       printf("Input  %d: %f, %f, %f, %f\n", i,
@@ -118,30 +119,29 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage )
            const GLuint size = VB->AttribPtr[attr]->size;
            const GLuint stride = VB->AttribPtr[attr]->stride;
            const GLfloat *data = (GLfloat *) (ptr + stride * i);
-           COPY_CLEAN_4V(ctx->VertexProgram.Machine.Inputs[attr], size, data);
+           COPY_CLEAN_4V(machine.Inputs[attr], size, data);
         }
       }
 
       /* execute the program */
       ASSERT(program);
-      _mesa_exec_vertex_program(ctx, program);
+      _mesa_exec_vertex_program(ctx, &machine, program);
 
       /* Fixup fog an point size results if needed */
       if (ctx->Fog.Enabled &&
           (program->Base.OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) {
-         ctx->VertexProgram.Machine.Outputs[VERT_RESULT_FOGC][0] = 1.0;
+         machine.Outputs[VERT_RESULT_FOGC][0] = 1.0;
       }
 
       if (ctx->VertexProgram.PointSizeEnabled &&
           (program->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) {
-         ctx->VertexProgram.Machine.Outputs[VERT_RESULT_PSIZ][0] = ctx->Point.Size;
+         machine.Outputs[VERT_RESULT_PSIZ][0] = ctx->Point.Size;
       }
 
       /* copy the output registers into the VB->attribs arrays */
       /* XXX (optimize) could use a conditional and smaller loop limit here */
       for (attr = 0; attr < 15; attr++) {
-         COPY_4V(store->attribs[attr].data[i],
-                 ctx->VertexProgram.Machine.Outputs[attr]);
+         COPY_4V(store->attribs[attr].data[i], machine.Outputs[attr]);
       }
    }