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