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