diff options
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/drivers/dri/intel/intel_buffer_objects.c | 5 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 62 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_gen_mipmap.c | 82 | 
3 files changed, 93 insertions, 56 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index 7f6fb66d52..a0225936c8 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c @@ -229,7 +229,10 @@ intel_bufferobj_get_subdata(GLcontext * ctx,     struct intel_buffer_object *intel_obj = intel_buffer_object(obj);     assert(intel_obj); -   dri_bo_get_subdata(intel_obj->buffer, offset, size, data); +   if (intel_obj->sys_buffer) +      memcpy(data, (char *)intel_obj->sys_buffer + offset, size); +   else +      dri_bo_get_subdata(intel_obj->buffer, offset, size, data);  } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index be895ca4ea..b13e3774c8 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -1705,53 +1705,6 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,  } -/** - * Compute which mipmap levels that really need to be sent to the hardware. - * This depends on the base image size, GL_TEXTURE_MIN_LOD, - * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. - */ -static void -calculate_first_last_level(struct st_texture_object *stObj) -{ -   struct gl_texture_object *tObj = &stObj->base; - -   /* These must be signed values.  MinLod and MaxLod can be negative numbers, -    * and having firstLevel and lastLevel as signed prevents the need for -    * extra sign checks. -    */ -   GLint firstLevel; -   GLint lastLevel; - -   /* Yes, this looks overly complicated, but it's all needed. -    */ -   switch (tObj->Target) { -   case GL_TEXTURE_1D: -   case GL_TEXTURE_2D: -   case GL_TEXTURE_3D: -   case GL_TEXTURE_CUBE_MAP: -      if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { -         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. -          */ -         firstLevel = lastLevel = tObj->BaseLevel; -      } -      else { -         firstLevel = 0; -         lastLevel = MIN2(tObj->MaxLevel, -                          (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2); -      } -      break; -   case GL_TEXTURE_RECTANGLE_NV: -   case GL_TEXTURE_4D_SGIS: -      firstLevel = lastLevel = 0; -      break; -   default: -      return; -   } - -   stObj->lastLevel = lastLevel; -} - -  static void  copy_image_data_to_texture(struct st_context *st,  			   struct st_texture_object *stObj, @@ -1815,13 +1768,16 @@ st_finalize_texture(GLcontext *ctx,     *needFlush = GL_FALSE; -   /* We know/require this is true by now:  -    */ -   assert(stObj->base._Complete); +   if (stObj->base._Complete) { +      /* The texture is complete and we know exactly how many mipmap levels +       * are present/needed.  This is conditional because we may be called +       * from the st_generate_mipmap() function when the texture object is +       * incomplete.  In that case, we'll have set stObj->lastLevel before +       * we get here. +       */ +      stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel; +   } -   /* What levels must the texture include at a minimum? -    */ -   calculate_first_last_level(stObj);     firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);     /* If both firstImage and stObj point to a texture which can contain diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 58f6933652..f75b2348b8 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -27,6 +27,7 @@  #include "main/imports.h" +#include "main/macros.h"  #include "main/mipmap.h"  #include "main/teximage.h"  #include "main/texformat.h" @@ -161,6 +162,43 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target,  } +/** + * Compute the expected number of mipmap levels in the texture given + * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/ + * GL_TEXTURE_MAX_LEVEL settings.  This will tell us how many mipmap + * level should be generated. + */ +static GLuint +compute_num_levels(GLcontext *ctx, +                   struct gl_texture_object *texObj, +                   GLenum target) +{ +   if (target == GL_TEXTURE_RECTANGLE_ARB) { +      return 1; +   } +   else { +      const GLuint maxLevels = texObj->MaxLevel - texObj->BaseLevel + 1; +      const struct gl_texture_image *baseImage =  +         _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel); +      GLuint size, numLevels; + +      size = MAX2(baseImage->Width2, baseImage->Height2); +      size = MAX2(size, baseImage->Depth2); + +      numLevels = 0; + +      while (size > 0) { +         numLevels++; +         size >>= 1; +      } + +      numLevels = MIN2(numLevels, maxLevels); + +      return numLevels; +   } +} + +  void  st_generate_mipmap(GLcontext *ctx, GLenum target,                     struct gl_texture_object *texObj) @@ -174,9 +212,49 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,     if (!pt)        return; -   lastLevel = pt->last_level; +   /* find expected last mipmap level */ +   lastLevel = compute_num_levels(ctx, texObj, target) - 1; + +   if (pt->last_level < lastLevel) { +      /* The current gallium texture doesn't have space for all the +       * mipmap levels we need to generate.  So allocate a new texture. +       */ +      struct st_texture_object *stObj = st_texture_object(texObj); +      struct pipe_texture *oldTex = stObj->pt; +      GLboolean needFlush; + +      /* create new texture with space for more levels */ +      stObj->pt = st_texture_create(st, +                                    oldTex->target, +                                    oldTex->format, +                                    lastLevel, +                                    oldTex->width[0], +                                    oldTex->height[0], +                                    oldTex->depth[0], +                                    oldTex->tex_usage); + +      /* The texture isn't in a "complete" state yet so set the expected +       * lastLevel here, since it won't get done in st_finalize_texture(). +       */ +      stObj->lastLevel = lastLevel; + +      /* This will copy the old texture's base image into the new texture +       * which we just allocated. +       */ +      st_finalize_texture(ctx, st->pipe, texObj, &needFlush); + +      /* release the old tex (will likely be freed too) */ +      pipe_texture_reference(&oldTex, NULL); + +      pt = stObj->pt; +   } + +   assert(lastLevel <= pt->last_level); -   if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) { +   /* Recall that the Mesa BaseLevel image is stored in the gallium +    * texture's level[0] position.  So pass baseLevel=0 here. +    */ +   if (!st_render_mipmap(st, target, pt, 0, lastLevel)) {        fallback_generate_mipmap(ctx, target, texObj);     }  | 
