summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/llvmpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_texture.c74
1 files changed, 29 insertions, 45 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index 40e5815ab33..756734b890b 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -59,16 +59,15 @@ static struct llvmpipe_resource resource_list;
#endif
static unsigned id_counter = 0;
-static void
-alloc_image_data(struct llvmpipe_resource *lpr);
/**
* Conventional allocation path for non-display textures:
- * Just compute row strides here. Storage is allocated on demand later.
+ * Compute strides and allocate data (unless asked not to).
*/
static boolean
llvmpipe_texture_layout(struct llvmpipe_screen *screen,
- struct llvmpipe_resource *lpr)
+ struct llvmpipe_resource *lpr,
+ boolean allocate)
{
struct pipe_resource *pt = &lpr->base;
unsigned level;
@@ -77,11 +76,20 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
unsigned depth = pt->depth0;
uint64_t total_size = 0;
unsigned layers = pt->array_size;
+ /* XXX:
+ * This alignment here (same for displaytarget) was added for the purpose of
+ * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer
+ * resources. Otherwise we'd want the max of cacheline size and 16 (max size
+ * of a block for all formats) though this should not be strictly necessary
+ * neither. In any case it can only affect compressed or 1d textures.
+ */
+ unsigned mip_align = MAX2(64, util_cpu_caps.cacheline);
assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
for (level = 0; level <= pt->last_level; level++) {
+ uint64_t mipsize;
/* Row stride and image stride */
{
@@ -143,14 +151,15 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
}
/* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */
- if (lpr->img_stride[level] >
- LP_MAX_TEXTURE_SIZE / lpr->num_slices_faces[level]) {
+ mipsize = (uint64_t)lpr->num_slices_faces[level] * lpr->img_stride[level];
+ if (mipsize > LP_MAX_TEXTURE_SIZE) {
/* volume too large */
goto fail;
}
- total_size += (uint64_t) lpr->num_slices_faces[level]
- * (uint64_t) lpr->img_stride[level];
+ lpr->mip_offsets[level] = total_size;
+
+ total_size += align((unsigned)mipsize, mip_align);
if (total_size > LP_MAX_TEXTURE_SIZE) {
goto fail;
}
@@ -161,6 +170,16 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
depth = u_minify(depth, 1);
}
+ if (allocate) {
+ lpr->tex_data = align_malloc(total_size, mip_align);
+ if (!lpr->tex_data) {
+ return FALSE;
+ }
+ else {
+ memset(lpr->tex_data, 0, total_size);
+ }
+ }
+
return TRUE;
fail:
@@ -179,7 +198,7 @@ llvmpipe_can_create_resource(struct pipe_screen *screen,
struct llvmpipe_resource lpr;
memset(&lpr, 0, sizeof(lpr));
lpr.base = *res;
- return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr);
+ return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false);
}
@@ -247,13 +266,8 @@ llvmpipe_resource_create(struct pipe_screen *_screen,
}
else {
/* texture map */
- if (!llvmpipe_texture_layout(screen, lpr))
- goto fail;
-
- alloc_image_data(lpr);
- if (!lpr->tex_data) {
+ if (!llvmpipe_texture_layout(screen, lpr, true))
goto fail;
- }
}
}
else {
@@ -747,36 +761,6 @@ llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
/**
- * Allocate storage for a linear image
- * (all cube faces and all 3D slices, all levels).
- */
-static void
-alloc_image_data(struct llvmpipe_resource *lpr)
-{
- uint alignment = MAX2(64, util_cpu_caps.cacheline);
- uint level;
- uint offset = 0;
-
- assert(!lpr->dt);
-
- /* not a display target - allocate regular memory */
- /*
- * Offset calculation for start of a specific mip/layer is always
- * offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer
- */
- for (level = 0; level <= lpr->base.last_level; level++) {
- uint buffer_size = tex_image_size(lpr, level);
- lpr->mip_offsets[level] = offset;
- offset += align(buffer_size, alignment);
- }
- lpr->tex_data = align_malloc(offset, alignment);
- if (lpr->tex_data) {
- memset(lpr->tex_data, 0, offset);
- }
-}
-
-
-/**
* Return size of resource in bytes
*/
unsigned