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