void st_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = ctx->st; struct pipe_texture *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; uint lastLevel; uint dstLevel; if (!pt) return; lastLevel = pt->last_level; if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) { fallback_generate_mipmap(ctx, target, texObj); } /* Fill in the Mesa gl_texture_image fields */ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; const struct gl_texture_image *srcImage = _mesa_get_tex_image(ctx, texObj, target, srcLevel); struct gl_texture_image *dstImage; struct st_texture_image *stImage; uint dstWidth = pt->width[dstLevel]; uint dstHeight = pt->height[dstLevel]; uint dstDepth = pt->depth[dstLevel]; uint border = srcImage->Border; dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); if (!dstImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); return; } /* Free old image data */ if (dstImage->Data) ctx->Driver.FreeTexImageData(ctx, dstImage); /* initialize new image */ _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, dstDepth, border, srcImage->InternalFormat); dstImage->TexFormat = srcImage->TexFormat; stImage = (struct st_texture_image *) dstImage; pipe_texture_reference(&stImage->pt, pt); } }
/** * Called via ctx->Driver.GenerateMipmap(). */ void st_generate_mipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_resource *pt = st_get_texobj_resource(texObj); const uint baseLevel = texObj->BaseLevel; uint lastLevel; uint dstLevel; if (!pt) return; /* not sure if this ultimately actually should work, but we're not supporting multisampled textures yet. */ assert(pt->nr_samples < 2); /* find expected last mipmap level to generate*/ lastLevel = compute_num_levels(ctx, texObj, target) - 1; if (lastLevel == 0) return; /* 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; 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 pipe_resource *oldTex = stObj->pt; /* create new texture with space for more levels */ stObj->pt = st_texture_create(st, oldTex->target, oldTex->format, lastLevel, oldTex->width0, oldTex->height0, oldTex->depth0, oldTex->array_size, oldTex->bind); /* This will copy the old texture's base image into the new texture * which we just allocated. */ st_finalize_texture(ctx, st->pipe, texObj); /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); pipe_sampler_view_reference(&stObj->sampler_view, NULL); } else { /* Make sure that the base texture image data is present in the * texture buffer. */ st_finalize_texture(ctx, st->pipe, texObj); } pt = stObj->pt; assert(pt->last_level >= lastLevel); /* Try to generate the mipmap by rendering/texturing. If that fails, * use the software fallback. */ if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) { /* since the util code actually also has a fallback, should probably make it never fail and kill this */ _mesa_generate_mipmap(ctx, target, texObj); } /* Fill in the Mesa gl_texture_image fields */ for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) { const uint srcLevel = dstLevel - 1; const struct gl_texture_image *srcImage = _mesa_get_tex_image(ctx, texObj, target, srcLevel); struct gl_texture_image *dstImage; struct st_texture_image *stImage; uint border = srcImage->Border; uint dstWidth, dstHeight, dstDepth; dstWidth = u_minify(pt->width0, dstLevel); if (texObj->Target == GL_TEXTURE_1D_ARRAY) { dstHeight = pt->array_size; } else { dstHeight = u_minify(pt->height0, dstLevel); } if (texObj->Target == GL_TEXTURE_2D_ARRAY) { dstDepth = pt->array_size; } else { dstDepth = u_minify(pt->depth0, dstLevel); } dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); if (!dstImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); return; } /* Free old image data */ ctx->Driver.FreeTextureImageBuffer(ctx, dstImage); /* initialize new image */ _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight, dstDepth, border, srcImage->InternalFormat, srcImage->TexFormat); stImage = st_texture_image(dstImage); pipe_resource_reference(&stImage->pt, pt); } }