I copied together some sort of GL_ARB_texture_cube_map support
for radeon in swtcl mode.

tested with cubemap from mesa.
Unfortunately when using TMU0, only the front, right and top
face is rendered fine, the other faces look strange.

@Michel Daenzer: and it shows missing triangles/quads.

I modified cubemap to use TMU1
 glTexCoord3f( -> glMultiTexCoord3fARB( GL_TEXTURE1_ARB, 
and setting glActiveTexture...

and now it works as expected. Sometimes a triangle is missing,
but overall texturing looks ok.

any hints?

greetings,
Andreas

patches: one is against mesa cvs, the other is against dri-cvs (kernel-code)
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_context.c Mesa/src/mesa/drivers/dri/radeon/radeon_context.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_context.c	Sat Dec 13 18:07:05 2003
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_context.c	Sat Jan 10 10:04:38 2004
@@ -147,6 +147,7 @@
 };
 
 extern const struct tnl_pipeline_stage _radeon_texrect_stage;
+extern const struct tnl_pipeline_stage _radeon_cubemap_stage;
 extern const struct tnl_pipeline_stage _radeon_render_stage;
 extern const struct tnl_pipeline_stage _radeon_tcl_stage;
 
@@ -169,6 +170,10 @@
     */
    &_radeon_texrect_stage,
 
+   /* move R -> Q coord
+    */
+   &_radeon_cubemap_stage,
+
    &_radeon_render_stage,
    &_tnl_render_stage,		/* FALLBACK:  */
    0,
@@ -314,7 +319,9 @@
 				 4,
 				 11, /* max 2D texture size is 2048x2048 */
 				 0,  /* 3D textures unsupported. */
-				 0,  /* cube textures unsupported. */
+				 10,  /* FIXME: don't know about the max cube texture size of r100 / IGP */
+				     /* I got segfault with 2048er cubes, notex with 1024er cubes */
+				     /* could that be a generic problem when someone just doesnt respect GL_MAX_TEXTURE_SIZE_XX */
 				 11, /* max rect texture size is 2048x2048. */
 				 12,
 				 GL_FALSE );
@@ -388,6 +395,9 @@
 
    if (rmesa->dri.drmMinor >= 9)
       _mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
+
+   if (rmesa->radeonScreen->drmSupportsCubeMaps)
+      _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map");
 
    radeonInitDriverFuncs( ctx );
    radeonInitIoctlFuncs( ctx );
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_context.h Mesa/src/mesa/drivers/dri/radeon/radeon_context.h
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_context.h	Sun Jan  4 23:14:53 2004
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_context.h	Sat Jan 10 10:08:59 2004
@@ -262,6 +262,16 @@
 #define TXR_PP_TEX_PITCH            2 /* 0x1d08, 0x1d10 for NPOT! */
 #define TXR_STATE_SIZE              3
 
+#define CUBE_CMD_0                  0
+#define CUBE_PP_CUBIC_FACES         1
+#define CUBE_CMD_1                  2
+#define CUBE_PP_CUBIC_OFFSET_0      3
+#define CUBE_PP_CUBIC_OFFSET_1      4
+#define CUBE_PP_CUBIC_OFFSET_2      5
+#define CUBE_PP_CUBIC_OFFSET_3      6
+#define CUBE_PP_CUBIC_OFFSET_4      7
+#define CUBE_STATE_SIZE             8
+
 #define ZBS_CMD_0              0
 #define ZBS_SE_ZBIAS_FACTOR             1
 #define ZBS_SE_ZBIAS_CONSTANT           2
@@ -416,6 +426,7 @@
    struct radeon_state_atom tcl;
    struct radeon_state_atom msc;
    struct radeon_state_atom tex[2];
+   struct radeon_state_atom cube[2];
    struct radeon_state_atom zbs;
    struct radeon_state_atom mtl; 
    struct radeon_state_atom mat[5]; 
@@ -638,23 +649,27 @@
    GLuint prim;
 };
 
