New driver for i915 as well as older i830/i845/i865 chipsets.
authorKeith Whitwell <keith@tungstengraphics.com>
Thu, 10 Jun 2004 12:48:07 +0000 (12:48 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Thu, 10 Jun 2004 12:48:07 +0000 (12:48 +0000)
43 files changed:
src/mesa/drivers/dri/i915/Makefile [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_context.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_context.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_metaops.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_state.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_texblend.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i830_vtbl.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_context.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_context.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_debug.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_fragprog.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_metaops.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_program.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_program.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_state.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_texprog.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/i915_vtbl.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_batchbuffer.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_batchbuffer.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_context.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_context.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_ioctl.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_ioctl.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_pixel.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_render.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_screen.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_span.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_span.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_state.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_tris.c [new file with mode: 0644]
src/mesa/drivers/dri/i915/intel_tris.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/server/i830_common.h [new file with mode: 0644]
src/mesa/drivers/dri/i915/server/i830_dri.h [new file with mode: 0644]

diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile
new file mode 100644 (file)
index 0000000..acf78d7
--- /dev/null
@@ -0,0 +1,58 @@
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = i915_dri.so
+
+
+COMMON_SOURCES = \
+       ../../common/driverfuncs.c \
+       ../common/mm.c \
+       ../common/utils.c \
+       ../common/texmem.c \
+       ../common/vblank.c \
+       ../common/xmlconfig.c \
+       ../common/dri_util.c \
+       ../common/glcontextmodes.c
+
+DRIVER_SOURCES = \
+       i915_context.c \
+       i915_debug.c \
+       i915_fragprog.c \
+       i915_metaops.c \
+       i915_program.c \
+       i915_state.c \
+       i915_tex.c \
+       i915_texprog.c \
+       i915_texstate.c \
+       i915_vtbl.c \
+       i830_context.c \
+       i830_metaops.c \
+       i830_state.c \
+       i830_texblend.c \
+       i830_tex.c \
+       i830_texstate.c \
+       i830_vtbl.c \
+       intel_batchbuffer.c \
+       intel_context.c \
+       intel_ioctl.c \
+       intel_pixel.c \
+       intel_render.c \
+       intel_screen.c \
+       intel_span.c \
+       intel_state.c \
+       intel_tex.c \
+       intel_tris.c 
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(MINIGLX_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+
+
+include ../Makefile.template
+
+symlinks:
diff --git a/src/mesa/drivers/dri/i915/i830_context.c b/src/mesa/drivers/dri/i915/i830_context.c
new file mode 100644 (file)
index 0000000..4acec31
--- /dev/null
@@ -0,0 +1,143 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+/* This is the extension list explicitly enabled by the client and
+ * excludes functionality available in Mesa and also excludes legacy
+ * extensions.  It is recognized that in an open source driver, those
+ * extensions will probably be re-enabled.
+ */
+static const GLubyte *i830GetString( GLcontext *ctx, GLenum name )
+{
+   if (name == GL_EXTENSIONS)
+      return 
+        "GL_ARB_multitexture "
+        "GL_ARB_texture_border_clamp "
+        "GL_ARB_texture_compression "
+        "GL_ARB_texture_env_add "
+        "GL_ARB_texture_env_combine "
+        "GL_ARB_texture_env_dot3 "
+        "GL_ARB_texture_mirrored_repeat "
+        "GL_ARB_transpose_matrix "
+        "GL_ARB_vertex_buffer_object "
+        "GL_ARB_vertex_program "
+        "GL_ARB_window_pos "
+        "GL_EXT_abgr "
+        "GL_EXT_bgra "
+        "GL_EXT_blend_color "
+        "GL_EXT_blend_func_separate "
+        "GL_EXT_blend_minmax "
+        "GL_EXT_blend_subtract "
+        "GL_EXT_clip_volume_hint "
+        "GL_EXT_compiled_vertex_array "
+        "GL_EXT_draw_range_elements "
+        "GL_EXT_fog_coord "
+        "GL_EXT_multi_draw_arrays "
+        "GL_EXT_packed_pixels "
+        "GL_EXT_rescale_normal "
+        "GL_EXT_secondary_color "
+        "GL_EXT_separate_specular_color "
+        "GL_EXT_stencil_wrap "
+        "GL_EXT_texture_env_add "
+        "GL_EXT_texture_env_combine "
+        "GL_EXT_texture_filter_anisotropic "
+        "GL_IBM_texture_mirrored_repeat "
+        "GL_MESA_ycbcr_texture "
+        "GL_MESA_window_pos "
+        "GL_NV_texgen_reflection "
+        "GL_SGIS_generate_mipmap ";
+   return intelGetString( ctx, name );
+}
+
+
+static void i830InitDriverFunctions( struct dd_function_table *functions )
+{
+   intelInitDriverFunctions( functions );
+   i830InitStateFuncs( functions );
+   i830InitTextureFuncs( functions );
+   functions->GetString = i830GetString;
+}
+
+
+GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
+                           __DRIcontextPrivate *driContextPriv,
+                           void *sharedContextPrivate)
+{
+   struct dd_function_table functions;
+   i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context);
+   intelContextPtr 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;
+
+   intel->nr_heaps = 1;
+   intel->texture_heaps[0] = 
+      driCreateTextureHeap( 0, intel,
+                           intel->intelScreen->textureSize,
+                           12,
+                           I830_NR_TEX_REGIONS,
+                           intel->sarea->texList,
+                           & intel->sarea->texAge,
+                           & intel->swapped,
+                           sizeof( struct i830_texture_object ),
+                           (destroy_texture_object_t *)intelDestroyTexObj );
+
+   /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
+    * FIXME: packed, but they're not in Intel graphics hardware.
+    */
+   intel->ctx.Const.MaxTextureUnits = 1;
+   driCalculateMaxTextureLevels( intel->texture_heaps,
+                                intel->nr_heaps,
+                                &intel->ctx.Const,
+                                4,
+                                11, /* max 2D texture size is 2048x2048 */
+                                8,  /* max 3D texture size is 256^3 */
+                                0,  /* max CUBE. not supported */
+                                0,  /* max RECT. supported, but not enabled */
+                                12,
+                                GL_FALSE );
+   intel->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;
+
+   i830InitState( i830 );
+
+
+   _tnl_allow_vertex_fog( ctx, 1 ); 
+   _tnl_allow_pixel_fog( ctx, 0 ); 
+
+   return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h
new file mode 100644 (file)
index 0000000..27948f0
--- /dev/null
@@ -0,0 +1,197 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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_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_CBUFADDR2 2
+#define I830_DESTREG_DBUFADDR0 3
+#define I830_DESTREG_DBUFADDR1 4
+#define I830_DESTREG_DBUFADDR2 5
+#define I830_DESTREG_DV0 6
+#define I830_DESTREG_DV1 7
+#define I830_DESTREG_SENABLE 8
+#define I830_DESTREG_SR0 9
+#define I830_DESTREG_SR1 10
+#define I830_DESTREG_SR2 11
+#define I830_DEST_SETUP_SIZE 12
+
+#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_TM0S0      1
+#define I830_TEXREG_TM0S1      2
+#define I830_TEXREG_TM0S2      3
+#define I830_TEXREG_TM0S3      4
+#define I830_TEXREG_TM0S4      5
+#define I830_TEXREG_MCS              6 /* _3DSTATE_MAP_COORD_SETS */
+#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];
+   GLuint emitted;             /* I810_UPLOAD_* */
+   GLuint active;
+};
+
+struct i830_context 
+{
+   struct intel_context intel;
+   
+   GLuint last_index;
+
+   struct i830_hw_state meta, initial, state, *current;
+};
+
+typedef struct i830_context *i830ContextPtr;
+typedef struct i830_texture_object *i830TextureObjectPtr;
+
+#define I830_CONTEXT(ctx)      ((i830ContextPtr)(ctx))
+
+
+
+#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( i830ContextPtr i830 );
+
+/* i830_context.c
+ */
+extern GLboolean 
+i830CreateContext( const __GLcontextModes *mesaVis,
+                  __DRIcontextPrivate *driContextPriv,
+                  void *sharedContextPrivate);
+
+/* i830_tex.c, i830_texstate.c
+ */
+extern void 
+i830UpdateTextureState( intelContextPtr intel );
+
+extern void 
+i830InitTextureFuncs( struct dd_function_table *functions );
+
+extern intelTextureObjectPtr
+i830AllocTexObj( struct gl_texture_object *tObj );
+
+/* i830_texblend.c
+ */
+extern GLuint 
+i830SetBlend_GL1_2(i830ContextPtr i830, int unit, 
+                  GLenum envMode, GLenum format,
+                  GLuint texel_op,
+                  GLuint *state,
+                  const GLfloat *envcolor );
+
+extern void 
+i830EmitTextureBlend( i830ContextPtr i830 );
+
+
+/* i830_state.c
+ */
+extern void 
+i830InitStateFuncs( struct dd_function_table *functions );
+
+extern void 
+i830EmitState( i830ContextPtr i830 );
+
+extern void 
+i830InitState( i830ContextPtr i830 );
+
+/* i830_metaops.c
+ */
+extern GLboolean
+i830TryTextureReadPixels( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *pack,
+                         GLvoid *pixels );
+
+extern GLboolean
+i830TryTextureDrawPixels( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *unpack,
+                         const GLvoid *pixels );
+
+extern void 
+i830ClearWithTris( intelContextPtr intel, GLbitfield mask,
+                  GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
+
+
+       
+#endif
+
diff --git a/src/mesa/drivers/dri/i915/i830_metaops.c b/src/mesa/drivers/dri/i915/i830_metaops.c
new file mode 100644 (file)
index 0000000..fb2ee12
--- /dev/null
@@ -0,0 +1,699 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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 "i830_context.h"
+#include "i830_reg.h"
+
+/* A large amount of state doesn't need to be uploaded.
+ */
+#define ACTIVE (I830_UPLOAD_TEXBLEND(0) |      \
+               I830_UPLOAD_STIPPLE |           \
+               I830_UPLOAD_CTX |               \
+               I830_UPLOAD_BUFFERS |           \
+               I830_UPLOAD_TEX(0))             
+
+
+#define SET_STATE( i830, STATE )               \
+do {                                           \
+   i830->current->emitted &= ~ACTIVE;                  \
+   i830->current = &i830->STATE;               \
+   i830->current->emitted &= ~ACTIVE;                  \
+} while (0)
+
+/* 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 set_initial_state( i830ContextPtr i830 )
+{
+   memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
+   i830->meta.active = ACTIVE;
+   i830->meta.emitted = 0;
+}
+
+
+static void set_no_depth_stencil_write( i830ContextPtr i830 )
+{
+   /* 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;
+
+
+   /* 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 stencil unit to replace always with the reference value.
+ */
+static void set_stencil_replace( i830ContextPtr i830,
+                                GLuint s_mask,
+                                GLuint s_clear)
+{
+   /* 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.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;
+
+   /* 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( i830ContextPtr i830, GLboolean state )
+{
+   const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
+                       (1 << WRITEMASK_GREEN_SHIFT) |
+                       (1 << WRITEMASK_BLUE_SHIFT) |
+                       (1 << WRITEMASK_ALPHA_SHIFT));
+
+   if (state) {
+      i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
+      i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= 
+        (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
+   }
+   else 
+      i830->meta.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( i830ContextPtr i830 )
+{
+   i830->meta.TexBlendWordsUsed[0] = 
+      i830SetBlend_GL1_2( i830, 0, GL_NONE, 0, 
+                         TEXBLENDARG_TEXEL0,
+                         i830->meta.TexBlend[0], 0 );
+   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 enable_texture_blend_replace( i830ContextPtr i830,
+                                         GLenum format )
+{
+   i830->meta.TexBlendWordsUsed[0] = 
+      i830SetBlend_GL1_2( i830, 0, GL_REPLACE, format, 
+                         TEXBLENDARG_TEXEL0,
+                         i830->meta.TexBlend[0], 0 );
+   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 void set_tex_rect_source( i830ContextPtr i830,
+                                GLuint offset,
+                                GLuint width, 
+                                GLuint height,
+                                GLuint pitch,
+                                GLuint textureFormat )
+{
+   GLint numLevels = 1;
+   GLuint *setup = i830->meta.Tex[0];
+
+   pitch *= i830->intel.intelScreen->cpp;
+
+/*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
+/*        __FUNCTION__, offset, width, height, pitch, textureFormat ); */
+
+   setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 
+                              (LOAD_TEXTURE_MAP0 << 0) | 4);
+   setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
+   setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
+                              ((width - 1) << TM0S1_WIDTH_SHIFT) |
+                              textureFormat);
+   setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));   
+   setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
+   setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
+   setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
+
+   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);
+}
+
+
+/* Select between front and back draw buffers.
+ */
+static void set_draw_offset( i830ContextPtr i830,
+                            GLuint offset )
+{
+   i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
+   i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
+}
+
+/* Setup an arbitary draw format, useful for targeting
+ * texture or agp memory.
+ */
+static void set_draw_format( i830ContextPtr i830,
+                            GLuint format,
+                            GLuint depth_format)
+{
+   i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
+                                         DSTORG_VERT_BIAS(0x8) | /* .5 */
+                                         format |
+                                         DEPTH_IS_Z |
+                                         depth_format);
+}
+
+
+static void set_vertex_format( i830ContextPtr i830 )
+{
+   i830->meta.Ctx[I830_CTXREG_VF] =  (_3DSTATE_VFT0_CMD |
+                                     VFT0_TEX_COUNT(1) |
+                                     VFT0_DIFFUSE |
+                                     VFT0_SPEC |
+                                     VFT0_XYZW);
+   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 draw_quad(i830ContextPtr i830, 
+                     GLfloat x0, GLfloat x1,
+                     GLfloat y0, GLfloat y1, 
+                     GLubyte red, GLubyte green,
+                     GLubyte blue, GLubyte alpha,
+                     GLfloat s0, GLfloat s1,
+                     GLfloat t0, GLfloat t1 )
+{
+   GLuint vertex_size = 8;
+   GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel, 
+                                               PRIM3D_TRIFAN, 
+                                               4*vertex_size,
+                                               vertex_size );
+   intelVertex tmp;
+   int i;
+
+   
+/*    fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
+/*        __FUNCTION__, */
+/*        x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
+
+
+   /* initial vertex, left bottom */
+   tmp.v.x = x0;
+   tmp.v.y = y0;
+   tmp.v.z = 1.0;
+   tmp.v.w = 1.0;
+   tmp.v.color.red = red;
+   tmp.v.color.green = green;
+   tmp.v.color.blue = blue;
+   tmp.v.color.alpha = alpha;
+   tmp.v.specular.red = 0;
+   tmp.v.specular.green = 0;
+   tmp.v.specular.blue = 0;
+   tmp.v.specular.alpha = 0;
+   tmp.v.u0 = s0;
+   tmp.v.v0 = t0;
+   for (i = 0 ; i < 8 ; i++)
+      vb[i] = tmp.ui[i];
+
+   /* right bottom */
+   vb += 8;
+   tmp.v.x = x1;
+   tmp.v.u0 = s1;
+   for (i = 0 ; i < 8 ; i++)
+      vb[i] = tmp.ui[i];
+
+   /* right top */
+   vb += 8;
+   tmp.v.y = y1;
+   tmp.v.v0 = t1;
+   for (i = 0 ; i < 8 ; i++)
+      vb[i] = tmp.ui[i];
+
+   /* left top */
+   vb += 8;
+   tmp.v.x = x0;
+   tmp.v.u0 = s0;
+   for (i = 0 ; i < 8 ; i++)
+      vb[i] = tmp.ui[i];
+
+/*    fprintf(stderr, "%s: DV1: %x\n",  */
+/*        __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
+}
+
+void 
+i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
+                 GLboolean all,
+                 GLint cx, GLint cy, GLint cw, GLint ch)
+{
+   i830ContextPtr i830 = I830_CONTEXT( intel );
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   intelScreenPrivate *screen = intel->intelScreen;
+   int x0, y0, x1, y1;
+
+
+   SET_STATE( i830, meta );
+   set_initial_state( i830 );
+   set_no_texture( i830 );
+   set_vertex_format( i830 ); 
+
+   LOCK_HARDWARE(intel);
+
+   if(!all) {
+      x0 = cx;
+      y0 = cy;
+      x1 = x0 + cw;
+      y1 = y0 + ch;
+   } else {
+      x0 = 0;
+      y0 = 0;
+      x1 = x0 + dPriv->w;
+      y1 = y0 + dPriv->h;
+   }
+
+   /* Don't do any clipping to screen - these are window coordinates.
+    * The active cliprects will be applied as for any other geometry.
+    */
+
+   if(mask & DD_FRONT_LEFT_BIT) {
+      set_no_depth_stencil_write( i830 );
+      set_color_mask( i830, GL_TRUE );
+      set_draw_offset( i830, screen->frontOffset );
+      draw_quad(i830, x0, x1, y0, y1,
+               intel->clear_red, intel->clear_green,
+               intel->clear_blue, intel->clear_alpha,
+               0, 0, 0, 0);
+   }
+
+   if(mask & DD_BACK_LEFT_BIT) {
+      set_no_depth_stencil_write( i830 );
+      set_color_mask( i830, GL_TRUE );
+      set_draw_offset( i830, screen->backOffset );
+
+      draw_quad(i830, x0, x1, y0, y1,
+               intel->clear_red, intel->clear_green,
+               intel->clear_blue, intel->clear_alpha,
+               0, 0, 0, 0);
+   }
+
+   if(mask & DD_STENCIL_BIT) {
+      set_stencil_replace( i830, 
+                          intel->ctx.Stencil.WriteMask[0], 
+                          intel->ctx.Stencil.Clear);
+
+      set_color_mask( i830, GL_FALSE );
+      set_draw_offset( i830, screen->frontOffset );
+      draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
+   }
+
+   UNLOCK_HARDWARE(intel);
+
+   SET_STATE( i830, state );
+}
+
+
+
+
+GLboolean
+i830TryTextureReadPixels( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *pack,
+                         GLvoid *pixels )
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   intelScreenPrivate *screen = i830->intel.intelScreen;
+   GLint pitch = pack->RowLength ? pack->RowLength : width;
+   __DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
+   int textureFormat;
+   GLenum glTextureFormat;
+   int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
+   int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
+   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) {
+      fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   switch (screen->fbFormat) {
+   case DV_PF_565:
+      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+      glTextureFormat = GL_RGB;
+      break;
+   case DV_PF_555:
+      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
+      glTextureFormat = GL_RGBA;
+      break;
+   case DV_PF_8888:
+      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+      glTextureFormat = GL_RGBA;
+      break;
+   default:
+      fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
+             screen->fbFormat);
+      return GL_FALSE;
+   }
+
+
+   switch (type) {
+   case GL_UNSIGNED_SHORT_5_6_5: 
+      if (format != GL_RGB) return GL_FALSE;
+      destFormat = COLR_BUF_RGB565; 
+      depthFormat = DEPTH_FRMT_16_FIXED;
+      destPitch = pitch * 2;
+      break;
+   case GL_UNSIGNED_INT_8_8_8_8_REV: 
+      if (format != GL_BGRA) return GL_FALSE;
+      destFormat = COLR_BUF_ARGB8888; 
+      depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
+      destPitch = pitch * 4;
+      break;
+   default:
+      fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
+             _mesa_lookup_enum_by_nr(type));
+      return GL_FALSE;
+   }
+
+   destFormat |= (0x02<<24);
+
+/*    fprintf(stderr, "type: %s destFormat: %x\n", */
+/*        _mesa_lookup_enum_by_nr(type), */
+/*        destFormat); */
+
+   intelFlush( ctx );
+
+   SET_STATE( i830, meta );
+   set_initial_state( i830 );
+   set_no_depth_stencil_write( i830 );
+
+   LOCK_HARDWARE( intel );
+   {
+      intelWaitForIdle( intel ); /* required by GL */
+
+      if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
+        UNLOCK_HARDWARE( intel );
+        SET_STATE(i830, state);
+        fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
+        return GL_TRUE;
+      }
+
+#if 0
+      /* FIXME -- Just emit the correct state
+       */
+      if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH, 
+                     destPitch) != 0) {
+        UNLOCK_HARDWARE( intel );
+        SET_STATE(i830, state);
+        fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
+        return GL_FALSE;
+      }
+#endif
+
+
+      y = dPriv->h - y - height;
+      x += dPriv->x;
+      y += dPriv->y;
+
+
+      /* Set the frontbuffer up as a large rectangular texture.
+       */
+      set_tex_rect_source( i830, 
+                          src_offset, 
+                          screen->width, 
+                          screen->height, 
+                          screen->frontPitch, 
+                          textureFormat ); 
+   
+   
+      enable_texture_blend_replace( i830, glTextureFormat ); 
+
+
+      /* Set the 3d engine to draw into the agp memory
+       */
+
+      set_draw_offset( i830, destOffset ); 
+      set_draw_format( i830, destFormat, depthFormat );  
+
+
+      /* Draw a single quad, no cliprects:
+       */
+      i830->intel.numClipRects = 1;
+      i830->intel.pClipRects = &tmp;
+      i830->intel.pClipRects[0].x1 = 0;
+      i830->intel.pClipRects[0].y1 = 0;
+      i830->intel.pClipRects[0].x2 = width;
+      i830->intel.pClipRects[0].y2 = height;
+
+      draw_quad( i830, 
+                0, width, 0, height, 
+                0, 255, 0, 0, 
+                x, x+width, y, y+height );
+
+      intelWindowMoved( intel );
+   }
+   UNLOCK_HARDWARE( intel );
+   intelFinish( ctx ); /* required by GL */
+
+   SET_STATE( i830, state );
+   return GL_TRUE;
+}
+
+
+GLboolean
+i830TryTextureDrawPixels( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *unpack,
+                         const GLvoid *pixels )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   GLint pitch = unpack->RowLength ? unpack->RowLength : width;
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   int textureFormat;
+   GLenum glTextureFormat;
+   int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
+   int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* Todo -- upload images that aren't in agp space, then texture
+    * from them.  
+    */
+
+   if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
+      fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   /* Todo -- don't want to clobber all the drawing state like we do
+    * for readpixels -- most of this state can be handled just fine.
+    */
+   if (        ctx->_ImageTransferState ||
+       unpack->SwapBytes ||
+       unpack->LsbFirst ||
+       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->Depth.OcclusionTest) {
+      fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   /* Todo -- remove these restrictions:
+    */
+   if (ctx->Pixel.ZoomX != 1.0F ||
+       ctx->Pixel.ZoomY != -1.0F)
+      return GL_FALSE;
+
+
+
+   switch (type) {
+   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+      if (format != GL_BGRA) return GL_FALSE;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
+      glTextureFormat = GL_RGBA;
+      break;
+   case GL_UNSIGNED_SHORT_5_6_5: 
+      if (format != GL_RGB) return GL_FALSE;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+      glTextureFormat = GL_RGB;
+      break;
+   case GL_UNSIGNED_SHORT_8_8_MESA: 
+      if (format != GL_YCBCR_MESA) return GL_FALSE;
+      textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY 
+/*                    | TM0S1_COLORSPACE_CONVERSION */
+        );
+      glTextureFormat = GL_YCBCR_MESA;
+      break;
+   case GL_UNSIGNED_SHORT_8_8_REV_MESA: 
+      if (format != GL_YCBCR_MESA) return GL_FALSE;
+      textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL 
+/*                    | TM0S1_COLORSPACE_CONVERSION */
+        );
+      glTextureFormat = GL_YCBCR_MESA;
+      break;
+   case GL_UNSIGNED_INT_8_8_8_8_REV: 
+      if (format != GL_BGRA) return GL_FALSE;
+      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+      glTextureFormat = GL_RGBA;
+      break;
+   default:
+      fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   intelFlush( ctx );
+
+   SET_STATE( i830, meta );
+
+   LOCK_HARDWARE( intel );
+   {
+      intelWaitForIdle( intel ); /* required by GL */
+
+      y -= height;                     /* cope with pixel zoom */
+
+      if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
+        UNLOCK_HARDWARE( intel );
+        SET_STATE(i830, state);
+        fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
+        return GL_TRUE;
+      }
+
+
+      y = dPriv->h - y - height;
+
+      set_initial_state( i830 );
+
+      /* Set the pixel image up as a rectangular texture.
+       */
+      set_tex_rect_source( i830, 
+                          src_offset, 
+                          width, 
+                          height, 
+                          pitch, /* XXXX!!!! -- /2 sometimes */
+                          textureFormat ); 
+   
+   
+      enable_texture_blend_replace( i830, glTextureFormat ); 
+
+   
+      /* Draw to the current draw buffer:
+       */
+      set_draw_offset( i830, dst_offset );
+
+      /* Draw a quad, use regular cliprects
+       */
+/*       fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
+
+      draw_quad( i830, 
+                x, x+width, y, y+height,
+                0, 255, 0, 0, 
+                0, width, 0, height );
+
+      intelWindowMoved( intel );
+   }
+   UNLOCK_HARDWARE( intel );
+   intelFinish( ctx ); /* required by GL */
+   
+   SET_STATE(i830, state);
+
+   return GL_TRUE;
+}
+
diff --git a/src/mesa/drivers/dri/i915/i830_reg.h b/src/mesa/drivers/dri/i915/i830_reg.h
new file mode 100644 (file)
index 0000000..176c869
--- /dev/null
@@ -0,0 +1,665 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#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)
+
+#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
+
+/* _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)
+
+/* Use the blendfact defines for BLND_FACTOR macros */
+#if 0
+#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_CONST_ALPHA          0x0e
+#define BLENDFACT_INV_CONST_ALPHA      0x0f
+#endif
+
+/* _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
+#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
+
+/* _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)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK        ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK      (1<<16)
+#define STENCIL_WRITE_MASK(x)          (x)
+
+/* _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 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 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_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/i915/i830_state.c b/src/mesa/drivers/dri/i915/i830_state.c
new file mode 100644 (file)
index 0000000..4649a75
--- /dev/null
@@ -0,0 +1,1183 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#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 "i830_context.h"
+#include "i830_reg.h"
+
+static void i830StencilFunc(GLcontext *ctx, GLenum func, GLint ref,
+                           GLuint mask)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int test = 0;
+
+   mask = mask & 0xff;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
+             _mesa_lookup_enum_by_nr(func), ref, mask);
+
+   switch(func) {
+   case GL_NEVER: 
+      test = COMPAREFUNC_NEVER; 
+      break;
+   case GL_LESS: 
+      test = COMPAREFUNC_LESS; 
+      break;
+   case GL_LEQUAL: 
+      test = COMPAREFUNC_LEQUAL; 
+      break;
+   case GL_GREATER: 
+      test = COMPAREFUNC_GREATER; 
+      break;
+   case GL_GEQUAL: 
+      test = COMPAREFUNC_GEQUAL; 
+      break;
+   case GL_NOTEQUAL: 
+      test = COMPAREFUNC_NOTEQUAL; 
+      break;
+   case GL_EQUAL: 
+      test = COMPAREFUNC_EQUAL; 
+      break;
+   case GL_ALWAYS: 
+      test = COMPAREFUNC_ALWAYS; 
+      break;
+   default:
+      return;
+   }
+
+   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 i830StencilMask(GLcontext *ctx, GLuint mask)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 i830StencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
+                         GLenum zpass)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int fop, dfop, dpop;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int test = 0;
+   GLubyte refByte;
+   GLuint refInt;
+
+   UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
+   refInt = (GLuint)refByte;
+
+   switch(func) {
+   case GL_NEVER: 
+      test = COMPAREFUNC_NEVER; 
+      break;
+   case GL_LESS: 
+      test = COMPAREFUNC_LESS; 
+      break;
+   case GL_LEQUAL: 
+      test = COMPAREFUNC_LEQUAL; 
+      break;
+   case GL_GREATER: 
+      test = COMPAREFUNC_GREATER; 
+      break;
+   case GL_GEQUAL: 
+      test = COMPAREFUNC_GEQUAL; 
+      break;
+   case GL_NOTEQUAL: 
+      test = COMPAREFUNC_NOTEQUAL; 
+      break;
+   case GL_EQUAL: 
+      test = COMPAREFUNC_EQUAL; 
+      break;
+   case GL_ALWAYS: 
+      test = COMPAREFUNC_ALWAYS; 
+      break;
+   default:
+      return;
+   }
+
+   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));
+}
+
+/* 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 i830EvalLogicOpBlendState(GLcontext *ctx)
+{
+   i830ContextPtr 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])
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   GLubyte r, g, b, a;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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;
+}
+
+static void i830BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB,
+                                     GLenum modeA) 
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int func = ENABLE_ALPHA_BLENDFUNC;
+
+   assert( modeRGB == modeA );
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+     fprintf(stderr, "%s %s\n", __FUNCTION__,
+            _mesa_lookup_enum_by_nr(modeRGB));
+
+   /* This will catch a logicop blend equation */
+   i830EvalLogicOpBlendState(ctx);
+
+   switch(modeRGB) {
+   case GL_FUNC_ADD: 
+      func |= BLENDFUNC_ADD; 
+      break;
+   case GL_MIN: 
+      func |= BLENDFUNC_MIN; 
+      break;
+   case GL_MAX: 
+      func |= BLENDFUNC_MAX; 
+      break;
+   case GL_FUNC_SUBTRACT: 
+      func |= BLENDFUNC_SUB; 
+      break;
+   case GL_FUNC_REVERSE_SUBTRACT: 
+      func |= BLENDFUNC_RVRSE_SUB; 
+      break;
+   case GL_LOGIC_OP:
+   default: return;
+   }
+
+   I830_STATECHANGE(i830, I830_UPLOAD_CTX);
+   i830->state.Ctx[I830_CTXREG_STATE1] &= ~BLENDFUNC_MASK;
+   i830->state.Ctx[I830_CTXREG_STATE1] |= func;
+}
+
+
+
+static int 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;
+   default:
+      return BLENDFACT_ZERO;
+   }
+}
+
+static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, 
+                                 GLenum dfactorRGB, GLenum sfactorA,
+                                 GLenum dfactorA )
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int iab = i830->state.Ctx[I830_CTXREG_IALPHAB];
+   int s1 = i830->state.Ctx[I830_CTXREG_STATE1];
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+
+   iab &= ~(SRC_DST_ABLEND_MASK|ENABLE_INDPT_ALPHA_BLEND);
+   s1 &= ~SRC_DST_BLND_MASK;
+      
+   iab |= (ENABLE_SRC_ABLEND_FACTOR|ENABLE_DST_ABLEND_FACTOR);
+   s1 |= (ENABLE_SRC_BLND_FACTOR|ENABLE_DST_BLND_FACTOR);
+
+   if (ctx->Color.BlendEquationRGB == GL_MIN ||
+       ctx->Color.BlendEquationRGB == GL_MAX) {
+      sfactorA = sfactorRGB = dfactorA = dfactorRGB = GL_ONE;
+   }
+
+   iab |= SRC_ABLEND_FACT(translate_blend_factor(sfactorA)); 
+   iab |= DST_ABLEND_FACT(translate_blend_factor(dfactorA)); 
+   s1 |= SRC_BLND_FACT(translate_blend_factor(sfactorRGB)); 
+   s1 |= DST_BLND_FACT(translate_blend_factor(dfactorRGB)); 
+
+   if (sfactorA != sfactorRGB || dfactorA != dfactorRGB) 
+      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;
+   }
+}
+
+
+
+static void i830DepthFunc(GLcontext *ctx, GLenum func)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int test = 0;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   switch(func) {
+   case GL_NEVER: 
+      test = COMPAREFUNC_NEVER; 
+      break;
+   case GL_LESS: 
+      test = COMPAREFUNC_LESS; 
+      break;
+   case GL_LEQUAL: 
+      test = COMPAREFUNC_LEQUAL; 
+      break;
+   case GL_GREATER: 
+      test = COMPAREFUNC_GREATER; 
+      break;
+   case GL_GEQUAL: 
+      test = COMPAREFUNC_GEQUAL; 
+      break;
+   case GL_NOTEQUAL: 
+      test = COMPAREFUNC_NOTEQUAL; 
+      break;
+   case GL_EQUAL: 
+      test = COMPAREFUNC_EQUAL; 
+      break;
+   case GL_ALWAYS: 
+      test = COMPAREFUNC_ALWAYS; 
+      break;
+   default: return;
+   }
+
+   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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 )
+{
+   i830ContextPtr 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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   intelScreenPrivate *screen = i830->intel.intelScreen;
+   int x1, y1, x2, y2;
+
+   if (!i830->intel.driDrawable)
+      return;
+
+   x1 = x;
+   y1 = i830->intel.driDrawable->h - (y + h);
+   x2 = x + w - 1;
+   y2 = y1 + h - 1;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
+             x, y, w, h);
+
+   if (x1 < 0) x1 = 0;
+   if (y1 < 0) y1 = 0;
+   if (x2 < 0) x2 = 0;
+   if (y2 < 0) y2 = 0;
+
+   if (x2 >= screen->width) x2 = screen->width-1;
+   if (y2 >= screen->height) y2 = screen->height-1;
+   if (x1 >= screen->width) x1 = screen->width-1;
+   if (y1 >= screen->height) y1 = screen->height-1;
+
+
+   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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   int tmp = 0;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* FIXME: This should be a look-up table, like the r200 driver. */
+   switch(opcode) {
+   case GL_CLEAR: 
+      tmp = LOGICOP_CLEAR; 
+      break;
+   case GL_AND: 
+      tmp = LOGICOP_AND; 
+      break;
+   case GL_AND_REVERSE: 
+      tmp = LOGICOP_AND_RVRSE; 
+      break;
+   case GL_COPY: 
+      tmp = LOGICOP_COPY; 
+      break;
+   case GL_COPY_INVERTED: 
+      tmp = LOGICOP_COPY_INV; 
+      break;
+   case GL_AND_INVERTED: 
+      tmp = LOGICOP_AND_INV; 
+      break;
+   case GL_NOOP: 
+      tmp = LOGICOP_NOOP; 
+      break;
+   case GL_XOR: 
+      tmp = LOGICOP_XOR; 
+      break;
+   case GL_OR: 
+      tmp = LOGICOP_OR; 
+      break;
+   case GL_OR_INVERTED: 
+      tmp = LOGICOP_OR_INV; 
+      break;
+   case GL_NOR: 
+      tmp = LOGICOP_NOR; 
+      break;
+   case GL_EQUIV: 
+      tmp = LOGICOP_EQUIV; 
+      break;
+   case GL_INVERT: 
+      tmp = LOGICOP_INV; 
+      break;
+   case GL_OR_REVERSE: 
+      tmp = LOGICOP_OR_RVRSE; 
+      break;
+   case GL_NAND: 
+      tmp = LOGICOP_NAND; 
+      break;
+   case GL_SET: 
+      tmp = LOGICOP_SET; 
+      break;
+   default:
+      return;
+   }
+
+   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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   GLuint mode;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 )
+{
+   i830ContextPtr i830 = I830_CONTEXT( ctx );
+   int width;
+   int state5;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   GLint point_size = (int)size;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+     fprintf(stderr, "%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)
+{
+   i830ContextPtr i830 = I830_CONTEXT( ctx );
+   GLuint tmp = 0;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 )
+{
+   i830ContextPtr 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)
+{
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i830ContextPtr 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)
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i830ContextPtr 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:
+      if (i830->intel.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( i830ContextPtr 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 (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 {
+      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->frontPitch * screen->cpp) |
+       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->depthPitch * screen->cpp) |
+       BUF_3D_USE_FENCE);
+   i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depthOffset;
+
+
+   i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
+
+   switch (screen->fbFormat) {
+   case DV_PF_555:
+   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->StencilFunc = i830StencilFunc;
+   functions->StencilMask = i830StencilMask;
+   functions->StencilOp = i830StencilOp;
+}
+
+void i830InitState( i830ContextPtr 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_TEXBLEND(0) |
+                        I830_UPLOAD_STIPPLE |
+                        I830_UPLOAD_CTX |
+                        I830_UPLOAD_BUFFERS);
+}
+
+
+
+
+
diff --git a/src/mesa/drivers/dri/i915/i830_tex.c b/src/mesa/drivers/dri/i915/i830_tex.c
new file mode 100644 (file)
index 0000000..34baf28
--- /dev/null
@@ -0,0 +1,325 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+
+
+
+/**
+ * Set the texture wrap modes.
+ * 
+ * The i830M (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.
+ * 
+ * \param t Texture object whose wrap modes are to be set
+ * \param swrap Wrap mode for the \a s texture coordinate
+ * \param twrap Wrap mode for the \a t texture coordinate
+ */
+static void i830SetTexWrapping(i830TextureObjectPtr tex,
+                              GLenum swrap, 
+                              GLenum twrap)
+{
+   tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK);
+
+   switch( swrap ) {
+   case GL_REPEAT:
+      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP);
+      break;
+   case GL_CLAMP:
+   case GL_CLAMP_TO_EDGE:
+      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP);
+      break;
+   case GL_CLAMP_TO_BORDER:
+      tex->Setup[I830_TEXREG_MCS] |= 
+                       TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER);
+      break;
+   case GL_MIRRORED_REPEAT:
+      tex->Setup[I830_TEXREG_MCS] |= 
+                       TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR);
+      break;
+   default:
+      break;
+   }
+
+   switch( twrap ) {
+   case GL_REPEAT:
+      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP);
+      break;
+   case GL_CLAMP:
+   case GL_CLAMP_TO_EDGE:
+      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP);
+      break;
+   case GL_CLAMP_TO_BORDER:
+      tex->Setup[I830_TEXREG_MCS] |= 
+                       TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER);
+      break;
+   case GL_MIRRORED_REPEAT:
+      tex->Setup[I830_TEXREG_MCS] |=
+                       TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR);
+      break;
+   default:
+      break;
+   }
+}
+
+
+/**
+ * Set the texture magnification and minification modes.
+ * 
+ * \param t Texture whose filter modes are to be set
+ * \param minf Texture minification mode
+ * \param magf Texture magnification mode
+ * \param bias LOD bias for this texture unit.
+ */
+
+static void i830SetTexFilter( i830TextureObjectPtr t, GLenum minf, GLenum magf,
+                             GLfloat maxanisotropy )
+{
+   int minFilt = 0, mipFilt = 0, magFilt = 0;
+
+   if(INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if ( maxanisotropy > 1.0 ) {
+      minFilt = FILTER_ANISOTROPIC;
+      magFilt = FILTER_ANISOTROPIC;
+   }
+   else {
+      switch (minf) {
+      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:
+        break;
+      }
+
+      switch (magf) {
+      case GL_NEAREST:
+        magFilt = FILTER_NEAREST;
+        break;
+      case GL_LINEAR:
+        magFilt = FILTER_LINEAR;
+        break;
+      default:
+        break;
+      }  
+   }
+
+   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK;
+   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK;
+   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK;
+   t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
+                                  (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
+                                  (magFilt << TM0S3_MAG_FILTER_SHIFT));
+}
+
+static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4])
+{
+   if(INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+    t->Setup[I830_TEXREG_TM0S4] = 
+        INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]);
+}
+
+
+/**
+ * Allocate space for and load the mesa images into the texture memory block.
+ * This will happen before drawing with a new texture, or drawing with a
+ * texture after it was swapped out or teximaged again.
+ */
+
+intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
+{
+   i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object );
+   if ( !t ) 
+      return NULL;
+
+   texObj->DriverData = t;
+   t->intel.base.tObj = texObj;
+   t->intel.dirty = I830_UPLOAD_TEX_ALL;
+   make_empty_list( &t->intel.base );
+
+   t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
+   t->Setup[I830_TEXREG_TM0S0] = 0;
+   t->Setup[I830_TEXREG_TM0S1] = 0;
+   t->Setup[I830_TEXREG_TM0S2] = 0;
+   t->Setup[I830_TEXREG_TM0S3] = 0;
+   t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
+                               MAP_UNIT(0) |
+                               ENABLE_TEXCOORD_PARAMS |
+                               TEXCOORDS_ARE_NORMAL |
+                               TEXCOORDTYPE_CARTESIAN |
+                               ENABLE_ADDR_V_CNTL |
+                               TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
+                               ENABLE_ADDR_U_CNTL |
+                               TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
+
+   
+   i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
+   i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter, 
+                    texObj->MaxAnisotropy );
+   i830SetTexBorderColor( t, texObj->_BorderChan );
+
+   return &t->intel;
+}
+
+
+static void i830TexParameter( GLcontext *ctx, GLenum target,
+                             struct gl_texture_object *tObj,
+                             GLenum pname, const GLfloat *params )
+{
+   i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
+   if (!t)
+      return;
+
+   switch (pname) {
+   case GL_TEXTURE_MIN_FILTER:
+   case GL_TEXTURE_MAG_FILTER:
+   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+      i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter,
+                       tObj->MaxAnisotropy);
+      break;
+
+   case GL_TEXTURE_WRAP_S:
+   case GL_TEXTURE_WRAP_T:
+      i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT );
+      break;
+  
+   case GL_TEXTURE_BORDER_COLOR:
+      i830SetTexBorderColor( t, tObj->_BorderChan );
+      break;
+
+   case GL_TEXTURE_BASE_LEVEL:
+   case GL_TEXTURE_MAX_LEVEL:
+   case GL_TEXTURE_MIN_LOD:
+   case GL_TEXTURE_MAX_LOD:
+      /* The i830 and its successors can do a lot of this without
+       * reloading the textures.  A project for someone?
+       */
+      intelFlush( ctx );
+      driSwapOutTextureObject( (driTextureObject *) t );
+      break;
+
+   default:
+      return;
+   }
+
+   t->intel.dirty = I830_UPLOAD_TEX_ALL;
+}
+
+
+static void i830TexEnv( GLcontext *ctx, GLenum target, 
+                       GLenum pname, const GLfloat *param )
+{
+   i830ContextPtr i830 = I830_CONTEXT( ctx );
+   GLuint unit = ctx->Texture.CurrentUnit;
+
+   switch (pname) {
+   case GL_TEXTURE_ENV_COLOR: 
+#if 0
+   {
+      GLubyte r, g, b, a;
+      GLuint col;
+      
+      UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]);
+      UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]);
+      UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]);
+      UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]);
+
+      col = ((a << 24) | (r << 16) | (g << 8) | b);
+
+      if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) {
+        I830_STATECHANGE(i830, I830_UPLOAD_TEXENV);
+        i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col;
+      }
+
+      break;
+   }
+#endif
+   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: {
+      int b = (int) ((*param) * 16.0);
+      if (b > 63) b = 63;
+      if (b < -64) b = -64;
+      I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
+      i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
+      i830->state.Tex[unit][I830_TEXREG_TM0S3] |= 
+        ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
+      break;
+   }
+
+   default:
+      break;
+   }
+}
+
+
+
+
+void i830InitTextureFuncs( struct dd_function_table *functions )
+{
+   functions->TexEnv                    = i830TexEnv;
+   functions->TexParameter              = i830TexParameter;
+}
diff --git a/src/mesa/drivers/dri/i915/i830_texblend.c b/src/mesa/drivers/dri/i915/i830_texblend.c
new file mode 100644 (file)
index 0000000..e30b2df
--- /dev/null
@@ -0,0 +1,1058 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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;
+   }
+}
+
+
+GLuint i830SetBlend_GL1_2(i830ContextPtr i830, int blendUnit, 
+                         GLenum envMode, GLenum format, GLuint texel_op,
+                         GLuint *state, const GLfloat *factor)
+{
+   if(INTEL_DEBUG&DEBUG_TEXTURE)
+      fprintf(stderr, "%s %s %s texel_op(0x%x)\n",
+             __FUNCTION__,
+             _mesa_lookup_enum_by_nr(format),
+             _mesa_lookup_enum_by_nr(envMode),
+             texel_op);
+
+   switch(envMode) {
+   case GL_REPLACE:
+      switch(format) {
+      case GL_ALPHA:
+        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 |
+                    texel_op);
+        return 4;
+
+      case GL_LUMINANCE:
+      case GL_RGB:
+      case GL_YCBCR_MESA:
+        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 |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 4;
+
+      case GL_INTENSITY:
+      case GL_LUMINANCE_ALPHA:
+      case GL_RGBA:
+        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 |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        return 4;
+
+      default:
+        /* Always set to passthru if something is funny */
+        return pass_through( state, blendUnit );
+      }
+
+   case GL_MODULATE:
+      switch(format) {
+      case GL_ALPHA:
+        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_MODULATE);
+        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 |
+                    texel_op);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 5;
+
+      case GL_LUMINANCE:
+      case GL_RGB:
+      case GL_YCBCR_MESA:
+        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_MODULATE);
+        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 |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 5;
+
+      case GL_INTENSITY:
+      case GL_LUMINANCE_ALPHA:
+      case GL_RGBA:
+        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_MODULATE);
+        state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT |
+                    TEXOP_SCALE_1X |
+                    TEXOP_MODIFY_PARMS |
+                    TEXBLENDOP_MODULATE);
+        state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 6;
+
+      default:
+        /* Always set to passthru if something is funny */
+        return pass_through( state, blendUnit );
+      }
+
+   case GL_DECAL:
+      switch(format) {
+      case GL_RGB:
+      case GL_YCBCR_MESA:
+        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 |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 4;
+
+      case GL_RGBA:
+        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_BLEND);
+        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_ARG0 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_REPLICATE_ALPHA |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 6;
+      default:
+        /* Always set to passthru if something is funny */
+        return pass_through( state, blendUnit );
+      }
+
+   case GL_BLEND:
+      switch(format) {
+      case GL_ALPHA:
+        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_MODULATE);
+        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 |
+                    texel_op);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 5;
+
+      case GL_LUMINANCE:
+      case GL_RGB:
+      case GL_YCBCR_MESA:
+        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_BLEND);
+        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_ARG0 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_FACTOR_N);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return emit_factor( blendUnit, state, 6, factor );
+
+      case GL_INTENSITY:
+        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_BLEND);
+        state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT |
+                    TEXOP_SCALE_1X |
+                    TEXOP_MODIFY_PARMS |
+                    TEXBLENDOP_BLEND);
+        state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG0 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_FACTOR_N);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG0 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[6] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_FACTOR_N);
+        state[7] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return emit_factor( blendUnit, state, 8, factor );
+
+
+      case GL_LUMINANCE_ALPHA:
+      case GL_RGBA:
+        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_BLEND);
+        state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT |
+                    TEXOP_SCALE_1X |
+                    TEXOP_MODIFY_PARMS |
+                    TEXBLENDOP_MODULATE);
+        state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG0 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_FACTOR_N);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[6] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return emit_factor( blendUnit, state, 7, factor );
+
+      default:
+        /* Always set to passthru if something is funny */
+        return pass_through( state, blendUnit );
+      }
+
+   case GL_ADD:
+      switch(format) {
+      case GL_ALPHA:
+        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_MODULATE);
+        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 |
+                    texel_op);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 5;
+
+      case GL_LUMINANCE:
+      case GL_RGB:
+      case GL_YCBCR_MESA:
+        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_ADD);
+        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 |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 5;
+
+      case GL_INTENSITY:
+        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_ADD);
+        state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT |
+                    TEXOP_SCALE_1X |
+                    TEXOP_MODIFY_PARMS |
+                    TEXBLENDOP_ADD);
+        state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 6;
+
+      case GL_LUMINANCE_ALPHA:
+      case GL_RGBA:
+        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_ADD);
+        state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    ENABLE_TEXOUTPUT_WRT_SEL |
+                    TEXOP_OUTPUT_CURRENT |
+                    TEXOP_SCALE_1X |
+                    TEXOP_MODIFY_PARMS |
+                    TEXBLENDOP_MODULATE);
+        state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_COLOR |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        state[4] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG1 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    texel_op);
+        state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+                    TEXPIPE_ALPHA |
+                    TEXBLEND_ARG2 |
+                    TEXBLENDARG_MODIFY_PARMS |
+                    TEXBLENDARG_CURRENT);
+        return 6;
+
+      default:
+        /* Always set to passthru if something is funny */
+        return pass_through( state, blendUnit );
+      }
+
+   default:
+      /* Always set to passthru if something is funny */
+      return pass_through( state, blendUnit );
+   }
+}
+
+static GLuint i830SetTexEnvCombine(i830ContextPtr i830,
+                                  const struct gl_texture_unit *texUnit, 
+                                  GLint blendUnit,
+                                  GLuint texel_op,
+                                  GLuint *state,
+                                  const GLfloat *factor )
+{
+   GLuint blendop;
+   GLuint ablendop;
+   GLuint args_RGB[3];
+   GLuint args_A[3];
+   GLuint rgb_shift;
+   GLuint alpha_shift;
+   GLboolean need_factor = 0;
+   int i;
+
+   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 (texUnit->Combine.ModeRGB) {
+   case GL_DOT3_RGB_EXT:
+      alpha_shift = texUnit->Combine.ScaleShiftA;
+      rgb_shift = 0;
+      break;
+
+   case GL_DOT3_RGBA_EXT:
+      alpha_shift = 0;
+      rgb_shift = 0;
+      break;
+
+   default:
+      rgb_shift = texUnit->Combine.ScaleShiftRGB;
+      alpha_shift = texUnit->Combine.ScaleShiftA;
+      break;
+   }
+
+
+   switch(texUnit->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(texUnit->Combine.SourceRGB[i]) {
+      case GL_TEXTURE: 
+        args_RGB[i] = texel_op;
+        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(texUnit->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 ( texUnit->Combine.ModeRGB == GL_DOT3_RGBA_EXT || 
+       texUnit->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(texUnit->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(texUnit->Combine.SourceA[i]) {
+        case GL_TEXTURE: 
+           args_A[i] = texel_op;
+           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(texUnit->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 pipeline */
+
+   state[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+              TEXPIPE_COLOR |
+              ENABLE_TEXOUTPUT_WRT_SEL |
+              TEXOP_OUTPUT_CURRENT |
+              DISABLE_TEX_CNTRL_STAGE |
+              TEXOP_MODIFY_PARMS |
+              blendop);
+   state[1] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+              TEXPIPE_COLOR |
+              TEXBLEND_ARG1 |
+              TEXBLENDARG_MODIFY_PARMS |
+              args_RGB[0]);
+   state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+              TEXPIPE_COLOR |
+              TEXBLEND_ARG2 |
+              TEXBLENDARG_MODIFY_PARMS |
+              args_RGB[1]);
+   state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+              TEXPIPE_COLOR |
+              TEXBLEND_ARG0 |
+              TEXBLENDARG_MODIFY_PARMS |
+              args_RGB[2]);
+
+   /* Build Alpha pipeline */
+   state[4] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
+              TEXPIPE_ALPHA |
+              ENABLE_TEXOUTPUT_WRT_SEL |
+              TEXOP_OUTPUT_CURRENT |
+              TEXOP_MODIFY_PARMS |
+              ablendop);
+   state[5] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+              TEXPIPE_ALPHA |
+              TEXBLEND_ARG1 |
+              TEXBLENDARG_MODIFY_PARMS |
+              args_A[0]);
+   state[6] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+              TEXPIPE_ALPHA |
+              TEXBLEND_ARG2 |
+              TEXBLENDARG_MODIFY_PARMS |
+              args_A[1]);
+   state[7] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
+              TEXPIPE_ALPHA |
+              TEXBLEND_ARG0 |
+              TEXBLENDARG_MODIFY_PARMS |
+              args_A[2]);
+
+
+   if (need_factor) 
+      return emit_factor( blendUnit, state, 8, factor );
+   else 
+      return 8;
+}
+
+
+static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit,
+                          GLboolean last_stage )
+{
+   struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
+   GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
+
+
+   if (0) fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
+
+   /* Update i830->state.TexBlend
+    */ 
+   if (texUnit->EnvMode == GL_COMBINE) {
+      tmp_sz = i830SetTexEnvCombine(i830, texUnit, blendUnit, 
+                                   GetTexelOp(unit), tmp,
+                                   texUnit->EnvColor );
+   } 
+   else {
+      tmp_sz = i830SetBlend_GL1_2(i830, blendUnit, texUnit->EnvMode,
+                                 t->intel.image[0][0].internalFormat, 
+                                 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( i830ContextPtr 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( i830ContextPtr 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/i915/i830_texstate.c b/src/mesa/drivers/dri/i915/i830_texstate.c
new file mode 100644 (file)
index 0000000..acf5cc9
--- /dev/null
@@ -0,0 +1,333 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+
+#define I830_TEX_UNIT_ENABLED(unit)            (1<<unit)
+
+static GLboolean i830SetTexImages( i830ContextPtr i830, 
+                                 struct gl_texture_object *tObj )
+{
+   GLuint total_height, pitch, i, textureFormat;
+   i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
+   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
+   GLint firstLevel, lastLevel, numLevels;
+
+   switch( baseImage->TexFormat->MesaFormat ) {
+   case MESA_FORMAT_L8:
+      t->intel.texelBytes = 1;
+      textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
+      break;
+
+   case MESA_FORMAT_I8:
+      t->intel.texelBytes = 1;
+      textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
+      break;
+
+   case MESA_FORMAT_A8:
+      t->intel.texelBytes = 1;
+      textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */
+      break;
+
+   case MESA_FORMAT_AL88:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
+      break;
+
+   case MESA_FORMAT_RGB565:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+      break;
+
+   case MESA_FORMAT_ARGB1555:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
+      break;
+
+   case MESA_FORMAT_ARGB4444:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
+      break;
+
+   case MESA_FORMAT_ARGB8888:
+      t->intel.texelBytes = 4;
+      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+      break;
+
+   case MESA_FORMAT_YCBCR_REV:
+      t->intel.texelBytes = 2;
+      textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL | 
+                      TM0S1_COLORSPACE_CONVERSION);
+      break;
+
+   case MESA_FORMAT_YCBCR:
+      t->intel.texelBytes = 2;
+      textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
+                      TM0S1_COLORSPACE_CONVERSION);
+      break;
+
+   default:
+      fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
+      abort();
+   }
+
+   /* Compute which mipmap levels we really want to send 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.
+    * Yes, this looks overly complicated, but it's all needed.
+    */
+   driCalculateTextureFirstLastLevel( (driTextureObject *) t );
+
+
+   /* Figure out the amount of memory required to hold all the mipmap
+    * levels.  Choose the smallest pitch to accomodate the largest
+    * mipmap:
+    */
+   firstLevel = t->intel.base.firstLevel;
+   lastLevel = t->intel.base.lastLevel;
+   numLevels = lastLevel - firstLevel + 1;
+
+   /* Pitch would be subject to additional rules if texture memory were
+    * tiled.  Currently it isn't. 
+    */
+   if (0) {
+      pitch = 128;
+      while (pitch < tObj->Image[0][firstLevel]->Width * t->intel.texelBytes)
+        pitch *= 2;
+   }
+   else {
+      pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
+      pitch = (pitch + 3) & ~3;
+   }
+
+
+   /* All images must be loaded at this pitch.  Count the number of
+    * lines required:
+    */
+   for ( total_height = i = 0 ; i < numLevels ; i++ ) {
+      t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
+      if (!t->intel.image[0][i].image) 
+        break;
+      
+      t->intel.image[0][i].offset = total_height * pitch;
+      t->intel.image[0][i].internalFormat = baseImage->Format;
+      total_height += MAX2(2, t->intel.image[0][i].image->Height);
+   }
+
+   t->intel.Pitch = pitch;
+   t->intel.base.totalSize = total_height*pitch;
+   t->intel.max_level = i-1;
+   t->Setup[I830_TEXREG_TM0S1] = 
+      (((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
+       ((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
+       textureFormat);
+   t->Setup[I830_TEXREG_TM0S2] = 
+      (((pitch / 4) - 1) << TM0S2_PITCH_SHIFT);
+   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
+   t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
+   t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
+   t->intel.dirty = I830_UPLOAD_TEX_ALL;
+
+   return intelUploadTexImages( &i830->intel, &t->intel, 0 );
+}
+
+
+static void i830_import_tex_unit( i830ContextPtr i830, 
+                          i830TextureObjectPtr t,
+                          GLuint unit )
+{
+   if(INTEL_DEBUG&DEBUG_TEXTURE)
+      fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
+   
+   if (i830->intel.CurrentTexObj[unit]) 
+      i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
+
+   i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
+   t->intel.base.bound |= (1 << unit);
+
+   I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
+
+   i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 
+                                              (LOAD_TEXTURE_MAP0 << unit) | 4);
+   i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
+                                              t->intel.TextureOffset);
+
+   i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1];
+   i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2];
+
+   i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK;
+   i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] &
+                                               ~TM0S3_LOD_BIAS_MASK);
+
+   i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4];
+   i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] & 
+                                            ~MAP_UNIT_MASK);   
+   i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
+
+   t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
+}
+
+
+
+static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
+
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* Fallback if there's a texture border */
+   if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
+      fprintf(stderr, "Texture border\n");
+      return GL_FALSE;
+   }
+
+   /* Upload teximages (not pipelined)
+    */
+   if (t->intel.base.dirty_images[0]) {
+      if (!i830SetTexImages( i830, tObj )) {
+        return GL_FALSE;
+      }
+   }
+
+   /* Update state if this is a different texture object to last
+    * time.
+    */
+   if (i830->intel.CurrentTexObj[unit] != &t->intel || 
+       (t->intel.dirty & I830_UPLOAD_TEX(unit))) {
+      i830_import_tex_unit( i830, t, unit);
+   }
+
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
+
+   return GL_TRUE;
+}
+
+static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
+
+   mcs &= ~TEXCOORDS_ARE_NORMAL;
+   mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
+
+   if (mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) {
+      I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
+      i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
+   }
+
+   return GL_TRUE;
+}
+
+
+static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+   GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
+
+   mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
+   mcs |= TEXCOORDS_ARE_NORMAL;
+
+   if (mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) {
+      I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
+      i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
+{
+   i830ContextPtr i830 = I830_CONTEXT(ctx);
+
+   /* This is happening too often.  I need to conditionally send diffuse
+    * state to the card.  Perhaps a diffuse dirty flag of some kind.
+    * Will need to change this logic if more than 2 texture units are
+    * used.  We need to only do this up to the last unit enabled, or unit
+    * one if nothing is enabled.
+    */
+
+   if ( i830->intel.CurrentTexObj[unit] != NULL ) {
+      /* The old texture is no longer bound to this texture unit.
+       * Mark it as such.
+       */
+
+      i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
+      i830->intel.CurrentTexObj[unit] = NULL;
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
+{
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+   if (texUnit->_ReallyEnabled &&
+       INTEL_CONTEXT(ctx)->intelScreen->textureSize < 2048 * 1024)
+      return GL_FALSE;
+
+   if (texUnit->_ReallyEnabled == TEXTURE_1D_BIT ||
+       texUnit->_ReallyEnabled == TEXTURE_2D_BIT) {
+      return (enable_tex_common( ctx, unit ) &&
+             enable_tex_2d( ctx, unit ));
+   }
+   else if (texUnit->_ReallyEnabled == TEXTURE_RECT_BIT) {      
+      return (enable_tex_common( ctx, unit ) &&
+             enable_tex_rect( ctx, unit ));
+   }
+   else if (texUnit->_ReallyEnabled) {
+      return GL_FALSE;
+   }
+   else {
+      return disable_tex( ctx, unit );
+   }
+}
+
+
+void i830UpdateTextureState( intelContextPtr intel )
+{
+   i830ContextPtr i830 = I830_CONTEXT(intel);
+   GLcontext *ctx = &intel->ctx;
+   GLboolean ok;
+
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE);
+
+   ok = (i830UpdateTexUnit( ctx, 0 ) &&
+        i830UpdateTexUnit( ctx, 1 ) &&
+        i830UpdateTexUnit( ctx, 2 ) &&
+        i830UpdateTexUnit( ctx, 3 ));
+
+   FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok );
+
+   if (ok)
+      i830EmitTextureBlend( i830 );
+}
+
+
+
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
new file mode 100644 (file)
index 0000000..5fb436f
--- /dev/null
@@ -0,0 +1,426 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#include "i830_context.h"
+#include "i830_reg.h"
+
+#include "intel_batchbuffer.h"
+
+#include "tnl/t_context.h"
+#include "tnl/t_vertex.h"
+
+static GLboolean i830_check_vertex_size( intelContextPtr 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( intelContextPtr intel )
+{
+   GLcontext *ctx = &intel->ctx;
+   i830ContextPtr i830 = I830_CONTEXT(intel);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint index = tnl->render_inputs;
+   GLuint v0 = _3DSTATE_VFT0_CMD;
+   GLuint v2 = _3DSTATE_VFT1_CMD;
+   GLuint mcsb1 = 0;
+
+   /* 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 (index & _TNL_BITS_TEX_ANY) {
+      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;
+   }
+
+   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, VFT0_DIFFUSE );
+      
+   intel->specoffset = 0;
+   if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+      if (index & _TNL_BIT_COLOR1) {
+        intel->specoffset = intel->coloroffset + 1;
+        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, VFT0_SPEC );
+      }
+      else 
+        EMIT_PAD( 3 );
+      
+      if (index & _TNL_BIT_FOG)
+        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC );
+      else
+        EMIT_PAD( 1 );
+   }
+
+   if (index & _TNL_BITS_TEX_ANY) {
+      int i, count = 0;
+
+      for (i = 0; i < I830_TEX_UNITS; i++) {
+        if (index & _TNL_BIT_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: 
+           case 3:             /* XXX: fix for CUBE/VOLUME textures */
+              emit = EMIT_2F; 
+              sz = 2; 
+              mcs |= TEXCOORDTYPE_CARTESIAN; 
+              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] ||
+       index != i830->last_index) {
+    
+      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;
+      i830->last_index = index;
+
+      assert(i830_check_vertex_size( intel, intel->vertex_size ));
+   }
+}
+
+static void i830_reduced_primitive_state( intelContextPtr intel,
+                                         GLenum rprim )
+{
+    i830ContextPtr i830 = I830_CONTEXT(intel);
+    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]) {
+       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( intelContextPtr intel,
+                                        GLuint expected )
+{
+   i830ContextPtr i830 = I830_CONTEXT(intel);
+   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( intelContextPtr intel )
+{
+   BATCH_LOCALS;
+
+   BEGIN_BATCH( 200 );
+
+   OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
+   OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
+   OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
+   OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
+
+   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_SCISSOR_ENABLE_CMD | 
+            DISABLE_SCISSOR_RECT);
+
+   OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
+   OUT_BATCH(0);
+   OUT_BATCH(0);
+
+   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));                        \
+   for (k = 0 ; k < size / sizeof(GLuint) ; k++)       \
+      OUT_BATCH(state[k]);                             \
+   ADVANCE_BATCH();                                    \
+} while (0);
+
+
+/* Push the state into the sarea and/or texture memory.
+ */
+static void i830_emit_state( intelContextPtr intel )
+{
+   i830ContextPtr i830 = I830_CONTEXT(intel);
+   struct i830_hw_state *state = i830->current;
+   BATCH_LOCALS;
+   int i;
+   GLuint dirty = state->active & ~state->emitted;
+
+   if (dirty & I830_UPLOAD_CTX) {
+      if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n"); 
+      emit( i830, state->Ctx, sizeof(state->Ctx) );
+   }
+
+   if (dirty & I830_UPLOAD_BUFFERS) {
+      if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n"); 
+      emit( i830, state->Buffer, sizeof(state->Buffer) );
+   }
+
+   if (dirty & I830_UPLOAD_STIPPLE) {
+      if (VERBOSE) fprintf(stderr, "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))) { 
+        if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i); 
+        emit( i830, state->Tex[i], sizeof(state->Tex[i])); 
+      } 
+
+      if (dirty & I830_UPLOAD_TEXBLEND(i)) {
+        if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i); 
+        emit( i830, state->TexBlend[i], 
+              state->TexBlendWordsUsed[i] * 4 );
+      }
+   }
+
+   state->emitted |= dirty;
+}
+
+static void i830_destroy_context( intelContextPtr intel )
+{
+   _tnl_free_vertices(&intel->ctx);
+}
+
+static void i830_set_draw_offset( intelContextPtr intel, int offset )
+{
+   i830ContextPtr i830 = I830_CONTEXT(intel);
+   I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
+   i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset;
+}
+
+/* This isn't really handled at the moment.
+ */
+static void i830_lost_hardware( intelContextPtr intel )
+{
+   I830_CONTEXT(intel)->state.emitted = 0;
+}
+
+
+
+static void i830_emit_flush( intelContextPtr intel )
+{
+   BATCH_LOCALS;
+
+   BEGIN_BATCH(2);
+   OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE ); 
+   OUT_BATCH( 0 );
+   ADVANCE_BATCH();
+}
+
+
+
+
+void i830InitVtbl( i830ContextPtr i830 )
+{
+   i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj;
+   i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
+   i830->intel.vtbl.clear_with_tris = i830ClearWithTris;
+   i830->intel.vtbl.destroy = i830_destroy_context;
+   i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state;
+   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_offset = i830_set_draw_offset;
+   i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
+   i830->intel.vtbl.emit_flush = i830_emit_flush;
+   i830->intel.vtbl.render_start = i830_render_start;
+}
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
new file mode 100644 (file)
index 0000000..f2cdcfc
--- /dev/null
@@ -0,0 +1,211 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+
+static const char * const card_extensions[] =
+{
+   "GL_ARB_fragment_program",
+   "GL_ARB_texture_cube_map",
+   "GL_EXT_blend_equation_separate",
+   "GL_ATI_blend_equation_separate",
+   "GL_ARB_point_parameters",
+   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->nr_params)
+        p->params_uptodate = 0;
+   }
+
+}
+
+/* This is the extension list explicitly enabled by the client and
+ * excludes functionality available in Mesa and also excludes legacy
+ * extensions.  It is recognized that in an open source driver, those
+ * extensions will probably be re-enabled.
+ */
+static const GLubyte *i915GetString( GLcontext *ctx, GLenum name )
+{
+   if (name == GL_EXTENSIONS)
+      return 
+        "GL_ARB_fragment_program "
+        "GL_ARB_multitexture "
+        "GL_ARB_point_parameters "
+        "GL_ARB_texture_border_clamp "
+        "GL_ARB_texture_compression "
+        "GL_ARB_texture_cube_map "
+        "GL_ARB_texture_env_add "
+        "GL_ARB_texture_env_combine "
+        "GL_ARB_texture_env_dot3 "
+        "GL_ARB_texture_mirrored_repeat "
+        "GL_ARB_transpose_matrix "
+        "GL_ARB_vertex_buffer_object "
+        "GL_ARB_vertex_program "
+        "GL_ARB_window_pos "
+        "GL_EXT_abgr "
+        "GL_EXT_bgra "
+        "GL_EXT_blend_color "
+        "GL_EXT_blend_func_separate "
+        "GL_EXT_blend_minmax "
+        "GL_EXT_blend_subtract "
+        "GL_EXT_clip_volume_hint "
+        "GL_EXT_compiled_vertex_array "
+        "GL_EXT_draw_range_elements "
+        "GL_EXT_fog_coord "
+        "GL_EXT_multi_draw_arrays "
+        "GL_EXT_packed_pixels "
+        "GL_EXT_rescale_normal "
+        "GL_EXT_secondary_color "
+        "GL_EXT_separate_specular_color "
+        "GL_EXT_stencil_wrap "
+        "GL_EXT_texture3D "
+        "GL_EXT_texture_env_add "
+        "GL_EXT_texture_env_combine "
+        "GL_EXT_texture_filter_anisotropic "
+        "GL_IBM_texture_mirrored_repeat "
+        "GL_MESA_ycbcr_texture "
+        "GL_MESA_window_pos "
+        "GL_NV_texgen_reflection "
+        "GL_SGIS_generate_mipmap";
+
+   return intelGetString( ctx, name );
+}
+
+
+static void i915InitDriverFunctions( struct dd_function_table *functions )
+{
+   intelInitDriverFunctions( functions );
+   i915InitStateFunctions( functions );
+   i915InitTextureFuncs( functions );
+   i915InitFragProgFuncs( functions );
+   functions->UpdateState = i915InvalidateState;
+   functions->GetString = i915GetString;
+}
+
+
+
+GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
+                           __DRIcontextPrivate *driContextPriv,
+                           void *sharedContextPrivate)
+{
+   struct dd_function_table functions;
+   i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context);
+   intelContextPtr intel = &i915->intel;
+   GLcontext *ctx = &intel->ctx;
+
+   if (!i915) return GL_FALSE;
+
+   i915InitVtbl( 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;
+
+   intel->nr_heaps = 1;
+   intel->texture_heaps[0] = 
+      driCreateTextureHeap( 0, intel,
+                           intel->intelScreen->textureSize,
+                           12,
+                           I830_NR_TEX_REGIONS,
+                           intel->sarea->texList,
+                           & intel->sarea->texAge,
+                           & intel->swapped,
+                           sizeof( struct i915_texture_object ),
+                           (destroy_texture_object_t *)intelDestroyTexObj );
+
+   /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
+    * FIXME: packed, but they're not in Intel graphics hardware.
+    */
+   ctx->Const.MaxTextureUnits = 1;
+   driCalculateMaxTextureLevels( intel->texture_heaps,
+                                intel->nr_heaps,
+                                &intel->ctx.Const,
+                                4,
+                                11, /* max 2D texture size is 2048x2048 */
+                                8,  /* 3D texture */
+                                11, /* cube texture. */
+                                0,  /* max RECT. supported, but not enabled */
+                                12,
+                                GL_FALSE );
+   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.MaxFragmentProgramTemps = I915_MAX_TEMPORARY;
+   ctx->Const.MaxFragmentProgramAttribs = 11; /* 8 tex, 2 color, fog */
+   ctx->Const.MaxFragmentProgramLocalParams = I915_MAX_CONSTANT;
+   ctx->Const.MaxFragmentProgramEnvParams = I915_MAX_CONSTANT;
+   ctx->Const.MaxFragmentProgramAluInstructions = I915_MAX_ALU_INSN;
+   ctx->Const.MaxFragmentProgramTexInstructions = I915_MAX_TEX_INSN;
+   ctx->Const.MaxFragmentProgramInstructions = (I915_MAX_ALU_INSN + 
+                                               I915_MAX_TEX_INSN);
+   ctx->Const.MaxFragmentProgramTexIndirections = I915_MAX_TEX_INDIRECT;
+   ctx->Const.MaxFragmentProgramAddressRegs = 0; /* I don't think we have one */
+
+
+   driInitExtensions( ctx, card_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/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h
new file mode 100644 (file)
index 0000000..05863fa
--- /dev/null
@@ -0,0 +1,330 @@
+ /**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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_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_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_CBUFADDR2 2
+#define I915_DESTREG_DBUFADDR0 3
+#define I915_DESTREG_DBUFADDR1 4
+#define I915_DESTREG_DBUFADDR2 5
+#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_MS2        0
+#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_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 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;
+};
+
+
+
+
+
+
+struct i915_texture_object
+{
+   struct intel_texture_object intel;
+   GLenum lastTarget;
+   GLboolean refs_border_color;
+   GLuint Setup[I915_TEX_SETUP_SIZE];
+};
+
+#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 Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE];
+   GLuint Constant[I915_CONSTANT_SIZE];
+   GLuint ConstantSize;
+   GLuint Program[I915_PROGRAM_SIZE];
+   GLuint ProgramSize;
+   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;
+
+   struct i915_fragment_program tex_program;
+   struct i915_fragment_program *current_program;
+
+   struct i915_hw_state meta, initial, state, *current;
+};
+
+
+typedef struct i915_context *i915ContextPtr;
+typedef struct i915_texture_object *i915TextureObjectPtr;
+
+#define I915_CONTEXT(ctx)      ((i915ContextPtr)(ctx))
+
+
+
+#define I915_STATECHANGE(i915, flag)                                   \
+do {                                                                   \
+   if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__);  \
+   INTEL_FIREVERTICES( &(i915)->intel );                                       \
+   (i915)->state.emitted &= ~(flag);                                   \
+} while (0)
+
+#define I915_ACTIVESTATE(i915, flag, mode)                     \
+do {                                                           \
+   if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n",    \
+                 flag, mode, __FUNCTION__);                    \
+   INTEL_FIREVERTICES( &(i915)->intel );                               \
+   if (mode)                                                   \
+      (i915)->state.active |= (flag);                          \
+   else                                                                \
+      (i915)->state.active &= ~(flag);                         \
+} while (0)
+
+
+/*======================================================================
+ * i915_vtbl.c
+ */
+extern void i915InitVtbl( i915ContextPtr i915 );
+
+
+
+#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( i915ContextPtr 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( i915ContextPtr i915 );
+
+
+/*======================================================================
+ * i915_tex.c
+ */
+extern void i915UpdateTextureState( intelContextPtr intel );
+extern void i915InitTextureFuncs( struct dd_function_table *functions );
+extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
+
+/*======================================================================
+ * i915_metaops.c
+ */
+extern GLboolean
+i915TryTextureReadPixels( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *pack,
+                         GLvoid *pixels );
+
+extern GLboolean
+i915TryTextureDrawPixels( GLcontext *ctx,
+                         GLint x, GLint y, GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *unpack,
+                         const GLvoid *pixels );
+
+extern void 
+i915ClearWithTris( intelContextPtr intel, GLbitfield mask,
+                  GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
+
+
+/*======================================================================
+ * i915_fragprog.c
+ */
+extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
+extern void i915InitFragProgFuncs( struct dd_function_table *functions );
+       
+#endif
+
diff --git a/src/mesa/drivers/dri/i915/i915_debug.c b/src/mesa/drivers/dri/i915/i915_debug.c
new file mode 100644 (file)
index 0000000..c67e0d4
--- /dev/null
@@ -0,0 +1,272 @@
+#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 (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/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
new file mode 100644 (file)
index 0000000..f9c80cb
--- /dev/null
@@ -0,0 +1,1033 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+#include "nvfragprog.h"
+#include "program.h"
+#include "arbfragparse.h"
+
+
+
+
+#define PI 3.141592
+
+
+/* 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 fp_src_register *source,
+                         const struct 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->Parameters->Parameters[source->Index].Values );
+        break;
+
+      default:
+        i915_program_error( p, "Bad source->File" ); 
+        return 0;
+   }
+
+   src = swizzle(src, 
+                source->Swizzle[0],
+                source->Swizzle[1],
+                source->Swizzle[2],
+                source->Swizzle[3]);
+
+   if (source->NegateBase)
+      src = negate( src, 1,1,1,1 );
+
+   return src;
+}
+
+
+static GLuint get_result_vector( struct i915_fragment_program *p,
+                                const struct fp_instruction *inst )
+{
+   switch (inst->DstReg.File) {
+   case PROGRAM_OUTPUT:
+      switch (inst->DstReg.Index) {
+      case 0: 
+        return UREG(REG_TYPE_OC, 0);
+      case 1: 
+        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 fp_instruction *inst )
+{
+   GLuint flags = 0;
+
+   if (inst->Saturate) flags |= A0_DEST_SATURATE;
+   if (inst->DstReg.WriteMask[0]) flags |= A0_DEST_CHANNEL_X;
+   if (inst->DstReg.WriteMask[1]) flags |= A0_DEST_CHANNEL_Y;
+   if (inst->DstReg.WriteMask[2]) flags |= A0_DEST_CHANNEL_Z;
+   if (inst->DstReg.WriteMask[3]) flags |= A0_DEST_CHANNEL_W;
+
+   return flags;
+}
+
+static GLuint translate_tex_src_bit( struct i915_fragment_program *p,
+                                    GLubyte bit )
+{
+   switch (bit) {
+   case TEXTURE_1D_BIT:   return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_2D_BIT:   return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_RECT_BIT: return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_3D_BIT:   return D0_SAMPLE_TYPE_VOLUME;
+   case TEXTURE_CUBE_BIT: return D0_SAMPLE_TYPE_CUBE;
+   default: i915_program_error(p, "TexSrcBit"); return 0;
+   }
+}
+
+#define EMIT_TEX( OP )                                         \
+do {                                                           \
+   GLuint dim = translate_tex_src_bit( p, inst->TexSrcBit );   \
+   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 fragment_program *program = p->ctx->FragmentProgram.Current;
+   const struct fp_instruction *inst = program->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 == FP_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 FP_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 FP_OPCODE_ADD: 
+        EMIT_2ARG_ARITH( A0_ADD );
+        break;
+
+      case FP_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 FP_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/(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, (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 FP_OPCODE_DP3: 
+        EMIT_2ARG_ARITH( A0_DP3 );
+        break;
+
+      case FP_OPCODE_DP4: 
+        EMIT_2ARG_ARITH( A0_DP4 );
+        break;
+
+      case FP_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 FP_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 FP_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 FP_OPCODE_FLR: 
+        EMIT_1ARG_ARITH( A0_FLR );
+        break;
+
+      case FP_OPCODE_FRC: 
+        EMIT_1ARG_ARITH( A0_FRC );
+        break;
+
+      case FP_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 FP_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 FP_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 FP_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 FP_OPCODE_MAD:
+        EMIT_3ARG_ARITH( A0_MAD );
+        break;
+
+      case FP_OPCODE_MAX:
+        EMIT_2ARG_ARITH( A0_MAX );
+        break;
+
+      case FP_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 FP_OPCODE_MOV: 
+        EMIT_1ARG_ARITH( A0_MOV );
+        break;
+
+      case FP_OPCODE_MUL: 
+        EMIT_2ARG_ARITH( A0_MUL );
+        break;
+
+      case FP_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 FP_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 FP_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 FP_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[1]) {
+           GLuint tmp1;
+           
+           if (inst->DstReg.WriteMask[0])
+              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[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 ), 
+                           A0_DEST_CHANNEL_X, 0,
+                           swizzle(tmp, ONE,Z,Y,X), 
+                           i915_emit_const4fv( p, cos_constants ), 0);
+        }
+        break;
+
+      case FP_OPCODE_SGE: 
+        EMIT_2ARG_ARITH( A0_SGE );
+        break;
+
+      case FP_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/(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, (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 FP_OPCODE_SLT: 
+        EMIT_2ARG_ARITH( A0_SLT );
+        break;
+
+      case FP_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 FP_OPCODE_SWZ: 
+        EMIT_1ARG_ARITH( A0_MOV ); /* extended swizzle handled natively */
+        break;
+
+      case FP_OPCODE_TEX: 
+        EMIT_TEX( T0_TEXLD );
+        break;
+
+      case FP_OPCODE_TXB:
+        EMIT_TEX( T0_TEXLDB );
+        break;
+
+      case FP_OPCODE_TXP:
+        EMIT_TEX( T0_TEXLDP );
+        break;
+
+      case FP_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 FP_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.InputsRead;
+   GLint i;
+
+   p->wpos_tex = 0;
+
+   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 )
+{
+   i915ContextPtr 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.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 program *prog )
+{
+   if (target == GL_FRAGMENT_PROGRAM_ARB) {
+      i915ContextPtr 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 program *i915NewProgram( GLcontext *ctx,
+                                     GLenum target, 
+                                     GLuint id )
+{
+   switch (target) {
+   case GL_VERTEX_PROGRAM_ARB:
+      return _mesa_init_vertex_program( ctx, CALLOC_STRUCT(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;
+   }
+
+   case GL_FRAGMENT_PROGRAM_NV:
+   default:
+      _mesa_problem(ctx, "bad target in _mesa_new_program");
+      return NULL;
+   }
+}
+
+static void i915DeleteProgram( GLcontext *ctx,
+                             struct program *prog )
+{
+   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
+      i915ContextPtr 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 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 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 );
+   }
+}
+
+
+void i915ValidateFragmentProgram( i915ContextPtr i915 )
+{
+   GLcontext *ctx = &i915->intel.ctx;
+   intelContextPtr 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;
+
+   GLuint inputsRead = p->FragProg.InputsRead;
+   GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
+   GLuint s2 = S2_TEXCOORD_NONE;
+   int i, offset = 0;
+
+   /* 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_RGBA, S4_VFMT_COLOR, 4 );
+   }
+   
+   if (inputsRead & FRAG_BIT_COL1) {
+      intel->specoffset = offset / 4;
+      EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, S4_VFMT_SPEC_FOG, 3 );
+      EMIT_PAD( 1 );
+   }
+
+   if (inputsRead & FRAG_BIT_FOGC) {
+      EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4 );
+   }
+
+   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]) {
+    
+      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;
+
+      assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
+   }
+
+   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/i915/i915_metaops.c b/src/mesa/drivers/dri/i915/i915_metaops.c
new file mode 100644 (file)
index 0000000..4c620cb
--- /dev/null
@@ -0,0 +1,494 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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 "i915_context.h"
+#include "i915_reg.h"
+
+/* A large amount of state doesn't need to be uploaded.
+ */
+#define ACTIVE (I915_UPLOAD_PROGRAM |          \
+               I915_UPLOAD_STIPPLE |           \
+               I915_UPLOAD_CTX |               \
+               I915_UPLOAD_BUFFERS |           \
+               I915_UPLOAD_TEX(0))             
+
+#define SET_STATE( i915, STATE )                       \
+do {                                           \
+   i915->current->emitted &= ~ACTIVE;          \
+   i915->current = &i915->STATE;                       \
+   i915->current->emitted &= ~ACTIVE;          \
+} while (0)
+
+/* 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 set_initial_state( i915ContextPtr i915 )
+{
+   memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
+   i915->meta.active = ACTIVE;
+   i915->meta.emitted = 0;
+}
+
+
+static void set_no_depth_stencil_write( i915ContextPtr i915 )
+{
+   /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE | 
+                                      S5_STENCIL_WRITE_ENABLE);
+
+   /* 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;
+}
+
+/* Set stencil unit to replace always with the reference value.
+ */
+static void set_stencil_replace( i915ContextPtr i915,
+                                GLuint s_mask,
+                                GLuint s_clear)
+{
+   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.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
+    */
+   i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
+                                      S6_DEPTH_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 set_color_mask( i915ContextPtr i915, GLboolean state )
+{
+   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;
+}
+
+
+
+
+#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 set_no_texture( i915ContextPtr i915 )
+{
+   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 enable_texture_blend_replace( i915ContextPtr i915 )
+{
+   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 void set_tex_rect_source( i915ContextPtr i915,
+                                GLuint offset,
+                                GLuint width, 
+                                GLuint height,
+                                GLuint pitch,
+                                GLuint textureFormat )
+{
+   GLuint unit = 0;
+   GLint numLevels = 1;
+   GLuint *state = i915->meta.Tex[0];
+
+   pitch *= i915->intel.intelScreen->cpp;
+
+/*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
+/*        __FUNCTION__, offset, width, height, pitch, textureFormat ); */
+
+   state[I915_TEXREG_MS2] = offset;
+   state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
+                           ((width - 1) << MS3_WIDTH_SHIFT) |
+                           textureFormat |
+                           MS3_USE_FENCE_REGS);
+
+   state[I915_TEXREG_MS4] = ((((pitch / 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);
+}
+
+
+/* Select between front and back draw buffers.
+ */
+static void set_draw_offset( i915ContextPtr i915,
+                            GLuint offset )
+{
+   i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
+   i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
+}
+
+/* Setup an arbitary draw format, useful for targeting texture or agp
+ * memory.
+ */
+static void set_draw_format( i915ContextPtr i915,
+                            GLuint format,
+                            GLuint depth_format)
+{
+   i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
+                                       DSTORG_VERT_BIAS(0x8) | /* .5 */
+                                       format |
+                                       LOD_PRECLAMP_OGL |
+                                       TEX_DEFAULT_COLOR_OGL |
+                                       depth_format);
+
+   i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
+/*    fprintf(stderr, "%s: DV1: %x\n",  */
+/*        __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
+}
+
+static void set_vertex_format( i915ContextPtr i915 )
+{
+   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_SPEC_FOG |
+       S4_VFMT_XYZW);
+
+   i915->meta.emitted &= ~I915_UPLOAD_CTX;
+
+}
+
+
+static void draw_quad(i915ContextPtr i915, 
+                     GLfloat x0, GLfloat x1,
+                     GLfloat y0, GLfloat y1, 
+                     GLubyte red, GLubyte green,
+                     GLubyte blue, GLubyte alpha,
+                     GLfloat s0, GLfloat s1,
+                     GLfloat t0, GLfloat t1 )
+{
+   GLuint vertex_size = 8;
+   GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel, 
+                                               PRIM3D_TRIFAN, 
+                                               4 * vertex_size,
+                                               vertex_size );
+   intelVertex tmp;
+   int i;
+
+   if (0)
+      fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
+             __FUNCTION__,
+             x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
+
+
+   /* initial vertex, left bottom */
+   tmp.v.x = x0;
+   tmp.v.y = y0;
+   tmp.v.z = 1.0;
+   tmp.v.w = 1.0; 
+   tmp.v.color.red = red;
+   tmp.v.color.green = green;
+   tmp.v.color.blue = blue;
+   tmp.v.color.alpha = alpha;
+   tmp.v.specular.red = 0;
+   tmp.v.specular.green = 0;
+   tmp.v.specular.blue = 0;
+   tmp.v.specular.alpha = 0;
+   tmp.v.u0 = s0;
+   tmp.v.v0 = t0;
+
+   for (i = 0 ; i < vertex_size ; i++)
+      vb[i] = tmp.ui[i];
+
+   /* right bottom */
+   vb += vertex_size;
+   tmp.v.x = x1;
+   tmp.v.u0 = s1;
+   for (i = 0 ; i < vertex_size ; i++)
+      vb[i] = tmp.ui[i];
+
+   /* right top */
+   vb += vertex_size;
+   tmp.v.y = y1;
+   tmp.v.v0 = t1;
+   for (i = 0 ; i < vertex_size ; i++)
+      vb[i] = tmp.ui[i];
+
+   /* left top */
+   vb += vertex_size;
+   tmp.v.x = x0;
+   tmp.v.u0 = s0;
+   for (i = 0 ; i < vertex_size ; i++)
+      vb[i] = tmp.ui[i];
+}
+
+void 
+i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
+                 GLboolean all,
+                 GLint cx, GLint cy, GLint cw, GLint ch)
+{
+   i915ContextPtr i915 = I915_CONTEXT( intel );
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   intelScreenPrivate *screen = intel->intelScreen;
+   int x0, y0, x1, y1;
+
+   SET_STATE( i915, meta ); 
+   set_initial_state( i915 ); 
+   set_no_texture( i915 ); 
+   set_vertex_format( i915 ); 
+
+   LOCK_HARDWARE(intel);
+
+   if(!all) {
+      x0 = cx;
+      y0 = cy;
+      x1 = x0 + cw;
+      y1 = y0 + ch;
+   } else {
+      x0 = 0;
+      y0 = 0;
+      x1 = x0 + dPriv->w;
+      y1 = y0 + dPriv->h;
+   }
+
+   /* Don't do any clipping to screen - these are window coordinates.
+    * The active cliprects will be applied as for any other geometry.
+    */
+
+   if (mask & DD_FRONT_LEFT_BIT) { 
+      set_no_depth_stencil_write( i915 );
+      set_color_mask( i915, GL_TRUE );
+      set_draw_offset( i915, screen->frontOffset );
+
+      draw_quad(i915, x0, x1, y0, y1,
+               intel->clear_red, intel->clear_green, 
+               intel->clear_blue, intel->clear_alpha, 
+               0, 0, 0, 0);
+   }
+
+   if(mask & DD_BACK_LEFT_BIT) {
+      set_no_depth_stencil_write( i915 );
+      set_color_mask( i915, GL_TRUE );
+      set_draw_offset( i915, screen->backOffset );
+
+      draw_quad(i915, x0, x1, y0, y1,
+               intel->clear_red, intel->clear_green,
+               intel->clear_blue, intel->clear_alpha,
+               0, 0, 0, 0);
+   }
+
+   if(mask & DD_STENCIL_BIT) {
+      set_stencil_replace( i915, 
+                          intel->ctx.Stencil.WriteMask[0], 
+                          intel->ctx.Stencil.Clear);
+      
+      set_color_mask( i915, GL_FALSE );
+      set_draw_offset( i915, screen->frontOffset ); /* could be either? */
+
+      draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
+   }
+
+   UNLOCK_HARDWARE(intel);
+
+   SET_STATE( i915, state );
+}
+
+
diff --git a/src/mesa/drivers/dri/i915/i915_program.c b/src/mesa/drivers/dri/i915/i915_program.c
new file mode 100644 (file)
index 0000000..03baa16
--- /dev/null
@@ -0,0 +1,446 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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);
+   assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(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 )
+{
+   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 ) |
+                 destmask |
+                 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 GLubyte *msg )
+{
+   fprintf(stderr, "%s\n", msg);
+   p->error = 1;
+}
+
+void i915_init_program( i915ContextPtr 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 = 0;
+   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");
+
+   p->declarations[0] |= program_size + decl_size - 2;
+}
+
+void i915_upload_program( i915ContextPtr 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/i915/i915_program.h b/src/mesa/drivers/dri/i915/i915_program.h
new file mode 100644 (file)
index 0000000..7ed2e84
--- /dev/null
@@ -0,0 +1,143 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#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 GLubyte *msg );
+
+extern void i915_init_program( i915ContextPtr i915,
+                             struct i915_fragment_program *p );
+
+extern void i915_upload_program( i915ContextPtr i915, 
+                               struct i915_fragment_program *p );
+
+extern void i915_fini_program( struct i915_fragment_program *p );
+
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/i915_reg.h b/src/mesa/drivers/dri/i915/i915_reg.h
new file mode 100644 (file)
index 0000000..c5a93cb
--- /dev/null
@@ -0,0 +1,859 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#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 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 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 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 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 */
+
+
+/* _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                   ((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)<<8)
+#define MODE4_ENABLE_STENCIL_WRITE_MASK        ((1<<16)|(0x00ff))
+#define ENABLE_STENCIL_WRITE_MASK      (1<<16)
+#define STENCIL_WRITE_MASK(x)          (x)
+
+/* _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_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_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)
+#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)
+#define   SHADOWOP_ALWAYS               0
+#define   SHADOWOP_NEVER                1
+#define   SHADOWOP_LESS                 2
+#define   SHADOWOP_EQUAL                3
+#define   SHADOWOP_LEQUAL               4
+#define   SHADOWOP_GREATER              5
+#define   SHADOWOP_NOTEQUAL             6
+#define   SHADOWOP_GEQUAL               7
+
+#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 MI_FLUSH           ((0<<29)|(4<<23))
+#define FLUSH_MAP_CACHE    (1<<0)
+#define FLUSH_RENDER_CACHE (1<<1)
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/i915_state.c b/src/mesa/drivers/dri/i915/i915_state.c
new file mode 100644 (file)
index 0000000..d6c3e90
--- /dev/null
@@ -0,0 +1,1073 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#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_screen.h"
+#include "intel_batchbuffer.h"
+
+#include "i915_context.h"
+#include "i915_reg.h"
+
+static int 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: 
+   default:
+      return COMPAREFUNC_ALWAYS; 
+   }
+}
+
+
+static void i915StencilFunc(GLcontext *ctx, GLenum func, GLint ref,
+                           GLuint mask)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   int test = translate_compare_func( func );
+
+   mask = mask & 0xff;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 i915StencilMask(GLcontext *ctx, GLuint mask)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 int 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 0;
+   }
+}
+
+static void i915StencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
+                         GLenum zpass)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   int fop = translate_stencil_op(fail); 
+   int dfop = translate_stencil_op(zfail); 
+   int dpop = translate_stencil_op(zpass);
+
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   int test = 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)
+{
+   i915ContextPtr 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])
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   GLubyte r, g, b, a;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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;
+}
+
+static int 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;
+   default:
+      return BLENDFACT_ZERO;
+   }
+}
+
+#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 )
+{
+   i915ContextPtr 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(translate_blend_factor(srcRGB)); 
+   lis6 |= DST_BLND_FACT(translate_blend_factor(dstRGB)); 
+   lis6 |= translate_blend_equation( eqRGB ) << S6_CBUF_BLEND_FUNC_SHIFT;
+
+   iab |= SRC_ABLND_FACT(translate_blend_factor(srcA)); 
+   iab |= DST_ABLND_FACT(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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   int test = translate_compare_func( func );
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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 )
+{
+   i915ContextPtr 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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   intelScreenPrivate *screen = i915->intel.intelScreen;
+   int x1, y1, x2, y2;
+
+   if (!i915->intel.driDrawable)
+      return;
+
+   x1 = x;
+   y1 = i915->intel.driDrawable->h - (y + h);
+   x2 = x + w - 1;
+   y2 = y1 + h - 1;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
+             x, y, w, h);
+
+   if (x1 < 0) x1 = 0;
+   if (y1 < 0) y1 = 0;
+   if (x2 < 0) x2 = 0;
+   if (y2 < 0) y2 = 0;
+
+   if (x2 >= screen->width) x2 = screen->width-1;
+   if (y2 >= screen->height) y2 = screen->height-1;
+   if (x1 >= screen->width) x1 = screen->width-1;
+   if (y1 >= screen->height) y1 = screen->height-1;
+
+
+   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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   int tmp = 0;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   switch(opcode) {
+   case GL_CLEAR: 
+      tmp = LOGICOP_CLEAR; 
+      break;
+   case GL_AND: 
+      tmp = LOGICOP_AND; 
+      break;
+   case GL_AND_REVERSE: 
+      tmp = LOGICOP_AND_RVRSE; 
+      break;
+   case GL_COPY: 
+      tmp = LOGICOP_COPY; 
+      break;
+   case GL_COPY_INVERTED: 
+      tmp = LOGICOP_COPY_INV; 
+      break;
+   case GL_AND_INVERTED: 
+      tmp = LOGICOP_AND_INV; 
+      break;
+   case GL_NOOP: 
+      tmp = LOGICOP_NOOP; 
+      break;
+   case GL_XOR: 
+      tmp = LOGICOP_XOR; 
+      break;
+   case GL_OR: 
+      tmp = LOGICOP_OR; 
+      break;
+   case GL_OR_INVERTED: 
+      tmp = LOGICOP_OR_INV; 
+      break;
+   case GL_NOR: 
+      tmp = LOGICOP_NOR; 
+      break;
+   case GL_EQUIV: 
+      tmp = LOGICOP_EQUIV; 
+      break;
+   case GL_INVERT: 
+      tmp = LOGICOP_INV; 
+      break;
+   case GL_OR_REVERSE: 
+      tmp = LOGICOP_OR_RVRSE; 
+      break;
+   case GL_NAND: 
+      tmp = LOGICOP_NAND; 
+      break;
+   case GL_SET: 
+      tmp = LOGICOP_SET; 
+      break;
+   default:
+      return;
+   }
+
+   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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   GLuint mode;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (!ctx->Polygon.CullFlag) {
+      mode = S4_CULLMODE_NONE;
+   }
+   else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
+      mode = S4_CULLMODE_CW;
+
+      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 )
+{
+   i915ContextPtr i915 = I915_CONTEXT( ctx );
+   int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
+   int width;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
+   GLint point_size = (int)size;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+     fprintf(stderr, "%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)
+{
+   i915ContextPtr i915 = I915_CONTEXT( ctx );
+   GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK;
+
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%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)
+{
+   if (INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+      update_specular( ctx );
+   }
+}
+
+static void i915ShadeModel(GLcontext *ctx, GLenum mode)
+{
+   i915ContextPtr 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
+ */
+static void update_fog( GLcontext *ctx )
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   GLenum mode;
+   GLboolean enabled;
+   GLboolean try_pixel_fog;
+   
+   if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) {
+      /* Pull in static fog state from program */
+      
+      mode = ctx->FragmentProgram.Current->FogOption;
+      enabled = (mode != GL_NONE);
+      try_pixel_fog = 1;
+   }
+   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)
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+
+   switch (pname) {
+   case GL_FOG_COORDINATE_SOURCE_EXT: 
+   case GL_FOG_MODE:
+   case GL_FOG_START:
+   case GL_FOG_END: 
+      update_fog( ctx );
+      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:
+      update_fog( ctx );
+      break;
+   default:
+      break;
+   }
+}
+
+/* =============================================================
+ */
+
+static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+   i915ContextPtr 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)
+        FALLBACK( &i915->intel, I915_FALLBACK_LOGICOP, state );
+      break;
+
+   case GL_FRAGMENT_PROGRAM_ARB:
+      update_fog( ctx );
+      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:
+      update_fog( ctx );
+      break;
+
+   case GL_CULL_FACE:
+      i915CullFaceFrontFace(ctx, 0);
+      break;
+
+   case GL_STENCIL_TEST:
+      if (i915->intel.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;
+
+   default:
+      ;
+   }
+}
+
+
+static void i915_init_packets( i915ContextPtr 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)
+        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);
+      i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+      i915->state.Buffer[I915_DESTREG_CBUFADDR1] = 
+        (BUF_3D_ID_COLOR_BACK | 
+         BUF_3D_PITCH(screen->frontPitch * screen->cpp) |
+         BUF_3D_USE_FENCE);
+
+
+      i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
+      i915->state.Buffer[I915_DESTREG_DBUFADDR1] = 
+        (BUF_3D_ID_DEPTH |
+         BUF_3D_PITCH(screen->depthPitch * screen->cpp) |
+         BUF_3D_USE_FENCE);
+      i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depthOffset;
+
+
+      i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
+
+      switch (screen->fbFormat) {
+      case DV_PF_555:
+      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;
+      }
+      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;
+   }
+
+
+   /* 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);
+}
+
+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->StencilFunc = i915StencilFunc;
+   functions->StencilMask = i915StencilMask;
+   functions->StencilOp = i915StencilOp;
+}
+
+
+void i915InitState( i915ContextPtr 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/i915/i915_tex.c b/src/mesa/drivers/dri/i915/i915_tex.c
new file mode 100644 (file)
index 0000000..8d37151
--- /dev/null
@@ -0,0 +1,155 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+
+
+
+
+
+/**
+ * Allocate space for and load the mesa images into the texture memory block.
+ * This will happen before drawing with a new texture, or drawing with a
+ * texture after it was swapped out or teximaged again.
+ */
+
+intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj )
+{
+   i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object );
+   if ( !t ) 
+      return NULL;
+
+   texObj->DriverData = t;
+   t->intel.base.tObj = texObj;
+   t->intel.dirty = I915_UPLOAD_TEX_ALL;
+   make_empty_list( &t->intel.base );
+   return &t->intel;
+}
+
+
+static void i915TexParameter( GLcontext *ctx, GLenum target,
+                            struct gl_texture_object *tObj,
+                            GLenum pname, const GLfloat *params )
+{
+   i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
+   switch (pname) {
+   case GL_TEXTURE_MIN_FILTER:
+   case GL_TEXTURE_MAG_FILTER:
+   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+   case GL_TEXTURE_WRAP_S:
+   case GL_TEXTURE_WRAP_T:
+   case GL_TEXTURE_WRAP_R:
+   case GL_TEXTURE_BORDER_COLOR:
+      t->intel.dirty = I915_UPLOAD_TEX_ALL;
+      break;
+
+   case GL_TEXTURE_BASE_LEVEL:
+   case GL_TEXTURE_MAX_LEVEL:
+   case GL_TEXTURE_MIN_LOD:
+   case GL_TEXTURE_MAX_LOD:
+      /* The i915 and its successors can do a lot of this without
+       * reloading the textures.  A project for someone?
+       */
+      intelFlush( ctx );
+      driSwapOutTextureObject( (driTextureObject *) t );
+      t->intel.dirty = I915_UPLOAD_TEX_ALL;
+      break;
+
+   default:
+      return;
+   }
+}
+
+
+static void i915TexEnv( GLcontext *ctx, GLenum target, 
+                       GLenum pname, const GLfloat *param )
+{
+   i915ContextPtr i915 = I915_CONTEXT( ctx );
+   GLuint unit = ctx->Texture.CurrentUnit;
+
+   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: {
+      int b = (int) ((*param) * 16.0);
+      if (b > 255) b = 255;
+      if (b < -256) b = -256;
+      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
+      i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK;
+      i915->state.Tex[unit][I915_TEXREG_SS2] |= 
+        ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
+      break;
+   }
+
+   default:
+      break;
+   }
+}
+
+
+static void i915BindTexture( GLcontext *ctx, GLenum target,
+                           struct gl_texture_object *texObj )
+{
+   i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData;
+
+   if (tex->lastTarget != texObj->Target) {
+      tex->intel.dirty = I915_UPLOAD_TEX_ALL;
+      tex->lastTarget = texObj->Target;
+   }
+
+   /* 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;
+   functions->TexParameter = i915TexParameter;
+}
diff --git a/src/mesa/drivers/dri/i915/i915_texprog.c b/src/mesa/drivers/dri/i915/i915_texprog.c
new file mode 100644 (file)
index 0000000..33132df
--- /dev/null
@@ -0,0 +1,635 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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"
+
+static GLuint translate_tex_src_bit( struct i915_fragment_program *p,
+                                    GLubyte bit )
+{
+   switch (bit) {
+   case TEXTURE_1D_BIT:   return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_2D_BIT:   return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_RECT_BIT: return D0_SAMPLE_TYPE_2D;
+   case TEXTURE_3D_BIT:   return D0_SAMPLE_TYPE_VOLUME;
+   case TEXTURE_CUBE_BIT: return D0_SAMPLE_TYPE_CUBE;
+   default: i915_program_error(p, "TexSrcBit"); return 0;
+   }
+}
+
+static GLuint get_source( struct i915_fragment_program *p, 
+                         GLenum src, GLuint unit )
+{
+   switch (src) {
+   case GL_TEXTURE: 
+      if (p->src_texture == UREG_BAD) {
+
+        /* TODO: Use D0_CHANNEL_XY where possible.
+         */
+        GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled);
+        GLuint sampler = i915_emit_decl(p, REG_TYPE_S, unit, dim);
+        GLuint texcoord = i915_emit_decl(p, REG_TYPE_T, unit, D0_CHANNEL_ALL);
+        GLuint tmp = i915_get_temp( p );
+        GLuint op = T0_TEXLD;
+
+        if (p->VB->TexCoordPtr[unit]->size == 4)
+           op = T0_TEXLDP;
+
+        p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, 
+                                         sampler, texcoord, op );
+      }
+
+      return p->src_texture;
+   case GL_CONSTANT:
+      return i915_emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor );
+   case GL_PRIMARY_COLOR:
+      return i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
+   case GL_PREVIOUS:
+   default: 
+      i915_emit_decl(p, 
+               GET_UREG_TYPE(p->src_previous),
+               GET_UREG_NR(p->src_previous), D0_CHANNEL_ALL); 
+      return p->src_previous;
+   }
+}
+                       
+
+static GLuint emit_combine_source( struct i915_fragment_program *p, 
+                                  GLuint mask,
+                                  GLuint unit,
+                                  GLenum source, 
+                                  GLenum operand )
+{
+   GLuint arg, src;
+
+   src = get_source(p, source, unit);
+
+   switch (operand) {
+   case GL_ONE_MINUS_SRC_COLOR: 
+      /* Get unused tmp,
+       * Emit tmp = 1.0 + arg.-x-y-z-w
+       */
+      arg = i915_get_temp( p );
+      return i915_emit_arith( p, A0_ADD, arg, mask, 0,
+                 swizzle(src, ONE, ONE, ONE, ONE ),
+                 negate(src, 1,1,1,1), 0);
+
+   case GL_SRC_ALPHA: 
+      if (mask == A0_DEST_CHANNEL_W)
+        return src;
+      else
+        return swizzle( src, W, W, W, W );
+   case GL_ONE_MINUS_SRC_ALPHA: 
+      /* Get unused tmp,
+       * Emit tmp = 1.0 + arg.-w-w-w-w
+       */
+      arg = i915_get_temp( p );
+      return i915_emit_arith( p, A0_ADD, arg, mask, 0,
+                        swizzle(src, ONE, ONE, ONE, ONE ),
+                        negate( swizzle(src,W,W,W,W), 1,1,1,1), 0);
+   case GL_SRC_COLOR: 
+   default:
+      return src;
+   }
+}
+
+
+
+static int nr_args( GLenum mode )
+{
+   switch (mode) {
+   case GL_REPLACE: return 1; 
+   case GL_MODULATE: return 2;
+   case GL_ADD: return 2;
+   case GL_ADD_SIGNED: return 2;
+   case GL_INTERPOLATE:        return 3;
+   case GL_SUBTRACT: return 2;
+   case GL_DOT3_RGB_EXT: return 2;
+   case GL_DOT3_RGBA_EXT: return 2;
+   case GL_DOT3_RGB: return 2;
+   case GL_DOT3_RGBA: return 2;
+   default: return 0;
+   }
+}
+
+
+static GLboolean args_match( struct gl_texture_unit *texUnit )
+{
+   int i, nr = nr_args(texUnit->Combine.ModeRGB);
+
+   for (i = 0 ; i < nr ; i++) {
+      if (texUnit->Combine.SourceA[i] != texUnit->Combine.SourceRGB[i]) 
+        return GL_FALSE;
+
+      switch(texUnit->Combine.OperandA[i]) {
+      case GL_SRC_ALPHA: 
+        switch(texUnit->Combine.OperandRGB[i]) {
+        case GL_SRC_COLOR: 
+        case GL_SRC_ALPHA: 
+           break;
+        default:
+           return GL_FALSE;
+        }
+        break;
+      case GL_ONE_MINUS_SRC_ALPHA: 
+        switch(texUnit->Combine.OperandRGB[i]) {
+        case GL_ONE_MINUS_SRC_COLOR: 
+        case GL_ONE_MINUS_SRC_ALPHA: 
+           break;
+        default:
+           return GL_FALSE;
+        }
+        break;
+      default: 
+        return GL_FALSE;       /* impossible */
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
+static GLuint emit_combine( struct i915_fragment_program *p,
+                           GLuint dest,
+                           GLuint mask,
+                           GLuint saturate,
+                           GLuint unit,
+                           GLenum mode,
+                           const GLenum *source,
+                           const GLenum *operand)
+{
+   int tmp, src[3], nr = nr_args(mode);
+   int i;
+
+   for (i = 0; i < nr; i++)
+      src[i] = emit_combine_source( p, mask, unit, source[i], operand[i] );
+
+   switch (mode) {
+   case GL_REPLACE: 
+      if (mask == A0_DEST_CHANNEL_ALL && !saturate)
+        return src[0];
+      else
+        return i915_emit_arith( p, A0_MOV, dest, mask, saturate, src[0], 0, 0 );
+   case GL_MODULATE: 
+      return i915_emit_arith( p, A0_MUL, dest, mask, saturate,
+                            src[0], src[1], 0 );
+   case GL_ADD: 
+      return i915_emit_arith( p, A0_ADD, dest, mask, saturate, 
+                            src[0], src[1], 0 );
+   case GL_ADD_SIGNED:
+      /* tmp = arg0 + arg1
+       * result = tmp + -.5
+       */
+      tmp = i915_emit_const1f(p, .5);
+      tmp = negate(swizzle(tmp,X,X,X,X),1,1,1,1);
+      i915_emit_arith( p, A0_ADD, dest, mask, 0, src[0], src[1], 0 );
+      i915_emit_arith( p, A0_ADD, dest, mask, saturate, dest, tmp, 0 );
+      return dest;
+   case GL_INTERPOLATE:                /* TWO INSTRUCTIONS */
+      /* Arg0 * (Arg2) + Arg1 * (1-Arg2)
+       *
+       * Arg0*Arg2 + Arg1 - Arg1Arg2 
+       *
+       * tmp = Arg0*Arg2 + Arg1, 
+       * result = (-Arg1)Arg2 + tmp 
+       */
+      tmp = i915_get_temp( p );
+      i915_emit_arith( p, A0_MAD, tmp, mask, 0, src[0], src[2], src[1] );
+      i915_emit_arith( p, A0_MAD, dest, mask, saturate, 
+                     negate(src[1], 1,1,1,1), src[2], tmp );
+      return dest;
+   case GL_SUBTRACT: 
+      /* negate src[1] */
+      return i915_emit_arith( p, A0_ADD, dest, mask, saturate, src[0],
+                        negate(src[1],1,1,1,1), 0 );
+
+   case GL_DOT3_RGBA:
+   case GL_DOT3_RGBA_EXT: 
+   case GL_DOT3_RGB_EXT:
+   case GL_DOT3_RGB: {
+      GLuint tmp0 = i915_get_temp( p );
+      GLuint tmp1 = i915_get_temp( p );
+      GLuint neg1 = negate(swizzle(i915_emit_const1f(p, 1),X,X,X,X), 1,1,1,1);
+      GLuint two = swizzle(i915_emit_const1f(p, 2),X,X,X,X);
+      i915_emit_arith( p, A0_MAD, tmp0, A0_DEST_CHANNEL_ALL, 0, 
+                     two, src[0], neg1);
+      if (src[0] == src[1])
+        tmp1 = tmp0;
+      else
+        i915_emit_arith( p, A0_MAD, tmp1, A0_DEST_CHANNEL_ALL, 0, 
+                        two, src[1], neg1);
+      i915_emit_arith( p, A0_DP3, dest, mask, saturate, tmp0, tmp1, 0);
+      return dest;
+   }
+
+   default: 
+      return src[0];
+   }
+}
+
+static GLuint get_dest( struct i915_fragment_program *p, int unit )
+{
+   if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+      return i915_get_temp( p );
+   else if (unit != p->last_tex_stage)
+      return i915_get_temp( p );
+   else
+      return UREG(REG_TYPE_OC, 0);
+}
+      
+
+
+static GLuint emit_texenv( struct i915_fragment_program *p, int unit )
+{
+   struct gl_texture_unit *texUnit = &p->ctx->Texture.Unit[unit];
+   GLenum envMode = texUnit->EnvMode;
+   struct gl_texture_object *tObj = texUnit->_Current;
+   GLenum format = tObj->Image[0][tObj->BaseLevel]->Format;
+   GLuint saturate = unit < p->last_tex_stage ? A0_DEST_SATURATE : 0;
+
+   switch(envMode) {
+   case GL_BLEND: {
+      const int cf = get_source(p, GL_PREVIOUS, unit);
+      const int cc = get_source(p, GL_CONSTANT, unit);
+      const int cs = get_source(p, GL_TEXTURE, unit);
+      const int out = get_dest(p, unit);
+
+      if (format == GL_INTENSITY) {
+        /* cv = cf(1 - cs) + cc.cs
+         * cv = cf - cf.cs + cc.cs
+         */
+        /* u[2] = MAD( -cf * cs + cf )
+         * cv   = MAD( cc * cs + u[2] )
+         */
+        
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0, 
+                        negate(cf,1,1,1,1), cs, cf );
+
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate, 
+                        cc, cs, out );
+
+        return out;
+      } else {
+        /* cv = cf(1 - cs) + cc.cs
+         * cv = cf - cf.cs + cc.cs
+         * av =      af.as
+         */
+        /* u[2] = MAD( cf.-x-y-zw * cs.xyzw + cf.xyz0 )
+         * oC   = MAD( cc.xyz0 * cs.xyz0 + u[2].xyzw )
+         */
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
+                        negate(cf,1,1,1,0),  
+                        cs,
+                        swizzle(cf,X,Y,Z,ZERO) );
+
+
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
+                        swizzle(cc,X,Y,Z,ZERO),  
+                        swizzle(cs,X,Y,Z,ZERO),
+                        out );
+
+        return out;
+      }
+   }
+
+   case GL_DECAL: {
+      if (format == GL_RGB ||
+         format == GL_RGBA) {
+        int cf = get_source( p, GL_PREVIOUS, unit );
+        int cs = get_source( p, GL_TEXTURE, unit );
+        int out = get_dest(p, unit);
+        
+        /* cv = cf(1-as) + cs.as
+         * cv = cf.(-as) + cf + cs.as
+         * av = af
+         */ 
+        
+        /* u[2] = mad( cf.xyzw * cs.-w-w-w1 + cf.xyz0 )
+         * oc = mad( cs.xyz0 * cs.www0 + u[2].xyzw )
+         */
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
+                        cf,  
+                        negate(swizzle(cs,W,W,W,ONE),1,1,1,0),
+                        swizzle(cf,X,Y,Z,ZERO) );
+        
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
+                        swizzle(cs,X,Y,Z,ZERO),  
+                        swizzle(cs,W,W,W,ZERO),
+                        out );
+        return out;
+      }
+      else {
+        return get_source( p, GL_PREVIOUS, unit );
+      }
+   }
+
+   case GL_REPLACE: {
+      const int cs = get_source( p, GL_TEXTURE, unit );        /* saturated */
+      switch (format) {
+      case GL_ALPHA: {
+        const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */
+        i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_XYZ, 0, cf, 0, 0 );
+        return cs;
+      }
+      case GL_RGB:
+      case GL_LUMINANCE: {
+        const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */
+        i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_W, 0, cf, 0, 0 );
+        return cs;
+      }
+      default:
+        return cs;
+      }
+   }
+
+   case GL_MODULATE: {
+      const int cf = get_source( p, GL_PREVIOUS, unit );
+      const int cs = get_source( p, GL_TEXTURE, unit );
+      const int out = get_dest(p, unit);
+      switch (format) {
+      case GL_ALPHA: 
+        i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate,
+                        swizzle(cs, ONE, ONE, ONE, W), cf, 0 );
+        break;
+      default:
+        i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate, 
+                        cs, cf, 0 );
+        break;
+      }
+      return out;
+   }
+   case GL_ADD: {
+      int cf = get_source( p, GL_PREVIOUS, unit );
+      int cs = get_source( p, GL_TEXTURE, unit );
+      const int out = get_dest( p, unit );
+
+      if (format == GL_INTENSITY) {
+        /* output-color.rgba = add( incoming, u[1] )
+         */
+        i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, saturate, 
+                        cs, cf, 0 );
+        return out;
+      }
+      else {
+        /* cv.xyz = cf.xyz + cs.xyz
+         * cv.w   = cf.w * cs.w
+         *
+         * cv.xyzw = MAD( cf.111w * cs.xyzw + cf.xyz0 )
+         */
+        i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
+                        swizzle(cf,ONE,ONE,ONE,W), 
+                        cs,  
+                        swizzle(cf,X,Y,Z,ZERO) ); 
+        return out;
+      }
+      break;
+   }
+   case GL_COMBINE: {
+      GLuint rgb_shift, alpha_shift, out, shift;
+      GLuint dest = get_dest(p, unit);
+
+      /* 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 (texUnit->Combine.ModeRGB) {
+      case GL_DOT3_RGB_EXT:
+        alpha_shift = texUnit->Combine.ScaleShiftA;
+        rgb_shift = 0;
+        break;
+
+      case GL_DOT3_RGBA_EXT:
+        alpha_shift = 0;
+        rgb_shift = 0;
+        break;
+
+      default:
+        rgb_shift = texUnit->Combine.ScaleShiftRGB;
+        alpha_shift = texUnit->Combine.ScaleShiftA;
+        break;
+      }
+
+
+      /* Emit the RGB and A combine ops
+       */
+      if (texUnit->Combine.ModeRGB == texUnit->Combine.ModeA && 
+         args_match( texUnit )) {
+        out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate,
+                            unit,
+                            texUnit->Combine.ModeRGB,
+                            texUnit->Combine.SourceRGB,
+                            texUnit->Combine.OperandRGB );
+      }
+      else if (texUnit->Combine.ModeRGB == GL_DOT3_RGBA_EXT ||
+              texUnit->Combine.ModeRGB == GL_DOT3_RGBA) {
+
+        out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate,
+                            unit,
+                            texUnit->Combine.ModeRGB,
+                            texUnit->Combine.SourceRGB,
+                            texUnit->Combine.OperandRGB );
+      }
+      else {
+        /* Need to do something to stop from re-emitting identical
+         * argument calculations here:
+         */
+        out = emit_combine( p, dest, A0_DEST_CHANNEL_XYZ, saturate,
+                            unit,
+                            texUnit->Combine.ModeRGB,
+                            texUnit->Combine.SourceRGB,
+                            texUnit->Combine.OperandRGB );
+        out = emit_combine( p, dest, A0_DEST_CHANNEL_W, saturate,
+                            unit,
+                            texUnit->Combine.ModeA,
+                            texUnit->Combine.SourceA,
+                            texUnit->Combine.OperandA );
+      }
+
+      /* Deal with the final shift:
+       */
+      if (alpha_shift || rgb_shift) {
+        if (rgb_shift == alpha_shift) {
+           shift = i915_emit_const1f(p, 1<<rgb_shift);
+           shift = swizzle(shift,X,X,X,X);
+        }
+        else {
+           shift = i915_emit_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
+           shift = swizzle(shift,X,X,X,Y);
+        }
+        return i915_emit_arith( p, A0_MUL, dest, A0_DEST_CHANNEL_ALL, 
+                               saturate, out, shift, 0 );
+      }
+
+      return out;
+   }
+
+   default:
+      return get_source(p, GL_PREVIOUS, 0);
+   }
+}
+
+static void emit_program_fini( struct i915_fragment_program *p )
+{
+   int cf = get_source( p, GL_PREVIOUS, 0 );
+   int out = UREG( REG_TYPE_OC, 0 );
+
+   if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+      /* Emit specular add.
+       */
+      GLuint s = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_ALL);
+      i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, 0, cf, 
+                 swizzle(s, X,Y,Z,ZERO), 0 );
+   }
+   else if (cf != out) {
+      /* Will wind up in here if no texture enabled or a couple of
+       * other scenarios (GL_REPLACE for instance).
+       */
+      i915_emit_arith( p, A0_MOV, out, A0_DEST_CHANNEL_ALL, 0, cf, 0, 0 );
+   }
+}
+
+
+static void i915EmitTextureProgram( i915ContextPtr i915 )
+{
+   GLcontext *ctx = &i915->intel.ctx;
+   struct i915_fragment_program *p = &i915->tex_program;
+   GLuint unit;
+
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   i915_init_program( i915, p );
+
+   if (ctx->Texture._EnabledUnits) {
+      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
+        if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+           p->last_tex_stage = unit;
+        }
+
+      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
+        if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+           p->src_previous = emit_texenv( p, unit );
+           p->src_texture = UREG_BAD;
+           p->temp_flag = 0xffff000;
+           p->temp_flag |= 1 << GET_UREG_NR(p->src_previous);
+        }
+   }
+
+   emit_program_fini( p );
+
+   i915_fini_program( p );
+   i915_upload_program( i915, p );
+
+   p->translated = 1;
+}
+
+
+void i915ValidateTextureProgram( i915ContextPtr i915 )
+{
+   intelContextPtr intel = &i915->intel;
+   GLcontext *ctx = &intel->ctx;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint index = tnl->render_inputs;
+   int i, offset;
+   GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
+   GLuint s2 = S2_TEXCOORD_NONE;
+
+   /* Important:
+    */
+   VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
+   intel->vertex_attr_count = 0;
+   intel->coloroffset = 0;
+   intel->specoffset = 0;
+   offset = 0;
+
+   if (i915->vertex_fog == I915_FOG_PIXEL) {
+      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
+      index &= ~_TNL_BIT_FOG;
+   }
+   else if (index & _TNL_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 );
+   }
+
+   /* How undefined is undefined? */
+   if (index & _TNL_BIT_POINTSIZE) {
+      EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4 );
+   }
+      
+   intel->coloroffset = offset / 4;
+   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, S4_VFMT_COLOR, 4 );
+            
+   if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+      if (index & _TNL_BIT_COLOR1) {
+        intel->specoffset = offset / 4;
+        EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, S4_VFMT_SPEC_FOG, 3 );
+      } else 
+        EMIT_PAD( 3 );
+      
+      if (index & _TNL_BIT_FOG)
+        EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1 );
+      else
+        EMIT_PAD( 1 );
+   }
+
+   if (index & _TNL_BITS_TEX_ANY) {
+      for (i = 0; i < 8; i++) {
+        if (index & _TNL_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 );
+        }
+      }
+   }
+
+   /* Only need to change the vertex emit code if there has been a
+    * statechange to a new hardware vertex format:
+    */
+   if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
+       s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
+    
+      I915_STATECHANGE( i915, I915_UPLOAD_CTX );
+
+      i915->tex_program.translated = 0;
+
+      /* 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;
+
+      i915->state.Ctx[I915_CTXREG_LIS2] = s2;
+      i915->state.Ctx[I915_CTXREG_LIS4] = s4;
+
+      assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
+   }
+
+   if (!i915->tex_program.translated ||
+       i915->last_ReallyEnabled != ctx->Texture._EnabledUnits) {
+      i915EmitTextureProgram( i915 );      
+      i915->last_ReallyEnabled = ctx->Texture._EnabledUnits;
+   }
+}
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
new file mode 100644 (file)
index 0000000..93656dd
--- /dev/null
@@ -0,0 +1,625 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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 "i915_context.h"
+#include "i915_reg.h"
+
+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} };
+
+
+#define I915_TEX_UNIT_ENABLED(unit)            (1<<unit)
+
+static void i915SetTexImages( i915ContextPtr i915, 
+                            struct gl_texture_object *tObj )
+{
+   GLuint total_height, pitch, i, textureFormat;
+   i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
+   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
+   GLint firstLevel, lastLevel, numLevels;
+   GLint ss2 = 0;
+
+   switch( baseImage->TexFormat->MesaFormat ) {
+   case MESA_FORMAT_L8:
+      t->intel.texelBytes = 1;
+      textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
+      break;
+
+   case MESA_FORMAT_I8:
+      t->intel.texelBytes = 1;
+      textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
+      break;
+
+   case MESA_FORMAT_A8:
+      t->intel.texelBytes = 1;
+      textureFormat = MAPSURF_8BIT | MT_8BIT_A8; 
+      break;
+
+   case MESA_FORMAT_AL88:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
+      break;
+
+   case MESA_FORMAT_RGB565:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
+      break;
+
+   case MESA_FORMAT_ARGB1555:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
+      break;
+
+   case MESA_FORMAT_ARGB4444:
+      t->intel.texelBytes = 2;
+      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
+      break;
+
+   case MESA_FORMAT_ARGB8888:
+      t->intel.texelBytes = 4;
+      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
+      break;
+
+   case MESA_FORMAT_YCBCR_REV:
+      t->intel.texelBytes = 2;
+      textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL);
+      ss2 |= SS2_COLORSPACE_CONVERSION;
+      break;
+
+   case MESA_FORMAT_YCBCR:
+      t->intel.texelBytes = 2;
+      textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY);
+      ss2 |= SS2_COLORSPACE_CONVERSION;
+      break;
+
+   default:
+      fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
+      abort();
+   }
+
+   /* Compute which mipmap levels we really want to send to the hardware.
+    */
+   driCalculateTextureFirstLastLevel( (driTextureObject *) t );
+
+
+   /* Figure out the amount of memory required to hold all the mipmap
+    * levels.  Choose the smallest pitch to accomodate the largest
+    * mipmap:
+    */
+   firstLevel = t->intel.base.firstLevel;
+   lastLevel = t->intel.base.lastLevel;
+   numLevels = lastLevel - firstLevel + 1;
+
+
+
+   /* All images must be loaded at this pitch.  Count the number of
+    * lines required:
+    */
+   switch (tObj->Target) {
+   case GL_TEXTURE_CUBE_MAP: {
+      const GLuint dim = tObj->Image[0][firstLevel]->Width;
+      GLuint face;
+
+      pitch = dim * t->intel.texelBytes;
+      pitch *= 2;              /* double pitch for cube layouts */
+      pitch = (pitch + 3) & ~3;
+      
+      total_height = dim * 4;
+
+      for ( face = 0 ; face < 6 ; face++) {
+        GLuint x = initial_offsets[face][0] * dim;
+        GLuint y = initial_offsets[face][1] * dim;
+        GLuint d = dim;
+        
+        t->intel.base.dirty_images[face] = ~0;
+
+        assert(tObj->Image[face][firstLevel]->Width == dim);
+        assert(tObj->Image[face][firstLevel]->Height == dim);
+
+        for (i = 0; i < numLevels; i++) {
+           t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
+           if (!t->intel.image[face][i].image) {
+              fprintf(stderr, "no image %d %d\n", face, i);
+              break;           /* can't happen */
+           }
+        
+           t->intel.image[face][i].offset = 
+              y * pitch + x * t->intel.texelBytes;
+           t->intel.image[face][i].internalFormat = baseImage->Format;
+
+           d >>= 1;
+           x += step_offsets[face][0] * d;
+           y += step_offsets[face][1] * d;
+        }
+      }
+      break;
+   }
+   case GL_TEXTURE_3D: {
+      GLuint virtual_height;
+      GLuint tmp_numLevels = numLevels;
+      pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
+      pitch = (pitch + 3) & ~3;
+      t->intel.base.dirty_images[0] = ~0;
+
+      /* Calculate the size of a single slice.  Hardware demands a
+       * minimum of 8 mipmaps, some of which might ultimately not be
+       * used:
+       */
+      if (tmp_numLevels < 9)
+        tmp_numLevels = 9;
+
+      virtual_height = tObj->Image[0][firstLevel]->Height;
+
+      for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
+        t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
+        if (t->intel.image[0][i].image) {
+           t->intel.image[0][i].offset = total_height * pitch;
+           t->intel.image[0][i].internalFormat = baseImage->Format;
+        }
+
+        total_height += MAX2(2, virtual_height);
+        virtual_height >>= 1;
+      }
+
+      t->intel.depth_pitch = total_height * pitch;
+
+      /* Multiply slice size by texture depth for total size.  It's
+       * remarkable how wasteful of memory all the i8x0 texture
+       * layouts are.
+       */
+      total_height *= t->intel.image[0][0].image->Depth;
+      break;
+   }
+   default:
+      pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
+      pitch = (pitch + 3) & ~3;
+      t->intel.base.dirty_images[0] = ~0;
+
+      for ( total_height = i = 0 ; i < numLevels ; i++ ) {
+        t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
+        if (!t->intel.image[0][i].image) 
+           break;
+        
+        t->intel.image[0][i].offset = total_height * pitch;
+        t->intel.image[0][i].internalFormat = baseImage->Format;
+        total_height += MAX2(2, t->intel.image[0][i].image->Height);
+      }
+      break;
+   }
+
+   t->intel.Pitch = pitch;
+   t->intel.base.totalSize = total_height*pitch;
+   t->intel.max_level = numLevels-1;
+   t->Setup[I915_TEXREG_MS3] = 
+      (((tObj->Image[0][firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
+       ((tObj->Image[0][firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) |
+       textureFormat |
+       MS3_USE_FENCE_REGS);
+   t->Setup[I915_TEXREG_MS4] = 
+      ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) | 
+       MS4_CUBE_FACE_ENA_MASK |
+       (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) |
+       ((tObj->Image[0][firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
+
+   t->Setup[I915_TEXREG_SS2] &= ~SS2_COLORSPACE_CONVERSION;
+   t->Setup[I915_TEXREG_SS2] |= ss2;
+
+   t->intel.dirty = I915_UPLOAD_TEX_ALL;
+}
+
+
+/* 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;
+   }
+}
+
+
+/**
+ */
+static void i915ImportTexObjState( struct gl_texture_object *texObj )
+{   
+   i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData;
+   int minFilt = 0, mipFilt = 0, magFilt = 0;
+
+   if(INTEL_DEBUG&DEBUG_DRI)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   switch (texObj->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:
+      break;
+   }
+
+   if ( texObj->MaxAnisotropy > 1.0 ) {
+      minFilt = FILTER_ANISOTROPIC; 
+      magFilt = FILTER_ANISOTROPIC;
+   }
+   else {
+      switch (texObj->MagFilter) {
+      case GL_NEAREST:
+        magFilt = FILTER_NEAREST;
+        break;
+      case GL_LINEAR:
+        magFilt = FILTER_LINEAR;
+        break;
+      default:
+        break;
+      }  
+   }
+
+   t->Setup[I915_TEXREG_SS2] &= ~SS2_MIN_FILTER_MASK;
+   t->Setup[I915_TEXREG_SS2] &= ~SS2_MIP_FILTER_MASK;
+   t->Setup[I915_TEXREG_SS2] &= ~SS2_MAG_FILTER_MASK;
+   t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
+                               (mipFilt << SS2_MIP_FILTER_SHIFT) |
+                               (magFilt << SS2_MAG_FILTER_SHIFT));
+
+   {
+      GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK |
+                                               SS3_TCY_ADDR_MODE_MASK |
+                                               SS3_TCZ_ADDR_MODE_MASK);
+      GLenum ws = texObj->WrapS;
+      GLenum wt = texObj->WrapT;
+      GLenum wr = texObj->WrapR;
+      
+      t->refs_border_color = 0;
+
+      if (texObj->Target == GL_TEXTURE_3D &&
+         (texObj->MinFilter != GL_NEAREST ||
+          texObj->MagFilter != GL_NEAREST)) {
+        
+        /* Try to mimic GL_CLAMP functionality a little better -
+         * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is
+         * in use.  Only do this for 3D textures at the moment --
+         * doing it universally would fix the conform texbc.c
+         * failure, though.
+         */
+        if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER;
+        if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER;
+        if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER;
+
+        /* 3D textures don't seem to respect the border color.
+         * Fallback if there's ever a danger that they might refer to
+         * it.
+         */
+        if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
+        if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
+        if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
+      }
+
+      ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT;
+      ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT;
+      ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT;
+   
+      if (ss3 != t->Setup[I915_TEXREG_SS3]) {
+        t->intel.dirty = I915_UPLOAD_TEX_ALL;
+        t->Setup[I915_TEXREG_SS3] = ss3;
+      }
+   }
+
+   {   
+      const GLubyte *color = texObj->_BorderChan;
+
+      t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1],
+                                                    color[2],color[3]);
+   }
+}
+
+
+
+static void i915_import_tex_unit( i915ContextPtr i915, 
+                                i915TextureObjectPtr t,
+                                GLuint unit )
+{
+   GLuint state[I915_TEX_SETUP_SIZE];
+
+   if(INTEL_DEBUG&DEBUG_TEXTURE)
+      fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
+   
+   if (i915->intel.CurrentTexObj[unit]) 
+      i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
+
+   i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
+   t->intel.base.bound |= (1 << unit);
+
+   if (t->intel.dirty & I915_UPLOAD_TEX(unit)) {
+      i915ImportTexObjState( t->intel.base.tObj );
+      t->intel.dirty &= ~I915_UPLOAD_TEX(unit);
+   }
+
+   state[I915_TEXREG_MS2] = t->intel.TextureOffset;
+   state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3];
+   state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4];
+
+   state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] &
+                           SS2_LOD_BIAS_MASK);
+   state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK);
+
+   state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] &
+                           SS3_NORMALIZED_COORDS);
+   state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] &
+                            ~(SS3_NORMALIZED_COORDS|
+                              SS3_TEXTUREMAP_INDEX_MASK));
+
+   state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT);
+
+   state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4];
+
+
+   if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
+      I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
+      memcpy(i915->state.Tex[unit], state, sizeof(state));
+   }
+}
+
+
+
+static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
+
+   if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit);
+
+   if (!(i915->state.active & I915_UPLOAD_TEX(unit))) {
+      I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
+   }
+
+   /* Fallback if there's a texture border */
+   if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
+      return GL_FALSE;
+   }
+
+
+   /* Update state if this is a different texture object to last
+    * time.
+    */
+   if (i915->intel.CurrentTexObj[unit] != &t->intel || 
+       (t->intel.dirty & I915_UPLOAD_TEX(unit))) {
+      i915_import_tex_unit( i915, t, unit);
+      i915->tex_program.translated = 0;
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
+   GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
+
+   ss3 &= ~SS3_NORMALIZED_COORDS;
+
+   if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
+      i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
+   }
+
+   /* Upload teximages (not pipelined)
+    */
+   if (t->intel.base.dirty_images[0]) {
+      i915SetTexImages( i915, tObj );
+      if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
+        return GL_FALSE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
+static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
+   GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
+
+   ss3 |= SS3_NORMALIZED_COORDS;
+
+   if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
+      i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
+   }
+
+   /* Upload teximages (not pipelined)
+    */
+   if (t->intel.base.dirty_images[0]) {
+      i915SetTexImages( i915, tObj );
+      if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
+        return GL_FALSE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
+   GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
+   GLuint face;
+
+   ss3 |= SS3_NORMALIZED_COORDS;
+
+   if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
+      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
+      i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
+   }
+
+   /* Upload teximages (not pipelined)
+    */
+   if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
+        t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
+        t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
+      i915SetTexImages( i915, tObj );
+   }
+
+   /* upload (per face) */
+   for (face = 0; face < 6; face++) {
+      if (t->intel.base.dirty_images[face]) {
+        if (!intelUploadTexImages( &i915->intel, &t->intel, face )) {
+           return GL_FALSE;
+        }
+      }
+   }
+
+
+   return GL_TRUE;
+}
+
+static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit )
+{
+   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
+   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
+
+   /* 3D textures on I915 seem to get bogus border colors, hence this
+    * fallback:
+    */
+   if (t->refs_border_color)
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+
+
+
+static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
+{
+   i915ContextPtr i915 = I915_CONTEXT(ctx);
+
+   if (i915->state.active & I915_UPLOAD_TEX(unit)) {
+      I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE);
+   }
+
+   /* The old texture is no longer bound to this texture unit.
+    * Mark it as such.
+    */
+   if ( i915->intel.CurrentTexObj[unit] != NULL ) {
+      i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
+      i915->intel.CurrentTexObj[unit] = NULL;
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit )
+{
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+   if (texUnit->_ReallyEnabled &&
+       INTEL_CONTEXT(ctx)->intelScreen->textureSize < 2048 * 1024)
+      return GL_FALSE;
+
+   switch (texUnit->_ReallyEnabled) {
+   case TEXTURE_1D_BIT:
+   case TEXTURE_2D_BIT:
+      return (enable_tex_2d( ctx, unit ) &&
+             enable_tex_common( ctx, unit ));
+   case TEXTURE_RECT_BIT:
+      return (enable_tex_rect( ctx, unit ) &&
+             enable_tex_common( ctx, unit ));
+   case TEXTURE_CUBE_BIT:
+      return (enable_tex_cube( ctx, unit ) &&
+             enable_tex_common( ctx, unit ));
+   case TEXTURE_3D_BIT:
+       return (enable_tex_2d( ctx, unit ) && 
+              enable_tex_common( ctx, unit ) &&
+              enable_tex_3d( ctx, unit)); 
+   case 0:
+      return disable_tex( ctx, unit );
+   default:
+      return GL_FALSE;
+   }
+}
+
+
+void i915UpdateTextureState( intelContextPtr intel )
+{
+   GLcontext *ctx = &intel->ctx;
+   GLboolean ok = GL_TRUE;
+   GLuint i;
+
+   for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) {
+      ok = i915UpdateTexUnit( ctx, i );
+   }
+
+   FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok );
+}
+
+
+
diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c
new file mode 100644 (file)
index 0000000..cfea354
--- /dev/null
@@ -0,0 +1,332 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+
+#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 "i915_reg.h"
+#include "i915_context.h"
+
+static void i915_render_start( intelContextPtr intel )
+{
+   GLcontext *ctx = &intel->ctx;
+   i915ContextPtr i915 = I915_CONTEXT(intel);
+
+   if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) 
+      i915ValidateFragmentProgram( i915 );
+   else 
+      i915ValidateTextureProgram( i915 );
+}
+
+
+static void i915_reduced_primitive_state( intelContextPtr intel,
+                                         GLenum rprim )
+{
+    i915ContextPtr i915 = I915_CONTEXT(intel);
+    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]) {
+       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( intelContextPtr intel,
+                                        GLuint expected )
+{
+   i915ContextPtr i915 = I915_CONTEXT(intel);
+   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++;
+       
+   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( intelContextPtr intel )
+{
+   BATCH_LOCALS;
+
+   BEGIN_BATCH( 200 );
+
+   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 )                     \
+do {                                                   \
+   int k;                                              \
+   BEGIN_BATCH( (size) / sizeof(GLuint));              \
+   for (k = 0 ; k < (size) / sizeof(GLuint) ; k++)     \
+      OUT_BATCH((state)[k]);                           \
+   ADVANCE_BATCH();                                    \
+} while (0);
+
+
+/* Push the state into the sarea and/or texture memory.
+ */
+static void i915_emit_state( intelContextPtr intel )
+{
+   i915ContextPtr i915 = I915_CONTEXT(intel);
+   struct i915_hw_state *state = i915->current;
+   BATCH_LOCALS;
+   int i;
+   GLuint dirty;
+
+   /* More to 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;
+
+
+   if (VERBOSE) 
+      fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
+
+   if (dirty & I915_UPLOAD_CTX) {
+      if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n"); 
+      emit( i915, state->Ctx, sizeof(state->Ctx) );
+   }
+
+   if (dirty & I915_UPLOAD_BUFFERS) {
+      if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); 
+      emit( i915, state->Buffer, sizeof(state->Buffer) );
+   }
+
+   if (dirty & I915_UPLOAD_STIPPLE) {
+      if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); 
+      emit( i915, state->Stipple, sizeof(state->Stipple) );
+   }
+
+   if (dirty & I915_UPLOAD_FOG) {
+      if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n"); 
+      emit( i915, 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);
+      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)) {
+           OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]);
+           OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
+           OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
+        }
+      ADVANCE_BATCH();
+
+      BEGIN_BATCH(2+nr*3);
+      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 (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n"); 
+      emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) );
+   }
+
+   if (dirty & I915_UPLOAD_PROGRAM) {
+      if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n"); 
+
+      assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize);
+      
+      emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) );
+      if (VERBOSE)
+        i915_disassemble_program( state->Program, state->ProgramSize );
+   }
+
+   state->emitted |= dirty;
+}
+
+static void i915_destroy_context( intelContextPtr intel )
+{
+   _tnl_free_vertices(&intel->ctx);
+}
+
+static void i915_set_draw_offset( intelContextPtr intel, int offset )
+{
+   i915ContextPtr i915 = I915_CONTEXT(intel);
+   I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
+   i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset;
+}
+
+static void i915_lost_hardware( intelContextPtr intel )
+{
+   I915_CONTEXT(intel)->state.emitted = 0;
+}
+
+static void i915_emit_flush( intelContextPtr intel )
+{
+   BATCH_LOCALS;
+
+   BEGIN_BATCH(2);
+   OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE ); 
+   OUT_BATCH( 0 );
+   ADVANCE_BATCH();
+}
+
+
+void i915InitVtbl( i915ContextPtr i915 )
+{
+   i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj;
+   i915->intel.vtbl.check_vertex_size = i915_check_vertex_size;
+   i915->intel.vtbl.clear_with_tris = i915ClearWithTris;
+   i915->intel.vtbl.destroy = i915_destroy_context;
+   i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state;
+   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_offset = i915_set_draw_offset;
+   i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
+   i915->intel.vtbl.emit_flush = i915_emit_flush;
+}
+
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c
new file mode 100644 (file)
index 0000000..9146cbe
--- /dev/null
@@ -0,0 +1,668 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "mtypes.h"
+#include "context.h"
+#include "enums.h"
+
+#include "intel_reg.h"
+#include "intel_batchbuffer.h"
+#include "intel_context.h"
+
+
+
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void intel_fill_box( intelContextPtr intel,
+                           GLshort x, GLshort y,
+                           GLshort w, GLshort h,
+                           GLubyte r, GLubyte g, GLubyte b )
+{
+   intelEmitFillBlitLocked( intel, 
+                           intel->intelScreen->cpp,
+                           intel->intelScreen->backPitch,
+                           intel->intelScreen->frontOffset,
+                           x, y, w, h,
+                           INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
+                                           r,g,b,0xff));
+}
+
+static void intel_draw_performance_boxes( intelContextPtr intel )
+{
+   /* Purple box for page flipping
+    */
+   if ( intel->perf_boxes & I830_BOX_FLIP ) 
+      intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
+
+   /* Red box if we have to wait for idle at any point
+    */
+   if ( intel->perf_boxes & I830_BOX_WAIT ) 
+      intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
+
+   /* Blue box: lost context?
+    */
+   if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT ) 
+      intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
+
+   /* Yellow box for texture swaps
+    */
+   if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD ) 
+      intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
+
+   /* Green box if hardware never idles (as far as we can tell)
+    */
+   if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) ) 
+      intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
+
+
+   /* Draw bars indicating number of buffers allocated 
+    * (not a great measure, easily confused)
+    */
+#if 0
+   if (intel->dma_used) {
+      int bar = intel->dma_used / 10240;
+      if (bar > 100) bar = 100;
+      if (bar < 1) bar = 1;
+      intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
+      intel->dma_used = 0;
+   }
+#endif
+
+   intel->perf_boxes = 0;
+}
+
+
+
+
+
+
+static int bad_prim_vertex_nr( int primitive, int nr )
+{
+   switch (primitive & PRIM3D_MASK) {
+   case PRIM3D_POINTLIST:
+      return nr < 1;
+   case PRIM3D_LINELIST:
+      return (nr & 1) || nr == 0;
+   case PRIM3D_LINESTRIP:
+      return nr < 2;
+   case PRIM3D_TRILIST:
+   case PRIM3D_RECTLIST:
+      return nr % 3 || nr == 0;
+   case PRIM3D_POLY:
+   case PRIM3D_TRIFAN:
+   case PRIM3D_TRISTRIP:
+   case PRIM3D_TRISTRIP_RVRSE:
+      return nr < 3;
+   default:
+      return 1;
+   }   
+}
+
+static void intel_flush_inline_primitive( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   GLuint used = intel->batch.ptr - intel->prim.start_ptr;
+   GLuint vertcount;
+
+   assert(intel->prim.primitive != ~0);
+
+   if (1) {
+      /* Check vertex size against the vertex we're specifying to
+       * hardware.  If it's wrong, ditch the primitive.
+       */ 
+      if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size )) 
+        goto do_discard;
+
+      vertcount = (used - 4)/ (intel->vertex_size * 4);
+
+      if (!vertcount)
+        goto do_discard;
+      
+      if (vertcount * intel->vertex_size * 4 != used - 4) {
+        fprintf(stderr, "vertex size confusion %d %d\n", used, 
+                intel->vertex_size * vertcount * 4);
+        goto do_discard;
+      }
+
+      if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
+        fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
+                vertcount);
+        goto do_discard;
+      }
+   }
+
+   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;
+   intel->batch.space += used;
+   assert(intel->batch.space >= 0);
+
+ 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( intelContextPtr intel, GLuint prim )
+{
+   BATCH_LOCALS;
+
+   if (0)
+      fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
+
+
+   /* Finish any in-progress primitive:
+    */
+   INTEL_FIREVERTICES( intel );
+   
+   /* Emit outstanding state:
+    */
+   intel->vtbl.emit_state( intel );
+   
+   /* Make sure there is some space in this buffer:
+    */
+   if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
+      intelFlushBatch(intel, GL_TRUE); 
+
+
+#if 1
+   if (((int)intel->batch.ptr) & 0x4) {
+      BEGIN_BATCH(1);
+      OUT_BATCH(0);
+      ADVANCE_BATCH();
+   }
+#endif
+
+   /* Emit a slot which will be filled with the inline primitive
+    * command later.
+    */
+   BEGIN_BATCH(2);
+   OUT_BATCH( 0 );
+
+   intel->prim.start_ptr = batch_ptr;
+   intel->prim.primitive = prim;
+   intel->prim.flush = intel_flush_inline_primitive;
+
+   OUT_BATCH( 0 );
+   ADVANCE_BATCH();
+}
+
+
+void intelRestartInlinePrimitive( intelContextPtr intel )
+{
+   GLuint prim = intel->prim.primitive;
+
+   intel_flush_inline_primitive( &intel->ctx );
+   if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
+   intelStartInlinePrimitive( intel, prim );
+}
+
+
+
+void intelWrapInlinePrimitive( intelContextPtr intel )
+{
+   GLuint prim = intel->prim.primitive;
+
+   if (0)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+   intel_flush_inline_primitive( &intel->ctx );
+   intelFlushBatch(intel, GL_TRUE);
+   intelStartInlinePrimitive( intel, prim );
+}
+
+
+/* Emit a primitive with space for inline vertices.
+ */
+GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, 
+                                      int primitive,
+                                      int dwords,
+                                      int vertex_size )
+{
+   GLuint *tmp = 0;
+   BATCH_LOCALS;
+
+   if (0)
+      fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
+
+   /* Emit outstanding state:
+    */
+   intel->vtbl.emit_state( intel );
+
+
+   if (1) {
+      int used = dwords * 4;
+      int vertcount;
+
+      /* Check vertex size against the vertex we're specifying to
+       * hardware.  If it's wrong, ditch the primitive.
+       */ 
+      if (!intel->vtbl.check_vertex_size( intel, vertex_size )) 
+        goto do_discard;
+
+      vertcount = dwords / vertex_size;
+      
+      if (dwords % vertex_size) {
+        fprintf(stderr, "did not request a whole number of vertices\n");
+        goto do_discard;
+      }
+
+      if (bad_prim_vertex_nr( primitive, vertcount )) {
+        fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
+        goto do_discard;
+      }
+
+      if (used < 8)
+        goto do_discard;
+   }
+
+   /* Emit 3D_PRIMITIVE commands:
+    */
+   BEGIN_BATCH(1 + dwords);
+   OUT_BATCH( _3DPRIMITIVE | 
+             primitive |
+             (dwords-1) );
+
+   tmp = (GLuint *)batch_ptr;
+   batch_ptr += dwords * 4;
+
+   ADVANCE_BATCH();
+
+ do_discard:
+   return tmp;
+}
+
+
+
+/*
+ * Copy the back buffer to the front buffer. 
+ */
+void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) 
+{
+   intelContextPtr intel;
+
+   if (0)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
+
+   intelFlush( &intel->ctx );
+   LOCK_HARDWARE( intel );
+   {
+      intelScreenPrivate *intelScreen = intel->intelScreen;
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      int nbox = dPriv->numClipRects;
+      drm_clip_rect_t *pbox = dPriv->pClipRects;
+      int pitch = intelScreen->frontPitch;
+      int cpp = intelScreen->cpp;
+      int i;
+      GLuint CMD, BR13;
+      BATCH_LOCALS;
+
+      switch(cpp) {
+      case 2: 
+        BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
+        CMD = XY_SRC_COPY_BLT_CMD;
+        break;
+      case 4:
+        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);
+        break;
+      default:
+        BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
+        CMD = XY_SRC_COPY_BLT_CMD;
+        break;
+      }
+
+      if (0)
+        intel_draw_performance_boxes( intel );
+
+      for (i = 0 ; i < nbox; i++, pbox++) 
+      {
+        if (pbox->x1 > pbox->x2 ||
+            pbox->y1 > pbox->y2 ||
+            pbox->x2 > intelScreen->width ||
+            pbox->y2 > intelScreen->height)
+           continue;
+        BEGIN_BATCH( 8);
+        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_BATCH( intelScreen->frontOffset );
+        else
+           OUT_BATCH( intelScreen->backOffset );                       
+
+        OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
+        OUT_BATCH( BR13 & 0xffff );
+
+        if (intel->sarea->pf_current_page == 0) 
+           OUT_BATCH( intelScreen->backOffset );                       
+        else
+           OUT_BATCH( intelScreen->frontOffset );
+
+        ADVANCE_BATCH();
+      }
+   }
+   intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
+   UNLOCK_HARDWARE( intel );
+}
+
+
+
+
+void intelEmitFillBlitLocked( intelContextPtr intel,
+                             GLuint cpp,
+                             GLshort dst_pitch,
+                             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;
+   }
+
+   BEGIN_BATCH( 6);
+   OUT_BATCH( CMD );
+   OUT_BATCH( BR13 );
+   OUT_BATCH( (y << 16) | x );
+   OUT_BATCH( ((y+h) << 16) | (x+w) );
+   OUT_BATCH( dst_offset );
+   OUT_BATCH( color );
+   ADVANCE_BATCH();
+}
+
+
+/* Copy BitBlt
+ */
+void intelEmitCopyBlitLocked( intelContextPtr intel,
+                             GLuint cpp,
+                             GLshort src_pitch,
+                             GLuint  src_offset,
+                             GLshort dst_pitch,
+                             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;
+
+   src_pitch *= cpp;
+   dst_pitch *= cpp;
+
+   switch(cpp) {
+   case 1: 
+   case 2: 
+   case 3: 
+      BR13 = dst_pitch | (0xCC << 16) | (1<<24);
+      CMD = XY_SRC_COPY_BLT_CMD;
+      break;
+   case 4:
+      BR13 = dst_pitch | (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;
+   }
+
+   BEGIN_BATCH( 12);
+   OUT_BATCH( CMD );
+   OUT_BATCH( BR13 );
+   OUT_BATCH( (dst_y << 16) | dst_x );
+   OUT_BATCH( (dst_y2 << 16) | dst_x2 );
+   OUT_BATCH( dst_offset );    
+   OUT_BATCH( (src_y << 16) | src_x );
+   OUT_BATCH( src_pitch );
+   OUT_BATCH( src_offset ); 
+   ADVANCE_BATCH();
+}
+
+
+
+void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
+                     GLint cx1, GLint cy1, GLint cw, GLint ch)
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   intelScreenPrivate *intelScreen = intel->intelScreen;
+   GLuint clear_depth, clear_color;
+   GLint cx, cy;
+   GLint pitch = intelScreen->frontPitch;
+   GLint cpp = intelScreen->cpp;
+   GLint i;
+   GLuint BR13, CMD, D_CMD;
+   BATCH_LOCALS;
+
+   
+   clear_color = intel->ClearColor;
+   clear_depth = 0;
+
+   if (flags & DD_DEPTH_BIT) {
+      clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
+   }
+
+   if (flags & DD_STENCIL_BIT) {
+      clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
+   }
+
+   switch(cpp) {
+   case 2: 
+      BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
+      D_CMD = CMD = XY_COLOR_BLT_CMD;
+      break;
+   case 4:
+      BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
+      CMD = (XY_COLOR_BLT_CMD |
+            XY_COLOR_BLT_WRITE_ALPHA | 
+            XY_COLOR_BLT_WRITE_RGB);
+      D_CMD = XY_COLOR_BLT_CMD;
+      if (flags & DD_DEPTH_BIT) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
+      if (flags & DD_STENCIL_BIT) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+      break;
+   default:
+      BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
+      D_CMD = CMD = XY_COLOR_BLT_CMD;
+      break;
+   }
+
+   intelFlush( &intel->ctx );
+   LOCK_HARDWARE( intel );
+   {
+      /* flip top to bottom */
+      cy = intel->driDrawable->h-cy1-ch;
+      cx = cx1 + intel->drawX;
+      cy += intel->drawY;
+
+      /* adjust for page flipping */
+      if ( intel->sarea->pf_current_page == 1 ) {
+        GLuint tmp = flags;
+
+        flags &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
+        if ( tmp & DD_FRONT_LEFT_BIT ) flags |= DD_BACK_LEFT_BIT;
+        if ( tmp & DD_BACK_LEFT_BIT )  flags |= DD_FRONT_LEFT_BIT;
+      }
+
+      for (i = 0 ; i < intel->numClipRects ; i++) 
+      {         
+        drm_clip_rect_t *box = &intel->pClipRects[i];   
+        drm_clip_rect_t b;
+
+        if (!all) {
+           GLint x = box[i].x1;
+           GLint y = box[i].y1;
+           GLint w = box[i].x2 - x;
+           GLint h = box[i].y2 - y;
+
+           if (x < cx) w -= cx - x, x = cx; 
+           if (y < cy) h -= cy - y, y = cy;
+           if (x + w > cx + cw) w = cx + cw - x;
+           if (y + h > cy + ch) h = cy + ch - y;
+           if (w <= 0) continue;
+           if (h <= 0) continue;
+
+           b.x1 = x;
+           b.y1 = y;
+           b.x2 = x + w;
+           b.y2 = y + h;      
+        } else {
+           b = *box;
+        }
+
+
+        if (b.x1 > b.x2 ||
+            b.y1 > b.y2 ||
+            b.x2 > intelScreen->width ||
+            b.y2 > intelScreen->height)
+           continue;
+
+        if ( flags & DD_FRONT_LEFT_BIT ) {         
+           BEGIN_BATCH( 6);        
+           OUT_BATCH( CMD );
+           OUT_BATCH( BR13 );
+           OUT_BATCH( (b.y1 << 16) | b.x1 );
+           OUT_BATCH( (b.y2 << 16) | b.x2 );
+           OUT_BATCH( intelScreen->frontOffset );
+           OUT_BATCH( clear_color );
+           ADVANCE_BATCH();
+        }
+
+        if ( flags & DD_BACK_LEFT_BIT ) {
+           BEGIN_BATCH( 6); 
+           OUT_BATCH( CMD );
+           OUT_BATCH( BR13 );
+           OUT_BATCH( (b.y1 << 16) | b.x1 );
+           OUT_BATCH( (b.y2 << 16) | b.x2 );
+           OUT_BATCH( intelScreen->backOffset );
+           OUT_BATCH( clear_color );
+           ADVANCE_BATCH();
+        }
+
+        if ( flags & (DD_STENCIL_BIT | DD_DEPTH_BIT) ) {
+           BEGIN_BATCH( 6);
+           OUT_BATCH( D_CMD );
+           OUT_BATCH( BR13 );
+           OUT_BATCH( (b.y1 << 16) | b.x1 );
+           OUT_BATCH( (b.y2 << 16) | b.x2 );
+           OUT_BATCH( intelScreen->depthOffset );
+           OUT_BATCH( clear_depth );
+           ADVANCE_BATCH();
+        }      
+      }
+   }
+   intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
+   UNLOCK_HARDWARE( intel );
+}
+
+
+
+
+void intelDestroyBatchBuffer( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+
+   if (intel->alloc.ptr) {
+      intelFreeAGP( intel, intel->alloc.ptr );
+      intel->alloc.ptr = 0;
+   }
+}
+
+
+void intelInitBatchBuffer( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+
+   if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
+      intel->alloc.size = 8 * 1024;
+      intel->alloc.ptr = malloc( intel->alloc.size );
+      intel->alloc.offset = 0;
+   }
+   else {
+      switch (intel->intelScreen->deviceID) {
+      case PCI_CHIP_I865_G:
+        /* HW bug?  Seems to crash if batchbuffer crosses 4k boundary.
+         */
+        intel->alloc.size = 8 * 1024; 
+        break;
+      default:
+        /* This is the smallest amount of memory the kernel deals with.
+         * We'd ideally like to make this smaller.
+         */
+        intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
+        break;
+      }
+
+      intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
+      if (intel->alloc.ptr)
+        intel->alloc.offset = 
+           intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
+   }
+
+   if (!intel->alloc.ptr) {
+      FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1);
+   }
+   else {
+      intel->prim.flush = 0;
+      intel->vtbl.emit_invarient_state( intel );
+
+      /* Make sure this gets to the hardware, even if we have no cliprects:
+       */
+      LOCK_HARDWARE( intel );
+      intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
+      UNLOCK_HARDWARE( intel );
+   }
+}
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.h b/src/mesa/drivers/dri/i915/intel_batchbuffer.h
new file mode 100644 (file)
index 0000000..d96b3e2
--- /dev/null
@@ -0,0 +1,103 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_BATCHBUFFER_H
+#define INTEL_BATCHBUFFER_H
+
+#include "intel_context.h"
+#include "intel_ioctl.h"
+
+
+#define BATCH_LOCALS   GLubyte *batch_ptr;
+
+/* #define VERBOSE 0 */
+#ifndef VERBOSE
+extern int VERBOSE;
+#endif
+
+
+#define BEGIN_BATCH(n)                                                 \
+do {                                                                   \
+   if (VERBOSE) fprintf(stderr,                                        \
+                       "BEGIN_BATCH(%d) in %s, %d dwords free\n",      \
+                       (n), __FUNCTION__, intel->batch.space/4);       \
+   if (intel->batch.space < (n)*4)                                     \
+      intelFlushBatch(intel, GL_TRUE);                                 \
+   batch_ptr = intel->batch.ptr;                                       \
+} while (0)
+
+#define OUT_BATCH(n)                                   \
+do {                                                   \
+   *(GLuint *)batch_ptr = (n);                         \
+   if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__);       \
+   batch_ptr += 4;                                     \
+} while (0)
+
+#define ADVANCE_BATCH()                                                \
+do {                                                           \
+   if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n");          \
+   intel->batch.space -= (batch_ptr - intel->batch.ptr);       \
+   intel->batch.ptr = batch_ptr;                               \
+   assert(intel->batch.space >= 0);                            \
+} while(0)
+
+extern void intelInitBatchBuffer( GLcontext *ctx );
+extern void intelDestroyBatchBuffer( GLcontext *ctx );
+
+extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim );
+extern void intelWrapInlinePrimitive( intelContextPtr intel );
+extern void intelRestartInlinePrimitive( intelContextPtr intel );
+extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, 
+                                             int primitive, int dwords,
+                                             int vertex_size);
+extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
+extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
+                            GLint cx1, GLint cy1, GLint cw, GLint ch);
+
+extern void intelEmitCopyBlitLocked( intelContextPtr intel,
+                                    GLuint cpp,
+                                    GLshort src_pitch,
+                                    GLuint  src_offset,
+                                    GLshort dst_pitch,
+                                    GLuint  dst_offset,
+                                    GLshort srcx, GLshort srcy,
+                                    GLshort dstx, GLshort dsty,
+                                    GLshort w, GLshort h );
+
+extern void intelEmitFillBlitLocked( intelContextPtr intel,
+                                    GLuint cpp,
+                                    GLshort dst_pitch,
+                                    GLuint dst_offset,
+                                    GLshort x, GLshort y, 
+                                    GLshort w, GLshort h,
+                                    GLuint color );
+
+
+
+
+static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel, 
+                                               GLuint dwords )
+{
+   GLuint sz = dwords * sizeof(GLuint);
+   GLuint *ptr;
+
+   if (intel->batch.space < sz) {
+      intelWrapInlinePrimitive( intel );
+/*       assert(intel->batch.space >= sz); */
+   }
+
+/*    assert(intel->prim.primitive != ~0); */
+   ptr = (GLuint *)intel->batch.ptr;
+   intel->batch.ptr += sz;
+   intel->batch.space -= sz;
+
+   return ptr;
+}
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
new file mode 100644 (file)
index 0000000..9e11646
--- /dev/null
@@ -0,0 +1,666 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#include "glheader.h"
+#include "context.h"
+#include "matrix.h"
+#include "simple_list.h"
+#include "extensions.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 "i830_common.h"
+
+#include "intel_tex.h"
+#include "intel_span.h"
+#include "intel_tris.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+
+#include "utils.h"
+#ifndef INTEL_DEBUG
+int INTEL_DEBUG = (0);
+#endif
+
+#ifndef VERBOSE
+int VERBOSE = 0;
+#endif
+
+#if DEBUG_LOCKING
+char *prevLockFile;
+int prevLockLine;
+#endif
+
+const char __driConfigOptions[] = { 0 };
+const GLuint __driNConfigOptions = 0;
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+#define DRIVER_DATE                     "20040528"
+
+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;
+      default:
+        chipset = "Unknown Intel Chipset"; break;
+      }
+
+      (void) driGetRendererString( buffer, chipset, DRIVER_DATE, 0 );
+      return (GLubyte *) buffer;
+
+   default:
+      return NULL;
+   }
+}
+
+static void intelBufferSize(GLframebuffer *buffer,
+                          GLuint *width, GLuint *height)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   intelContextPtr 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.
+    */
+   LOCK_HARDWARE(intel);
+   *width = intel->driDrawable->w;
+   *height = intel->driDrawable->h;
+   UNLOCK_HARDWARE(intel);
+}
+
+
+
+/* Extension strings exported by the intel driver.
+ *
+ * NOTE: See implementation of glGetString in each hw_context.c file:
+ * This set of extensions is overridden and many are not actually
+ * exported to the driver.  They are however enabled internally as
+ * Mesa requires this when calculating things like GL version number.
+ */
+static const char * const card_extensions[] =
+{
+   "GL_APPLE_client_storage",
+   "GL_ARB_multisample",
+   "GL_ARB_multitexture",
+   "GL_ARB_texture_border_clamp",
+   "GL_ARB_texture_compression",
+   "GL_ARB_texture_env_add",
+   "GL_ARB_texture_env_combine",
+   "GL_ARB_texture_env_dot3",
+   "GL_ARB_texture_mirrored_repeat",
+   "GL_ARB_vertex_program",
+   "GL_EXT_blend_color",
+   "GL_EXT_blend_func_separate",
+   "GL_EXT_blend_minmax",
+   "GL_EXT_blend_subtract",
+   "GL_EXT_fog_coord",
+   "GL_EXT_secondary_color",
+   "GL_EXT_stencil_wrap",
+   "GL_EXT_texture_edge_clamp",
+   "GL_EXT_texture_env_add",
+   "GL_EXT_texture_env_combine",
+   "GL_EXT_texture_env_dot3",
+   "GL_EXT_texture_filter_anisotropic",
+   "GL_EXT_texture_lod_bias",
+   "GL_IBM_texture_mirrored_repeat",
+   "GL_INGR_blend_func_separate",
+   "GL_MESA_pack_invert",
+   "GL_MESA_ycbcr_texture",
+   "GL_NV_texture_rectangle",
+   "GL_NV_vertex_program",
+
+/* New in final:
+ */
+   "GL_ARB_vertex_buffer_object",
+   "GL_ARB_window_pos",
+   "GL_EXT_multi_draw_arrays",
+   "GL_EXT_abgr",
+   "GL_EXT_bgra",
+
+
+   "GL_SGIS_generate_mipmap",
+   "GL_SGIS_texture_border_clamp",
+   "GL_SGIS_texture_edge_clamp",
+   NULL
+};
+
+
+extern const struct tnl_pipeline_stage _intel_render_stage;
+
+static const struct tnl_pipeline_stage *intel_pipeline[] = {
+   &_tnl_vertex_transform_stage,
+   &_tnl_normal_transform_stage,
+   &_tnl_lighting_stage,
+   &_tnl_fog_coordinate_stage,
+   &_tnl_texgen_stage,
+   &_tnl_texture_transform_stage,
+   &_tnl_point_attenuation_stage,
+   &_tnl_vertex_program_stage,
+#if 1
+   &_intel_render_stage,     /* ADD: unclipped rastersetup-to-dma */
+#endif
+   &_tnl_render_stage,
+   0,
+};
+
+
+static const struct dri_debug_control debug_control[] =
+{
+    { "fall",  DEBUG_FALLBACKS },
+    { "tex",   DEBUG_TEXTURE },
+    { "ioctl", DEBUG_IOCTL },
+    { "prim",  DEBUG_PRIMS },
+    { "vert",  DEBUG_VERTS },
+    { "state", DEBUG_STATE },
+    { "verb",  DEBUG_VERBOSE },
+    { "dri",   DEBUG_DRI },
+    { "dma",   DEBUG_DMA },
+    { "san",   DEBUG_SANITY },
+    { "sync",  DEBUG_SYNC },
+    { "sleep", DEBUG_SLEEP },
+    { "pix",   DEBUG_PIXEL },
+    { 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 intelInitDriverFunctions( struct dd_function_table *functions )
+{
+   _mesa_init_driver_functions( functions );
+
+   functions->Flush = intelFlush;
+   functions->Clear = intelClear;
+   functions->Finish = intelFinish;
+   functions->GetBufferSize = intelBufferSize;
+   functions->ResizeBuffers = _swrast_alloc_buffers;
+   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 );
+}
+
+
+
+GLboolean intelInitContext( intelContextPtr 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);
+
+   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;
+
+
+   (void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) );
+   make_empty_list( & intel->swapped );
+
+   ctx->Const.MaxTextureMaxAnisotropy = 2.0;
+
+   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;
+
+   /* 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_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
+   intel->hw_stipple = 1;
+
+   switch(mesaVis->depthBits) {
+   case 0:                     /* what to do in this case? */
+   case 16:
+      intel->depth_scale = 1.0/0xffff;
+      intel->polygon_offset_scale = 1.0/0xffff;
+      intel->depth_clear_mask = ~0;
+      intel->ClearDepth = 0xffff;
+      break;
+   case 24:
+      intel->depth_scale = 1.0/0xffffff;
+      intel->polygon_offset_scale = 2.0/0xffffff; /* req'd to pass glean */
+      intel->depth_clear_mask = 0x00ffffff;
+      intel->stencil_clear_mask = 0xff000000;
+      intel->ClearDepth = 0x00ffffff;
+      break;
+   default:
+      assert(0); 
+      break;
+   }
+
+   /* Initialize swrast, tnl driver tables: */
+   intelInitSpanFuncs( ctx );
+   intelInitTriFuncs( ctx );
+
+
+   intel->RenderIndex = ~0;
+
+   intel->do_irqs = (intel->intelScreen->irq_active &&
+                    !getenv("INTEL_NO_IRQS"));
+
+   _math_matrix_ctr (&intel->ViewportMatrix);
+
+   driInitExtensions( ctx, card_extensions, GL_TRUE );
+
+/*    driInitTextureObjects( ctx, & intel->swapped, */
+/*                       DRI_TEXMGR_DO_TEXTURE_1D | */
+/*                       DRI_TEXMGR_DO_TEXTURE_2D |  */
+/*                       DRI_TEXMGR_DO_TEXTURE_RECT ); */
+
+
+   intel->prim.flush = intelInitBatchBuffer;
+   intel->prim.primitive = ~0;
+
+
+#if DO_DEBUG
+   INTEL_DEBUG  = driParseDebugString( getenv( "INTEL_DEBUG" ),
+                                      debug_control );
+   INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
+                                      debug_control );
+#endif
+
+#ifndef VERBOSE
+   if (getenv("INTEL_VERBOSE"))
+      VERBOSE=1;
+#endif
+
+   if (getenv("INTEL_NO_RAST") || 
+       getenv("INTEL_NO_RAST")) {
+      fprintf(stderr, "disabling 3D rasterization\n");
+      FALLBACK(intel, INTEL_FALLBACK_USER, 1); 
+   }
+
+   return GL_TRUE;
+}
+
+void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
+{
+   intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
+
+   assert(intel); /* should never be null */
+   if (intel) {
+      GLboolean   release_texture_heaps;
+
+
+      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 */
+
+      intelDestroyBatchBuffer(&intel->ctx);
+      
+
+      if ( release_texture_heaps ) {
+         /* This share group is about to go away, free our private
+          * texture object data.
+          */
+         int i;
+
+         for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
+           driDestroyTextureHeap( intel->texture_heaps[ i ] );
+           intel->texture_heaps[ i ] = NULL;
+         }
+
+        assert( is_empty_list( & intel->swapped ) );
+      }
+
+      /* free the Mesa context */
+      _mesa_destroy_context(&intel->ctx);
+   }
+}
+
+void intelSetFrontClipRects( intelContextPtr intel )
+{
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+   if (!dPriv) return;
+
+   intel->numClipRects = dPriv->numClipRects;
+   intel->pClipRects = dPriv->pClipRects;
+   intel->drawX = dPriv->x;
+   intel->drawY = dPriv->y;
+}
+
+
+void intelSetBackClipRects( intelContextPtr intel )
+{
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+   if (!dPriv) return;
+
+   if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
+      intel->numClipRects = dPriv->numClipRects;
+      intel->pClipRects = dPriv->pClipRects;
+      intel->drawX = dPriv->x;
+      intel->drawY = dPriv->y;
+   } else {
+      intel->numClipRects = dPriv->numBackClipRects;
+      intel->pClipRects = dPriv->pBackClipRects;
+      intel->drawX = dPriv->backX;
+      intel->drawY = dPriv->backY;
+      
+      if (dPriv->numBackClipRects == 1 &&
+         dPriv->x == dPriv->backX &&
+         dPriv->y == dPriv->backY) {
+      
+        /* Repeat the calculation of the back cliprect dimensions here
+         * as early versions of dri.a in the Xserver are incorrect.  Try
+         * very hard not to restrict future versions of dri.a which
+         * might eg. allocate truly private back buffers.
+         */
+        int x1, y1;
+        int x2, y2;
+        
+        x1 = dPriv->x;
+        y1 = dPriv->y;      
+        x2 = dPriv->x + dPriv->w;
+        y2 = dPriv->y + dPriv->h;
+        
+        if (x1 < 0) x1 = 0;
+        if (y1 < 0) y1 = 0;
+        if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
+        if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
+
+        if (x1 == dPriv->pBackClipRects[0].x1 &&
+            y1 == dPriv->pBackClipRects[0].y1) {
+
+           dPriv->pBackClipRects[0].x2 = x2;
+           dPriv->pBackClipRects[0].y2 = y2;
+        }
+      }
+   }
+}
+
+
+void intelWindowMoved( intelContextPtr intel )
+{
+   switch (intel->ctx.Color._DrawDestMask) {
+   case DD_FRONT_LEFT_BIT:
+      intelSetFrontClipRects( intel );
+      break;
+   case DD_BACK_LEFT_BIT:
+      intelSetBackClipRects( intel );
+      break;
+   default:
+      /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
+      intelSetFrontClipRects( intel );
+   }
+}
+
+GLboolean intelUnbindContext(__DRIcontextPrivate *driContextPriv)
+{
+   return GL_TRUE;
+}
+
+GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
+                         __DRIdrawablePrivate *driDrawPriv,
+                         __DRIdrawablePrivate *driReadPriv)
+{
+
+   if (driContextPriv) {
+      intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
+
+      if ( intel->driDrawable != driDrawPriv ) {
+        /* Shouldn't the readbuffer be stored also? */
+        intel->driDrawable = driDrawPriv;
+        intelWindowMoved( intel );
+      }
+
+      _mesa_make_current2(&intel->ctx,
+                         (GLframebuffer *) driDrawPriv->driverPrivate,
+                         (GLframebuffer *) driReadPriv->driverPrivate);
+
+      if (!intel->ctx.Viewport.Width)
+        _mesa_set_viewport(&intel->ctx, 0, 0, driDrawPriv->w, driDrawPriv->h);
+   } else {
+      _mesa_make_current(0,0);
+   }
+
+   return GL_TRUE;
+}
+
+void intelGetLock( intelContextPtr intel, GLuint flags )
+{
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   __DRIscreenPrivate *sPriv = intel->driScreen;
+   drmI830Sarea * sarea = intel->sarea;
+   int me = intel->hHWContext;
+   unsigned   i;
+
+   drmGetLock(intel->driFd, intel->hHWContext, flags);
+
+   /* 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 we lost context, need to dump all registers to hardware.
+    * Note that we don't care about 2d contexts, even if they perform
+    * accelerated commands, so the DRI locking in the X server is even
+    * more broken than usual.
+    */
+
+   if (sarea->ctxOwner != me) {
+      intel->perf_boxes |= I830_BOX_LOST_CONTEXT;
+      sarea->ctxOwner = me;
+   }
+
+   /* Shared texture managment - if another client has played with
+    * texture space, figure out which if any of our textures have been
+    * ejected, and update our global LRU.
+    */
+
+   for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
+      DRI_AGE_TEXTURES( intel->texture_heaps[ i ] );
+   }
+
+   if (dPriv && intel->lastStamp != dPriv->lastStamp) {
+      intelWindowMoved( intel );
+      intel->lastStamp = dPriv->lastStamp;
+   }
+}
+
+void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      intelContextPtr intel;
+      GLcontext *ctx;
+      intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = &intel->ctx;
+      if (ctx->Visual.doubleBufferMode) {
+        _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+        if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
+           intelPageFlip( dPriv );
+        } else {
+           intelCopyBuffer( dPriv );
+        }
+      }
+   } 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__);
+   }
+}
+
+
+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.StencilFunc( ctx, 
+                           ctx->Stencil.Function[0],
+                           ctx->Stencil.Ref[0],
+                           ctx->Stencil.ValueMask[0] );
+   ctx->Driver.StencilMask( ctx, ctx->Stencil.WriteMask[0] );
+   ctx->Driver.StencilOp( ctx, 
+                         ctx->Stencil.FailFunc[0],
+                         ctx->Stencil.ZFailFunc[0],
+                         ctx->Stencil.ZPassFunc[0]);
+
+
+   ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer );
+}
diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h
new file mode 100644 (file)
index 0000000..c72ef61
--- /dev/null
@@ -0,0 +1,431 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef INTELCONTEXT_INC
+#define INTELCONTEXT_INC
+
+
+
+#include "mtypes.h"
+#include "drm.h"
+#include "mm.h"
+#include "texmem.h"
+
+#include "intel_screen.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)
+
+#define INTEL_CONTEXT(ctx)     ((intelContextPtr)(ctx))
+
+typedef struct intel_context intelContext;
+typedef struct intel_context *intelContextPtr;
+typedef struct intel_texture_object *intelTextureObjectPtr;
+
+typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *,
+                                                         intelVertex *);
+typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *);
+typedef void (*intel_point_func)(intelContextPtr, intelVertex *);
+
+#define INTEL_FALLBACK_DRAW_BUFFER      0x1
+#define INTEL_FALLBACK_READ_BUFFER      0x2
+#define INTEL_FALLBACK_USER             0x4
+#define INTEL_FALLBACK_NO_BATCHBUFFER   0x8
+#define INTEL_FALLBACK_NO_TEXMEM        0x10
+#define INTEL_FALLBACK_RENDERMODE       0x20
+
+extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode );
+#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
+
+
+#define INTEL_TEX_MAXLEVELS 10
+
+
+struct intel_texture_object
+{
+   driTextureObject    base;   /* the parent class */
+
+   GLuint texelBytes;
+   GLuint age;
+   GLuint Pitch;
+   GLuint Height;
+   GLuint TextureOffset;
+   GLubyte *BufAddr;   
+
+   GLuint min_level;
+   GLuint max_level;
+   GLuint depth_pitch;
+
+   struct {
+      const struct gl_texture_image *image;
+      GLuint offset;       /* into BufAddr */
+      GLuint height;
+      GLuint internalFormat;
+   } image[6][INTEL_TEX_MAXLEVELS];
+
+   GLuint dirty;
+   GLuint firstLevel,lastLevel;
+};
+
+
+struct intel_context
+{
+   GLcontext ctx;              /* the parent class */
+
+   struct {
+      void (*destroy)( intelContextPtr intel ); 
+      void (*emit_state)( intelContextPtr intel );
+      void (*emit_invarient_state)( intelContextPtr intel );
+      void (*lost_hardware)( intelContextPtr intel );
+      void (*update_texture_state)( intelContextPtr intel );
+
+      void (*render_start)( intelContextPtr intel );
+      void (*set_draw_offset)( intelContextPtr intel, int offset );
+      void (*emit_flush)( intelContextPtr intel );
+
+      void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim );
+
+      GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected );
+
+      void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask,
+                              GLboolean all, 
+                              GLint cx, GLint cy, GLint cw, GLint ch);
+
+      intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj );
+
+   } vtbl;
+
+   GLint refcount;   
+   GLuint Fallback;
+   GLuint NewGLState;
+   
+   struct {
+      GLuint start_offset;
+      GLint size;
+      GLint space;
+      GLubyte *ptr;
+   } batch;
+      
+   struct {
+      void *ptr;
+      GLint size;
+      GLuint offset;
+      GLuint active_buf;
+      GLuint irq_emitted;
+   } alloc;
+
+   struct {
+      GLuint primitive;
+      GLubyte *start_ptr;      
+      void (*flush)( GLcontext * );
+   } prim;
+
+   GLboolean locked;
+
+   GLubyte clear_red;
+   GLubyte clear_green;
+   GLubyte clear_blue;
+   GLubyte clear_alpha;
+   GLuint ClearColor;
+   GLuint ClearDepth;
+
+   GLuint coloroffset;
+   GLuint specoffset;
+
+   /* Support for duplicating XYZW as WPOS parameter (crutch for I915).
+    */
+   GLuint wpos_offset;
+   GLuint wpos_size;
+
+   struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
+   GLuint vertex_attr_count;
+
+   GLfloat depth_scale;
+   GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */
+   GLuint depth_clear_mask;
+   GLuint stencil_clear_mask;
+
+   GLboolean hw_stencil;
+   GLboolean hw_stipple;
+   
+   /* Texture object bookkeeping
+    */
+   GLuint                nr_heaps;
+   driTexHeap          * texture_heaps[1];
+   driTextureObject      swapped;
+   GLuint                lastStamp;
+
+   struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
+
+   /* State for intelvb.c and inteltris.c.
+    */
+   GLuint RenderIndex;
+   GLmatrix ViewportMatrix;
+   GLenum render_primitive;
+   GLenum reduced_primitive;
+   GLuint vertex_size;
+   char *verts;                        /* points to tnl->clipspace.vertex_buf */
+
+
+   /* Fallback rasterization functions 
+    */
+   intel_point_func draw_point;
+   intel_line_func draw_line;
+   intel_tri_func draw_tri;
+
+   /* These refer to the current draw (front vs. back) buffer:
+    */
+   char *drawMap;              /* draw buffer address in virtual mem */
+   char *readMap;      
+   GLuint drawOffset;          /* agp offset of drawbuffer */
+   int drawX;                  /* origin of drawable in draw buffer */
+   int drawY;
+   GLuint numClipRects;                /* cliprects for that buffer */
+   drm_clip_rect_t *pClipRects;
+
+   int dirtyAge;
+   int perf_boxes;
+   int do_irqs;
+
+   GLboolean scissor;
+   drm_clip_rect_t draw_rect;
+   drm_clip_rect_t scissor_rect;
+
+   drm_context_t hHWContext;
+   drmLock *driHwLock;
+   int driFd;
+
+   __DRIdrawablePrivate *driDrawable;
+   __DRIscreenPrivate *driScreen;
+   intelScreenPrivate *intelScreen; 
+   drmI830Sarea *sarea; 
+};
+
+
+#define DEBUG_LOCKING  1
+
+#if DEBUG_LOCKING
+extern char *prevLockFile;
+extern int prevLockLine;
+
+#define DEBUG_LOCK()                                                   \
+   do {                                                                        \
+      prevLockFile = (__FILE__);                                       \
+      prevLockLine = (__LINE__);                                       \
+   } while (0)
+
+#define DEBUG_RESET()                                                  \
+   do {                                                                        \
+      prevLockFile = 0;                                                        \
+      prevLockLine = 0;                                                        \
+   } while (0)
+
+/* Slightly less broken way of detecting recursive locking in a
+ * threaded environment.  The right way to do this would be to make
+ * prevLockFile, prevLockLine thread-local.
+ *
+ * This technique instead checks to see if the same context is
+ * requesting the lock twice -- this will not catch application
+ * breakages where the same context is active in two different threads
+ * at once, but it will catch driver breakages (recursive locking) in
+ * threaded apps.
+ */
+#define DEBUG_CHECK_LOCK()                                             \
+   do {                                                                        \
+      if ( *((volatile int *)intel->driHwLock) ==                      \
+          (DRM_LOCK_HELD | intel->hHWContext) ) {                      \
+        fprintf( stderr,                                               \
+                 "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n",    \
+                 prevLockFile, prevLockLine, __FILE__, __LINE__ );     \
+        abort();                                                       \
+      }                                                                        \
+   } while (0)
+
+#else
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+#endif
+
+
+
+
+/* Lock the hardware and validate our state.  
+ */
+#define LOCK_HARDWARE( intel )                         \
+do {                                                   \
+    char __ret=0;                                      \
+    DEBUG_CHECK_LOCK();                                        \
+    assert(!(intel)->locked);                          \
+    DRM_CAS((intel)->driHwLock, (intel)->hHWContext,   \
+        (DRM_LOCK_HELD|(intel)->hHWContext), __ret);   \
+    if (__ret)                                         \
+        intelGetLock( (intel), 0 );                    \
+      DEBUG_LOCK();                                    \
+    (intel)->locked = 1;                               \
+}while (0)
+  
+  /* Unlock the hardware using the global current context 
+   */
+#define UNLOCK_HARDWARE(intel)                                         \
+do {                                                                   \
+   intel->locked = 0;                                                  \
+   if (0) {                                                            \
+      intel->perf_boxes |= intel->sarea->perf_boxes;                   \
+      intel->sarea->perf_boxes = 0;                                    \
+   }                                                                   \
+   DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext);        \
+   DEBUG_RESET();                                                      \
+} while (0)
+
+
+#define SUBPIXEL_X 0.125
+#define SUBPIXEL_Y 0.125
+
+#define INTEL_FIREVERTICES(intel)              \
+do {                                           \
+   if ((intel)->prim.flush)                    \
+      (intel)->prim.flush(&(intel)->ctx);              \
+} 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)
+
+
+#define INTEL_PACKCOLOR(format, r,  g,  b, a)          \
+(format == DV_PF_555 ? INTEL_PACKCOLOR1555(r,g,b,a) :  \
+ (format == DV_PF_565 ? INTEL_PACKCOLOR565(r,g,b) :    \
+  (format == DV_PF_8888 ? INTEL_PACKCOLOR8888(r,g,b,a) :       \
+   0)))
+
+
+
+/* ================================================================
+ * From linux kernel i386 header files, copes with odd sizes better
+ * than COPY_DWORDS would:
+ */
+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);
+}
+
+
+
+/* ================================================================
+ * 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_PRIMS    0x8
+#define DEBUG_VERTS    0x10
+#define DEBUG_FALLBACKS        0x20
+#define DEBUG_VERBOSE  0x40
+#define DEBUG_DRI       0x80
+#define DEBUG_DMA       0x100
+#define DEBUG_SANITY    0x200
+#define DEBUG_SYNC      0x400
+#define DEBUG_SLEEP     0x800
+#define DEBUG_PIXEL     0x1000
+
+
+#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
+
+
+/* ================================================================
+ * intel_context.c:
+ */
+
+extern void intelInitDriverFunctions( struct dd_function_table *functions );
+
+extern GLboolean intelInitContext( intelContextPtr intel, 
+                                  const __GLcontextModes *mesaVis,
+                                  __DRIcontextPrivate *driContextPriv,
+                                  void *sharedContextPrivate,
+                                  struct dd_function_table *functions );
+
+extern void intelGetLock(intelContextPtr intel, GLuint flags);
+extern void intelSetBackClipRects(intelContextPtr intel);
+extern void intelSetFrontClipRects(intelContextPtr intel);
+extern void intelWindowMoved( intelContextPtr intel );
+
+extern void intelInitState( GLcontext *ctx );
+extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name );
+
+
+/* ================================================================
+ * intel_state.c:
+ */
+extern void intelInitStateFuncs( struct dd_function_table *functions );
+
+
+/* ================================================================
+ * intel_ioctl.c:
+ */
+extern void intel_dump_batchbuffer( long offset,
+                                   int *ptr,
+                                   int count );
+
+
+/* ================================================================
+ * intel_pixel.c:
+ */    
+extern void intelInitPixelFuncs( struct dd_function_table *functions );
+
+
+
+#endif
+
diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.c b/src/mesa/drivers/dri/i915/intel_ioctl.c
new file mode 100644 (file)
index 0000000..2fa88b5
--- /dev/null
@@ -0,0 +1,585 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "mtypes.h"
+#include "context.h"
+#include "swrast/swrast.h"
+
+#include "intel_context.h"
+#include "intel_ioctl.h"
+#include "intel_batchbuffer.h"
+#include "drm.h"
+
+
+
+static int intelEmitIrqLocked( intelContextPtr 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);
+   }
+   
+   if (0)
+      fprintf(stderr, "%s -->  %d\n", __FUNCTION__, seq );
+
+   return seq;
+}
+
+static void intelWaitIrq( intelContextPtr intel, int seq )
+{
+   drmI830IrqWait iw;
+   int ret;
+      
+   if (0)
+      fprintf(stderr, "%s %d\n", __FUNCTION__, seq );
+
+   iw.irq_seq = seq;
+        
+   do {
+      ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) );
+   } while (ret == -EAGAIN || ret == -EINTR);
+
+   if ( ret ) {
+      fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
+      if (0)
+        intel_dump_batchbuffer( intel->alloc.offset,
+                                intel->alloc.ptr,
+                                intel->alloc.size );
+      exit(1);
+   }
+}
+
+
+
+static void age_intel( intelContextPtr intel, int age )
+{
+   GLuint i;
+
+   for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
+      if (intel->CurrentTexObj[i]) 
+        intel->CurrentTexObj[i]->age = age;
+}
+
+void intel_dump_batchbuffer( long offset,
+                            int *ptr,
+                            int count )
+{
+   int i;
+   fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count);
+   for (i = 0; i < count/4; i += 4) 
+      fprintf(stderr, "\t0x%x: 0x%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 intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock )
+{
+   GLuint last_irq = intel->alloc.irq_emitted;
+   GLuint half = intel->alloc.size / 2;
+   GLuint buf = (intel->alloc.active_buf ^= 1);
+
+   intel->alloc.irq_emitted = intelEmitIrqLocked( intel );
+
+   if (last_irq) {
+      if (allow_unlock) UNLOCK_HARDWARE( intel ); 
+      intelWaitIrq( intel, last_irq );
+      if (allow_unlock) LOCK_HARDWARE( intel ); 
+   }
+
+   if (0)
+      fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf);
+
+   intel->batch.start_offset = intel->alloc.offset + buf * half;
+   intel->batch.ptr = (char *)intel->alloc.ptr + buf * half;
+   intel->batch.size = half - 8;
+   intel->batch.space = half - 8;
+   assert(intel->batch.space >= 0);
+}
+
+#define MI_BATCH_BUFFER_END    (0xA<<23)
+
+
+void intelFlushBatchLocked( intelContextPtr intel, 
+                           GLboolean ignore_cliprects,
+                           GLboolean refill,
+                           GLboolean allow_unlock)
+{
+   drmI830BatchBuffer batch;
+
+   assert(intel->locked);
+
+   if (0)
+      fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n",
+             __FUNCTION__, 
+             (intel->batch.size - intel->batch.space), 
+             intel->batch.size,
+             intel->batch.start_offset,
+             intel->batch.start_offset + 
+             (intel->batch.size - intel->batch.space), 
+             refill);
+
+   /* 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.space = intel->batch.size;
+      
+      /* Without this yeild, an application with no cliprects can hog
+       * the hardware.  Without unlocking, the effect is much worse -
+       * effectively a lock-out of other contexts.
+       */
+      if (allow_unlock) {
+        UNLOCK_HARDWARE( intel );
+        sched_yield();
+        LOCK_HARDWARE( intel );
+      }
+
+      /* Note that any state thought to have been emitted actually
+       * hasn't:
+       */
+      intel->vtbl.lost_hardware( intel ); 
+   }
+
+   if (intel->batch.space != intel->batch.size) {
+      batch.start = intel->batch.start_offset;
+      batch.used = intel->batch.size - intel->batch.space;
+      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));
+      
+      if (intel->alloc.offset) {
+        if ((batch.used & 0x4) == 0) {
+           ((int *)intel->batch.ptr)[0] = 0;
+           ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END;
+           batch.used += 0x8;
+           intel->batch.ptr += 0x8;
+        }
+        else {
+           ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END;
+           batch.used += 0x4;
+           intel->batch.ptr += 0x4;
+        }      
+      }
+
+      if (0)
+        intel_dump_batchbuffer( batch.start,
+                                (int *)(intel->batch.ptr - batch.used),
+                                batch.used );
+
+      if (0)
+        fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
+                __FUNCTION__, 
+                batch.start, 
+                batch.start + batch.used,
+                batch.DR4, batch.num_cliprects);
+
+      intel->batch.start_offset += batch.used;
+      intel->batch.size -= batch.used;
+
+      if (intel->batch.size < 8) {
+        refill = GL_TRUE;
+        intel->batch.space = intel->batch.size = 0;
+      }
+      else {
+        intel->batch.size -= 8;
+        intel->batch.space = intel->batch.size;
+      }
+
+
+      assert(intel->batch.space >= 0);
+      assert(batch.start >= intel->alloc.offset);
+      assert(batch.start < intel->alloc.offset + intel->alloc.size);
+      assert(batch.start + batch.used > intel->alloc.offset);
+      assert(batch.start + batch.used <= 
+            intel->alloc.offset + intel->alloc.size);
+
+
+      if (intel->alloc.offset) {
+        if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch, 
+                             sizeof(batch))) {
+           fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n",  -errno);
+           UNLOCK_HARDWARE(intel);
+           exit(1);
+        }
+      } else {
+        drmI830CmdBuffer cmd;
+        cmd.buf = intel->alloc.ptr + batch.start;
+        cmd.sz = batch.used;
+        cmd.DR1 = batch.DR1;
+        cmd.DR4 = batch.DR4;
+        cmd.num_cliprects = batch.num_cliprects;
+        cmd.cliprects = batch.cliprects;
+        
+        if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd, 
+                             sizeof(cmd))) {
+           fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n",  -errno);
+           UNLOCK_HARDWARE(intel);
+           exit(1);
+        }
+      }         
+
+      
+      age_intel(intel, intel->sarea->last_enqueue);
+
+      /* FIXME: use hardware contexts to avoid 'losing' hardware after
+       * each buffer flush.
+       */
+      intel->vtbl.lost_hardware( intel );
+   }
+
+   if (refill)
+      intelRefillBatchLocked( intel, allow_unlock );
+}
+
+void intelFlushBatch( intelContextPtr intel, GLboolean refill )
+{
+   if (intel->locked) {
+      intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE );
+   } 
+   else {
+      LOCK_HARDWARE(intel);
+      intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE );
+      UNLOCK_HARDWARE(intel);
+   }
+}
+
+
+
+
+
+
+
+void intelWaitForIdle( intelContextPtr intel )
+{   
+   if (0)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   intel->vtbl.emit_flush( intel );
+   intelFlushBatch( intel, GL_TRUE );
+
+   /* Use an irq to wait for dma idle -- Need to track lost contexts
+    * to shortcircuit consecutive calls to this function:
+    */
+   intelWaitIrq( intel, intel->alloc.irq_emitted );
+   intel->alloc.irq_emitted = 0;
+}
+
+
+
+void intelFlush( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+
+   if (intel->Fallback)
+      _swrast_flush( ctx );
+
+   INTEL_FIREVERTICES( intel );
+
+   if (intel->batch.size != intel->batch.space)
+      intelFlushBatch( intel, GL_FALSE );
+}
+
+void intelFinish( GLcontext *ctx  ) 
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   intelFlush( ctx );
+   intelWaitForIdle( intel );
+}
+
+
+void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+               GLint cx, GLint cy, GLint cw, GLint ch)
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
+   GLbitfield tri_mask = 0;
+   GLbitfield blit_mask = 0;
+   GLbitfield swrast_mask = 0;
+
+   if (0)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* Take care of cliprects, which are handled differently for
+    * clears, etc.
+    */
+   intelFlush( &intel->ctx );
+
+   if (mask & DD_FRONT_LEFT_BIT) {
+      if (colorMask == ~0) {
+        blit_mask |= DD_FRONT_LEFT_BIT;
+      } 
+      else {
+        tri_mask |= DD_FRONT_LEFT_BIT;
+      }
+   }
+
+   if (mask & DD_BACK_LEFT_BIT) {
+      if (colorMask == ~0) {
+        blit_mask |= DD_BACK_LEFT_BIT;
+      } 
+      else {
+        tri_mask |= DD_BACK_LEFT_BIT;
+      }
+   }
+
+   if (mask & DD_DEPTH_BIT) {
+      blit_mask |= DD_DEPTH_BIT;
+   }
+
+   if (mask & DD_STENCIL_BIT) {
+      if (!intel->hw_stencil) {
+        swrast_mask |= DD_STENCIL_BIT;
+      }
+      else if (ctx->Stencil.WriteMask[0] != 0xff) {
+        tri_mask |= DD_STENCIL_BIT;
+      } 
+      else {
+        blit_mask |= DD_STENCIL_BIT;
+      }
+   }
+
+   swrast_mask |= (mask & DD_ACCUM_BIT);
+
+   if (blit_mask) 
+      intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
+
+   if (tri_mask) 
+      intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch);
+
+   if (swrast_mask)
+      _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
+}
+
+
+
+void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
+{
+   int region_offset;
+   drmI830MemAlloc alloc;
+   int ret;
+
+   if (0)
+      fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size);
+
+   alloc.region = I830_MEM_REGION_AGP;
+   alloc.alignment = 0;
+   alloc.size = size;
+   alloc.region_offset = &region_offset;
+
+   LOCK_HARDWARE(intel);
+
+   /* Make sure the global heap is initialized
+    */
+   if (intel->texture_heaps[0])
+      driAgeTextures( intel->texture_heaps[0] );
+
+
+   ret = drmCommandWriteRead( intel->driFd,
+                             DRM_I830_ALLOC,
+                             &alloc, sizeof(alloc));
+   
+   if (ret) {
+      fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret);
+      UNLOCK_HARDWARE(intel);
+      return NULL;
+   }
+   
+   if (0)
+      fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size);
+
+   /* Need to propogate this information (agp memory in use) to our
+    * local texture lru.  The kernel has already updated the global
+    * lru.  An alternative would have been to allocate memory the
+    * usual way and then notify the kernel to pin the allocation.
+    */
+   if (intel->texture_heaps[0])
+      driAgeTextures( intel->texture_heaps[0] );
+
+   UNLOCK_HARDWARE(intel);   
+
+   return (void *)((char *)intel->intelScreen->tex.map + region_offset);
+}
+
+void intelFreeAGP( intelContextPtr intel, void *pointer )
+{
+   int region_offset;
+   drmI830MemFree memfree;
+   int ret;
+
+   region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
+
+   if (region_offset < 0 || 
+       region_offset > intel->intelScreen->tex.size) {
+      fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
+             intel->intelScreen->tex.size);
+      return;
+   }
+
+   memfree.region = I830_MEM_REGION_AGP;
+   memfree.region_offset = region_offset;
+   
+   ret = drmCommandWrite( intel->driFd,
+                         DRM_I830_FREE,
+                         &memfree, sizeof(memfree));
+   
+   if (ret) 
+      fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret);
+}
+
+/* This version of AllocateMemoryMESA allocates only agp memory, and
+ * only does so after the point at which the driver has been
+ * initialized.
+ *
+ * Theoretically a valid context isn't required.  However, in this
+ * implementation, it is, as I'm using the hardware lock to protect
+ * the kernel data structures, and the current context to get the
+ * device fd.
+ */
+void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn,
+                             GLsizei size, GLfloat readfreq,
+                             GLfloat writefreq, GLfloat priority)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (INTEL_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq, 
+             writefreq, priority);
+
+   if (getenv("INTEL_NO_ALLOC"))
+      return NULL;
+   
+   if (!ctx || INTEL_CONTEXT(ctx) == 0) 
+      return NULL;
+   
+   return intelAllocateAGP( INTEL_CONTEXT(ctx), size );
+}
+
+
+/* Called via glXFreeMemoryMESA() */
+void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (INTEL_DEBUG & DEBUG_IOCTL) 
+      fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
+
+   if (!ctx || INTEL_CONTEXT(ctx) == 0) {
+      fprintf(stderr, "%s: no context\n", __FUNCTION__);
+      return;
+   }
+
+   intelFreeAGP( INTEL_CONTEXT(ctx), pointer );
+}
+
+/* Called via glXGetMemoryOffsetMESA() 
+ *
+ * Returns offset of pointer from the start of agp aperture.
+ */
+GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn, 
+                               const GLvoid *pointer)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   intelContextPtr intel;
+
+   if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) {
+      fprintf(stderr, "%s: no context\n", __FUNCTION__);
+      return ~0;
+   }
+
+   if (!intelIsAgpMemory( intel, pointer, 0 ))
+      return ~0;
+
+   return intelAgpOffsetFromVirtual( intel, pointer );
+}
+
+
+GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
+                          GLint size )
+{
+   int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
+   int valid = (size >= 0 &&
+               offset >= 0 &&
+               offset + size < intel->intelScreen->tex.size);
+
+   if (INTEL_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid );
+   
+   return valid;
+}
+
+
+GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer )
+{
+   int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
+
+   if (offset < 0 || offset > intel->intelScreen->tex.size)
+      return ~0;
+   else
+      return intel->intelScreen->textureOffset + offset;
+}
+
+
+
+
+
+/* Flip the front & back buffes
+ */
+void intelPageFlip( const __DRIdrawablePrivate *dPriv )
+{
+#if 0
+   intelContextPtr intel;
+   int tmp, ret;
+
+   if (INTEL_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   intel = (intelContextPtr) 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
+}
diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.h b/src/mesa/drivers/dri/i915/intel_ioctl.h
new file mode 100644 (file)
index 0000000..c6a8c7f
--- /dev/null
@@ -0,0 +1,46 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef INTEL_IOCTL_H
+#define INTEL_IOCTL_H
+
+#include "intel_context.h"
+
+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 intelPageFlip( const __DRIdrawablePrivate *dpriv );
+extern void intelWaitForIdle( intelContextPtr intel );
+extern void intelFlushBatch( intelContextPtr intel, GLboolean refill );
+extern void intelFlushBatchLocked( intelContextPtr intel,
+                                  GLboolean ignore_cliprects,
+                                  GLboolean refill,
+                                  GLboolean allow_unlock);
+extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock );
+extern void intelFinish( GLcontext *ctx );
+extern void intelFlush( GLcontext *ctx );
+
+extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size );
+extern void intelFreeAGP( intelContextPtr intel, void *pointer );
+
+extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn, 
+                                     GLsizei size, GLfloat readfreq,
+                                     GLfloat writefreq, GLfloat priority );
+
+extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn, 
+                                GLvoid *pointer );
+
+extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer );
+extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
+                                 GLint size );
+
+extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p );
+
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c
new file mode 100644 (file)
index 0000000..6ffc33a
--- /dev/null
@@ -0,0 +1,469 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "enums.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"
+
+
+
+static GLboolean
+check_color( const GLcontext *ctx, GLenum type, GLenum format,
+            const struct gl_pixelstore_attrib *packing,
+            const void *pixels, GLint sz, GLint pitch )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   GLuint cpp = intel->intelScreen->cpp;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (        (pitch & 63) ||
+       ctx->_ImageTransferState ||
+       packing->SwapBytes ||
+       packing->LsbFirst) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+        fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if ( type == GL_UNSIGNED_INT_8_8_8_8_REV && 
+       cpp == 4 && 
+       format == GL_BGRA ) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+        fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
+      return GL_TRUE;
+   }
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s: failed\n", __FUNCTION__);
+
+   return GL_FALSE;
+}
+
+static GLboolean
+check_color_per_fragment_ops( const GLcontext *ctx )
+{
+   int result;
+   result = (!(     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->Depth.OcclusionTest
+           ) &&
+          ctx->Current.RasterPosValid);
+   
+   return result;
+}
+
+
+
+static GLboolean
+clip_pixelrect( const GLcontext *ctx,
+               const GLframebuffer *buffer,
+               GLint *x, GLint *y,
+               GLsizei *width, GLsizei *height,
+               GLint *size )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+
+   /* left clipping */
+   if (*x < buffer->_Xmin) {
+      *width -= (buffer->_Xmin - *x);
+      *x = buffer->_Xmin;
+   }
+
+   /* right clipping */
+   if (*x + *width > buffer->_Xmax)
+      *width -= (*x + *width - buffer->_Xmax - 1);
+
+   if (*width <= 0)
+      return GL_FALSE;
+
+   /* bottom clipping */
+   if (*y < buffer->_Ymin) {
+      *height -= (buffer->_Ymin - *y);
+      *y = buffer->_Ymin;
+   }
+
+   /* top clipping */
+   if (*y + *height > buffer->_Ymax)
+      *height -= (*y + *height - buffer->_Ymax - 1);
+
+   if (*height <= 0)
+      return GL_FALSE;
+
+   *size = ((*y + *height - 1) * intel->intelScreen->frontPitch +
+           (*x + *width - 1) * intel->intelScreen->cpp);
+
+   return GL_TRUE;
+}
+
+static GLboolean
+intelTryReadPixels( GLcontext *ctx,
+                 GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLenum format, GLenum type,
+                 const struct gl_pixelstore_attrib *pack,
+                 GLvoid *pixels )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   GLint size;
+   GLint pitch = pack->RowLength ? pack->RowLength : width;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* Only accelerate reading to agp buffers.
+    */
+   if ( !intelIsAgpMemory(intel, pixels, 
+                       pitch * height * intel->intelScreen->cpp ) ) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+        fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
+    * blitter:
+    */
+   if (!pack->Invert) {
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+        fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   if (!check_color(ctx, type, format, pack, pixels, size, pitch))
+      return GL_FALSE;
+
+   switch ( intel->intelScreen->cpp ) {
+   case 4:
+      break;
+   default:
+      return GL_FALSE;
+   }
+
+
+   /* Although the blits go on the command buffer, need to do this and
+    * fire with lock held to guarentee cliprects and drawOffset are
+    * correct.
+    *
+    * This is an unusual situation however, as the code which flushes
+    * a full command buffer expects to be called unlocked.  As a
+    * workaround, immediately flush the buffer on aquiring the lock.
+    */
+   intelFlush( &intel->ctx );
+   LOCK_HARDWARE( intel );
+   {
+      __DRIdrawablePrivate *dPriv = intel->driDrawable;
+      int nbox = dPriv->numClipRects;
+      int src_offset = intel->drawOffset;
+      int src_pitch = intel->intelScreen->frontPitch;
+      int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
+      drm_clip_rect_t *box = dPriv->pClipRects;
+      int i;
+
+      if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
+                         &size)) {
+        UNLOCK_HARDWARE( intel );
+        if (INTEL_DEBUG & DEBUG_PIXEL)
+           fprintf(stderr, "%s totally clipped -- nothing to do\n",
+                   __FUNCTION__);
+        return GL_TRUE;
+      }
+
+
+      y = dPriv->h - y - height;
+      x += dPriv->x;
+      y += dPriv->y;
+
+
+      if (INTEL_DEBUG & DEBUG_PIXEL)
+        fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
+                src_pitch, pitch);
+
+      for (i = 0 ; i < nbox ; i++)
+      {
+        GLint bx = box[i].x1;
+        GLint by = box[i].y1;
+        GLint bw = box[i].x2 - bx;
+        GLint bh = box[i].y2 - by;
+        
+        if (bx < x) bw -= x - bx, bx = x;
+        if (by < y) bh -= y - by, by = y;
+        if (bx + bw > x + width) bw = x + width - bx;
+        if (by + bh > y + height) bh = y + height - by;
+        if (bw <= 0) continue;
+        if (bh <= 0) continue;
+
+        intelEmitCopyBlitLocked( intel,
+                           intel->intelScreen->cpp,
+                           src_pitch, src_offset,
+                           pitch, dst_offset,
+                           bx, by,
+                           bx - x, by - y,
+                           bw, bh );
+      }
+   }
+   UNLOCK_HARDWARE( intel );
+   intelFinish( &intel->ctx );
+
+   return GL_TRUE;
+}
+
+static 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__);
+
+   if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack, 
+                          pixels))
+      _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, 
+                         pixels);
+}
+
+
+
+
+static void do_draw_pix( GLcontext *ctx,
+                        GLint x, GLint y, GLsizei width, GLsizei height,
+                        GLint pitch,
+                        const void *pixels,
+                        GLuint dest )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;
+   drm_clip_rect_t *box = dPriv->pClipRects;
+   int nbox = dPriv->numClipRects;
+   int i;
+   int size;
+   int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
+   int src_pitch = pitch;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   intelFlush( &intel->ctx );
+   LOCK_HARDWARE( intel );
+   {
+      y -= height;                     /* cope with pixel zoom */
+   
+      if (!clip_pixelrect(ctx, ctx->DrawBuffer,
+                         &x, &y, &width, &height,
+                         &size)) {
+        UNLOCK_HARDWARE( intel );
+        return;
+      }
+
+      y = dPriv->h - y - height;       /* convert from gl to hardware coords */
+      x += dPriv->x;
+      y += dPriv->y;
+
+
+      for (i = 0 ; i < nbox ; i++ )
+      {
+        GLint bx = box[i].x1;
+        GLint by = box[i].y1;
+        GLint bw = box[i].x2 - bx;
+        GLint bh = box[i].y2 - by;
+
+        if (bx < x) bw -= x - bx, bx = x;
+        if (by < y) bh -= y - by, by = y;
+        if (bx + bw > x + width) bw = x + width - bx;
+        if (by + bh > y + height) bh = y + height - by;
+        if (bw <= 0) continue;
+        if (bh <= 0) continue;
+
+        intelEmitCopyBlitLocked( intel,
+                           intel->intelScreen->cpp,
+                           src_pitch, src_offset,
+                           intel->intelScreen->frontPitch,
+                             intel->drawOffset,
+                           bx - x, by - y,
+                           bx, by,
+                           bw, bh );
+      }
+   }
+   UNLOCK_HARDWARE( intel );
+   intelFinish( &intel->ctx );
+}
+
+
+
+
+static GLboolean
+intelTryDrawPixels( GLcontext *ctx,
+                 GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLenum format, GLenum type,
+                 const struct gl_pixelstore_attrib *unpack,
+                 const GLvoid *pixels )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   GLint pitch = unpack->RowLength ? unpack->RowLength : width;
+   GLuint dest;
+   GLuint cpp = intel->intelScreen->cpp;
+   GLint size = width * pitch * cpp;
+
+   if (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   switch (format) {
+   case GL_RGB:
+   case GL_RGBA:
+   case GL_BGRA:
+      dest = intel->drawOffset;
+
+      /* Planemask doesn't have full support in blits.
+       */
+      if (!ctx->Color.ColorMask[RCOMP] ||
+         !ctx->Color.ColorMask[GCOMP] ||
+         !ctx->Color.ColorMask[BCOMP] ||
+         !ctx->Color.ColorMask[ACOMP]) {
+        if (INTEL_DEBUG & DEBUG_PIXEL)
+           fprintf(stderr, "%s: planemask\n", __FUNCTION__);
+        return GL_FALSE;       
+      }
+
+      /* Can't do conversions on agp reads/draws. 
+       */
+      if ( !intelIsAgpMemory( intel, pixels, size ) ) {
+        if (INTEL_DEBUG & DEBUG_PIXEL)
+           fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
+        return GL_FALSE;
+      }
+
+      if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
+        return GL_FALSE;
+      }
+      if (!check_color_per_fragment_ops(ctx)) {
+        return GL_FALSE;
+      }
+
+      if (ctx->Pixel.ZoomX != 1.0F ||
+         ctx->Pixel.ZoomY != -1.0F)
+        return GL_FALSE;
+      break;
+
+   default:
+      return GL_FALSE;
+   }
+
+   if ( intelIsAgpMemory(intel, pixels, size) )
+   {
+      do_draw_pix( ctx, x, y, width, height, pitch, pixels,
+                  dest );
+      return GL_TRUE;
+   }
+   else if (0)
+   {
+      /* Pixels is in regular memory -- get dma buffers and perform
+       * upload through them.  No point doing this for regular uploads
+       * but once we remove some of the restrictions above (colormask,
+       * pixelformat conversion, zoom?, etc), this could be a win.
+       */
+   }
+   else
+      return GL_FALSE;
+}
+
+static 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 (INTEL_DEBUG & DEBUG_PIXEL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
+                         unpack, pixels ))
+      _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+                         unpack, pixels );
+}
+
+
+
+
+/**
+ * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
+ * for the color buffer.  Don't support zooming, pixel transfer, etc.
+ * We do support copying from one window to another, ala glXMakeCurrentRead.
+ */
+static void
+intelCopyPixels( GLcontext *ctx,
+                GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+                GLint destx, GLint desty, GLenum type )
+{
+#if 0
+   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+   XMesaDisplay *dpy = xmesa->xm_visual->display;
+   const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
+   const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
+   const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+   ASSERT(dpy);
+   ASSERT(gc);
+
+   if (drawBuffer &&  /* buffer != 0 means it's a Window or Pixmap */
+       readBuffer &&
+       type == GL_COLOR &&
+       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
+       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
+       ctx->Pixel.ZoomY == 1.0) {
+      /* Note: we don't do any special clipping work here.  We could,
+       * but X will do it for us.
+       */
+      srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
+      desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
+      XCopyArea(dpy, readBuffer, drawBuffer, gc,
+                srcx, srcy, width, height, destx, desty);
+   }
+#else
+   _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
+#endif
+}
+
+
+
+
+void intelInitPixelFuncs( struct dd_function_table *functions )
+{
+   /* Pixel path fallbacks.
+    */
+   functions->Accum = _swrast_Accum;
+   functions->Bitmap = _swrast_Bitmap;
+   functions->CopyPixels = intelCopyPixels;
+
+   if (!getenv("INTEL_NO_BLITS")) {
+      functions->ReadPixels = intelReadPixels;  
+      functions->DrawPixels = intelDrawPixels; 
+   }
+   else {
+      functions->ReadPixels = _swrast_ReadPixels;
+      functions->DrawPixels = _swrast_DrawPixels;
+   }
+}
diff --git a/src/mesa/drivers/dri/i915/intel_reg.h b/src/mesa/drivers/dri/i915/intel_reg.h
new file mode 100644 (file)
index 0000000..7c4e716
--- /dev/null
@@ -0,0 +1,64 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#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/i915/intel_render.c b/src/mesa/drivers/dri/i915/intel_render.c
new file mode 100644 (file)
index 0000000..5441115
--- /dev/null
@@ -0,0 +1,239 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+/*
+ * 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( intelContextPtr 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] );
+}
+
+
+#define LOCAL_VARS intelContextPtr 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->alloc.size / 2) - 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( intelContextPtr 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 )
+{
+   intelContextPtr 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 );
+
+   return GL_FALSE;     /* finished the pipe */
+}
+
+
+static void intel_check_render( GLcontext *ctx, 
+                              struct tnl_pipeline_stage *stage )
+{
+   stage->inputs = TNL_CONTEXT(ctx)->render_inputs;
+}
+
+static void dtr( struct tnl_pipeline_stage *stage )
+{
+   (void)stage;
+}
+
+
+const struct tnl_pipeline_stage _intel_render_stage =
+{
+   "intel render",
+   (_DD_NEW_SEPARATE_SPECULAR |
+    _NEW_TEXTURE|
+    _NEW_FOG|
+    _NEW_RENDERMODE),  /* re-check (new inputs) */
+   0,                  /* re-run (always runs) */
+   GL_TRUE,            /* active */
+   0, 0,               /* inputs (set in check_render), outputs */
+   0, 0,               /* changed_inputs, private */
+   dtr,                /* destructor */
+   intel_check_render, /* check - initially set to alloc data */
+   intel_run_render    /* run */
+};
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
new file mode 100644 (file)
index 0000000..d34f7ac
--- /dev/null
@@ -0,0 +1,543 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "context.h"
+#include "matrix.h"
+#include "simple_list.h"
+#include "utils.h"
+
+
+#include "intel_screen.h"
+
+#include "intel_tex.h"
+#include "intel_span.h"
+#include "intel_tris.h"
+#include "intel_ioctl.h"
+
+
+
+#include "i830_dri.h"
+
+#ifdef USE_NEW_INTERFACE
+static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
+#endif /*USE_NEW_INTERFACE*/
+
+
+static void intelPrintDRIInfo(intelScreenPrivate *intelScreen,
+                            __DRIscreenPrivate *sPriv,
+                           I830DRIPtr gDRIPriv)
+{
+   fprintf(stderr, "Front size : 0x%x\n", sPriv->fbSize);
+   fprintf(stderr, "Front offset : 0x%x\n", intelScreen->frontOffset);
+   fprintf(stderr, "Back size : 0x%x\n", intelScreen->back.size);
+   fprintf(stderr, "Back offset : 0x%x\n", intelScreen->backOffset);
+   fprintf(stderr, "Depth size : 0x%x\n", intelScreen->depth.size);
+   fprintf(stderr, "Depth offset : 0x%x\n", intelScreen->depthOffset);
+   fprintf(stderr, "Texture size : 0x%x\n", intelScreen->textureSize);
+   fprintf(stderr, "Texture offset : 0x%x\n", intelScreen->textureOffset);
+   fprintf(stderr, "Memory : 0x%x\n", gDRIPriv->mem);
+}
+
+static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
+{
+   intelScreenPrivate *intelScreen;
+   I830DRIPtr         gDRIPriv = (I830DRIPtr)sPriv->pDevPriv;
+
+
+   /* Allocate the private area */
+   intelScreen = (intelScreenPrivate *)MALLOC(sizeof(intelScreenPrivate));
+   if (!intelScreen) {
+      fprintf(stderr,"\nERROR!  Allocating private area failed\n");
+      return GL_FALSE;
+   }
+
+   intelScreen->driScrnPriv = sPriv;
+   sPriv->private = (void *)intelScreen;
+
+   intelScreen->deviceID = gDRIPriv->deviceID;
+   intelScreen->width = gDRIPriv->width;
+   intelScreen->height = gDRIPriv->height;
+   intelScreen->mem = gDRIPriv->mem;
+   intelScreen->cpp = gDRIPriv->cpp;
+   intelScreen->frontPitch = gDRIPriv->fbStride;
+   intelScreen->frontOffset = gDRIPriv->fbOffset;
+                        
+   switch (gDRIPriv->bitsPerPixel) {
+   case 15: intelScreen->fbFormat = DV_PF_555; break;
+   case 16: intelScreen->fbFormat = DV_PF_565; break;
+   case 32: intelScreen->fbFormat = DV_PF_8888; break;
+   }
+                        
+   intelScreen->backOffset = gDRIPriv->backOffset;
+   intelScreen->backPitch = gDRIPriv->backPitch;
+   intelScreen->depthOffset = gDRIPriv->depthOffset;
+   intelScreen->depthPitch = gDRIPriv->depthPitch;
+   intelScreen->textureOffset = gDRIPriv->textureOffset;
+   intelScreen->textureSize = gDRIPriv->textureSize;
+   intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
+   intelScreen->back.handle = gDRIPriv->backbuffer;
+   intelScreen->back.size = gDRIPriv->backbufferSize;
+                        
+   if (drmMap(sPriv->fd,
+             intelScreen->back.handle,
+             intelScreen->back.size,
+             (drmAddress *)&intelScreen->back.map) != 0) {
+      fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
+             __LINE__, __FUNCTION__, __FILE__);
+      FREE(intelScreen);
+      sPriv->private = NULL;
+      return GL_FALSE;
+   }
+
+   intelScreen->depth.handle = gDRIPriv->depthbuffer;
+   intelScreen->depth.size = gDRIPriv->depthbufferSize;
+
+   if (drmMap(sPriv->fd, 
+             intelScreen->depth.handle,
+             intelScreen->depth.size,
+             (drmAddress *)&intelScreen->depth.map) != 0) {
+      fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", 
+             __LINE__, __FUNCTION__, __FILE__);
+      FREE(intelScreen);
+      drmUnmap(intelScreen->back.map, intelScreen->back.size);
+      sPriv->private = NULL;
+      return GL_FALSE;
+   }
+
+   intelScreen->tex.handle = gDRIPriv->textures;
+   intelScreen->tex.size = gDRIPriv->textureSize;
+
+   if (drmMap(sPriv->fd,
+             intelScreen->tex.handle,
+             intelScreen->tex.size,
+             (drmAddress *)&intelScreen->tex.map) != 0) {
+      fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n",
+             __LINE__, __FUNCTION__, __FILE__);
+      FREE(intelScreen);
+      drmUnmap(intelScreen->back.map, intelScreen->back.size);
+      drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
+      sPriv->private = NULL;
+      return GL_FALSE;
+   }
+                        
+   intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
+   
+   if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
+
+   intelScreen->drmMinor = sPriv->drmMinor;
+
+   {
+      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;
+      }
+   }
+
+   {
+      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;
+      }
+   }
+
+#ifndef _SOLO       
+   if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
+      PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
+          (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
+      void * const psc = sPriv->psc->screenConfigs;
+
+      if (glx_enable_extension != NULL) {
+        (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
+
+        if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
+           (*glx_enable_extension)( psc, "GLX_SGIX_fbconfig" );
+           (*glx_enable_extension)( psc, "GLX_OML_swap_method" );
+        }
+
+        if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
+           sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
+           sPriv->psc->freeMemory     = (void *) intelFreeMemoryMESA;
+           sPriv->psc->memoryOffset   = (void *) intelGetMemoryOffsetMESA;
+
+           (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
+        }
+      }
+   }
+#endif
+
+   return GL_TRUE;
+}
+               
+               
+static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
+{
+   intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
+
+   /* Need to unmap all the bufs and maps here:
+    */
+   drmUnmap(intelScreen->back.map, intelScreen->back.size);
+   drmUnmap(intelScreen->depth.map, intelScreen->depth.size);
+   drmUnmap(intelScreen->tex.map, intelScreen->tex.size);
+   FREE(intelScreen);
+   sPriv->private = NULL;
+}
+
+static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+                                   __DRIdrawablePrivate *driDrawPriv,
+                                   const __GLcontextModes *mesaVis,
+                                   GLboolean isPixmap )
+{
+   if (isPixmap) {
+      return GL_FALSE; /* not implemented */
+   } else {
+      GLboolean swStencil = (mesaVis->stencilBits > 0 && 
+                            mesaVis->depthBits != 24);
+
+      driDrawPriv->driverPrivate = (void *) 
+        _mesa_create_framebuffer(mesaVis,
+                                 GL_FALSE,  /* software depth buffer? */
+                                 swStencil,
+                                 mesaVis->accumRedBits > 0,
+                                 GL_FALSE /* s/w alpha planes */);
+      
+      return (driDrawPriv->driverPrivate != NULL);
+   }
+}
+
+static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+/* 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) {
+   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:
+      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     = NULL,
+   .GetMSC          = NULL,
+   .WaitForMSC      = NULL,
+   .WaitForSBC      = NULL,
+   .SwapBuffersMSC  = NULL
+};
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return:  pointer to a __DRIscreenPrivate.
+ */
+#if !defined(DRI_NEW_INTERFACE_ONLY)
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                       int numConfigs, __GLXvisualConfig *config)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &intelAPI);
+   return (void *) psp;
+}
+#else
+void *__driCreateScreen(struct DRIDriverRec *driver,
+                        struct DRIDriverContextRec *driverContext)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(driver, driverContext, &i830API);
+   return (void *) psp;
+}
+#endif
+#endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
+            
+
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we'd register new extension functions with the dispatcher.
+ *
+ * Note: Most of these are probably already registered - just doing
+ * this for the benefit of old libGL.so's out there.
+ */
+#include "glapioffsets.h"
+
+void __driRegisterExtensions( void )
+{
+   int i;
+   static struct { const char *name; int offset; } funcs[] = {
+       { "glSecondaryColor3bEXT", _gloffset_SecondaryColor3bEXT },
+       { "glSecondaryColor3dEXT", _gloffset_SecondaryColor3dEXT },
+       { "glSecondaryColor3fEXT", _gloffset_SecondaryColor3fEXT },
+       { "glSecondaryColor3iEXT", _gloffset_SecondaryColor3iEXT },
+       { "glSecondaryColor3sEXT", _gloffset_SecondaryColor3sEXT },
+       { "glSecondaryColor3ubEXT", _gloffset_SecondaryColor3ubEXT },
+       { "glSecondaryColor3uiEXT", _gloffset_SecondaryColor3uiEXT },
+       { "glSecondaryColor3usEXT", _gloffset_SecondaryColor3usEXT },
+       { "glSecondaryColor3bvEXT", _gloffset_SecondaryColor3bvEXT },
+       { "glSecondaryColor3dvEXT", _gloffset_SecondaryColor3dvEXT },
+       { "glSecondaryColor3fvEXT", _gloffset_SecondaryColor3fvEXT },
+       { "glSecondaryColor3ivEXT", _gloffset_SecondaryColor3ivEXT },
+       { "glSecondaryColor3svEXT", _gloffset_SecondaryColor3svEXT },
+       { "glSecondaryColor3ubvEXT", _gloffset_SecondaryColor3ubvEXT },
+       { "glSecondaryColor3uivEXT", _gloffset_SecondaryColor3uivEXT },
+       { "glSecondaryColor3usvEXT", _gloffset_SecondaryColor3usvEXT },
+       { "glSecondaryColorPointerEXT", _gloffset_SecondaryColorPointerEXT }
+   };
+
+   for (i = 0 ; i < sizeof(funcs) / sizeof(*funcs) ; i++ ) 
+      _glapi_add_entrypoint( funcs[i].name, funcs[i].offset );
+}
+
+
+#ifdef USE_NEW_INTERFACE
+static __GLcontextModes * fill_in_modes( __GLcontextModes * modes,
+                                        unsigned pixel_bits, 
+                                        unsigned depth_bits,
+                                        unsigned stencil_bits,
+                                        const GLenum * db_modes,
+                                        unsigned num_db_modes,
+                                        int visType )
+{
+    static const uint8_t bits[2][4] = {
+       {          5,          6,          5,          0 },
+       {          8,          8,          8,          8 }
+    };
+
+    static const uint32_t masks[2][4] = {
+       { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
+       { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }
+    };
+
+    unsigned   i;
+    unsigned   j;
+    const unsigned index = ((pixel_bits + 15) / 16) - 1;
+
+    for ( i = 0 ; i < num_db_modes ; i++ ) {
+       for ( j = 0 ; j < 2 ; j++ ) {
+
+           modes->redBits   = bits[index][0];
+           modes->greenBits = bits[index][1];
+           modes->blueBits  = bits[index][2];
+           modes->alphaBits = bits[index][3];
+           modes->redMask   = masks[index][0];
+           modes->greenMask = masks[index][1];
+           modes->blueMask  = masks[index][2];
+           modes->alphaMask = masks[index][3];
+           modes->rgbBits   = modes->redBits + modes->greenBits
+               + modes->blueBits + modes->alphaBits;
+
+           modes->accumRedBits   = 16 * j;
+           modes->accumGreenBits = 16 * j;
+           modes->accumBlueBits  = 16 * j;
+           modes->accumAlphaBits = (masks[index][3] != 0) ? 16 * j : 0;
+           modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
+
+           modes->stencilBits = stencil_bits;
+           modes->depthBits = depth_bits;
+
+           modes->visualType = visType;
+           modes->renderType = GLX_RGBA_BIT;
+           modes->drawableType = GLX_WINDOW_BIT;
+           modes->rgbMode = GL_TRUE;
+
+           if ( db_modes[i] == GLX_NONE ) {
+               modes->doubleBufferMode = GL_FALSE;
+           }
+           else {
+               modes->doubleBufferMode = GL_TRUE;
+               modes->swapMethod = db_modes[i];
+           }
+
+           modes = modes->next;
+       }
+    }
+    
+    return modes;
+}
+#endif /* USE_NEW_INTERFACE */
+
+
+#ifdef USE_NEW_INTERFACE
+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;
+   unsigned i;
+
+   /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
+    * support pageflipping at all.
+    */
+   static const GLenum back_buffer_modes[] = {
+      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+   };
+
+   int depth_buffer_modes[2][2];
+
+
+   depth_buffer_modes[0][0] = depth_bits;
+   depth_buffer_modes[1][0] = 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.
+    */
+   depth_buffer_modes[0][1] = 0;
+   depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
+   back_buffer_factor  = (have_back_buffer) ? 3 : 1;
+
+   num_modes = depth_buffer_factor * back_buffer_factor * 4;
+
+   modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
+   m = modes;
+   for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
+      m = fill_in_modes( m, pixel_bits, 
+                        depth_buffer_modes[i][0], depth_buffer_modes[i][1],
+                        back_buffer_modes, back_buffer_factor,
+                        GLX_TRUE_COLOR );
+   }
+
+   /* There's no direct color modes on intel? */
+#if 0
+   for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
+      m = fill_in_modes( m, pixel_bits, 
+                        depth_buffer_modes[i][0], depth_buffer_modes[i][1],
+                        back_buffer_modes, back_buffer_factor,
+                        GLX_DIRECT_COLOR );
+   }
+#endif
+
+   /* 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;
+}
+#endif /* USE_NEW_INTERFACE */
+
+
+/**
+ * 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.
+ */
+#ifdef USE_NEW_INTERFACE
+void * __driCreateNewScreen( __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,
+                            __GLcontextModes ** driver_modes )
+                            
+{
+   __DRIscreenPrivate *psp;
+   static const __DRIversion ddx_expected = { 1, 0, 0 };
+   static const __DRIversion dri_expected = { 4, 0, 0 };
+   static const __DRIversion drm_expected = { 1, 1, 0 };
+
+   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 ) {
+      create_context_modes = (PFNGLXCREATECONTEXTMODES)
+         glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
+      if ( create_context_modes != 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,
+                                          (dri_priv->backOffset != dri_priv->depthOffset) );
+      }
+   }
+
+   return (void *) psp;
+}
+#endif /* USE_NEW_INTERFACE */
diff --git a/src/mesa/drivers/dri/i915/intel_screen.h b/src/mesa/drivers/dri/i915/intel_screen.h
new file mode 100644 (file)
index 0000000..88d02ca
--- /dev/null
@@ -0,0 +1,76 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef _INTEL_INIT_H_
+#define _INTEL_INIT_H_
+
+#include <sys/time.h>
+#include "dri_util.h"
+
+
+typedef struct {
+   drm_handle_t handle;
+   drmSize size;
+   char *map;
+} intelRegion;
+
+typedef struct 
+{
+   intelRegion front;
+   intelRegion back;
+   intelRegion depth;
+   intelRegion tex;
+   
+   int deviceID;
+   int width;
+   int height;
+   int mem;
+   
+   int cpp;         /* for front and back buffers */
+   int bitsPerPixel;
+   
+   int fbFormat;
+
+   int frontOffset;
+   int frontPitch;
+
+   int backOffset;
+   int backPitch;
+
+   int depthOffset;
+   int depthPitch;
+   
+   
+   int textureOffset;
+   int textureSize;
+   int logTextureGranularity;
+   
+   __DRIscreenPrivate *driScrnPriv;
+   unsigned int sarea_priv_offset;
+
+   int drmMinor;
+
+   int irq_active;
+   int allow_batchbuffer;
+} intelScreenPrivate;
+
+
+extern void
+intelDestroyContext(__DRIcontextPrivate *driContextPriv);
+
+extern GLboolean
+intelUnbindContext(__DRIcontextPrivate *driContextPriv);
+
+extern GLboolean
+intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
+                __DRIdrawablePrivate *driDrawPriv,
+                __DRIdrawablePrivate *driReadPriv);
+
+extern void
+intelSwapBuffers( __DRIdrawablePrivate *dPriv);
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/intel_span.c b/src/mesa/drivers/dri/i915/intel_span.c
new file mode 100644 (file)
index 0000000..f9f7eb9
--- /dev/null
@@ -0,0 +1,323 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "colormac.h"
+
+#include "intel_screen.h"
+
+#include "intel_span.h"
+#include "intel_ioctl.h"
+#include "swrast/swrast.h"
+
+
+#define DBG 0
+
+#define LOCAL_VARS                                             \
+   intelContextPtr intel = INTEL_CONTEXT(ctx);                    \
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;           \
+   intelScreenPrivate *intelScreen = intel->intelScreen;               \
+   GLuint pitch = intelScreen->backPitch * intelScreen->cpp;   \
+   GLuint height = dPriv->h;                                   \
+   char *buf = (char *)(intel->drawMap +                       \
+                       dPriv->x * intelScreen->cpp +           \
+                       dPriv->y * pitch);                      \
+   char *read_buf = (char *)(intel->readMap +                  \
+                            dPriv->x * intelScreen->cpp +      \
+                            dPriv->y * pitch);                 \
+   GLushort p;                                                         \
+   (void) read_buf; (void) buf; (void) p
+
+#define LOCAL_DEPTH_VARS                                       \
+   intelContextPtr intel = INTEL_CONTEXT(ctx);                    \
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;           \
+   intelScreenPrivate *intelScreen = intel->intelScreen;               \
+   GLuint pitch = intelScreen->backPitch * intelScreen->cpp;   \
+   GLuint height = dPriv->h;                                   \
+   char *buf = (char *)(intelScreen->depth.map +                       \
+                       dPriv->x * intelScreen->cpp +           \
+                       dPriv->y * pitch)
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS 
+
+#define INIT_MONO_PIXEL(p,color)\
+        p = PACK_COLOR_565(color[0],color[1],color[2])
+
+#define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \
+                         _y >= miny && _y < maxy)
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i )                           \
+   if ( _y < miny || _y >= maxy ) {                                    \
+      _n1 = 0, _x1 = x;                                                \
+   } else {                                                            \
+      _n1 = _n;                                                        \
+      _x1 = _x;                                                        \
+      if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+      if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx);                \
+   }
+
+#define Y_FLIP(_y) (height - _y - 1)
+
+
+#define HW_LOCK()
+
+#define HW_CLIPLOOP()                                          \
+  do {                                                         \
+    __DRIdrawablePrivate *dPriv = intel->driDrawable;          \
+    int _nc = dPriv->numClipRects;                             \
+    while (_nc--) {                                            \
+       int minx = dPriv->pClipRects[_nc].x1 - dPriv->x;                \
+       int miny = dPriv->pClipRects[_nc].y1 - dPriv->y;        \
+       int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x;                \
+       int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+
+#define HW_ENDCLIPLOOP()                       \
+    }                                          \
+  } while (0)
+
+#define HW_UNLOCK()
+
+/* 16 bit, 565 rgb color spanline and pixel functions
+ */
+#define WRITE_RGBA( _x, _y, r, g, b, a )                               \
+   *(GLushort *)(buf + _x*2 + _y*pitch)  = ( (((int)r & 0xf8) << 8) |  \
+                                            (((int)g & 0xfc) << 3) |   \
+                                            (((int)b & 0xf8) >> 3))
+#define WRITE_PIXEL( _x, _y, p )  \
+   *(GLushort *)(buf + _x*2 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y )                              \
+do {                                                           \
+   GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch);     \
+   rgba[0] = (((p >> 11) & 0x1f) * 255) / 31;                  \
+   rgba[1] = (((p >>  5) & 0x3f) * 255) / 63;                  \
+   rgba[2] = (((p >>  0) & 0x1f) * 255) / 31;                  \
+   rgba[3] = 255;                                              \
+} while(0)
+
+#define TAG(x) intel##x##_565
+#include "spantmp.h"
+
+
+
+
+/* 15 bit, 555 rgb color spanline and pixel functions
+ */
+#define WRITE_RGBA( _x, _y, r, g, b, a )                       \
+   *(GLushort *)(buf + _x*2 + _y*pitch)  = (((r & 0xf8) << 7) |        \
+                                           ((g & 0xf8) << 3) | \
+                                           ((b & 0xf8) >> 3))
+
+#define WRITE_PIXEL( _x, _y, p )  \
+   *(GLushort *)(buf + _x*2 + _y*pitch)  = p
+
+#define READ_RGBA( rgba, _x, _y )                              \
+do {                                                           \
+   GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch);     \
+   rgba[0] = (p >> 7) & 0xf8;                                  \
+   rgba[1] = (p >> 3) & 0xf8;                                  \
+   rgba[2] = (p << 3) & 0xf8;                                  \
+   rgba[3] = 255;                                              \
+} while(0)
+
+#define TAG(x) intel##x##_555
+#include "spantmp.h"
+
+/* 16 bit depthbuffer functions.
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+   *(GLushort *)(buf + _x*2 + _y*pitch)  = d;
+
+#define READ_DEPTH( d, _x, _y )        \
+   d = *(GLushort *)(buf + _x*2 + _y*pitch);    
+
+
+#define TAG(x) intel##x##_16
+#include "depthtmp.h"
+
+
+#undef LOCAL_VARS
+#define LOCAL_VARS                                             \
+   intelContextPtr intel = INTEL_CONTEXT(ctx);                 \
+   __DRIdrawablePrivate *dPriv = intel->driDrawable;           \
+   intelScreenPrivate *intelScreen = intel->intelScreen;               \
+   GLuint pitch = intelScreen->backPitch * intelScreen->cpp;   \
+   GLuint height = dPriv->h;                                   \
+   char *buf = (char *)(intel->drawMap +                       \
+                       dPriv->x * intelScreen->cpp +           \
+                       dPriv->y * pitch);                      \
+   char *read_buf = (char *)(intel->readMap +                  \
+                            dPriv->x * intelScreen->cpp +      \
+                            dPriv->y * pitch);                 \
+   GLuint p;                                                   \
+   (void) read_buf; (void) buf; (void) p
+
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p,color)\
+        p = PACK_COLOR_888(color[0],color[1],color[2])
+
+/* 32 bit, 8888 argb color spanline and pixel functions
+ */
+#define WRITE_RGBA(_x, _y, r, g, b, a)                 \
+    *(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) |  \
+                                         (g << 8)  |   \
+                                         (b << 0)  |   \
+                                         (a << 24) )
+
+#define WRITE_PIXEL(_x, _y, p)                 \
+    *(GLuint *)(buf + _x*4 + _y*pitch) = p
+
+
+#define READ_RGBA(rgba, _x, _y)                                        \
+    do {                                                       \
+       GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch);     \
+       rgba[0] = (p >> 16) & 0xff;                             \
+       rgba[1] = (p >> 8)  & 0xff;                             \
+       rgba[2] = (p >> 0)  & 0xff;                             \
+       rgba[3] = (p >> 24) & 0xff;                             \
+    } while (0)
+
+#define TAG(x) intel##x##_8888
+#include "spantmp.h"
+
+
+/* 24/8 bit interleaved depth/stencil functions
+ */
+#define WRITE_DEPTH( _x, _y, d ) {                     \
+   GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);        \
+   tmp &= 0xff000000;                                  \
+   tmp |= (d) & 0xffffff;                              \
+   *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp;               \
+}
+
+#define READ_DEPTH( d, _x, _y )                \
+   d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) & 0xffffff;
+
+
+#define TAG(x) intel##x##_24_8
+#include "depthtmp.h"
+
+#define WRITE_STENCIL( _x, _y, d ) {                   \
+   GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);        \
+   tmp &= 0xffffff;                                    \
+   tmp |= ((d)<<24);                                   \
+   *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp;               \
+}
+
+#define READ_STENCIL( d, _x, _y )                      \
+   d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24;
+
+#define TAG(x) intel##x##_24_8
+#include "stenciltmp.h"
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks.  This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void intelSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
+                          GLuint bufferBit)
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   if (bufferBit == DD_FRONT_LEFT_BIT) {
+      intel->drawMap = (char *)intel->driScreen->pFB;
+      intel->readMap = (char *)intel->driScreen->pFB;
+   } else if (bufferBit == DD_BACK_LEFT_BIT) {
+      intel->drawMap = intel->intelScreen->back.map;
+      intel->readMap = intel->intelScreen->back.map;
+   } else {
+      ASSERT(0);
+   }
+}
+
+
+/* Move locking out to get reasonable span performance.
+ */
+void intelSpanRenderStart( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+
+   intelFlush(&intel->ctx);
+   LOCK_HARDWARE(intel);
+   intelWaitForIdle(intel);
+}
+
+void intelSpanRenderFinish( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   _swrast_flush( ctx );
+   UNLOCK_HARDWARE( intel );
+}
+
+void intelInitSpanFuncs( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   intelScreenPrivate *intelScreen = intel->intelScreen;
+
+   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+   swdd->SetBuffer = intelSetBuffer;
+
+   switch (intelScreen->fbFormat) {
+   case DV_PF_555:
+      swdd->WriteRGBASpan = intelWriteRGBASpan_555;
+      swdd->WriteRGBSpan = intelWriteRGBSpan_555;
+      swdd->WriteMonoRGBASpan = intelWriteMonoRGBASpan_555;
+      swdd->WriteRGBAPixels = intelWriteRGBAPixels_555;
+      swdd->WriteMonoRGBAPixels = intelWriteMonoRGBAPixels_555;
+      swdd->ReadRGBASpan = intelReadRGBASpan_555;
+      swdd->ReadRGBAPixels = intelReadRGBAPixels_555;
+
+      swdd->ReadDepthSpan = intelReadDepthSpan_16;
+      swdd->WriteDepthSpan = intelWriteDepthSpan_16;
+      swdd->ReadDepthPixels = intelReadDepthPixels_16;
+      swdd->WriteDepthPixels = intelWriteDepthPixels_16;
+      break;
+
+   case DV_PF_565:
+      swdd->WriteRGBASpan = intelWriteRGBASpan_565;
+      swdd->WriteRGBSpan = intelWriteRGBSpan_565;
+      swdd->WriteMonoRGBASpan = intelWriteMonoRGBASpan_565;
+      swdd->WriteRGBAPixels = intelWriteRGBAPixels_565;
+      swdd->WriteMonoRGBAPixels = intelWriteMonoRGBAPixels_565; 
+      swdd->ReadRGBASpan = intelReadRGBASpan_565;
+      swdd->ReadRGBAPixels = intelReadRGBAPixels_565;
+
+      swdd->ReadDepthSpan = intelReadDepthSpan_16;
+      swdd->WriteDepthSpan = intelWriteDepthSpan_16;
+      swdd->ReadDepthPixels = intelReadDepthPixels_16;
+      swdd->WriteDepthPixels = intelWriteDepthPixels_16;
+      break;
+
+   case DV_PF_8888:
+      swdd->WriteRGBASpan = intelWriteRGBASpan_8888;
+      swdd->WriteRGBSpan = intelWriteRGBSpan_8888;
+      swdd->WriteMonoRGBASpan = intelWriteMonoRGBASpan_8888;
+      swdd->WriteRGBAPixels = intelWriteRGBAPixels_8888;
+      swdd->WriteMonoRGBAPixels = intelWriteMonoRGBAPixels_8888;
+      swdd->ReadRGBASpan = intelReadRGBASpan_8888;
+      swdd->ReadRGBAPixels = intelReadRGBAPixels_8888;
+
+      swdd->ReadDepthSpan = intelReadDepthSpan_24_8;
+      swdd->WriteDepthSpan = intelWriteDepthSpan_24_8;
+      swdd->ReadDepthPixels = intelReadDepthPixels_24_8;
+      swdd->WriteDepthPixels = intelWriteDepthPixels_24_8;
+
+      swdd->WriteStencilSpan = intelWriteStencilSpan_24_8;
+      swdd->ReadStencilSpan = intelReadStencilSpan_24_8;
+      swdd->WriteStencilPixels = intelWriteStencilPixels_24_8;
+      swdd->ReadStencilPixels = intelReadStencilPixels_24_8;
+      break;
+   }
+
+   swdd->SpanRenderStart = intelSpanRenderStart;
+   swdd->SpanRenderFinish = intelSpanRenderFinish; 
+}
diff --git a/src/mesa/drivers/dri/i915/intel_span.h b/src/mesa/drivers/dri/i915/intel_span.h
new file mode 100644 (file)
index 0000000..3498bd4
--- /dev/null
@@ -0,0 +1,16 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef _INTEL_SPAN_H
+#define _INTEL_SPAN_H
+
+extern void intelInitSpanFuncs( GLcontext *ctx );
+
+extern void intelSpanRenderFinish( GLcontext *ctx );
+extern void intelSpanRenderStart( GLcontext *ctx );
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/intel_state.c b/src/mesa/drivers/dri/i915/intel_state.c
new file mode 100644 (file)
index 0000000..23e4955
--- /dev/null
@@ -0,0 +1,135 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "enums.h"
+#include "dd.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "swrast/swrast.h"
+
+
+static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   intelScreenPrivate *screen = intel->intelScreen;
+   int front = 0;
+   switch ( ctx->Color._DrawDestMask ) {
+   case DD_FRONT_LEFT_BIT:
+      front = 1;
+      FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      break;
+   case DD_BACK_LEFT_BIT:
+      front = 0;
+      FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      break;
+   default:
+      FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
+      return;
+   }
+
+   /* We want to update the s/w rast state too so that r200SetBuffer()
+    * gets called.
+    */
+   _swrast_DrawBuffer(ctx, mode);
+
+   if ( intel->sarea->pf_current_page == 1 ) 
+      front ^= 1;
+   
+   intelSetFrontClipRects( intel );
+
+   if (front) {
+      intel->drawOffset = screen->frontOffset;
+      intel->drawMap = (char *)intel->driScreen->pFB;
+      intel->readMap = (char *)intel->driScreen->pFB;
+   } else {
+      intel->drawOffset = screen->backOffset;
+      intel->drawMap = screen->back.map;
+      intel->readMap = screen->back.map;
+   }
+
+   intel->vtbl.set_draw_offset( intel, intel->drawOffset );
+}
+
+static void intelReadBuffer( GLcontext *ctx, GLenum mode )
+{
+   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   intelScreenPrivate *screen = intel->intelScreen;
+
+   CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]);
+   CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]);
+   CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]);
+   CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]);
+
+   intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat,
+                                      intel->clear_red, 
+                                      intel->clear_green, 
+                                      intel->clear_blue, 
+                                      intel->clear_alpha);
+}
+
+
+static void intelCalcViewport( GLcontext *ctx )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   const GLfloat *v = ctx->Viewport._WindowMap.m;
+   GLfloat *m = intel->ViewportMatrix.m;
+
+   /* See also intel_translate_vertex.  SUBPIXEL adjustments can be done
+    * via state vars, too.
+    */
+   m[MAT_SX] =   v[MAT_SX];
+   m[MAT_TX] =   v[MAT_TX] + SUBPIXEL_X;
+   m[MAT_SY] = - v[MAT_SY];
+   m[MAT_TY] = - v[MAT_TY] + intel->driDrawable->h + SUBPIXEL_Y;
+   m[MAT_SZ] =   v[MAT_SZ] * intel->depth_scale;
+   m[MAT_TZ] =   v[MAT_TZ] * intel->depth_scale;
+}
+
+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 )
+{
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
+}
+
+
+void intelInitStateFuncs( struct dd_function_table *functions )
+{
+   functions->DrawBuffer = intelDrawBuffer;
+   functions->ReadBuffer = intelReadBuffer;
+   functions->RenderMode = intelRenderMode;
+   functions->Viewport = intelViewport;
+   functions->DepthRange = intelDepthRange;
+   functions->ClearColor = intelClearColor;
+}
+
diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c
new file mode 100644 (file)
index 0000000..fac6efa
--- /dev/null
@@ -0,0 +1,665 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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 "teximage.h"
+#include "texmem.h"
+#include "texobj.h"
+#include "swrast/swrast.h"
+
+#include "mm.h"
+
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+#include "intel_context.h"
+#include "intel_tex.h"
+#include "intel_ioctl.h"
+
+
+
+static GLboolean
+intelValidateClientStorage( intelContextPtr intel, GLenum target,
+                           GLint internalFormat,
+                           GLint srcWidth, GLint srcHeight, 
+                           GLenum format, GLenum type,  const void *pixels,
+                           const struct gl_pixelstore_attrib *packing,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage)
+
+{
+   GLcontext *ctx = &intel->ctx;
+   int texelBytes;
+
+   if (0)
+      fprintf(stderr, "intformat %s format %s type %s\n",
+             _mesa_lookup_enum_by_nr( internalFormat ),
+             _mesa_lookup_enum_by_nr( format ),
+             _mesa_lookup_enum_by_nr( type ));
+
+   if (!ctx->Unpack.ClientStorage)
+      return 0;
+
+   if (ctx->_ImageTransferState ||
+       texImage->IsCompressed ||
+       texObj->GenerateMipmap)
+      return 0;
+
+
+   /* This list is incomplete
+    */
+   switch ( internalFormat ) {
+   case GL_RGBA:
+      if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
+        texImage->TexFormat = &_mesa_texformat_argb8888;
+        texelBytes = 4;
+      }
+      else
+        return 0;
+      break;
+
+   case GL_RGB:
+      if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
+        texImage->TexFormat = &_mesa_texformat_rgb565;
+        texelBytes = 2;
+      }
+      else
+        return 0;
+      break;
+
+   case GL_YCBCR_MESA:
+      if ( format == GL_YCBCR_MESA && 
+          type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
+        texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
+        texelBytes = 2;
+      }
+      else if ( format == GL_YCBCR_MESA && 
+               (type == GL_UNSIGNED_SHORT_8_8_APPLE || 
+                type == GL_UNSIGNED_BYTE)) {
+        texImage->TexFormat = &_mesa_texformat_ycbcr;
+        texelBytes = 2;
+      }
+      else
+        return 0;
+      break;
+      
+        
+   default:
+      return 0;
+   }
+
+   /* Could deal with these packing issues, but currently don't:
+    */
+   if (packing->SkipPixels || 
+       packing->SkipRows || 
+       packing->SwapBytes ||
+       packing->LsbFirst) {
+      return 0;
+   }
+
+   {      
+      GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
+                                                 format, type);
+
+      
+      if (0)
+        fprintf(stderr, "%s: srcRowStride %d/%x\n", 
+                __FUNCTION__, srcRowStride, srcRowStride);
+
+      /* Could check this later in upload, pitch restrictions could be
+       * relaxed, but would need to store the image pitch somewhere,
+       * as packing details might change before image is uploaded:
+       */
+      if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
+         (srcRowStride & 63))
+        return 0;
+
+
+      /* Have validated that _mesa_transfer_teximage would be a straight
+       * memcpy at this point.  NOTE: future calls to TexSubImage will
+       * overwrite the client data.  This is explicitly mentioned in the
+       * extension spec.
+       */
+      texImage->Data = (void *)pixels;
+      texImage->IsClientData = GL_TRUE;
+      texImage->RowStride = srcRowStride / texelBytes;
+      return 1;
+   }
+}
+
+
+static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
+                           GLint internalFormat,
+                           GLint width, GLint border,
+                           GLenum format, GLenum type, const GLvoid *pixels,
+                           const struct gl_pixelstore_attrib *packing,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert(t);
+   intelFlush( ctx );
+   driSwapOutTextureObject( t );
+
+   texImage->IsClientData = GL_FALSE;
+
+   _mesa_store_teximage1d( ctx, target, level, internalFormat,
+                          width, border, format, type,
+                          pixels, packing, texObj, texImage );
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+static 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 )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert(t);
+   intelFlush( ctx );
+   driSwapOutTextureObject( t );
+
+   _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, 
+                            format, type, pixels, packing, texObj,
+                            texImage);
+}
+
+
+/* Handles 2D, CUBE, RECT:
+ */
+static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+                           GLint internalFormat,
+                           GLint width, GLint height, GLint border,
+                           GLenum format, GLenum type, const GLvoid *pixels,
+                           const struct gl_pixelstore_attrib *packing,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+   GLuint face;
+
+   /* which cube face or ordinary 2D image */
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+      ASSERT(face < 6);
+      break;
+   default:
+      face = 0;
+   }
+
+   assert(t);
+   intelFlush( ctx );
+   driSwapOutTextureObject( t );
+   texImage->IsClientData = GL_FALSE;
+
+   if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target, 
+                                  internalFormat, 
+                                  width, height, 
+                                  format, type, pixels, 
+                                  packing, texObj, texImage)) {
+      if (INTEL_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "%s: Using client storage\n", __FUNCTION__); 
+   }
+   else {
+      _mesa_store_teximage2d( ctx, target, level, internalFormat,
+                             width, height, border, format, type,
+                             pixels, packing, texObj, texImage );
+
+      t->dirty_images[face] |= (1 << level);
+   }
+}
+
+static 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 )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+   GLuint face;
+
+   /* which cube face or ordinary 2D image */
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+      ASSERT(face < 6);
+      break;
+   default:
+      face = 0;
+   }
+
+   if (texImage->IsClientData &&
+       (char *)pixels == (char *)texImage->Data + 
+       ((xoffset + yoffset * texImage->RowStride) * 
+       texImage->TexFormat->TexelBytes)) {
+
+      /* Notification only - no upload required */
+   }
+   else {
+      assert( t ); /* this _should_ be true */
+      intelFlush( ctx );
+      driSwapOutTextureObject( t );
+
+      _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, 
+                               height, format, type, pixels, packing, texObj,
+                               texImage);
+
+      t->dirty_images[face] |= (1 << level);
+   }
+}
+
+
+
+static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
+                            GLint internalFormat,
+                            GLint width, GLint height, GLint depth,
+                            GLint border,
+                            GLenum format, GLenum type, const GLvoid *pixels,
+                            const struct gl_pixelstore_attrib *packing,
+                            struct gl_texture_object *texObj,
+                            struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert(t);
+   driSwapOutTextureObject( t );
+   texImage->IsClientData = GL_FALSE;
+
+   _mesa_store_teximage3d(ctx, target, level, internalFormat,
+                         width, height, depth, border,
+                         format, type, pixels,
+                         &ctx->Unpack, texObj, texImage);
+   
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static 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 )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert( t ); /* this _should_ be true */
+   driSwapOutTextureObject( t );
+
+   _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
+                             width, height, depth,
+                             format, type, pixels, packing, texObj, texImage);
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+
+
+static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
+{
+   driTextureObject * t = (driTextureObject *) tObj->DriverData;
+
+   if ( t != NULL ) {
+      intelFlush( ctx );
+      driDestroyTextureObject( t );
+   }
+   
+   /* Free mipmap images and the texture object itself */
+   _mesa_delete_texture_object(ctx, tObj);
+}
+
+
+static const struct gl_texture_format *
+intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+                        GLenum format, GLenum type )
+{
+   intelContextPtr intel = INTEL_CONTEXT( ctx );
+   const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
+                              intel->intelScreen->textureSize > 4*1024*1024);
+
+   switch ( internalFormat ) {
+   case 4:
+   case GL_RGBA:
+   case GL_COMPRESSED_RGBA:
+      if ( format == GL_BGRA ) {
+        if ( 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 do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+
+   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:
+/*       if (1 || intel->intelScreen->deviceID == PCI_CHIP_I915_G) */
+        return &_mesa_texformat_a8;
+/*       else */
+/*      return &_mesa_texformat_al88; */
+
+   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;
+
+   default:
+      fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
+      return NULL;
+   }
+
+   return NULL; /* never get here */
+}
+
+
+
+void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
+{
+   unsigned   i;
+
+   if ( intel == NULL ) 
+      return;
+
+   if ( t->age > intel->dirtyAge )
+      intel->dirtyAge = t->age;
+
+   for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
+      if ( t == intel->CurrentTexObj[ i ] ) 
+        intel->CurrentTexObj[ i ] = NULL;
+   }
+}
+
+
+
+/* Upload an image from mesa's internal copy.  Image may be 1D, 2D or
+ * 3D.  Cubemaps are expanded elsewhere.
+ */
+static void intelUploadTexImage( intelContextPtr intel,
+                                intelTextureObjectPtr t,
+                                const struct gl_texture_image *image,
+                                const GLuint offset )
+{
+
+   if (!image || !image->Data) 
+      return;
+
+   if (image->Depth == 1 && image->IsClientData) {
+      if (INTEL_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "Blit uploading\n");
+
+      /* Do it with a blit.
+       */
+      intelEmitCopyBlitLocked( intel,
+                              image->TexFormat->TexelBytes,
+                              image->RowStride, /* ? */
+                              intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
+                              t->Pitch / image->TexFormat->TexelBytes,
+                              intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
+                              0, 0,
+                              0, 0,
+                              image->Width,
+                              image->Height);
+   }
+   else {
+      GLuint row_len = image->Width * image->TexFormat->TexelBytes;
+      GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
+      GLubyte *src = (GLubyte *)image->Data;
+      GLuint d, j;
+
+      if (INTEL_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, 
+                "Upload image %dx%dx%d offset %xm row_len %x "
+                "pitch %x depth_pitch %x\n",
+                image->Width, image->Height, image->Depth, offset,
+                row_len, t->Pitch, t->depth_pitch);
+
+      if (row_len == t->Pitch) {
+        for (d = 0; d < image->Depth; d++) {
+           memcpy( dst, src, t->Pitch * image->Height );
+           dst += t->depth_pitch;
+           src += row_len * image->Height;
+        }
+      }
+      else { 
+        for (d = 0 ; d < image->Depth ; d++) {
+           for (j = 0 ; j < image->Height ; j++) {
+              __memcpy(dst, src, row_len );
+              src += row_len;
+              dst += t->Pitch;
+           }
+
+           dst += t->depth_pitch - (t->Pitch * image->Height);
+        }
+      }
+   }
+}
+
+
+
+int intelUploadTexImages( intelContextPtr intel, 
+                         intelTextureObjectPtr t,
+                         GLuint face)
+{
+   const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+   const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
+   int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
+
+   /* Can we texture out of the existing client data? */
+   if ( numLevels == 1 &&
+       firstImage->IsClientData &&
+       (pitch & 3) == 0) {
+
+      if (INTEL_DEBUG & DEBUG_TEXTURE)
+        fprintf(stderr, "AGP texturing from client memory\n");
+
+      t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
+      t->BufAddr = 0;
+      t->dirty = ~0;
+      return GL_TRUE;
+   }
+   else {
+      if (INTEL_DEBUG & DEBUG_TEXTURE) 
+        fprintf(stderr, "Uploading client data to agp\n");
+
+      INTEL_FIREVERTICES( intel );
+      LOCK_HARDWARE( intel );
+
+      if ( t->base.memBlock == NULL ) {
+        int heap;
+
+        heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
+                                   (driTextureObject *) t );
+        if ( heap == -1 ) {
+           UNLOCK_HARDWARE( intel );
+           return GL_FALSE;
+        }
+
+        /* Set the base offset of the texture image */
+        t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
+        t->TextureOffset = intel->intelScreen->textureOffset + t->base.memBlock->ofs;
+        t->dirty = ~0;
+      }
+
+
+      /* Let the world know we've used this memory recently.
+       */
+      driUpdateTextureLRU( (driTextureObject *) t );
+
+
+      /* Upload any images that are new */
+      if (t->base.dirty_images[face]) {
+        int i;
+
+        intelWaitForIdle( intel );
+           
+        for (i = 0 ; i < numLevels ; i++) { 
+           int level = i + t->base.firstLevel;
+
+           if (t->base.dirty_images[face] & (1<<level)) {
+
+              const struct gl_texture_image *image = t->image[face][i].image;
+              GLuint offset = t->image[face][i].offset;
+
+              if (INTEL_DEBUG & DEBUG_TEXTURE)
+                 fprintf(stderr, "upload level %d, offset %x\n", 
+                         level, offset);
+
+              intelUploadTexImage( intel, t, image, offset );
+           }
+        }
+        t->base.dirty_images[face] = 0;
+        intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
+      }
+      
+      UNLOCK_HARDWARE( intel );
+      return GL_TRUE;
+   }
+}
+
+/**
+ * Allocate a new texture object.
+ * Called via ctx->Driver.NewTextureObject.
+ * Note: this function will be called during context creation to
+ * allocate the default texture objects.
+ * Note: we could use containment here to 'derive' the driver-specific
+ * texture object from the core mesa gl_texture_object.  Not done at this time.
+ */
+static struct gl_texture_object *
+intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
+{
+   struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
+   INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
+   return obj;
+}
+
+
+void intelInitTextureFuncs( struct dd_function_table *functions )
+{
+   functions->NewTextureObject          = intelNewTextureObject;
+   functions->ChooseTextureFormat       = intelChooseTextureFormat;
+   functions->TexImage1D                = intelTexImage1D;
+   functions->TexImage2D                = intelTexImage2D;
+   functions->TexImage3D                = intelTexImage3D;
+   functions->TexSubImage1D             = intelTexSubImage1D;
+   functions->TexSubImage2D             = intelTexSubImage2D;
+   functions->TexSubImage3D             = intelTexSubImage3D;
+   functions->CopyTexImage1D            = _swrast_copy_teximage1d;
+   functions->CopyTexImage2D            = _swrast_copy_teximage2d;
+   functions->CopyTexSubImage1D         = _swrast_copy_texsubimage1d;
+   functions->CopyTexSubImage2D         = _swrast_copy_texsubimage2d;
+   functions->CopyTexSubImage3D         = _swrast_copy_texsubimage3d;
+   functions->DeleteTexture             = intelDeleteTexture;
+   functions->UpdateTexturePalette      = NULL;
+   functions->IsTextureResident         = driIsTextureResident;
+   functions->TestProxyTexImage         = _mesa_test_proxy_teximage;
+   functions->DeleteTexture             = intelDeleteTexture;
+}
diff --git a/src/mesa/drivers/dri/i915/intel_tex.h b/src/mesa/drivers/dri/i915/intel_tex.h
new file mode 100644 (file)
index 0000000..fd4b926
--- /dev/null
@@ -0,0 +1,22 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#ifndef INTELTEX_INC
+#define INTELTEX_INC
+
+#include "mtypes.h"
+#include "intel_context.h"
+#include "texmem.h"
+
+
+void intelInitTextureFuncs( struct dd_function_table *functions );
+
+void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t );
+int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t,
+                         GLuint face );
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c
new file mode 100644 (file)
index 0000000..07d9878
--- /dev/null
@@ -0,0 +1,900 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "enums.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_tris.h"
+#include "intel_batchbuffer.h"
+#include "intel_reg.h"
+#include "intel_span.h"
+
+static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
+static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
+
+/***********************************************************************
+ *                    Emit primitives as inline vertices               *
+ ***********************************************************************/
+
+#if 1
+#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 {                                           \
+   if (1) fprintf(stderr, "\n");       \
+   for ( j = 0 ; j < vertsize ; j++ ) {                \
+      if (1) fprintf(stderr, "   -- v(%d): %x/%f\n",j, \
+             ((GLuint *)v)[j],                 \
+             ((GLfloat *)v)[j]);               \
+      vb[j] = ((GLuint *)v)[j];                        \
+   }                                           \
+   vb += vertsize;                             \
+} while (0)
+#endif
+
+static void __inline__ intel_draw_quad( intelContextPtr 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 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v2 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+}
+
+static void __inline__ intel_draw_triangle( intelContextPtr 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 __inline__ void intel_draw_line( intelContextPtr 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 __inline__ void intel_draw_point( intelContextPtr 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                       *
+ ***********************************************************************/
+
+static void intel_atten_point( intelContextPtr 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( intelContextPtr 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( intelContextPtr 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( intelContextPtr 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 {
+   points_func         points;
+   line_func           line;
+   triangle_func       triangle;
+   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)                                                  \
+   intelContextPtr 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( intelContextPtr intel,
+                  intelVertex *v0,
+                  intelVertex *v1,
+                  intelVertex *v2 )
+{
+   GLcontext *ctx = &intel->ctx;
+   SWvertex v[3];
+
+   if (0)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   _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( intelContextPtr intel,
+                   intelVertex *v0,
+                   intelVertex *v1 )
+{
+   GLcontext *ctx = &intel->ctx;
+   SWvertex v[2];
+
+   if (0)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   _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( intelContextPtr intel,
+                    intelVertex *v0 )
+{
+   GLcontext *ctx = &intel->ctx;
+   SWvertex v[1];
+
+   if (0)
+      fprintf(stderr, "\n%s\n", __FUNCTION__);
+
+   _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                                             \
+    intelContextPtr 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 )
+{
+   intelContextPtr 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 )
+{
+   intelContextPtr 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 POINT_FALLBACK (0)
+#define LINE_FALLBACK (DD_LINE_STIPPLE)
+#define TRI_FALLBACK (0)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
+                            DD_TRI_STIPPLE|DD_POINT_ATTEN)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
+void intelChooseRenderState(GLcontext *ctx)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   intelContextPtr intel = INTEL_CONTEXT(ctx);
+   GLuint flags = ctx->_TriangleCaps;
+   struct fragment_program *program = ctx->FragmentProgram.Current;
+   GLboolean have_wpos = (program && (program->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 & POINT_FALLBACK)
+           intel->draw_point = intel_fallback_point;
+
+        if (flags & LINE_FALLBACK)
+           intel->draw_line = intel_fallback_line;
+
+        if (flags & TRI_FALLBACK)
+           intel->draw_tri = intel_fallback_tri;
+
+        if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple) 
+           intel->draw_tri = intel_fallback_tri;
+
+        if (flags & DD_POINT_ATTEN)
+           intel->draw_point = intel_atten_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 )
+{
+   intelContextPtr intel = INTEL_CONTEXT(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 );
+}
+
+static void intelRenderStart( GLcontext *ctx )
+{
+   INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) );
+}
+
+static void intelRenderFinish( GLcontext *ctx )
+{
+   if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
+      _swrast_flush( ctx );
+}
+
+
+
+
+ /* System to flush dma and emit state changes based on the rasterized
+  * primitive.
+  */
+static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
+{
+   intelContextPtr 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) 
+      intelStartInlinePrimitive( intel, hwprim );
+}
+
+
+ /* 
+  */
+ static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
+ {
+    intelContextPtr 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[] = {
+    "Texture",
+    "Draw buffer",
+    "Read buffer",
+    "Color mask",
+    "Render mode",
+    "Stencil",
+    "Stipple",
+    "User disable"
+ };
+
+
+ static char *getFallbackString(GLuint bit)
+ {
+    int i = 0;
+    while (bit > 1) {
+       i++;
+       bit >>= 1;
+    }
+    return fallbackStrings[i];
+ }
+
+
+
+ void intelFallback( intelContextPtr 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;
+       }
+    }
+ }
+
+
+
+
+/**********************************************************************/
+/*                            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/i915/intel_tris.h b/src/mesa/drivers/dri/i915/intel_tris.h
new file mode 100644 (file)
index 0000000..928bfb1
--- /dev/null
@@ -0,0 +1,26 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ **************************************************************************/
+
+#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 intelPrintRenderState( const char *msg, GLuint state );
+extern void intelChooseRenderState( GLcontext *ctx );
+
+#endif
diff --git a/src/mesa/drivers/dri/i915/server/i830_common.h b/src/mesa/drivers/dri/i915/server/i830_common.h
new file mode 100644 (file)
index 0000000..c03f742
--- /dev/null
@@ -0,0 +1,169 @@
+/**************************************************************************
+
+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
+
+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 */   
+} 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;
+
+
+#endif /* _I830_DRM_H_ */
diff --git a/src/mesa/drivers/dri/i915/server/i830_dri.h b/src/mesa/drivers/dri/i915/server/i830_dri.h
new file mode 100644 (file)
index 0000000..29a5988
--- /dev/null
@@ -0,0 +1,70 @@
+/* $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
+
+/* Note: This structure has changed slightly from what is expected by
+ * the i830_drv.o driver.  Maybe that should be reverted.
+ */
+typedef struct _I830DRIRec {
+   drm_handle_t regs;
+   drmSize regsSize;
+   drmAddress regsMap;
+
+   drmSize backbufferSize;
+   drm_handle_t backbuffer;
+
+   drmSize depthbufferSize;
+   drm_handle_t depthbuffer;
+
+   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 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