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