+#define RADEON_MAX_VERTEX_SIZE 15
+/* at the moment packed colors are used, so we have only 4 byte for color, not 4 floats (IMHO) */
+
 struct radeon_vbinfo {
    GLint counter, initial_counter;
    GLint *dmaptr;
    void (*notify)( void );
    GLint vertex_size;
 
-   /* A maximum total of 15 elements per vertex:  3 floats for position, 3
+   /* A maximum total of 17 elements per vertex:  3 floats for position, 3
     * floats for normal, 4 floats for color, 4 bytes for secondary color,
-    * 2 floats for each texture unit (4 floats total).
+    * 3 floats for each texture unit (6 floats total).
     * 
     * As soon as the 3rd TMU is supported or cube maps (or 3D textures) are
     * supported, this value will grow.
+    * we need 1 add. float per TMU for the q-coord! -> 17
     * 
     * The position data is never actually stored here, so 3 elements could be
     * trimmed out of the buffer.
     */
-   union { float f; int i; radeon_color_t color; } vertex[15];
+   union { float f; int i; radeon_color_t color; } vertex[RADEON_MAX_VERTEX_SIZE];
 
    GLfloat *normalptr;
    GLfloat *floatcolorptr;
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_ioctl.c Mesa/src/mesa/drivers/dri/radeon/radeon_ioctl.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_ioctl.c	Sun Jan  4 23:14:53 2004
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_ioctl.c	Sat Jan 10 01:08:47 2004
@@ -128,6 +128,7 @@
    for (i = 0; i < texunits; ++i) {
        EMIT_ATOM (tex[i]);
        EMIT_ATOM (txr[i]);
+       EMIT_ATOM (cube[i]);
    }
    EMIT_ATOM (zbs);
    EMIT_ATOM (mtl);
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_sanity.c Mesa/src/mesa/drivers/dri/radeon/radeon_sanity.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_sanity.c	Fri Dec 12 18:14:26 2003
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_sanity.c	Sat Jan 10 10:09:37 2004
@@ -138,6 +138,12 @@
    { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
    { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
    { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
+   { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0" },
+   { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0" },
+   { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1" },
+   { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0" },
+   { RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2" },
+   { RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0" },
 };
 
 struct reg_names {
@@ -231,6 +237,24 @@
    { RADEON_PP_TEX_SIZE_0+4, "RADEON_PP_TEX_PITCH_0" },
    { RADEON_PP_TEX_SIZE_1+4, "RADEON_PP_TEX_PITCH_1" },
    { RADEON_PP_TEX_SIZE_2+4, "RADEON_PP_TEX_PITCH_2" },
+   { RADEON_PP_CUBIC_FACES_0, "RADEON_PP_CUBIC_FACES_0" },
+   { RADEON_PP_CUBIC_FACES_1, "RADEON_PP_CUBIC_FACES_1" },
+   { RADEON_PP_CUBIC_FACES_2, "RADEON_PP_CUBIC_FACES_2" },
+   { RADEON_PP_CUBIC_OFFSET_T0_0, "RADEON_PP_CUBIC_OFFSET_T0_0" },
+   { RADEON_PP_CUBIC_OFFSET_T0_1, "RADEON_PP_CUBIC_OFFSET_T0_1" },
+   { RADEON_PP_CUBIC_OFFSET_T0_2, "RADEON_PP_CUBIC_OFFSET_T0_2" },
+   { RADEON_PP_CUBIC_OFFSET_T0_3, "RADEON_PP_CUBIC_OFFSET_T0_3" },
+   { RADEON_PP_CUBIC_OFFSET_T0_4, "RADEON_PP_CUBIC_OFFSET_T0_4" },
+   { RADEON_PP_CUBIC_OFFSET_T1_0, "RADEON_PP_CUBIC_OFFSET_T1_0" },
+   { RADEON_PP_CUBIC_OFFSET_T1_1, "RADEON_PP_CUBIC_OFFSET_T1_1" },
+   { RADEON_PP_CUBIC_OFFSET_T1_2, "RADEON_PP_CUBIC_OFFSET_T1_2" },
+   { RADEON_PP_CUBIC_OFFSET_T1_3, "RADEON_PP_CUBIC_OFFSET_T1_3" },
+   { RADEON_PP_CUBIC_OFFSET_T1_4, "RADEON_PP_CUBIC_OFFSET_T1_4" },
+   { RADEON_PP_CUBIC_OFFSET_T2_0, "RADEON_PP_CUBIC_OFFSET_T2_0" },
+   { RADEON_PP_CUBIC_OFFSET_T2_1, "RADEON_PP_CUBIC_OFFSET_T2_1" },
+   { RADEON_PP_CUBIC_OFFSET_T2_2, "RADEON_PP_CUBIC_OFFSET_T2_2" },
+   { RADEON_PP_CUBIC_OFFSET_T2_3, "RADEON_PP_CUBIC_OFFSET_T2_3" },
+   { RADEON_PP_CUBIC_OFFSET_T2_4, "RADEON_PP_CUBIC_OFFSET_T2_4" },
 };
 
 static struct reg_names scalar_names[] = {
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_screen.c Mesa/src/mesa/drivers/dri/radeon/radeon_screen.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_screen.c	Wed Jan  7 18:47:59 2004
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_screen.c	Sat Jan 10 01:08:47 2004
@@ -157,6 +157,7 @@
 	    fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
 	    return NULL;
 	 }
+	 screen->drmSupportsCubeMaps = (sPriv->drmMinor >= 11);
       }
    }
 
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_screen.h Mesa/src/mesa/drivers/dri/radeon/radeon_screen.h
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_screen.h	Mon Dec  8 22:05:23 2003
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_screen.h	Sat Jan 10 01:08:47 2004
@@ -98,6 +98,7 @@
 
    /* Configuration cache with default values for all contexts */
    driOptionCache optionCache;
+   GLboolean drmSupportsCubeMaps;       /* need radeon kernel module >= 1.11 */
 } radeonScreenRec, *radeonScreenPtr;
 
 extern radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv );
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_state_init.c Mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_state_init.c	Mon Dec  8 22:05:23 2003
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c	Sat Jan 10 17:21:03 2004
@@ -112,8 +112,11 @@
 
 
 CHECK( always, GL_TRUE )
+CHECK( never, GL_FALSE )
 CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled )
 CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+CHECK( cube0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_CUBE_BIT))
+CHECK( cube1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_CUBE_BIT))
 CHECK( fog, ctx->Fog.Enabled )
 TCL_CHECK( tcl, GL_TRUE )
 TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled )
@@ -232,6 +235,16 @@
    ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
    ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 );
    ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 );
