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