diff options
Diffstat (limited to 'src/gallium/drivers/i965/brw_screen_tex_layout.c')
-rw-r--r-- | src/gallium/drivers/i965/brw_screen_tex_layout.c | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/src/gallium/drivers/i965/brw_screen_tex_layout.c b/src/gallium/drivers/i965/brw_screen_tex_layout.c new file mode 100644 index 0000000000..894f4bea40 --- /dev/null +++ b/src/gallium/drivers/i965/brw_screen_tex_layout.c @@ -0,0 +1,414 @@ +/* + Copyright (C) Intel Corp. 2006. All Rights Reserved. + Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + develop this 3D driver. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + **********************************************************************/ + +#include "pipe/p_format.h" + +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "brw_screen.h" +#include "brw_debug.h" +#include "brw_winsys.h" + +/* Code to layout images in a mipmap tree for i965. + */ + +static int +brw_tex_pitch_align (struct brw_texture *tex, + int pitch) +{ + if (!tex->compressed) { + int pitch_align; + + switch (tex->tiling) { + case BRW_TILING_X: + pitch_align = 512; + break; + case BRW_TILING_Y: + pitch_align = 128; + break; + default: + /* XXX: Untiled pitch alignment of 64 bytes for now to allow + * render-to-texture to work in all cases. This should + * probably be replaced at some point by some scheme to only + * do this when really necessary, for example standalone + * render target views. + */ + pitch_align = 64; + break; + } + + pitch = align(pitch * tex->cpp, pitch_align); + pitch /= tex->cpp; + } + + return pitch; +} + + +static void +brw_tex_alignment_unit(enum pipe_format pf, + GLuint *w, GLuint *h) +{ + switch (pf) { + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: + case PIPE_FORMAT_DXT1_SRGB: + case PIPE_FORMAT_DXT1_SRGBA: + case PIPE_FORMAT_DXT3_SRGBA: + case PIPE_FORMAT_DXT5_SRGBA: + *w = 4; + *h = 4; + break; + + default: + *w = 4; + *h = 2; + break; + } +} + + +static void +brw_tex_set_level_info(struct brw_texture *tex, + GLuint level, + GLuint nr_images, + GLuint x, GLuint y, + GLuint w, GLuint h, GLuint d) +{ + + if (BRW_DEBUG & DEBUG_TEXTURE) + debug_printf("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, + level, w, h, d, x, y, tex->level_offset[level]); + + assert(tex->image_offset[level] == NULL); + assert(nr_images >= 1); + + tex->level_offset[level] = (x + y * tex->pitch) * tex->cpp; + tex->nr_images[level] = nr_images; + + tex->image_offset[level] = MALLOC(nr_images * sizeof(GLuint)); + tex->image_offset[level][0] = 0; +} + + +static void +brw_tex_set_image_offset(struct brw_texture *tex, + GLuint level, GLuint img, + GLuint x, GLuint y, + GLuint offset) +{ + assert((x == 0 && y == 0) || img != 0 || level != 0); + assert(img < tex->nr_images[level]); + + if (BRW_DEBUG & DEBUG_TEXTURE) + debug_printf("%s level %d img %d pos %d,%d image_offset %x\n", + __FUNCTION__, level, img, x, y, + tex->image_offset[level][img]); + + tex->image_offset[level][img] = (x + y * tex->pitch) * tex->cpp + offset; +} + + + +static void brw_layout_2d( struct brw_texture *tex ) +{ + GLuint align_h = 2, align_w = 4; + GLuint level; + GLuint x = 0; + GLuint y = 0; + GLuint width = tex->base.width0; + GLuint height = tex->base.height0; + + tex->pitch = tex->base.width0; + brw_tex_alignment_unit(tex->base.format, &align_w, &align_h); + + if (tex->compressed) { + tex->pitch = align(tex->base.width0, align_w); + } + + /* 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 (tex->base.last_level > 0) { + GLuint mip1_width; + + if (tex->compressed) { + mip1_width = (align(u_minify(tex->base.width0, 1), align_w) + + align(u_minify(tex->base.width0, 2), align_w)); + } else { + mip1_width = (align(u_minify(tex->base.width0, 1), align_w) + + u_minify(tex->base.width0, 2)); + } + + if (mip1_width > tex->pitch) { + tex->pitch = mip1_width; + } + } + + /* Pitch must be a whole number of dwords, even though we + * express it in texels. + */ + tex->pitch = brw_tex_pitch_align (tex, tex->pitch); + tex->total_height = 0; + + for ( level = 0 ; level <= tex->base.last_level ; level++ ) { + GLuint img_height; + + brw_tex_set_level_info(tex, level, 1, x, y, width, height, 1); + + if (tex->compressed) + img_height = MAX2(1, height/4); + else + img_height = align(height, align_h); + + + /* Because the images are packed better, the final offset + * might not be the maximal one: + */ + tex->total_height = MAX2(tex->total_height, y + img_height); + + /* Layout_below: step right after second mipmap. + */ + if (level == 1) { + x += align(width, align_w); + } + else { + y += img_height; + } + + width = u_minify(width, 1); + height = u_minify(height, 1); + } +} + + +static boolean +brw_layout_cubemap_idgng( struct brw_texture *tex ) +{ + GLuint align_h = 2, align_w = 4; + GLuint level; + GLuint x = 0; + GLuint y = 0; + GLuint width = tex->base.width0; + GLuint height = tex->base.height0; + GLuint qpitch = 0; + GLuint y_pitch = 0; + + tex->pitch = tex->base.width0; + brw_tex_alignment_unit(tex->base.format, &align_w, &align_h); + y_pitch = align(height, align_h); + + if (tex->compressed) { + tex->pitch = align(tex->base.width0, align_w); + } + + if (tex->base.last_level != 0) { + GLuint mip1_width; + + if (tex->compressed) { + mip1_width = (align(u_minify(tex->base.width0, 1), align_w) + + align(u_minify(tex->base.width0, 2), align_w)); + } else { + mip1_width = (align(u_minify(tex->base.width0, 1), align_w) + + u_minify(tex->base.width0, 2)); + } + + if (mip1_width > tex->pitch) { + tex->pitch = mip1_width; + } + } + + tex->pitch = brw_tex_pitch_align(tex, tex->pitch); + + if (tex->compressed) { + qpitch = ((y_pitch + + align(u_minify(y_pitch, 1), align_h) + + 11 * align_h) / 4) * tex->pitch * tex->cpp; + + tex->total_height = ((y_pitch + + align(u_minify(y_pitch, 1), align_h) + + 11 * align_h) / 4) * 6; + } else { + qpitch = (y_pitch + + align(u_minify(y_pitch, 1), align_h) + + 11 * align_h) * tex->pitch * tex->cpp; + + tex->total_height = (y_pitch + + align(u_minify(y_pitch, 1), align_h) + + 11 * align_h) * 6; + } + + for (level = 0; level <= tex->base.last_level; level++) { + GLuint img_height; + GLuint nr_images = 6; + GLuint q = 0; + + brw_tex_set_level_info(tex, level, nr_images, x, y, width, height, 1); + + for (q = 0; q < nr_images; q++) + brw_tex_set_image_offset(tex, level, q, x, y, q * qpitch); + + if (tex->compressed) + img_height = MAX2(1, height/4); + else + img_height = align(height, align_h); + + if (level == 1) { + x += align(width, align_w); + } + else { + y += img_height; + } + + width = u_minify(width, 1); + height = u_minify(height, 1); + } + + return TRUE; +} + + +static boolean +brw_layout_3d_cube( struct brw_texture *tex ) +{ + GLuint width = tex->base.width0; + GLuint height = tex->base.height0; + GLuint depth = tex->base.depth0; + GLuint pack_x_pitch, pack_x_nr; + GLuint pack_y_pitch; + GLuint level; + GLuint align_h = 2; + GLuint align_w = 4; + + tex->total_height = 0; + brw_tex_alignment_unit(tex->base.format, &align_w, &align_h); + + if (tex->compressed) { + tex->pitch = align(width, align_w); + pack_y_pitch = (height + 3) / 4; + } else { + tex->pitch = brw_tex_pitch_align(tex, tex->base.width0); + pack_y_pitch = align(tex->base.height0, align_h); + } + + pack_x_pitch = width; + pack_x_nr = 1; + + for (level = 0 ; level <= tex->base.last_level ; level++) { + GLuint nr_images = tex->base.target == PIPE_TEXTURE_3D ? depth : 6; + GLint x = 0; + GLint y = 0; + GLint q, j; + + brw_tex_set_level_info(tex, level, nr_images, + 0, tex->total_height, + width, height, depth); + + for (q = 0; q < nr_images;) { + for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) { + brw_tex_set_image_offset(tex, level, q, x, y, 0); + x += pack_x_pitch; + } + + x = 0; + y += pack_y_pitch; + } + + + tex->total_height += y; + width = u_minify(width, 1); + height = u_minify(height, 1); + depth = u_minify(depth, 1); + + if (tex->compressed) { + pack_y_pitch = (height + 3) / 4; + + if (pack_x_pitch > align(width, align_w)) { + pack_x_pitch = align(width, align_w); + pack_x_nr <<= 1; + } + } else { + if (pack_x_pitch > 4) { + pack_x_pitch >>= 1; + pack_x_nr <<= 1; + assert(pack_x_pitch * pack_x_nr <= tex->pitch); + } + + if (pack_y_pitch > 2) { + pack_y_pitch >>= 1; + pack_y_pitch = align(pack_y_pitch, align_h); + } + } + } + + /* The 965's sampler lays cachelines out according to how accesses + * in the texture surfaces run, so they may be "vertical" through + * memory. As a result, the docs say in Surface Padding Requirements: + * Sampling Engine Surfaces that two extra rows of padding are required. + */ + if (tex->base.target == PIPE_TEXTURE_CUBE) + tex->total_height += 2; + + return TRUE; +} + + + +GLboolean brw_texture_layout(struct brw_screen *brw_screen, + struct brw_texture *tex ) +{ + switch (tex->base.target) { + case PIPE_TEXTURE_CUBE: + if (brw_screen->chipset.is_igdng) + brw_layout_cubemap_idgng( tex ); + else + brw_layout_3d_cube( tex ); + break; + + case PIPE_TEXTURE_3D: + brw_layout_3d_cube( tex ); + break; + + default: + brw_layout_2d( tex ); + break; + } + + if (BRW_DEBUG & DEBUG_TEXTURE) + debug_printf("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__, + tex->pitch, + tex->total_height, + tex->cpp, + tex->pitch * tex->total_height * tex->cpp ); + + return GL_TRUE; +} |