+   if (rmesa->radeonScreen->drmSupportsCubeMaps)
+   {
+      ALLOC_STATE( cube[0], cube0, CUBE_STATE_SIZE, "CUBE/cube-0", 0 );
+      ALLOC_STATE( cube[1], cube1, CUBE_STATE_SIZE, "CUBE/cube-1", 0 );
+   }
+   else
+   {
+      ALLOC_STATE( cube[0], never, CUBE_STATE_SIZE, "CUBE/cube-0", 0 );
+      ALLOC_STATE( cube[1], never, CUBE_STATE_SIZE, "CUBE/cube-1", 0 );
+   }
    ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
    ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
    ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
@@ -271,6 +284,10 @@
    rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0);
    rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1);
    rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1);
+   rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(RADEON_EMIT_PP_CUBIC_FACES_0);
+   rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(RADEON_EMIT_PP_CUBIC_OFFSETS_T0);
+   rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(RADEON_EMIT_PP_CUBIC_FACES_1);
+   rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(RADEON_EMIT_PP_CUBIC_OFFSETS_T1);
    rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
    rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
    rmesa->hw.mtl.cmd[MTL_CMD_0] = 
@@ -311,8 +328,8 @@
 				     RADEON_CHROMA_FUNC_FAIL |
 				     RADEON_CHROMA_KEY_NEAREST |
 				     RADEON_SHADOW_FUNC_EQUAL |
-				     RADEON_SHADOW_PASS_1 |
-				     RADEON_RIGHT_HAND_CUBE_OGL);
+				     RADEON_SHADOW_PASS_1);
+     /* isn't it strange that we mustn't set RADEON_RIGHT_HAND_CUBE_OGL ? */
 
    rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
 					  RADEON_FOG_USE_DEPTH);
