diff options
| -rw-r--r-- | src/mesa/state_tracker/st_atom_sampler.c | 9 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_atom_texture.c | 3 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_fbo.c | 8 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 162 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_gen_mipmap.c | 6 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_texture.c | 3 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_texture.h | 12 | 
7 files changed, 122 insertions, 81 deletions
| diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index a8262a5e1a..92fe72d4df 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -194,9 +194,12 @@ update_samplers(struct st_context *st)              sampler->normalized_coords = 1;           sampler->lod_bias = st->ctx->Texture.Unit[su].LodBias; -         sampler->min_lod = MAX2(0.0f, texobj->MinLod); -         sampler->max_lod = MIN2(texobj->MaxLevel - texobj->BaseLevel, -                                 texobj->MaxLod); + +         sampler->min_lod = texobj->BaseLevel + texobj->MinLod; +         if (sampler->min_lod < texobj->BaseLevel) +            sampler->min_lod = texobj->BaseLevel; + +         sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel, texobj->MaxLod);           if (sampler->max_lod < sampler->min_lod) {              /* The GL spec doesn't seem to specify what to do in this case.               * Swap the values. diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index f4294ac1e6..2575adda8f 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -138,7 +138,6 @@ finalize_textures(struct st_context *st)           const GLuint texUnit = fprog->Base.SamplerUnits[su];           struct gl_texture_object *texObj              = st->ctx->Texture.Unit[texUnit]._Current; -         struct st_texture_object *stObj = st_texture_object(texObj);           if (texObj) {              GLboolean flush, retval; @@ -149,8 +148,6 @@ finalize_textures(struct st_context *st)                 st->missing_textures = GL_TRUE;                 continue;              } - -            stObj->teximage_realloc = TRUE;           }        }     } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index e5c956d561..c02121fbd1 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -321,15 +321,13 @@ st_render_texture(GLcontext *ctx,     struct pipe_resource *pt = st_get_texobj_resource(att->Texture);     struct st_texture_object *stObj;     const struct gl_texture_image *texImage; -   GLint pt_level;     /* When would this fail?  Perhaps assert? */     if (!pt)         return; -   /* The first gallium texture level = Mesa BaseLevel */ -   pt_level = MAX2(0, (GLint) att->TextureLevel - att->Texture->BaseLevel); -   texImage = att->Texture->Image[att->CubeMapFace][pt_level]; +   /* get pointer to texture image we're rendeing to */ +   texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];     /* create new renderbuffer which wraps the texture image */     rb = st_new_renderbuffer(ctx, 0); @@ -350,7 +348,7 @@ st_render_texture(GLcontext *ctx,     /* point renderbuffer at texobject */     strb->rtt = stObj; -   strb->rtt_level = pt_level; +   strb->rtt_level = att->TextureLevel;     strb->rtt_face = att->CubeMapFace;     strb->rtt_slice = att->Zoffset; diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 3457214ca4..7e2e533881 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -231,70 +231,86 @@ default_bindings(struct st_context *st, enum pipe_format format)  } +/** Return number of image dimensions (1, 2 or 3) for a texture target. */ +static GLuint +get_texture_dims(GLenum target) +{ +   switch (target) { +   case GL_TEXTURE_1D: +   case GL_TEXTURE_1D_ARRAY_EXT: +      return 1; +   case GL_TEXTURE_2D: +   case GL_TEXTURE_CUBE_MAP_ARB: +   case GL_TEXTURE_RECTANGLE_NV: +   case GL_TEXTURE_2D_ARRAY_EXT: +      return 2; +   case GL_TEXTURE_3D: +      return 3; +   default: +      assert(0 && "invalid texture target in get_texture_dims()"); +      return 1; +   } +} + +  /** - * Allocate a pipe_resource object for the given st_texture_object using - * the given st_texture_image to guess the mipmap size/levels. + * Try to allocate a pipe_resource object for the given st_texture_object.   * - * [comments...] - * Otherwise, store it in memory if (Border != 0) or (any dimension == - * 1). - *     - * Otherwise, if max_level >= level >= min_level, create texture with - * space for images from min_level down to max_level. + * We use the given st_texture_image as a clue to determine the size of the + * mipmap image at level=0.   * - * Otherwise, create texture with space for images from (level 0)..(1x1). - * Consider pruning this texture at a validation if the saving is worth it.   */  static void  guess_and_alloc_texture(struct st_context *st,  			struct st_texture_object *stObj,  			const struct st_texture_image *stImage)  { -   GLuint firstLevel; -   GLuint lastLevel; -   GLuint width = stImage->base.Width2;  /* size w/out border */ -   GLuint height = stImage->base.Height2; -   GLuint depth = stImage->base.Depth2; -   GLuint i, bindings; +   const GLuint dims = get_texture_dims(stObj->base.Target); +   GLuint level, lastLevel, width, height, depth; +   GLuint bindings;     enum pipe_format fmt;     DBG("%s\n", __FUNCTION__);     assert(!stObj->pt); -   if (stObj->pt && -       (GLint) stImage->level > stObj->base.BaseLevel && -       (stImage->base.Width == 1 || -        (stObj->base.Target != GL_TEXTURE_1D && -         stImage->base.Height == 1) || -        (stObj->base.Target == GL_TEXTURE_3D && -         stImage->base.Depth == 1))) -      return; +   level = stImage->level; +   width = stImage->base.Width2;  /* size w/out border */ +   height = stImage->base.Height2; +   depth = stImage->base.Depth2; -   /* If this image disrespects BaseLevel, allocate from level zero. -    * Usually BaseLevel == 0, so it's unlikely to happen. -    */ -   if ((GLint) stImage->level < stObj->base.BaseLevel) -      firstLevel = 0; -   else -      firstLevel = stObj->base.BaseLevel; +   assert(width > 0); +   assert(height > 0); +   assert(depth > 0); - -   /* Figure out image dimensions at start level.  +   /* Depending on the image's size, we can't always make a guess here.      */ -   for (i = stImage->level; i > firstLevel; i--) { +   if (level > 0) { +      if ( (dims >= 1 && width == 1) || +           (dims >= 2 && height == 1) || +           (dims >= 3 && depth == 1) ) { +         /* we can't determine the image size at level=0 */ +         stObj->width0 = stObj->height0 = stObj->depth0 = 0; +         return; +      } +   } + +   /* grow the image size until we hit level = 0 */ +   while (level > 0) {        if (width != 1)           width <<= 1;        if (height != 1)           height <<= 1;        if (depth != 1)           depth <<= 1; -   } +      level--; +   }       -   if (width == 0 || height == 0 || depth == 0) { -      /* no texture needed */ -      return; -   } +   assert(level == 0); + +   /* At this point, (width x height x depth) is the expected size of +    * the level=0 mipmap image. +    */     /* Guess a reasonable value for lastLevel.  This is probably going      * to be wrong fairly often and might mean that we have to look at @@ -306,18 +322,23 @@ guess_and_alloc_texture(struct st_context *st,          stImage->base._BaseFormat == GL_DEPTH_COMPONENT ||          stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) &&         !stObj->base.GenerateMipmap && -       stImage->level == firstLevel) { +       stImage->level == 0) {        /* only alloc space for a single mipmap level */ -      lastLevel = firstLevel; +      lastLevel = 0;     }     else {        /* alloc space for a full mipmap */        GLuint l2width = util_logbase2(width);        GLuint l2height = util_logbase2(height);        GLuint l2depth = util_logbase2(depth); -      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); +      lastLevel = MAX2(MAX2(l2width, l2height), l2depth);     } +   /* Save the level=0 dimensions */ +   stObj->width0 = width; +   stObj->height0 = height; +   stObj->depth0 = depth; +     fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat);     bindings = default_bindings(st, fmt); @@ -581,15 +602,13 @@ st_TexImage(GLcontext * ctx,      * mipmap.  If so, free the old mipmap.      */     if (stObj->pt) { -      if (stObj->teximage_realloc || -          level > (GLint) stObj->pt->last_level || +      if (level > (GLint) stObj->pt->last_level ||            !st_texture_match_image(stObj->pt, &stImage->base,                                    stImage->face, stImage->level)) {           DBG("release it\n");           pipe_resource_reference(&stObj->pt, NULL);           assert(!stObj->pt);           pipe_sampler_view_reference(&stObj->sampler_view, NULL); -         stObj->teximage_realloc = FALSE;        }     } @@ -1757,12 +1776,26 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,  } +/** + * Copy image data from stImage into the texture object 'stObj' at level + * 'dstLevel'. + */  static void  copy_image_data_to_texture(struct st_context *st,  			   struct st_texture_object *stObj,                             GLuint dstLevel,  			   struct st_texture_image *stImage)  { +   /* debug checks */ +   { +      const struct gl_texture_image *dstImage = +         stObj->base.Image[stImage->face][stImage->level]; +      assert(dstImage); +      assert(dstImage->Width == stImage->base.Width); +      assert(dstImage->Height == stImage->base.Height); +      assert(dstImage->Depth == stImage->base.Depth); +   } +     if (stImage->pt) {        /* Copy potentially with the blitter:         */ @@ -1811,8 +1844,9 @@ st_finalize_texture(GLcontext *ctx,     struct st_context *st = st_context(ctx);     struct st_texture_object *stObj = st_texture_object(tObj);     const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; -   GLuint blockSize, face; +   GLuint face;     struct st_texture_image *firstImage; +   enum pipe_format firstImageFormat;     *needFlush = GL_FALSE; @@ -1827,10 +1861,11 @@ st_finalize_texture(GLcontext *ctx,            stObj->base.MinFilter == GL_NEAREST)           stObj->lastLevel = stObj->base.BaseLevel;        else -         stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel; +         stObj->lastLevel = stObj->base._MaxLevel;     }     firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); +   assert(firstImage);     /* If both firstImage and stObj point to a texture which can contain      * all active images, favour firstImage.  Note that because of the @@ -1844,22 +1879,23 @@ st_finalize_texture(GLcontext *ctx,        pipe_sampler_view_reference(&stObj->sampler_view, NULL);     } -   /* bytes per pixel block (blocks are usually 1x1) */ -   blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat); +   /* Find gallium format for the Mesa texture */ +   firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);     /* If we already have a gallium texture, check that it matches the texture      * object's format, target, size, num_levels, etc.      */     if (stObj->pt) { -      const enum pipe_format fmt = -         st_mesa_format_to_pipe_format(firstImage->base.TexFormat);        if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || -          stObj->pt->format != fmt || -          stObj->pt->last_level < stObj->lastLevel || -          stObj->pt->width0 != firstImage->base.Width2 || -          stObj->pt->height0 != firstImage->base.Height2 || -          stObj->pt->depth0 != firstImage->base.Depth2) +          stObj->pt->format != firstImageFormat || +          stObj->pt->last_level != stObj->lastLevel || +          stObj->pt->width0 != stObj->width0 || +          stObj->pt->height0 != stObj->height0 || +          stObj->pt->depth0 != stObj->depth0)        { +         /* The gallium texture does not match the Mesa texture so delete the +          * gallium texture now.  We'll make a new one below. +          */           pipe_resource_reference(&stObj->pt, NULL);           pipe_sampler_view_reference(&stObj->sampler_view, NULL);           st->dirty.st |= ST_NEW_FRAMEBUFFER; @@ -1869,17 +1905,15 @@ st_finalize_texture(GLcontext *ctx,     /* May need to create a new gallium texture:      */     if (!stObj->pt) { -      const enum pipe_format fmt = -         st_mesa_format_to_pipe_format(firstImage->base.TexFormat); -      GLuint bindings = default_bindings(st, fmt); +      GLuint bindings = default_bindings(st, firstImageFormat);        stObj->pt = st_texture_create(st,                                      gl_target_to_pipe(stObj->base.Target), -                                    fmt, +                                    firstImageFormat,                                      stObj->lastLevel, -                                    firstImage->base.Width2, -                                    firstImage->base.Height2, -                                    firstImage->base.Depth2, +                                    stObj->width0, +                                    stObj->height0, +                                    stObj->depth0,                                      bindings);        if (!stObj->pt) { @@ -1894,7 +1928,7 @@ st_finalize_texture(GLcontext *ctx,        GLuint level;        for (level = 0; level <= stObj->lastLevel; level++) {           struct st_texture_image *stImage = -            st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]); +            st_texture_image(stObj->base.Image[face][level]);           /* Need to import images in main memory or held in other textures.            */ diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index b8b75c7de6..a015c4bb58 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -342,10 +342,10 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,     assert(lastLevel <= pt->last_level); -   /* Recall that the Mesa BaseLevel image is stored in the gallium -    * texture's level[0] position.  So pass baseLevel=0 here. +   /* Try to generate the mipmap by rendering/texturing.  If that fails, +    * use the software fallback.      */ -   if (!st_render_mipmap(st, target, stObj, 0, lastLevel)) { +   if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {        fallback_generate_mipmap(ctx, target, texObj);     } diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 1b52e77b7d..722f60e425 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -269,6 +269,9 @@ st_texture_image_copy(struct pipe_context *pipe,     struct pipe_surface *dst_surface;     GLuint i; +   assert(src->width0 == dst->width0); +   assert(src->height0 == dst->height0); +     for (i = 0; i < depth; i++) {        GLuint srcLevel; diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index d0298817de..447f091db1 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -38,6 +38,9 @@  struct pipe_resource; +/** + * Subclass of gl_texure_image. + */  struct st_texture_image  {     struct gl_texture_image base; @@ -57,7 +60,9 @@ struct st_texture_image  }; - +/** + * Subclass of gl_texure_object. + */  struct st_texture_object  {     struct gl_texture_object base;       /* The "parent" object */ @@ -66,6 +71,9 @@ struct st_texture_object      */     GLuint lastLevel; +   /** The size of the level=0 mipmap image */ +   GLuint width0, height0, depth0; +     /* On validation any active images held in main memory or in other      * textures will be copied to this texture and the old storage freed.      */ @@ -76,8 +84,6 @@ struct st_texture_object      */     struct pipe_sampler_view *sampler_view; -   GLboolean teximage_realloc; -     /* True if there is/was a surface bound to this texture object.  It helps      * track whether the texture object is surface based or not.      */ | 
