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