@@ -461,6 +478,18 @@
 	   RADEON_SCALE_1X |
 	   RADEON_CLAMP_TX);
       rmesa->hw.tex[i].cmd[TEX_PP_TFACTOR] = 0;
+
+      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0;
+      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_0] =
+	  rmesa->radeonScreen->texOffset[RADEON_CARD_HEAP];
+      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_1] =
+	  rmesa->radeonScreen->texOffset[RADEON_CARD_HEAP];
+      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_2] =
+	  rmesa->radeonScreen->texOffset[RADEON_CARD_HEAP];
+      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_3] =
+	  rmesa->radeonScreen->texOffset[RADEON_CARD_HEAP];
+      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_4] =
+	  rmesa->radeonScreen->texOffset[RADEON_CARD_HEAP];
    }
 
    /* Can only add ST1 at the time of doing some multitex but can keep
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_swtcl.c Mesa/src/mesa/drivers/dri/radeon/radeon_swtcl.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_swtcl.c	Wed Jan  7 18:47:59 2004
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_swtcl.c	Sat Jan 10 17:43:01 2004
@@ -670,8 +670,141 @@
    radeon_run_render		/* run */
 };
 
-
 /**************************************************************************/
+
+/* Radeon texture cubemapping expects the r coord as q coord
+ * so we have to move the r value to q's place if cubemapping.
+ * but dont if sw-rendering fallback required (as in radeon texrect stage)
+ */
+/* FIXME: I just copied from texrect stage and modified a bit, someone
+   who understands how the stages work should clean it up a bit ;) */
+/* do we really need to copy everything or could we mess in the input-buffer? */
+/* is there a better place for doing that moving? */
+struct cubemap_stage_data {
+   GLvector4f texcoord[MAX_TEXTURE_UNITS];	/* or should we use RADEON_MAX_TEXTURE_UNITS ? if, then when freeing also! */
+};
+
+#define CUBEMAP_STAGE_DATA(stage) ((struct cubemap_stage_data *)stage->privatePtr)
+
+
+static GLboolean run_cubemap_stage( GLcontext *ctx,
+				    struct tnl_pipeline_stage *stage )
+{
+   struct cubemap_stage_data *store = CUBEMAP_STAGE_DATA(stage);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i;
+
+   if (rmesa->Fallback)
+      return GL_TRUE;
+
+   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
+      if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT))
+	 continue;
+   
+      if (stage->changed_inputs & VERT_BIT_TEX(i)) {
+	 GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data;
+	 GLint instride = VB->TexCoordPtr[i]->stride;
+	 GLfloat (*out)[4] = store->texcoord[i].data;
+	 GLint j;
+
+ASSERT(instride>=16);	/* we need 4 coords! */
+
+	 for (j = 0 ; j < VB->Count ; j++) {
+	    out[j][0] = in[0];
+	    out[j][1] = in[1];
+	    out[j][3] = in[2];
+	    out[j][2] = in[3];
+#if 0
+   in[2]= in[3];
+   in[3]= out[j][3];
+#endif
+	    in = (GLfloat *)((GLubyte *)in + instride);
+	 }
+      }
+#if 1
+      VB->TexCoordPtr[i] = &store->texcoord[i];
+#endif
+      VB->TexCoordPtr[i]->size= 4;
+   }
+
+   return GL_TRUE;
+}
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_cubemap_data( GLcontext *ctx,
+				     struct tnl_pipeline_stage *stage )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct cubemap_stage_data *store;
+   GLuint i;
+
+   stage->privatePtr = CALLOC(sizeof(*store));
+   store = CUBEMAP_STAGE_DATA(stage);
+   if (!store)
+      return GL_FALSE;
+
+   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+      _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+   /* Now run the stage.
+    */
+   stage->run = run_cubemap_stage;
+   return stage->run( ctx, stage );
+}
+
+/* FIXME: what should be used: VERT_BIT_xxx or _TNL_BIT_xxx ? */
+
+static void check_cubemap( GLcontext *ctx,
+			   struct tnl_pipeline_stage *stage )
+{
+   GLuint flags = 0;
+   GLuint unit;
+
+   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
+      if (ctx->Texture.Unit[unit]._ReallyEnabled & TEXTURE_CUBE_BIT)
+	 flags |= VERT_BIT_TEX(unit);
+   }
+
+   stage->inputs = flags;
+   stage->outputs = flags;
+   stage->active = (flags != 0);
+}
+
+
+static void free_cubemap_data( struct tnl_pipeline_stage *stage )
+{
+   struct cubemap_stage_data *store = CUBEMAP_STAGE_DATA(stage);
+   GLuint i;
+
+   if (store) {
+      for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)	/* or should we use MAX_TEXTURE_UNITS ? */
+	 if (store->texcoord[i].data)
+	    _mesa_vector4f_free( &store->texcoord[i] );
+      FREE( store );
+      stage->privatePtr = 0;
+   }
+}
+
+
+const struct tnl_pipeline_stage _radeon_cubemap_stage =
+{
+   "radeon cubemap stage",			/* name */
+   _NEW_TEXTURE,	/* check_state */
+   _NEW_TEXTURE,	/* run_state */
+   GL_TRUE,				/* active? */
+   0,					/* inputs */
+   0,					/* outputs */
+   0,					/* changed_inputs */
+   NULL,				/* private data */
+   free_cubemap_data,			/* destructor */
+   check_cubemap,			/* check */
+   alloc_cubemap_data,			/* run -- initially set to init */
+};
+
 
 /* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension
  * as in the extension spec.  Need to translate here.
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_tcl.h Mesa/src/mesa/drivers/dri/radeon/radeon_tcl.h
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_tcl.h	Tue Oct 21 08:05:50 2003
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_tcl.h	Sat Jan 10 01:08:47 2004
@@ -60,8 +60,11 @@
 #define RADEON_TCL_FALLBACK_TEXRECT_0         0x100 /* texture rectangle */
 #define RADEON_TCL_FALLBACK_TEXRECT_1         0x200 /* texture rectangle */
 #define RADEON_TCL_FALLBACK_TEXRECT_2         0x400 /* texture rectangle */
