Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[mesa.git] / src / gallium / drivers / i915 / 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/internal/p_winsys_screen.h"
38 #include "util/u_math.h"
39 #include "util/u_memory.h"
40
41 #include "i915_context.h"
42 #include "i915_texture.h"
43 #include "i915_debug.h"
44 #include "i915_screen.h"
45 #include "intel_winsys.h"
46
47
48 /*
49 * Helper function and arrays
50 */
51
52
53 /**
54 * Initial offset for Cube map.
55 */
56 static const int initial_offsets[6][2] = {
57 {0, 0},
58 {0, 2},
59 {1, 0},
60 {1, 2},
61 {1, 1},
62 {1, 3}
63 };
64
65 /**
66 * Step offsets for Cube map.
67 */
68 static const int step_offsets[6][2] = {
69 {0, 2},
70 {0, 2},
71 {-1, 2},
72 {-1, 2},
73 {-1, 1},
74 {-1, 1}
75 };
76
77 static unsigned
78 power_of_two(unsigned x)
79 {
80 unsigned value = 1;
81 while (value < x)
82 value = value << 1;
83 return value;
84 }
85
86 static unsigned
87 round_up(unsigned n, unsigned multiple)
88 {
89 return (n + multiple - 1) & ~(multiple - 1);
90 }
91
92
93 /*
94 * More advanced helper funcs
95 */
96
97
98 static void
99 i915_miptree_set_level_info(struct i915_texture *tex,
100 unsigned level,
101 unsigned nr_images,
102 unsigned w, unsigned h, unsigned d)
103 {
104 struct pipe_texture *pt = &tex->base;
105
106 assert(level < PIPE_MAX_TEXTURE_LEVELS);
107
108 pt->width[level] = w;
109 pt->height[level] = h;
110 pt->depth[level] = d;
111
112 pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w);
113 pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h);
114
115 tex->nr_images[level] = nr_images;
116
117 /*
118 DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
119 level, w, h, d, x, y, tex->level_offset[level]);
120 */
121
122 /* Not sure when this would happen, but anyway:
123 */
124 if (tex->image_offset[level]) {
125 FREE(tex->image_offset[level]);
126 tex->image_offset[level] = NULL;
127 }
128
129 assert(nr_images);
130 assert(!tex->image_offset[level]);
131
132 tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
133 tex->image_offset[level][0] = 0;
134 }
135
136 static void
137 i915_miptree_set_image_offset(struct i915_texture *tex,
138 unsigned level, unsigned img, unsigned x, unsigned y)
139 {
140 if (img == 0 && level == 0)
141 assert(x == 0 && y == 0);
142
143 assert(img < tex->nr_images[level]);
144
145 tex->image_offset[level][img] = y * tex->stride + x * tex->base.block.size;
146
147 /*
148 printf("%s level %d img %d pos %d,%d image_offset %x\n",
149 __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
150 */
151 }
152
153
154 /*
155 * i915 layout functions, some used by i945
156 */
157
158
159 /**
160 * Special case to deal with scanout textures.
161 */
162 static boolean
163 i915_scanout_layout(struct i915_texture *tex)
164 {
165 struct pipe_texture *pt = &tex->base;
166
167 if (pt->last_level > 0 || pt->block.size != 4)
168 return FALSE;
169
170 i915_miptree_set_level_info(tex, 0, 1,
171 tex->base.width[0],
172 tex->base.height[0],
173 1);
174 i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
175
176 if (tex->base.width[0] >= 240) {
177 tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size);
178 tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8);
179 tex->hw_tiled = INTEL_TILE_X;
180 } else if (tex->base.width[0] == 64 && tex->base.height[0] == 64) {
181 tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size);
182 tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8);
183 } else {
184 return FALSE;
185 }
186
187 debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
188 tex->base.width[0], tex->base.height[0], pt->block.size,
189 tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy);
190
191 return TRUE;
192 }
193
194 /**
195 * Special case to deal with shared textures.
196 */
197 static boolean
198 i915_display_target_layout(struct i915_texture *tex)
199 {
200 struct pipe_texture *pt = &tex->base;
201
202 if (pt->last_level > 0 || pt->block.size != 4)
203 return FALSE;
204
205 /* fallback to normal textures for small textures */
206 if (tex->base.width[0] < 240)
207 return FALSE;
208
209 i915_miptree_set_level_info(tex, 0, 1,
210 tex->base.width[0],
211 tex->base.height[0],
212 1);
213 i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
214
215 tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size);
216 tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8);
217 tex->hw_tiled = INTEL_TILE_X;
218
219 debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
220 tex->base.width[0], tex->base.height[0], pt->block.size,
221 tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy);
222
223 return TRUE;
224 }
225
226 static void
227 i915_miptree_layout_2d(struct i915_texture *tex)
228 {
229 struct pipe_texture *pt = &tex->base;
230 unsigned level;
231 unsigned width = pt->width[0];
232 unsigned height = pt->height[0];
233 unsigned nblocksx = pt->nblocksx[0];
234 unsigned nblocksy = pt->nblocksy[0];
235
236 /* used for scanouts that need special layouts */
237 if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY)
238 if (i915_scanout_layout(tex))
239 return;
240
241 /* for shared buffers we use some very like scanout */
242 if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET)
243 if (i915_display_target_layout(tex))
244 return;
245
246 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
247 tex->total_nblocksy = 0;
248
249 for (level = 0; level <= pt->last_level; level++) {
250 i915_miptree_set_level_info(tex, level, 1, width, height, 1);
251 i915_miptree_set_image_offset(tex, level, 0, 0, tex->total_nblocksy);
252
253 nblocksy = round_up(MAX2(2, nblocksy), 2);
254
255 tex->total_nblocksy += nblocksy;
256
257 width = minify(width);
258 height = minify(height);
259 nblocksx = pf_get_nblocksx(&pt->block, width);
260 nblocksy = pf_get_nblocksy(&pt->block, height);
261 }
262 }
263
264 static void
265 i915_miptree_layout_3d(struct i915_texture *tex)
266 {
267 struct pipe_texture *pt = &tex->base;
268 unsigned level;
269
270 unsigned width = pt->width[0];
271 unsigned height = pt->height[0];
272 unsigned depth = pt->depth[0];
273 unsigned nblocksx = pt->nblocksx[0];
274 unsigned nblocksy = pt->nblocksy[0];
275 unsigned stack_nblocksy = 0;
276
277 /* Calculate the size of a single slice.
278 */
279 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
280
281 /* XXX: hardware expects/requires 9 levels at minimum.
282 */
283 for (level = 0; level <= MAX2(8, pt->last_level); level++) {
284 i915_miptree_set_level_info(tex, level, depth, width, height, depth);
285
286 stack_nblocksy += MAX2(2, nblocksy);
287
288 width = minify(width);
289 height = minify(height);
290 depth = minify(depth);
291 nblocksx = pf_get_nblocksx(&pt->block, width);
292 nblocksy = pf_get_nblocksy(&pt->block, height);
293 }
294
295 /* Fixup depth image_offsets:
296 */
297 depth = pt->depth[0];
298 for (level = 0; level <= pt->last_level; level++) {
299 unsigned i;
300 for (i = 0; i < depth; i++)
301 i915_miptree_set_image_offset(tex, level, i, 0, i * stack_nblocksy);
302
303 depth = minify(depth);
304 }
305
306 /* Multiply slice size by texture depth for total size. It's
307 * remarkable how wasteful of memory the i915 texture layouts
308 * are. They are largely fixed in the i945.
309 */
310 tex->total_nblocksy = stack_nblocksy * pt->depth[0];
311 }
312
313 static void
314 i915_miptree_layout_cube(struct i915_texture *tex)
315 {
316 struct pipe_texture *pt = &tex->base;
317 unsigned width = pt->width[0], height = pt->height[0];
318 const unsigned nblocks = pt->nblocksx[0];
319 unsigned level;
320 unsigned face;
321
322 assert(width == height); /* cubemap images are square */
323
324 /* double pitch for cube layouts */
325 tex->stride = round_up(nblocks * pt->block.size * 2, 4);
326 tex->total_nblocksy = nblocks * 4;
327
328 for (level = 0; level <= pt->last_level; level++) {
329 i915_miptree_set_level_info(tex, level, 6, width, height, 1);
330 width /= 2;
331 height /= 2;
332 }
333
334 for (face = 0; face < 6; face++) {
335 unsigned x = initial_offsets[face][0] * nblocks;
336 unsigned y = initial_offsets[face][1] * nblocks;
337 unsigned d = nblocks;
338
339 for (level = 0; level <= pt->last_level; level++) {
340 i915_miptree_set_image_offset(tex, level, face, x, y);
341 d >>= 1;
342 x += step_offsets[face][0] * d;
343 y += step_offsets[face][1] * d;
344 }
345 }
346 }
347
348 static boolean
349 i915_miptree_layout(struct i915_texture * tex)
350 {
351 struct pipe_texture *pt = &tex->base;
352
353 switch (pt->target) {
354 case PIPE_TEXTURE_1D:
355 case PIPE_TEXTURE_2D:
356 i915_miptree_layout_2d(tex);
357 break;
358 case PIPE_TEXTURE_3D:
359 i915_miptree_layout_3d(tex);
360 break;
361 case PIPE_TEXTURE_CUBE:
362 i915_miptree_layout_cube(tex);
363 break;
364 default:
365 assert(0);
366 return FALSE;
367 }
368
369 return TRUE;
370 }
371
372
373 /*
374 * i945 layout functions
375 */
376
377
378 static void
379 i945_miptree_layout_2d(struct i915_texture *tex)
380 {
381 struct pipe_texture *pt = &tex->base;
382 const int align_x = 2, align_y = 4;
383 unsigned level;
384 unsigned x = 0;
385 unsigned y = 0;
386 unsigned width = pt->width[0];
387 unsigned height = pt->height[0];
388 unsigned nblocksx = pt->nblocksx[0];
389 unsigned nblocksy = pt->nblocksy[0];
390
391 /* used for scanouts that need special layouts */
392 if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_PRIMARY)
393 if (i915_scanout_layout(tex))
394 return;
395
396 /* for shared buffers we use some very like scanout */
397 if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET)
398 if (i915_display_target_layout(tex))
399 return;
400
401 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
402
403 /* May need to adjust pitch to accomodate the placement of
404 * the 2nd mipmap level. This occurs when the alignment
405 * constraints of mipmap placement push the right edge of the
406 * 2nd mipmap level out past the width of its parent.
407 */
408 if (pt->last_level > 0) {
409 unsigned mip1_nblocksx
410 = align(pf_get_nblocksx(&pt->block, minify(width)), align_x)
411 + pf_get_nblocksx(&pt->block, minify(minify(width)));
412
413 if (mip1_nblocksx > nblocksx)
414 tex->stride = mip1_nblocksx * pt->block.size;
415 }
416
417 /* Pitch must be a whole number of dwords
418 */
419 tex->stride = align(tex->stride, 64);
420 tex->total_nblocksy = 0;
421
422 for (level = 0; level <= pt->last_level; level++) {
423 i915_miptree_set_level_info(tex, level, 1, width, height, 1);
424 i915_miptree_set_image_offset(tex, level, 0, x, y);
425
426 nblocksy = align(nblocksy, align_y);
427
428 /* Because the images are packed better, the final offset
429 * might not be the maximal one:
430 */
431 tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
432
433 /* Layout_below: step right after second mipmap level.
434 */
435 if (level == 1) {
436 x += align(nblocksx, align_x);
437 }
438 else {
439 y += nblocksy;
440 }
441
442 width = minify(width);
443 height = minify(height);
444 nblocksx = pf_get_nblocksx(&pt->block, width);
445 nblocksy = pf_get_nblocksy(&pt->block, height);
446 }
447 }
448
449 static void
450 i945_miptree_layout_3d(struct i915_texture *tex)
451 {
452 struct pipe_texture *pt = &tex->base;
453 unsigned width = pt->width[0];
454 unsigned height = pt->height[0];
455 unsigned depth = pt->depth[0];
456 unsigned nblocksx = pt->nblocksx[0];
457 unsigned nblocksy = pt->nblocksy[0];
458 unsigned pack_x_pitch, pack_x_nr;
459 unsigned pack_y_pitch;
460 unsigned level;
461
462 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
463 tex->total_nblocksy = 0;
464
465 pack_y_pitch = MAX2(pt->nblocksy[0], 2);
466 pack_x_pitch = tex->stride / pt->block.size;
467 pack_x_nr = 1;
468
469 for (level = 0; level <= pt->last_level; level++) {
470 int x = 0;
471 int y = 0;
472 unsigned q, j;
473
474 i915_miptree_set_level_info(tex, level, depth, width, height, depth);
475
476 for (q = 0; q < depth;) {
477 for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
478 i915_miptree_set_image_offset(tex, level, q, x, y + tex->total_nblocksy);
479 x += pack_x_pitch;
480 }
481
482 x = 0;
483 y += pack_y_pitch;
484 }
485
486 tex->total_nblocksy += y;
487
488 if (pack_x_pitch > 4) {
489 pack_x_pitch >>= 1;
490 pack_x_nr <<= 1;
491 assert(pack_x_pitch * pack_x_nr * pt->block.size <= tex->stride);
492 }
493
494 if (pack_y_pitch > 2) {
495 pack_y_pitch >>= 1;
496 }
497
498 width = minify(width);
499 height = minify(height);
500 depth = minify(depth);
501 nblocksx = pf_get_nblocksx(&pt->block, width);
502 nblocksy = pf_get_nblocksy(&pt->block, height);
503 }
504 }
505
506 static void
507 i945_miptree_layout_cube(struct i915_texture *tex)
508 {
509 struct pipe_texture *pt = &tex->base;
510 unsigned level;
511
512 const unsigned nblocks = pt->nblocksx[0];
513 unsigned face;
514 unsigned width = pt->width[0];
515 unsigned height = pt->height[0];
516
517 /*
518 printf("%s %i, %i\n", __FUNCTION__, pt->width[0], pt->height[0]);
519 */
520
521 assert(width == height); /* cubemap images are square */
522
523 /*
524 * XXX Should only be used for compressed formats. But lets
525 * keep this code active just in case.
526 *
527 * Depending on the size of the largest images, pitch can be
528 * determined either by the old-style packing of cubemap faces,
529 * or the final row of 4x4, 2x2 and 1x1 faces below this.
530 */
531 if (nblocks > 32)
532 tex->stride = round_up(nblocks * pt->block.size * 2, 4);
533 else
534 tex->stride = 14 * 8 * pt->block.size;
535
536 tex->total_nblocksy = nblocks * 4;
537
538 /* Set all the levels to effectively occupy the whole rectangular region.
539 */
540 for (level = 0; level <= pt->last_level; level++) {
541 i915_miptree_set_level_info(tex, level, 6, width, height, 1);
542 width /= 2;
543 height /= 2;
544 }
545
546 for (face = 0; face < 6; face++) {
547 unsigned x = initial_offsets[face][0] * nblocks;
548 unsigned y = initial_offsets[face][1] * nblocks;
549 unsigned d = nblocks;
550
551 #if 0 /* Fix and enable this code for compressed formats */
552 if (nblocks == 4 && face >= 4) {
553 y = tex->total_height - 4;
554 x = (face - 4) * 8;
555 }
556 else if (nblocks < 4 && (face > 0)) {
557 y = tex->total_height - 4;
558 x = face * 8;
559 }
560 #endif
561
562 for (level = 0; level <= pt->last_level; level++) {
563 i915_miptree_set_image_offset(tex, level, face, x, y);
564
565 d >>= 1;
566
567 #if 0 /* Fix and enable this code for compressed formats */
568 switch (d) {
569 case 4:
570 switch (face) {
571 case PIPE_TEX_FACE_POS_X:
572 case PIPE_TEX_FACE_NEG_X:
573 x += step_offsets[face][0] * d;
574 y += step_offsets[face][1] * d;
575 break;
576 case PIPE_TEX_FACE_POS_Y:
577 case PIPE_TEX_FACE_NEG_Y:
578 y += 12;
579 x -= 8;
580 break;
581 case PIPE_TEX_FACE_POS_Z:
582 case PIPE_TEX_FACE_NEG_Z:
583 y = tex->total_height - 4;
584 x = (face - 4) * 8;
585 break;
586 }
587 case 2:
588 y = tex->total_height - 4;
589 x = 16 + face * 8;
590 break;
591
592 case 1:
593 x += 48;
594 break;
595 default:
596 #endif
597 x += step_offsets[face][0] * d;
598 y += step_offsets[face][1] * d;
599 #if 0
600 break;
601 }
602 #endif
603 }
604 }
605 }
606
607 static boolean
608 i945_miptree_layout(struct i915_texture * tex)
609 {
610 struct pipe_texture *pt = &tex->base;
611
612 switch (pt->target) {
613 case PIPE_TEXTURE_1D:
614 case PIPE_TEXTURE_2D:
615 i945_miptree_layout_2d(tex);
616 break;
617 case PIPE_TEXTURE_3D:
618 i945_miptree_layout_3d(tex);
619 break;
620 case PIPE_TEXTURE_CUBE:
621 i945_miptree_layout_cube(tex);
622 break;
623 default:
624 assert(0);
625 return FALSE;
626 }
627
628 return TRUE;
629 }
630
631
632 /*
633 * Screen texture functions
634 */
635
636
637 static struct pipe_texture *
638 i915_texture_create(struct pipe_screen *screen,
639 const struct pipe_texture *templat)
640 {
641 struct i915_screen *is = i915_screen(screen);
642 struct intel_winsys *iws = is->iws;
643 struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
644 size_t tex_size;
645 unsigned buf_usage = 0;
646
647 if (!tex)
648 return NULL;
649
650 tex->base = *templat;
651 pipe_reference_init(&tex->base.reference, 1);
652 tex->base.screen = screen;
653
654 tex->base.nblocksx[0] = pf_get_nblocksx(&tex->base.block, tex->base.width[0]);
655 tex->base.nblocksy[0] = pf_get_nblocksy(&tex->base.block, tex->base.height[0]);
656
657 if (is->is_i945) {
658 if (!i945_miptree_layout(tex))
659 goto fail;
660 } else {
661 if (!i915_miptree_layout(tex))
662 goto fail;
663 }
664
665 tex_size = tex->stride * tex->total_nblocksy;
666
667
668
669 /* for scanouts and cursors, cursors arn't scanouts */
670 if (templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY && templat->width[0] != 64)
671 buf_usage = INTEL_NEW_SCANOUT;
672 else
673 buf_usage = INTEL_NEW_TEXTURE;
674
675 tex->buffer = iws->buffer_create(iws, tex_size, 64, buf_usage);
676 if (!tex->buffer)
677 goto fail;
678
679 /* setup any hw fences */
680 if (tex->hw_tiled) {
681 assert(tex->sw_tiled == INTEL_TILE_NONE);
682 iws->buffer_set_fence_reg(iws, tex->buffer, tex->stride, tex->hw_tiled);
683 }
684
685
686 #if 0
687 void *ptr = ws->buffer_map(ws, tex->buffer,
688 PIPE_BUFFER_USAGE_CPU_WRITE);
689 memset(ptr, 0x80, tex_size);
690 ws->buffer_unmap(ws, tex->buffer);
691 #endif
692
693 return &tex->base;
694
695 fail:
696 FREE(tex);
697 return NULL;
698 }
699
700 static struct pipe_texture *
701 i915_texture_blanket(struct pipe_screen * screen,
702 const struct pipe_texture *base,
703 const unsigned *stride,
704 struct pipe_buffer *buffer)
705 {
706 #if 0
707 struct i915_texture *tex;
708 assert(screen);
709
710 /* Only supports one type */
711 if (base->target != PIPE_TEXTURE_2D ||
712 base->last_level != 0 ||
713 base->depth[0] != 1) {
714 return NULL;
715 }
716
717 tex = CALLOC_STRUCT(i915_texture);
718 if (!tex)
719 return NULL;
720
721 tex->base = *base;
722 pipe_reference_init(&tex->base.reference, 1);
723 tex->base.screen = screen;
724
725 tex->stride = stride[0];
726
727 i915_miptree_set_level_info(tex, 0, 1, base->width[0], base->height[0], 1);
728 i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
729
730 pipe_buffer_reference(&tex->buffer, buffer);
731
732 return &tex->base;
733 #else
734 return NULL;
735 #endif
736 }
737
738 static void
739 i915_texture_destroy(struct pipe_texture *pt)
740 {
741 struct i915_texture *tex = (struct i915_texture *)pt;
742 struct intel_winsys *iws = i915_screen(pt->screen)->iws;
743 uint i;
744
745 /*
746 DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
747 */
748
749 iws->buffer_destroy(iws, tex->buffer);
750
751 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
752 if (tex->image_offset[i])
753 FREE(tex->image_offset[i]);
754
755 FREE(tex);
756 }
757
758
759 /*
760 * Screen surface functions
761 */
762
763
764 static struct pipe_surface *
765 i915_get_tex_surface(struct pipe_screen *screen,
766 struct pipe_texture *pt,
767 unsigned face, unsigned level, unsigned zslice,
768 unsigned flags)
769 {
770 struct i915_texture *tex = (struct i915_texture *)pt;
771 struct pipe_surface *ps;
772 unsigned offset; /* in bytes */
773
774 if (pt->target == PIPE_TEXTURE_CUBE) {
775 offset = tex->image_offset[level][face];
776 }
777 else if (pt->target == PIPE_TEXTURE_3D) {
778 offset = tex->image_offset[level][zslice];
779 }
780 else {
781 offset = tex->image_offset[level][0];
782 assert(face == 0);
783 assert(zslice == 0);
784 }
785
786 ps = CALLOC_STRUCT(pipe_surface);
787 if (ps) {
788 pipe_reference_init(&ps->reference, 1);
789 pipe_texture_reference(&ps->texture, pt);
790 ps->format = pt->format;
791 ps->width = pt->width[level];
792 ps->height = pt->height[level];
793 ps->offset = offset;
794 ps->usage = flags;
795 }
796 return ps;
797 }
798
799 static void
800 i915_tex_surface_destroy(struct pipe_surface *surf)
801 {
802 pipe_texture_reference(&surf->texture, NULL);
803 FREE(surf);
804 }
805
806
807 /*
808 * Screen transfer functions
809 */
810
811
812 static struct pipe_transfer*
813 i915_get_tex_transfer(struct pipe_screen *screen,
814 struct pipe_texture *texture,
815 unsigned face, unsigned level, unsigned zslice,
816 enum pipe_transfer_usage usage, unsigned x, unsigned y,
817 unsigned w, unsigned h)
818 {
819 struct i915_texture *tex = (struct i915_texture *)texture;
820 struct i915_transfer *trans;
821 unsigned offset; /* in bytes */
822
823 if (texture->target == PIPE_TEXTURE_CUBE) {
824 offset = tex->image_offset[level][face];
825 }
826 else if (texture->target == PIPE_TEXTURE_3D) {
827 offset = tex->image_offset[level][zslice];
828 }
829 else {
830 offset = tex->image_offset[level][0];
831 assert(face == 0);
832 assert(zslice == 0);
833 }
834
835 trans = CALLOC_STRUCT(i915_transfer);
836 if (trans) {
837 pipe_texture_reference(&trans->base.texture, texture);
838 trans->base.format = trans->base.format;
839 trans->base.x = x;
840 trans->base.y = y;
841 trans->base.width = w;
842 trans->base.height = h;
843 trans->base.block = texture->block;
844 trans->base.nblocksx = texture->nblocksx[level];
845 trans->base.nblocksy = texture->nblocksy[level];
846 trans->base.stride = tex->stride;
847 trans->offset = offset;
848 trans->base.usage = usage;
849 }
850 return &trans->base;
851 }
852
853 static void *
854 i915_transfer_map(struct pipe_screen *screen,
855 struct pipe_transfer *transfer)
856 {
857 struct i915_texture *tex = (struct i915_texture *)transfer->texture;
858 struct intel_winsys *iws = i915_screen(tex->base.screen)->iws;
859 char *map;
860 boolean write = FALSE;
861
862 if (transfer->usage & PIPE_TRANSFER_WRITE)
863 write = TRUE;
864
865 map = iws->buffer_map(iws, tex->buffer, write);
866 if (map == NULL)
867 return NULL;
868
869 return map + i915_transfer(transfer)->offset +
870 transfer->y / transfer->block.height * transfer->stride +
871 transfer->x / transfer->block.width * transfer->block.size;
872 }
873
874 static void
875 i915_transfer_unmap(struct pipe_screen *screen,
876 struct pipe_transfer *transfer)
877 {
878 struct i915_texture *tex = (struct i915_texture *)transfer->texture;
879 struct intel_winsys *iws = i915_screen(tex->base.screen)->iws;
880 iws->buffer_unmap(iws, tex->buffer);
881 }
882
883 static void
884 i915_tex_transfer_destroy(struct pipe_transfer *trans)
885 {
886 pipe_texture_reference(&trans->texture, NULL);
887 FREE(trans);
888 }
889
890
891 /*
892 * Other texture functions
893 */
894
895
896 void
897 i915_init_screen_texture_functions(struct i915_screen *is)
898 {
899 is->base.texture_create = i915_texture_create;
900 is->base.texture_blanket = i915_texture_blanket;
901 is->base.texture_destroy = i915_texture_destroy;
902 is->base.get_tex_surface = i915_get_tex_surface;
903 is->base.tex_surface_destroy = i915_tex_surface_destroy;
904 is->base.get_tex_transfer = i915_get_tex_transfer;
905 is->base.transfer_map = i915_transfer_map;
906 is->base.transfer_unmap = i915_transfer_unmap;
907 is->base.tex_transfer_destroy = i915_tex_transfer_destroy;
908 }
909
910 struct pipe_texture *
911 i915_texture_blanket_intel(struct pipe_screen *screen,
912 struct pipe_texture *base,
913 unsigned stride,
914 struct intel_buffer *buffer)
915 {
916 struct i915_texture *tex;
917 assert(screen);
918
919 /* Only supports one type */
920 if (base->target != PIPE_TEXTURE_2D ||
921 base->last_level != 0 ||
922 base->depth[0] != 1) {
923 return NULL;
924 }
925
926 tex = CALLOC_STRUCT(i915_texture);
927 if (!tex)
928 return NULL;
929
930 tex->base = *base;
931 pipe_reference_init(&tex->base.reference, 1);
932 tex->base.screen = screen;
933
934 tex->stride = stride;
935
936 i915_miptree_set_level_info(tex, 0, 1, base->width[0], base->height[0], 1);
937 i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
938
939 tex->buffer = buffer;
940
941 return &tex->base;
942 }
943
944 boolean
945 i915_get_texture_buffer_intel(struct pipe_texture *texture,
946 struct intel_buffer **buffer,
947 unsigned *stride)
948 {
949 struct i915_texture *tex = (struct i915_texture *)texture;
950
951 if (!texture)
952 return FALSE;
953
954 *stride = tex->stride;
955 *buffer = tex->buffer;
956
957 return TRUE;
958 }