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/detect_os.h"
39 #include "util/simple_mtx.h"
40 #include "util/u_inlines.h"
41 #include "util/u_cpu_detect.h"
42 #include "util/format/u_format.h"
43 #include "util/u_math.h"
44 #include "util/u_memory.h"
45 #include "util/u_transfer.h"
46
47 #if DETECT_OS_POSIX
48 #include "util/os_mman.h"
49 #endif
50
51 #include "lp_context.h"
52 #include "lp_flush.h"
53 #include "lp_screen.h"
54 #include "lp_texture.h"
55 #include "lp_setup.h"
56 #include "lp_state.h"
57 #include "lp_rast.h"
58
59 #include "frontend/sw_winsys.h"
60 #include "git_sha1.h"
61
62 #ifndef _WIN32
63 #include "drm-uapi/drm_fourcc.h"
64 #endif
65
66 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
67 #include <fcntl.h>
68 #include <sys/mman.h>
69 #include <sys/ioctl.h>
70 #include <linux/udmabuf.h>
71 #include <util/os_file.h>
72 #endif
73
74 #if MESA_DEBUG
75 static struct llvmpipe_resource resource_list;
76 static simple_mtx_t resource_list_mutex = SIMPLE_MTX_INITIALIZER;
77 #endif
78 static unsigned id_counter = 0;
79
80
81 #ifdef PIPE_MEMORY_FD
82
83 static const char *driver_id = "llvmpipe" MESA_GIT_SHA1;
84
85 #endif
86
87 /**
88 * Conventional allocation path for non-display textures:
89 * Compute strides and allocate data (unless asked not to).
90 */
91 static bool
llvmpipe_texture_layout(struct llvmpipe_screen * screen,struct llvmpipe_resource * lpr,bool allocate)92 llvmpipe_texture_layout(struct llvmpipe_screen *screen,
93 struct llvmpipe_resource *lpr,
94 bool allocate)
95 {
96 struct pipe_resource *pt = &lpr->base;
97 unsigned width = pt->width0;
98 unsigned height = pt->height0;
99 unsigned depth = pt->depth0;
100 uint64_t total_size = 0;
101 unsigned layers = pt->array_size;
102 unsigned num_samples = util_res_sample_count(pt);
103
104 /* XXX: This alignment here (same for displaytarget) was added for the
105 * purpose of ARB_map_buffer_alignment. I am not convinced it's needed for
106 * non-buffer resources. Otherwise we'd want the max of cacheline size and
107 * 16 (max size of a block for all formats) though this should not be
108 * strictly necessary neither. In any case it can only affect compressed or
109 * 1d textures.
110 */
111 uint64_t mip_align = MAX2(64, util_get_cpu_caps()->cacheline);
112
113 /* KVM on Linux requires memory mapping to be aligned to the page size,
114 * otherwise Linux kernel errors out on trying to map host GPU mapping
115 * to guest (ARB_map_buffer_range). The improper alignment creates trouble
116 * for the virgl driver when host uses llvmpipe, causing Qemu and crosvm to
117 * bail out on the KVM error.
118 */
119 if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE)
120 mip_align = 64 * 1024;
121 else if (lpr->base.flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
122 os_get_page_size(&mip_align);
123
124 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
125 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
126
127 uint32_t dimensions = 1;
128 switch (pt->target) {
129 case PIPE_TEXTURE_2D:
130 case PIPE_TEXTURE_CUBE:
131 case PIPE_TEXTURE_RECT:
132 case PIPE_TEXTURE_2D_ARRAY:
133 dimensions = 2;
134 break;
135 case PIPE_TEXTURE_3D:
136 dimensions = 3;
137 break;
138 default:
139 break;
140 }
141
142 uint32_t sparse_tile_size[3] = {
143 util_format_get_tilesize(pt->format, dimensions, pt->nr_samples, 0),
144 util_format_get_tilesize(pt->format, dimensions, pt->nr_samples, 1),
145 util_format_get_tilesize(pt->format, dimensions, pt->nr_samples, 2),
146 };
147
148 for (unsigned level = 0; level <= pt->last_level; level++) {
149 uint64_t mipsize;
150 unsigned align_x, align_y, align_z, nblocksx, nblocksy, block_size, num_slices;
151
152 /* Row stride and image stride */
153
154 /* For non-compressed formats we need 4x4 pixel alignment
155 * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
156 * We also want cache line size in x direction,
157 * otherwise same cache line could end up in multiple threads.
158 * For explicit 1d resources however we reduce this to 4x1 and
159 * handle specially in render output code (as we need to do special
160 * handling there for buffers in any case).
161 */
162 if (util_format_is_compressed(pt->format)) {
163 align_x = align_y = 1;
164 } else {
165 align_x = LP_RASTER_BLOCK_SIZE;
166 if (llvmpipe_resource_is_1d(&lpr->base))
167 align_y = 1;
168 else
169 align_y = LP_RASTER_BLOCK_SIZE;
170 }
171 align_z = 1;
172
173 nblocksx = util_format_get_nblocksx(pt->format,
174 align(width, align_x));
175 nblocksy = util_format_get_nblocksy(pt->format,
176 align(height, align_y));
177 block_size = util_format_get_blocksize(pt->format);
178
179 if (pt->flags & PIPE_RESOURCE_FLAG_SPARSE) {
180 nblocksx = align(nblocksx, sparse_tile_size[0]);
181 nblocksy = align(nblocksy, sparse_tile_size[1]);
182 align_z = MAX2(align_z, sparse_tile_size[2]);
183 }
184
185 if (util_format_is_compressed(pt->format))
186 lpr->row_stride[level] = nblocksx * block_size;
187 else
188 lpr->row_stride[level] = align(nblocksx * block_size,
189 util_get_cpu_caps()->cacheline);
190
191 lpr->img_stride[level] = (uint64_t)lpr->row_stride[level] * nblocksy;
192
193 /* Number of 3D image slices, cube faces or texture array layers */
194 if (lpr->base.target == PIPE_TEXTURE_CUBE) {
195 assert(layers == 6);
196 }
197
198 if (lpr->base.target == PIPE_TEXTURE_3D)
199 num_slices = align(depth, align_z);
200 else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
201 lpr->base.target == PIPE_TEXTURE_2D_ARRAY ||
202 lpr->base.target == PIPE_TEXTURE_CUBE ||
203 lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY)
204 num_slices = layers;
205 else
206 num_slices = 1;
207
208 mipsize = lpr->img_stride[level] * num_slices;
209 lpr->mip_offsets[level] = total_size;
210
211 total_size += align64(mipsize, mip_align);
212
213 /* Compute size of next mipmap level */
214 width = u_minify(width, 1);
215 height = u_minify(height, 1);
216 depth = u_minify(depth, 1);
217 }
218
219 lpr->sample_stride = total_size;
220 total_size *= num_samples;
221
222 lpr->size_required = total_size;
223 if (allocate) {
224 if (total_size > LP_MAX_TEXTURE_SIZE)
225 goto fail;
226
227 lpr->tex_data = align_malloc(total_size, mip_align);
228 if (!lpr->tex_data) {
229 return false;
230 } else {
231 memset(lpr->tex_data, 0, total_size);
232 }
233 }
234 if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) {
235 uint64_t page_align;
236 os_get_page_size(&page_align);
237 lpr->size_required = align64(lpr->size_required, page_align);
238 }
239
240 return true;
241
242 fail:
243 return false;
244 }
245
246
247 /**
248 * Check the size of the texture specified by 'res'.
249 * \return TRUE if OK, FALSE if too large.
250 */
251 static bool
llvmpipe_can_create_resource(struct pipe_screen * screen,const struct pipe_resource * res)252 llvmpipe_can_create_resource(struct pipe_screen *screen,
253 const struct pipe_resource *res)
254 {
255 struct llvmpipe_resource lpr;
256 memset(&lpr, 0, sizeof(lpr));
257 lpr.base = *res;
258 if (!llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false))
259 return false;
260
261 return lpr.size_required <= LP_MAX_TEXTURE_SIZE;
262 }
263
264
265 static bool
llvmpipe_displaytarget_layout(struct llvmpipe_screen * screen,struct llvmpipe_resource * lpr,const void * map_front_private)266 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
267 struct llvmpipe_resource *lpr,
268 const void *map_front_private)
269 {
270 struct sw_winsys *winsys = screen->winsys;
271
272 /* Round up the surface size to a multiple of the tile size to
273 * avoid tile clipping.
274 */
275 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
276 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
277
278 lpr->dt = winsys->displaytarget_create(winsys,
279 lpr->base.bind,
280 lpr->base.format,
281 width, height,
282 64,
283 map_front_private,
284 &lpr->row_stride[0] );
285
286 return lpr->dt != NULL;
287 }
288
289
290 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)291 llvmpipe_resource_create_all(struct pipe_screen *_screen,
292 const struct pipe_resource *templat,
293 const void *map_front_private,
294 bool alloc_backing)
295 {
296 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
297 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
298 if (!lpr)
299 return NULL;
300
301 lpr->base = *templat;
302 lpr->screen = screen;
303 pipe_reference_init(&lpr->base.reference, 1);
304 lpr->base.screen = &screen->base;
305
306 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
307 lpr->dmabuf_alloc = NULL;
308 #endif
309
310 /* assert(lpr->base.bind); */
311
312 if (llvmpipe_resource_is_texture(&lpr->base)) {
313 if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
314 PIPE_BIND_SCANOUT |
315 PIPE_BIND_SHARED)) {
316 /* displayable surface */
317 if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private))
318 goto fail;
319 } else {
320 /* texture map */
321 if (!llvmpipe_texture_layout(screen, lpr, alloc_backing))
322 goto fail;
323
324 if (templat->flags & PIPE_RESOURCE_FLAG_SPARSE) {
325 #if DETECT_OS_LINUX
326 lpr->tex_data = os_mmap(NULL, lpr->size_required, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED,
327 -1, 0);
328 madvise(lpr->tex_data, lpr->size_required, MADV_DONTNEED);
329 #endif
330
331 lpr->residency = calloc(DIV_ROUND_UP(lpr->size_required, 64 * 1024 * sizeof(uint32_t) * 8), sizeof(uint32_t));
332 }
333 }
334 } else {
335 /* other data (vertex buffer, const buffer, etc) */
336 const uint bytes = templat->width0;
337 assert(util_format_get_blocksize(templat->format) == 1);
338 assert(templat->height0 == 1);
339 assert(templat->depth0 == 1);
340 assert(templat->last_level == 0);
341 /*
342 * Reserve some extra storage since if we'd render to a buffer we
343 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
344 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
345 */
346 /*
347 * buffers don't really have stride but it's probably safer
348 * (for code doing same calculations for buffers and textures)
349 * to put something sane in there.
350 */
351 lpr->row_stride[0] = bytes;
352
353 lpr->size_required = bytes;
354 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
355 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
356
357 uint64_t alignment = sizeof(uint64_t) * 16;
358 if (alloc_backing) {
359 if (templat->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
360 os_get_page_size(&alignment);
361
362 lpr->data = align_malloc(lpr->size_required, alignment);
363
364 if (!lpr->data)
365 goto fail;
366 memset(lpr->data, 0, bytes);
367 }
368
369 if (templat->flags & PIPE_RESOURCE_FLAG_SPARSE) {
370 os_get_page_size(&alignment);
371 lpr->size_required = align64(lpr->size_required, alignment);
372 #if DETECT_OS_LINUX
373 lpr->data = os_mmap(NULL, lpr->size_required, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED,
374 -1, 0);
375 madvise(lpr->data, lpr->size_required, MADV_DONTNEED);
376 #endif
377 }
378 }
379
380 lpr->id = id_counter++;
381
382 #if MESA_DEBUG
383 simple_mtx_lock(&resource_list_mutex);
384 list_addtail(&lpr->list, &resource_list.list);
385 simple_mtx_unlock(&resource_list_mutex);
386 #endif
387
388 return &lpr->base;
389
390 fail:
391 FREE(lpr);
392 return NULL;
393 }
394
395
396 static struct pipe_resource *
llvmpipe_resource_create_front(struct pipe_screen * _screen,const struct pipe_resource * templat,const void * map_front_private)397 llvmpipe_resource_create_front(struct pipe_screen *_screen,
398 const struct pipe_resource *templat,
399 const void *map_front_private)
400 {
401 return llvmpipe_resource_create_all(_screen, templat,
402 map_front_private, true);
403 }
404
405
406 static struct pipe_resource *
llvmpipe_resource_create(struct pipe_screen * _screen,const struct pipe_resource * templat)407 llvmpipe_resource_create(struct pipe_screen *_screen,
408 const struct pipe_resource *templat)
409 {
410 return llvmpipe_resource_create_front(_screen, templat, NULL);
411 }
412
413 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
414 static struct pipe_resource *
llvmpipe_resource_create_with_modifiers(struct pipe_screen * _screen,const struct pipe_resource * templat,const uint64_t * modifiers,int count)415 llvmpipe_resource_create_with_modifiers(struct pipe_screen *_screen,
416 const struct pipe_resource *templat,
417 const uint64_t *modifiers, int count)
418 {
419 bool has_linear = false;
420 for (unsigned i = 0; i < count; i++)
421 if (modifiers[i] == DRM_FORMAT_MOD_LINEAR)
422 has_linear = true;
423 if (!has_linear)
424 return NULL;
425 return llvmpipe_resource_create_front(_screen, templat, NULL);
426 }
427 #endif
428
429 static struct pipe_resource *
llvmpipe_resource_create_unbacked(struct pipe_screen * _screen,const struct pipe_resource * templat,uint64_t * size_required)430 llvmpipe_resource_create_unbacked(struct pipe_screen *_screen,
431 const struct pipe_resource *templat,
432 uint64_t *size_required)
433 {
434 struct pipe_resource *pt =
435 llvmpipe_resource_create_all(_screen, templat, NULL, false);
436 if (!pt)
437 return pt;
438 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
439 lpr->backable = true;
440 *size_required = lpr->size_required;
441 return pt;
442 }
443
444
445 static struct pipe_memory_object *
llvmpipe_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * handle,bool dedicated)446 llvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen,
447 struct winsys_handle *handle,
448 bool dedicated)
449 {
450 #ifdef PIPE_MEMORY_FD
451 struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object);
452 pipe_reference_init(&memobj->reference, 1);
453
454 if (handle->type == WINSYS_HANDLE_TYPE_FD &&
455 pscreen->import_memory_fd(pscreen,
456 handle->handle,
457 (struct pipe_memory_allocation **)&memobj->mem_alloc,
458 &memobj->size,
459 false)) {
460 return &memobj->b;
461 }
462 free(memobj);
463 #endif
464 return NULL;
465 }
466
467
468 static void
llvmpipe_memobj_destroy(struct pipe_screen * pscreen,struct pipe_memory_object * memobj)469 llvmpipe_memobj_destroy(struct pipe_screen *pscreen,
470 struct pipe_memory_object *memobj)
471 {
472 if (!memobj)
473 return;
474 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
475 if (pipe_reference(&lpmo->reference, NULL))
476 {
477 #ifdef PIPE_MEMORY_FD
478 pscreen->free_memory_fd(pscreen, (struct pipe_memory_allocation *)lpmo->mem_alloc);
479 #endif
480 free(lpmo);
481 }
482 }
483
484
485 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)486 llvmpipe_resource_from_memobj(struct pipe_screen *pscreen,
487 const struct pipe_resource *templat,
488 struct pipe_memory_object *memobj,
489 uint64_t offset)
490 {
491 if (!memobj)
492 return NULL;
493 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
494 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
495 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
496 lpr->base = *templat;
497
498 lpr->screen = screen;
499 pipe_reference_init(&lpr->base.reference, 1);
500 lpr->base.screen = &screen->base;
501
502 if (llvmpipe_resource_is_texture(&lpr->base)) {
503 /* texture map */
504 if (!llvmpipe_texture_layout(screen, lpr, false))
505 goto fail;
506 if (lpmo->size < lpr->size_required)
507 goto fail;
508 lpr->tex_data = lpmo->mem_alloc->cpu_addr;
509 } else {
510 /* other data (vertex buffer, const buffer, etc) */
511 const uint bytes = templat->width0;
512 assert(util_format_get_blocksize(templat->format) == 1);
513 assert(templat->height0 == 1);
514 assert(templat->depth0 == 1);
515 assert(templat->last_level == 0);
516 /*
517 * Reserve some extra storage since if we'd render to a buffer we
518 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
519 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
520 */
521 /*
522 * buffers don't really have stride but it's probably safer
523 * (for code doing same calculations for buffers and textures)
524 * to put something reasonable in there.
525 */
526 lpr->row_stride[0] = bytes;
527
528 lpr->size_required = bytes;
529 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
530 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
531
532 if (lpmo->size < lpr->size_required)
533 goto fail;
534 lpr->data = lpmo->mem_alloc->cpu_addr;
535 }
536 lpr->id = id_counter++;
537 lpr->imported_memory = &lpmo->b;
538 pipe_reference(NULL, &lpmo->reference);
539
540 #if MESA_DEBUG
541 simple_mtx_lock(&resource_list_mutex);
542 list_addtail(&lpr->list, &resource_list.list);
543 simple_mtx_unlock(&resource_list_mutex);
544 #endif
545
546 return &lpr->base;
547
548 fail:
549 free(lpr);
550 return NULL;
551 }
552
553 static void
llvmpipe_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * pt)554 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
555 struct pipe_resource *pt)
556 {
557 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
558 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
559
560 if (!lpr->backable && !lpr->user_ptr) {
561 if (lpr->dt) {
562 /* display target */
563 struct sw_winsys *winsys = screen->winsys;
564 if (lpr->dmabuf)
565 winsys->displaytarget_unmap(winsys, lpr->dt);
566 winsys->displaytarget_destroy(winsys, lpr->dt);
567 } else if (llvmpipe_resource_is_texture(pt)) {
568 /* free linear image data */
569 if (lpr->tex_data) {
570 if (lpr->imported_memory)
571 llvmpipe_memobj_destroy(pscreen, lpr->imported_memory);
572 else
573 align_free(lpr->tex_data);
574 lpr->tex_data = NULL;
575 lpr->imported_memory = NULL;
576 }
577 } else if (lpr->data) {
578 if (lpr->imported_memory)
579 llvmpipe_memobj_destroy(pscreen, lpr->imported_memory);
580 else
581 align_free(lpr->data);
582 lpr->imported_memory = NULL;
583 }
584 }
585
586 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
587 if (lpr->dmabuf_alloc)
588 pscreen->free_memory_fd(pscreen, (struct pipe_memory_allocation*)lpr->dmabuf_alloc);
589 #endif
590
591 if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) {
592 #if DETECT_OS_LINUX
593 if (llvmpipe_resource_is_texture(pt))
594 munmap(lpr->tex_data, lpr->size_required);
595 else
596 munmap(lpr->data, lpr->size_required);
597 #endif
598 }
599
600 free(lpr->residency);
601
602 #if MESA_DEBUG
603 simple_mtx_lock(&resource_list_mutex);
604 if (!list_is_empty(&lpr->list))
605 list_del(&lpr->list);
606 simple_mtx_unlock(&resource_list_mutex);
607 #endif
608
609 FREE(lpr);
610 }
611
612
613 /**
614 * Map a resource for read/write.
615 */
616 void *
llvmpipe_resource_map(struct pipe_resource * resource,unsigned level,unsigned layer,enum lp_texture_usage tex_usage)617 llvmpipe_resource_map(struct pipe_resource *resource,
618 unsigned level,
619 unsigned layer,
620 enum lp_texture_usage tex_usage)
621 {
622 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
623 uint8_t *map;
624
625 assert(level < LP_MAX_TEXTURE_LEVELS);
626 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
627
628 assert(tex_usage == LP_TEX_USAGE_READ ||
629 tex_usage == LP_TEX_USAGE_READ_WRITE ||
630 tex_usage == LP_TEX_USAGE_WRITE_ALL);
631
632 if (lpr->dt) {
633 if (lpr->dmabuf)
634 return lpr->tex_data;
635 /* display target */
636 struct llvmpipe_screen *screen = lpr->screen;
637 struct sw_winsys *winsys = screen->winsys;
638 unsigned dt_usage;
639
640 if (tex_usage == LP_TEX_USAGE_READ) {
641 dt_usage = PIPE_MAP_READ;
642 } else {
643 dt_usage = PIPE_MAP_READ_WRITE;
644 }
645
646 assert(level == 0);
647 assert(layer == 0);
648
649 /* FIXME: keep map count? */
650 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
651
652 /* install this linear image in texture data structure */
653 lpr->tex_data = map;
654
655 return map;
656 } else if (llvmpipe_resource_is_texture(resource)) {
657
658 map = llvmpipe_get_texture_image_address(lpr, layer, level);
659 return map;
660 } else {
661 return lpr->data;
662 }
663 }
664
665
666 /**
667 * Unmap a resource.
668 */
669 void
llvmpipe_resource_unmap(struct pipe_resource * resource,unsigned level,unsigned layer)670 llvmpipe_resource_unmap(struct pipe_resource *resource,
671 unsigned level,
672 unsigned layer)
673 {
674 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
675
676 if (lpr->dt) {
677 if (lpr->dmabuf)
678 return;
679 /* display target */
680 struct llvmpipe_screen *lp_screen = lpr->screen;
681 struct sw_winsys *winsys = lp_screen->winsys;
682
683 assert(level == 0);
684 assert(layer == 0);
685
686 winsys->displaytarget_unmap(winsys, lpr->dt);
687 }
688 }
689
690
691 void *
llvmpipe_resource_data(struct pipe_resource * resource)692 llvmpipe_resource_data(struct pipe_resource *resource)
693 {
694 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
695
696 assert(!llvmpipe_resource_is_texture(resource));
697
698 return lpr->data;
699 }
700
701
702 static struct pipe_resource *
llvmpipe_resource_from_handle(struct pipe_screen * _screen,const struct pipe_resource * template,struct winsys_handle * whandle,unsigned usage)703 llvmpipe_resource_from_handle(struct pipe_screen *_screen,
704 const struct pipe_resource *template,
705 struct winsys_handle *whandle,
706 unsigned usage)
707 {
708 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
709 struct sw_winsys *winsys = screen->winsys;
710 struct llvmpipe_resource *lpr;
711
712 /* no multisampled */
713 assert(template->nr_samples < 2);
714 /* no miplevels */
715 assert(template->last_level == 0);
716
717 /* Multiplanar surfaces are not supported */
718 if (whandle->plane > 0)
719 return NULL;
720
721 lpr = CALLOC_STRUCT(llvmpipe_resource);
722 if (!lpr) {
723 goto no_lpr;
724 }
725
726 lpr->base = *template;
727 lpr->screen = screen;
728 lpr->dt_format = whandle->format;
729 pipe_reference_init(&lpr->base.reference, 1);
730 lpr->base.screen = _screen;
731
732 /*
733 * Looks like unaligned displaytargets work just fine,
734 * at least sampler/render ones.
735 */
736 #if 0
737 assert(lpr->base.width0 == width);
738 assert(lpr->base.height0 == height);
739 #endif
740
741 unsigned nblocksy = util_format_get_nblocksy(template->format, align(template->height0, LP_RASTER_BLOCK_SIZE));
742 if (whandle->type == WINSYS_HANDLE_TYPE_UNBACKED && whandle->image_stride)
743 lpr->img_stride[0] = whandle->image_stride;
744 else
745 lpr->img_stride[0] = whandle->stride * nblocksy;
746 lpr->sample_stride = lpr->img_stride[0];
747 lpr->size_required = lpr->sample_stride;
748
749 if (whandle->type != WINSYS_HANDLE_TYPE_UNBACKED) {
750 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
751 struct llvmpipe_memory_allocation *alloc;
752 uint64_t size;
753 /* Not all winsys implement displaytarget_create_mapped so we need to check
754 * that is available (not null).
755 */
756 if (winsys->displaytarget_create_mapped &&
757 _screen->import_memory_fd(_screen, whandle->handle,
758 (struct pipe_memory_allocation**)&alloc,
759 &size, true)) {
760 void *data = alloc->cpu_addr;
761 lpr->dt = winsys->displaytarget_create_mapped(winsys, template->bind,
762 template->format, template->width0, template->height0,
763 whandle->stride, data);
764 if (!lpr->dt)
765 goto no_dt;
766 lpr->dmabuf_alloc = alloc;
767 lpr->dmabuf = true;
768 lpr->tex_data = data;
769 lpr->row_stride[0] = whandle->stride;
770 whandle->size = size;
771 } else
772 #endif
773 {
774 lpr->dt = winsys->displaytarget_from_handle(winsys,
775 template,
776 whandle,
777 &lpr->row_stride[0]);
778 if (!lpr->dt)
779 goto no_dt;
780 }
781
782 assert(llvmpipe_resource_is_texture(&lpr->base));
783 } else {
784 whandle->size = lpr->size_required;
785 lpr->row_stride[0] = whandle->stride;
786 lpr->backable = true;
787 }
788
789
790 lpr->id = id_counter++;
791
792 #if MESA_DEBUG
793 simple_mtx_lock(&resource_list_mutex);
794 list_addtail(&lpr->list, &resource_list.list);
795 simple_mtx_unlock(&resource_list_mutex);
796 #endif
797
798 return &lpr->base;
799
800 no_dt:
801 FREE(lpr);
802 no_lpr:
803 return NULL;
804 }
805
806
807 static bool
llvmpipe_resource_get_handle(struct pipe_screen * _screen,struct pipe_context * ctx,struct pipe_resource * pt,struct winsys_handle * whandle,unsigned usage)808 llvmpipe_resource_get_handle(struct pipe_screen *_screen,
809 struct pipe_context *ctx,
810 struct pipe_resource *pt,
811 struct winsys_handle *whandle,
812 unsigned usage)
813 {
814 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
815 struct sw_winsys *winsys = screen->winsys;
816 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
817
818 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
819 if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_FD) {
820 if (!lpr->dmabuf_alloc) {
821 lpr->dmabuf_alloc = (struct llvmpipe_memory_allocation*)_screen->allocate_memory_fd(_screen, lpr->size_required, (int*)&whandle->handle, true);
822 if (!lpr->dmabuf_alloc)
823 return false;
824
825 /* replace existing backing with fd backing */
826 bool is_tex = llvmpipe_resource_is_texture(pt);
827 if (is_tex) {
828 if (lpr->tex_data)
829 memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->tex_data, lpr->size_required);
830 } else {
831 if (lpr->data)
832 memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->data, lpr->size_required);
833 }
834 if (!lpr->imported_memory)
835 align_free(is_tex ? lpr->tex_data : lpr->data);
836 if (is_tex)
837 lpr->tex_data = lpr->dmabuf_alloc->cpu_addr;
838 else
839 lpr->data = lpr->dmabuf_alloc->cpu_addr;
840 /* reuse lavapipe codepath to handle destruction */
841 lpr->backable = true;
842 } else {
843 whandle->handle = os_dupfd_cloexec(lpr->dmabuf_alloc->dmabuf_fd);
844 }
845 whandle->modifier = DRM_FORMAT_MOD_LINEAR;
846 whandle->stride = lpr->row_stride[0];
847 return true;
848 } else if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_KMS) {
849 /* dri winsys code will use this to query the drm modifiers
850 * We can just return an null handle and return DRM_FORMAT_MOD_LINEAR */
851 whandle->handle = 0;
852 whandle->modifier = DRM_FORMAT_MOD_LINEAR;
853 return true;
854 }
855 #endif
856 assert(lpr->dt);
857 if (!lpr->dt)
858 return false;
859
860 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
861 }
862
863
864 static struct pipe_resource *
llvmpipe_resource_from_user_memory(struct pipe_screen * _screen,const struct pipe_resource * resource,void * user_memory)865 llvmpipe_resource_from_user_memory(struct pipe_screen *_screen,
866 const struct pipe_resource *resource,
867 void *user_memory)
868 {
869 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
870 struct llvmpipe_resource *lpr;
871
872 lpr = CALLOC_STRUCT(llvmpipe_resource);
873 if (!lpr) {
874 return NULL;
875 }
876
877 lpr->base = *resource;
878 lpr->screen = screen;
879 pipe_reference_init(&lpr->base.reference, 1);
880 lpr->base.screen = _screen;
881
882 if (llvmpipe_resource_is_texture(&lpr->base)) {
883 if (!llvmpipe_texture_layout(screen, lpr, false))
884 goto fail;
885
886 lpr->tex_data = user_memory;
887 } else
888 lpr->data = user_memory;
889 lpr->user_ptr = true;
890 #if MESA_DEBUG
891 simple_mtx_lock(&resource_list_mutex);
892 list_addtail(&lpr->list, &resource_list.list);
893 simple_mtx_unlock(&resource_list_mutex);
894 #endif
895 return &lpr->base;
896 fail:
897 FREE(lpr);
898 return NULL;
899 }
900
901
902 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)903 llvmpipe_transfer_map_ms(struct pipe_context *pipe,
904 struct pipe_resource *resource,
905 unsigned level,
906 unsigned usage,
907 unsigned sample,
908 const struct pipe_box *box,
909 struct pipe_transfer **transfer)
910 {
911 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
912 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
913 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
914 struct llvmpipe_transfer *lpt;
915 struct pipe_transfer *pt;
916 uint8_t *map;
917 enum pipe_format format;
918
919 assert(resource);
920 assert(level <= resource->last_level);
921
922 /*
923 * Transfers, like other pipe operations, must happen in order, so flush
924 * the context if necessary.
925 */
926 if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
927 bool read_only = !(usage & PIPE_MAP_WRITE);
928 bool do_not_block = !!(usage & PIPE_MAP_DONTBLOCK);
929 if (!llvmpipe_flush_resource(pipe, resource,
930 level,
931 read_only,
932 true, /* cpu_access */
933 do_not_block,
934 __func__)) {
935 /*
936 * It would have blocked, but gallium frontend requested no to.
937 */
938 assert(do_not_block);
939 return NULL;
940 }
941 }
942
943 /* Check if we're mapping a current constant buffer */
944 if ((usage & PIPE_MAP_WRITE) &&
945 (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
946 unsigned i;
947 for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
948 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
949 /* constants may have changed */
950 llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
951 break;
952 }
953 }
954 }
955
956 lpt = CALLOC_STRUCT(llvmpipe_transfer);
957 if (!lpt)
958 return NULL;
959 pt = &lpt->base;
960 pipe_resource_reference(&pt->resource, resource);
961 pt->box = *box;
962 pt->level = level;
963 pt->stride = lpr->row_stride[level];
964 pt->layer_stride = lpr->img_stride[level];
965 pt->usage = usage;
966 *transfer = pt;
967
968 assert(level < LP_MAX_TEXTURE_LEVELS);
969
970 /*
971 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d)\n",
972 transfer->x, transfer->y, transfer->width, transfer->height,
973 transfer->texture->width0,
974 transfer->texture->height0,
975 transfer->usage);
976 */
977
978 enum lp_texture_usage tex_usage;
979 const char *mode;
980 if (usage == PIPE_MAP_READ) {
981 tex_usage = LP_TEX_USAGE_READ;
982 mode = "read";
983 } else {
984 tex_usage = LP_TEX_USAGE_READ_WRITE;
985 mode = "read/write";
986 }
987
988 if (0) {
989 printf("transfer map tex %u mode %s\n", lpr->id, mode);
990 }
991
992 format = lpr->base.format;
993
994 if (llvmpipe_resource_is_texture(resource) && (resource->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
995 map = llvmpipe_resource_map(resource, 0, 0, tex_usage);
996 if (!map)
997 return NULL;
998
999 lpt->block_box = (struct pipe_box) {
1000 .x = box->x / util_format_get_blockwidth(format),
1001 .width = DIV_ROUND_UP(box->x + box->width, util_format_get_blockwidth(format)),
1002 .y = box->y / util_format_get_blockheight(format),
1003 .height = DIV_ROUND_UP(box->y + box->height, util_format_get_blockheight(format)),
1004 .z = box->z / util_format_get_blockdepth(format),
1005 .depth = DIV_ROUND_UP(box->z + box->depth, util_format_get_blockdepth(format)),
1006 };
1007
1008 lpt->block_box.width -= lpt->block_box.x;
1009 lpt->block_box.height -= lpt->block_box.y;
1010 lpt->block_box.depth -= lpt->block_box.z;
1011
1012 uint32_t block_stride = util_format_get_blocksize(format);
1013 pt->stride = lpt->block_box.width * block_stride;
1014 pt->layer_stride = pt->stride * lpt->block_box.height;
1015
1016 uint8_t *staging_map = malloc(pt->layer_stride * lpt->block_box.depth);
1017 lpt->map = staging_map;
1018
1019 if (usage & PIPE_MAP_READ) {
1020 for (uint32_t z = 0; z < lpt->block_box.depth; z++) {
1021 for (uint32_t y = 0; y < lpt->block_box.height; y++) {
1022 for (uint32_t x = 0; x < lpt->block_box.width; x++) {
1023 memcpy(staging_map,
1024 map + llvmpipe_get_texel_offset(resource, level,
1025 lpt->block_box.x + x,
1026 lpt->block_box.y + y,
1027 lpt->block_box.z + z),
1028 block_stride);
1029 staging_map += block_stride;
1030 }
1031 }
1032 }
1033 }
1034
1035 return lpt->map;
1036 }
1037
1038 map = llvmpipe_resource_map(resource, level, box->z, tex_usage);
1039 if (!map)
1040 return NULL;
1041
1042 /* May want to do different things here depending on read/write nature
1043 * of the map:
1044 */
1045 if (usage & PIPE_MAP_WRITE) {
1046 /* Do something to notify sharing contexts of a texture change.
1047 */
1048 screen->timestamp++;
1049 }
1050
1051 map +=
1052 box->y / util_format_get_blockheight(format) * pt->stride +
1053 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
1054
1055 map += sample * lpr->sample_stride;
1056 return map;
1057 }
1058
1059 uint32_t
llvmpipe_get_texel_offset(struct pipe_resource * resource,uint32_t level,uint32_t x,uint32_t y,uint32_t z)1060 llvmpipe_get_texel_offset(struct pipe_resource *resource,
1061 uint32_t level, uint32_t x,
1062 uint32_t y, uint32_t z)
1063 {
1064 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1065
1066 uint32_t layer = 0;
1067 if (resource->target != PIPE_TEXTURE_3D) {
1068 layer = z;
1069 z = 0;
1070 }
1071
1072 uint32_t dimensions = 1;
1073 switch (resource->target) {
1074 case PIPE_TEXTURE_2D:
1075 case PIPE_TEXTURE_CUBE:
1076 case PIPE_TEXTURE_RECT:
1077 case PIPE_TEXTURE_2D_ARRAY:
1078 dimensions = 2;
1079 break;
1080 case PIPE_TEXTURE_3D:
1081 dimensions = 3;
1082 break;
1083 default:
1084 break;
1085 }
1086
1087 uint32_t sparse_tile_size[3] = {
1088 util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 0),
1089 util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 1),
1090 util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 2),
1091 };
1092
1093 uint32_t num_tiles_x = DIV_ROUND_UP(u_minify(resource->width0, level),
1094 sparse_tile_size[0] * util_format_get_blockwidth(resource->format));
1095 uint32_t num_tiles_y = DIV_ROUND_UP(u_minify(resource->height0, level),
1096 sparse_tile_size[1] * util_format_get_blockheight(resource->format));
1097
1098 uint32_t offset = (
1099 x / sparse_tile_size[0] +
1100 y / sparse_tile_size[1] * num_tiles_x +
1101 z / sparse_tile_size[2] * num_tiles_x * num_tiles_y
1102 ) * 64 * 1024;
1103
1104 offset += (
1105 x % sparse_tile_size[0] +
1106 (y % sparse_tile_size[1]) * sparse_tile_size[0] +
1107 (z % sparse_tile_size[2]) * sparse_tile_size[0] * sparse_tile_size[1]
1108 ) * util_format_get_blocksize(resource->format);
1109
1110 return offset + lpr->mip_offsets[level] + lpr->img_stride[level] * layer;
1111 }
1112
1113
1114 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)1115 llvmpipe_transfer_map(struct pipe_context *pipe,
1116 struct pipe_resource *resource,
1117 unsigned level,
1118 unsigned usage,
1119 const struct pipe_box *box,
1120 struct pipe_transfer **transfer)
1121 {
1122 return llvmpipe_transfer_map_ms(pipe, resource, level, usage, 0,
1123 box, transfer);
1124 }
1125
1126
1127 static void
llvmpipe_transfer_unmap(struct pipe_context * pipe,struct pipe_transfer * transfer)1128 llvmpipe_transfer_unmap(struct pipe_context *pipe,
1129 struct pipe_transfer *transfer)
1130 {
1131 struct llvmpipe_transfer *lpt = (struct llvmpipe_transfer *)transfer;
1132 struct pipe_resource *resource = transfer->resource;
1133 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1134
1135 assert(resource);
1136
1137 if (llvmpipe_resource_is_texture(resource) && (resource->flags & PIPE_RESOURCE_FLAG_SPARSE) &&
1138 (transfer->usage & PIPE_MAP_WRITE)) {
1139 uint32_t block_stride = util_format_get_blocksize(resource->format);
1140
1141 const uint8_t *src = lpt->map;
1142 uint8_t *dst = lpr->tex_data;
1143
1144 for (uint32_t z = 0; z < lpt->block_box.depth; z++) {
1145 for (uint32_t y = 0; y < lpt->block_box.height; y++) {
1146 for (uint32_t x = 0; x < lpt->block_box.width; x++) {
1147 memcpy(dst + llvmpipe_get_texel_offset(resource, transfer->level,
1148 lpt->block_box.x + x,
1149 lpt->block_box.y + y,
1150 lpt->block_box.z + z),
1151 src, block_stride);
1152 src += block_stride;
1153 }
1154 }
1155 }
1156 }
1157
1158 llvmpipe_resource_unmap(resource,
1159 transfer->level,
1160 transfer->box.z);
1161
1162 pipe_resource_reference(&resource, NULL);
1163 free(lpt->map);
1164 FREE(transfer);
1165 }
1166
1167
1168 unsigned int
llvmpipe_is_resource_referenced(struct pipe_context * pipe,struct pipe_resource * presource,unsigned level)1169 llvmpipe_is_resource_referenced(struct pipe_context *pipe,
1170 struct pipe_resource *presource,
1171 unsigned level)
1172 {
1173 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
1174 if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
1175 PIPE_BIND_RENDER_TARGET |
1176 PIPE_BIND_SAMPLER_VIEW |
1177 PIPE_BIND_CONSTANT_BUFFER |
1178 PIPE_BIND_SHADER_BUFFER |
1179 PIPE_BIND_SHADER_IMAGE)))
1180 return LP_UNREFERENCED;
1181
1182 return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
1183 }
1184
1185
1186 /**
1187 * Returns the largest possible alignment for a format in llvmpipe
1188 */
1189 unsigned
llvmpipe_get_format_alignment(enum pipe_format format)1190 llvmpipe_get_format_alignment(enum pipe_format format)
1191 {
1192 const struct util_format_description *desc = util_format_description(format);
1193 unsigned size = 0;
1194
1195 for (unsigned i = 0; i < desc->nr_channels; ++i) {
1196 size += desc->channel[i].size;
1197 }
1198
1199 unsigned bytes = size / 8;
1200
1201 if (!util_is_power_of_two_or_zero(bytes)) {
1202 bytes /= desc->nr_channels;
1203 }
1204
1205 if (bytes % 2 || bytes < 1) {
1206 return 1;
1207 } else {
1208 return bytes;
1209 }
1210 }
1211
1212
1213 /**
1214 * Create buffer which wraps user-space data.
1215 * XXX unreachable.
1216 */
1217 struct pipe_resource *
llvmpipe_user_buffer_create(struct pipe_screen * screen,void * ptr,unsigned bytes,unsigned bind_flags)1218 llvmpipe_user_buffer_create(struct pipe_screen *screen,
1219 void *ptr,
1220 unsigned bytes,
1221 unsigned bind_flags)
1222 {
1223 struct llvmpipe_resource *buffer;
1224
1225 buffer = CALLOC_STRUCT(llvmpipe_resource);
1226 if (!buffer)
1227 return NULL;
1228
1229 buffer->screen = llvmpipe_screen(screen);
1230 pipe_reference_init(&buffer->base.reference, 1);
1231 buffer->base.screen = screen;
1232 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
1233 buffer->base.bind = bind_flags;
1234 buffer->base.usage = PIPE_USAGE_IMMUTABLE;
1235 buffer->base.flags = 0;
1236 buffer->base.width0 = bytes;
1237 buffer->base.height0 = 1;
1238 buffer->base.depth0 = 1;
1239 buffer->base.array_size = 1;
1240 buffer->user_ptr = true;
1241 buffer->data = ptr;
1242
1243 return &buffer->base;
1244 }
1245
1246
1247 /**
1248 * Compute size (in bytes) need to store a texture image / mipmap level,
1249 * for just one cube face, one array layer or one 3D texture slice
1250 */
1251 static unsigned
tex_image_face_size(const struct llvmpipe_resource * lpr,unsigned level)1252 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
1253 {
1254 return lpr->img_stride[level];
1255 }
1256
1257
1258 /**
1259 * Return pointer to a 2D texture image/face/slice.
1260 * No tiled/linear conversion is done.
1261 */
1262 uint8_t *
llvmpipe_get_texture_image_address(struct llvmpipe_resource * lpr,unsigned face_slice,unsigned level)1263 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
1264 unsigned face_slice, unsigned level)
1265 {
1266 assert(llvmpipe_resource_is_texture(&lpr->base));
1267
1268 unsigned offset = lpr->mip_offsets[level];
1269
1270 if (face_slice > 0)
1271 offset += face_slice * tex_image_face_size(lpr, level);
1272
1273 return (uint8_t *) lpr->tex_data + offset;
1274 }
1275
1276
1277 /**
1278 * Return size of resource in bytes
1279 */
1280 unsigned
llvmpipe_resource_size(const struct pipe_resource * resource)1281 llvmpipe_resource_size(const struct pipe_resource *resource)
1282 {
1283 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
1284 unsigned size = 0;
1285
1286 if (llvmpipe_resource_is_texture(resource)) {
1287 /* Note this will always return 0 for displaytarget resources */
1288 size = lpr->total_alloc_size;
1289 } else {
1290 size = resource->width0;
1291 }
1292 return size;
1293 }
1294
1295
1296 static void
llvmpipe_memory_barrier(struct pipe_context * pipe,unsigned flags)1297 llvmpipe_memory_barrier(struct pipe_context *pipe,
1298 unsigned flags)
1299 {
1300 /* this may be an overly large hammer for this nut. */
1301 llvmpipe_finish(pipe, "barrier");
1302 }
1303
1304
1305 static struct pipe_memory_allocation *
llvmpipe_allocate_memory(struct pipe_screen * _screen,uint64_t size)1306 llvmpipe_allocate_memory(struct pipe_screen *_screen, uint64_t size)
1307 {
1308 struct llvmpipe_memory_allocation *mem = CALLOC_STRUCT(llvmpipe_memory_allocation);
1309 uint64_t alignment;
1310 if (!os_get_page_size(&alignment))
1311 alignment = 256;
1312
1313 mem->size = align64(size, alignment);
1314
1315 #if DETECT_OS_LINUX
1316 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
1317
1318 mem->cpu_addr = MAP_FAILED;
1319 mem->fd = screen->fd_mem_alloc;
1320
1321 mtx_lock(&screen->mem_mutex);
1322
1323 mem->offset = util_vma_heap_alloc(&screen->mem_heap, mem->size, alignment);
1324 if (!mem->offset) {
1325 mtx_unlock(&screen->mem_mutex);
1326 FREE(mem);
1327 return NULL;
1328 }
1329
1330 if (mem->offset + mem->size > screen->mem_file_size) {
1331 /* expand the anonymous file */
1332 screen->mem_file_size = mem->offset + mem->size;
1333 UNUSED int unused = ftruncate(screen->fd_mem_alloc, screen->mem_file_size);
1334 }
1335
1336 mtx_unlock(&screen->mem_mutex);
1337 #else
1338 mem->cpu_addr = malloc(mem->size);
1339 #endif
1340
1341 return (struct pipe_memory_allocation *)mem;
1342 }
1343
1344
1345 static void
llvmpipe_free_memory(struct pipe_screen * pscreen,struct pipe_memory_allocation * pmem)1346 llvmpipe_free_memory(struct pipe_screen *pscreen,
1347 struct pipe_memory_allocation *pmem)
1348 {
1349 struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1350
1351 #if DETECT_OS_LINUX
1352 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1353
1354 if (mem->fd) {
1355 mtx_lock(&screen->mem_mutex);
1356 util_vma_heap_free(&screen->mem_heap, mem->offset, mem->size);
1357 mtx_unlock(&screen->mem_mutex);
1358 }
1359
1360 if (mem->cpu_addr != MAP_FAILED)
1361 munmap(mem->cpu_addr, mem->size);
1362 #else
1363 free(mem->cpu_addr);
1364 #endif
1365
1366 FREE(mem);
1367 }
1368
1369
1370 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1371 static void*
llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen * screen,struct llvmpipe_memory_allocation * alloc,size_t size)1372 llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen *screen,
1373 struct llvmpipe_memory_allocation *alloc,
1374 size_t size)
1375 {
1376 int mem_fd = -1;
1377 int dmabuf_fd = -1;
1378 if (screen->udmabuf_fd != -1) {
1379 uint64_t alignment;
1380 if (!os_get_page_size(&alignment))
1381 alignment = 256;
1382
1383 size = align(size, alignment);
1384
1385 int mem_fd = memfd_create("lp_dma_buf", MFD_ALLOW_SEALING);
1386 if (mem_fd == -1)
1387 goto fail;
1388
1389 int res = ftruncate(mem_fd, size);
1390 if (res == -1)
1391 goto fail;
1392
1393 /* udmabuf create requires that the memfd have
1394 * have the F_SEAL_SHRINK seal added and must not
1395 * have the F_SEAL_WRITE seal added */
1396 if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
1397 goto fail;
1398
1399 struct udmabuf_create create = {
1400 .memfd = mem_fd,
1401 .flags = UDMABUF_FLAGS_CLOEXEC,
1402 .offset = 0,
1403 .size = size
1404 };
1405
1406 int dmabuf_fd = ioctl(screen->udmabuf_fd, UDMABUF_CREATE, &create);
1407 if (dmabuf_fd < 0)
1408 goto fail;
1409
1410 struct pipe_memory_allocation *data =
1411 mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0);
1412
1413 if (!data)
1414 goto fail;
1415
1416 alloc->mem_fd = mem_fd;
1417 alloc->dmabuf_fd = dmabuf_fd;
1418 alloc->size = size;
1419 return data;
1420 }
1421
1422 fail:
1423 if (mem_fd != -1)
1424 close(mem_fd);
1425 if (dmabuf_fd != -1)
1426 close(dmabuf_fd);
1427 /* If we don't have access to the udmabuf device
1428 * or something else fails we return NULL */
1429 return NULL;
1430 }
1431 #endif
1432
1433 #ifdef PIPE_MEMORY_FD
1434 static struct pipe_memory_allocation *
llvmpipe_allocate_memory_fd(struct pipe_screen * pscreen,uint64_t size,int * fd,bool dmabuf)1435 llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen,
1436 uint64_t size,
1437 int *fd,
1438 bool dmabuf)
1439 {
1440 struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
1441 if (!alloc)
1442 goto fail;
1443
1444 alloc->mem_fd = -1;
1445 alloc->dmabuf_fd = -1;
1446 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1447 if (dmabuf) {
1448 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1449 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
1450 alloc->cpu_addr = llvmpipe_resource_alloc_udmabuf(screen, alloc, size);
1451
1452 if (alloc->cpu_addr)
1453 *fd = os_dupfd_cloexec(alloc->dmabuf_fd);
1454 } else
1455 #endif
1456 {
1457 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE;
1458 uint64_t alignment;
1459 if (!os_get_page_size(&alignment))
1460 alignment = 256;
1461 alloc->cpu_addr = os_malloc_aligned_fd(size, alignment, fd,
1462 "llvmpipe memory fd", driver_id);
1463 }
1464
1465 if(alloc && !alloc->cpu_addr) {
1466 free(alloc);
1467 alloc = NULL;
1468 }
1469
1470 fail:
1471 return (struct pipe_memory_allocation*)alloc;
1472 }
1473
1474
1475 static bool
llvmpipe_import_memory_fd(struct pipe_screen * screen,int fd,struct pipe_memory_allocation ** ptr,uint64_t * size,bool dmabuf)1476 llvmpipe_import_memory_fd(struct pipe_screen *screen,
1477 int fd,
1478 struct pipe_memory_allocation **ptr,
1479 uint64_t *size,
1480 bool dmabuf)
1481 {
1482 struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
1483 alloc->mem_fd = -1;
1484 alloc->dmabuf_fd = -1;
1485 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1486 if (dmabuf) {
1487 off_t mmap_size = lseek(fd, 0, SEEK_END);
1488 lseek(fd, 0, SEEK_SET);
1489 void *cpu_addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1490 if (cpu_addr == MAP_FAILED) {
1491 free(alloc);
1492 *ptr = NULL;
1493 return false;
1494 }
1495
1496 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
1497 alloc->cpu_addr = cpu_addr;
1498 alloc->size = mmap_size;
1499 alloc->dmabuf_fd = os_dupfd_cloexec(fd);
1500 *ptr = (struct pipe_memory_allocation*)alloc;
1501 *size = mmap_size;
1502
1503 return true;
1504 } else
1505 #endif
1506 {
1507 bool ret = os_import_memory_fd(fd, (void**)&alloc->cpu_addr, size, driver_id);
1508
1509 if (!ret) {
1510 free(alloc);
1511 *ptr = NULL;
1512 return false;
1513 } else {
1514 *ptr = (struct pipe_memory_allocation*)alloc;
1515 }
1516
1517 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE;
1518 return ret;
1519 }
1520 }
1521
1522
1523 static void
llvmpipe_free_memory_fd(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1524 llvmpipe_free_memory_fd(struct pipe_screen *screen,
1525 struct pipe_memory_allocation *pmem)
1526 {
1527 struct llvmpipe_memory_allocation *alloc = (struct llvmpipe_memory_allocation*)pmem;
1528 if (alloc->type == LLVMPIPE_MEMORY_FD_TYPE_OPAQUE) {
1529 os_free_fd(alloc->cpu_addr);
1530 }
1531 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1532 else {
1533 munmap(alloc->cpu_addr, alloc->size);
1534 if (alloc->dmabuf_fd >= 0)
1535 close(alloc->dmabuf_fd);
1536 if (alloc->mem_fd >= 0)
1537 close(alloc->mem_fd);
1538 }
1539 #endif
1540
1541 free(alloc);
1542 }
1543
1544 #endif
1545
1546 static void *
llvmpipe_map_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1547 llvmpipe_map_memory(struct pipe_screen *screen,
1548 struct pipe_memory_allocation *pmem)
1549 {
1550 struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1551
1552 #if DETECT_OS_LINUX
1553 if (mem->cpu_addr != MAP_FAILED)
1554 return mem->cpu_addr;
1555
1556 /* create a "CPU" mapping */
1557 mem->cpu_addr = mmap(NULL, mem->size, PROT_READ|PROT_WRITE, MAP_SHARED,
1558 mem->fd, mem->offset);
1559 assert(mem->cpu_addr != MAP_FAILED);
1560 #endif
1561
1562 return mem->cpu_addr;
1563 }
1564
1565 static void
llvmpipe_unmap_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1566 llvmpipe_unmap_memory(struct pipe_screen *screen,
1567 struct pipe_memory_allocation *pmem)
1568 {
1569 }
1570
1571 static bool
llvmpipe_resource_bind_backing(struct pipe_screen * pscreen,struct pipe_resource * pt,struct pipe_memory_allocation * pmem,uint64_t fd_offset,uint64_t size,uint64_t offset)1572 llvmpipe_resource_bind_backing(struct pipe_screen *pscreen,
1573 struct pipe_resource *pt,
1574 struct pipe_memory_allocation *pmem,
1575 uint64_t fd_offset,
1576 uint64_t size,
1577 uint64_t offset)
1578 {
1579 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1580 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
1581 struct sw_winsys *winsys = screen->winsys;
1582
1583 void *addr;
1584 if (!lpr->backable)
1585 return false;
1586
1587 if ((lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) && offset < lpr->size_required) {
1588 #if DETECT_OS_LINUX
1589 struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1590 if (mem) {
1591 if (llvmpipe_resource_is_texture(&lpr->base)) {
1592 mmap((char *)lpr->tex_data + offset, size, PROT_READ|PROT_WRITE,
1593 MAP_SHARED|MAP_FIXED, mem->fd, mem->offset + fd_offset);
1594 BITSET_SET(lpr->residency, offset / (64 * 1024));
1595 } else {
1596 mmap((char *)lpr->data + offset, size, PROT_READ|PROT_WRITE,
1597 MAP_SHARED|MAP_FIXED, mem->fd, mem->offset + fd_offset);
1598 }
1599 } else {
1600 if (llvmpipe_resource_is_texture(&lpr->base)) {
1601 mmap((char *)lpr->tex_data + offset, size, PROT_READ|PROT_WRITE,
1602 MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1603 BITSET_CLEAR(lpr->residency, offset / (64 * 1024));
1604 } else {
1605 mmap((char *)lpr->data + offset, size, PROT_READ|PROT_WRITE,
1606 MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1607 }
1608 }
1609 #endif
1610
1611 return true;
1612 }
1613
1614 addr = llvmpipe_map_memory(pscreen, pmem);
1615
1616 if (llvmpipe_resource_is_texture(&lpr->base)) {
1617 if (lpr->size_required > LP_MAX_TEXTURE_SIZE)
1618 return false;
1619
1620 lpr->tex_data = (char *)addr + offset;
1621
1622 if (lpr->dmabuf) {
1623 if (lpr->dt)
1624 {
1625 winsys->displaytarget_unmap(winsys, lpr->dt);
1626 winsys->displaytarget_destroy(winsys, lpr->dt);
1627 }
1628 if (pmem) {
1629 /* Round up the surface size to a multiple of the tile size to
1630 * avoid tile clipping.
1631 */
1632 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
1633 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
1634
1635 lpr->dt = winsys->displaytarget_create_mapped(winsys,
1636 lpr->base.bind,
1637 lpr->base.format,
1638 width, height,
1639 lpr->row_stride[0],
1640 lpr->tex_data);
1641 }
1642 }
1643 } else
1644 lpr->data = (char *)addr + offset;
1645 lpr->backing_offset = offset;
1646
1647 return true;
1648 }
1649
1650
1651
1652 #if MESA_DEBUG
1653 void
llvmpipe_print_resources(void)1654 llvmpipe_print_resources(void)
1655 {
1656 struct llvmpipe_resource *lpr;
1657 unsigned n = 0, total = 0;
1658
1659 debug_printf("LLVMPIPE: current resources:\n");
1660 simple_mtx_lock(&resource_list_mutex);
1661 LIST_FOR_EACH_ENTRY(lpr, &resource_list.list, list) {
1662 unsigned size = llvmpipe_resource_size(&lpr->base);
1663 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
1664 lpr->id, (void *) lpr,
1665 lpr->base.width0, lpr->base.height0, lpr->base.depth0,
1666 size, lpr->base.reference.count);
1667 total += size;
1668 n++;
1669 }
1670 simple_mtx_unlock(&resource_list_mutex);
1671 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
1672 }
1673 #endif
1674
1675
1676 static void
llvmpipe_get_resource_info(struct pipe_screen * screen,struct pipe_resource * resource,unsigned * stride,unsigned * offset)1677 llvmpipe_get_resource_info(struct pipe_screen *screen,
1678 struct pipe_resource *resource,
1679 unsigned *stride,
1680 unsigned *offset)
1681 {
1682 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1683
1684 *stride = lpr->row_stride[0];
1685 *offset = 0;
1686 }
1687
1688
1689 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)1690 llvmpipe_resource_get_param(struct pipe_screen *screen,
1691 struct pipe_context *context,
1692 struct pipe_resource *resource,
1693 unsigned plane,
1694 unsigned layer,
1695 unsigned level,
1696 enum pipe_resource_param param,
1697 unsigned handle_usage,
1698 uint64_t *value)
1699 {
1700 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1701 struct winsys_handle whandle;
1702
1703 switch (param) {
1704 case PIPE_RESOURCE_PARAM_NPLANES:
1705 *value = lpr->dmabuf ? util_format_get_num_planes(lpr->dt_format) : 1;
1706 return true;
1707 case PIPE_RESOURCE_PARAM_STRIDE:
1708 *value = lpr->row_stride[level];
1709 return true;
1710 case PIPE_RESOURCE_PARAM_OFFSET:
1711 *value = lpr->mip_offsets[level] + (lpr->img_stride[level] * layer);
1712 return true;
1713 case PIPE_RESOURCE_PARAM_LAYER_STRIDE:
1714 *value = lpr->img_stride[level];
1715 return true;
1716 #ifndef _WIN32
1717 case PIPE_RESOURCE_PARAM_MODIFIER:
1718 *value = lpr->dmabuf ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
1719 return true;
1720 #endif
1721 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
1722 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
1723 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
1724 if (!lpr->dt)
1725 return false;
1726
1727 memset(&whandle, 0, sizeof(whandle));
1728 if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED)
1729 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1730 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS)
1731 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1732 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD)
1733 whandle.type = WINSYS_HANDLE_TYPE_FD;
1734
1735 if (!llvmpipe_resource_get_handle(screen, context, resource,
1736 &whandle, handle_usage)) {
1737 return false;
1738 }
1739 *value = (uint64_t)(uintptr_t)whandle.handle;
1740 return true;
1741 default:
1742 break;
1743 }
1744 assert(0);
1745 *value = 0;
1746 return false;
1747 }
1748
1749 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1750 static void
llvmpipe_query_dmabuf_modifiers(struct pipe_screen * pscreen,enum pipe_format format,int max,uint64_t * modifiers,unsigned int * external_only,int * count)1751 llvmpipe_query_dmabuf_modifiers(struct pipe_screen *pscreen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count)
1752 {
1753 *count = 1;
1754
1755 if (max)
1756 *modifiers = DRM_FORMAT_MOD_LINEAR;
1757 }
1758
1759 static bool
llvmpipe_is_dmabuf_modifier_supported(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format,bool * external_only)1760 llvmpipe_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format, bool *external_only)
1761 {
1762 return modifier == DRM_FORMAT_MOD_LINEAR;
1763 }
1764
1765 static unsigned
llvmpipe_get_dmabuf_modifier_planes(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format)1766 llvmpipe_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format)
1767 {
1768 return modifier == DRM_FORMAT_MOD_LINEAR;
1769 }
1770 #endif
1771
1772 void
llvmpipe_init_screen_resource_funcs(struct pipe_screen * screen)1773 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
1774 {
1775 #if MESA_DEBUG
1776 /* init linked list for tracking resources */
1777 {
1778 static bool first_call = true;
1779 if (first_call) {
1780 memset(&resource_list, 0, sizeof(resource_list));
1781 list_inithead(&resource_list.list);
1782 first_call = false;
1783 }
1784 }
1785 #endif
1786
1787 screen->resource_create = llvmpipe_resource_create;
1788 /* screen->resource_create_front = llvmpipe_resource_create_front; */
1789 screen->resource_destroy = llvmpipe_resource_destroy;
1790 screen->resource_from_handle = llvmpipe_resource_from_handle;
1791 screen->resource_from_memobj = llvmpipe_resource_from_memobj;
1792 screen->resource_get_handle = llvmpipe_resource_get_handle;
1793 screen->can_create_resource = llvmpipe_can_create_resource;
1794
1795 screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
1796
1797 screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle;
1798 screen->memobj_destroy = llvmpipe_memobj_destroy;
1799
1800 screen->resource_get_info = llvmpipe_get_resource_info;
1801 screen->resource_get_param = llvmpipe_resource_get_param;
1802 screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
1803 screen->allocate_memory = llvmpipe_allocate_memory;
1804 screen->free_memory = llvmpipe_free_memory;
1805 #ifdef PIPE_MEMORY_FD
1806 screen->allocate_memory_fd = llvmpipe_allocate_memory_fd;
1807 screen->import_memory_fd = llvmpipe_import_memory_fd;
1808 screen->free_memory_fd = llvmpipe_free_memory_fd;
1809 #endif
1810 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1811 screen->query_dmabuf_modifiers = llvmpipe_query_dmabuf_modifiers;
1812 screen->is_dmabuf_modifier_supported = llvmpipe_is_dmabuf_modifier_supported;
1813 screen->get_dmabuf_modifier_planes = llvmpipe_get_dmabuf_modifier_planes;
1814 screen->resource_create_with_modifiers = llvmpipe_resource_create_with_modifiers;
1815 #endif
1816 screen->map_memory = llvmpipe_map_memory;
1817 screen->unmap_memory = llvmpipe_unmap_memory;
1818
1819 screen->resource_bind_backing = llvmpipe_resource_bind_backing;
1820 }
1821
1822
1823 void
llvmpipe_init_context_resource_funcs(struct pipe_context * pipe)1824 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
1825 {
1826 pipe->buffer_map = llvmpipe_transfer_map;
1827 pipe->buffer_unmap = llvmpipe_transfer_unmap;
1828 pipe->texture_map = llvmpipe_transfer_map;
1829 pipe->texture_unmap = llvmpipe_transfer_unmap;
1830
1831 pipe->transfer_flush_region = u_default_transfer_flush_region;
1832 pipe->buffer_subdata = u_default_buffer_subdata;
1833 pipe->texture_subdata = u_default_texture_subdata;
1834
1835 pipe->memory_barrier = llvmpipe_memory_barrier;
1836 }
1837