summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-09-28 10:02:20 -0600
committerBrian Paul <brianp@vmware.com>2009-09-28 10:02:20 -0600
commit8fda97afb8b7a03415dbca6d83691d2d6461126c (patch)
treed78b55385eed2b37baa4dcc8df8a63bcca95e6ac /src/mesa/state_tracker
parenteb82373abb08171d7fcb15b5f4f229fc9ca9aa91 (diff)
parenteeb7e04da64fdae3a40b1afdcde71dcded2481f3 (diff)
Merge branch 'mesa_7_6_branch'
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r--src/mesa/state_tracker/st_cb_texture.c62
-rw-r--r--src/mesa/state_tracker/st_gen_mipmap.c82
2 files changed, 89 insertions, 55 deletions
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 3520c986b4..c0fba8641b 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -1693,53 +1693,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,
@@ -1803,13 +1756,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);
}