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