+#define RADEON_TCL_FALLBACK_TEXCUBEMAP_0      0x800 /* cubemapping */
+#define RADEON_TCL_FALLBACK_TEXCUBEMAP_1      0x1000 /* cubemapping */
+#define RADEON_TCL_FALLBACK_TEXCUBEMAP_2      0x2000 /* cubemapping */
 
-#define RADEON_MAX_TCL_VERTSIZE (15*4)
+#define RADEON_MAX_TCL_VERTSIZE (RADEON_MAX_VERTEX_SIZE*4)
 
 #define TCL_FALLBACK( ctx, bit, mode )	radeonTclFallback( ctx, bit, mode )
 
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_texstate.c Mesa/src/mesa/drivers/dri/radeon/radeon_texstate.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_texstate.c	Tue Oct 21 08:05:50 2003
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_texstate.c	Sat Jan 10 17:08:32 2004
@@ -203,6 +203,25 @@
     */
    t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
 
+   /* Setup remaining cube face blits, if needed */
+   if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
+      /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
+      const GLuint faceSize = (t->base.totalSize + BLIT_WIDTH_BYTES - 1)
+                              & ~(BLIT_WIDTH_BYTES-1);
+      const GLuint lines = faceSize / BLIT_WIDTH_BYTES;
+      GLuint face;
+      /* reuse face 0 x/y/width/height - just adjust y */
+      for (face = 1; face < 6; face++) {
+         for (i = 0; i < numLevels; i++) {
+            t->image[face][i].x =  t->image[0][i].x;
+            t->image[face][i].y =  t->image[0][i].y + face * lines;
+            t->image[face][i].width  = t->image[0][i].width;
+            t->image[face][i].height = t->image[0][i].height;
+         }
+      }
+      t->base.totalSize = 6 * faceSize; /* total texmem needed */
+   }
+
    /* Hardware state:
     */
    t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
