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/format/u_format.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43 #include "util/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 "frontend/sw_winsys.h"
55 #include "git_sha1.h"
56
57 #ifndef _WIN32
58 #include "drm-uapi/drm_fourcc.h"
59 #endif
60
61
62 #ifdef DEBUG
63 static struct llvmpipe_resource resource_list;
64 static mtx_t resource_list_mutex = _MTX_INITIALIZER_NP;
65 #endif
66 static unsigned id_counter = 0;
67
68
69 /**
70 * Conventional allocation path for non-display textures:
71 * Compute strides and allocate data (unless asked not to).
72 */
73 static boolean
llvmpipe_texture_layout(struct llvmpipe_screen * screen,struct llvmpipe_resource * lpr,boolean allocate)74 llvmpipe_texture_layout(struct llvmpipe_screen *screen,
75 struct llvmpipe_resource *lpr,
76 boolean allocate)
77 {
78 struct pipe_resource *pt = &lpr->base;
79 unsigned level;
80 unsigned width = pt->width0;
81 unsigned height = pt->height0;
82 unsigned depth = pt->depth0;
83 uint64_t total_size = 0;
84 unsigned layers = pt->array_size;
85 unsigned num_samples = util_res_sample_count(pt);
86
87 /* XXX:
88 * This alignment here (same for displaytarget) was added for the purpose of
89 * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer
90 * resources. Otherwise we'd want the max of cacheline size and 16 (max size
91 * of a block for all formats) though this should not be strictly necessary
92 * neither. In any case it can only affect compressed or 1d textures.
93 */
94 unsigned mip_align = MAX2(64, util_get_cpu_caps()->cacheline);
95
96 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
97 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
98
99 for (level = 0; level <= pt->last_level; level++) {
100 uint64_t mipsize;
101 unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices;
102
103 /* Row stride and image stride */
104
105 /* For non-compressed formats we need 4x4 pixel alignment
106 * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
107 * We also want cache line size in x direction,
108 * otherwise same cache line could end up in multiple threads.
109 * For explicit 1d resources however we reduce this to 4x1 and
110 * handle specially in render output code (as we need to do special
111 * handling there for buffers in any case).
112 */
113 if (util_format_is_compressed(pt->format))
114 align_x = align_y = 1;
115 else {
116 align_x = LP_RASTER_BLOCK_SIZE;
117 if (llvmpipe_resource_is_1d(&lpr->base))
118 align_y = 1;
119 else
120 align_y = LP_RASTER_BLOCK_SIZE;
121 }
122
123 nblocksx = util_format_get_nblocksx(pt->format,
124 align(width, align_x));
125 nblocksy = util_format_get_nblocksy(pt->format,
126 align(height, align_y));
127 block_size = util_format_get_blocksize(pt->format);
128
129 if (util_format_is_compressed(pt->format))
130 lpr->row_stride[level] = nblocksx * block_size;
131 else
132 lpr->row_stride[level] = align(nblocksx * block_size, util_get_cpu_caps()->cacheline);
133
134 lpr->img_stride[level] = (uint64_t)lpr->row_stride[level] * nblocksy;
135
136 /* Number of 3D image slices, cube faces or texture array layers */
137 if (lpr->base.target == PIPE_TEXTURE_CUBE) {
138 assert(layers == 6);
139 }
140
141 if (lpr->base.target == PIPE_TEXTURE_3D)
142 num_slices = depth;
143 else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
144 lpr->base.target == PIPE_TEXTURE_2D_ARRAY ||
145 lpr->base.target == PIPE_TEXTURE_CUBE ||
146 lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY)
147 num_slices = layers;
148 else
149 num_slices = 1;
150
151 mipsize = lpr->img_stride[level] * num_slices;
152 lpr->mip_offsets[level] = total_size;
153
154 total_size += align64(mipsize, mip_align);
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 lpr->sample_stride = total_size;
163 total_size *= num_samples;
164
165 lpr->size_required = total_size;
166 if (allocate) {
167 if (total_size > LP_MAX_TEXTURE_SIZE)
168 goto fail;
169
170 lpr->tex_data = align_malloc(total_size, mip_align);
171 if (!lpr->tex_data) {
172 return FALSE;
173 }
174 else {
175 memset(lpr->tex_data, 0, total_size);
176 }
177 }
178
179 return TRUE;
180
181 fail:
182 return FALSE;
183 }
184
185
186 /**
187 * Check the size of the texture specified by 'res'.
188 * \return TRUE if OK, FALSE if too large.
189 */
190 static bool
llvmpipe_can_create_resource(struct pipe_screen * screen,const struct pipe_resource * res)191 llvmpipe_can_create_resource(struct pipe_screen *screen,
192 const struct pipe_resource *res)
193 {
194 struct llvmpipe_resource lpr;
195 memset(&lpr, 0, sizeof(lpr));
196 lpr.base = *res;
197 if (!llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false))
198 return false;
199
200 return lpr.size_required <= LP_MAX_TEXTURE_SIZE;
201 }
202
203
204 static boolean
llvmpipe_displaytarget_layout(struct llvmpipe_screen * screen,struct llvmpipe_resource * lpr,const void * map_front_private)205 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
206 struct llvmpipe_resource *lpr,
207 const void *map_front_private)
208 {
209 struct sw_winsys *winsys = screen->winsys;
210
211 /* Round up the surface size to a multiple of the tile size to
212 * avoid tile clipping.
213 */
214 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
215 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
216
217 lpr->dt = winsys->displaytarget_create(winsys,
218 lpr->base.bind,
219 lpr->base.format,
220 width, height,
221 64,
222 map_front_private,
223 &lpr->row_stride[0] );
224
225 return lpr->dt != NULL;
226 }
227
228
229 static struct pipe_resource *
llvmpipe_resource_create_all(struct pipe_screen * _screen,const struct pipe_resource * templat,const void * map_front_private,bool alloc_backing)230 llvmpipe_resource_create_all(struct pipe_screen *_screen,
231 const struct pipe_resource *templat,
232 const void *map_front_private, bool alloc_backing)
233 {
234 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
235 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
236 if (!lpr)
237 return NULL;
238
239 lpr->base = *templat;
240 lpr->screen = screen;
241 pipe_reference_init(&lpr->base.reference, 1);
242 lpr->base.screen = &screen->base;
243
244 /* assert(lpr->base.bind); */
245
246 if (llvmpipe_resource_is_texture(&lpr->base)) {
247 if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
248 PIPE_BIND_SCANOUT |
249 PIPE_BIND_SHARED)) {
250 /* displayable surface */
251 if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private))
252 goto fail;
253 }
254 else {
255 /* texture map */
256 if (!llvmpipe_texture_layout(screen, lpr, alloc_backing))
257 goto fail;
258 }
259 }
260 else {
261 /* other data (vertex buffer, const buffer, etc) */
262 const uint bytes = templat->width0;
263 assert(util_format_get_blocksize(templat->format) == 1);
264 assert(templat->height0 == 1);
265 assert(templat->depth0 == 1);
266 assert(templat->last_level == 0);
267 /*
268 * Reserve some extra storage since if we'd render to a buffer we
269 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
270 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
271 */
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
279 lpr->size_required = bytes;
280 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
281 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
282
283 if (alloc_backing) {
284 lpr->data = align_malloc(lpr->size_required, 64);
285
286 if (!lpr->data)
287 goto fail;
288 memset(lpr->data, 0, bytes);
289 }
290 }
291
292 lpr->id = id_counter++;
293
294 #ifdef DEBUG
295 mtx_lock(&resource_list_mutex);
296 insert_at_tail(&resource_list, lpr);
297 mtx_unlock(&resource_list_mutex);
298 #endif
299
300 return &lpr->base;
301
302 fail:
303 FREE(lpr);
304 return NULL;
305 }
306
307 static struct pipe_resource *
llvmpipe_resource_create_front(struct pipe_screen * _screen,const struct pipe_resource * templat,const void * map_front_private)308 llvmpipe_resource_create_front(struct pipe_screen *_screen,
309 const struct pipe_resource *templat,
310 const void *map_front_private)
311 {
312 return llvmpipe_resource_create_all(_screen, templat, map_front_private, true);
313 }
314
315 static struct pipe_resource *
llvmpipe_resource_create(struct pipe_screen * _screen,const struct pipe_resource * templat)316 llvmpipe_resource_create(struct pipe_screen *_screen,
317 const struct pipe_resource *templat)
318 {
319 return llvmpipe_resource_create_front(_screen, templat, NULL);
320 }
321
322 static struct pipe_resource *
llvmpipe_resource_create_unbacked(struct pipe_screen * _screen,const struct pipe_resource * templat,uint64_t * size_required)323 llvmpipe_resource_create_unbacked(struct pipe_screen *_screen,
324 const struct pipe_resource *templat,
325 uint64_t *size_required)
326 {
327 struct pipe_resource *pt;
328 struct llvmpipe_resource *lpr;
329 pt = llvmpipe_resource_create_all(_screen, templat, NULL, false);
330 if (!pt)
331 return pt;
332 lpr = llvmpipe_resource(pt);
333 lpr->backable = true;
334 *size_required = lpr->size_required;
335 return pt;
336 }
337
338 static struct pipe_memory_object *
llvmpipe_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * handle,bool dedicated)339 llvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen,
340 struct winsys_handle *handle,
341 bool dedicated)
342 {
343 #ifdef PIPE_MEMORY_FD
344 struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object);
345
346 if (handle->type == WINSYS_HANDLE_TYPE_FD &&
347 pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size)) {
348 return &memobj->b;
349 }
350 free(memobj);
351 #endif
352 return NULL;
353 }
354
355 static void
llvmpipe_memobj_destroy(struct pipe_screen * pscreen,struct pipe_memory_object * memobj)356 llvmpipe_memobj_destroy(struct pipe_screen *pscreen,
357 struct pipe_memory_object *memobj)
358 {
359 if (!memobj)
360 return;
361 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
362 #ifdef PIPE_MEMORY_FD
363 pscreen->free_memory_fd(pscreen, lpmo->data);
364 #endif
365 free(lpmo);
366 }
367
368 static struct pipe_resource *
llvmpipe_resource_from_memobj(struct pipe_screen * pscreen,const struct pipe_resource * templat,struct pipe_memory_object * memobj,uint64_t offset)369 llvmpipe_resource_from_memobj(struct pipe_screen *pscreen,
370 const struct pipe_resource *templat,
371 struct pipe_memory_object *memobj,
372 uint64_t offset)
373 {
374 if (!memobj)
375 return NULL;
376 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
377 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
378 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
379 lpr->base = *templat;
380
381 lpr->screen = screen;
382 pipe_reference_init(&lpr->base.reference, 1);
383 lpr->base.screen = &screen->base;
384
385 if (llvmpipe_resource_is_texture(&lpr->base)) {
386 /* texture map */
387 if (!llvmpipe_texture_layout(screen, lpr, false))
388 goto fail;
389 if(lpmo->size < lpr->size_required)
390 goto fail;
391 lpr->tex_data = lpmo->data;
392 }
393 else {
394 /* other data (vertex buffer, const buffer, etc) */
395 const uint bytes = templat->width0;
396 assert(util_format_get_blocksize(templat->format) == 1);
397 assert(templat->height0 == 1);
398 assert(templat->depth0 == 1);
399 assert(templat->last_level == 0);
400 /*
401 * Reserve some extra storage since if we'd render to a buffer we
402 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
403 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
404 */
405 /*
406 * buffers don't really have stride but it's probably safer
407 * (for code doing same calculations for buffers and textures)
408 * to put something reasonable in there.
409 */
410 lpr->row_stride[0] = bytes;
411
412 lpr->size_required = bytes;
413 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
414 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
415
416 if(lpmo->size < lpr->size_required)
417 goto fail;
418 lpr->data = lpmo->data;
419 }
420 lpr->id = id_counter++;
421 lpr->imported_memory = true;
422
423 #ifdef DEBUG
424 mtx_lock(&resource_list_mutex);
425 insert_at_tail(&resource_list, lpr);
426 mtx_unlock(&resource_list_mutex);
427 #endif
428
429 return &lpr->base;
430
431 fail:
432 free(lpr);
433 return NULL;
434 }
435
436 static void
llvmpipe_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * pt)437 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
438 struct pipe_resource *pt)
439 {
440 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
441 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
442
443 if (!lpr->backable && !lpr->user_ptr) {
444 if (lpr->dt) {
445 /* display target */
446 struct sw_winsys *winsys = screen->winsys;
447 winsys->displaytarget_destroy(winsys, lpr->dt);
448 }
449 else if (llvmpipe_resource_is_texture(pt)) {
450 /* free linear image data */
451 if (lpr->tex_data) {
452 if (!lpr->imported_memory)
453 align_free(lpr->tex_data);
454 lpr->tex_data = NULL;
455 }
456 }
457 else if (lpr->data) {
458 if (!lpr->imported_memory)
459 align_free(lpr->data);
460 }
461 }
462 #ifdef DEBUG
463 mtx_lock(&resource_list_mutex);
464 if (lpr->next)
465 remove_from_list(lpr);
466 mtx_unlock(&resource_list_mutex);
467 #endif
468
469 FREE(lpr);
470 }
471
472
473 /**
474 * Map a resource for read/write.
475 */
476 void *
llvmpipe_resource_map(struct pipe_resource * resource,unsigned level,unsigned layer,enum lp_texture_usage tex_usage)477 llvmpipe_resource_map(struct pipe_resource *resource,
478 unsigned level,
479 unsigned layer,
480 enum lp_texture_usage tex_usage)
481 {
482 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
483 uint8_t *map;
484
485 assert(level < LP_MAX_TEXTURE_LEVELS);
486 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
487
488 assert(tex_usage == LP_TEX_USAGE_READ ||
489 tex_usage == LP_TEX_USAGE_READ_WRITE ||
490 tex_usage == LP_TEX_USAGE_WRITE_ALL);
491
492 if (lpr->dt) {
493 /* display target */
494 struct llvmpipe_screen *screen = lpr->screen;
495 struct sw_winsys *winsys = screen->winsys;
496 unsigned dt_usage;
497
498 if (tex_usage == LP_TEX_USAGE_READ) {
499 dt_usage = PIPE_MAP_READ;
500 }
501 else {
502 dt_usage = PIPE_MAP_READ_WRITE;
503 }
504
505 assert(level == 0);
506 assert(layer == 0);
507
508 /* FIXME: keep map count? */
509 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
510
511 /* install this linear image in texture data structure */
512 lpr->tex_data = map;
513
514 return map;
515 }
516 else if (llvmpipe_resource_is_texture(resource)) {
517
518 map = llvmpipe_get_texture_image_address(lpr, layer, level);
519 return map;
520 }
521 else {
522 return lpr->data;
523 }
524 }
525
526
527 /**
528 * Unmap a resource.
529 */
530 void
llvmpipe_resource_unmap(struct pipe_resource * resource,unsigned level,unsigned layer)531 llvmpipe_resource_unmap(struct pipe_resource *resource,
532 unsigned level,
533 unsigned layer)
534 {
535 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
536
537 if (lpr->dt) {
538 /* display target */
539 struct llvmpipe_screen *lp_screen = lpr->screen;
540 struct sw_winsys *winsys = lp_screen->winsys;
541
542 assert(level == 0);
543 assert(layer == 0);
544
545 winsys->displaytarget_unmap(winsys, lpr->dt);
546 }
547 }
548
549
550 void *
llvmpipe_resource_data(struct pipe_resource * resource)551 llvmpipe_resource_data(struct pipe_resource *resource)
552 {
553 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
554
555 assert(!llvmpipe_resource_is_texture(resource));
556
557 return lpr->data;
558 }
559
560
561 static struct pipe_resource *
llvmpipe_resource_from_handle(struct pipe_screen * _screen,const struct pipe_resource * template,struct winsys_handle * whandle,unsigned usage)562 llvmpipe_resource_from_handle(struct pipe_screen *_screen,
563 const struct pipe_resource *template,
564 struct winsys_handle *whandle,
565 unsigned usage)
566 {
567 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
568 struct sw_winsys *winsys = screen->winsys;
569 struct llvmpipe_resource *lpr;
570
571 /* XXX Seems like from_handled depth textures doesn't work that well */
572
573 lpr = CALLOC_STRUCT(llvmpipe_resource);
574 if (!lpr) {
575 goto no_lpr;
576 }
577
578 lpr->base = *template;
579 lpr->screen = screen;
580 pipe_reference_init(&lpr->base.reference, 1);
581 lpr->base.screen = _screen;
582
583 /*
584 * Looks like unaligned displaytargets work just fine,
585 * at least sampler/render ones.
586 */
587 #if 0
588 assert(lpr->base.width0 == width);
589 assert(lpr->base.height0 == height);
590 #endif
591
592 lpr->dt = winsys->displaytarget_from_handle(winsys,
593 template,
594 whandle,
595 &lpr->row_stride[0]);
596 if (!lpr->dt) {
597 goto no_dt;
598 }
599
600 lpr->id = id_counter++;
601
602 #ifdef DEBUG
603 mtx_lock(&resource_list_mutex);
604 insert_at_tail(&resource_list, lpr);
605 mtx_unlock(&resource_list_mutex);
606 #endif
607
608 return &lpr->base;
609
610 no_dt:
611 FREE(lpr);
612 no_lpr:
613 return NULL;
614 }
615
616
617 static bool
llvmpipe_resource_get_handle(struct pipe_screen * screen,struct pipe_context * ctx,struct pipe_resource * pt,struct winsys_handle * whandle,unsigned usage)618 llvmpipe_resource_get_handle(struct pipe_screen *screen,
619 struct pipe_context *ctx,
620 struct pipe_resource *pt,
621 struct winsys_handle *whandle,
622 unsigned usage)
623 {
624 struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
625 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
626
627 assert(lpr->dt);
628 if (!lpr->dt)
629 return false;
630
631 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
632 }
633
634 static struct pipe_resource *
llvmpipe_resource_from_user_memory(struct pipe_screen * _screen,const struct pipe_resource * resource,void * user_memory)635 llvmpipe_resource_from_user_memory(struct pipe_screen *_screen,
636 const struct pipe_resource *resource,
637 void *user_memory)
638 {
639 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
640 struct llvmpipe_resource *lpr;
641
642 lpr = CALLOC_STRUCT(llvmpipe_resource);
643 if (!lpr) {
644 return NULL;
645 }
646
647 lpr->base = *resource;
648 lpr->screen = screen;
649 pipe_reference_init(&lpr->base.reference, 1);
650 lpr->base.screen = _screen;
651
652 if (llvmpipe_resource_is_texture(&lpr->base)) {
653 if (!llvmpipe_texture_layout(screen, lpr, false))
654 goto fail;
655
656 lpr->tex_data = user_memory;
657 } else
658 lpr->data = user_memory;
659 lpr->user_ptr = true;
660 return &lpr->base;
661 fail:
662 FREE(lpr);
663 return NULL;
664 }
665
666 void *
llvmpipe_transfer_map_ms(struct pipe_context * pipe,struct pipe_resource * resource,unsigned level,unsigned usage,unsigned sample,const struct pipe_box * box,struct pipe_transfer ** transfer)667 llvmpipe_transfer_map_ms( struct pipe_context *pipe,
668 struct pipe_resource *resource,
669 unsigned level,
670 unsigned usage,
671 unsigned sample,
672 const struct pipe_box *box,
673 struct pipe_transfer **transfer )
674 {
675 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
676 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
677 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
678 struct llvmpipe_transfer *lpt;
679 struct pipe_transfer *pt;
680 ubyte *map;
681 enum pipe_format format;
682 enum lp_texture_usage tex_usage;
683 const char *mode;
684
685 assert(resource);
686 assert(level <= resource->last_level);
687
688 /*
689 * Transfers, like other pipe operations, must happen in order, so flush the
690 * context if necessary.
691 */
692 if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
693 boolean read_only = !(usage & PIPE_MAP_WRITE);
694 boolean do_not_block = !!(usage & PIPE_MAP_DONTBLOCK);
695 if (!llvmpipe_flush_resource(pipe, resource,
696 level,
697 read_only,
698 TRUE, /* cpu_access */
699 do_not_block,
700 __FUNCTION__)) {
701 /*
702 * It would have blocked, but gallium frontend requested no to.
703 */
704 assert(do_not_block);
705 return NULL;
706 }
707 }
708
709 /* Check if we're mapping a current constant buffer */
710 if ((usage & PIPE_MAP_WRITE) &&
711 (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
712 unsigned i;
713 for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
714 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
715 /* constants may have changed */
716 llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
717 break;
718 }
719 }
720 }
721
722 lpt = CALLOC_STRUCT(llvmpipe_transfer);
723 if (!lpt)
724 return NULL;
725 pt = &lpt->base;
726 pipe_resource_reference(&pt->resource, resource);
727 pt->box = *box;
728 pt->level = level;
729 pt->stride = lpr->row_stride[level];
730 pt->layer_stride = lpr->img_stride[level];
731 pt->usage = usage;
732 *transfer = pt;
733
734 assert(level < LP_MAX_TEXTURE_LEVELS);
735
736 /*
737 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d )\n",
738 transfer->x, transfer->y, transfer->width, transfer->height,
739 transfer->texture->width0,
740 transfer->texture->height0,
741 transfer->usage);
742 */
743
744 if (usage == PIPE_MAP_READ) {
745 tex_usage = LP_TEX_USAGE_READ;
746 mode = "read";
747 }
748 else {
749 tex_usage = LP_TEX_USAGE_READ_WRITE;
750 mode = "read/write";
751 }
752
753 if (0) {
754 printf("transfer map tex %u mode %s\n", lpr->id, mode);
755 }
756
757 format = lpr->base.format;
758
759 map = llvmpipe_resource_map(resource,
760 level,
761 box->z,
762 tex_usage);
763
764
765 /* May want to do different things here depending on read/write nature
766 * of the map:
767 */
768 if (usage & PIPE_MAP_WRITE) {
769 /* Do something to notify sharing contexts of a texture change.
770 */
771 screen->timestamp++;
772 }
773
774 map +=
775 box->y / util_format_get_blockheight(format) * pt->stride +
776 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
777
778 map += sample * lpr->sample_stride;
779 return map;
780 }
781
782 static void *
llvmpipe_transfer_map(struct pipe_context * pipe,struct pipe_resource * resource,unsigned level,unsigned usage,const struct pipe_box * box,struct pipe_transfer ** transfer)783 llvmpipe_transfer_map( struct pipe_context *pipe,
784 struct pipe_resource *resource,
785 unsigned level,
786 unsigned usage,
787 const struct pipe_box *box,
788 struct pipe_transfer **transfer )
789 {
790 return llvmpipe_transfer_map_ms(pipe, resource, level, usage, 0, box, transfer);
791 }
792
793 static void
llvmpipe_transfer_unmap(struct pipe_context * pipe,struct pipe_transfer * transfer)794 llvmpipe_transfer_unmap(struct pipe_context *pipe,
795 struct pipe_transfer *transfer)
796 {
797 assert(transfer->resource);
798
799 llvmpipe_resource_unmap(transfer->resource,
800 transfer->level,
801 transfer->box.z);
802
803 /* Effectively do the texture_update work here - if texture images
804 * needed post-processing to put them into hardware layout, this is
805 * where it would happen. For llvmpipe, nothing to do.
806 */
807 assert (transfer->resource);
808 pipe_resource_reference(&transfer->resource, NULL);
809 FREE(transfer);
810 }
811
812 unsigned int
llvmpipe_is_resource_referenced(struct pipe_context * pipe,struct pipe_resource * presource,unsigned level)813 llvmpipe_is_resource_referenced( struct pipe_context *pipe,
814 struct pipe_resource *presource,
815 unsigned level)
816 {
817 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
818 if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
819 PIPE_BIND_RENDER_TARGET |
820 PIPE_BIND_SAMPLER_VIEW |
821 PIPE_BIND_SHADER_BUFFER |
822 PIPE_BIND_SHADER_IMAGE)))
823 return LP_UNREFERENCED;
824
825 return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
826 }
827
828
829 /**
830 * Returns the largest possible alignment for a format in llvmpipe
831 */
832 unsigned
llvmpipe_get_format_alignment(enum pipe_format format)833 llvmpipe_get_format_alignment( enum pipe_format format )
834 {
835 const struct util_format_description *desc = util_format_description(format);
836 unsigned size = 0;
837 unsigned bytes;
838 unsigned i;
839
840 for (i = 0; i < desc->nr_channels; ++i) {
841 size += desc->channel[i].size;
842 }
843
844 bytes = size / 8;
845
846 if (!util_is_power_of_two_or_zero(bytes)) {
847 bytes /= desc->nr_channels;
848 }
849
850 if (bytes % 2 || bytes < 1) {
851 return 1;
852 } else {
853 return bytes;
854 }
855 }
856
857
858 /**
859 * Create buffer which wraps user-space data.
860 * XXX unreachable.
861 */
862 struct pipe_resource *
llvmpipe_user_buffer_create(struct pipe_screen * screen,void * ptr,unsigned bytes,unsigned bind_flags)863 llvmpipe_user_buffer_create(struct pipe_screen *screen,
864 void *ptr,
865 unsigned bytes,
866 unsigned bind_flags)
867 {
868 struct llvmpipe_resource *buffer;
869
870 buffer = CALLOC_STRUCT(llvmpipe_resource);
871 if (!buffer)
872 return NULL;
873
874 buffer->screen = llvmpipe_screen(screen);
875 pipe_reference_init(&buffer->base.reference, 1);
876 buffer->base.screen = screen;
877 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
878 buffer->base.bind = bind_flags;
879 buffer->base.usage = PIPE_USAGE_IMMUTABLE;
880 buffer->base.flags = 0;
881 buffer->base.width0 = bytes;
882 buffer->base.height0 = 1;
883 buffer->base.depth0 = 1;
884 buffer->base.array_size = 1;
885 buffer->user_ptr = true;
886 buffer->data = ptr;
887
888 return &buffer->base;
889 }
890
891
892 /**
893 * Compute size (in bytes) need to store a texture image / mipmap level,
894 * for just one cube face, one array layer or one 3D texture slice
895 */
896 static unsigned
tex_image_face_size(const struct llvmpipe_resource * lpr,unsigned level)897 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
898 {
899 return lpr->img_stride[level];
900 }
901
902
903 /**
904 * Return pointer to a 2D texture image/face/slice.
905 * No tiled/linear conversion is done.
906 */
907 ubyte *
llvmpipe_get_texture_image_address(struct llvmpipe_resource * lpr,unsigned face_slice,unsigned level)908 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
909 unsigned face_slice, unsigned level)
910 {
911 unsigned offset;
912
913 assert(llvmpipe_resource_is_texture(&lpr->base));
914
915 offset = lpr->mip_offsets[level];
916
917 if (face_slice > 0)
918 offset += face_slice * tex_image_face_size(lpr, level);
919
920 return (ubyte *) lpr->tex_data + offset;
921 }
922
923
924 /**
925 * Return size of resource in bytes
926 */
927 unsigned
llvmpipe_resource_size(const struct pipe_resource * resource)928 llvmpipe_resource_size(const struct pipe_resource *resource)
929 {
930 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
931 unsigned size = 0;
932
933 if (llvmpipe_resource_is_texture(resource)) {
934 /* Note this will always return 0 for displaytarget resources */
935 size = lpr->total_alloc_size;
936 }
937 else {
938 size = resource->width0;
939 }
940 return size;
941 }
942
943 static void
llvmpipe_memory_barrier(struct pipe_context * pipe,unsigned flags)944 llvmpipe_memory_barrier(struct pipe_context *pipe,
945 unsigned flags)
946 {
947 /* this may be an overly large hammer for this nut. */
948 llvmpipe_finish(pipe, "barrier");
949 }
950
llvmpipe_allocate_memory(struct pipe_screen * screen,uint64_t size)951 static struct pipe_memory_allocation *llvmpipe_allocate_memory(struct pipe_screen *screen, uint64_t size)
952 {
953 return os_malloc_aligned(size, 256);
954 }
955
llvmpipe_free_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)956 static void llvmpipe_free_memory(struct pipe_screen *screen,
957 struct pipe_memory_allocation *pmem)
958 {
959 os_free_aligned(pmem);
960 }
961
962 #ifdef PIPE_MEMORY_FD
963
964 static const char *driver_id = "llvmpipe" MESA_GIT_SHA1;
965
llvmpipe_allocate_memory_fd(struct pipe_screen * screen,uint64_t size,int * fd)966 static struct pipe_memory_allocation *llvmpipe_allocate_memory_fd(struct pipe_screen *screen, uint64_t size, int *fd)
967 {
968 return os_malloc_aligned_fd(size, 256, fd, "llvmpipe memory fd", driver_id);
969 }
970
llvmpipe_import_memory_fd(struct pipe_screen * screen,int fd,struct pipe_memory_allocation ** ptr,uint64_t * size)971 static bool llvmpipe_import_memory_fd(struct pipe_screen *screen, int fd, struct pipe_memory_allocation **ptr, uint64_t *size)
972 {
973 return os_import_memory_fd(fd, (void**)ptr, size, driver_id);
974 }
975
llvmpipe_free_memory_fd(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)976 static void llvmpipe_free_memory_fd(struct pipe_screen *screen,
977 struct pipe_memory_allocation *pmem)
978 {
979 os_free_fd(pmem);
980 }
981
982 #endif
983
llvmpipe_resource_bind_backing(struct pipe_screen * screen,struct pipe_resource * pt,struct pipe_memory_allocation * pmem,uint64_t offset)984 static bool llvmpipe_resource_bind_backing(struct pipe_screen *screen,
985 struct pipe_resource *pt,
986 struct pipe_memory_allocation *pmem,
987 uint64_t offset)
988 {
989 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
990
991 if (!lpr->backable)
992 return FALSE;
993
994 if (llvmpipe_resource_is_texture(&lpr->base)) {
995 if (lpr->size_required > LP_MAX_TEXTURE_SIZE)
996 return FALSE;
997
998 lpr->tex_data = (char *)pmem + offset;
999 } else
1000 lpr->data = (char *)pmem + offset;
1001 lpr->backing_offset = offset;
1002
1003 return TRUE;
1004 }
1005
llvmpipe_map_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1006 static void *llvmpipe_map_memory(struct pipe_screen *screen,
1007 struct pipe_memory_allocation *pmem)
1008 {
1009 return pmem;
1010 }
1011
llvmpipe_unmap_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1012 static void llvmpipe_unmap_memory(struct pipe_screen *screen,
1013 struct pipe_memory_allocation *pmem)
1014 {
1015 }
1016
1017 #ifdef DEBUG
1018 void
llvmpipe_print_resources(void)1019 llvmpipe_print_resources(void)
1020 {
1021 struct llvmpipe_resource *lpr;
1022 unsigned n = 0, total = 0;
1023
1024 debug_printf("LLVMPIPE: current resources:\n");
1025 mtx_lock(&resource_list_mutex);
1026 foreach(lpr, &resource_list) {
1027 unsigned size = llvmpipe_resource_size(&lpr->base);
1028 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
1029 lpr->id, (void *) lpr,
1030 lpr->base.width0, lpr->base.height0, lpr->base.depth0,
1031 size, lpr->base.reference.count);
1032 total += size;
1033 n++;
1034 }
1035 mtx_unlock(&resource_list_mutex);
1036 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
1037 }
1038 #endif
1039
1040 static void
llvmpipe_get_resource_info(struct pipe_screen * screen,struct pipe_resource * resource,unsigned * stride,unsigned * offset)1041 llvmpipe_get_resource_info(struct pipe_screen *screen,
1042 struct pipe_resource *resource,
1043 unsigned *stride,
1044 unsigned *offset)
1045 {
1046 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1047
1048 *stride = lpr->row_stride[0];
1049 *offset = 0;
1050 }
1051
1052 static bool
llvmpipe_resource_get_param(struct pipe_screen * screen,struct pipe_context * context,struct pipe_resource * resource,unsigned plane,unsigned layer,unsigned level,enum pipe_resource_param param,unsigned handle_usage,uint64_t * value)1053 llvmpipe_resource_get_param(struct pipe_screen *screen,
1054 struct pipe_context *context,
1055 struct pipe_resource *resource,
1056 unsigned plane,
1057 unsigned layer,
1058 unsigned level,
1059 enum pipe_resource_param param,
1060 unsigned handle_usage,
1061 uint64_t *value)
1062 {
1063 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1064 struct winsys_handle whandle;
1065
1066 switch (param) {
1067 case PIPE_RESOURCE_PARAM_NPLANES:
1068 *value = 1;
1069 return true;
1070 case PIPE_RESOURCE_PARAM_STRIDE:
1071 *value = lpr->row_stride[level];
1072 return true;
1073 case PIPE_RESOURCE_PARAM_OFFSET:
1074 *value = lpr->mip_offsets[level] + (lpr->img_stride[level] * layer);
1075 return true;
1076 case PIPE_RESOURCE_PARAM_LAYER_STRIDE:
1077 *value = lpr->img_stride[level];
1078 return true;
1079 #ifndef _WIN32
1080 case PIPE_RESOURCE_PARAM_MODIFIER:
1081 *value = DRM_FORMAT_MOD_INVALID;
1082 return true;
1083 #endif
1084 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
1085 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
1086 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
1087 if (!lpr->dt)
1088 return false;
1089
1090 memset(&whandle, 0, sizeof(whandle));
1091 if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED)
1092 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1093 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS)
1094 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1095 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD)
1096 whandle.type = WINSYS_HANDLE_TYPE_FD;
1097
1098 if (!llvmpipe_resource_get_handle(screen, context, resource, &whandle, handle_usage))
1099 return false;
1100 *value = whandle.handle;
1101 return true;
1102 default:
1103 break;
1104 }
1105 assert(0);
1106 *value = 0;
1107 return false;
1108 }
1109
1110 void
llvmpipe_init_screen_resource_funcs(struct pipe_screen * screen)1111 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
1112 {
1113 #ifdef DEBUG
1114 /* init linked list for tracking resources */
1115 {
1116 static boolean first_call = TRUE;
1117 if (first_call) {
1118 memset(&resource_list, 0, sizeof(resource_list));
1119 make_empty_list(&resource_list);
1120 first_call = FALSE;
1121 }
1122 }
1123 #endif
1124
1125 screen->resource_create = llvmpipe_resource_create;
1126 /* screen->resource_create_front = llvmpipe_resource_create_front; */
1127 screen->resource_destroy = llvmpipe_resource_destroy;
1128 screen->resource_from_handle = llvmpipe_resource_from_handle;
1129 screen->resource_from_memobj = llvmpipe_resource_from_memobj;
1130 screen->resource_get_handle = llvmpipe_resource_get_handle;
1131 screen->can_create_resource = llvmpipe_can_create_resource;
1132
1133 screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
1134
1135 screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle;
1136 screen->memobj_destroy = llvmpipe_memobj_destroy;
1137
1138 screen->resource_get_info = llvmpipe_get_resource_info;
1139 screen->resource_get_param = llvmpipe_resource_get_param;
1140 screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
1141 screen->allocate_memory = llvmpipe_allocate_memory;
1142 screen->free_memory = llvmpipe_free_memory;
1143 #ifdef PIPE_MEMORY_FD
1144 screen->allocate_memory_fd = llvmpipe_allocate_memory_fd;
1145 screen->import_memory_fd = llvmpipe_import_memory_fd;
1146 screen->free_memory_fd = llvmpipe_free_memory_fd;
1147 #endif
1148 screen->map_memory = llvmpipe_map_memory;
1149 screen->unmap_memory = llvmpipe_unmap_memory;
1150
1151 screen->resource_bind_backing = llvmpipe_resource_bind_backing;
1152 }
1153
1154
1155 void
llvmpipe_init_context_resource_funcs(struct pipe_context * pipe)1156 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
1157 {
1158 pipe->buffer_map = llvmpipe_transfer_map;
1159 pipe->buffer_unmap = llvmpipe_transfer_unmap;
1160 pipe->texture_map = llvmpipe_transfer_map;
1161 pipe->texture_unmap = llvmpipe_transfer_unmap;
1162
1163 pipe->transfer_flush_region = u_default_transfer_flush_region;
1164 pipe->buffer_subdata = u_default_buffer_subdata;
1165 pipe->texture_subdata = u_default_texture_subdata;
1166
1167 pipe->memory_barrier = llvmpipe_memory_barrier;
1168 }
1169