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