Merge branch '7.8'
[mesa.git] / src / mesa / drivers / dri / i915 / i915_tex_layout.c
1 /**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /** @file i915_tex_layout.c
29 * Code to layout images in a mipmap tree for i830M-GM915 and G945 and beyond.
30 */
31
32 #include "intel_mipmap_tree.h"
33 #include "intel_tex_layout.h"
34 #include "main/macros.h"
35 #include "intel_context.h"
36
37 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
38
39 static GLint initial_offsets[6][2] = {
40 [FACE_POS_X] = {0, 0},
41 [FACE_POS_Y] = {1, 0},
42 [FACE_POS_Z] = {1, 1},
43 [FACE_NEG_X] = {0, 2},
44 [FACE_NEG_Y] = {1, 2},
45 [FACE_NEG_Z] = {1, 3},
46 };
47
48
49 static GLint step_offsets[6][2] = {
50 [FACE_POS_X] = {0, 2},
51 [FACE_POS_Y] = {-1, 2},
52 [FACE_POS_Z] = {-1, 1},
53 [FACE_NEG_X] = {0, 2},
54 [FACE_NEG_Y] = {-1, 2},
55 [FACE_NEG_Z] = {-1, 1},
56 };
57
58
59 static GLint bottom_offsets[6] = {
60 [FACE_POS_X] = 16 + 0 * 8,
61 [FACE_POS_Y] = 16 + 1 * 8,
62 [FACE_POS_Z] = 16 + 2 * 8,
63 [FACE_NEG_X] = 16 + 3 * 8,
64 [FACE_NEG_Y] = 16 + 4 * 8,
65 [FACE_NEG_Z] = 16 + 5 * 8,
66 };
67
68
69 /**
70 * Cube texture map layout for i830M-GM915.
71 *
72 * Hardware layout looks like:
73 *
74 * +-------+-------+
75 * | | |
76 * | | |
77 * | | |
78 * | +x | +y |
79 * | | |
80 * | | |
81 * | | |
82 * | | |
83 * +---+---+-------+
84 * | | | |
85 * | +x| +y| |
86 * | | | |
87 * | | | |
88 * +-+-+---+ +z |
89 * | | | | |
90 * +-+-+ +z| |
91 * | | | |
92 * +-+-+---+-------+
93 * | | |
94 * | | |
95 * | | |
96 * | -x | -y |
97 * | | |
98 * | | |
99 * | | |
100 * | | |
101 * +---+---+-------+
102 * | | | |
103 * | -x| -y| |
104 * | | | |
105 * | | | |
106 * +-+-+---+ -z |
107 * | | | | |
108 * +-+-+ -z| |
109 * | | | |
110 * +-+---+-------+
111 *
112 */
113 static void
114 i915_miptree_layout_cube(struct intel_context *intel,
115 struct intel_mipmap_tree * mt,
116 uint32_t tiling)
117 {
118 const GLuint dim = mt->width0;
119 GLuint face;
120 GLuint lvlWidth = mt->width0, lvlHeight = mt->height0;
121 GLint level;
122
123 assert(lvlWidth == lvlHeight); /* cubemap images are square */
124
125 /* double pitch for cube layouts */
126 mt->total_width = dim * 2;
127 mt->total_height = dim * 4;
128
129 for (level = mt->first_level; level <= mt->last_level; level++) {
130 intel_miptree_set_level_info(mt, level, 6,
131 0, 0,
132 lvlWidth, lvlHeight,
133 1);
134 lvlWidth /= 2;
135 lvlHeight /= 2;
136 }
137
138 for (face = 0; face < 6; face++) {
139 GLuint x = initial_offsets[face][0] * dim;
140 GLuint y = initial_offsets[face][1] * dim;
141 GLuint d = dim;
142
143 for (level = mt->first_level; level <= mt->last_level; level++) {
144 intel_miptree_set_image_offset(mt, level, face, x, y);
145
146 if (d == 0)
147 printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
148 face, level, mt->first_level, mt->last_level);
149
150 d >>= 1;
151 x += step_offsets[face][0] * d;
152 y += step_offsets[face][1] * d;
153 }
154 }
155 }
156
157 static void
158 i915_miptree_layout_3d(struct intel_context *intel,
159 struct intel_mipmap_tree * mt,
160 uint32_t tiling)
161 {
162 GLuint width = mt->width0;
163 GLuint height = mt->height0;
164 GLuint depth = mt->depth0;
165 GLuint stack_height = 0;
166 GLint level;
167
168 /* Calculate the size of a single slice. */
169 mt->total_width = mt->width0;
170
171 /* XXX: hardware expects/requires 9 levels at minimum. */
172 for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) {
173 intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height,
174 width, height, depth);
175
176 stack_height += MAX2(2, height);
177
178 width = minify(width);
179 height = minify(height);
180 depth = minify(depth);
181 }
182
183 /* Fixup depth image_offsets: */
184 depth = mt->depth0;
185 for (level = mt->first_level; level <= mt->last_level; level++) {
186 GLuint i;
187 for (i = 0; i < depth; i++) {
188 intel_miptree_set_image_offset(mt, level, i,
189 0, i * stack_height);
190 }
191
192 depth = minify(depth);
193 }
194
195 /* Multiply slice size by texture depth for total size. It's
196 * remarkable how wasteful of memory the i915 texture layouts
197 * are. They are largely fixed in the i945.
198 */
199 mt->total_height = stack_height * mt->depth0;
200 }
201
202 static void
203 i915_miptree_layout_2d(struct intel_context *intel,
204 struct intel_mipmap_tree * mt,
205 uint32_t tiling)
206 {
207 GLuint width = mt->width0;
208 GLuint height = mt->height0;
209 GLuint img_height;
210 GLint level;
211
212 mt->total_width = mt->width0;
213 mt->total_height = 0;
214
215 for (level = mt->first_level; level <= mt->last_level; level++) {
216 intel_miptree_set_level_info(mt, level, 1,
217 0, mt->total_height,
218 width, height, 1);
219
220 if (mt->compressed)
221 img_height = MAX2(1, height / 4);
222 else
223 img_height = (MAX2(2, height) + 1) & ~1;
224
225 mt->total_height += img_height;
226
227 width = minify(width);
228 height = minify(height);
229 }
230 }
231
232 GLboolean
233 i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt,
234 uint32_t tiling)
235 {
236 switch (mt->target) {
237 case GL_TEXTURE_CUBE_MAP:
238 i915_miptree_layout_cube(intel, mt, tiling);
239 break;
240 case GL_TEXTURE_3D:
241 i915_miptree_layout_3d(intel, mt, tiling);
242 break;
243 case GL_TEXTURE_1D:
244 case GL_TEXTURE_2D:
245 case GL_TEXTURE_RECTANGLE_ARB:
246 i915_miptree_layout_2d(intel, mt, tiling);
247 break;
248 default:
249 _mesa_problem(NULL, "Unexpected tex target in i915_miptree_layout()");
250 break;
251 }
252
253 DBG("%s: %dx%dx%d\n", __FUNCTION__,
254 mt->total_width, mt->total_height, mt->cpp);
255
256 return GL_TRUE;
257 }
258
259
260 /**
261 * Cube texture map layout for GM945 and later.
262 *
263 * The hardware layout looks like the 830-915 layout, except for the small
264 * sizes. A zoomed in view of the layout for 945 is:
265 *
266 * +-------+-------+
267 * | 8x8 | 8x8 |
268 * | | |
269 * | | |
270 * | +x | +y |
271 * | | |
272 * | | |
273 * | | |
274 * | | |
275 * +---+---+-------+
276 * |4x4| | 8x8 |
277 * | +x| | |
278 * | | | |
279 * | | | |
280 * +---+ | +z |
281 * |4x4| | |
282 * | +y| | |
283 * | | | |
284 * +---+ +-------+
285 *
286 * ...
287 *
288 * +-------+-------+
289 * | 8x8 | 8x8 |
290 * | | |
291 * | | |
292 * | -x | -y |
293 * | | |
294 * | | |
295 * | | |
296 * | | |
297 * +---+---+-------+
298 * |4x4| | 8x8 |
299 * | -x| | |
300 * | | | |
301 * | | | |
302 * +---+ | -z |
303 * |4x4| | |
304 * | -y| | |
305 * | | | |
306 * +---+ +---+---+---+---+---+---+---+---+---+
307 * |4x4| |4x4| |2x2| |2x2| |2x2| |2x2|
308 * | +z| | -z| | +x| | +y| | +z| | -x| ...
309 * | | | | | | | | | | | |
310 * +---+ +---+ +---+ +---+ +---+ +---+
311 *
312 * The bottom row continues with the remaining 2x2 then the 1x1 mip contents
313 * in order, with each of them aligned to a 8x8 block boundary. Thus, for
314 * 32x32 cube maps and smaller, the bottom row layout is going to dictate the
315 * pitch of the tree. For a tree with 4x4 images, the pitch is at least
316 * 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1
317 * it is 6 * 8 texels.
318 */
319
320 static void
321 i945_miptree_layout_cube(struct intel_context *intel,
322 struct intel_mipmap_tree * mt,
323 uint32_t tiling)
324 {
325 const GLuint dim = mt->width0;
326 GLuint face;
327 GLuint lvlWidth = mt->width0, lvlHeight = mt->height0;
328 GLint level;
329
330 assert(lvlWidth == lvlHeight); /* cubemap images are square */
331
332 /* Depending on the size of the largest images, pitch can be
333 * determined either by the old-style packing of cubemap faces,
334 * or the final row of 4x4, 2x2 and 1x1 faces below this.
335 */
336 if (dim > 32)
337 mt->total_width = dim * 2;
338 else
339 mt->total_width = 14 * 8;
340
341 if (dim >= 4)
342 mt->total_height = dim * 4 + 4;
343 else
344 mt->total_height = 4;
345
346 /* Set all the levels to effectively occupy the whole rectangular region. */
347 for (level = mt->first_level; level <= mt->last_level; level++) {
348 intel_miptree_set_level_info(mt, level, 6,
349 0, 0,
350 lvlWidth, lvlHeight, 1);
351 lvlWidth /= 2;
352 lvlHeight /= 2;
353 }
354
355 for (face = 0; face < 6; face++) {
356 GLuint x = initial_offsets[face][0] * dim;
357 GLuint y = initial_offsets[face][1] * dim;
358 GLuint d = dim;
359
360 if (dim == 4 && face >= 4) {
361 y = mt->total_height - 4;
362 x = (face - 4) * 8;
363 } else if (dim < 4 && (face > 0 || mt->first_level > 0)) {
364 y = mt->total_height - 4;
365 x = face * 8;
366 }
367
368 for (level = mt->first_level; level <= mt->last_level; level++) {
369 intel_miptree_set_image_offset(mt, level, face, x, y);
370
371 d >>= 1;
372
373 switch (d) {
374 case 4:
375 switch (face) {
376 case FACE_POS_X:
377 case FACE_NEG_X:
378 x += step_offsets[face][0] * d;
379 y += step_offsets[face][1] * d;
380 break;
381 case FACE_POS_Y:
382 case FACE_NEG_Y:
383 y += 12;
384 x -= 8;
385 break;
386 case FACE_POS_Z:
387 case FACE_NEG_Z:
388 y = mt->total_height - 4;
389 x = (face - 4) * 8;
390 break;
391 }
392 break;
393
394 case 2:
395 y = mt->total_height - 4;
396 x = bottom_offsets[face];
397 break;
398
399 case 1:
400 x += 48;
401 break;
402
403 default:
404 x += step_offsets[face][0] * d;
405 y += step_offsets[face][1] * d;
406 break;
407 }
408 }
409 }
410 }
411
412 static void
413 i945_miptree_layout_3d(struct intel_context *intel,
414 struct intel_mipmap_tree * mt,
415 uint32_t tiling)
416 {
417 GLuint width = mt->width0;
418 GLuint height = mt->height0;
419 GLuint depth = mt->depth0;
420 GLuint pack_x_pitch, pack_x_nr;
421 GLuint pack_y_pitch;
422 GLuint level;
423
424 mt->total_width = mt->width0;
425 mt->total_height = 0;
426
427 pack_y_pitch = MAX2(mt->height0, 2);
428 pack_x_pitch = mt->total_width;
429 pack_x_nr = 1;
430
431 for (level = mt->first_level; level <= mt->last_level; level++) {
432 GLint x = 0;
433 GLint y = 0;
434 GLint q, j;
435
436 intel_miptree_set_level_info(mt, level, depth,
437 0, mt->total_height,
438 width, height, depth);
439
440 for (q = 0; q < depth;) {
441 for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
442 intel_miptree_set_image_offset(mt, level, q, x, y);
443 x += pack_x_pitch;
444 }
445
446 x = 0;
447 y += pack_y_pitch;
448 }
449
450 mt->total_height += y;
451
452 if (pack_x_pitch > 4) {
453 pack_x_pitch >>= 1;
454 pack_x_nr <<= 1;
455 assert(pack_x_pitch * pack_x_nr <= mt->total_width);
456 }
457
458 if (pack_y_pitch > 2) {
459 pack_y_pitch >>= 1;
460 }
461
462 width = minify(width);
463 height = minify(height);
464 depth = minify(depth);
465 }
466 }
467
468 GLboolean
469 i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt,
470 uint32_t tiling)
471 {
472 switch (mt->target) {
473 case GL_TEXTURE_CUBE_MAP:
474 if (mt->compressed)
475 i945_miptree_layout_cube(intel, mt, tiling);
476 else
477 i915_miptree_layout_cube(intel, mt, tiling);
478 break;
479 case GL_TEXTURE_3D:
480 i945_miptree_layout_3d(intel, mt, tiling);
481 break;
482 case GL_TEXTURE_1D:
483 case GL_TEXTURE_2D:
484 case GL_TEXTURE_RECTANGLE_ARB:
485 i945_miptree_layout_2d(intel, mt, tiling);
486 break;
487 default:
488 _mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
489 break;
490 }
491
492 DBG("%s: %dx%dx%d\n", __FUNCTION__,
493 mt->total_width, mt->total_height, mt->cpp);
494
495 return GL_TRUE;
496 }