Index: radeon_context.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_context.c,v retrieving revision 1.45 diff -u -r1.45 radeon_context.c --- radeon_context.c 17 Oct 2005 00:54:12 -0000 1.45 +++ radeon_context.c 18 Oct 2005 17:53:49 -0000 @@ -342,7 +342,7 @@ & ctx->Const, 4, 11, /* max 2D texture size is 2048x2048 */ - 0, /* 3D textures unsupported. */ + 8, /* 256^3 */ 9, /* \todo: max cube texture size seems to be 512x512(x6) */ 11, /* max rect texture size is 2048x2048. */ 12, Index: radeon_context.h =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_context.h,v retrieving revision 1.27 diff -u -r1.27 radeon_context.h --- radeon_context.h 15 Oct 2005 23:45:54 -0000 1.27 +++ radeon_context.h 18 Oct 2005 17:53:50 -0000 @@ -773,7 +773,8 @@ GLuint NeedTexMatrix; GLuint TexMatColSwap; GLmatrix tmpmat[RADEON_MAX_TEXTURE_UNITS]; - GLuint last_ReallyEnabled; + GLuint tex3dunit; + GLboolean needunit2restore; /* VBI */ Index: radeon_maos_arrays.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c,v retrieving revision 1.13 diff -u -r1.13 radeon_maos_arrays.c --- radeon_maos_arrays.c 18 Oct 2005 13:09:53 -0000 1.13 +++ radeon_maos_arrays.c 18 Oct 2005 17:53:50 -0000 @@ -584,7 +584,7 @@ vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2)); - + for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (inputs & VERT_BIT_TEX(unit)) { if (!rmesa->tcl.tex[unit].buf) @@ -605,7 +605,8 @@ if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) ) vtx |= RADEON_Q_BIT(unit); else if ((VB->TexCoordPtr[unit]->size >= 3) && - ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) { + ((ctx->Texture.Unit[unit]._ReallyEnabled & + (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0)) { GLuint swaptexmatcol = (VB->TexCoordPtr[unit]->size - 3); if (((rmesa->NeedTexMatrix >> unit) & 1) && (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1))) @@ -646,7 +647,7 @@ if (newinputs & VERT_BIT_COLOR1) radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ ); - + if (newinputs & VERT_BIT_FOG) radeonReleaseDmaRegion( rmesa, &rmesa->tcl.fog, __FUNCTION__ ); Index: radeon_maos_verts.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_maos_verts.c,v retrieving revision 1.15 diff -u -r1.15 radeon_maos_verts.c --- radeon_maos_verts.c 17 Oct 2005 00:54:12 -0000 1.15 +++ radeon_maos_verts.c 18 Oct 2005 17:53:50 -0000 @@ -356,7 +356,8 @@ if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) ) vtx |= RADEON_Q_BIT(unit); else if ((VB->TexCoordPtr[unit]->size >= 3) && - ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) { + ((ctx->Texture.Unit[unit]._ReallyEnabled & + (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0)) { GLuint swaptexmatcol = (VB->TexCoordPtr[unit]->size - 3); if (((rmesa->NeedTexMatrix >> unit) & 1) && (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1))) Index: radeon_state_init.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c,v retrieving revision 1.18 diff -u -r1.18 radeon_state_init.c --- radeon_state_init.c 17 Oct 2005 00:54:12 -0000 1.18 +++ radeon_state_init.c 18 Oct 2005 17:53:51 -0000 @@ -333,7 +333,8 @@ cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 ); } - rmesa->last_ReallyEnabled = -1; + rmesa->tex3dunit = 0; + rmesa->needunit2restore = GL_FALSE; /* Initial Harware state: */ Index: radeon_swtcl.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_swtcl.c,v retrieving revision 1.25 diff -u -r1.25 radeon_swtcl.c --- radeon_swtcl.c 15 Oct 2005 23:45:54 -0000 1.25 +++ radeon_swtcl.c 18 Oct 2005 17:53:51 -0000 @@ -189,7 +189,8 @@ break; case 3: case 4: - if (ctx->Texture.Unit[i]._ReallyEnabled & (TEXTURE_CUBE_BIT) ) { + if (ctx->Texture.Unit[i]._ReallyEnabled & + (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT) ) { EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F, radeon_cp_vc_frmts[i][1] ); } else { Index: radeon_tex.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_tex.c,v retrieving revision 1.16 diff -u -r1.16 radeon_tex.c --- radeon_tex.c 15 Oct 2005 23:45:54 -0000 1.16 +++ radeon_tex.c 18 Oct 2005 17:53:52 -0000 @@ -175,7 +175,8 @@ t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK); /* r100 chips can't handle mipmaps/aniso for cubemap/volume textures */ - if ( t->base.tObj->Target == GL_TEXTURE_CUBE_MAP ) { + if ( (t->base.tObj->Target == GL_TEXTURE_CUBE_MAP) || + (t->base.tObj->Target == GL_TEXTURE_3D) ) { switch ( minf ) { case GL_NEAREST: case GL_NEAREST_MIPMAP_NEAREST: @@ -577,6 +578,69 @@ t->dirty_images[face] |= (1 << level); } +static void radeonTexImage3D( 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; + + if ( t ) { + driSwapOutTextureObject( t ); + } + else { + t = (driTextureObject *) radeonAllocTexObj( texObj ); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); + return; + } + } + + /* Note, this will call radeonChooseTextureFormat. */ + _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 +radeonTexSubImage3D( 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 */ + if ( t ) { + driSwapOutTextureObject( t ); + } + else { + t = (driTextureObject *) radeonAllocTexObj( texObj ); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); + return; + } + texObj->DriverData = 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 radeonCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, @@ -791,8 +855,8 @@ } assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D && - target != GL_TEXTURE_RECTANGLE_NV && target != GL_TEXTURE_CUBE_MAP) || - (texObj->DriverData != NULL) ); + target != GL_TEXTURE_3D && target != GL_TEXTURE_RECTANGLE_NV && + target != GL_TEXTURE_CUBE_MAP) || (texObj->DriverData != NULL) ); } @@ -866,6 +930,8 @@ functions->TexImage2D = radeonTexImage2D; functions->TexSubImage1D = radeonTexSubImage1D; functions->TexSubImage2D = radeonTexSubImage2D; + functions->TexImage3D = radeonTexImage3D; + functions->TexSubImage3D = radeonTexSubImage3D; functions->NewTextureObject = radeonNewTextureObject; functions->BindTexture = radeonBindTexture; Index: radeon_texstate.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/radeon/radeon_texstate.c,v retrieving revision 1.22 diff -u -r1.22 radeon_texstate.c --- radeon_texstate.c 15 Oct 2005 23:45:54 -0000 1.22 +++ radeon_texstate.c 18 Oct 2005 17:53:52 -0000 @@ -153,7 +153,7 @@ /* Compute which mipmap levels we really want to send to the hardware. */ - if (tObj->Target != GL_TEXTURE_CUBE_MAP) + if ((tObj->Target != GL_TEXTURE_CUBE_MAP) && (tObj->Target != GL_TEXTURE_3D)) driCalculateTextureFirstLastLevel( (driTextureObject *) t ); else { /* r100 can't handle mipmaps for cube/3d textures, so don't waste @@ -265,7 +265,7 @@ t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES; t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES; t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES); - t->image[0][i].height = size / t->image[0][i].width; + t->image[0][i].height = size / t->image[0][i].width; } #if 0 @@ -862,7 +862,7 @@ ASSERT(texobj->totalSize % 6 == 0); cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; - /* dont know if this setup conforms to OpenGL.. + /* 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 */ @@ -1147,7 +1147,7 @@ radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, face ); } } - + if ( !t->base.memBlock ) { /* texmem alloc failed, use s/w fallback */ return GL_FALSE; @@ -1156,6 +1156,41 @@ return GL_TRUE; } +static GLboolean enable_tex_3d( 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; + + /* Need to load the 3d images associated with this unit. + */ + if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) { + t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2; + t->base.dirty_images[0] = ~0; + } + + ASSERT(tObj->Target == GL_TEXTURE_3D); + + /* R100 & R200 do not support mipmaps for 3D textures. + * - we'll just ignore the mips, seems better than fallback. + * can have only one 3d map, either on unit 0 or maybe (unconfirmed) on unit 1 + * setup of unit 2 is done later */ + if ((unit == 2) || ((unit == 1) && rmesa->tex3dunit)) + return GL_FALSE; + rmesa->tex3dunit = unit + 1; + + if ( t->base.dirty_images[0] ) { + RADEON_FIREVERTICES( rmesa ); + radeonSetTexImages( rmesa, tObj ); + radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 ); + if ( !t->base.memBlock ) + return GL_FALSE; + } + + return GL_TRUE; +} + static GLboolean enable_tex_rect( GLcontext *ctx, int unit ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); @@ -1233,6 +1268,11 @@ } if (t->dirty_state & (1<needunit2restore) { + ctx->Driver.TexParameter( ctx, 0, tObj, GL_TEXTURE_BORDER_COLOR, NULL ); + ctx->Driver.TexEnv( ctx, 0, GL_TEXTURE_ENV_COLOR, NULL ); + rmesa->needunit2restore = 0; + } import_tex_obj_state( rmesa, unit, t ); /* may need to update texture matrix (for texrect adjustments) */ rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; @@ -1259,7 +1299,62 @@ return !t->border_fallback; } +static GLboolean radeon3dTexFinishSetup( GLcontext *ctx, GLuint 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; + struct gl_texture_unit *texUnit2 = &ctx->Texture.Unit[2]; + if (texUnit2->_ReallyEnabled) + return GL_FALSE; + + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_TEX_3D_ENABLE_0 << unit; + + /* Update state if this is a different texture object to last + * time. + */ + if ( rmesa->state.texture.unit[2].texobj != t ) { + if ( rmesa->state.texture.unit[2].texobj != NULL ) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + rmesa->state.texture.unit[2].texobj->base.bound &= + ~(1UL << 2); + } + + rmesa->state.texture.unit[2].texobj = t; + t->base.bound |= (1UL << 2); + t->dirty_state |= 1<<2; + } + + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_TEX_BLEND_2_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_TEX_2_ENABLE; + + if (t->dirty_state & ((1 << 2) | (1 << unit))) { + import_tex_obj_state( rmesa, 2, t ); + /* need to put log2depth into txformat width field */ + rmesa->hw.tex[2].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_WIDTH_MASK; + rmesa->hw.tex[2].cmd[TEX_PP_TXFORMAT] |= + tObj->Image[0][t->base.firstLevel]->DepthLog2 << RADEON_TXFORMAT_WIDTH_SHIFT; + } + + if ( (rmesa->hw.tex[2].cmd[TEX_PP_TFACTOR] + != rmesa->hw.tex[0].cmd[TEX_PP_TFACTOR]) || + (rmesa->hw.tex[2].cmd[TEX_PP_BORDER_COLOR] + != rmesa->hw.tex[0].cmd[TEX_PP_BORDER_COLOR]) ) { + RADEON_STATECHANGE( rmesa, tex[2] ); + /* dunno why the tfactor would be needed... */ + rmesa->hw.tex[2].cmd[TEX_PP_TFACTOR] = rmesa->hw.tex[0].cmd[TEX_PP_TFACTOR]; + rmesa->hw.tex[2].cmd[TEX_PP_BORDER_COLOR] = + rmesa->hw.tex[0].cmd[TEX_PP_BORDER_COLOR]; + rmesa->needunit2restore = GL_TRUE; + } + return GL_TRUE; +} static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit ) { @@ -1273,6 +1368,10 @@ return (enable_tex_2d( ctx, unit ) && update_tex_common( ctx, unit )); } + else if ( texUnit->_ReallyEnabled & (TEXTURE_3D_BIT) ) { + return (enable_tex_3d( 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 )); @@ -1290,10 +1389,19 @@ { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLboolean ok; + rmesa->tex3dunit = 0; - ok = (radeonUpdateTextureUnit( ctx, 0 ) && - radeonUpdateTextureUnit( ctx, 1 ) && - radeonUpdateTextureUnit( ctx, 2 )); + RADEON_STATECHANGE ( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= + ~(RADEON_TEX_3D_ENABLE_0|RADEON_TEX_3D_ENABLE_1); + + ok = radeonUpdateTextureUnit( ctx, 0 ) && + radeonUpdateTextureUnit( ctx, 1 ); + if (ok) { + if (rmesa->tex3dunit == 0) + ok = radeonUpdateTextureUnit( ctx, 2 ); + else ok = radeon3dTexFinishSetup( ctx, rmesa->tex3dunit - 1 ); + } FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );