2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **********************************************************************/
28 #include "pipe/p_format.h"
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
33 #include "brw_resource.h"
34 #include "brw_debug.h"
35 #include "brw_winsys.h"
37 /* Code to layout images in a mipmap tree for i965.
41 brw_tex_pitch_align (struct brw_texture *tex,
44 if (!tex->compressed) {
47 switch (tex->tiling) {
55 /* XXX: Untiled pitch alignment of 64 bytes for now to allow
56 * render-to-texture to work in all cases. This should
57 * probably be replaced at some point by some scheme to only
58 * do this when really necessary, for example standalone
59 * render target views.
65 pitch = align(pitch * tex->cpp, pitch_align);
74 brw_tex_alignment_unit(enum pipe_format pf,
78 case PIPE_FORMAT_DXT1_RGB:
79 case PIPE_FORMAT_DXT1_RGBA:
80 case PIPE_FORMAT_DXT3_RGBA:
81 case PIPE_FORMAT_DXT5_RGBA:
82 case PIPE_FORMAT_DXT1_SRGB:
83 case PIPE_FORMAT_DXT1_SRGBA:
84 case PIPE_FORMAT_DXT3_SRGBA:
85 case PIPE_FORMAT_DXT5_SRGBA:
99 brw_tex_set_level_info(struct brw_texture *tex,
103 GLuint w, GLuint h, GLuint d)
106 if (BRW_DEBUG & DEBUG_TEXTURE)
107 debug_printf("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
108 level, w, h, d, x, y, tex->level_offset[level]);
110 assert(tex->image_offset[level] == NULL);
111 assert(nr_images >= 1);
113 tex->level_offset[level] = (x + y * tex->pitch) * tex->cpp;
114 tex->nr_images[level] = nr_images;
116 tex->image_offset[level] = MALLOC(nr_images * sizeof(GLuint));
117 tex->image_offset[level][0] = 0;
122 brw_tex_set_image_offset(struct brw_texture *tex,
123 GLuint level, GLuint img,
127 assert((x == 0 && y == 0) || img != 0 || level != 0);
128 assert(img < tex->nr_images[level]);
130 if (BRW_DEBUG & DEBUG_TEXTURE)
131 debug_printf("%s level %d img %d pos %d,%d image_offset %x\n",
132 __FUNCTION__, level, img, x, y,
133 tex->image_offset[level][img]);
135 tex->image_offset[level][img] = (x + y * tex->pitch) * tex->cpp + offset;
140 static void brw_layout_2d( struct brw_texture *tex )
142 GLuint align_h = 2, align_w = 4;
146 GLuint width = tex->b.b.width0;
147 GLuint height = tex->b.b.height0;
149 tex->pitch = tex->b.b.width0;
150 brw_tex_alignment_unit(tex->b.b.format, &align_w, &align_h);
152 if (tex->compressed) {
153 tex->pitch = align(tex->b.b.width0, align_w);
156 /* May need to adjust pitch to accomodate the placement of
157 * the 2nd mipmap. This occurs when the alignment
158 * constraints of mipmap placement push the right edge of the
159 * 2nd mipmap out past the width of its parent.
161 if (tex->b.b.last_level > 0) {
164 if (tex->compressed) {
165 mip1_width = (align(u_minify(tex->b.b.width0, 1), align_w) +
166 align(u_minify(tex->b.b.width0, 2), align_w));
168 mip1_width = (align(u_minify(tex->b.b.width0, 1), align_w) +
169 u_minify(tex->b.b.width0, 2));
172 if (mip1_width > tex->pitch) {
173 tex->pitch = mip1_width;
177 /* Pitch must be a whole number of dwords, even though we
178 * express it in texels.
180 tex->pitch = brw_tex_pitch_align (tex, tex->pitch);
181 tex->total_height = 0;
183 for ( level = 0 ; level <= tex->b.b.last_level ; level++ ) {
186 brw_tex_set_level_info(tex, level, 1, x, y, width, height, 1);
189 img_height = MAX2(1, height/4);
191 img_height = align(height, align_h);
194 /* Because the images are packed better, the final offset
195 * might not be the maximal one:
197 tex->total_height = MAX2(tex->total_height, y + img_height);
199 /* Layout_below: step right after second mipmap.
202 x += align(width, align_w);
208 width = u_minify(width, 1);
209 height = u_minify(height, 1);
215 brw_layout_cubemap_idgng( struct brw_texture *tex )
217 GLuint align_h = 2, align_w = 4;
221 GLuint width = tex->b.b.width0;
222 GLuint height = tex->b.b.height0;
226 tex->pitch = tex->b.b.width0;
227 brw_tex_alignment_unit(tex->b.b.format, &align_w, &align_h);
228 y_pitch = align(height, align_h);
230 if (tex->compressed) {
231 tex->pitch = align(tex->b.b.width0, align_w);
234 if (tex->b.b.last_level != 0) {
237 if (tex->compressed) {
238 mip1_width = (align(u_minify(tex->b.b.width0, 1), align_w) +
239 align(u_minify(tex->b.b.width0, 2), align_w));
241 mip1_width = (align(u_minify(tex->b.b.width0, 1), align_w) +
242 u_minify(tex->b.b.width0, 2));
245 if (mip1_width > tex->pitch) {
246 tex->pitch = mip1_width;
250 tex->pitch = brw_tex_pitch_align(tex, tex->pitch);
252 if (tex->compressed) {
254 align(u_minify(y_pitch, 1), align_h) +
255 11 * align_h) / 4) * tex->pitch * tex->cpp;
257 tex->total_height = ((y_pitch +
258 align(u_minify(y_pitch, 1), align_h) +
259 11 * align_h) / 4) * 6;
262 align(u_minify(y_pitch, 1), align_h) +
263 11 * align_h) * tex->pitch * tex->cpp;
265 tex->total_height = (y_pitch +
266 align(u_minify(y_pitch, 1), align_h) +
270 for (level = 0; level <= tex->b.b.last_level; level++) {
272 GLuint nr_images = 6;
275 brw_tex_set_level_info(tex, level, nr_images, x, y, width, height, 1);
277 for (q = 0; q < nr_images; q++)
278 brw_tex_set_image_offset(tex, level, q, x, y, q * qpitch);
281 img_height = MAX2(1, height/4);
283 img_height = align(height, align_h);
286 x += align(width, align_w);
292 width = u_minify(width, 1);
293 height = u_minify(height, 1);
301 brw_layout_3d_cube( struct brw_texture *tex )
303 GLuint width = tex->b.b.width0;
304 GLuint height = tex->b.b.height0;
305 GLuint depth = tex->b.b.depth0;
306 GLuint pack_x_pitch, pack_x_nr;
312 tex->total_height = 0;
313 brw_tex_alignment_unit(tex->b.b.format, &align_w, &align_h);
315 if (tex->compressed) {
316 tex->pitch = align(width, align_w);
317 pack_y_pitch = (height + 3) / 4;
319 tex->pitch = brw_tex_pitch_align(tex, tex->b.b.width0);
320 pack_y_pitch = align(tex->b.b.height0, align_h);
323 pack_x_pitch = width;
326 for (level = 0 ; level <= tex->b.b.last_level ; level++) {
327 GLuint nr_images = tex->b.b.target == PIPE_TEXTURE_3D ? depth : 6;
332 brw_tex_set_level_info(tex, level, nr_images,
333 0, tex->total_height,
334 width, height, depth);
336 for (q = 0; q < nr_images;) {
337 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
338 brw_tex_set_image_offset(tex, level, q, x, y, 0);
347 tex->total_height += y;
348 width = u_minify(width, 1);
349 height = u_minify(height, 1);
350 depth = u_minify(depth, 1);
352 if (tex->compressed) {
353 pack_y_pitch = (height + 3) / 4;
355 if (pack_x_pitch > align(width, align_w)) {
356 pack_x_pitch = align(width, align_w);
360 if (pack_x_pitch > 4) {
363 assert(pack_x_pitch * pack_x_nr <= tex->pitch);
366 if (pack_y_pitch > 2) {
368 pack_y_pitch = align(pack_y_pitch, align_h);
373 /* The 965's sampler lays cachelines out according to how accesses
374 * in the texture surfaces run, so they may be "vertical" through
375 * memory. As a result, the docs say in Surface Padding Requirements:
376 * Sampling Engine Surfaces that two extra rows of padding are required.
378 if (tex->b.b.target == PIPE_TEXTURE_CUBE)
379 tex->total_height += 2;
386 GLboolean brw_texture_layout(struct brw_screen *brw_screen,
387 struct brw_texture *tex )
389 switch (tex->b.b.target) {
390 case PIPE_TEXTURE_CUBE:
391 if (brw_screen->chipset.is_igdng)
392 brw_layout_cubemap_idgng( tex );
394 brw_layout_3d_cube( tex );
397 case PIPE_TEXTURE_3D:
398 brw_layout_3d_cube( tex );
402 brw_layout_2d( tex );
406 if (BRW_DEBUG & DEBUG_TEXTURE)
407 debug_printf("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
411 tex->pitch * tex->total_height * tex->cpp );