summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2010-04-19 11:17:11 -0600
committerBrian Paul <[email protected]>2010-04-19 11:18:51 -0600
commit05bf77a2dac75bd58e4d4b03e18ab3ff1458ffaf (patch)
tree3287e7e3a2682f6094992d582e1ada0558a8f5d4
parent64644ec3b21884d4a974fa29087fa98c4ed9e112 (diff)
llvmpipe: fix surface memory allocation bug
We weren't always allocating the right amount of memory for image tiles for some formats (those < 32bpp). Fixes fd.o bug 27712.
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index 2267fcb29ca..f719ca48ee5 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -665,17 +665,35 @@ static unsigned
tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level,
enum lp_texture_layout layout)
{
- /* for tiled layout, force a 32bpp format */
- enum pipe_format format = layout == LP_TEX_LAYOUT_TILED
- ? PIPE_FORMAT_B8G8R8A8_UNORM : lpr->base.format;
+ const unsigned width = u_minify(lpr->base.width0, level);
const unsigned height = u_minify(lpr->base.height0, level);
const unsigned depth = u_minify(lpr->base.depth0, level);
- const unsigned nblocksy =
- util_format_get_nblocksy(format, align(height, TILE_SIZE));
- const unsigned buffer_size =
- nblocksy * lpr->stride[level] *
- (lpr->base.target == PIPE_TEXTURE_3D ? depth : 1);
- return buffer_size;
+
+ assert(layout == LP_TEX_LAYOUT_TILED ||
+ layout == LP_TEX_LAYOUT_LINEAR);
+
+ if (layout == LP_TEX_LAYOUT_TILED) {
+ /* for tiled layout, force a 32bpp format */
+ const enum pipe_format format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ const unsigned block_size = util_format_get_blocksize(format);
+ const unsigned nblocksy =
+ util_format_get_nblocksy(format, align(height, TILE_SIZE));
+ const unsigned nblocksx =
+ util_format_get_nblocksx(format, align(width, TILE_SIZE));
+ const unsigned buffer_size =
+ block_size * nblocksy * nblocksx *
+ (lpr->base.target == PIPE_TEXTURE_3D ? depth : 1);
+ return buffer_size;
+ }
+ else {
+ const enum pipe_format format = lpr->base.format;
+ const unsigned nblocksy =
+ util_format_get_nblocksy(format, align(height, TILE_SIZE));
+ const unsigned buffer_size =
+ nblocksy * lpr->stride[level] *
+ (lpr->base.target == PIPE_TEXTURE_3D ? depth : 1);
+ return buffer_size;
+ }
}
@@ -784,7 +802,7 @@ llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
/**
* Return pointer to texture image data (either linear or tiled layout).
* \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE
- * \param layout either LP_TEX_LAYOUT_LINEAR or LP_TEX_LAYOUT_TILED
+ * \param layout either LP_TEX_LAYOUT_LINEAR or _TILED or _NONE
*/
void *
llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
@@ -837,7 +855,11 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
if (!target_data) {
/* allocate memory for the target image now */
- unsigned buffer_size = tex_image_size(lpr, level, layout);
+ unsigned buffer_size;
+ if (layout == LP_TEX_LAYOUT_LINEAR)
+ buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR);
+ else
+ buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_TILED);
target_img->data = align_malloc(buffer_size, 16);
target_data = target_img->data;
}
@@ -853,7 +875,9 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
}
if (layout == LP_TEX_LAYOUT_NONE) {
- /* just allocating memory */
+ /* Just allocating tiled memory. Don't initialize it from the the
+ * linear data if it exists.
+ */
return target_data;
}