3bfa806d9eca7dc403cfe3ac84c31ad8065e865c
[mesa.git] / src / mesa / pipe / i915simple / i915_texture.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 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel Dänzer <michel@tungstengraphics.com>
31 */
32
33 #include "pipe/p_state.h"
34 #include "pipe/p_context.h"
35 #include "pipe/p_defines.h"
36 #include "pipe/p_util.h"
37 #include "pipe/p_winsys.h"
38
39 #include "i915_context.h"
40 #include "i915_texture.h"
41 #include "i915_debug.h"
42
43
44 static unsigned minify( unsigned d )
45 {
46 return MAX2(1, d>>1);
47 }
48
49 static int align(int value, int alignment)
50 {
51 return (value + alignment - 1) & ~(alignment - 1);
52 }
53
54
55 static void
56 i915_miptree_set_level_info(struct i915_texture *tex,
57 unsigned level,
58 unsigned nr_images,
59 unsigned x, unsigned y, unsigned w, unsigned h, unsigned d)
60 {
61 struct pipe_texture *pt = &tex->base;
62
63 assert(level < PIPE_MAX_TEXTURE_LEVELS);
64
65 pt->width[level] = w;
66 pt->height[level] = h;
67 pt->depth[level] = d;
68
69 tex->level_offset[level] = (x + y * tex->pitch) * pt->cpp;
70 tex->nr_images[level] = nr_images;
71
72 /*
73 DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
74 level, w, h, d, x, y, tex->level_offset[level]);
75 */
76
77 /* Not sure when this would happen, but anyway:
78 */
79 if (tex->image_offset[level]) {
80 FREE(tex->image_offset[level]);
81 tex->image_offset[level] = NULL;
82 }
83
84 assert(nr_images);
85 assert(!tex->image_offset[level]);
86
87 tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
88 tex->image_offset[level][0] = 0;
89 }
90
91
92 static void
93 i915_miptree_set_image_offset(struct i915_texture *tex,
94 unsigned level, unsigned img, unsigned x, unsigned y)
95 {
96 if (img == 0 && level == 0)
97 assert(x == 0 && y == 0);
98
99 assert(img < tex->nr_images[level]);
100
101 tex->image_offset[level][img] = (x + y * tex->pitch);
102
103 /*
104 DBG("%s level %d img %d pos %d,%d image_offset %x\n",
105 __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
106 */
107 }
108
109
110 static void
111 i945_miptree_layout_2d( struct i915_texture *tex )
112 {
113 struct pipe_texture *pt = &tex->base;
114 int align_h = 2, align_w = 4;
115 unsigned level;
116 unsigned x = 0;
117 unsigned y = 0;
118 unsigned width = pt->width[0];
119 unsigned height = pt->height[0];
120
121 tex->pitch = pt->width[0];
122
123 /* May need to adjust pitch to accomodate the placement of
124 * the 2nd mipmap. This occurs when the alignment
125 * constraints of mipmap placement push the right edge of the
126 * 2nd mipmap out past the width of its parent.
127 */
128 if (pt->first_level != pt->last_level) {
129 unsigned mip1_width = align(minify(pt->width[0]), align_w)
130 + minify(minify(pt->width[0]));
131
132 if (mip1_width > pt->width[0])
133 tex->pitch = mip1_width;
134 }
135
136 /* Pitch must be a whole number of dwords, even though we
137 * express it in texels.
138 */
139 tex->pitch = align(tex->pitch * pt->cpp, 4) / pt->cpp;
140 tex->total_height = 0;
141
142 for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
143 unsigned img_height;
144
145 i915_miptree_set_level_info(tex, level, 1, x, y, width, height, 1);
146
147 if (pt->compressed)
148 img_height = MAX2(1, height/4);
149 else
150 img_height = align(height, align_h);
151
152
153 /* Because the images are packed better, the final offset
154 * might not be the maximal one:
155 */
156 tex->total_height = MAX2(tex->total_height, y + img_height);
157
158 /* Layout_below: step right after second mipmap.
159 */
160 if (level == pt->first_level + 1) {
161 x += align(width, align_w);
162 }
163 else {
164 y += img_height;
165 }
166
167 width = minify(width);
168 height = minify(height);
169 }
170 }
171
172
173 static const int initial_offsets[6][2] = {
174 {0, 0},
175 {0, 2},
176 {1, 0},
177 {1, 2},
178 {1, 1},
179 {1, 3}
180 };
181
182 static const int step_offsets[6][2] = {
183 {0, 2},
184 {0, 2},
185 {-1, 2},
186 {-1, 2},
187 {-1, 1},
188 {-1, 1}
189 };
190
191
192 static boolean
193 i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
194 {
195 struct pipe_texture *pt = &tex->base;
196 unsigned level;
197
198 switch (pt->target) {
199 case PIPE_TEXTURE_CUBE: {
200 const unsigned dim = pt->width[0];
201 unsigned face;
202 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
203
204 assert(lvlWidth == lvlHeight); /* cubemap images are square */
205
206 /* double pitch for cube layouts */
207 tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
208 tex->total_height = dim * 4;
209
210 for (level = pt->first_level; level <= pt->last_level; level++) {
211 i915_miptree_set_level_info(tex, level, 6,
212 0, 0,
213 /*OLD: tex->pitch, tex->total_height,*/
214 lvlWidth, lvlHeight,
215 1);
216 lvlWidth /= 2;
217 lvlHeight /= 2;
218 }
219
220 for (face = 0; face < 6; face++) {
221 unsigned x = initial_offsets[face][0] * dim;
222 unsigned y = initial_offsets[face][1] * dim;
223 unsigned d = dim;
224
225 for (level = pt->first_level; level <= pt->last_level; level++) {
226 i915_miptree_set_image_offset(tex, level, face, x, y);
227 d >>= 1;
228 x += step_offsets[face][0] * d;
229 y += step_offsets[face][1] * d;
230 }
231 }
232 break;
233 }
234 case PIPE_TEXTURE_3D:{
235 unsigned width = pt->width[0];
236 unsigned height = pt->height[0];
237 unsigned depth = pt->depth[0];
238 unsigned stack_height = 0;
239
240 /* Calculate the size of a single slice.
241 */
242 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
243
244 /* XXX: hardware expects/requires 9 levels at minimum.
245 */
246 for (level = pt->first_level; level <= MAX2(8, pt->last_level);
247 level++) {
248 i915_miptree_set_level_info(tex, level, depth, 0, tex->total_height,
249 width, height, depth);
250
251
252 stack_height += MAX2(2, height);
253
254 width = minify(width);
255 height = minify(height);
256 depth = minify(depth);
257 }
258
259 /* Fixup depth image_offsets:
260 */
261 depth = pt->depth[0];
262 for (level = pt->first_level; level <= pt->last_level; level++) {
263 unsigned i;
264 for (i = 0; i < depth; i++)
265 i915_miptree_set_image_offset(tex, level, i,
266 0, i * stack_height);
267
268 depth = minify(depth);
269 }
270
271
272 /* Multiply slice size by texture depth for total size. It's
273 * remarkable how wasteful of memory the i915 texture layouts
274 * are. They are largely fixed in the i945.
275 */
276 tex->total_height = stack_height * pt->depth[0];
277 break;
278 }
279
280 default:{
281 unsigned width = pt->width[0];
282 unsigned height = pt->height[0];
283 unsigned img_height;
284
285 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
286 tex->total_height = 0;
287
288 for (level = pt->first_level; level <= pt->last_level; level++) {
289 i915_miptree_set_level_info(tex, level, 1,
290 0, tex->total_height,
291 width, height, 1);
292
293 if (pt->compressed)
294 img_height = MAX2(1, height / 4);
295 else
296 img_height = (MAX2(2, height) + 1) & ~1;
297
298 tex->total_height += img_height;
299
300 width = minify(width);
301 height = minify(height);
302 }
303 break;
304 }
305 }
306 /*
307 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
308 tex->pitch,
309 tex->total_height, pt->cpp, tex->pitch * tex->total_height * pt->cpp);
310 */
311
312 return TRUE;
313 }
314
315
316 static boolean
317 i945_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
318 {
319 struct pipe_texture *pt = &tex->base;
320 unsigned level;
321
322 switch (pt->target) {
323 case PIPE_TEXTURE_CUBE:{
324 const unsigned dim = pt->width[0];
325 unsigned face;
326 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
327
328 assert(lvlWidth == lvlHeight); /* cubemap images are square */
329
330 /* Depending on the size of the largest images, pitch can be
331 * determined either by the old-style packing of cubemap faces,
332 * or the final row of 4x4, 2x2 and 1x1 faces below this.
333 */
334 if (dim > 32)
335 tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
336 else
337 tex->pitch = 14 * 8;
338
339 tex->total_height = dim * 4 + 4;
340
341 /* Set all the levels to effectively occupy the whole rectangular region.
342 */
343 for (level = pt->first_level; level <= pt->last_level; level++) {
344 i915_miptree_set_level_info(tex, level, 6,
345 0, 0,
346 lvlWidth, lvlHeight, 1);
347 lvlWidth /= 2;
348 lvlHeight /= 2;
349 }
350
351
352 for (face = 0; face < 6; face++) {
353 unsigned x = initial_offsets[face][0] * dim;
354 unsigned y = initial_offsets[face][1] * dim;
355 unsigned d = dim;
356
357 if (dim == 4 && face >= 4) {
358 y = tex->total_height - 4;
359 x = (face - 4) * 8;
360 }
361 else if (dim < 4 && (face > 0 || pt->first_level > 0)) {
362 y = tex->total_height - 4;
363 x = face * 8;
364 }
365
366 for (level = pt->first_level; level <= pt->last_level; level++) {
367 i915_miptree_set_image_offset(tex, level, face, x, y);
368
369 d >>= 1;
370
371 switch (d) {
372 case 4:
373 switch (face) {
374 case PIPE_TEX_FACE_POS_X:
375 case PIPE_TEX_FACE_NEG_X:
376 x += step_offsets[face][0] * d;
377 y += step_offsets[face][1] * d;
378 break;
379 case PIPE_TEX_FACE_POS_Y:
380 case PIPE_TEX_FACE_NEG_Y:
381 y += 12;
382 x -= 8;
383 break;
384 case PIPE_TEX_FACE_POS_Z:
385 case PIPE_TEX_FACE_NEG_Z:
386 y = tex->total_height - 4;
387 x = (face - 4) * 8;
388 break;
389 }
390
391 case 2:
392 y = tex->total_height - 4;
393 x = 16 + face * 8;
394 break;
395
396 case 1:
397 x += 48;
398 break;
399
400 default:
401 x += step_offsets[face][0] * d;
402 y += step_offsets[face][1] * d;
403 break;
404 }
405 }
406 }
407 break;
408 }
409 case PIPE_TEXTURE_3D:{
410 unsigned width = pt->width[0];
411 unsigned height = pt->height[0];
412 unsigned depth = pt->depth[0];
413 unsigned pack_x_pitch, pack_x_nr;
414 unsigned pack_y_pitch;
415 unsigned level;
416
417 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
418 tex->total_height = 0;
419
420 pack_y_pitch = MAX2(pt->height[0], 2);
421 pack_x_pitch = tex->pitch;
422 pack_x_nr = 1;
423
424 for (level = pt->first_level; level <= pt->last_level; level++) {
425 unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
426 int x = 0;
427 int y = 0;
428 unsigned q, j;
429
430 i915_miptree_set_level_info(tex, level, nr_images,
431 0, tex->total_height,
432 width, height, depth);
433
434 for (q = 0; q < nr_images;) {
435 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
436 i915_miptree_set_image_offset(tex, level, q, x, y);
437 x += pack_x_pitch;
438 }
439
440 x = 0;
441 y += pack_y_pitch;
442 }
443
444
445 tex->total_height += y;
446
447 if (pack_x_pitch > 4) {
448 pack_x_pitch >>= 1;
449 pack_x_nr <<= 1;
450 assert(pack_x_pitch * pack_x_nr <= tex->pitch);
451 }
452
453 if (pack_y_pitch > 2) {
454 pack_y_pitch >>= 1;
455 }
456
457 width = minify(width);
458 height = minify(height);
459 depth = minify(depth);
460 }
461 break;
462 }
463
464 case PIPE_TEXTURE_1D:
465 case PIPE_TEXTURE_2D:
466 // case PIPE_TEXTURE_RECTANGLE:
467 i945_miptree_layout_2d(tex);
468 break;
469 default:
470 assert(0);
471 return FALSE;
472 }
473
474 /*
475 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
476 tex->pitch,
477 tex->total_height, pt->cpp, tex->pitch * tex->total_height * pt->cpp);
478 */
479
480 return TRUE;
481 }
482
483 void
484 i915_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
485 {
486 struct i915_texture *tex = REALLOC(*pt, sizeof(struct pipe_texture),
487 sizeof(struct i915_texture));
488
489 if (tex) {
490 struct i915_context *i915 = i915_context(pipe);
491
492 memset(&tex->base + 1, 0,
493 sizeof(struct i915_texture) - sizeof(struct pipe_texture));
494
495 if (i915->flags.is_i945 ? i945_miptree_layout(pipe, tex) :
496 i915_miptree_layout(pipe, tex)) {
497 tex->region = pipe->winsys->region_alloc(pipe->winsys,
498 tex->pitch * tex->base.cpp *
499 tex->total_height,
500 PIPE_SURFACE_FLAG_TEXTURE);
501 }
502
503 if (!tex->region) {
504 FREE(tex);
505 tex = NULL;
506 }
507 }
508
509 *pt = &tex->base;
510 }
511
512 void
513 i915_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
514 {
515 if (!*pt)
516 return;
517
518 /*
519 DBG("%s %p refcount will be %d\n",
520 __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
521 */
522 if (--(*pt)->refcount <= 0) {
523 struct i915_texture *tex = (struct i915_texture *)*pt;
524 uint i;
525
526 /*
527 DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
528 */
529
530 pipe->winsys->region_release(pipe->winsys, &tex->region);
531
532 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
533 if (tex->image_offset[i])
534 free(tex->image_offset[i]);
535
536 free(tex);
537 }
538 *pt = NULL;
539 }