added support for textures bigger than HW can support (SW rescaling)
authorDaniel Borca <dborca@users.sourceforge.net>
Tue, 13 Jan 2004 08:47:44 +0000 (08:47 +0000)
committerDaniel Borca <dborca@users.sourceforge.net>
Tue, 13 Jan 2004 08:47:44 +0000 (08:47 +0000)
src/mesa/drivers/glide/fxdd.c
src/mesa/drivers/glide/fxdrv.h
src/mesa/drivers/glide/fxsetup.c

index 0d0de38e02f0e3c4c2d17333803ca36d85ef68b9..d7d347abae62c520d43007432b637578cccdb87c 100644 (file)
@@ -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 */
index 27a721ae60feb9be81d3103fd1d203989cd63228..e6320441d0c3450864943f8caada43e4e64b68b7 100644 (file)
@@ -462,6 +462,7 @@ struct tfxMesaContext
    GLfloat fogStart, fogEnd;
    GrFog_t *fogTable;
    GLint textureAlign;
+   GLint textureMaxLod;
 
    /* Vertex building and storage:
     */
index c00bd83f786fc284870d589bde8c90416ba6173b..61ceb6e7ac038414aae351e91a429377a465cfb2 100644 (file)
@@ -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),