From 247f3b3e81fffa86c50531070fab573e26ffb452 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Sat, 15 Oct 2005 23:45:53 +0000 Subject: [PATCH] enable cube maps on radeon (#2241 on bugzilla). No vtxfmt code yet (just generates vfmt fallback). Code by Andreas Stenglein, some small adjustments by me. --- docs/VERSIONS | 1 + src/mesa/drivers/dri/radeon/radeon_context.c | 6 +- src/mesa/drivers/dri/radeon/radeon_context.h | 11 ++ src/mesa/drivers/dri/radeon/radeon_ioctl.c | 1 + .../drivers/dri/radeon/radeon_maos_arrays.c | 4 +- .../drivers/dri/radeon/radeon_maos_verts.c | 3 +- src/mesa/drivers/dri/radeon/radeon_screen.c | 1 + src/mesa/drivers/dri/radeon/radeon_screen.h | 1 + src/mesa/drivers/dri/radeon/radeon_state.c | 1 - .../drivers/dri/radeon/radeon_state_init.c | 37 +++++- src/mesa/drivers/dri/radeon/radeon_swtcl.c | 11 +- src/mesa/drivers/dri/radeon/radeon_tex.c | 21 ++- src/mesa/drivers/dri/radeon/radeon_texmem.c | 3 +- src/mesa/drivers/dri/radeon/radeon_texstate.c | 120 +++++++++++++++++- 14 files changed, 202 insertions(+), 19 deletions(-) diff --git a/docs/VERSIONS b/docs/VERSIONS index 315fd3ddbc6..58ec9edff25 100644 --- a/docs/VERSIONS +++ b/docs/VERSIONS @@ -1383,6 +1383,7 @@ Mesa Version History - GL_EXT_timer_query extension - r200: add support for GL_ATI_fragment_shader - added fast XOR-mode line drawing optimization + - radeon: add support for all 3 tmus and cube maps Changes: - removed GL_HP_occlusion_test (use GL_ARB_occlusion_query instead) Bug fixes: diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c index 9ab6e676780..a1e3582415c 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_context.c @@ -69,7 +69,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define need_GL_EXT_secondary_color #include "extension_helper.h" -#define DRIVER_DATE "20051008" +#define DRIVER_DATE "20051013" #include "vblank.h" #include "utils.h" @@ -338,7 +338,7 @@ radeonCreateContext( const __GLcontextModes *glVisual, 4, 11, /* max 2D texture size is 2048x2048 */ 0, /* 3D textures unsupported. */ - 0, /* cube textures unsupported. */ + 9, /* \todo: max cube texture size seems to be 512x512(x6) */ 11, /* max rect texture size is 2048x2048. */ 12, GL_FALSE ); @@ -412,6 +412,8 @@ radeonCreateContext( const __GLcontextModes *glVisual, } driInitExtensions( ctx, card_extensions, GL_TRUE ); + if (rmesa->radeonScreen->drmSupportsCubeMaps) + _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" ); if (rmesa->glCtx->Mesa_DXTn) { _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); _mesa_enable_extension( ctx, "GL_S3_s3tc" ); diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h index 09bb96861ee..d6dc9c46ed4 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_context.h @@ -264,6 +264,16 @@ struct radeon_state_atom { #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 @@ -415,6 +425,7 @@ struct radeon_hw_state { struct radeon_state_atom tcl; struct radeon_state_atom msc; struct radeon_state_atom tex[3]; + struct radeon_state_atom cube[3]; struct radeon_state_atom zbs; struct radeon_state_atom mtl; struct radeon_state_atom mat[6]; diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c index 1cf5340b9cb..37a619c2450 100644 --- a/src/mesa/drivers/dri/radeon/radeon_ioctl.c +++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c @@ -152,6 +152,7 @@ void radeonSetUpAtomList( radeonContextPtr rmesa ) for (i = 0; i < mtu; ++i) { insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tex[i]); insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.txr[i]); + insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.cube[i]); } insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.zbs); insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mtl); diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c index 1602464011a..76ad1f3cd4b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c +++ b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c @@ -542,13 +542,13 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs ) /* assume we need the 3rd coord if texgen is active for r/q OR at least 3 coords are submitted. This may not be 100% correct */ if (VB->TexCoordPtr[unit]->size >= 3) { - /* tcl_vtx and vc_frmt values are identical */ vtx |= RADEON_Q_BIT(unit); vfmt |= RADEON_Q_BIT(unit); } if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) ) vtx |= RADEON_Q_BIT(unit); - else if (VB->TexCoordPtr[unit]->size >= 3) { + else if ((VB->TexCoordPtr[unit]->size >= 3) && + ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) { GLuint swaptexmatcol = (VB->TexCoordPtr[unit]->size - 3); if (((rmesa->NeedTexMatrix >> unit) & 1) && (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1))) diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c index 57aa90321cf..24e681c8c09 100644 --- a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c +++ b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c @@ -352,7 +352,8 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs ) } if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) ) vtx |= RADEON_Q_BIT(unit); - else if (VB->TexCoordPtr[unit]->size >= 3) { + else if ((VB->TexCoordPtr[unit]->size >= 3) && + ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) { GLuint swaptexmatcol = (VB->TexCoordPtr[unit]->size - 3); if (((rmesa->NeedTexMatrix >> unit) & 1) && (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1))) diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index c79f406f68a..9a552c2c120 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -262,6 +262,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv ) fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret); return NULL; } + screen->drmSupportsCubeMaps = (sPriv->drmMinor >= 15); } } diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h index b9cbeaac335..0bf88d98416 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.h +++ b/src/mesa/drivers/dri/radeon/radeon_screen.h @@ -98,6 +98,7 @@ typedef struct { /* Configuration cache with default values for all contexts */ driOptionCache optionCache; + GLboolean drmSupportsCubeMaps; } radeonScreenRec, *radeonScreenPtr; #endif /* __RADEON_SCREEN_H__ */ diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c index a79fefee502..28033881c5e 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state.c +++ b/src/mesa/drivers/dri/radeon/radeon_state.c @@ -2098,7 +2098,6 @@ void radeonUploadTexMatrix( radeonContextPtr rmesa, } } else { - /* never used currently - no swapping needed at all presumably */ for (i = 0 ; i < 4 ; i++) { *dest++ = src[i]; *dest++ = src[i+4]; diff --git a/src/mesa/drivers/dri/radeon/radeon_state_init.c b/src/mesa/drivers/dri/radeon/radeon_state_init.c index 7e7dc0f7823..6e538a29732 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state_init.c +++ b/src/mesa/drivers/dri/radeon/radeon_state_init.c @@ -113,9 +113,14 @@ static GLboolean check_##NM( GLcontext *ctx ) \ CHECK( always, GL_TRUE ) +CHECK( never, GL_FALSE ) CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled ) CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled ) -CHECK( tex2, ctx->Texture.Unit[2]._ReallyEnabled ) +/* need this for the cubic_map on disabled unit 2 bug, maybe r100 only? */ +CHECK( tex2, ctx->Texture._EnabledUnits ) +CHECK( cube0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_CUBE_BIT)) +CHECK( cube1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_CUBE_BIT)) +CHECK( cube2, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_CUBE_BIT)) CHECK( fog, ctx->Fog.Enabled ) TCL_CHECK( tcl, GL_TRUE ) TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled ) @@ -233,6 +238,18 @@ void radeonInitState( radeonContextPtr rmesa ) ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 ); ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 ); ALLOC_STATE( tex[2], tex2, TEX_STATE_SIZE, "TEX/tex-2", 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 ); + ALLOC_STATE( cube[2], cube2, CUBE_STATE_SIZE, "CUBE/cube-2", 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( cube[2], never, CUBE_STATE_SIZE, "CUBE/cube-2", 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 ); @@ -277,6 +294,12 @@ void radeonInitState( radeonContextPtr rmesa ) rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1); rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_2); rmesa->hw.tex[2].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_2); + 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.cube[2].cmd[CUBE_CMD_0] = cmdpkt(RADEON_EMIT_PP_CUBIC_FACES_2); + rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(RADEON_EMIT_PP_CUBIC_OFFSETS_T2); 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] = @@ -488,6 +511,18 @@ void radeonInitState( radeonContextPtr rmesa ) 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_LOCAL_TEX_HEAP]; + rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_1] = + rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; + rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_2] = + rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; + rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_3] = + rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; + rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_4] = + rmesa->radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; } /* Can only add ST1 at the time of doing some multitex but can keep diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c index 7200f71ef6b..7a97cf0ce60 100644 --- a/src/mesa/drivers/dri/radeon/radeon_swtcl.c +++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c @@ -184,13 +184,18 @@ static void radeonSetVertexFormat( GLcontext *ctx ) switch (sz) { case 1: case 2: - case 3: EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_2F, radeon_cp_vc_frmts[i][0] ); break; + case 3: case 4: - EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F_XYW, - radeon_cp_vc_frmts[i][1] ); + if (ctx->Texture.Unit[i]._ReallyEnabled & (TEXTURE_CUBE_BIT) ) { + EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F, + radeon_cp_vc_frmts[i][1] ); + } else { + EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F_XYW, + radeon_cp_vc_frmts[i][1] ); + } break; default: continue; diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.c b/src/mesa/drivers/dri/radeon/radeon_tex.c index c466af868c4..46ca86bde26 100644 --- a/src/mesa/drivers/dri/radeon/radeon_tex.c +++ b/src/mesa/drivers/dri/radeon/radeon_tex.c @@ -174,7 +174,24 @@ static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf ) t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK); - if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) { + /* r100 chips can't handle mipmaps/aniso for cubemap/volume textures */ + if ( t->base.tObj->Target == GL_TEXTURE_CUBE_MAP ) { + switch ( minf ) { + case GL_NEAREST: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; + break; + case GL_LINEAR: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_LINEAR: + t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR; + break; + default: + break; + } + } + else if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) { switch ( minf ) { case GL_NEAREST: t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; @@ -774,7 +791,7 @@ static void radeonBindTexture( GLcontext *ctx, GLenum target, } assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D && - target != GL_TEXTURE_RECTANGLE_NV) || + target != GL_TEXTURE_RECTANGLE_NV && target != GL_TEXTURE_CUBE_MAP) || (texObj->DriverData != NULL) ); } diff --git a/src/mesa/drivers/dri/radeon/radeon_texmem.c b/src/mesa/drivers/dri/radeon/radeon_texmem.c index 3943afcde0b..e2766713b2f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texmem.c +++ b/src/mesa/drivers/dri/radeon/radeon_texmem.c @@ -67,7 +67,6 @@ radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) { if ( t == rmesa->state.texture.unit[i].texobj ) { rmesa->state.texture.unit[i].texobj = NULL; - rmesa->hw.tex[i].dirty = GL_FALSE; } } } @@ -226,7 +225,7 @@ static void uploadSubImage( radeonContextPtr rmesa, radeonTexObjPtr t, imageWidth = texImage->Width; imageHeight = texImage->Height; - offset = t->bufAddr; + offset = t->bufAddr + t->base.totalSize * face / 6; if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) { GLint imageX = 0; diff --git a/src/mesa/drivers/dri/radeon/radeon_texstate.c b/src/mesa/drivers/dri/radeon/radeon_texstate.c index fe5445bf626..ccf08850c2a 100644 --- a/src/mesa/drivers/dri/radeon/radeon_texstate.c +++ b/src/mesa/drivers/dri/radeon/radeon_texstate.c @@ -153,7 +153,13 @@ static void radeonSetTexImages( radeonContextPtr rmesa, /* Compute which mipmap levels we really want to send to the hardware. */ - driCalculateTextureFirstLastLevel( (driTextureObject *) t ); + if (tObj->Target != GL_TEXTURE_CUBE_MAP) + driCalculateTextureFirstLastLevel( (driTextureObject *) t ); + else { + /* r100 can't handle mipmaps for cube/3d textures, so don't waste + memory for them */ + t->base.firstLevel = t->base.lastLevel = tObj->BaseLevel; + } log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2; @@ -284,6 +290,22 @@ static void radeonSetTexImages( radeonContextPtr rmesa, */ t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK; + /* Setup remaining cube face blits, if needed */ + if (tObj->Target == GL_TEXTURE_CUBE_MAP) { + const GLuint faceSize = t->base.totalSize; + GLuint face; + /* reuse face 0 x/y/width/height - just update the offset when uploading */ + 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; + 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; @@ -291,10 +313,27 @@ static void radeonSetTexImages( radeonContextPtr rmesa, t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK | RADEON_TXFORMAT_HEIGHT_MASK | - RADEON_TXFORMAT_CUBIC_MAP_ENABLE); + RADEON_TXFORMAT_CUBIC_MAP_ENABLE | + RADEON_TXFORMAT_F5_WIDTH_MASK | + RADEON_TXFORMAT_F5_HEIGHT_MASK); 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[0][t->base.firstLevel]->Width - 1) << 0) | ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16)); @@ -816,15 +855,33 @@ static void import_tex_obj_state( radeonContextPtr rmesa, 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<recheck_texgen[unit] = GL_TRUE; } - + if (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) { + /* this seems to be a genuine (r100 only?) hw bug. Need to remove the + cubic_map bit on unit 2 when the unit is disabled, otherwise every + 2nd (2d) mipmap on unit 0 will be broken (may not be needed for other + units, better be safe than sorry though).*/ + RADEON_STATECHANGE( rmesa, tex[unit] ); + rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE; + } { GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; @@ -1050,6 +1114,48 @@ static GLboolean enable_tex_2d( GLcontext *ctx, int unit ) 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); @@ -1167,6 +1273,10 @@ static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit ) return (enable_tex_2d( ctx, unit ) && update_tex_common( ctx, unit )); } + else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) { + return (enable_tex_cube( ctx, unit ) && + update_tex_common( ctx, unit )); + } else if ( texUnit->_ReallyEnabled ) { return GL_FALSE; } -- 2.30.2