summaryrefslogtreecommitdiff
path: root/src/mesa/pipe/softpipe
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2008-01-10 10:03:47 +0100
committerMichel Dänzer <michel@tungstengraphics.com>2008-01-10 10:06:00 +0100
commitede7b00b59b37f078de0663918c0c84d572c27e8 (patch)
tree9625fa23bec799b40d4785fa40ad31f778d945af /src/mesa/pipe/softpipe
parent51ea675745f4212c0bd859a940350faf466df102 (diff)
softpipe: Simplify texture memory layout.
Diffstat (limited to 'src/mesa/pipe/softpipe')
-rw-r--r--src/mesa/pipe/softpipe/sp_surface.c27
-rw-r--r--src/mesa/pipe/softpipe/sp_texture.c330
-rw-r--r--src/mesa/pipe/softpipe/sp_texture.h19
3 files changed, 30 insertions, 346 deletions
diff --git a/src/mesa/pipe/softpipe/sp_surface.c b/src/mesa/pipe/softpipe/sp_surface.c
index 5259fbfd20..ece30e36ec 100644
--- a/src/mesa/pipe/softpipe/sp_surface.c
+++ b/src/mesa/pipe/softpipe/sp_surface.c
@@ -46,20 +46,6 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
{
struct softpipe_texture *spt = softpipe_texture(pt);
struct pipe_surface *ps;
- unsigned offset; /* in bytes */
-
- offset = spt->level_offset[level];
-
- if (pt->target == PIPE_TEXTURE_CUBE) {
- offset += spt->image_offset[level][face] * pt->cpp;
- }
- else if (pt->target == PIPE_TEXTURE_3D) {
- offset += spt->image_offset[level][zslice] * pt->cpp;
- }
- else {
- assert(face == 0);
- assert(zslice == 0);
- }
ps = pipe->winsys->surface_alloc(pipe->winsys);
if (ps) {
@@ -69,8 +55,17 @@ softpipe_get_tex_surface(struct pipe_context *pipe,
ps->cpp = pt->cpp;
ps->width = pt->width[level];
ps->height = pt->height[level];
- ps->pitch = spt->pitch;
- ps->offset = offset;
+ ps->pitch = ps->width;
+ ps->offset = spt->level_offset[level];
+
+ if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
+ ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
+ (pt->compressed ? ps->height/4 : ps->height) *
+ ps->width * ps->cpp;
+ } else {
+ assert(face == 0);
+ assert(zslice == 0);
+ }
}
return ps;
}
diff --git a/src/mesa/pipe/softpipe/sp_texture.c b/src/mesa/pipe/softpipe/sp_texture.c
index 44512e4281..e5e6bfe01b 100644
--- a/src/mesa/pipe/softpipe/sp_texture.c
+++ b/src/mesa/pipe/softpipe/sp_texture.c
@@ -41,10 +41,7 @@
#include "sp_texture.h"
-/* At the moment, just make softpipe use the same layout for its
- * textures as the i945. Softpipe needs some sort of texture layout,
- * this one was handy. May be worthwhile to simplify this code a
- * little.
+/* Simple, maximally packed layout.
*/
static unsigned minify( unsigned d )
@@ -53,319 +50,35 @@ static unsigned minify( unsigned d )
}
-
-static void
-sp_miptree_set_level_info(struct softpipe_texture *spt,
- unsigned level,
- unsigned nr_images,
- unsigned x, unsigned y, unsigned w, unsigned h,
- unsigned d)
-{
- struct pipe_texture *pt = &spt->base;
-
- assert(level < PIPE_MAX_TEXTURE_LEVELS);
-
- pt->width[level] = w;
- pt->height[level] = h;
- pt->depth[level] = d;
-
- spt->nr_images[level] = nr_images;
- spt->level_offset[level] = (x + y * spt->pitch) * pt->cpp;
-
- /*
- DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
- level, w, h, d, x, y, spt->level_offset[level]);
- */
-
- /* Not sure when this would happen, but anyway:
- */
- if (spt->image_offset[level]) {
- FREE( spt->image_offset[level] );
- spt->image_offset[level] = NULL;
- }
-
- assert(nr_images);
- assert(!spt->image_offset[level]);
-
- spt->image_offset[level] = (unsigned *) MALLOC( nr_images * sizeof(unsigned) );
- spt->image_offset[level][0] = 0;
-}
-
-
-static void
-sp_miptree_set_image_offset(struct softpipe_texture *spt,
- unsigned level, unsigned img, unsigned x, unsigned y)
-{
- if (img == 0 && level == 0)
- assert(x == 0 && y == 0);
-
- assert(img < spt->nr_images[level]);
-
- spt->image_offset[level][img] = (x + y * spt->pitch);
-
- /*
- DBG("%s level %d img %d pos %d,%d image_offset %x\n",
- __FUNCTION__, level, img, x, y, spt->image_offset[level][img]);
- */
-}
-
-
static void
-sp_miptree_layout_2d( struct softpipe_texture *spt )
+softpipe_texture_layout(struct softpipe_texture * spt)
{
struct pipe_texture *pt = &spt->base;
- int align_h = 2, align_w = 4;
unsigned level;
- unsigned x = 0;
- unsigned y = 0;
unsigned width = pt->width[0];
unsigned height = pt->height[0];
+ unsigned depth = pt->depth[0];
- spt->pitch = pt->width[0];
- /* XXX FIX THIS:
- * we use alignment=64 bytes in sp_region_alloc(). If we change
- * that, change this too.
- */
- if (spt->pitch < 16)
- spt->pitch = 16;
-
- /* May need to adjust pitch to accomodate the placement of
- * the 2nd mipmap. This occurs when the alignment
- * constraints of mipmap placement push the right edge of the
- * 2nd mipmap out past the width of its parent.
- */
- if (pt->first_level != pt->last_level) {
- unsigned mip1_width = align(minify(pt->width[0]), align_w)
- + minify(minify(pt->width[0]));
-
- if (mip1_width > pt->width[0])
- spt->pitch = mip1_width;
- }
-
- /* Pitch must be a whole number of dwords, even though we
- * express it in texels.
- */
- spt->pitch = align(spt->pitch * pt->cpp, 4) / pt->cpp;
- spt->total_height = 0;
+ spt->buffer_size = 0;
for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
- unsigned img_height;
-
- sp_miptree_set_level_info(spt, level, 1, x, y, width, height, 1);
-
- if (pt->compressed)
- img_height = MAX2(1, height/4);
- else
- img_height = align(height, align_h);
+ pt->width[level] = width;
+ pt->height[level] = height;
+ pt->depth[level] = depth;
+ spt->level_offset[level] = spt->buffer_size;
- /* Because the images are packed better, the final offset
- * might not be the maximal one:
- */
- spt->total_height = MAX2(spt->total_height, y + img_height);
-
- /* Layout_below: step right after second mipmap.
- */
- if (level == pt->first_level + 1) {
- x += align(width, align_w);
- }
- else {
- y += img_height;
- }
+ spt->buffer_size += ((pt->compressed) ? MAX2(1, height/4) : height) *
+ ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
+ width * pt->cpp;
width = minify(width);
height = minify(height);
+ depth = minify(depth);
}
}
-static const int initial_offsets[6][2] = {
- {0, 0},
- {0, 2},
- {1, 0},
- {1, 2},
- {1, 1},
- {1, 3}
-};
-
-static const int step_offsets[6][2] = {
- {0, 2},
- {0, 2},
- {-1, 2},
- {-1, 2},
- {-1, 1},
- {-1, 1}
-};
-
-
-
-static boolean
-softpipe_mipmap_tree_layout(struct pipe_context *pipe, struct softpipe_texture * spt)
-{
- struct pipe_texture *pt = &spt->base;
- unsigned level;
-
- switch (pt->target) {
- case PIPE_TEXTURE_CUBE:{
- const unsigned dim = pt->width[0];
- unsigned face;
- unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
-
- assert(lvlWidth == lvlHeight); /* cubemap images are square */
-
- /* Depending on the size of the largest images, pitch can be
- * determined either by the old-style packing of cubemap faces,
- * or the final row of 4x4, 2x2 and 1x1 faces below this.
- */
- if (dim > 32)
- spt->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
- else
- spt->pitch = 14 * 8;
-
- spt->total_height = dim * 4 + 4;
-
- /* Set all the levels to effectively occupy the whole rectangular region.
- */
- for (level = pt->first_level; level <= pt->last_level; level++) {
- sp_miptree_set_level_info(spt, level, 6,
- 0, 0,
- lvlWidth, lvlHeight, 1);
- lvlWidth /= 2;
- lvlHeight /= 2;
- }
-
-
- for (face = 0; face < 6; face++) {
- unsigned x = initial_offsets[face][0] * dim;
- unsigned y = initial_offsets[face][1] * dim;
- unsigned d = dim;
-
- if (dim == 4 && face >= 4) {
- y = spt->total_height - 4;
- x = (face - 4) * 8;
- }
- else if (dim < 4 && (face > 0 || pt->first_level > 0)) {
- y = spt->total_height - 4;
- x = face * 8;
- }
-
- for (level = pt->first_level; level <= pt->last_level; level++) {
- sp_miptree_set_image_offset(spt, level, face, x, y);
-
- d >>= 1;
-
- switch (d) {
- case 4:
- switch (face) {
- case PIPE_TEX_FACE_POS_X:
- case PIPE_TEX_FACE_NEG_X:
- x += step_offsets[face][0] * d;
- y += step_offsets[face][1] * d;
- break;
- case PIPE_TEX_FACE_POS_Y:
- case PIPE_TEX_FACE_NEG_Y:
- y += 12;
- x -= 8;
- break;
- case PIPE_TEX_FACE_POS_Z:
- case PIPE_TEX_FACE_NEG_Z:
- y = spt->total_height - 4;
- x = (face - 4) * 8;
- break;
- }
-
- case 2:
- y = spt->total_height - 4;
- x = 16 + face * 8;
- break;
-
- case 1:
- x += 48;
- break;
-
- default:
- x += step_offsets[face][0] * d;
- y += step_offsets[face][1] * d;
- break;
- }
- }
- }
- break;
- }
- case PIPE_TEXTURE_3D:{
- unsigned width = pt->width[0];
- unsigned height = pt->height[0];
- unsigned depth = pt->depth[0];
- unsigned pack_x_pitch, pack_x_nr;
- unsigned pack_y_pitch;
- unsigned level;
-
- spt->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
- spt->total_height = 0;
-
- pack_y_pitch = MAX2(pt->height[0], 2);
- pack_x_pitch = spt->pitch;
- pack_x_nr = 1;
-
- for (level = pt->first_level; level <= pt->last_level; level++) {
- unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
- int x = 0;
- int y = 0;
- unsigned q, j;
-
- sp_miptree_set_level_info(spt, level, nr_images,
- 0, spt->total_height,
- width, height, depth);
-
- for (q = 0; q < nr_images;) {
- for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
- sp_miptree_set_image_offset(spt, level, q, x, y);
- x += pack_x_pitch;
- }
-
- x = 0;
- y += pack_y_pitch;
- }
-
-
- spt->total_height += y;
-
- if (pack_x_pitch > 4) {
- pack_x_pitch >>= 1;
- pack_x_nr <<= 1;
- assert(pack_x_pitch * pack_x_nr <= spt->pitch);
- }
-
- if (pack_y_pitch > 2) {
- pack_y_pitch >>= 1;
- }
-
- width = minify(width);
- height = minify(height);
- depth = minify(depth);
- }
- break;
- }
-
- case PIPE_TEXTURE_1D:
- case PIPE_TEXTURE_2D:
-// case PIPE_TEXTURE_RECTANGLE:
- sp_miptree_layout_2d(spt);
- break;
- default:
- assert(0);
- break;
- }
-
- /*
- DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
- spt->pitch,
- spt->total_height, pt->cpp, spt->pitch * spt->total_height * pt->cpp);
- */
-
- return TRUE;
-}
-
void
softpipe_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
{
@@ -376,15 +89,13 @@ softpipe_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
memset(&spt->base + 1, 0,
sizeof(struct softpipe_texture) - sizeof(struct pipe_texture));
- if (softpipe_mipmap_tree_layout(pipe, spt)) {
- spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32, 0, 0);
+ softpipe_texture_layout(spt);
- if (spt->buffer) {
- pipe->winsys->buffer_data(pipe->winsys, spt->buffer,
- spt->pitch * spt->base.cpp *
- spt->total_height, NULL,
- PIPE_BUFFER_USAGE_PIXEL);
- }
+ spt->buffer = pipe->winsys->buffer_create(pipe->winsys, 32, 0, 0);
+
+ if (spt->buffer) {
+ pipe->winsys->buffer_data(pipe->winsys, spt->buffer, spt->buffer_size,
+ NULL, PIPE_BUFFER_USAGE_PIXEL);
}
if (!spt->buffer) {
@@ -408,7 +119,6 @@ softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
*/
if (--(*pt)->refcount <= 0) {
struct softpipe_texture *spt = softpipe_texture(*pt);
- uint i;
/*
DBG("%s deleting %p\n", __FUNCTION__, (void *) spt);
@@ -416,10 +126,6 @@ softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
pipe->winsys->buffer_reference(pipe->winsys, &spt->buffer, NULL);
- for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
- if (spt->image_offset[i])
- free(spt->image_offset[i]);
-
free(spt);
}
*pt = NULL;
diff --git a/src/mesa/pipe/softpipe/sp_texture.h b/src/mesa/pipe/softpipe/sp_texture.h
index 732064d986..e1a5db2791 100644
--- a/src/mesa/pipe/softpipe/sp_texture.h
+++ b/src/mesa/pipe/softpipe/sp_texture.h
@@ -10,29 +10,12 @@ struct softpipe_texture
{
struct pipe_texture base;
- /* Derived from the above:
- */
- unsigned pitch;
- unsigned depth_pitch; /* per-image on i945? */
- unsigned total_height;
-
- unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS];
-
- /* Explicitly store the offset of each image for each cube face or
- * depth value. Pretty much have to accept that hardware formats
- * are going to be so diverse that there is no unified way to
- * compute the offsets of depth/cube images within a mipmap level,
- * so have to store them as a lookup table:
- */
- unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; /**< array [depth] of offsets */
-
- /* Includes image offset tables:
- */
unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct pipe_buffer_handle *buffer;
+ unsigned long buffer_size;
};