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