From 09a4fcb59272afdf460032916b008e610d2d7eca Mon Sep 17 00:00:00 2001 From: Daniel Borca Date: Tue, 13 Jan 2004 08:47:44 +0000 Subject: added support for textures bigger than HW can support (SW rescaling) --- src/mesa/drivers/glide/fxdd.c | 15 +++++++- src/mesa/drivers/glide/fxdrv.h | 1 + src/mesa/drivers/glide/fxsetup.c | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) (limited to 'src/mesa/drivers/glide') diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c index 0d0de38e02..d7d347abae 100644 --- a/src/mesa/drivers/glide/fxdd.c +++ b/src/mesa/drivers/glide/fxdd.c @@ -797,6 +797,7 @@ fxDDReadPixels565 (GLcontext * ctx, GrLfbInfo_t info; BEGIN_BOARD_LOCK(); + info.size = sizeof(info); if (grLfbLock(GR_LFB_READ_ONLY, fxMesa->currentFB, GR_LFBWRITEMODE_ANY, @@ -909,6 +910,7 @@ fxDDReadPixels555 (GLcontext * ctx, GrLfbInfo_t info; BEGIN_BOARD_LOCK(); + info.size = sizeof(info); if (grLfbLock(GR_LFB_READ_ONLY, fxMesa->currentFB, GR_LFBWRITEMODE_ANY, @@ -1021,6 +1023,7 @@ fxDDReadPixels8888 (GLcontext * ctx, GrLfbInfo_t info; BEGIN_BOARD_LOCK(); + info.size = sizeof(info); if (grLfbLock(GR_LFB_READ_ONLY, fxMesa->currentFB, GR_LFBWRITEMODE_ANY, @@ -1338,17 +1341,25 @@ fxDDInitFxMesaContext(fxMesaContext fxMesa) fxMesa->textureAlign = FX_grGetInteger(GR_TEXTURE_ALIGN); /* [koolsmoky] */ { + char *env; int textureLevels = 0; int textureSize = FX_grGetInteger(GR_MAX_TEXTURE_SIZE); do { textureLevels++; } while ((textureSize >>= 0x1) & 0x7ff); + fxMesa->textureMaxLod = textureLevels - 1; ctx->Const.MaxTextureLevels = textureLevels; + if ((env = getenv("MESA_FX_MAXLOD")) != NULL) { + int maxLevels = atoi(env) + 1; + if ((maxLevels <= MAX_TEXTURE_LEVELS) && (maxLevels > textureLevels)) { + ctx->Const.MaxTextureLevels = maxLevels; + } + } } - ctx->Const.MaxTextureCoordUnits = fxMesa->haveTwoTMUs ? 2 : 1; + ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureImageUnits = fxMesa->haveTwoTMUs ? 2 : 1; ctx->Const.MaxTextureUnits = MAX2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits); - + fxMesa->new_state = _NEW_ALL; if (!fxMesa->haveHwStencil) { /* don't touch stencil if there is none */ diff --git a/src/mesa/drivers/glide/fxdrv.h b/src/mesa/drivers/glide/fxdrv.h index 27a721ae60..e6320441d0 100644 --- a/src/mesa/drivers/glide/fxdrv.h +++ b/src/mesa/drivers/glide/fxdrv.h @@ -462,6 +462,7 @@ struct tfxMesaContext GLfloat fogStart, fogEnd; GrFog_t *fogTable; GLint textureAlign; + GLint textureMaxLod; /* Vertex building and storage: */ diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c index c00bd83f78..61ceb6e7ac 100644 --- a/src/mesa/drivers/glide/fxsetup.c +++ b/src/mesa/drivers/glide/fxsetup.c @@ -65,6 +65,88 @@ fxTexValidate(GLcontext * ctx, struct gl_texture_object *tObj) minl = ti->minLevel = tObj->BaseLevel; maxl = ti->maxLevel = MIN2(tObj->MaxLevel, tObj->Image[0]->MaxLog2); +#if 1||FX_RESCALE_BIG_TEXURES +{ + extern void _mesa_rescale_teximage2d( GLuint bytesPerPixel, + GLuint dstRowStride, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage ); + fxMesaContext fxMesa = FX_CONTEXT(ctx); + if (maxl - minl > fxMesa->textureMaxLod) { + /* [dBorca] + * Ooooooook! Here's a(nother) long story. + * We get here because we need to handle a texture larger + * than hardware can support. Two cases: + * 1) we have mipmaps. Then we just push up to the first supported + * LOD. A possible drawback is that Mesa will ignore the skipped + * LODs on further texture handling (including memory freeing). + * Will this interfere with GL_TEXTURE_[MIN|BASE]_LEVEL? How? + * 2) we don't have mipmaps. We need to rescale texture; two ways: + * a) create a new LOD and push up ti->minLevel and tObj->BaseLevel + * but this means we need to rescale on both axes, which + * yield unnecessary ugly texture. Also, same issues as 1) + * b) rescale the biggest LOD in place and go two ways: + * - update texImage->Width and texImage->Height, then + * decrease maxLevel, so we won't rescale again on the + * next validation. Changing texImage-> parameters is + * not quite legal here (see convolution), but... + * - leaving texImage-> parameters alone, while rescaling + * texture and decreasing maxLevel makes Mesa puke. Also + * this approach requires that mml->[wh]Scale go below 1, + * otherwise bad ju-ju will be in our future (see fetch_texel) + * Will this interfere with GL_TEXTURE_MAX_LEVEL? How? + * The above approach is somehow dumb! we might have rescaled + * once in TexImage2D to accomodate aspect ratio, and now we + * are rescaling again. The thing is, in TexImage2D we don't + * know whether we'll hit 1) or 2) by the time of validation. + * NB: we could handle mml->[wh]Scale nicely, using (biased) shifts. + * + * Which brings me to another issue. How can we handle NPOT textures? + * - rescaling NPOT to the next bigger POT (mml->[wh]Scale can't shift) + * - upping the max LOD to the next power-of-two, in fxTexGetInfo; then + * choosing non-power-of-two values for ti->[st]Scale... Anyhow, we + * still need to align mipmaps correctly in texture memory! + */ + if ((tObj->MinFilter == GL_NEAREST) || (tObj->MinFilter == GL_LINEAR)) { + /* no mipmaps! need to rescale */ + struct gl_texture_image *texImage = tObj->Image[minl]; + tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); + GLint texelBytes = texImage->TexFormat->TexelBytes; + GLvoid *texImage_Data = texImage->Data; + GLint _w = MIN2(mml->width, 1 << fxMesa->textureMaxLod); + GLint _h = MIN2(mml->height, 1 << fxMesa->textureMaxLod); + if (TDFX_DEBUG & VERBOSE_TEXTURE) { + fprintf(stderr, "fxTexValidate: rescaling %d x %d -> %d x %d\n", + mml->width, mml->height, + _w, _h); + } + fxTexGetInfo(_w, _h, NULL, NULL, NULL, NULL, + &(mml->wScale), &(mml->hScale)); + texImage->Width = _w / mml->wScale; + texImage->Height = _h / mml->hScale; + texImage->Data = MESA_PBUFFER_ALLOC(_w * _h * texelBytes); + _mesa_rescale_teximage2d(texelBytes, + _w * texelBytes, /* dst stride */ + mml->width, mml->height, /* src */ + _w, _h, /* dst */ + texImage_Data /*src*/, texImage->Data /*dst*/ ); + MESA_PBUFFER_FREE(texImage_Data); + mml->width = _w; + mml->height = _h; + maxl = ti->maxLevel = tObj->Image[0]->MaxLog2 = minl + fxMesa->textureMaxLod; + } else { + /* skip a certain number of LODs */ + minl += maxl - fxMesa->textureMaxLod; + if (TDFX_DEBUG & VERBOSE_TEXTURE) { + fprintf(stderr, "fxTexValidate: skipping %d LODs\n", minl - ti->minLevel); + } + ti->minLevel = tObj->BaseLevel = minl; + } + } +} +#endif + fxTexGetInfo(tObj->Image[minl]->Width, tObj->Image[minl]->Height, &(FX_largeLodLog2(ti->info)), &(FX_aspectRatioLog2(ti->info)), &(ti->sScale), &(ti->tScale), -- cgit v1.2.3