gallium: remove bad assertion
[mesa.git] / src / gallium / drivers / 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_inlines.h"
37 #include "pipe/p_util.h"
38 #include "pipe/p_winsys.h"
39
40 #include "i915_context.h"
41 #include "i915_texture.h"
42 #include "i915_debug.h"
43 #include "i915_screen.h"
44
45 /*
46 * Helper function and arrays
47 */
48
49 /**
50 * Initial offset for Cube map.
51 */
52 static const int initial_offsets[6][2] = {
53 {0, 0},
54 {0, 2},
55 {1, 0},
56 {1, 2},
57 {1, 1},
58 {1, 3}
59 };
60
61 /**
62 * Step offsets for Cube map.
63 */
64 static const int step_offsets[6][2] = {
65 {0, 2},
66 {0, 2},
67 {-1, 2},
68 {-1, 2},
69 {-1, 1},
70 {-1, 1}
71 };
72
73 static unsigned minify( unsigned d )
74 {
75 return MAX2(1, d>>1);
76 }
77
78 static unsigned
79 power_of_two(unsigned x)
80 {
81 unsigned value = 1;
82 while (value <= x)
83 value = value << 1;
84 return value;
85 }
86
87 static unsigned
88 round_up(unsigned n, unsigned multiple)
89 {
90 return (n + multiple - 1) & ~(multiple - 1);
91 }
92
93
94 /*
95 * More advanced helper funcs
96 */
97
98
99 static void
100 i915_miptree_set_level_info(struct i915_texture *tex,
101 unsigned level,
102 unsigned nr_images,
103 unsigned w, unsigned h, unsigned d)
104 {
105 struct pipe_texture *pt = &tex->base;
106
107 assert(level < PIPE_MAX_TEXTURE_LEVELS);
108
109 pt->width[level] = w;
110 pt->height[level] = h;
111 pt->depth[level] = d;
112
113 tex->nr_images[level] = nr_images;
114
115 /*
116 DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
117 level, w, h, d, x, y, tex->level_offset[level]);
118 */
119
120 /* Not sure when this would happen, but anyway:
121 */
122 if (tex->image_offset[level]) {
123 FREE(tex->image_offset[level]);
124 tex->image_offset[level] = NULL;
125 }
126
127 assert(nr_images);
128 assert(!tex->image_offset[level]);
129
130 tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
131 tex->image_offset[level][0] = 0;
132 }
133
134 static void
135 i915_miptree_set_image_offset(struct i915_texture *tex,
136 unsigned level, unsigned img, unsigned x, unsigned y)
137 {
138 if (img == 0 && level == 0)
139 assert(x == 0 && y == 0);
140
141 assert(img < tex->nr_images[level]);
142
143 tex->image_offset[level][img] = (x + y * tex->pitch);
144
145 /*
146 printf("%s level %d img %d pos %d,%d image_offset %x\n",
147 __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
148 */
149 }
150
151
152 /*
153 * Layout functions
154 */
155
156
157 /**
158 * Special case to deal with display targets.
159 */
160 static boolean
161 i915_displaytarget_layout(struct i915_texture *tex)
162 {
163 struct pipe_texture *pt = &tex->base;
164
165 if (pt->last_level > 0 || pt->cpp != 4)
166 return 0;
167
168 i915_miptree_set_level_info( tex, 0, 1,
169 tex->base.width[0],
170 tex->base.height[0],
171 1 );
172 i915_miptree_set_image_offset( tex, 0, 0, 0, 0 );
173
174 if (tex->base.width[0] >= 128) {
175 tex->pitch = power_of_two(tex->base.width[0] * pt->cpp) / pt->cpp;
176 tex->total_height = round_up(tex->base.height[0], 8);
177 tex->tiled = 1;
178 } else {
179 tex->pitch = round_up(tex->base.width[0], 64 / pt->cpp);
180 tex->total_height = tex->base.height[0];
181 }
182
183 /*
184 printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
185 tex->base.width[0], tex->base.height[0], pt->cpp,
186 tex->pitch, tex->total_height, tex->pitch * tex->total_height * 4);
187 */
188
189 return 1;
190 }
191
192 static void
193 i945_miptree_layout_2d( struct i915_texture *tex )
194 {
195 struct pipe_texture *pt = &tex->base;
196 int align_h = 2, align_w = 4;
197 unsigned level;
198 unsigned x = 0;
199 unsigned y = 0;
200 unsigned width = pt->width[0];
201 unsigned height = pt->height[0];
202
203 #if 0 /* used for tiled display targets */
204 if (pt->last_level == 0 && pt->cpp == 4)
205 if (i915_displaytarget_layout(tex))
206 return;
207 #endif
208
209 tex->pitch = pt->width[0];
210
211 /* May need to adjust pitch to accomodate the placement of
212 * the 2nd mipmap level. This occurs when the alignment
213 * constraints of mipmap placement push the right edge of the
214 * 2nd mipmap level out past the width of its parent.
215 */
216 if (pt->last_level > 0) {
217 unsigned mip1_width = align_int(minify(pt->width[0]), align_w)
218 + minify(minify(pt->width[0]));
219
220 if (mip1_width > pt->width[0])
221 tex->pitch = mip1_width;
222 }
223
224 /* Pitch must be a whole number of dwords, even though we
225 * express it in texels.
226 */
227 tex->pitch = align_int(tex->pitch * pt->cpp, 64) / pt->cpp;
228 tex->total_height = 0;
229
230 for (level = 0; level <= pt->last_level; level++) {
231 unsigned img_height;
232
233 i915_miptree_set_level_info(tex, level, 1, width, height, 1);
234 i915_miptree_set_image_offset(tex, level, 0, x, y);
235
236 if (pt->compressed)
237 img_height = MAX2(1, height/4);
238 else
239 img_height = align_int(height, align_h);
240
241
242 /* Because the images are packed better, the final offset
243 * might not be the maximal one:
244 */
245 tex->total_height = MAX2(tex->total_height, y + img_height);
246
247 /* Layout_below: step right after second mipmap level.
248 */
249 if (level == 1) {
250 x += align_int(width, align_w);
251 }
252 else {
253 y += img_height;
254 }
255
256 width = minify(width);
257 height = minify(height);
258 }
259 }
260
261 static void
262 i945_miptree_layout_cube(struct i915_texture *tex)
263 {
264 struct pipe_texture *pt = &tex->base;
265 unsigned level;
266
267 const unsigned dim = pt->width[0];
268 unsigned face;
269 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
270
271 /*
272 printf("%s %i, %i\n", __FUNCTION__, pt->width[0], pt->height[0]);
273 */
274
275 assert(lvlWidth == lvlHeight); /* cubemap images are square */
276
277 /*
278 * XXX Should only be used for compressed formats. But lets
279 * keep this code active just in case.
280 *
281 * Depending on the size of the largest images, pitch can be
282 * determined either by the old-style packing of cubemap faces,
283 * or the final row of 4x4, 2x2 and 1x1 faces below this.
284 */
285 if (dim > 32)
286 tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
287 else
288 tex->pitch = 14 * 8;
289
290 /*
291 * XXX The 4 is only needed for compressed formats. See above.
292 */
293 tex->total_height = dim * 4 + 4;
294
295 /* Set all the levels to effectively occupy the whole rectangular region.
296 */
297 for (level = 0; level <= pt->last_level; level++) {
298 i915_miptree_set_level_info(tex, level, 6, lvlWidth, lvlHeight, 1);
299 lvlWidth /= 2;
300 lvlHeight /= 2;
301 }
302
303 for (face = 0; face < 6; face++) {
304 unsigned x = initial_offsets[face][0] * dim;
305 unsigned y = initial_offsets[face][1] * dim;
306 unsigned d = dim;
307
308 #if 0 /* Fix and enable this code for compressed formats */
309 if (dim == 4 && face >= 4) {
310 y = tex->total_height - 4;
311 x = (face - 4) * 8;
312 }
313 else if (dim < 4 && (face > 0)) {
314 y = tex->total_height - 4;
315 x = face * 8;
316 }
317 #endif
318
319 for (level = 0; level <= pt->last_level; level++) {
320 i915_miptree_set_image_offset(tex, level, face, x, y);
321
322 d >>= 1;
323
324 #if 0 /* Fix and enable this code for compressed formats */
325 switch (d) {
326 case 4:
327 switch (face) {
328 case PIPE_TEX_FACE_POS_X:
329 case PIPE_TEX_FACE_NEG_X:
330 x += step_offsets[face][0] * d;
331 y += step_offsets[face][1] * d;
332 break;
333 case PIPE_TEX_FACE_POS_Y:
334 case PIPE_TEX_FACE_NEG_Y:
335 y += 12;
336 x -= 8;
337 break;
338 case PIPE_TEX_FACE_POS_Z:
339 case PIPE_TEX_FACE_NEG_Z:
340 y = tex->total_height - 4;
341 x = (face - 4) * 8;
342 break;
343 }
344 case 2:
345 y = tex->total_height - 4;
346 x = 16 + face * 8;
347 break;
348
349 case 1:
350 x += 48;
351 break;
352 default:
353 #endif
354 x += step_offsets[face][0] * d;
355 y += step_offsets[face][1] * d;
356 #if 0
357 break;
358 }
359 #endif
360 }
361 }
362 }
363
364 static boolean
365 i915_miptree_layout(struct i915_texture * tex)
366 {
367 struct pipe_texture *pt = &tex->base;
368 unsigned level;
369
370 switch (pt->target) {
371 case PIPE_TEXTURE_CUBE: {
372 const unsigned dim = pt->width[0];
373 unsigned face;
374 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
375
376 assert(lvlWidth == lvlHeight); /* cubemap images are square */
377
378 /* double pitch for cube layouts */
379 tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
380 tex->total_height = dim * 4;
381
382 for (level = 0; level <= pt->last_level; level++) {
383 i915_miptree_set_level_info(tex, level, 6,
384 lvlWidth, lvlHeight,
385 1);
386 lvlWidth /= 2;
387 lvlHeight /= 2;
388 }
389
390 for (face = 0; face < 6; face++) {
391 unsigned x = initial_offsets[face][0] * dim;
392 unsigned y = initial_offsets[face][1] * dim;
393 unsigned d = dim;
394
395 for (level = 0; level <= pt->last_level; level++) {
396 i915_miptree_set_image_offset(tex, level, face, x, y);
397 d >>= 1;
398 x += step_offsets[face][0] * d;
399 y += step_offsets[face][1] * d;
400 }
401 }
402 break;
403 }
404 case PIPE_TEXTURE_3D:{
405 unsigned width = pt->width[0];
406 unsigned height = pt->height[0];
407 unsigned depth = pt->depth[0];
408 unsigned stack_height = 0;
409
410 /* Calculate the size of a single slice.
411 */
412 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
413
414 /* XXX: hardware expects/requires 9 levels at minimum.
415 */
416 for (level = 0; level <= MAX2(8, pt->last_level);
417 level++) {
418 i915_miptree_set_level_info(tex, level, depth,
419 width, height, depth);
420
421
422 stack_height += MAX2(2, height);
423
424 width = minify(width);
425 height = minify(height);
426 depth = minify(depth);
427 }
428
429 /* Fixup depth image_offsets:
430 */
431 depth = pt->depth[0];
432 for (level = 0; level <= pt->last_level; level++) {
433 unsigned i;
434 for (i = 0; i < depth; i++)
435 i915_miptree_set_image_offset(tex, level, i,
436 0, i * stack_height);
437
438 depth = minify(depth);
439 }
440
441
442 /* Multiply slice size by texture depth for total size. It's
443 * remarkable how wasteful of memory the i915 texture layouts
444 * are. They are largely fixed in the i945.
445 */
446 tex->total_height = stack_height * pt->depth[0];
447 break;
448 }
449
450 default:{
451 unsigned width = pt->width[0];
452 unsigned height = pt->height[0];
453 unsigned img_height;
454
455 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
456 tex->total_height = 0;
457
458 for (level = 0; level <= pt->last_level; level++) {
459 i915_miptree_set_level_info(tex, level, 1,
460 width, height, 1);
461 i915_miptree_set_image_offset(tex, level, 0,
462 0, tex->total_height);
463
464 if (pt->compressed)
465 img_height = MAX2(1, height / 4);
466 else
467 img_height = (MAX2(2, height) + 1) & ~1;
468
469 tex->total_height += img_height;
470
471 width = minify(width);
472 height = minify(height);
473 }
474 break;
475 }
476 }
477 /*
478 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
479 tex->pitch,
480 tex->total_height, pt->cpp, tex->pitch * tex->total_height * pt->cpp);
481 */
482
483 return TRUE;
484 }
485
486
487 static boolean
488 i945_miptree_layout(struct i915_texture * tex)
489 {
490 struct pipe_texture *pt = &tex->base;
491 unsigned level;
492
493 switch (pt->target) {
494 case PIPE_TEXTURE_CUBE:
495 i945_miptree_layout_cube(tex);
496 break;
497 case PIPE_TEXTURE_3D:{
498 unsigned width = pt->width[0];
499 unsigned height = pt->height[0];
500 unsigned depth = pt->depth[0];
501 unsigned pack_x_pitch, pack_x_nr;
502 unsigned pack_y_pitch;
503
504 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
505 tex->total_height = 0;
506
507 pack_y_pitch = MAX2(pt->height[0], 2);
508 pack_x_pitch = tex->pitch;
509 pack_x_nr = 1;
510
511 for (level = 0; level <= pt->last_level; level++) {
512 unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
513 int x = 0;
514 int y = 0;
515 unsigned q, j;
516
517 i915_miptree_set_level_info(tex, level, nr_images,
518 width, height, depth);
519
520 for (q = 0; q < nr_images;) {
521 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
522 i915_miptree_set_image_offset(tex, level, q, x, y + tex->total_height);
523 x += pack_x_pitch;
524 }
525
526 x = 0;
527 y += pack_y_pitch;
528 }
529
530
531 tex->total_height += y;
532
533 if (pack_x_pitch > 4) {
534 pack_x_pitch >>= 1;
535 pack_x_nr <<= 1;
536 assert(pack_x_pitch * pack_x_nr <= tex->pitch);
537 }
538
539 if (pack_y_pitch > 2) {
540 pack_y_pitch >>= 1;
541 }
542
543 width = minify(width);
544 height = minify(height);
545 depth = minify(depth);
546 }
547 break;
548 }
549
550 case PIPE_TEXTURE_1D:
551 case PIPE_TEXTURE_2D:
552 // case PIPE_TEXTURE_RECTANGLE:
553 i945_miptree_layout_2d(tex);
554 break;
555 default:
556 assert(0);
557 return FALSE;
558 }
559
560 /*
561 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
562 tex->pitch,
563 tex->total_height, pt->cpp, tex->pitch * tex->total_height * pt->cpp);
564 */
565
566 return TRUE;
567 }
568
569
570 static struct pipe_texture *
571 i915_texture_create(struct pipe_screen *screen,
572 const struct pipe_texture *templat)
573 {
574 struct i915_screen *i915screen = i915_screen(screen);
575 struct pipe_winsys *ws = screen->winsys;
576 struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
577
578 if (!tex)
579 return NULL;
580
581 tex->base = *templat;
582 tex->base.refcount = 1;
583 tex->base.screen = screen;
584
585 if (i915screen->is_i945) {
586 if (!i945_miptree_layout(tex))
587 goto fail;
588 } else {
589 if (!i915_miptree_layout(tex))
590 goto fail;
591 }
592
593 tex->buffer = ws->buffer_create(ws, 64,
594 PIPE_BUFFER_USAGE_PIXEL,
595 tex->pitch * tex->base.cpp *
596 tex->total_height);
597
598 if (!tex->buffer)
599 goto fail;
600
601 return &tex->base;
602
603 fail:
604 FREE(tex);
605 return NULL;
606 }
607
608
609 static void
610 i915_texture_release(struct pipe_screen *screen,
611 struct pipe_texture **pt)
612 {
613 if (!*pt)
614 return;
615
616 /*
617 DBG("%s %p refcount will be %d\n",
618 __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
619 */
620 if (--(*pt)->refcount <= 0) {
621 struct i915_texture *tex = (struct i915_texture *)*pt;
622 uint i;
623
624 /*
625 DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
626 */
627
628 pipe_buffer_reference(screen->winsys, &tex->buffer, NULL);
629
630 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
631 if (tex->image_offset[i])
632 FREE(tex->image_offset[i]);
633
634 FREE(tex);
635 }
636 *pt = NULL;
637 }
638
639 static struct pipe_surface *
640 i915_get_tex_surface(struct pipe_screen *screen,
641 struct pipe_texture *pt,
642 unsigned face, unsigned level, unsigned zslice,
643 unsigned flags)
644 {
645 struct i915_texture *tex = (struct i915_texture *)pt;
646 struct pipe_winsys *ws = screen->winsys;
647 struct pipe_surface *ps;
648 unsigned offset; /* in bytes */
649
650 if (pt->target == PIPE_TEXTURE_CUBE) {
651 offset = tex->image_offset[level][face] * pt->cpp;
652 }
653 else if (pt->target == PIPE_TEXTURE_3D) {
654 offset = tex->image_offset[level][zslice] * pt->cpp;
655 }
656 else {
657 offset = tex->image_offset[level][0] * pt->cpp;
658 assert(face == 0);
659 assert(zslice == 0);
660 }
661
662 ps = CALLOC_STRUCT(pipe_surface);
663 if (ps) {
664 ps->refcount = 1;
665 ps->winsys = ws;
666 pipe_texture_reference(&ps->texture, pt);
667 pipe_buffer_reference(ws, &ps->buffer, tex->buffer);
668 ps->format = pt->format;
669 ps->cpp = pt->cpp;
670 ps->width = pt->width[level];
671 ps->height = pt->height[level];
672 ps->pitch = tex->pitch;
673 ps->offset = offset;
674 ps->usage = flags;
675 ps->status = PIPE_SURFACE_STATUS_DEFINED;
676 }
677 return ps;
678 }
679
680 static struct pipe_texture *
681 i915_texture_blanket(struct pipe_screen * screen,
682 const struct pipe_texture *base,
683 const unsigned *pitch,
684 struct pipe_buffer *buffer)
685 {
686 struct i915_texture *tex;
687 assert(screen);
688
689 /* Only supports one type */
690 if (base->target != PIPE_TEXTURE_2D ||
691 base->last_level != 0 ||
692 base->depth[0] != 1) {
693 return NULL;
694 }
695
696 tex = CALLOC_STRUCT(i915_texture);
697 if (!tex)
698 return NULL;
699
700 tex->base = *base;
701
702 tex->pitch = pitch[0];
703
704 i915_miptree_set_level_info(tex, 0, 1, base->width[0], base->height[0], 1);
705 i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
706
707 pipe_buffer_reference(screen->winsys, &tex->buffer, buffer);
708
709 return &tex->base;
710 }
711
712 void
713 i915_init_texture_functions(struct i915_context *i915)
714 {
715 // i915->pipe.texture_update = i915_texture_update;
716 }
717
718 static void
719 i915_tex_surface_release(struct pipe_screen *screen,
720 struct pipe_surface **surface)
721 {
722 struct pipe_surface *surf = *surface;
723
724 if (--surf->refcount == 0) {
725
726 /* This really should not be possible, but it's actually
727 * happening quite a bit... Will fix.
728 */
729 if (surf->status == PIPE_SURFACE_STATUS_CLEAR) {
730 debug_printf("XXX destroying a surface with pending clears...\n");
731 assert(0);
732 }
733
734 pipe_texture_reference(&surf->texture, NULL);
735 pipe_buffer_reference(screen->winsys, &surf->buffer, NULL);
736 FREE(surf);
737 }
738
739 *surface = NULL;
740 }
741
742 void
743 i915_init_screen_texture_functions(struct pipe_screen *screen)
744 {
745 screen->texture_create = i915_texture_create;
746 screen->texture_release = i915_texture_release;
747 screen->get_tex_surface = i915_get_tex_surface;
748 screen->texture_blanket = i915_texture_blanket;
749 screen->tex_surface_release = i915_tex_surface_release;
750 }