From ede7b00b59b37f078de0663918c0c84d572c27e8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michel=20D=C3=A4nzer?= Date: Thu, 10 Jan 2008 10:03:47 +0100 Subject: [PATCH] softpipe: Simplify texture memory layout. --- src/mesa/pipe/softpipe/sp_surface.c | 27 +-- src/mesa/pipe/softpipe/sp_texture.c | 330 ++-------------------------- src/mesa/pipe/softpipe/sp_texture.h | 19 +- 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 5259fbfd207..ece30e36ec4 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 44512e4281e..e5e6bfe01b8 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 732064d9867..e1a5db27911 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; }; -- 2.30.2