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