@@ -214,6 +233,21 @@
    t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
 		      (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
 
+   if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
+      assert(log2Width == log2Height);
+      t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |
+                         (log2Height << RADEON_TXFORMAT_F5_HEIGHT_SHIFT) |
+                         (RADEON_TXFORMAT_CUBIC_MAP_ENABLE));
+      t->pp_cubic_faces = ((log2Width << RADEON_FACE_WIDTH_1_SHIFT) |
+                           (log2Height << RADEON_FACE_HEIGHT_1_SHIFT) |
+                           (log2Width << RADEON_FACE_WIDTH_2_SHIFT) |
+                           (log2Height << RADEON_FACE_HEIGHT_2_SHIFT) |
+                           (log2Width << RADEON_FACE_WIDTH_3_SHIFT) |
+                           (log2Height << RADEON_FACE_HEIGHT_3_SHIFT) |
+                           (log2Width << RADEON_FACE_WIDTH_4_SHIFT) |
+                           (log2Height << RADEON_FACE_HEIGHT_4_SHIFT));
+   }
+
    t->pp_txsize = (((tObj->Image[t->base.firstLevel]->Width - 1) << 0) |
                    ((tObj->Image[t->base.firstLevel]->Height - 1) << 16));
 
@@ -1253,30 +1287,59 @@
    cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
    cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
    cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
-   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
 
-   if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+   if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
+      GLuint *cube_cmd = RADEON_DB_STATE( cube[unit] );
+      GLuint bytesPerFace = texobj->base.totalSize / 6;
+      ASSERT(texobj->totalSize % 6 == 0);
+
+      cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
+      /* dont know if this setup conforms to OpenGL.. 
+       * at least it matches the behavior of mesa software renderer
+       */
+      cube_cmd[CUBE_PP_CUBIC_OFFSET_0] = texobj->pp_txoffset; /* right */
+      cube_cmd[CUBE_PP_CUBIC_OFFSET_1] = texobj->pp_txoffset + 1 * bytesPerFace; /* left */
+      cube_cmd[CUBE_PP_CUBIC_OFFSET_2] = texobj->pp_txoffset + 2 * bytesPerFace; /* top */
+      cube_cmd[CUBE_PP_CUBIC_OFFSET_3] = texobj->pp_txoffset + 3 * bytesPerFace; /* bottom */
+      cube_cmd[CUBE_PP_CUBIC_OFFSET_4] = texobj->pp_txoffset + 4 * bytesPerFace; /* front */
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.cube[unit] );
+      cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset + 5 * bytesPerFace; /* back */
+   }
+   else if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
       GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
       txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
       txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
       RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] );
    }
 
+   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
+
    texobj->dirty_state &= ~(1<<unit);
 }
 
 
 
+/* FIXME: cubemap-patch: I didnt bother trying to understand the following, so just
+ * copied from R200 and/or earlier (nonworking) cubemap-patches I found.
+ * Maybe its only needed if cubemapping is done with hw-tcl.
+ *
+ * btw: is cubemapping even possible in hw-tcl on R100 ?
+ * Or is it only possible if in non-texgen-mode?
+ * Or do we need texgen-mode for Q first? (its a fallback atm)
+ * or some magic between texgen-Q and R ?
+ */
 
 static void set_texgen_matrix( radeonContextPtr rmesa, 
 			       GLuint unit,
 			       const GLfloat *s_plane,
-			       const GLfloat *t_plane )
+			       const GLfloat *t_plane,
+			       const GLfloat *r_plane )
 {
    static const GLfloat scale_identity[4] = { 1,1,1,1 };
 
    if (!TEST_EQ_4V( s_plane, scale_identity) ||
-       !TEST_EQ_4V( t_plane, scale_identity)) {
+       !TEST_EQ_4V( t_plane, scale_identity) ||
+       !TEST_EQ_4V( r_plane, scale_identity)) {
       rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
       rmesa->TexGenMatrix[unit].m[0]  = s_plane[0];
       rmesa->TexGenMatrix[unit].m[4]  = s_plane[1];
@@ -1287,10 +1350,46 @@
       rmesa->TexGenMatrix[unit].m[5]  = t_plane[1];
       rmesa->TexGenMatrix[unit].m[9]  = t_plane[2];
       rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
+
+      /* NOTE: r_plane goes in the 4th row, not 3rd! */
+      rmesa->TexGenMatrix[unit].m[3]  = r_plane[0];
+      rmesa->TexGenMatrix[unit].m[7]  = r_plane[1];
+      rmesa->TexGenMatrix[unit].m[11] = r_plane[2];
+      rmesa->TexGenMatrix[unit].m[15] = r_plane[3];
+
       rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
    }
 }
 
