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