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