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