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