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