+/* Need this special matrix to get correct reflection map coords */
+static void
+set_texgen_reflection_matrix( radeonContextPtr rmesa, GLuint unit )
+{
+   static const GLfloat m[16] = {
+      -1,  0,  0,  0,
+       0, -1,  0,  0,
+       0,  0,  0, -1,
+       0,  0, -1,  0 };
+   _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
+   _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
+   rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
+}
+
+/* Need this special matrix to get correct normal map coords */
+static void
+set_texgen_normal_map_matrix( radeonContextPtr rmesa, GLuint unit )
+{
+   static const GLfloat m[16] = {
+      1, 0, 0, 0,
+      0, 1, 0, 0,
+      0, 0, 0, 1,
+      0, 0, 1, 0 };
+   _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
+   _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
+   rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
+}
+
+
 /* Ignoring the Q texcoord for now.
  *
  * Returns GL_FALSE if fallback required.  
@@ -1307,7 +1406,7 @@
    rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
    rmesa->TexGenNeedNormals[unit] = 0;
 
-   if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) == 0) {
+   if ((texUnit->TexGenEnabled & (S_BIT|T_BIT|R_BIT)) == 0) {
       /* Disabled, no fallback:
        */
       rmesa->TexGenEnabled |= 
@@ -1318,42 +1417,58 @@
       /* Very easy to do this, in fact would remove a fallback case
        * elsewhere, but I haven't done it yet...  Fallback: 
        */
-      fprintf(stderr, "fallback Q_BIT\n");
+      /*fprintf(stderr, "fallback Q_BIT\n");*/
       return GL_FALSE;
    }
-   else if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) != (S_BIT|T_BIT) ||
-	    texUnit->GenModeS != texUnit->GenModeT) {
+   else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
+	    texUnit->GenModeS == texUnit->GenModeT) {
+      /* OK */
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
+      /* continue */
+   }
+   else if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT) &&
+	    texUnit->GenModeS == texUnit->GenModeT &&
+            texUnit->GenModeT == texUnit->GenModeR) {
+      /* OK */
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
+      /* continue */
+   }
+   else {
       /* Mixed modes, fallback:
        */
       /* fprintf(stderr, "fallback mixed texgen\n"); */
       return GL_FALSE;
    }
-   else
-      rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
+
+   rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
 
    switch (texUnit->GenModeS) {
    case GL_OBJECT_LINEAR:
       rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
       set_texgen_matrix( rmesa, unit, 
 			 texUnit->ObjectPlaneS,
-			 texUnit->ObjectPlaneT);
+			 texUnit->ObjectPlaneT,
+                         texUnit->ObjectPlaneR);
       break;
 
    case GL_EYE_LINEAR:
       rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
       set_texgen_matrix( rmesa, unit, 
 			 texUnit->EyePlaneS,
-			 texUnit->EyePlaneT);
+			 texUnit->EyePlaneT,
+			 texUnit->EyePlaneR);
       break;
 
    case GL_REFLECTION_MAP_NV:
       rmesa->TexGenNeedNormals[unit] = GL_TRUE;
       rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
+      set_texgen_reflection_matrix(rmesa, unit);
       break;
 
    case GL_NORMAL_MAP_NV:
       rmesa->TexGenNeedNormals[unit] = GL_TRUE;
       rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
+      set_texgen_normal_map_matrix(rmesa, unit);
       break;
 
    case GL_SPHERE_MAP:
@@ -1459,6 +1574,48 @@
    return GL_TRUE;
 }
 
