i965g: more files compiling
[mesa.git] / src / gallium / drivers / i965 / brw_screen_tex_layout.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
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:
13
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.
17
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.
25
26 **********************************************************************/
27
28 #include "pipe/p_format.h"
29
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
32
33 #include "brw_screen.h"
34 #include "brw_debug.h"
35
36 /* Code to layout images in a mipmap tree for i965.
37 */
38
39 static int
40 brw_tex_pitch_align (struct brw_texture *tex,
41 int pitch)
42 {
43 if (!tex->compressed) {
44 int pitch_align;
45
46 switch (tex->tiling) {
47 case BRW_TILING_X:
48 pitch_align = 512;
49 break;
50 case BRW_TILING_Y:
51 pitch_align = 128;
52 break;
53 default:
54 /* XXX: Untiled pitch alignment of 64 bytes for now to allow
55 * render-to-texture to work in all cases. This should
56 * probably be replaced at some point by some scheme to only
57 * do this when really necessary, for example standalone
58 * render target views.
59 */
60 pitch_align = 64;
61 break;
62 }
63
64 pitch = align(pitch * tex->cpp, pitch_align);
65 pitch /= tex->cpp;
66 }
67
68 return pitch;
69 }
70
71
72 static void
73 brw_tex_alignment_unit(enum pipe_format pf,
74 GLuint *w, GLuint *h)
75 {
76 switch (pf) {
77 case PIPE_FORMAT_DXT1_RGB:
78 case PIPE_FORMAT_DXT1_RGBA:
79 case PIPE_FORMAT_DXT3_RGBA:
80 case PIPE_FORMAT_DXT5_RGBA:
81 case PIPE_FORMAT_DXT1_SRGB:
82 case PIPE_FORMAT_DXT1_SRGBA:
83 case PIPE_FORMAT_DXT3_SRGBA:
84 case PIPE_FORMAT_DXT5_SRGBA:
85 *w = 4;
86 *h = 4;
87 break;
88
89 default:
90 *w = 4;
91 *h = 2;
92 break;
93 }
94 }
95
96
97 static void
98 brw_tex_set_level_info(struct brw_texture *tex,
99 GLuint level,
100 GLuint nr_images,
101 GLuint x, GLuint y,
102 GLuint w, GLuint h, GLuint d)
103 {
104 assert(tex->base.width[level] == w);
105 assert(tex->base.height[level] == h);
106 assert(tex->base.depth[level] == d);
107 assert(tex->image_offset[level] == NULL);
108 assert(nr_images >= 1);
109
110 if (BRW_DEBUG & DEBUG_TEXTURE)
111 debug_printf("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
112 level, w, h, d, x, y, tex->level_offset[level]);
113
114
115 tex->level_offset[level] = (x + y * tex->pitch) * tex->cpp;
116 tex->nr_images[level] = nr_images;
117
118 tex->image_offset[level] = MALLOC(nr_images * sizeof(GLuint));
119 tex->image_offset[level][0] = 0;
120 }
121
122
123 static void
124 brw_tex_set_image_offset(struct brw_texture *tex,
125 GLuint level, GLuint img,
126 GLuint x, GLuint y,
127 GLuint offset)
128 {
129 assert((x == 0 && y == 0) || img != 0 || level != 0);
130 assert(img < tex->nr_images[level]);
131
132 if (BRW_DEBUG & DEBUG_TEXTURE)
133 debug_printf("%s level %d img %d pos %d,%d image_offset %x\n",
134 __FUNCTION__, level, img, x, y,
135 tex->image_offset[level][img]);
136
137 tex->image_offset[level][img] = (x + y * tex->pitch) * tex->cpp + offset;
138 }
139
140
141
142 static void brw_layout_2d( struct brw_texture *tex )
143 {
144 GLuint align_h = 2, align_w = 4;
145 GLuint level;
146 GLuint x = 0;
147 GLuint y = 0;
148 GLuint width = tex->base.width[0];
149 GLuint height = tex->base.height[0];
150
151 tex->pitch = tex->base.width[0];
152 brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
153
154 if (tex->compressed) {
155 tex->pitch = align(tex->base.width[0], align_w);
156 }
157
158 /* May need to adjust pitch to accomodate the placement of
159 * the 2nd mipmap. This occurs when the alignment
160 * constraints of mipmap placement push the right edge of the
161 * 2nd mipmap out past the width of its parent.
162 */
163 if (tex->base.last_level > 0) {
164 GLuint mip1_width;
165
166 if (tex->compressed) {
167 mip1_width = align(minify(tex->base.width[0]), align_w)
168 + align(minify(minify(tex->base.width[0])), align_w);
169 } else {
170 mip1_width = align(minify(tex->base.width[0]), align_w)
171 + minify(minify(tex->base.width[0]));
172 }
173
174 if (mip1_width > tex->pitch) {
175 tex->pitch = mip1_width;
176 }
177 }
178
179 /* Pitch must be a whole number of dwords, even though we
180 * express it in texels.
181 */
182 tex->pitch = brw_tex_pitch_align (tex, tex->pitch);
183 tex->total_height = 0;
184
185 for ( level = 0 ; level <= tex->base.last_level ; level++ ) {
186 GLuint img_height;
187
188 brw_tex_set_level_info(tex, level, 1, x, y, width, height, 1);
189
190 if (tex->compressed)
191 img_height = MAX2(1, height/4);
192 else
193 img_height = align(height, align_h);
194
195
196 /* Because the images are packed better, the final offset
197 * might not be the maximal one:
198 */
199 tex->total_height = MAX2(tex->total_height, y + img_height);
200
201 /* Layout_below: step right after second mipmap.
202 */
203 if (level == 1) {
204 x += align(width, align_w);
205 }
206 else {
207 y += img_height;
208 }
209
210 width = minify(width);
211 height = minify(height);
212 }
213 }
214
215
216 static boolean
217 brw_layout_cubemap_idgng( struct brw_texture *tex )
218 {
219 GLuint align_h = 2, align_w = 4;
220 GLuint level;
221 GLuint x = 0;
222 GLuint y = 0;
223 GLuint width = tex->base.width[0];
224 GLuint height = tex->base.height[0];
225 GLuint qpitch = 0;
226 GLuint y_pitch = 0;
227
228 tex->pitch = tex->base.width[0];
229 brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
230 y_pitch = align(height, align_h);
231
232 if (tex->compressed) {
233 tex->pitch = align(tex->base.width[0], align_w);
234 }
235
236 if (tex->base.last_level != 0) {
237 GLuint mip1_width;
238
239 if (tex->compressed) {
240 mip1_width = (align(minify(tex->base.width[0]), align_w) +
241 align(minify(minify(tex->base.width[0])), align_w));
242 } else {
243 mip1_width = (align(minify(tex->base.width[0]), align_w) +
244 minify(minify(tex->base.width[0])));
245 }
246
247 if (mip1_width > tex->pitch) {
248 tex->pitch = mip1_width;
249 }
250 }
251
252 tex->pitch = brw_tex_pitch_align(tex, tex->pitch);
253
254 if (tex->compressed) {
255 qpitch = ((y_pitch +
256 align(minify(y_pitch), align_h) +
257 11 * align_h) / 4) * tex->pitch * tex->cpp;
258
259 tex->total_height = ((y_pitch +
260 align(minify(y_pitch), align_h) +
261 11 * align_h) / 4) * 6;
262 } else {
263 qpitch = (y_pitch +
264 align(minify(y_pitch), align_h) +
265 11 * align_h) * tex->pitch * tex->cpp;
266
267 tex->total_height = (y_pitch +
268 align(minify(y_pitch), align_h) +
269 11 * align_h) * 6;
270 }
271
272 for (level = 0; level <= tex->base.last_level; level++) {
273 GLuint img_height;
274 GLuint nr_images = 6;
275 GLuint q = 0;
276
277 brw_tex_set_level_info(tex, level, nr_images, x, y, width, height, 1);
278
279 for (q = 0; q < nr_images; q++)
280 brw_tex_set_image_offset(tex, level, q, x, y, q * qpitch);
281
282 if (tex->compressed)
283 img_height = MAX2(1, height/4);
284 else
285 img_height = align(height, align_h);
286
287 if (level == 1) {
288 x += align(width, align_w);
289 }
290 else {
291 y += img_height;
292 }
293
294 width = minify(width);
295 height = minify(height);
296 }
297
298 return TRUE;
299 }
300
301
302 static boolean
303 brw_layout_3d_cube( struct brw_texture *tex )
304 {
305 GLuint width = tex->base.width[0];
306 GLuint height = tex->base.height[0];
307 GLuint depth = tex->base.depth[0];
308 GLuint pack_x_pitch, pack_x_nr;
309 GLuint pack_y_pitch;
310 GLuint level;
311 GLuint align_h = 2;
312 GLuint align_w = 4;
313
314 tex->total_height = 0;
315 brw_tex_alignment_unit(tex->base.format, &align_w, &align_h);
316
317 if (tex->compressed) {
318 tex->pitch = align(width, align_w);
319 pack_y_pitch = (height + 3) / 4;
320 } else {
321 tex->pitch = brw_tex_pitch_align(tex, tex->base.width[0]);
322 pack_y_pitch = align(tex->base.height[0], align_h);
323 }
324
325 pack_x_pitch = width;
326 pack_x_nr = 1;
327
328 for (level = 0 ; level <= tex->base.last_level ; level++) {
329 GLuint nr_images = tex->base.target == PIPE_TEXTURE_3D ? depth : 6;
330 GLint x = 0;
331 GLint y = 0;
332 GLint q, j;
333
334 brw_tex_set_level_info(tex, level, nr_images,
335 0, tex->total_height,
336 width, height, depth);
337
338 for (q = 0; q < nr_images;) {
339 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
340 brw_tex_set_image_offset(tex, level, q, x, y, 0);
341 x += pack_x_pitch;
342 }
343
344 x = 0;
345 y += pack_y_pitch;
346 }
347
348
349 tex->total_height += y;
350 width = minify(width);
351 height = minify(height);
352 depth = minify(depth);
353
354 if (tex->compressed) {
355 pack_y_pitch = (height + 3) / 4;
356
357 if (pack_x_pitch > align(width, align_w)) {
358 pack_x_pitch = align(width, align_w);
359 pack_x_nr <<= 1;
360 }
361 } else {
362 if (pack_x_pitch > 4) {
363 pack_x_pitch >>= 1;
364 pack_x_nr <<= 1;
365 assert(pack_x_pitch * pack_x_nr <= tex->pitch);
366 }
367
368 if (pack_y_pitch > 2) {
369 pack_y_pitch >>= 1;
370 pack_y_pitch = align(pack_y_pitch, align_h);
371 }
372 }
373 }
374
375 /* The 965's sampler lays cachelines out according to how accesses
376 * in the texture surfaces run, so they may be "vertical" through
377 * memory. As a result, the docs say in Surface Padding Requirements:
378 * Sampling Engine Surfaces that two extra rows of padding are required.
379 */
380 if (tex->base.target == PIPE_TEXTURE_CUBE)
381 tex->total_height += 2;
382
383 return TRUE;
384 }
385
386
387
388 GLboolean brw_texture_layout(struct brw_screen *brw_screen,
389 struct brw_texture *tex )
390 {
391 switch (tex->base.target) {
392 case PIPE_TEXTURE_CUBE:
393 if (brw_screen->chipset.is_igdng)
394 brw_layout_cubemap_idgng( tex );
395 else
396 brw_layout_3d_cube( tex );
397 break;
398
399 case PIPE_TEXTURE_3D:
400 brw_layout_3d_cube( tex );
401 break;
402
403 default:
404 brw_layout_2d( tex );
405 break;
406 }
407
408 if (BRW_DEBUG & DEBUG_TEXTURE)
409 debug_printf("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
410 tex->pitch,
411 tex->total_height,
412 tex->cpp,
413 tex->pitch * tex->total_height * tex->cpp );
414
415 return GL_TRUE;
416 }