summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/radeon/radeon_texture.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-11-11 16:13:06 +0000
committerDave Airlie <airlied@redhat.com>2011-12-05 14:36:19 +0000
commitb2596c36c8f73e8bb7a0b1679b491662aeb2f9d9 (patch)
tree0eff8746b4334dbc6e780e7426031a910335a781 /src/mesa/drivers/dri/radeon/radeon_texture.c
parentfd7fcfcc2dffb73ac3159a04ccd164b527c11a8f (diff)
downloadexternal_mesa3d-b2596c36c8f73e8bb7a0b1679b491662aeb2f9d9.zip
external_mesa3d-b2596c36c8f73e8bb7a0b1679b491662aeb2f9d9.tar.gz
external_mesa3d-b2596c36c8f73e8bb7a0b1679b491662aeb2f9d9.tar.bz2
radeon: texture/renderbuffer overhaul.
This could have been split up better, but the driver is just broken now, so bisecting the brokenness is going to be painful no matter what. This adds renderbuffer mapping/unmapping along with texture image allocation. It drops all the old texture upload paths, some of which could possible be reimplemented with the blitter later. It also redoes the span code paths to use its own set of image mapping handlers, along with removing the tiling decode paths for the color buffers, since we now hope to use the blitter for this. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'src/mesa/drivers/dri/radeon/radeon_texture.c')
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_texture.c600
1 files changed, 184 insertions, 416 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_texture.c b/src/mesa/drivers/dri/radeon/radeon_texture.c
index 178ff09..71eff75 100644
--- a/src/mesa/drivers/dri/radeon/radeon_texture.c
+++ b/src/mesa/drivers/dri/radeon/radeon_texture.c
@@ -48,6 +48,13 @@
#include "radeon_mipmap_tree.h"
+static void teximage_assign_miptree(radeonContextPtr rmesa,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+
+static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
GLuint numrows, GLuint rowsize)
@@ -94,6 +101,33 @@ radeonDeleteTextureImage(struct gl_context *ctx, struct gl_texture_image *img)
_mesa_delete_texture_image(ctx, img);
}
+static GLboolean
+radeonAllocTextureImageBuffer(struct gl_context *ctx,
+ struct gl_texture_image *timage,
+ gl_format format, GLsizei width,
+ GLsizei height, GLsizei depth)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ radeon_texture_image *image = get_radeon_texture_image(timage);
+ struct gl_texture_object *texobj = timage->TexObject;
+ int slices;
+
+ ctx->Driver.FreeTextureImageBuffer(ctx, timage);
+
+ switch (texobj->Target) {
+ case GL_TEXTURE_3D:
+ slices = timage->Depth;
+ break;
+ default:
+ slices = 1;
+ }
+ assert(!image->base.ImageOffsets);
+ image->base.ImageOffsets = malloc(slices * sizeof(GLuint));
+ teximage_assign_miptree(rmesa, texobj, timage);
+
+ return GL_TRUE;
+}
+
/**
* Free memory associated with this texture image.
@@ -104,7 +138,6 @@ void radeonFreeTextureImageBuffer(struct gl_context *ctx, struct gl_texture_imag
if (image->mt) {
radeon_miptree_unreference(&image->mt);
- assert(!image->base.Buffer);
} else {
_swrast_free_texture_image_buffer(ctx, timage);
}
@@ -173,91 +206,6 @@ void radeon_teximage_unmap(radeon_texture_image *image)
}
}
-static void map_override(struct gl_context *ctx, radeonTexObj *t)
-{
- radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
-
- radeon_bo_map(t->bo, GL_FALSE);
-
- img->base.Data = t->bo->ptr;
-}
-
-static void unmap_override(struct gl_context *ctx, radeonTexObj *t)
-{
- radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
-
- radeon_bo_unmap(t->bo);
-
- img->base.Data = NULL;
-}
-
-/**
- * Map a validated texture for reading during software rendering.
- */
-void radeonMapTexture(struct gl_context *ctx, struct gl_texture_object *texObj)
-{
- radeonTexObj* t = radeon_tex_obj(texObj);
- int face, level;
-
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s(%p, tex %p)\n",
- __func__, ctx, texObj);
-
- if (!radeon_validate_texture_miptree(ctx, texObj)) {
- radeon_error("%s(%p, tex %p) Failed to validate miptree for "
- "sw fallback.\n",
- __func__, ctx, texObj);
- return;
- }
-
- if (t->image_override && t->bo) {
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s(%p, tex %p) Work around for missing miptree in r100.\n",
- __func__, ctx, texObj);
-
- map_override(ctx, t);
- }
-
- /* for r100 3D sw fallbacks don't have mt */
- if (!t->mt) {
- radeon_warning("%s(%p, tex %p) No miptree in texture.\n",
- __func__, ctx, texObj);
- return;
- }
-
- radeon_bo_map(t->mt->bo, GL_FALSE);
- for(face = 0; face < t->mt->faces; ++face) {
- for(level = t->minLod; level <= t->maxLod; ++level)
- teximage_set_map_data(get_radeon_texture_image(texObj->Image[face][level]));
- }
-}
-
-void radeonUnmapTexture(struct gl_context *ctx, struct gl_texture_object *texObj)
-{
- radeonTexObj* t = radeon_tex_obj(texObj);
- int face, level;
-
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s(%p, tex %p)\n",
- __func__, ctx, texObj);
-
- if (t->image_override && t->bo)
- unmap_override(ctx, t);
- /* for r100 3D sw fallbacks don't have mt */
- if (!t->mt)
- return;
-
- for(face = 0; face < t->mt->faces; ++face) {
- for(level = t->minLod; level <= t->maxLod; ++level) {
- radeon_texture_image *image =
- get_radeon_texture_image(texObj->Image[face][level]);
- image->base.Data = NULL;
- }
- }
- radeon_bo_unmap(t->mt->bo);
-}
-
-
/**
* Map texture memory/buffer into user space.
* Note: the region of interest parameters are ignored here.
@@ -286,7 +234,7 @@ radeon_map_texture_image(struct gl_context *ctx,
_mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
assert(y % bh == 0);
y /= bh;
- height /= bh;
+ texel_size /= bw;
if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
@@ -302,9 +250,11 @@ radeon_map_texture_image(struct gl_context *ctx,
*stride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texImage->TexObject->Target);
*map = bo->ptr;
} else if (likely(mt)) {
- radeon_bo_map(mt->bo, write);
+ void *base;
radeon_mipmap_level *lvl = &image->mt->levels[texImage->Level];
- void *base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset;
+
+ radeon_bo_map(mt->bo, write);
+ base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset;
*stride = lvl->rowstride;
*map = base + (slice * height) * *stride;
@@ -594,51 +544,24 @@ gl_format radeonChooseTextureFormat(struct gl_context * ctx,
/** Check if given image is valid within current texture object.
*/
-static int image_matches_texture_obj(struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- unsigned level)
-{
- const struct gl_texture_image *baseImage = texObj->Image[0][texObj->BaseLevel];
-
- if (!baseImage)
- return 0;
-
- if (level < texObj->BaseLevel || level > texObj->MaxLevel)
- return 0;
-
- const unsigned levelDiff = level - texObj->BaseLevel;
- const unsigned refWidth = MAX2(baseImage->Width >> levelDiff, 1);
- const unsigned refHeight = MAX2(baseImage->Height >> levelDiff, 1);
- const unsigned refDepth = MAX2(baseImage->Depth >> levelDiff, 1);
-
- return (texImage->Width == refWidth &&
- texImage->Height == refHeight &&
- texImage->Depth == refDepth);
-}
-
static void teximage_assign_miptree(radeonContextPtr rmesa,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- unsigned face,
- unsigned level)
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
{
radeonTexObj *t = radeon_tex_obj(texObj);
radeon_texture_image* image = get_radeon_texture_image(texImage);
- /* Since miptree holds only images for levels <BaseLevel..MaxLevel>
- * don't allocate the miptree if the teximage won't fit.
- */
- if (!image_matches_texture_obj(texObj, texImage, level))
- return;
-
/* Try using current miptree, or create new if there isn't any */
- if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
+ if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage)) {
radeon_miptree_unreference(&t->mt);
- radeon_try_alloc_miptree(rmesa, t);
+ t->mt = radeon_miptree_create_for_teximage(rmesa,
+ texObj,
+ texImage);
+
radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
- "%s: texObj %p, texImage %p, face %d, level %d, "
+ "%s: texObj %p, texImage %p, "
"texObj miptree doesn't match, allocated new miptree %p\n",
- __FUNCTION__, texObj, texImage, face, level, t->mt);
+ __FUNCTION__, texObj, texImage, t->mt);
}
/* Miptree alocation may have failed,
@@ -650,101 +573,6 @@ static void teximage_assign_miptree(radeonContextPtr rmesa,
"%s Failed to allocate miptree.\n", __func__);
}
-
-/**
- * Update a subregion of the given texture image.
- */
-static void radeon_store_teximage(struct gl_context* ctx, int dims,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- int compressed)
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- radeonTexObj *t = radeon_tex_obj(texObj);
- radeon_texture_image* image = get_radeon_texture_image(texImage);
- GLuint texel_size = _mesa_get_format_bytes(texImage->TexFormat);
-
- GLuint dstRowStride;
- GLuint alignedWidth;
- GLint i;
-
- radeon_print(RADEON_TEXTURE, RADEON_TRACE,
- "%s(%p, tex %p, image %p) compressed %d\n",
- __func__, ctx, texObj, texImage, compressed);
-
- if (image->mt) {
- dstRowStride = image->mt->levels[image->base.Base.Level].rowstride;
- } else if (t->bo) {
- /* TFP case */
- dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texObj->Target);
- } else {
- dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
- }
-
- assert(dstRowStride);
-
- /* fill in the ImageOffsets array */
- alignedWidth = dstRowStride / texel_size;
- for (i = 0; i < texImage->Depth; ++i) {
- image->base.ImageOffsets[i] = alignedWidth * texImage->Height * i;
- }
- /* and fill in RowStride (in texels) */
- image->base.RowStride = alignedWidth;
-
- radeon_teximage_map(image, GL_TRUE);
-
- if (compressed) {
- uint32_t srcRowStride, bytesPerRow, rows, block_width, block_height;
- GLubyte *img_start;
-
- _mesa_get_format_block_size(texImage->TexFormat, &block_width, &block_height);
-
- if (!image->mt) {
- dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
- img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
- texImage->TexFormat,
- texImage->Width, image->base.Data);
- }
- else {
- uint32_t offset;
- offset = dstRowStride / texel_size * yoffset / block_height + xoffset / block_width;
- offset *= texel_size;
- img_start = image->base.Data + offset;
- }
- srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
- bytesPerRow = srcRowStride;
- rows = (height + block_height - 1) / block_height;
-
- copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow);
- }
- else {
- GLubyte *slices[512];
- GLuint i;
- assert(depth <= 512);
- for (i = 0; i < depth; i++) {
- slices[i] = (GLubyte *) image->base.Data
- + image->base.ImageOffsets[i] * texel_size;
- }
- if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
- texImage->TexFormat,
- xoffset, yoffset, zoffset,
- dstRowStride,
- slices,
- width, height, depth,
- format, type, pixels, packing)) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
- }
- }
-
- radeon_teximage_unmap(image);
-}
-
/**
* All glTexImage calls go through this function.
*/
@@ -760,72 +588,10 @@ static void radeon_teximage(
struct gl_texture_image *texImage,
int compressed)
{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- radeonTexObj* t = radeon_tex_obj(texObj);
- radeon_texture_image* image = get_radeon_texture_image(texImage);
- GLuint face = _mesa_tex_target_to_face(target);
-
- radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
- "%s %dd: texObj %p, texImage %p, face %d, level %d\n",
- __func__, dims, texObj, texImage, face, level);
-
- t->validated = GL_FALSE;
-
- radeonFreeTextureImageBuffer(ctx, texImage);
-
- if (!t->bo) {
- teximage_assign_miptree(rmesa, texObj, texImage, face, level);
- if (!image->mt) {
- int size = _mesa_format_image_size(texImage->TexFormat,
- texImage->Width,
- texImage->Height,
- texImage->Depth);
- image->base.Buffer = _mesa_align_malloc(size, 512);
-
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s %dd: texObj %p, texImage %p, "
- " no miptree assigned, using local memory %p\n",
- __func__, dims, texObj, texImage, image->base.Buffer);
- }
- }
-
- {
- struct radeon_bo *bo;
- bo = !image->mt ? image->bo : image->mt->bo;
- if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s Calling teximage for texture that is "
- "queued for GPU processing.\n",
- __func__);
- radeon_firevertices(rmesa);
- }
- }
-
- image->base.ImageOffsets =
- (GLuint *) malloc(texImage->Depth * sizeof(GLuint));
-
-
- /* Upload texture image; note that the spec allows pixels to be NULL */
- if (compressed) {
- pixels = _mesa_validate_pbo_compressed_teximage(
- ctx, imageSize, pixels, packing, "glCompressedTexImage");
- } else {
- pixels = _mesa_validate_pbo_teximage(
- ctx, dims, width, height, depth,
- format, type, pixels, packing, "glTexImage");
- }
-
- if (pixels) {
- radeon_store_teximage(ctx, dims,
- 0, 0, 0,
- width, height, depth,
- imageSize, format, type,
- pixels, packing,
- texObj, texImage,
- compressed);
- }
-
- _mesa_unmap_teximage_pbo(ctx, packing);
+ _mesa_store_teximage3d(ctx, target, level, internalFormat,
+ width, height, depth, 0,
+ format, type, pixels,
+ packing, texObj, texImage);
}
void radeonTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
@@ -853,17 +619,6 @@ void radeonTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
0, format, type, pixels, packing, texObj, texImage, 0);
}
-void radeonCompressedTexImage2D(struct gl_context * ctx, GLenum target,
- GLint level, GLint internalFormat,
- GLint width, GLint height, GLint border,
- GLsizei imageSize, const GLvoid * data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_teximage(ctx, 2, target, level, internalFormat, width, height, 1,
- imageSize, 0, 0, data, &ctx->Unpack, texObj, texImage, 1);
-}
-
void radeonTexImage3D(struct gl_context * ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
@@ -877,116 +632,6 @@ void radeonTexImage3D(struct gl_context * ctx, GLenum target, GLint level,
0, format, type, pixels, packing, texObj, texImage, 0);
}
-/**
- * All glTexSubImage calls go through this function.
- */
-static void radeon_texsubimage(struct gl_context* ctx, int dims, GLenum target, int level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage,
- int compressed)
-{
- radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- radeonTexObj* t = radeon_tex_obj(texObj);
- radeon_texture_image* image = get_radeon_texture_image(texImage);
-
- radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
- "%s %dd: texObj %p, texImage %p, face %d, level %d\n",
- __func__, dims, texObj, texImage,
- _mesa_tex_target_to_face(target), level);
- {
- struct radeon_bo *bo;
- bo = !image->mt ? image->bo : image->mt->bo;
- if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
- radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
- "%s Calling texsubimage for texture that is "
- "queued for GPU processing.\n",
- __func__);
- radeon_firevertices(rmesa);
- }
- }
-
-
- t->validated = GL_FALSE;
- if (compressed) {
- pixels = _mesa_validate_pbo_compressed_teximage(
- ctx, imageSize, pixels, packing, "glCompressedTexSubImage");
- } else {
- pixels = _mesa_validate_pbo_teximage(ctx, dims,
- width, height, depth, format, type, pixels, packing, "glTexSubImage");
- }
-
- if (pixels) {
- radeon_store_teximage(ctx, dims,
- xoffset, yoffset, zoffset,
- width, height, depth,
- imageSize, format, type,
- pixels, packing,
- texObj, texImage,
- compressed);
- }
-
- _mesa_unmap_teximage_pbo(ctx, packing);
-}
-
-void radeonTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
- GLint xoffset,
- GLsizei width,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, 0,
- format, type, pixels, packing, texObj, texImage, 0);
-}
-
-void radeonTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1,
- 0, format, type, pixels, packing, texObj, texImage,
- 0);
-}
-
-void radeonCompressedTexSubImage2D(struct gl_context * ctx, GLenum target,
- GLint level, GLint xoffset,
- GLint yoffset, GLsizei width,
- GLsizei height, GLenum format,
- GLsizei imageSize, const GLvoid * data,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0, width, height, 1,
- imageSize, format, 0, data, &ctx->Unpack, texObj, texImage, 1);
-}
-
-
-void radeonTexSubImage3D(struct gl_context * ctx, GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type,
- const GLvoid * pixels,
- const struct gl_pixelstore_attrib *packing,
- struct gl_texture_object *texObj,
- struct gl_texture_image *texImage)
-{
- radeon_texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, width, height, depth, 0,
- format, type, pixels, packing, texObj, texImage, 0);
-}
-
unsigned radeonIsFormatRenderable(gl_format mesa_format)
{
if (mesa_format == _radeon_texformat_argb8888 || mesa_format == _radeon_texformat_rgb565 ||
@@ -1059,8 +704,7 @@ void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target,
radeon_bo_ref(image->bo);
t->mt->bo = image->bo;
- if (!radeon_miptree_matches_image(t->mt, &radeonImage->base.Base,
- radeonImage->base.Base.Face, 0))
+ if (!radeon_miptree_matches_image(t->mt, &radeonImage->base.Base))
fprintf(stderr, "miptree doesn't match image\n");
}
#endif
@@ -1101,9 +745,8 @@ radeon_init_common_texture_funcs(radeonContextPtr radeon,
{
functions->NewTextureImage = radeonNewTextureImage;
functions->DeleteTextureImage = radeonDeleteTextureImage;
+ functions->AllocTextureImageBuffer = radeonAllocTextureImageBuffer;
functions->FreeTextureImageBuffer = radeonFreeTextureImageBuffer;
- functions->MapTexture = radeonMapTexture;
- functions->UnmapTexture = radeonUnmapTexture;
functions->MapTextureImage = radeon_map_texture_image;
functions->UnmapTextureImage = radeon_unmap_texture_image;
@@ -1112,11 +755,6 @@ radeon_init_common_texture_funcs(radeonContextPtr radeon,
functions->TexImage1D = radeonTexImage1D;
functions->TexImage2D = radeonTexImage2D;
functions->TexImage3D = radeonTexImage3D;
- functions->TexSubImage1D = radeonTexSubImage1D;
- functions->TexSubImage2D = radeonTexSubImage2D;
- functions->TexSubImage3D = radeonTexSubImage3D;
- functions->CompressedTexImage2D = radeonCompressedTexImage2D;
- functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
functions->CopyTexSubImage2D = radeonCopyTexSubImage2D;
@@ -1127,3 +765,133 @@ radeon_init_common_texture_funcs(radeonContextPtr radeon,
radeonInitTextureFormats();
}
+
+static void
+radeon_swrast_map_image(radeonContextPtr rmesa,
+ radeon_texture_image *image)
+{
+ GLuint level, face;
+ radeon_mipmap_tree *mt;
+ GLuint texel_size;
+ radeon_mipmap_level *lvl;
+ int rs;
+
+ if (!image || !image->mt)
+ return;
+
+ texel_size = _mesa_get_format_bytes(image->base.Base.TexFormat);
+ level = image->base.Base.Level;
+ face = image->base.Base.Face;
+ mt = image->mt;
+
+ lvl = &image->mt->levels[level];
+
+ rs = lvl->rowstride / texel_size;
+
+ radeon_bo_map(mt->bo, 1);
+
+ image->base.Data = mt->bo->ptr + lvl->faces[face].offset;
+ if (mt->target == GL_TEXTURE_3D) {
+ int i;
+
+ for (i = 0; i < mt->levels[level].depth; i++)
+ image->base.ImageOffsets[i] = rs * lvl->height * i;
+ }
+ image->base.RowStride = rs;
+}
+
+static void
+radeon_swrast_unmap_image(radeonContextPtr rmesa,
+ radeon_texture_image *image)
+{
+ if (image && image->mt) {
+ image->base.Data = NULL;
+ radeon_bo_unmap(image->mt->bo);
+ }
+}
+
+void
+radeon_swrast_map_texture_images(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int i, face;
+
+ for (i = texObj->BaseLevel; i <= texObj->_MaxLevel; i++) {
+ for (face = 0; face < nr_faces; face++) {
+ radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][i]);
+ radeon_swrast_map_image(rmesa, image);
+ }
+ }
+}
+
+void
+radeon_swrast_unmap_texture_images(struct gl_context *ctx,
+ struct gl_texture_object *texObj)
+{
+ radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+ GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ int i, face;
+
+ for (i = texObj->BaseLevel; i <= texObj->_MaxLevel; i++) {
+ for (face = 0; face < nr_faces; face++) {
+ radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][i]);
+ radeon_swrast_unmap_image(rmesa, image);
+ }
+ }
+
+}
+
+static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ radeonTexObj *t = radeon_tex_obj(texObj);
+ GLuint firstLevel;
+ GLuint lastLevel;
+ int width, height, depth;
+ int i;
+
+ width = texImage->Width;
+ height = texImage->Height;
+ depth = texImage->Depth;
+
+ if (texImage->Level > texObj->BaseLevel &&
+ (width == 1 ||
+ (texObj->Target != GL_TEXTURE_1D && height == 1) ||
+ (texObj->Target == GL_TEXTURE_3D && depth == 1))) {
+ /* For this combination, we're at some lower mipmap level and
+ * some important dimension is 1. We can't extrapolate up to a
+ * likely base level width/height/depth for a full mipmap stack
+ * from this info, so just allocate this one level.
+ */
+ firstLevel = texImage->Level;
+ lastLevel = texImage->Level;
+ } else {
+ if (texImage->Level < texObj->BaseLevel)
+ firstLevel = 0;
+ else
+ firstLevel = texObj->BaseLevel;
+
+ for (i = texImage->Level; i > firstLevel; i--) {
+ width <<= 1;
+ if (height != 1)
+ height <<= 1;
+ if (depth != 1)
+ depth <<= 1;
+ }
+ if ((texObj->Sampler.MinFilter == GL_NEAREST ||
+ texObj->Sampler.MinFilter == GL_LINEAR) &&
+ texImage->Level == firstLevel) {
+ lastLevel = firstLevel;
+ } else {
+ lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth));
+ }
+ }
+
+ return radeon_miptree_create(rmesa, texObj->Target,
+ texImage->TexFormat, firstLevel, lastLevel - firstLevel + 1,
+ width, height, depth,
+ t->tile_bits);
+}