Merge branch 'gallium-0.1' into gallium-tex-surfaces
[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 static unsigned minify( unsigned d )
47 {
48 return MAX2(1, d>>1);
49 }
50
51
52
53 static void
54 i915_miptree_set_level_info(struct i915_texture *tex,
55 unsigned level,
56 unsigned nr_images,
57 unsigned x, unsigned y, unsigned w, unsigned h, unsigned d)
58 {
59 struct pipe_texture *pt = &tex->base;
60
61 assert(level < PIPE_MAX_TEXTURE_LEVELS);
62
63 pt->width[level] = w;
64 pt->height[level] = h;
65 pt->depth[level] = d;
66
67 tex->level_offset[level] = (x + y * tex->pitch) * pt->cpp;
68 tex->nr_images[level] = nr_images;
69
70 /*
71 DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
72 level, w, h, d, x, y, tex->level_offset[level]);
73 */
74
75 /* Not sure when this would happen, but anyway:
76 */
77 if (tex->image_offset[level]) {
78 FREE(tex->image_offset[level]);
79 tex->image_offset[level] = NULL;
80 }
81
82 assert(nr_images);
83 assert(!tex->image_offset[level]);
84
85 tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
86 tex->image_offset[level][0] = 0;
87 }
88
89
90 static void
91 i915_miptree_set_image_offset(struct i915_texture *tex,
92 unsigned level, unsigned img, unsigned x, unsigned y)
93 {
94 if (img == 0 && level == 0)
95 assert(x == 0 && y == 0);
96
97 assert(img < tex->nr_images[level]);
98
99 tex->image_offset[level][img] = (x + y * tex->pitch);
100
101 /*
102 DBG("%s level %d img %d pos %d,%d image_offset %x\n",
103 __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
104 */
105 }
106
107
108 /* Hack it up to use the old winsys->surface_alloc_storage()
109 * method for now:
110 */
111 static boolean
112 i915_displaytarget_layout(struct pipe_screen *screen,
113 struct i915_texture *tex)
114 {
115 struct pipe_winsys *ws = screen->winsys;
116 struct pipe_surface surf;
117 unsigned flags = (PIPE_BUFFER_USAGE_CPU_READ |
118 PIPE_BUFFER_USAGE_CPU_WRITE |
119 PIPE_BUFFER_USAGE_GPU_READ |
120 PIPE_BUFFER_USAGE_GPU_WRITE);
121
122
123 memset(&surf, 0, sizeof(surf));
124
125 ws->surface_alloc_storage( ws,
126 &surf,
127 tex->base.width[0],
128 tex->base.height[0],
129 tex->base.format,
130 flags,
131 tex->base.tex_usage);
132
133 /* Now extract the goodies:
134 */
135 i915_miptree_set_image_offset( tex, 0, 0, 0, 0 );
136 i915_miptree_set_level_info( tex, 0, 0, 0, 0,
137 tex->base.width[0],
138 tex->base.height[0],
139 1 );
140
141 tex->buffer = surf.buffer;
142 tex->pitch = surf.pitch;
143 tex->total_height = 0;
144
145
146 return tex->buffer != NULL;
147 }
148
149
150
151
152
153 static void
154 i945_miptree_layout_2d( struct i915_texture *tex )
155 {
156 struct pipe_texture *pt = &tex->base;
157 int align_h = 2, align_w = 4;
158 unsigned level;
159 unsigned x = 0;
160 unsigned y = 0;
161 unsigned width = pt->width[0];
162 unsigned height = pt->height[0];
163
164 tex->pitch = pt->width[0];
165
166 /* May need to adjust pitch to accomodate the placement of
167 * the 2nd mipmap level. This occurs when the alignment
168 * constraints of mipmap placement push the right edge of the
169 * 2nd mipmap level out past the width of its parent.
170 */
171 if (pt->last_level > 0) {
172 unsigned mip1_width = align_int(minify(pt->width[0]), align_w)
173 + minify(minify(pt->width[0]));
174
175 if (mip1_width > pt->width[0])
176 tex->pitch = mip1_width;
177 }
178
179 /* Pitch must be a whole number of dwords, even though we
180 * express it in texels.
181 */
182 tex->pitch = align_int(tex->pitch * pt->cpp, 4) / pt->cpp;
183 tex->total_height = 0;
184
185 for (level = 0; level <= pt->last_level; level++) {
186 unsigned img_height;
187
188 i915_miptree_set_level_info(tex, level, 1, x, y, width, height, 1);
189
190 if (pt->compressed)
191 img_height = MAX2(1, height/4);
192 else
193 img_height = align_int(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 level.
202 */
203 if (level == 1) {
204 x += align_int(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 const int initial_offsets[6][2] = {
217 {0, 0},
218 {0, 2},
219 {1, 0},
220 {1, 2},
221 {1, 1},
222 {1, 3}
223 };
224
225 static const int step_offsets[6][2] = {
226 {0, 2},
227 {0, 2},
228 {-1, 2},
229 {-1, 2},
230 {-1, 1},
231 {-1, 1}
232 };
233
234
235 static boolean
236 i915_miptree_layout(struct i915_texture * tex)
237 {
238 struct pipe_texture *pt = &tex->base;
239 unsigned level;
240
241 switch (pt->target) {
242 case PIPE_TEXTURE_CUBE: {
243 const unsigned dim = pt->width[0];
244 unsigned face;
245 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
246
247 assert(lvlWidth == lvlHeight); /* cubemap images are square */
248
249 /* double pitch for cube layouts */
250 tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
251 tex->total_height = dim * 4;
252
253 for (level = 0; level <= pt->last_level; level++) {
254 i915_miptree_set_level_info(tex, level, 6,
255 0, 0,
256 /*OLD: tex->pitch, tex->total_height,*/
257 lvlWidth, lvlHeight,
258 1);
259 lvlWidth /= 2;
260 lvlHeight /= 2;
261 }
262
263 for (face = 0; face < 6; face++) {
264 unsigned x = initial_offsets[face][0] * dim;
265 unsigned y = initial_offsets[face][1] * dim;
266 unsigned d = dim;
267
268 for (level = 0; level <= pt->last_level; level++) {
269 i915_miptree_set_image_offset(tex, level, face, x, y);
270 d >>= 1;
271 x += step_offsets[face][0] * d;
272 y += step_offsets[face][1] * d;
273 }
274 }
275 break;
276 }
277 case PIPE_TEXTURE_3D:{
278 unsigned width = pt->width[0];
279 unsigned height = pt->height[0];
280 unsigned depth = pt->depth[0];
281 unsigned stack_height = 0;
282
283 /* Calculate the size of a single slice.
284 */
285 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
286
287 /* XXX: hardware expects/requires 9 levels at minimum.
288 */
289 for (level = 0; level <= MAX2(8, pt->last_level);
290 level++) {
291 i915_miptree_set_level_info(tex, level, depth, 0, tex->total_height,
292 width, height, depth);
293
294
295 stack_height += MAX2(2, height);
296
297 width = minify(width);
298 height = minify(height);
299 depth = minify(depth);
300 }
301
302 /* Fixup depth image_offsets:
303 */
304 depth = pt->depth[0];
305 for (level = 0; level <= pt->last_level; level++) {
306 unsigned i;
307 for (i = 0; i < depth; i++)
308 i915_miptree_set_image_offset(tex, level, i,
309 0, i * stack_height);
310
311 depth = minify(depth);
312 }
313
314
315 /* Multiply slice size by texture depth for total size. It's
316 * remarkable how wasteful of memory the i915 texture layouts
317 * are. They are largely fixed in the i945.
318 */
319 tex->total_height = stack_height * pt->depth[0];
320 break;
321 }
322
323 default:{
324 unsigned width = pt->width[0];
325 unsigned height = pt->height[0];
326 unsigned img_height;
327
328 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
329 tex->total_height = 0;
330
331 for (level = 0; level <= pt->last_level; level++) {
332 i915_miptree_set_level_info(tex, level, 1,
333 0, tex->total_height,
334 width, height, 1);
335
336 if (pt->compressed)
337 img_height = MAX2(1, height / 4);
338 else
339 img_height = (MAX2(2, height) + 1) & ~1;
340
341 tex->total_height += img_height;
342
343 width = minify(width);
344 height = minify(height);
345 }
346 break;
347 }
348 }
349 /*
350 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
351 tex->pitch,
352 tex->total_height, pt->cpp, tex->pitch * tex->total_height * pt->cpp);
353 */
354
355 return TRUE;
356 }
357
358
359 static boolean
360 i945_miptree_layout(struct i915_texture * tex)
361 {
362 struct pipe_texture *pt = &tex->base;
363 unsigned level;
364
365 switch (pt->target) {
366 case PIPE_TEXTURE_CUBE:{
367 const unsigned dim = pt->width[0];
368 unsigned face;
369 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
370
371 assert(lvlWidth == lvlHeight); /* cubemap images are square */
372
373 /* Depending on the size of the largest images, pitch can be
374 * determined either by the old-style packing of cubemap faces,
375 * or the final row of 4x4, 2x2 and 1x1 faces below this.
376 */
377 if (dim > 32)
378 tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
379 else
380 tex->pitch = 14 * 8;
381
382 tex->total_height = dim * 4 + 4;
383
384 /* Set all the levels to effectively occupy the whole rectangular region.
385 */
386 for (level = 0; level <= pt->last_level; level++) {
387 i915_miptree_set_level_info(tex, level, 6,
388 0, 0,
389 lvlWidth, lvlHeight, 1);
390 lvlWidth /= 2;
391 lvlHeight /= 2;
392 }
393
394
395 for (face = 0; face < 6; face++) {
396 unsigned x = initial_offsets[face][0] * dim;
397 unsigned y = initial_offsets[face][1] * dim;
398 unsigned d = dim;
399
400 if (dim == 4 && face >= 4) {
401 y = tex->total_height - 4;
402 x = (face - 4) * 8;
403 }
404 else if (dim < 4 && (face > 0)) {
405 y = tex->total_height - 4;
406 x = face * 8;
407 }
408
409 for (level = 0; level <= pt->last_level; level++) {
410 i915_miptree_set_image_offset(tex, level, face, x, y);
411
412 d >>= 1;
413
414 switch (d) {
415 case 4:
416 switch (face) {
417 case PIPE_TEX_FACE_POS_X:
418 case PIPE_TEX_FACE_NEG_X:
419 x += step_offsets[face][0] * d;
420 y += step_offsets[face][1] * d;
421 break;
422 case PIPE_TEX_FACE_POS_Y:
423 case PIPE_TEX_FACE_NEG_Y:
424 y += 12;
425 x -= 8;
426 break;
427 case PIPE_TEX_FACE_POS_Z:
428 case PIPE_TEX_FACE_NEG_Z:
429 y = tex->total_height - 4;
430 x = (face - 4) * 8;
431 break;
432 }
433
434 case 2:
435 y = tex->total_height - 4;
436 x = 16 + face * 8;
437 break;
438
439 case 1:
440 x += 48;
441 break;
442
443 default:
444 x += step_offsets[face][0] * d;
445 y += step_offsets[face][1] * d;
446 break;
447 }
448 }
449 }
450 break;
451 }
452 case PIPE_TEXTURE_3D:{
453 unsigned width = pt->width[0];
454 unsigned height = pt->height[0];
455 unsigned depth = pt->depth[0];
456 unsigned pack_x_pitch, pack_x_nr;
457 unsigned pack_y_pitch;
458 unsigned level;
459
460 tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
461 tex->total_height = 0;
462
463 pack_y_pitch = MAX2(pt->height[0], 2);
464 pack_x_pitch = tex->pitch;
465 pack_x_nr = 1;
466
467 for (level = 0; level <= pt->last_level; level++) {
468 unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
469 int x = 0;
470 int y = 0;
471 unsigned q, j;
472
473 i915_miptree_set_level_info(tex, level, nr_images,
474 0, tex->total_height,
475 width, height, depth);
476
477 for (q = 0; q < nr_images;) {
478 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
479 i915_miptree_set_image_offset(tex, level, q, x, y);
480 x += pack_x_pitch;
481 }
482
483 x = 0;
484 y += pack_y_pitch;
485 }
486
487
488 tex->total_height += y;
489
490 if (pack_x_pitch > 4) {
491 pack_x_pitch >>= 1;
492 pack_x_nr <<= 1;
493 assert(pack_x_pitch * pack_x_nr <= tex->pitch);
494 }
495
496 if (pack_y_pitch > 2) {
497 pack_y_pitch >>= 1;
498 }
499
500 width = minify(width);
501 height = minify(height);
502 depth = minify(depth);
503 }
504 break;
505 }
506
507 case PIPE_TEXTURE_1D:
508 case PIPE_TEXTURE_2D:
509 // case PIPE_TEXTURE_RECTANGLE:
510 i945_miptree_layout_2d(tex);
511 break;
512 default:
513 assert(0);
514 return FALSE;
515 }
516
517 /*
518 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
519 tex->pitch,
520 tex->total_height, pt->cpp, tex->pitch * tex->total_height * pt->cpp);
521 */
522
523 return TRUE;
524 }
525
526
527 static struct pipe_texture *
528 i915_texture_create_screen(struct pipe_screen *screen,
529 const struct pipe_texture *templat)
530 {
531 struct i915_screen *i915screen = i915_screen(screen);
532 struct pipe_winsys *ws = screen->winsys;
533 struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
534
535 if (!tex)
536 return NULL;
537
538 tex->base = *templat;
539 tex->base.refcount = 1;
540 tex->base.screen = screen;
541
542 if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
543 if (!i915_displaytarget_layout(screen, tex))
544 goto fail;
545 }
546 else {
547 if (i915screen->is_i945) {
548 if (!i945_miptree_layout(tex))
549 goto fail;
550 }
551 else {
552 if (!i915_miptree_layout(tex))
553 goto fail;
554 }
555
556 tex->buffer = ws->buffer_create(ws, 64,
557 PIPE_BUFFER_USAGE_PIXEL,
558 tex->pitch * tex->base.cpp *
559 tex->total_height);
560
561 if (!tex->buffer)
562 goto fail;
563 }
564
565 return &tex->base;
566
567 fail:
568 FREE(tex);
569 return NULL;
570 }
571
572
573 static void
574 i915_texture_release_screen(struct pipe_screen *screen,
575 struct pipe_texture **pt)
576 {
577 if (!*pt)
578 return;
579
580 /*
581 DBG("%s %p refcount will be %d\n",
582 __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
583 */
584 if (--(*pt)->refcount <= 0) {
585 struct i915_texture *tex = (struct i915_texture *)*pt;
586 uint i;
587
588 /*
589 DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
590 */
591
592 pipe_buffer_reference(screen->winsys, &tex->buffer, NULL);
593
594 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
595 if (tex->image_offset[i])
596 FREE(tex->image_offset[i]);
597
598 FREE(tex);
599 }
600 *pt = NULL;
601 }
602
603
604
605 /*
606 * XXX note: same as code in sp_surface.c
607 */
608 static struct pipe_surface *
609 i915_get_tex_surface_screen(struct pipe_screen *screen,
610 struct pipe_texture *pt,
611 unsigned face, unsigned level, unsigned zslice,
612 unsigned flags)
613 {
614 struct i915_texture *tex = (struct i915_texture *)pt;
615 struct pipe_winsys *ws = screen->winsys;
616 struct pipe_surface *ps;
617 unsigned offset; /* in bytes */
618
619 offset = tex->level_offset[level];
620
621 if (pt->target == PIPE_TEXTURE_CUBE) {
622 offset += tex->image_offset[level][face] * pt->cpp;
623 }
624 else if (pt->target == PIPE_TEXTURE_3D) {
625 offset += tex->image_offset[level][zslice] * pt->cpp;
626 }
627 else {
628 assert(face == 0);
629 assert(zslice == 0);
630 }
631
632 ps = ws->surface_alloc(ws);
633 if (ps) {
634 assert(ps->refcount);
635 assert(ps->winsys);
636 pipe_buffer_reference(ws, &ps->buffer, tex->buffer);
637 ps->format = pt->format;
638 ps->cpp = pt->cpp;
639 ps->width = pt->width[level];
640 ps->height = pt->height[level];
641 ps->pitch = tex->pitch;
642 ps->offset = offset;
643 ps->usage = flags;
644 }
645 return ps;
646 }
647
648
649 void
650 i915_init_texture_functions(struct i915_context *i915)
651 {
652 // i915->pipe.texture_update = i915_texture_update;
653 }
654
655
656 void
657 i915_init_screen_texture_functions(struct pipe_screen *screen)
658 {
659 screen->texture_create = i915_texture_create_screen;
660 screen->texture_release = i915_texture_release_screen;
661 screen->get_tex_surface = i915_get_tex_surface_screen;
662 }