llvmpipe: allocate regular texture memory upfront
[mesa.git] / src / gallium / drivers / llvmpipe / lp_texture.c
1 /**************************************************************************
2 *
3 * Copyright 2006 VMware, Inc.
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 VMWARE 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 <keithw@vmware.com>
30 * Michel Dänzer <daenzer@vmware.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_texture.h"
50 #include "lp_setup.h"
51 #include "lp_state.h"
52 #include "lp_rast.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 static void
63 alloc_image_data(struct llvmpipe_resource *lpr);
64
65 /**
66 * Conventional allocation path for non-display textures:
67 * Just compute row strides here. Storage is allocated on demand later.
68 */
69 static boolean
70 llvmpipe_texture_layout(struct llvmpipe_screen *screen,
71 struct llvmpipe_resource *lpr)
72 {
73 struct pipe_resource *pt = &lpr->base;
74 unsigned level;
75 unsigned width = pt->width0;
76 unsigned height = pt->height0;
77 unsigned depth = pt->depth0;
78 uint64_t total_size = 0;
79 unsigned layers = pt->array_size;
80
81 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
82 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
83
84 for (level = 0; level <= pt->last_level; level++) {
85
86 /* Row stride and image stride */
87 {
88 unsigned align_x, align_y, nblocksx, nblocksy, block_size;
89
90 /* For non-compressed formats we need 4x4 pixel alignment
91 * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
92 * We also want cache line size in x direction,
93 * otherwise same cache line could end up in multiple threads.
94 * For explicit 1d resources however we reduce this to 4x1 and
95 * handle specially in render output code (as we need to do special
96 * handling there for buffers in any case).
97 */
98 if (util_format_is_compressed(pt->format))
99 align_x = align_y = 1;
100 else {
101 align_x = LP_RASTER_BLOCK_SIZE;
102 if (llvmpipe_resource_is_1d(&lpr->base))
103 align_y = 1;
104 else
105 align_y = LP_RASTER_BLOCK_SIZE;
106 }
107
108 nblocksx = util_format_get_nblocksx(pt->format,
109 align(width, align_x));
110 nblocksy = util_format_get_nblocksy(pt->format,
111 align(height, align_y));
112 block_size = util_format_get_blocksize(pt->format);
113
114 if (util_format_is_compressed(pt->format))
115 lpr->row_stride[level] = nblocksx * block_size;
116 else
117 lpr->row_stride[level] = align(nblocksx * block_size, util_cpu_caps.cacheline);
118
119 /* if row_stride * height > LP_MAX_TEXTURE_SIZE */
120 if ((uint64_t)lpr->row_stride[level] * nblocksy > LP_MAX_TEXTURE_SIZE) {
121 /* image too large */
122 goto fail;
123 }
124
125 lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
126 }
127
128 /* Number of 3D image slices, cube faces or texture array layers */
129 {
130 unsigned num_slices;
131
132 if (lpr->base.target == PIPE_TEXTURE_CUBE)
133 num_slices = 6;
134 else if (lpr->base.target == PIPE_TEXTURE_3D)
135 num_slices = depth;
136 else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
137 lpr->base.target == PIPE_TEXTURE_2D_ARRAY)
138 num_slices = layers;
139 else
140 num_slices = 1;
141
142 lpr->num_slices_faces[level] = num_slices;
143 }
144
145 /* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */
146 if (lpr->img_stride[level] >
147 LP_MAX_TEXTURE_SIZE / lpr->num_slices_faces[level]) {
148 /* volume too large */
149 goto fail;
150 }
151
152 total_size += (uint64_t) lpr->num_slices_faces[level]
153 * (uint64_t) lpr->img_stride[level];
154 if (total_size > LP_MAX_TEXTURE_SIZE) {
155 goto fail;
156 }
157
158 /* Compute size of next mipmap level */
159 width = u_minify(width, 1);
160 height = u_minify(height, 1);
161 depth = u_minify(depth, 1);
162 }
163
164 return TRUE;
165
166 fail:
167 return FALSE;
168 }
169
170
171 /**
172 * Check the size of the texture specified by 'res'.
173 * \return TRUE if OK, FALSE if too large.
174 */
175 static boolean
176 llvmpipe_can_create_resource(struct pipe_screen *screen,
177 const struct pipe_resource *res)
178 {
179 struct llvmpipe_resource lpr;
180 memset(&lpr, 0, sizeof(lpr));
181 lpr.base = *res;
182 return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr);
183 }
184
185
186 static boolean
187 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
188 struct llvmpipe_resource *lpr)
189 {
190 struct sw_winsys *winsys = screen->winsys;
191
192 /* Round up the surface size to a multiple of the tile size to
193 * avoid tile clipping.
194 */
195 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
196 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
197
198 lpr->num_slices_faces[0] = 1;
199 lpr->img_stride[0] = 0;
200
201 lpr->dt = winsys->displaytarget_create(winsys,
202 lpr->base.bind,
203 lpr->base.format,
204 width, height,
205 64,
206 &lpr->row_stride[0] );
207
208 if (lpr->dt == NULL)
209 return FALSE;
210
211 {
212 void *map = winsys->displaytarget_map(winsys, lpr->dt,
213 PIPE_TRANSFER_WRITE);
214
215 if (map)
216 memset(map, 0, height * lpr->row_stride[0]);
217
218 winsys->displaytarget_unmap(winsys, lpr->dt);
219 }
220
221 return TRUE;
222 }
223
224
225 static struct pipe_resource *
226 llvmpipe_resource_create(struct pipe_screen *_screen,
227 const struct pipe_resource *templat)
228 {
229 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
230 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
231 if (!lpr)
232 return NULL;
233
234 lpr->base = *templat;
235 pipe_reference_init(&lpr->base.reference, 1);
236 lpr->base.screen = &screen->base;
237
238 /* assert(lpr->base.bind); */
239
240 if (llvmpipe_resource_is_texture(&lpr->base)) {
241 if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
242 PIPE_BIND_SCANOUT |
243 PIPE_BIND_SHARED)) {
244 /* displayable surface */
245 if (!llvmpipe_displaytarget_layout(screen, lpr))
246 goto fail;
247 }
248 else {
249 /* texture map */
250 if (!llvmpipe_texture_layout(screen, lpr))
251 goto fail;
252
253 alloc_image_data(lpr);
254 if (!lpr->tex_data) {
255 goto fail;
256 }
257 }
258 }
259 else {
260 /* other data (vertex buffer, const buffer, etc) */
261 const uint bytes = templat->width0;
262 assert(util_format_get_blocksize(templat->format) == 1);
263 assert(templat->height0 == 1);
264 assert(templat->depth0 == 1);
265 assert(templat->last_level == 0);
266 /*
267 * Reserve some extra storage since if we'd render to a buffer we
268 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
269 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
270 */
271 lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 64);
272 /*
273 * buffers don't really have stride but it's probably safer
274 * (for code doing same calculations for buffers and textures)
275 * to put something sane in there.
276 */
277 lpr->row_stride[0] = bytes;
278 if (!lpr->data)
279 goto fail;
280 memset(lpr->data, 0, bytes);
281 }
282
283 lpr->id = id_counter++;
284
285 #ifdef DEBUG
286 insert_at_tail(&resource_list, lpr);
287 #endif
288
289 return &lpr->base;
290
291 fail:
292 FREE(lpr);
293 return NULL;
294 }
295
296
297 static void
298 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
299 struct pipe_resource *pt)
300 {
301 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
302 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
303
304 if (lpr->dt) {
305 /* display target */
306 struct sw_winsys *winsys = screen->winsys;
307 winsys->displaytarget_destroy(winsys, lpr->dt);
308 }
309 else if (llvmpipe_resource_is_texture(pt)) {
310 /* free linear image data */
311 if (lpr->tex_data) {
312 align_free(lpr->tex_data);
313 lpr->tex_data = NULL;
314 }
315 }
316 else if (!lpr->userBuffer) {
317 assert(lpr->data);
318 align_free(lpr->data);
319 }
320
321 #ifdef DEBUG
322 if (lpr->next)
323 remove_from_list(lpr);
324 #endif
325
326 FREE(lpr);
327 }
328
329
330 /**
331 * Map a resource for read/write.
332 */
333 void *
334 llvmpipe_resource_map(struct pipe_resource *resource,
335 unsigned level,
336 unsigned layer,
337 enum lp_texture_usage tex_usage)
338 {
339 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
340 uint8_t *map;
341
342 assert(level < LP_MAX_TEXTURE_LEVELS);
343 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
344
345 assert(tex_usage == LP_TEX_USAGE_READ ||
346 tex_usage == LP_TEX_USAGE_READ_WRITE ||
347 tex_usage == LP_TEX_USAGE_WRITE_ALL);
348
349 if (lpr->dt) {
350 /* display target */
351 struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
352 struct sw_winsys *winsys = screen->winsys;
353 unsigned dt_usage;
354
355 if (tex_usage == LP_TEX_USAGE_READ) {
356 dt_usage = PIPE_TRANSFER_READ;
357 }
358 else {
359 dt_usage = PIPE_TRANSFER_READ_WRITE;
360 }
361
362 assert(level == 0);
363 assert(layer == 0);
364
365 /* FIXME: keep map count? */
366 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
367
368 /* install this linear image in texture data structure */
369 lpr->tex_data = map;
370
371 return map;
372 }
373 else if (llvmpipe_resource_is_texture(resource)) {
374
375 map = llvmpipe_get_texture_image(lpr, layer, level, tex_usage);
376 return map;
377 }
378 else {
379 return lpr->data;
380 }
381 }
382
383
384 /**
385 * Unmap a resource.
386 */
387 void
388 llvmpipe_resource_unmap(struct pipe_resource *resource,
389 unsigned level,
390 unsigned layer)
391 {
392 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
393
394 if (lpr->dt) {
395 /* display target */
396 struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen);
397 struct sw_winsys *winsys = lp_screen->winsys;
398
399 assert(level == 0);
400 assert(layer == 0);
401
402 winsys->displaytarget_unmap(winsys, lpr->dt);
403 }
404 }
405
406
407 void *
408 llvmpipe_resource_data(struct pipe_resource *resource)
409 {
410 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
411
412 assert(!llvmpipe_resource_is_texture(resource));
413
414 return lpr->data;
415 }
416
417
418 static struct pipe_resource *
419 llvmpipe_resource_from_handle(struct pipe_screen *screen,
420 const struct pipe_resource *template,
421 struct winsys_handle *whandle)
422 {
423 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
424 struct llvmpipe_resource *lpr;
425
426 /* XXX Seems like from_handled depth textures doesn't work that well */
427
428 lpr = CALLOC_STRUCT(llvmpipe_resource);
429 if (!lpr) {
430 goto no_lpr;
431 }
432
433 lpr->base = *template;
434 pipe_reference_init(&lpr->base.reference, 1);
435 lpr->base.screen = screen;
436
437 /*
438 * Looks like unaligned displaytargets work just fine,
439 * at least sampler/render ones.
440 */
441 #if 0
442 assert(lpr->base.width0 == width);
443 assert(lpr->base.height0 == height);
444 #endif
445
446 lpr->num_slices_faces[0] = 1;
447 lpr->img_stride[0] = 0;
448
449 lpr->dt = winsys->displaytarget_from_handle(winsys,
450 template,
451 whandle,
452 &lpr->row_stride[0]);
453 if (!lpr->dt) {
454 goto no_dt;
455 }
456
457 lpr->id = id_counter++;
458
459 #ifdef DEBUG
460 insert_at_tail(&resource_list, lpr);
461 #endif
462
463 return &lpr->base;
464
465 no_dt:
466 FREE(lpr);
467 no_lpr:
468 return NULL;
469 }
470
471
472 static boolean
473 llvmpipe_resource_get_handle(struct pipe_screen *screen,
474 struct pipe_resource *pt,
475 struct winsys_handle *whandle)
476 {
477 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
478 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
479
480 assert(lpr->dt);
481 if (!lpr->dt)
482 return FALSE;
483
484 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
485 }
486
487
488 static void *
489 llvmpipe_transfer_map( struct pipe_context *pipe,
490 struct pipe_resource *resource,
491 unsigned level,
492 unsigned usage,
493 const struct pipe_box *box,
494 struct pipe_transfer **transfer )
495 {
496 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
497 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
498 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
499 struct llvmpipe_transfer *lpt;
500 struct pipe_transfer *pt;
501 ubyte *map;
502 enum pipe_format format;
503 enum lp_texture_usage tex_usage;
504 const char *mode;
505
506 assert(resource);
507 assert(level <= resource->last_level);
508
509 /*
510 * Transfers, like other pipe operations, must happen in order, so flush the
511 * context if necessary.
512 */
513 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
514 boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
515 boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
516 if (!llvmpipe_flush_resource(pipe, resource,
517 level,
518 read_only,
519 TRUE, /* cpu_access */
520 do_not_block,
521 __FUNCTION__)) {
522 /*
523 * It would have blocked, but state tracker requested no to.
524 */
525 assert(do_not_block);
526 return NULL;
527 }
528 }
529
530 /* Check if we're mapping the current constant buffer */
531 if ((usage & PIPE_TRANSFER_WRITE) &&
532 (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
533 unsigned i;
534 for (i = 0; i < Elements(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
535 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
536 /* constants may have changed */
537 llvmpipe->dirty |= LP_NEW_CONSTANTS;
538 break;
539 }
540 }
541 }
542
543 lpt = CALLOC_STRUCT(llvmpipe_transfer);
544 if (!lpt)
545 return NULL;
546 pt = &lpt->base;
547 pipe_resource_reference(&pt->resource, resource);
548 pt->box = *box;
549 pt->level = level;
550 pt->stride = lpr->row_stride[level];
551 pt->layer_stride = lpr->img_stride[level];
552 pt->usage = usage;
553 *transfer = pt;
554
555 assert(level < LP_MAX_TEXTURE_LEVELS);
556
557 /*
558 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n",
559 transfer->x, transfer->y, transfer->width, transfer->height,
560 transfer->texture->width0,
561 transfer->texture->height0,
562 transfer->usage);
563 */
564
565 if (usage == PIPE_TRANSFER_READ) {
566 tex_usage = LP_TEX_USAGE_READ;
567 mode = "read";
568 }
569 else {
570 tex_usage = LP_TEX_USAGE_READ_WRITE;
571 mode = "read/write";
572 }
573
574 if (0) {
575 printf("transfer map tex %u mode %s\n", lpr->id, mode);
576 }
577
578 format = lpr->base.format;
579
580 map = llvmpipe_resource_map(resource,
581 level,
582 box->z,
583 tex_usage);
584
585
586 /* May want to do different things here depending on read/write nature
587 * of the map:
588 */
589 if (usage & PIPE_TRANSFER_WRITE) {
590 /* Do something to notify sharing contexts of a texture change.
591 */
592 screen->timestamp++;
593 }
594
595 map +=
596 box->y / util_format_get_blockheight(format) * pt->stride +
597 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
598
599 return map;
600 }
601
602
603 static void
604 llvmpipe_transfer_unmap(struct pipe_context *pipe,
605 struct pipe_transfer *transfer)
606 {
607 assert(transfer->resource);
608
609 llvmpipe_resource_unmap(transfer->resource,
610 transfer->level,
611 transfer->box.z);
612
613 /* Effectively do the texture_update work here - if texture images
614 * needed post-processing to put them into hardware layout, this is
615 * where it would happen. For llvmpipe, nothing to do.
616 */
617 assert (transfer->resource);
618 pipe_resource_reference(&transfer->resource, NULL);
619 FREE(transfer);
620 }
621
622 unsigned int
623 llvmpipe_is_resource_referenced( struct pipe_context *pipe,
624 struct pipe_resource *presource,
625 unsigned level)
626 {
627 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
628
629 /*
630 * XXX checking only resources with the right bind flags
631 * is unsafe since with opengl state tracker we can end up
632 * with resources bound to places they weren't supposed to be
633 * (buffers bound as sampler views is one possibility here).
634 */
635 if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
636 PIPE_BIND_RENDER_TARGET |
637 PIPE_BIND_SAMPLER_VIEW)))
638 return LP_UNREFERENCED;
639
640 return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
641 }
642
643
644 /**
645 * Returns the largest possible alignment for a format in llvmpipe
646 */
647 unsigned
648 llvmpipe_get_format_alignment( enum pipe_format format )
649 {
650 const struct util_format_description *desc = util_format_description(format);
651 unsigned size = 0;
652 unsigned bytes;
653 unsigned i;
654
655 for (i = 0; i < desc->nr_channels; ++i) {
656 size += desc->channel[i].size;
657 }
658
659 bytes = size / 8;
660
661 if (!util_is_power_of_two(bytes)) {
662 bytes /= desc->nr_channels;
663 }
664
665 if (bytes % 2 || bytes < 1) {
666 return 1;
667 } else {
668 return bytes;
669 }
670 }
671
672
673 /**
674 * Create buffer which wraps user-space data.
675 */
676 struct pipe_resource *
677 llvmpipe_user_buffer_create(struct pipe_screen *screen,
678 void *ptr,
679 unsigned bytes,
680 unsigned bind_flags)
681 {
682 struct llvmpipe_resource *buffer;
683
684 buffer = CALLOC_STRUCT(llvmpipe_resource);
685 if(!buffer)
686 return NULL;
687
688 pipe_reference_init(&buffer->base.reference, 1);
689 buffer->base.screen = screen;
690 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
691 buffer->base.bind = bind_flags;
692 buffer->base.usage = PIPE_USAGE_IMMUTABLE;
693 buffer->base.flags = 0;
694 buffer->base.width0 = bytes;
695 buffer->base.height0 = 1;
696 buffer->base.depth0 = 1;
697 buffer->base.array_size = 1;
698 buffer->userBuffer = TRUE;
699 buffer->data = ptr;
700
701 return &buffer->base;
702 }
703
704
705 /**
706 * Compute size (in bytes) need to store a texture image / mipmap level,
707 * for just one cube face, one array layer or one 3D texture slice
708 */
709 static unsigned
710 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
711 {
712 return lpr->img_stride[level];
713 }
714
715
716 /**
717 * Compute size (in bytes) need to store a texture image / mipmap level,
718 * including all cube faces or 3D image slices
719 */
720 static unsigned
721 tex_image_size(const struct llvmpipe_resource *lpr, unsigned level)
722 {
723 const unsigned buf_size = tex_image_face_size(lpr, level);
724 return buf_size * lpr->num_slices_faces[level];
725 }
726
727
728 /**
729 * Return pointer to a 2D texture image/face/slice.
730 * No tiled/linear conversion is done.
731 */
732 ubyte *
733 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
734 unsigned face_slice, unsigned level)
735 {
736 unsigned offset;
737
738 offset = lpr->mip_offsets[level];
739
740 if (face_slice > 0)
741 offset += face_slice * tex_image_face_size(lpr, level);
742
743 return (ubyte *) lpr->tex_data + offset;
744 }
745
746
747 /**
748 * Allocate storage for a linear image
749 * (all cube faces and all 3D slices, all levels).
750 */
751 static void
752 alloc_image_data(struct llvmpipe_resource *lpr)
753 {
754 uint alignment = MAX2(64, util_cpu_caps.cacheline);
755 uint level;
756 uint offset = 0;
757
758 if (lpr->dt) {
759 /* we get the linear memory from the winsys, and it has
760 * already been zeroed
761 */
762 struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen);
763 struct sw_winsys *winsys = screen->winsys;
764
765 assert(lpr->base.last_level == 0);
766
767 lpr->tex_data =
768 winsys->displaytarget_map(winsys, lpr->dt,
769 PIPE_TRANSFER_READ_WRITE);
770 }
771 else {
772 /* not a display target - allocate regular memory */
773 /*
774 * Offset calculation for start of a specific mip/layer is always
775 * offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer
776 */
777 for (level = 0; level <= lpr->base.last_level; level++) {
778 uint buffer_size = tex_image_size(lpr, level);
779 lpr->mip_offsets[level] = offset;
780 offset += align(buffer_size, alignment);
781 }
782 lpr->tex_data = align_malloc(offset, alignment);
783 if (lpr->tex_data) {
784 memset(lpr->tex_data, 0, offset);
785 }
786 }
787 }
788
789
790
791 /**
792 * Return pointer to texture image data
793 * for a particular cube face or 3D texture slice.
794 *
795 * \param face_slice the cube face or 3D slice of interest
796 * \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE
797 */
798 void *
799 llvmpipe_get_texture_image(struct llvmpipe_resource *lpr,
800 unsigned face_slice, unsigned level,
801 enum lp_texture_usage usage)
802 {
803 void *target_data;
804 unsigned target_offset;
805 unsigned *target_off_ptr;
806
807 assert(usage == LP_TEX_USAGE_READ ||
808 usage == LP_TEX_USAGE_READ_WRITE ||
809 usage == LP_TEX_USAGE_WRITE_ALL);
810
811 if (lpr->dt) {
812 assert(lpr->tex_data);
813 }
814
815 target_off_ptr = lpr->mip_offsets;
816
817 if (!lpr->tex_data) {
818 /* allocate memory for the target image now */
819 alloc_image_data(lpr);
820 }
821
822 target_offset = target_off_ptr[level];
823
824 if (face_slice > 0) {
825 target_offset += face_slice * tex_image_face_size(lpr, level);
826 }
827
828 if (lpr->tex_data) {
829 target_data = (uint8_t *) lpr->tex_data + target_offset;
830 }
831
832 return target_data;
833 }
834
835
836 /**
837 * Return pointer to start of a texture image (1D, 2D, 3D, CUBE).
838 * This is typically used when we're about to sample from a texture.
839 */
840 void *
841 llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr,
842 unsigned level,
843 enum lp_texture_usage usage)
844 {
845 const int slices = lpr->num_slices_faces[level];
846 int slice;
847 void *map = NULL;
848
849 assert(slices > 0);
850
851 for (slice = slices - 1; slice >= 0; slice--) {
852 map = llvmpipe_get_texture_image(lpr, slice, level, usage);
853 }
854
855 return map;
856 }
857
858
859 /**
860 * Get pointer to a linear image (not the tile!) at tile (x,y).
861 * \return pointer to start of image/face (not the tile)
862 */
863 ubyte *
864 llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr,
865 unsigned face_slice, unsigned level,
866 enum lp_texture_usage usage,
867 unsigned x, unsigned y)
868 {
869 uint8_t *linear_image;
870
871 assert(llvmpipe_resource_is_texture(&lpr->base));
872 assert(x % TILE_SIZE == 0);
873 assert(y % TILE_SIZE == 0);
874
875 if (!lpr->tex_data) {
876 /* allocate memory for the linear image now */
877 /* XXX should probably not do that here? */
878 alloc_image_data(lpr);
879 }
880 assert(lpr->tex_data);
881
882 /* compute address of the slice/face of the image that contains the tile */
883 linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level);
884
885 return linear_image;
886 }
887
888
889 /**
890 * Return size of resource in bytes
891 */
892 unsigned
893 llvmpipe_resource_size(const struct pipe_resource *resource)
894 {
895 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
896 unsigned lvl, size = 0;
897
898 if (llvmpipe_resource_is_texture(resource)) {
899 for (lvl = 0; lvl <= lpr->base.last_level; lvl++) {
900 if (lpr->tex_data)
901 size += tex_image_size(lpr, lvl);
902 }
903 }
904 else {
905 size = resource->width0;
906 }
907
908 return size;
909 }
910
911
912 #ifdef DEBUG
913 void
914 llvmpipe_print_resources(void)
915 {
916 struct llvmpipe_resource *lpr;
917 unsigned n = 0, total = 0;
918
919 debug_printf("LLVMPIPE: current resources:\n");
920 foreach(lpr, &resource_list) {
921 unsigned size = llvmpipe_resource_size(&lpr->base);
922 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
923 lpr->id, (void *) lpr,
924 lpr->base.width0, lpr->base.height0, lpr->base.depth0,
925 size, lpr->base.reference.count);
926 total += size;
927 n++;
928 }
929 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
930 }
931 #endif
932
933
934 void
935 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
936 {
937 #ifdef DEBUG
938 /* init linked list for tracking resources */
939 {
940 static boolean first_call = TRUE;
941 if (first_call) {
942 memset(&resource_list, 0, sizeof(resource_list));
943 make_empty_list(&resource_list);
944 first_call = FALSE;
945 }
946 }
947 #endif
948
949 screen->resource_create = llvmpipe_resource_create;
950 screen->resource_destroy = llvmpipe_resource_destroy;
951 screen->resource_from_handle = llvmpipe_resource_from_handle;
952 screen->resource_get_handle = llvmpipe_resource_get_handle;
953 screen->can_create_resource = llvmpipe_can_create_resource;
954 }
955
956
957 void
958 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
959 {
960 pipe->transfer_map = llvmpipe_transfer_map;
961 pipe->transfer_unmap = llvmpipe_transfer_unmap;
962
963 pipe->transfer_flush_region = u_default_transfer_flush_region;
964 pipe->transfer_inline_write = u_default_transfer_inline_write;
965 }