summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/i965/brw_screen_tex_layout.c
diff options
context:
space:
mode:
authorKeith Whitwell <keithw@vmware.com>2009-11-01 14:32:50 +0000
committerKeith Whitwell <keithw@vmware.com>2009-11-01 14:33:01 +0000
commit15e7a3b8bb6771d24e5bde7805ea394f9ce0a3ec (patch)
tree799656b83f902dd40895ac859d12dba5e50d4341 /src/gallium/drivers/i965/brw_screen_tex_layout.c
parent39448a9aa061291f4253ee2a1a42e2488e14233c (diff)
i965g: more files compiling
Diffstat (limited to 'src/gallium/drivers/i965/brw_screen_tex_layout.c')
-rw-r--r--src/gallium/drivers/i965/brw_screen_tex_layout.c387
1 files changed, 387 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..8377d30564
--- /dev/null
+++ b/src/gallium/drivers/i965/brw_screen_tex_layout.c
@@ -0,0 +1,387 @@
+
+#include "pipe/p_format.h"
+
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "brw_screen.h"
+#include "brw_debug.h"
+
+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)
+{
+ assert(tex->base.width[level] == w);
+ assert(tex->base.height[level] == h);
+ assert(tex->base.depth[level] == d);
+ assert(tex->image_offset[level] == NULL);
+ assert(nr_images >= 1);
+
+ 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]);
+
+
+ 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.width[0];
+ GLuint height = tex->base.height[0];
+
+ tex->pitch = tex->base.width[0];
+ brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
+
+ if (tex->compressed) {
+ tex->pitch = align(tex->base.width[0], 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(minify(tex->base.width[0]), align_w)
+ + align(minify(minify(tex->base.width[0])), align_w);
+ } else {
+ mip1_width = align(minify(tex->base.width[0]), align_w)
+ + minify(minify(tex->base.width[0]));
+ }
+
+ 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 = minify(width);
+ height = minify(height);
+ }
+}
+
+
+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.width[0];
+ GLuint height = tex->base.height[0];
+ GLuint qpitch = 0;
+ GLuint y_pitch = 0;
+
+ tex->pitch = tex->base.width[0];
+ 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.width[0], align_w);
+ }
+
+ if (tex->base.last_level != 0) {
+ GLuint mip1_width;
+
+ if (tex->compressed) {
+ mip1_width = (align(minify(tex->base.width[0]), align_w) +
+ align(minify(minify(tex->base.width[0])), align_w));
+ } else {
+ mip1_width = (align(minify(tex->base.width[0]), align_w) +
+ minify(minify(tex->base.width[0])));
+ }
+
+ 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(minify(y_pitch), align_h) +
+ 11 * align_h) / 4) * tex->pitch * tex->cpp;
+
+ tex->total_height = ((y_pitch +
+ align(minify(y_pitch), align_h) +
+ 11 * align_h) / 4) * 6;
+ } else {
+ qpitch = (y_pitch +
+ align(minify(y_pitch), align_h) +
+ 11 * align_h) * tex->pitch * tex->cpp;
+
+ tex->total_height = (y_pitch +
+ align(minify(y_pitch), 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 = minify(width);
+ height = minify(height);
+ }
+
+ return TRUE;
+}
+
+
+static boolean
+brw_layout_3d_cube( struct brw_texture *tex )
+{
+ GLuint width = tex->base.width[0];
+ GLuint height = tex->base.height[0];
+ GLuint depth = tex->base.depth[0];
+ 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.width[0]);
+ pack_y_pitch = align(tex->base.height[0], 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 = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+
+ 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;
+}