Merge remote branch 'origin/master' into glsl2
[mesa.git] / src / gallium / drivers / llvmpipe / lp_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 <stdio.h>
34
35 #include "pipe/p_context.h"
36 #include "pipe/p_defines.h"
37
38 #include "util/u_inlines.h"
39 #include "util/u_cpu_detect.h"
40 #include "util/u_format.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43 #include "util/u_simple_list.h"
44 #include "util/u_transfer.h"
45
46 #include "lp_context.h"
47 #include "lp_flush.h"
48 #include "lp_screen.h"
49 #include "lp_tile_image.h"
50 #include "lp_texture.h"
51 #include "lp_setup.h"
52
53 #include "state_tracker/sw_winsys.h"
54
55
56 #ifdef DEBUG
57 static struct llvmpipe_resource resource_list;
58 #endif
59 static unsigned id_counter = 0;
60
61
62 static INLINE boolean
63 resource_is_texture(const struct pipe_resource *resource)
64 {
65 switch (resource->target) {
66 case PIPE_BUFFER:
67 return FALSE;
68 case PIPE_TEXTURE_1D:
69 case PIPE_TEXTURE_2D:
70 case PIPE_TEXTURE_3D:
71 case PIPE_TEXTURE_CUBE:
72 return TRUE;
73 default:
74 assert(0);
75 return FALSE;
76 }
77 }
78
79
80
81 /**
82 * Allocate storage for llvmpipe_texture::layout array.
83 * The number of elements is width_in_tiles * height_in_tiles.
84 */
85 static enum lp_texture_layout *
86 alloc_layout_array(unsigned num_slices, unsigned width, unsigned height)
87 {
88 const unsigned tx = align(width, TILE_SIZE) / TILE_SIZE;
89 const unsigned ty = align(height, TILE_SIZE) / TILE_SIZE;
90
91 assert(num_slices * tx * ty > 0);
92 assert(LP_TEX_LAYOUT_NONE == 0); /* calloc'ing LP_TEX_LAYOUT_NONE here */
93
94 return (enum lp_texture_layout *)
95 CALLOC(num_slices * tx * ty, sizeof(enum lp_texture_layout));
96 }
97
98
99
100 /**
101 * Conventional allocation path for non-display textures:
102 * Just compute row strides here. Storage is allocated on demand later.
103 */
104 static boolean
105 llvmpipe_texture_layout(struct llvmpipe_screen *screen,
106 struct llvmpipe_resource *lpr)
107 {
108 struct pipe_resource *pt = &lpr->base;
109 unsigned level;
110 unsigned width = pt->width0;
111 unsigned height = pt->height0;
112 unsigned depth = pt->depth0;
113
114 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
115 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
116
117 for (level = 0; level <= pt->last_level; level++) {
118
119 /* Row stride and image stride (for linear layout) */
120 {
121 unsigned alignment, nblocksx, nblocksy, block_size;
122
123 /* For non-compressed formats we need to align the texture size
124 * to the tile size to facilitate render-to-texture.
125 */
126 if (util_format_is_compressed(pt->format))
127 alignment = 1;
128 else
129 alignment = TILE_SIZE;
130
131 nblocksx = util_format_get_nblocksx(pt->format,
132 align(width, alignment));
133 nblocksy = util_format_get_nblocksy(pt->format,
134 align(height, alignment));
135 block_size = util_format_get_blocksize(pt->format);
136
137 lpr->row_stride[level] = align(nblocksx * block_size, 16);
138
139 lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
140 }
141
142 /* Size of the image in tiles (for tiled layout) */
143 {
144 const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
145 const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
146 lpr->tiles_per_row[level] = width_t;
147 lpr->tiles_per_image[level] = width_t * height_t;
148 }
149
150 /* Number of 3D image slices or cube faces */
151 {
152 unsigned num_slices;
153
154 if (lpr->base.target == PIPE_TEXTURE_CUBE)
155 num_slices = 6;
156 else if (lpr->base.target == PIPE_TEXTURE_3D)
157 num_slices = depth;
158 else
159 num_slices = 1;
160
161 lpr->num_slices_faces[level] = num_slices;
162
163 lpr->layout[level] = alloc_layout_array(num_slices, width, height);
164 }
165
166 /* Compute size of next mipmap level */
167 width = u_minify(width, 1);
168 height = u_minify(height, 1);
169 depth = u_minify(depth, 1);
170 }
171
172 return TRUE;
173 }
174
175
176
177 static boolean
178 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
179 struct llvmpipe_resource *lpr)
180 {
181 struct sw_winsys *winsys = screen->winsys;
182
183 /* Round up the surface size to a multiple of the tile size to
184 * avoid tile clipping.
185 */
186 const unsigned width = align(lpr->base.width0, TILE_SIZE);
187 const unsigned height = align(lpr->base.height0, TILE_SIZE);
188 const unsigned width_t = width / TILE_SIZE;
189 const unsigned height_t = height / TILE_SIZE;
190
191 lpr->tiles_per_row[0] = width_t;
192 lpr->tiles_per_image[0] = width_t * height_t;
193 lpr->num_slices_faces[0] = 1;
194 lpr->img_stride[0] = 0;
195
196 lpr->layout[0] = alloc_layout_array(1, width, height);
197 //lpr->layout[0][0] = LP_TEX_LAYOUT_LINEAR;
198
199 lpr->dt = winsys->displaytarget_create(winsys,
200 lpr->base.bind,
201 lpr->base.format,
202 width, height,
203 16,
204 &lpr->row_stride[0] );
205
206 return lpr->dt != NULL;
207 }
208
209
210 static struct pipe_resource *
211 llvmpipe_resource_create(struct pipe_screen *_screen,
212 const struct pipe_resource *templat)
213 {
214 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
215 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
216 if (!lpr)
217 return NULL;
218
219 lpr->base = *templat;
220 pipe_reference_init(&lpr->base.reference, 1);
221 lpr->base.screen = &screen->base;
222
223 /* assert(lpr->base.bind); */
224
225 if (resource_is_texture(&lpr->base)) {
226 if (lpr->base.bind & PIPE_BIND_DISPLAY_TARGET) {
227 /* displayable surface */
228 if (!llvmpipe_displaytarget_layout(screen, lpr))
229 goto fail;
230 assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
231 }
232 else {
233 /* texture map */
234 if (!llvmpipe_texture_layout(screen, lpr))
235 goto fail;
236 assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
237 }
238 assert(lpr->layout[0]);
239 }
240 else {
241 /* other data (vertex buffer, const buffer, etc) */
242 const enum pipe_format format = templat->format;
243 const uint w = templat->width0 / util_format_get_blockheight(format);
244 const uint h = templat->height0 / util_format_get_blockwidth(format);
245 const uint d = templat->depth0;
246 const uint bpp = util_format_get_blocksize(format);
247 const uint bytes = w * h * d * bpp;
248 lpr->data = align_malloc(bytes, 16);
249 if (!lpr->data)
250 goto fail;
251 }
252
253 lpr->id = id_counter++;
254
255 #ifdef DEBUG
256 insert_at_tail(&resource_list, lpr);
257 #endif
258
259 return &lpr->base;
260
261 fail:
262 FREE(lpr);
263 return NULL;
264 }
265
266
267 static void
268 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
269 struct pipe_resource *pt)
270 {
271 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
272 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
273
274 if (lpr->dt) {
275 /* display target */
276 struct sw_winsys *winsys = screen->winsys;
277 winsys->displaytarget_destroy(winsys, lpr->dt);
278
279 if (lpr->tiled[0].data) {
280 align_free(lpr->tiled[0].data);
281 lpr->tiled[0].data = NULL;
282 }
283
284 FREE(lpr->layout[0]);
285 }
286 else if (resource_is_texture(pt)) {
287 /* regular texture */
288 uint level;
289
290 /* free linear image data */
291 for (level = 0; level < Elements(lpr->linear); level++) {
292 if (lpr->linear[level].data) {
293 align_free(lpr->linear[level].data);
294 lpr->linear[level].data = NULL;
295 }
296 }
297
298 /* free tiled image data */
299 for (level = 0; level < Elements(lpr->tiled); level++) {
300 if (lpr->tiled[level].data) {
301 align_free(lpr->tiled[level].data);
302 lpr->tiled[level].data = NULL;
303 }
304 }
305
306 /* free layout flag arrays */
307 for (level = 0; level < Elements(lpr->tiled); level++) {
308 FREE(lpr->layout[level]);
309 lpr->layout[level] = NULL;
310 }
311 }
312 else if (!lpr->userBuffer) {
313 assert(lpr->data);
314 align_free(lpr->data);
315 }
316
317 #ifdef DEBUG
318 if (lpr->next)
319 remove_from_list(lpr);
320 #endif
321
322 FREE(lpr);
323 }
324
325
326 /**
327 * Map a resource for read/write.
328 */
329 void *
330 llvmpipe_resource_map(struct pipe_resource *resource,
331 unsigned face,
332 unsigned level,
333 unsigned zslice,
334 enum lp_texture_usage tex_usage,
335 enum lp_texture_layout layout)
336 {
337 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
338 uint8_t *map;
339
340 assert(face < 6);
341 assert(level < LP_MAX_TEXTURE_LEVELS);
342
343 assert(tex_usage == LP_TEX_USAGE_READ ||
344 tex_usage == LP_TEX_USAGE_READ_WRITE ||
345 tex_usage == LP_TEX_USAGE_WRITE_ALL);
346
347 assert(layout == LP_TEX_LAYOUT_NONE ||
348 layout == LP_TEX_LAYOUT_TILED ||
349 layout == LP_TEX_LAYOUT_LINEAR);
350
351 if (lpr->dt) {
352 /* display target */
353 struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
354 struct sw_winsys *winsys = screen->winsys;
355 unsigned dt_usage;
356 uint8_t *map2;
357
358 if (tex_usage == LP_TEX_USAGE_READ) {
359 dt_usage = PIPE_TRANSFER_READ;
360 }
361 else {
362 dt_usage = PIPE_TRANSFER_READ_WRITE;
363 }
364
365 assert(face == 0);
366 assert(level == 0);
367 assert(zslice == 0);
368
369 /* FIXME: keep map count? */
370 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
371
372 /* install this linear image in texture data structure */
373 lpr->linear[level].data = map;
374
375 /* make sure tiled data gets converted to linear data */
376 map2 = llvmpipe_get_texture_image(lpr, 0, 0, tex_usage, layout);
377 if (layout == LP_TEX_LAYOUT_LINEAR)
378 assert(map == map2);
379
380 return map2;
381 }
382 else if (resource_is_texture(resource)) {
383 /* regular texture */
384 if (resource->target != PIPE_TEXTURE_CUBE) {
385 assert(face == 0);
386 }
387 if (resource->target != PIPE_TEXTURE_3D) {
388 assert(zslice == 0);
389 }
390
391 map = llvmpipe_get_texture_image(lpr, face + zslice, level,
392 tex_usage, layout);
393 return map;
394 }
395 else {
396 return lpr->data;
397 }
398 }
399
400
401 /**
402 * Unmap a resource.
403 */
404 void
405 llvmpipe_resource_unmap(struct pipe_resource *resource,
406 unsigned face,
407 unsigned level,
408 unsigned zslice)
409 {
410 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
411
412 if (lpr->dt) {
413 /* display target */
414 struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen);
415 struct sw_winsys *winsys = lp_screen->winsys;
416
417 assert(face == 0);
418 assert(level == 0);
419 assert(zslice == 0);
420
421 /* make sure linear image is up to date */
422 (void) llvmpipe_get_texture_image(lpr, face + zslice, level,
423 LP_TEX_USAGE_READ,
424 LP_TEX_LAYOUT_LINEAR);
425
426 winsys->displaytarget_unmap(winsys, lpr->dt);
427 }
428 }
429
430
431 void *
432 llvmpipe_resource_data(struct pipe_resource *resource)
433 {
434 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
435
436 assert(!resource_is_texture(resource));
437
438 return lpr->data;
439 }
440
441
442 static struct pipe_resource *
443 llvmpipe_resource_from_handle(struct pipe_screen *screen,
444 const struct pipe_resource *template,
445 struct winsys_handle *whandle)
446 {
447 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
448 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
449 unsigned width, height, width_t, height_t;
450
451 /* XXX Seems like from_handled depth textures doesn't work that well */
452
453 if (!lpr)
454 return NULL;
455
456 lpr->base = *template;
457 pipe_reference_init(&lpr->base.reference, 1);
458 lpr->base.screen = screen;
459
460 width = align(lpr->base.width0, TILE_SIZE);
461 height = align(lpr->base.height0, TILE_SIZE);
462 width_t = width / TILE_SIZE;
463 height_t = height / TILE_SIZE;
464
465 /*
466 * Looks like unaligned displaytargets work just fine,
467 * at least sampler/render ones.
468 */
469 #if 0
470 assert(lpr->base.width0 == width);
471 assert(lpr->base.height0 == height);
472 #endif
473
474 lpr->tiles_per_row[0] = width_t;
475 lpr->tiles_per_image[0] = width_t * height_t;
476 lpr->num_slices_faces[0] = 1;
477 lpr->img_stride[0] = 0;
478
479 lpr->dt = winsys->displaytarget_from_handle(winsys,
480 template,
481 whandle,
482 &lpr->row_stride[0]);
483 if (!lpr->dt)
484 goto fail;
485
486 lpr->layout[0] = alloc_layout_array(1, lpr->base.width0, lpr->base.height0);
487
488 assert(lpr->layout[0]);
489 assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
490
491 lpr->id = id_counter++;
492
493 #ifdef DEBUG
494 insert_at_tail(&resource_list, lpr);
495 #endif
496
497 return &lpr->base;
498
499 fail:
500 FREE(lpr);
501 return NULL;
502 }
503
504
505 static boolean
506 llvmpipe_resource_get_handle(struct pipe_screen *screen,
507 struct pipe_resource *pt,
508 struct winsys_handle *whandle)
509 {
510 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
511 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
512
513 assert(lpr->dt);
514 if (!lpr->dt)
515 return FALSE;
516
517 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
518 }
519
520
521 static struct pipe_surface *
522 llvmpipe_get_tex_surface(struct pipe_screen *screen,
523 struct pipe_resource *pt,
524 unsigned face, unsigned level, unsigned zslice,
525 unsigned usage)
526 {
527 struct pipe_surface *ps;
528
529 assert(level <= pt->last_level);
530
531 ps = CALLOC_STRUCT(pipe_surface);
532 if (ps) {
533 pipe_reference_init(&ps->reference, 1);
534 pipe_resource_reference(&ps->texture, pt);
535 ps->format = pt->format;
536 ps->width = u_minify(pt->width0, level);
537 ps->height = u_minify(pt->height0, level);
538 ps->usage = usage;
539
540 ps->face = face;
541 ps->level = level;
542 ps->zslice = zslice;
543 }
544 return ps;
545 }
546
547
548 static void
549 llvmpipe_tex_surface_destroy(struct pipe_surface *surf)
550 {
551 /* Effectively do the texture_update work here - if texture images
552 * needed post-processing to put them into hardware layout, this is
553 * where it would happen. For llvmpipe, nothing to do.
554 */
555 assert(surf->texture);
556 pipe_resource_reference(&surf->texture, NULL);
557 FREE(surf);
558 }
559
560
561 static struct pipe_transfer *
562 llvmpipe_get_transfer(struct pipe_context *pipe,
563 struct pipe_resource *resource,
564 struct pipe_subresource sr,
565 unsigned usage,
566 const struct pipe_box *box)
567 {
568 struct llvmpipe_resource *lprex = llvmpipe_resource(resource);
569 struct llvmpipe_transfer *lpr;
570
571 assert(resource);
572 assert(sr.level <= resource->last_level);
573
574 /*
575 * Transfers, like other pipe operations, must happen in order, so flush the
576 * context if necessary.
577 */
578 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
579 boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
580 boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
581 if (!llvmpipe_flush_resource(pipe, resource,
582 sr.face, sr.level,
583 0, /* flush_flags */
584 read_only,
585 TRUE, /* cpu_access */
586 do_not_block)) {
587 /*
588 * It would have blocked, but state tracker requested no to.
589 */
590 assert(do_not_block);
591 return NULL;
592 }
593 }
594
595 lpr = CALLOC_STRUCT(llvmpipe_transfer);
596 if (lpr) {
597 struct pipe_transfer *pt = &lpr->base;
598 pipe_resource_reference(&pt->resource, resource);
599 pt->box = *box;
600 pt->sr = sr;
601 pt->stride = lprex->row_stride[sr.level];
602 pt->slice_stride = lprex->img_stride[sr.level];
603 pt->usage = usage;
604
605 return pt;
606 }
607 return NULL;
608 }
609
610
611 static void
612 llvmpipe_transfer_destroy(struct pipe_context *pipe,
613 struct pipe_transfer *transfer)
614 {
615 /* Effectively do the texture_update work here - if texture images
616 * needed post-processing to put them into hardware layout, this is
617 * where it would happen. For llvmpipe, nothing to do.
618 */
619 assert (transfer->resource);
620 pipe_resource_reference(&transfer->resource, NULL);
621 FREE(transfer);
622 }
623
624
625 static void *
626 llvmpipe_transfer_map( struct pipe_context *pipe,
627 struct pipe_transfer *transfer )
628 {
629 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
630 ubyte *map;
631 struct llvmpipe_resource *lpr;
632 enum pipe_format format;
633 enum lp_texture_usage tex_usage;
634 const char *mode;
635
636 assert(transfer->sr.face < 6);
637 assert(transfer->sr.level < LP_MAX_TEXTURE_LEVELS);
638
639 /*
640 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n",
641 transfer->x, transfer->y, transfer->width, transfer->height,
642 transfer->texture->width0,
643 transfer->texture->height0,
644 transfer->usage);
645 */
646
647 if (transfer->usage == PIPE_TRANSFER_READ) {
648 tex_usage = LP_TEX_USAGE_READ;
649 mode = "read";
650 }
651 else {
652 tex_usage = LP_TEX_USAGE_READ_WRITE;
653 mode = "read/write";
654 }
655
656 if (0) {
657 struct llvmpipe_resource *lpr = llvmpipe_resource(transfer->resource);
658 printf("transfer map tex %u mode %s\n", lpr->id, mode);
659 }
660
661
662 assert(transfer->resource);
663 lpr = llvmpipe_resource(transfer->resource);
664 format = lpr->base.format;
665
666 map = llvmpipe_resource_map(transfer->resource,
667 transfer->sr.face,
668 transfer->sr.level,
669 transfer->box.z,
670 tex_usage, LP_TEX_LAYOUT_LINEAR);
671
672
673 /* May want to do different things here depending on read/write nature
674 * of the map:
675 */
676 if (transfer->usage & PIPE_TRANSFER_WRITE) {
677 /* Do something to notify sharing contexts of a texture change.
678 */
679 screen->timestamp++;
680 }
681
682 map +=
683 transfer->box.y / util_format_get_blockheight(format) * transfer->stride +
684 transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
685
686 return map;
687 }
688
689
690 static void
691 llvmpipe_transfer_unmap(struct pipe_context *pipe,
692 struct pipe_transfer *transfer)
693 {
694 assert(transfer->resource);
695
696 llvmpipe_resource_unmap(transfer->resource,
697 transfer->sr.face,
698 transfer->sr.level,
699 transfer->box.z);
700 }
701
702 static unsigned int
703 llvmpipe_is_resource_referenced( struct pipe_context *pipe,
704 struct pipe_resource *presource,
705 unsigned face, unsigned level)
706 {
707 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
708
709 if (presource->target == PIPE_BUFFER)
710 return PIPE_UNREFERENCED;
711
712 return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
713 }
714
715
716
717 /**
718 * Create buffer which wraps user-space data.
719 */
720 static struct pipe_resource *
721 llvmpipe_user_buffer_create(struct pipe_screen *screen,
722 void *ptr,
723 unsigned bytes,
724 unsigned bind_flags)
725 {
726 struct llvmpipe_resource *buffer;
727
728 buffer = CALLOC_STRUCT(llvmpipe_resource);
729 if(!buffer)
730 return NULL;
731
732 pipe_reference_init(&buffer->base.reference, 1);
733 buffer->base.screen = screen;
734 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
735 buffer->base.bind = bind_flags;
736 buffer->base.usage = PIPE_USAGE_IMMUTABLE;
737 buffer->base.flags = 0;
738 buffer->base.width0 = bytes;
739 buffer->base.height0 = 1;
740 buffer->base.depth0 = 1;
741 buffer->userBuffer = TRUE;
742 buffer->data = ptr;
743
744 return &buffer->base;
745 }
746
747
748 /**
749 * Compute size (in bytes) need to store a texture image / mipmap level,
750 * for just one cube face or one 3D texture slice
751 */
752 static unsigned
753 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level,
754 enum lp_texture_layout layout)
755 {
756 const unsigned width = u_minify(lpr->base.width0, level);
757 const unsigned height = u_minify(lpr->base.height0, level);
758
759 assert(layout == LP_TEX_LAYOUT_TILED ||
760 layout == LP_TEX_LAYOUT_LINEAR);
761
762 if (layout == LP_TEX_LAYOUT_TILED) {
763 /* for tiled layout, force a 32bpp format */
764 const enum pipe_format format = PIPE_FORMAT_B8G8R8A8_UNORM;
765 const unsigned block_size = util_format_get_blocksize(format);
766 const unsigned nblocksy =
767 util_format_get_nblocksy(format, align(height, TILE_SIZE));
768 const unsigned nblocksx =
769 util_format_get_nblocksx(format, align(width, TILE_SIZE));
770 const unsigned buffer_size = block_size * nblocksy * nblocksx;
771 return buffer_size;
772 }
773 else {
774 /* we already computed this */
775 return lpr->img_stride[level];
776 }
777 }
778
779
780 /**
781 * Compute size (in bytes) need to store a texture image / mipmap level,
782 * including all cube faces or 3D image slices
783 */
784 static unsigned
785 tex_image_size(const struct llvmpipe_resource *lpr, unsigned level,
786 enum lp_texture_layout layout)
787 {
788 const unsigned buf_size = tex_image_face_size(lpr, level, layout);
789 return buf_size * lpr->num_slices_faces[level];
790 }
791
792
793 /**
794 * This function encapsulates some complicated logic for determining
795 * how to convert a tile of image data from linear layout to tiled
796 * layout, or vice versa.
797 * \param cur_layout the current tile layout
798 * \param target_layout the desired tile layout
799 * \param usage how the tile will be accessed (R/W vs. read-only, etc)
800 * \param new_layout_return returns the new layout mode
801 * \param convert_return returns TRUE if image conversion is needed
802 */
803 static void
804 layout_logic(enum lp_texture_layout cur_layout,
805 enum lp_texture_layout target_layout,
806 enum lp_texture_usage usage,
807 enum lp_texture_layout *new_layout_return,
808 boolean *convert)
809 {
810 enum lp_texture_layout other_layout, new_layout;
811
812 *convert = FALSE;
813
814 new_layout = 99; /* debug check */
815
816 if (target_layout == LP_TEX_LAYOUT_LINEAR) {
817 other_layout = LP_TEX_LAYOUT_TILED;
818 }
819 else {
820 assert(target_layout == LP_TEX_LAYOUT_TILED);
821 other_layout = LP_TEX_LAYOUT_LINEAR;
822 }
823
824 new_layout = target_layout; /* may get changed below */
825
826 if (cur_layout == LP_TEX_LAYOUT_BOTH) {
827 if (usage == LP_TEX_USAGE_READ) {
828 new_layout = LP_TEX_LAYOUT_BOTH;
829 }
830 }
831 else if (cur_layout == other_layout) {
832 if (usage != LP_TEX_USAGE_WRITE_ALL) {
833 /* need to convert tiled data to linear or vice versa */
834 *convert = TRUE;
835
836 if (usage == LP_TEX_USAGE_READ)
837 new_layout = LP_TEX_LAYOUT_BOTH;
838 }
839 }
840 else {
841 assert(cur_layout == LP_TEX_LAYOUT_NONE ||
842 cur_layout == target_layout);
843 }
844
845 assert(new_layout == LP_TEX_LAYOUT_BOTH ||
846 new_layout == target_layout);
847
848 *new_layout_return = new_layout;
849 }
850
851
852 /**
853 * Return pointer to a 2D texture image/face/slice.
854 * No tiled/linear conversion is done.
855 */
856 ubyte *
857 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
858 unsigned face_slice, unsigned level,
859 enum lp_texture_layout layout)
860 {
861 struct llvmpipe_texture_image *img;
862 unsigned offset;
863
864 if (layout == LP_TEX_LAYOUT_LINEAR) {
865 img = &lpr->linear[level];
866 }
867 else {
868 assert (layout == LP_TEX_LAYOUT_TILED);
869 img = &lpr->tiled[level];
870 }
871
872 if (face_slice > 0)
873 offset = face_slice * tex_image_face_size(lpr, level, layout);
874 else
875 offset = 0;
876
877 return (ubyte *) img->data + offset;
878 }
879
880
881 static INLINE enum lp_texture_layout
882 llvmpipe_get_texture_tile_layout(const struct llvmpipe_resource *lpr,
883 unsigned face_slice, unsigned level,
884 unsigned x, unsigned y)
885 {
886 uint i;
887 assert(resource_is_texture(&lpr->base));
888 assert(x < lpr->tiles_per_row[level]);
889 i = face_slice * lpr->tiles_per_image[level]
890 + y * lpr->tiles_per_row[level] + x;
891 return lpr->layout[level][i];
892 }
893
894
895 static INLINE void
896 llvmpipe_set_texture_tile_layout(struct llvmpipe_resource *lpr,
897 unsigned face_slice, unsigned level,
898 unsigned x, unsigned y,
899 enum lp_texture_layout layout)
900 {
901 uint i;
902 assert(resource_is_texture(&lpr->base));
903 assert(x < lpr->tiles_per_row[level]);
904 i = face_slice * lpr->tiles_per_image[level]
905 + y * lpr->tiles_per_row[level] + x;
906 lpr->layout[level][i] = layout;
907 }
908
909
910 /**
911 * Set the layout mode for all tiles in a particular image.
912 */
913 static INLINE void
914 llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr,
915 unsigned face_slice, unsigned level,
916 unsigned width_t, unsigned height_t,
917 enum lp_texture_layout layout)
918 {
919 const unsigned start = face_slice * lpr->tiles_per_image[level];
920 unsigned i;
921
922 for (i = 0; i < width_t * height_t; i++) {
923 lpr->layout[level][start + i] = layout;
924 }
925 }
926
927
928 /**
929 * Allocate storage for a linear or tile texture image (all cube
930 * faces and all 3D slices.
931 */
932 static void
933 alloc_image_data(struct llvmpipe_resource *lpr, unsigned level,
934 enum lp_texture_layout layout)
935 {
936 uint alignment = MAX2(16, util_cpu_caps.cacheline);
937
938 if (lpr->dt)
939 assert(level == 0);
940
941 if (layout == LP_TEX_LAYOUT_TILED) {
942 /* tiled data is stored in regular memory */
943 uint buffer_size = tex_image_size(lpr, level, layout);
944 lpr->tiled[level].data = align_malloc(buffer_size, alignment);
945 }
946 else {
947 assert(layout == LP_TEX_LAYOUT_LINEAR);
948 if (lpr->dt) {
949 /* we get the linear memory from the winsys */
950 struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen);
951 struct sw_winsys *winsys = screen->winsys;
952
953 lpr->linear[0].data =
954 winsys->displaytarget_map(winsys, lpr->dt,
955 PIPE_TRANSFER_READ_WRITE);
956 }
957 else {
958 /* not a display target - allocate regular memory */
959 uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR);
960 lpr->linear[level].data = align_malloc(buffer_size, alignment);
961 }
962 }
963 }
964
965
966
967 /**
968 * Return pointer to texture image data (either linear or tiled layout)
969 * for a particular cube face or 3D texture slice.
970 *
971 * \param face_slice the cube face or 3D slice of interest
972 * \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE
973 * \param layout either LP_TEX_LAYOUT_LINEAR or _TILED or _NONE
974 */
975 void *
976 llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
977 unsigned face_slice, unsigned level,
978 enum lp_texture_usage usage,
979 enum lp_texture_layout layout)
980 {
981 /*
982 * 'target' refers to the image which we're retrieving (either in
983 * tiled or linear layout).
984 * 'other' refers to the same image but in the other layout. (it may
985 * or may not exist.
986 */
987 struct llvmpipe_texture_image *target_img;
988 struct llvmpipe_texture_image *other_img;
989 void *target_data;
990 void *other_data;
991 const unsigned width = u_minify(lpr->base.width0, level);
992 const unsigned height = u_minify(lpr->base.height0, level);
993 const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
994 const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
995 enum lp_texture_layout other_layout;
996 boolean only_allocate;
997
998 assert(layout == LP_TEX_LAYOUT_NONE ||
999 layout == LP_TEX_LAYOUT_TILED ||
1000 layout == LP_TEX_LAYOUT_LINEAR);
1001
1002 assert(usage == LP_TEX_USAGE_READ ||
1003 usage == LP_TEX_USAGE_READ_WRITE ||
1004 usage == LP_TEX_USAGE_WRITE_ALL);
1005
1006 /* check for the special case of layout == LP_TEX_LAYOUT_NONE */
1007 if (layout == LP_TEX_LAYOUT_NONE) {
1008 only_allocate = TRUE;
1009 layout = LP_TEX_LAYOUT_TILED;
1010 }
1011 else {
1012 only_allocate = FALSE;
1013 }
1014
1015 if (lpr->dt) {
1016 assert(lpr->linear[level].data);
1017 }
1018
1019 /* which is target? which is other? */
1020 if (layout == LP_TEX_LAYOUT_LINEAR) {
1021 target_img = &lpr->linear[level];
1022 other_img = &lpr->tiled[level];
1023 other_layout = LP_TEX_LAYOUT_TILED;
1024 }
1025 else {
1026 target_img = &lpr->tiled[level];
1027 other_img = &lpr->linear[level];
1028 other_layout = LP_TEX_LAYOUT_LINEAR;
1029 }
1030
1031 target_data = target_img->data;
1032 other_data = other_img->data;
1033
1034 if (!target_data) {
1035 /* allocate memory for the target image now */
1036 alloc_image_data(lpr, level, layout);
1037 target_data = target_img->data;
1038 }
1039
1040 if (face_slice > 0) {
1041 unsigned target_offset, other_offset;
1042
1043 target_offset = face_slice * tex_image_face_size(lpr, level, layout);
1044 other_offset = face_slice * tex_image_face_size(lpr, level, other_layout);
1045 if (target_data) {
1046 target_data = (uint8_t *) target_data + target_offset;
1047 }
1048 if (other_data) {
1049 other_data = (uint8_t *) other_data + other_offset;
1050 }
1051 }
1052
1053 if (only_allocate) {
1054 /* Just allocating tiled memory. Don't initialize it from the
1055 * linear data if it exists.
1056 */
1057 return target_data;
1058 }
1059
1060 if (other_data) {
1061 /* may need to convert other data to the requested layout */
1062 enum lp_texture_layout new_layout;
1063 unsigned x, y;
1064
1065 /* loop over all image tiles, doing layout conversion where needed */
1066 for (y = 0; y < height_t; y++) {
1067 for (x = 0; x < width_t; x++) {
1068 enum lp_texture_layout cur_layout =
1069 llvmpipe_get_texture_tile_layout(lpr, face_slice, level, x, y);
1070 boolean convert;
1071
1072 layout_logic(cur_layout, layout, usage, &new_layout, &convert);
1073
1074 if (convert && other_data && target_data) {
1075 if (layout == LP_TEX_LAYOUT_TILED) {
1076 lp_linear_to_tiled(other_data, target_data,
1077 x * TILE_SIZE, y * TILE_SIZE,
1078 TILE_SIZE, TILE_SIZE,
1079 lpr->base.format,
1080 lpr->row_stride[level],
1081 lpr->tiles_per_row[level]);
1082 }
1083 else {
1084 assert(layout == LP_TEX_LAYOUT_LINEAR);
1085 lp_tiled_to_linear(other_data, target_data,
1086 x * TILE_SIZE, y * TILE_SIZE,
1087 TILE_SIZE, TILE_SIZE,
1088 lpr->base.format,
1089 lpr->row_stride[level],
1090 lpr->tiles_per_row[level]);
1091 }
1092 }
1093
1094 if (new_layout != cur_layout)
1095 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, x, y,
1096 new_layout);
1097 }
1098 }
1099 }
1100 else {
1101 /* no other data */
1102 llvmpipe_set_texture_image_layout(lpr, face_slice, level,
1103 width_t, height_t, layout);
1104 }
1105
1106 return target_data;
1107 }
1108
1109
1110 /**
1111 * Return pointer to start of a texture image (1D, 2D, 3D, CUBE).
1112 * All cube faces and 3D slices will be converted to the requested
1113 * layout if needed.
1114 * This is typically used when we're about to sample from a texture.
1115 */
1116 void *
1117 llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
1118 unsigned level,
1119 enum lp_texture_usage usage,
1120 enum lp_texture_layout layout)
1121 {
1122 const int slices = lpr->num_slices_faces[level];
1123 int slice;
1124 void *map = NULL;
1125
1126 assert(slices > 0);
1127
1128 for (slice = slices - 1; slice >= 0; slice--) {
1129 map = llvmpipe_get_texture_image(lpr, slice, level, usage, layout);
1130 }
1131
1132 return map;
1133 }
1134
1135
1136 /**
1137 * Get pointer to a linear image (not the tile!) where the tile at (x,y)
1138 * is known to be in linear layout.
1139 * Conversion from tiled to linear will be done if necessary.
1140 * \return pointer to start of image/face (not the tile)
1141 */
1142 ubyte *
1143 llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
1144 unsigned face_slice, unsigned level,
1145 enum lp_texture_usage usage,
1146 unsigned x, unsigned y)
1147 {
1148 struct llvmpipe_texture_image *linear_img = &lpr->linear[level];
1149 enum lp_texture_layout cur_layout, new_layout;
1150 const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
1151 boolean convert;
1152 uint8_t *tiled_image, *linear_image;
1153
1154 assert(resource_is_texture(&lpr->base));
1155 assert(x % TILE_SIZE == 0);
1156 assert(y % TILE_SIZE == 0);
1157
1158 if (!linear_img->data) {
1159 /* allocate memory for the linear image now */
1160 alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR);
1161 }
1162
1163 /* compute address of the slice/face of the image that contains the tile */
1164 tiled_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
1165 LP_TEX_LAYOUT_TILED);
1166 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
1167 LP_TEX_LAYOUT_LINEAR);
1168
1169 /* get current tile layout and determine if data conversion is needed */
1170 cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty);
1171
1172 layout_logic(cur_layout, LP_TEX_LAYOUT_LINEAR, usage,
1173 &new_layout, &convert);
1174
1175 if (convert && tiled_image && linear_image) {
1176 lp_tiled_to_linear(tiled_image, linear_image,
1177 x, y, TILE_SIZE, TILE_SIZE, lpr->base.format,
1178 lpr->row_stride[level],
1179 lpr->tiles_per_row[level]);
1180 }
1181
1182 if (new_layout != cur_layout)
1183 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout);
1184
1185 return linear_image;
1186 }
1187
1188
1189 /**
1190 * Get pointer to tiled data for rendering.
1191 * \return pointer to the tiled data at the given tile position
1192 */
1193 ubyte *
1194 llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr,
1195 unsigned face_slice, unsigned level,
1196 enum lp_texture_usage usage,
1197 unsigned x, unsigned y)
1198 {
1199 struct llvmpipe_texture_image *tiled_img = &lpr->tiled[level];
1200 enum lp_texture_layout cur_layout, new_layout;
1201 const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
1202 boolean convert;
1203 uint8_t *tiled_image, *linear_image;
1204 unsigned tile_offset;
1205
1206 assert(x % TILE_SIZE == 0);
1207 assert(y % TILE_SIZE == 0);
1208
1209 if (!tiled_img->data) {
1210 /* allocate memory for the tiled image now */
1211 alloc_image_data(lpr, level, LP_TEX_LAYOUT_TILED);
1212 }
1213
1214 /* compute address of the slice/face of the image that contains the tile */
1215 tiled_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
1216 LP_TEX_LAYOUT_TILED);
1217 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
1218 LP_TEX_LAYOUT_LINEAR);
1219
1220 /* get current tile layout and see if we need to convert the data */
1221 cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty);
1222
1223 layout_logic(cur_layout, LP_TEX_LAYOUT_TILED, usage, &new_layout, &convert);
1224 if (convert && linear_image && tiled_image) {
1225 lp_linear_to_tiled(linear_image, tiled_image,
1226 x, y, TILE_SIZE, TILE_SIZE, lpr->base.format,
1227 lpr->row_stride[level],
1228 lpr->tiles_per_row[level]);
1229 }
1230
1231 if (!tiled_image)
1232 return NULL;
1233
1234 if (new_layout != cur_layout)
1235 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout);
1236
1237 /* compute, return address of the 64x64 tile */
1238 tile_offset = (ty * lpr->tiles_per_row[level] + tx)
1239 * TILE_SIZE * TILE_SIZE * 4;
1240
1241 return (ubyte *) tiled_image + tile_offset;
1242 }
1243
1244
1245 /**
1246 * Get pointer to tiled data for rendering.
1247 * \return pointer to the tiled data at the given tile position
1248 */
1249 void
1250 llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr,
1251 unsigned face_slice, unsigned level,
1252 unsigned x, unsigned y,
1253 uint8_t *tile)
1254 {
1255 struct llvmpipe_texture_image *linear_img = &lpr->linear[level];
1256 const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
1257 uint8_t *linear_image;
1258
1259 assert(x % TILE_SIZE == 0);
1260 assert(y % TILE_SIZE == 0);
1261
1262 if (!linear_img->data) {
1263 /* allocate memory for the linear image now */
1264 alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR);
1265 }
1266
1267 /* compute address of the slice/face of the image that contains the tile */
1268 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
1269 LP_TEX_LAYOUT_LINEAR);
1270
1271 {
1272 uint ii = x, jj = y;
1273 uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE;
1274 uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4;
1275
1276 /* Note that lp_tiled_to_linear expects the tile parameter to
1277 * point at the first tile in a whole-image sized array. In
1278 * this code, we have only a single tile and have to do some
1279 * pointer arithmetic to figure out where the "image" would have
1280 * started.
1281 */
1282 lp_tiled_to_linear(tile - byte_offset, linear_image,
1283 x, y, TILE_SIZE, TILE_SIZE,
1284 lpr->base.format,
1285 lpr->row_stride[level],
1286 1); /* tiles per row */
1287 }
1288
1289 llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty,
1290 LP_TEX_LAYOUT_LINEAR);
1291 }
1292
1293
1294 /**
1295 * Get pointer to tiled data for rendering.
1296 * \return pointer to the tiled data at the given tile position
1297 */
1298 void
1299 llvmpipe_swizzle_cbuf_tile(struct llvmpipe_resource *lpr,
1300 unsigned face_slice, unsigned level,
1301 unsigned x, unsigned y,
1302 uint8_t *tile)
1303 {
1304 uint8_t *linear_image;
1305
1306 assert(x % TILE_SIZE == 0);
1307 assert(y % TILE_SIZE == 0);
1308
1309 /* compute address of the slice/face of the image that contains the tile */
1310 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
1311 LP_TEX_LAYOUT_LINEAR);
1312
1313 if (linear_image) {
1314 uint ii = x, jj = y;
1315 uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE;
1316 uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4;
1317
1318 /* Note that lp_linear_to_tiled expects the tile parameter to
1319 * point at the first tile in a whole-image sized array. In
1320 * this code, we have only a single tile and have to do some
1321 * pointer arithmetic to figure out where the "image" would have
1322 * started.
1323 */
1324 lp_linear_to_tiled(linear_image, tile - byte_offset,
1325 x, y, TILE_SIZE, TILE_SIZE,
1326 lpr->base.format,
1327 lpr->row_stride[level],
1328 1); /* tiles per row */
1329 }
1330 }
1331
1332
1333 /**
1334 * Return size of resource in bytes
1335 */
1336 unsigned
1337 llvmpipe_resource_size(const struct pipe_resource *resource)
1338 {
1339 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
1340 unsigned lvl, size = 0;
1341
1342 for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
1343 if (lpr->linear[lvl].data)
1344 size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR);
1345
1346 if (lpr->tiled[lvl].data)
1347 size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED);
1348 }
1349
1350 return size;
1351 }
1352
1353
1354 #ifdef DEBUG
1355 void
1356 llvmpipe_print_resources(void)
1357 {
1358 struct llvmpipe_resource *lpr;
1359 unsigned n = 0, total = 0;
1360
1361 debug_printf("LLVMPIPE: current resources:\n");
1362 foreach(lpr, &resource_list) {
1363 unsigned size = llvmpipe_resource_size(&lpr->base);
1364 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
1365 lpr->id, (void *) lpr,
1366 lpr->base.width0, lpr->base.height0, lpr->base.depth0,
1367 size, lpr->base.reference.count);
1368 total += size;
1369 n++;
1370 }
1371 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
1372 }
1373 #endif
1374
1375
1376 void
1377 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
1378 {
1379 #ifdef DEBUG
1380 /* init linked list for tracking resources */
1381 {
1382 static boolean first_call = TRUE;
1383 if (first_call) {
1384 memset(&resource_list, 0, sizeof(resource_list));
1385 make_empty_list(&resource_list);
1386 first_call = FALSE;
1387 }
1388 }
1389 #endif
1390
1391 screen->resource_create = llvmpipe_resource_create;
1392 screen->resource_destroy = llvmpipe_resource_destroy;
1393 screen->resource_from_handle = llvmpipe_resource_from_handle;
1394 screen->resource_get_handle = llvmpipe_resource_get_handle;
1395 screen->user_buffer_create = llvmpipe_user_buffer_create;
1396
1397 screen->get_tex_surface = llvmpipe_get_tex_surface;
1398 screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
1399 }
1400
1401
1402 void
1403 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
1404 {
1405 pipe->get_transfer = llvmpipe_get_transfer;
1406 pipe->transfer_destroy = llvmpipe_transfer_destroy;
1407 pipe->transfer_map = llvmpipe_transfer_map;
1408 pipe->transfer_unmap = llvmpipe_transfer_unmap;
1409 pipe->is_resource_referenced = llvmpipe_is_resource_referenced;
1410
1411 pipe->transfer_flush_region = u_default_transfer_flush_region;
1412 pipe->transfer_inline_write = u_default_transfer_inline_write;
1413 }