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