+static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+   GLuint face;
+
+   /* Need to load the 2d images associated with this unit.
+    */
+   if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
+      t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
+      for (face = 0; face < 6; face++)
+         t->base.dirty_images[face] = ~0;
+   }
+
+   ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
+
+   if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
+        t->base.dirty_images[2] || t->base.dirty_images[3] ||
+        t->base.dirty_images[4] || t->base.dirty_images[5] ) {
+      /* flush */
+      RADEON_FIREVERTICES( rmesa );
+      /* layout memory space, once for all faces */
+      radeonSetTexImages( rmesa, tObj );
+   }
+
+   /* upload (per face) */
+   for (face = 0; face < 6; face++) {
+      if (t->base.dirty_images[face]) {
+         radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, face );
+      }
+   }
+      
+   if ( !t->base.memBlock ) {
+      /* texmem alloc failed, use s/w fallback */
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
@@ -1570,6 +1727,7 @@
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
 
    TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 0 );
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXCUBEMAP_0 << unit, 0);
 
    if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
       TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 1 );
@@ -1579,6 +1737,13 @@
    }
    else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
       return (enable_tex_2d( ctx, unit ) &&
+	      update_tex_common( ctx, unit ));
+   }
+   else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
+#if 1
+      TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXCUBEMAP_0 << unit, 1);
+#endif
+      return (enable_tex_cube( ctx, unit ) &&
 	      update_tex_common( ctx, unit ));
    }
    else if ( texUnit->_ReallyEnabled ) {
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c Mesa/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
--- Mesa_orig/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c	Sun Jan  4 23:14:53 2004
+++ Mesa/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c	Sat Jan 10 01:08:47 2004
@@ -262,7 +262,7 @@
  * memory.  Could also use the counter/notify mechanism to populate
  * tmp on the fly as vertices are generated.  
  */
-static GLuint copy_dma_verts( radeonContextPtr rmesa, GLfloat (*tmp)[15] )
+static GLuint copy_dma_verts( radeonContextPtr rmesa, GLfloat (*tmp)[RADEON_MAX_VERTEX_SIZE] )
 {
    GLuint ovf, i;
    GLuint nr = (rmesa->vb.initial_counter - rmesa->vb.counter) - rmesa->vb.primlist[rmesa->vb.nrprims].start;
@@ -354,7 +354,7 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLfloat tmp[3][15];
+   GLfloat tmp[3][RADEON_MAX_VERTEX_SIZE];
    GLuint i, prim;
    GLuint ind = rmesa->vb.vertex_format;
    GLuint nrverts;
@@ -468,7 +468,7 @@
 {
    GET_CURRENT_CONTEXT(ctx);
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
-   GLfloat tmp[3][15];
+   GLfloat tmp[3][RADEON_MAX_VERTEX_SIZE];
    GLuint i, nrverts;
 
    if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS))
diff -ru Mesa_orig/src/mesa/drivers/dri/radeon/server/radeon_common.h Mesa/src/mesa/drivers/dri/radeon/server/radeon_common.h
--- Mesa_orig/src/mesa/drivers/dri/radeon/server/radeon_common.h	Mon Dec  8 22:05:23 2003
+++ Mesa/src/mesa/drivers/dri/radeon/server/radeon_common.h	Sat Jan 10 01:08:47 2004
@@ -360,7 +360,13 @@
 #define RADEON_EMIT_PP_TEX_SIZE_0                   73
 #define RADEON_EMIT_PP_TEX_SIZE_1                   74
 #define RADEON_EMIT_PP_TEX_SIZE_2                   75
-#define RADEON_MAX_STATE_PACKETS                    76
+#define RADEON_EMIT_PP_CUBIC_FACES_0                76
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0             77
+#define RADEON_EMIT_PP_CUBIC_FACES_1                78
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1             79
+#define RADEON_EMIT_PP_CUBIC_FACES_2                80
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2             81
+#define RADEON_MAX_STATE_PACKETS                    82
 
 
 /* Commands understood by cmd_buffer ioctl.  More can be added but

Attachment: dri_radeon_kernel_cube_10Jan2004.diff
Description: Binary data

Reply via email to