xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/llvmpipe/lp_texture.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 <[email protected]>
30   *   Michel Dänzer <[email protected]>
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 
453    if (handle->type == WINSYS_HANDLE_TYPE_FD &&
454        pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size, false)) {
455       return &memobj->b;
456    }
457    free(memobj);
458 #endif
459    return NULL;
460 }
461 
462 
463 static void
llvmpipe_memobj_destroy(struct pipe_screen * pscreen,struct pipe_memory_object * memobj)464 llvmpipe_memobj_destroy(struct pipe_screen *pscreen,
465                         struct pipe_memory_object *memobj)
466 {
467    if (!memobj)
468       return;
469    struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
470 #ifdef PIPE_MEMORY_FD
471    pscreen->free_memory_fd(pscreen, lpmo->data);
472 #endif
473    free(lpmo);
474 }
475 
476 
477 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)478 llvmpipe_resource_from_memobj(struct pipe_screen *pscreen,
479                               const struct pipe_resource *templat,
480                               struct pipe_memory_object *memobj,
481                               uint64_t offset)
482 {
483    if (!memobj)
484       return NULL;
485    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
486    struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
487    struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
488    lpr->base = *templat;
489 
490    lpr->screen = screen;
491    pipe_reference_init(&lpr->base.reference, 1);
492    lpr->base.screen = &screen->base;
493 
494    if (llvmpipe_resource_is_texture(&lpr->base)) {
495       /* texture map */
496       if (!llvmpipe_texture_layout(screen, lpr, false))
497          goto fail;
498       if (lpmo->size < lpr->size_required)
499          goto fail;
500       lpr->tex_data = lpmo->data;
501    } else {
502       /* other data (vertex buffer, const buffer, etc) */
503       const uint bytes = templat->width0;
504       assert(util_format_get_blocksize(templat->format) == 1);
505       assert(templat->height0 == 1);
506       assert(templat->depth0 == 1);
507       assert(templat->last_level == 0);
508       /*
509        * Reserve some extra storage since if we'd render to a buffer we
510        * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
511        * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
512        */
513       /*
514        * buffers don't really have stride but it's probably safer
515        * (for code doing same calculations for buffers and textures)
516        * to put something reasonable in there.
517        */
518       lpr->row_stride[0] = bytes;
519 
520       lpr->size_required = bytes;
521       if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
522          lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
523 
524       if (lpmo->size < lpr->size_required)
525          goto fail;
526       lpr->data = lpmo->data;
527    }
528    lpr->id = id_counter++;
529    lpr->imported_memory = true;
530 
531 #if MESA_DEBUG
532    simple_mtx_lock(&resource_list_mutex);
533    list_addtail(&lpr->list, &resource_list.list);
534    simple_mtx_unlock(&resource_list_mutex);
535 #endif
536 
537    return &lpr->base;
538 
539 fail:
540    free(lpr);
541    return NULL;
542 }
543 
544 static void
llvmpipe_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * pt)545 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
546                           struct pipe_resource *pt)
547 {
548    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
549    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
550 
551    if (!lpr->backable && !lpr->user_ptr) {
552       if (lpr->dt) {
553          /* display target */
554          struct sw_winsys *winsys = screen->winsys;
555          winsys->displaytarget_destroy(winsys, lpr->dt);
556       } else if (llvmpipe_resource_is_texture(pt)) {
557          /* free linear image data */
558          if (lpr->tex_data) {
559             if (!lpr->imported_memory)
560                align_free(lpr->tex_data);
561             lpr->tex_data = NULL;
562          }
563       } else if (lpr->data) {
564          if (!lpr->imported_memory)
565             align_free(lpr->data);
566       }
567    }
568 
569 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
570    if (lpr->dmabuf_alloc)
571       pscreen->free_memory_fd(pscreen, (struct pipe_memory_allocation*)lpr->dmabuf_alloc);
572 #endif
573 
574    if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) {
575 #if DETECT_OS_LINUX
576       if (llvmpipe_resource_is_texture(pt))
577          munmap(lpr->tex_data, lpr->size_required);
578       else
579          munmap(lpr->data, lpr->size_required);
580 #endif
581    }
582 
583    free(lpr->residency);
584 
585 #if MESA_DEBUG
586    simple_mtx_lock(&resource_list_mutex);
587    if (!list_is_empty(&lpr->list))
588       list_del(&lpr->list);
589    simple_mtx_unlock(&resource_list_mutex);
590 #endif
591 
592    FREE(lpr);
593 }
594 
595 
596 /**
597  * Map a resource for read/write.
598  */
599 void *
llvmpipe_resource_map(struct pipe_resource * resource,unsigned level,unsigned layer,enum lp_texture_usage tex_usage)600 llvmpipe_resource_map(struct pipe_resource *resource,
601                       unsigned level,
602                       unsigned layer,
603                       enum lp_texture_usage tex_usage)
604 {
605    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
606    uint8_t *map;
607 
608    assert(level < LP_MAX_TEXTURE_LEVELS);
609    assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
610 
611    assert(tex_usage == LP_TEX_USAGE_READ ||
612           tex_usage == LP_TEX_USAGE_READ_WRITE ||
613           tex_usage == LP_TEX_USAGE_WRITE_ALL);
614 
615    if (lpr->dt) {
616       if (lpr->dmabuf)
617          return lpr->tex_data;
618       /* display target */
619       struct llvmpipe_screen *screen = lpr->screen;
620       struct sw_winsys *winsys = screen->winsys;
621       unsigned dt_usage;
622 
623       if (tex_usage == LP_TEX_USAGE_READ) {
624          dt_usage = PIPE_MAP_READ;
625       } else {
626          dt_usage = PIPE_MAP_READ_WRITE;
627       }
628 
629       assert(level == 0);
630       assert(layer == 0);
631 
632       /* FIXME: keep map count? */
633       map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
634 
635       /* install this linear image in texture data structure */
636       lpr->tex_data = map;
637 
638       return map;
639    } else if (llvmpipe_resource_is_texture(resource)) {
640 
641       map = llvmpipe_get_texture_image_address(lpr, layer, level);
642       return map;
643    } else {
644       return lpr->data;
645    }
646 }
647 
648 
649 /**
650  * Unmap a resource.
651  */
652 void
llvmpipe_resource_unmap(struct pipe_resource * resource,unsigned level,unsigned layer)653 llvmpipe_resource_unmap(struct pipe_resource *resource,
654                         unsigned level,
655                         unsigned layer)
656 {
657    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
658 
659    if (lpr->dt) {
660       if (lpr->dmabuf)
661          return;
662       /* display target */
663       struct llvmpipe_screen *lp_screen = lpr->screen;
664       struct sw_winsys *winsys = lp_screen->winsys;
665 
666       assert(level == 0);
667       assert(layer == 0);
668 
669       winsys->displaytarget_unmap(winsys, lpr->dt);
670    }
671 }
672 
673 
674 void *
llvmpipe_resource_data(struct pipe_resource * resource)675 llvmpipe_resource_data(struct pipe_resource *resource)
676 {
677    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
678 
679    assert(!llvmpipe_resource_is_texture(resource));
680 
681    return lpr->data;
682 }
683 
684 
685 static struct pipe_resource *
llvmpipe_resource_from_handle(struct pipe_screen * _screen,const struct pipe_resource * template,struct winsys_handle * whandle,unsigned usage)686 llvmpipe_resource_from_handle(struct pipe_screen *_screen,
687                               const struct pipe_resource *template,
688                               struct winsys_handle *whandle,
689                               unsigned usage)
690 {
691    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
692    struct sw_winsys *winsys = screen->winsys;
693    struct llvmpipe_resource *lpr;
694 
695    /* no multisampled */
696    assert(template->nr_samples < 2);
697    /* no miplevels */
698    assert(template->last_level == 0);
699 
700    /* Multiplanar surfaces are not supported */
701    if (whandle->plane > 0)
702       return NULL;
703 
704    lpr = CALLOC_STRUCT(llvmpipe_resource);
705    if (!lpr) {
706       goto no_lpr;
707    }
708 
709    lpr->base = *template;
710    lpr->screen = screen;
711    lpr->dt_format = whandle->format;
712    pipe_reference_init(&lpr->base.reference, 1);
713    lpr->base.screen = _screen;
714 
715    /*
716     * Looks like unaligned displaytargets work just fine,
717     * at least sampler/render ones.
718     */
719 #if 0
720    assert(lpr->base.width0 == width);
721    assert(lpr->base.height0 == height);
722 #endif
723 
724    unsigned nblocksy = util_format_get_nblocksy(template->format, align(template->height0, LP_RASTER_BLOCK_SIZE));
725    if (whandle->type == WINSYS_HANDLE_TYPE_UNBACKED && whandle->image_stride)
726       lpr->img_stride[0] = whandle->image_stride;
727    else
728       lpr->img_stride[0] = whandle->stride * nblocksy;
729    lpr->sample_stride = lpr->img_stride[0];
730    lpr->size_required = lpr->sample_stride;
731 
732    if (whandle->type != WINSYS_HANDLE_TYPE_UNBACKED) {
733 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
734       struct llvmpipe_memory_allocation *alloc;
735       uint64_t size;
736       /* Not all winsys implement displaytarget_create_mapped so we need to check
737        * that is available (not null).
738        */
739       if (winsys->displaytarget_create_mapped &&
740           _screen->import_memory_fd(_screen, whandle->handle,
741                                     (struct pipe_memory_allocation**)&alloc,
742                                     &size, true)) {
743          void *data = alloc->cpu_addr;
744          lpr->dt = winsys->displaytarget_create_mapped(winsys, template->bind,
745                                                        template->format, template->width0, template->height0,
746                                                        whandle->stride, data);
747          if (!lpr->dt)
748             goto no_dt;
749          lpr->dmabuf_alloc = alloc;
750          lpr->dmabuf = true;
751          lpr->tex_data = data;
752          lpr->row_stride[0] = whandle->stride;
753          whandle->size = size;
754       } else
755 #endif
756       {
757          lpr->dt = winsys->displaytarget_from_handle(winsys,
758                                                      template,
759                                                      whandle,
760                                                      &lpr->row_stride[0]);
761          if (!lpr->dt)
762             goto no_dt;
763       }
764 
765       assert(llvmpipe_resource_is_texture(&lpr->base));
766    } else {
767       whandle->size = lpr->size_required;
768       lpr->row_stride[0] = whandle->stride;
769       lpr->backable = true;
770    }
771 
772 
773    lpr->id = id_counter++;
774 
775 #if MESA_DEBUG
776    simple_mtx_lock(&resource_list_mutex);
777    list_addtail(&lpr->list, &resource_list.list);
778    simple_mtx_unlock(&resource_list_mutex);
779 #endif
780 
781    return &lpr->base;
782 
783 no_dt:
784    FREE(lpr);
785 no_lpr:
786    return NULL;
787 }
788 
789 
790 static bool
llvmpipe_resource_get_handle(struct pipe_screen * _screen,struct pipe_context * ctx,struct pipe_resource * pt,struct winsys_handle * whandle,unsigned usage)791 llvmpipe_resource_get_handle(struct pipe_screen *_screen,
792                              struct pipe_context *ctx,
793                              struct pipe_resource *pt,
794                              struct winsys_handle *whandle,
795                              unsigned usage)
796 {
797    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
798    struct sw_winsys *winsys = screen->winsys;
799    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
800 
801 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
802    if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_FD) {
803       if (!lpr->dmabuf_alloc) {
804          lpr->dmabuf_alloc = (struct llvmpipe_memory_allocation*)_screen->allocate_memory_fd(_screen, lpr->size_required, (int*)&whandle->handle, true);
805          if (!lpr->dmabuf_alloc)
806             return false;
807 
808          /* replace existing backing with fd backing */
809          bool is_tex = llvmpipe_resource_is_texture(pt);
810          if (is_tex) {
811             if (lpr->tex_data)
812                memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->tex_data, lpr->size_required);
813          } else {
814             if (lpr->data)
815                memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->data, lpr->size_required);
816          }
817          if (!lpr->imported_memory)
818             align_free(is_tex ? lpr->tex_data : lpr->data);
819          if (is_tex)
820             lpr->tex_data = lpr->dmabuf_alloc->cpu_addr;
821          else
822             lpr->data = lpr->dmabuf_alloc->cpu_addr;
823          /* reuse lavapipe codepath to handle destruction */
824          lpr->backable = true;
825       } else {
826          whandle->handle = os_dupfd_cloexec(lpr->dmabuf_alloc->dmabuf_fd);
827       }
828       whandle->modifier = DRM_FORMAT_MOD_LINEAR;
829       whandle->stride = lpr->row_stride[0];
830       return true;
831    } else if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_KMS) {
832       /* dri winsys code will use this to query the drm modifiers
833        * We can just return an null handle and return DRM_FORMAT_MOD_LINEAR */
834       whandle->handle = 0;
835       whandle->modifier = DRM_FORMAT_MOD_LINEAR;
836       return true;
837     }
838 #endif
839    assert(lpr->dt);
840    if (!lpr->dt)
841       return false;
842 
843    return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
844 }
845 
846 
847 static struct pipe_resource *
llvmpipe_resource_from_user_memory(struct pipe_screen * _screen,const struct pipe_resource * resource,void * user_memory)848 llvmpipe_resource_from_user_memory(struct pipe_screen *_screen,
849                                    const struct pipe_resource *resource,
850                                    void *user_memory)
851 {
852    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
853    struct llvmpipe_resource *lpr;
854 
855    lpr = CALLOC_STRUCT(llvmpipe_resource);
856    if (!lpr) {
857       return NULL;
858    }
859 
860    lpr->base = *resource;
861    lpr->screen = screen;
862    pipe_reference_init(&lpr->base.reference, 1);
863    lpr->base.screen = _screen;
864 
865    if (llvmpipe_resource_is_texture(&lpr->base)) {
866       if (!llvmpipe_texture_layout(screen, lpr, false))
867          goto fail;
868 
869       lpr->tex_data = user_memory;
870    } else
871       lpr->data = user_memory;
872    lpr->user_ptr = true;
873 #if MESA_DEBUG
874    simple_mtx_lock(&resource_list_mutex);
875    list_addtail(&lpr->list, &resource_list.list);
876    simple_mtx_unlock(&resource_list_mutex);
877 #endif
878    return &lpr->base;
879 fail:
880    FREE(lpr);
881    return NULL;
882 }
883 
884 
885 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)886 llvmpipe_transfer_map_ms(struct pipe_context *pipe,
887                          struct pipe_resource *resource,
888                          unsigned level,
889                          unsigned usage,
890                          unsigned sample,
891                          const struct pipe_box *box,
892                          struct pipe_transfer **transfer)
893 {
894    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
895    struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
896    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
897    struct llvmpipe_transfer *lpt;
898    struct pipe_transfer *pt;
899    uint8_t *map;
900    enum pipe_format format;
901 
902    assert(resource);
903    assert(level <= resource->last_level);
904 
905    /*
906     * Transfers, like other pipe operations, must happen in order, so flush
907     * the context if necessary.
908     */
909    if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
910       bool read_only = !(usage & PIPE_MAP_WRITE);
911       bool do_not_block = !!(usage & PIPE_MAP_DONTBLOCK);
912       if (!llvmpipe_flush_resource(pipe, resource,
913                                    level,
914                                    read_only,
915                                    true, /* cpu_access */
916                                    do_not_block,
917                                    __func__)) {
918          /*
919           * It would have blocked, but gallium frontend requested no to.
920           */
921          assert(do_not_block);
922          return NULL;
923       }
924    }
925 
926    /* Check if we're mapping a current constant buffer */
927    if ((usage & PIPE_MAP_WRITE) &&
928        (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
929       unsigned i;
930       for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
931          if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
932             /* constants may have changed */
933             llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
934             break;
935          }
936       }
937    }
938 
939    lpt = CALLOC_STRUCT(llvmpipe_transfer);
940    if (!lpt)
941       return NULL;
942    pt = &lpt->base;
943    pipe_resource_reference(&pt->resource, resource);
944    pt->box = *box;
945    pt->level = level;
946    pt->stride = lpr->row_stride[level];
947    pt->layer_stride = lpr->img_stride[level];
948    pt->usage = usage;
949    *transfer = pt;
950 
951    assert(level < LP_MAX_TEXTURE_LEVELS);
952 
953    /*
954    printf("tex_transfer_map(%d, %d  %d x %d of %d x %d,  usage %d)\n",
955           transfer->x, transfer->y, transfer->width, transfer->height,
956           transfer->texture->width0,
957           transfer->texture->height0,
958           transfer->usage);
959    */
960 
961    enum lp_texture_usage tex_usage;
962    const char *mode;
963    if (usage == PIPE_MAP_READ) {
964       tex_usage = LP_TEX_USAGE_READ;
965       mode = "read";
966    } else {
967       tex_usage = LP_TEX_USAGE_READ_WRITE;
968       mode = "read/write";
969    }
970 
971    if (0) {
972       printf("transfer map tex %u  mode %s\n", lpr->id, mode);
973    }
974 
975    format = lpr->base.format;
976 
977    if (llvmpipe_resource_is_texture(resource) && (resource->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
978       map = llvmpipe_resource_map(resource, 0, 0, tex_usage);
979 
980       lpt->block_box = (struct pipe_box) {
981          .x = box->x / util_format_get_blockwidth(format),
982          .width = DIV_ROUND_UP(box->x + box->width, util_format_get_blockwidth(format)),
983          .y = box->y / util_format_get_blockheight(format),
984          .height = DIV_ROUND_UP(box->y + box->height, util_format_get_blockheight(format)),
985          .z = box->z / util_format_get_blockdepth(format),
986          .depth = DIV_ROUND_UP(box->z + box->depth, util_format_get_blockdepth(format)),
987       };
988 
989       lpt->block_box.width -= lpt->block_box.x;
990       lpt->block_box.height -= lpt->block_box.y;
991       lpt->block_box.depth -= lpt->block_box.z;
992 
993       uint32_t block_stride = util_format_get_blocksize(format);
994       pt->stride = lpt->block_box.width * block_stride;
995       pt->layer_stride = pt->stride * lpt->block_box.height;
996 
997       uint8_t *staging_map = malloc(pt->layer_stride * lpt->block_box.depth);
998       lpt->map = staging_map;
999 
1000       if (usage & PIPE_MAP_READ) {
1001          for (uint32_t z = 0; z < lpt->block_box.depth; z++) {
1002             for (uint32_t y = 0; y < lpt->block_box.height; y++) {
1003                for (uint32_t x = 0; x < lpt->block_box.width; x++) {
1004                   memcpy(staging_map,
1005                          map + llvmpipe_get_texel_offset(resource, level,
1006                                                          lpt->block_box.x + x,
1007                                                          lpt->block_box.y + y,
1008                                                          lpt->block_box.z + z),
1009                          block_stride);
1010                   staging_map += block_stride;
1011                }
1012             }
1013          }
1014       }
1015 
1016       return lpt->map;
1017    }
1018 
1019    map = llvmpipe_resource_map(resource, level, box->z, tex_usage);
1020 
1021 
1022    /* May want to do different things here depending on read/write nature
1023     * of the map:
1024     */
1025    if (usage & PIPE_MAP_WRITE) {
1026       /* Do something to notify sharing contexts of a texture change.
1027        */
1028       screen->timestamp++;
1029    }
1030 
1031    map +=
1032       box->y / util_format_get_blockheight(format) * pt->stride +
1033       box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
1034 
1035    map += sample * lpr->sample_stride;
1036    return map;
1037 }
1038 
1039 uint32_t
llvmpipe_get_texel_offset(struct pipe_resource * resource,uint32_t level,uint32_t x,uint32_t y,uint32_t z)1040 llvmpipe_get_texel_offset(struct pipe_resource *resource,
1041                           uint32_t level, uint32_t x,
1042                           uint32_t y, uint32_t z)
1043 {
1044    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1045 
1046    uint32_t layer = 0;
1047    if (resource->target != PIPE_TEXTURE_3D) {
1048       layer = z;
1049       z = 0;
1050    }
1051 
1052    uint32_t dimensions = 1;
1053    switch (resource->target) {
1054    case PIPE_TEXTURE_2D:
1055    case PIPE_TEXTURE_CUBE:
1056    case PIPE_TEXTURE_RECT:
1057    case PIPE_TEXTURE_2D_ARRAY:
1058       dimensions = 2;
1059       break;
1060    case PIPE_TEXTURE_3D:
1061       dimensions = 3;
1062       break;
1063    default:
1064       break;
1065    }
1066 
1067    uint32_t sparse_tile_size[3] = {
1068       util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 0),
1069       util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 1),
1070       util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 2),
1071    };
1072 
1073    uint32_t num_tiles_x = DIV_ROUND_UP(u_minify(resource->width0, level),
1074                                        sparse_tile_size[0] * util_format_get_blockwidth(resource->format));
1075    uint32_t num_tiles_y = DIV_ROUND_UP(u_minify(resource->height0, level),
1076                                        sparse_tile_size[1] * util_format_get_blockheight(resource->format));
1077 
1078    uint32_t offset = (
1079       x / sparse_tile_size[0] +
1080       y / sparse_tile_size[1] * num_tiles_x +
1081       z / sparse_tile_size[2] * num_tiles_x * num_tiles_y
1082    ) * 64 * 1024;
1083 
1084    offset += (
1085       x % sparse_tile_size[0] +
1086       (y % sparse_tile_size[1]) * sparse_tile_size[0] +
1087       (z % sparse_tile_size[2]) * sparse_tile_size[0] * sparse_tile_size[1]
1088    ) * util_format_get_blocksize(resource->format);
1089 
1090    return offset + lpr->mip_offsets[level] + lpr->img_stride[level] * layer;
1091 }
1092 
1093 
1094 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)1095 llvmpipe_transfer_map(struct pipe_context *pipe,
1096                       struct pipe_resource *resource,
1097                       unsigned level,
1098                       unsigned usage,
1099                       const struct pipe_box *box,
1100                       struct pipe_transfer **transfer)
1101 {
1102    return llvmpipe_transfer_map_ms(pipe, resource, level, usage, 0,
1103                                    box, transfer);
1104 }
1105 
1106 
1107 static void
llvmpipe_transfer_unmap(struct pipe_context * pipe,struct pipe_transfer * transfer)1108 llvmpipe_transfer_unmap(struct pipe_context *pipe,
1109                         struct pipe_transfer *transfer)
1110 {
1111    struct llvmpipe_transfer *lpt = (struct llvmpipe_transfer *)transfer;
1112    struct pipe_resource *resource = transfer->resource;
1113    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1114 
1115    assert(resource);
1116 
1117    if (llvmpipe_resource_is_texture(resource) && (resource->flags & PIPE_RESOURCE_FLAG_SPARSE) &&
1118        (transfer->usage & PIPE_MAP_WRITE)) {
1119       uint32_t block_stride = util_format_get_blocksize(resource->format);
1120 
1121       const uint8_t *src = lpt->map;
1122       uint8_t *dst = lpr->tex_data;
1123 
1124       for (uint32_t z = 0; z < lpt->block_box.depth; z++) {
1125          for (uint32_t y = 0; y < lpt->block_box.height; y++) {
1126             for (uint32_t x = 0; x < lpt->block_box.width; x++) {
1127                memcpy(dst + llvmpipe_get_texel_offset(resource, transfer->level,
1128                                                       lpt->block_box.x + x,
1129                                                       lpt->block_box.y + y,
1130                                                       lpt->block_box.z + z),
1131                       src, block_stride);
1132                src += block_stride;
1133             }
1134          }
1135       }
1136    }
1137 
1138    llvmpipe_resource_unmap(resource,
1139                            transfer->level,
1140                            transfer->box.z);
1141 
1142    pipe_resource_reference(&resource, NULL);
1143    free(lpt->map);
1144    FREE(transfer);
1145 }
1146 
1147 
1148 unsigned int
llvmpipe_is_resource_referenced(struct pipe_context * pipe,struct pipe_resource * presource,unsigned level)1149 llvmpipe_is_resource_referenced(struct pipe_context *pipe,
1150                                 struct pipe_resource *presource,
1151                                 unsigned level)
1152 {
1153    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
1154    if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
1155                             PIPE_BIND_RENDER_TARGET |
1156                             PIPE_BIND_SAMPLER_VIEW |
1157                             PIPE_BIND_CONSTANT_BUFFER |
1158                             PIPE_BIND_SHADER_BUFFER |
1159                             PIPE_BIND_SHADER_IMAGE)))
1160       return LP_UNREFERENCED;
1161 
1162    return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
1163 }
1164 
1165 
1166 /**
1167  * Returns the largest possible alignment for a format in llvmpipe
1168  */
1169 unsigned
llvmpipe_get_format_alignment(enum pipe_format format)1170 llvmpipe_get_format_alignment(enum pipe_format format)
1171 {
1172    const struct util_format_description *desc = util_format_description(format);
1173    unsigned size = 0;
1174 
1175    for (unsigned i = 0; i < desc->nr_channels; ++i) {
1176       size += desc->channel[i].size;
1177    }
1178 
1179    unsigned bytes = size / 8;
1180 
1181    if (!util_is_power_of_two_or_zero(bytes)) {
1182       bytes /= desc->nr_channels;
1183    }
1184 
1185    if (bytes % 2 || bytes < 1) {
1186       return 1;
1187    } else {
1188       return bytes;
1189    }
1190 }
1191 
1192 
1193 /**
1194  * Create buffer which wraps user-space data.
1195  * XXX unreachable.
1196  */
1197 struct pipe_resource *
llvmpipe_user_buffer_create(struct pipe_screen * screen,void * ptr,unsigned bytes,unsigned bind_flags)1198 llvmpipe_user_buffer_create(struct pipe_screen *screen,
1199                             void *ptr,
1200                             unsigned bytes,
1201                             unsigned bind_flags)
1202 {
1203    struct llvmpipe_resource *buffer;
1204 
1205    buffer = CALLOC_STRUCT(llvmpipe_resource);
1206    if (!buffer)
1207       return NULL;
1208 
1209    buffer->screen = llvmpipe_screen(screen);
1210    pipe_reference_init(&buffer->base.reference, 1);
1211    buffer->base.screen = screen;
1212    buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
1213    buffer->base.bind = bind_flags;
1214    buffer->base.usage = PIPE_USAGE_IMMUTABLE;
1215    buffer->base.flags = 0;
1216    buffer->base.width0 = bytes;
1217    buffer->base.height0 = 1;
1218    buffer->base.depth0 = 1;
1219    buffer->base.array_size = 1;
1220    buffer->user_ptr = true;
1221    buffer->data = ptr;
1222 
1223    return &buffer->base;
1224 }
1225 
1226 
1227 /**
1228  * Compute size (in bytes) need to store a texture image / mipmap level,
1229  * for just one cube face, one array layer or one 3D texture slice
1230  */
1231 static unsigned
tex_image_face_size(const struct llvmpipe_resource * lpr,unsigned level)1232 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
1233 {
1234    return lpr->img_stride[level];
1235 }
1236 
1237 
1238 /**
1239  * Return pointer to a 2D texture image/face/slice.
1240  * No tiled/linear conversion is done.
1241  */
1242 uint8_t *
llvmpipe_get_texture_image_address(struct llvmpipe_resource * lpr,unsigned face_slice,unsigned level)1243 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
1244                                    unsigned face_slice, unsigned level)
1245 {
1246    assert(llvmpipe_resource_is_texture(&lpr->base));
1247 
1248    unsigned offset = lpr->mip_offsets[level];
1249 
1250    if (face_slice > 0)
1251       offset += face_slice * tex_image_face_size(lpr, level);
1252 
1253    return (uint8_t *) lpr->tex_data + offset;
1254 }
1255 
1256 
1257 /**
1258  * Return size of resource in bytes
1259  */
1260 unsigned
llvmpipe_resource_size(const struct pipe_resource * resource)1261 llvmpipe_resource_size(const struct pipe_resource *resource)
1262 {
1263    const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
1264    unsigned size = 0;
1265 
1266    if (llvmpipe_resource_is_texture(resource)) {
1267       /* Note this will always return 0 for displaytarget resources */
1268       size = lpr->total_alloc_size;
1269    } else {
1270       size = resource->width0;
1271    }
1272    return size;
1273 }
1274 
1275 
1276 static void
llvmpipe_memory_barrier(struct pipe_context * pipe,unsigned flags)1277 llvmpipe_memory_barrier(struct pipe_context *pipe,
1278                         unsigned flags)
1279 {
1280    /* this may be an overly large hammer for this nut. */
1281    llvmpipe_finish(pipe, "barrier");
1282 }
1283 
1284 
1285 static struct pipe_memory_allocation *
llvmpipe_allocate_memory(struct pipe_screen * _screen,uint64_t size)1286 llvmpipe_allocate_memory(struct pipe_screen *_screen, uint64_t size)
1287 {
1288    struct llvmpipe_memory_allocation *mem = CALLOC_STRUCT(llvmpipe_memory_allocation);
1289    uint64_t alignment;
1290    if (!os_get_page_size(&alignment))
1291       alignment = 256;
1292 
1293    mem->size = align64(size, alignment);
1294 
1295 #if DETECT_OS_LINUX
1296    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
1297 
1298    mem->cpu_addr = MAP_FAILED;
1299    mem->fd = screen->fd_mem_alloc;
1300 
1301    mtx_lock(&screen->mem_mutex);
1302 
1303    mem->offset = util_vma_heap_alloc(&screen->mem_heap, mem->size, alignment);
1304    if (!mem->offset) {
1305       mtx_unlock(&screen->mem_mutex);
1306       FREE(mem);
1307       return NULL;
1308    }
1309 
1310    if (mem->offset + mem->size > screen->mem_file_size) {
1311       /* expand the anonymous file */
1312       screen->mem_file_size = mem->offset + mem->size;
1313       ftruncate(screen->fd_mem_alloc, screen->mem_file_size);
1314    }
1315 
1316    mtx_unlock(&screen->mem_mutex);
1317 #else
1318    mem->cpu_addr = malloc(mem->size);
1319 #endif
1320 
1321    return (struct pipe_memory_allocation *)mem;
1322 }
1323 
1324 
1325 static void
llvmpipe_free_memory(struct pipe_screen * pscreen,struct pipe_memory_allocation * pmem)1326 llvmpipe_free_memory(struct pipe_screen *pscreen,
1327                      struct pipe_memory_allocation *pmem)
1328 {
1329    struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1330 
1331 #if DETECT_OS_LINUX
1332    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1333 
1334    if (mem->fd) {
1335       mtx_lock(&screen->mem_mutex);
1336       util_vma_heap_free(&screen->mem_heap, mem->offset, mem->size);
1337       mtx_unlock(&screen->mem_mutex);
1338    }
1339 
1340    if (mem->cpu_addr != MAP_FAILED)
1341       munmap(mem->cpu_addr, mem->size);
1342 #else
1343    free(mem->cpu_addr);
1344 #endif
1345 
1346    FREE(mem);
1347 }
1348 
1349 
1350 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1351 static void*
llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen * screen,struct llvmpipe_memory_allocation * alloc,size_t size)1352 llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen *screen,
1353                                 struct llvmpipe_memory_allocation *alloc,
1354                                 size_t size)
1355 {
1356    int mem_fd = -1;
1357    int dmabuf_fd = -1;
1358    if (screen->udmabuf_fd != -1) {
1359       uint64_t alignment;
1360       if (!os_get_page_size(&alignment))
1361          alignment = 256;
1362 
1363       size = align(size, alignment);
1364 
1365       int mem_fd = memfd_create("lp_dma_buf", MFD_ALLOW_SEALING);
1366       if (mem_fd == -1)
1367          goto fail;
1368 
1369       int res = ftruncate(mem_fd, size);
1370       if (res == -1)
1371          goto fail;
1372 
1373       /* udmabuf create requires that the memfd have
1374        * have the F_SEAL_SHRINK seal added and must not
1375        * have the F_SEAL_WRITE seal added */
1376       if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
1377          goto fail;
1378 
1379       struct udmabuf_create create = {
1380          .memfd = mem_fd,
1381          .flags = UDMABUF_FLAGS_CLOEXEC,
1382          .offset = 0,
1383          .size = size
1384       };
1385 
1386       int dmabuf_fd = ioctl(screen->udmabuf_fd, UDMABUF_CREATE, &create);
1387       if (dmabuf_fd < 0)
1388          goto fail;
1389 
1390       struct pipe_memory_allocation *data =
1391          mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0);
1392 
1393       if (!data)
1394          goto fail;
1395 
1396       alloc->mem_fd = mem_fd;
1397       alloc->dmabuf_fd = dmabuf_fd;
1398       alloc->size = size;
1399       return data;
1400    }
1401 
1402 fail:
1403    if (mem_fd != -1)
1404       close(mem_fd);
1405    if (dmabuf_fd != -1)
1406       close(dmabuf_fd);
1407    /* If we don't have access to the udmabuf device
1408     * or something else fails we return NULL */
1409    return NULL;
1410 }
1411 #endif
1412 
1413 #ifdef PIPE_MEMORY_FD
1414 static struct pipe_memory_allocation *
llvmpipe_allocate_memory_fd(struct pipe_screen * pscreen,uint64_t size,int * fd,bool dmabuf)1415 llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen,
1416                             uint64_t size,
1417                             int *fd,
1418                             bool dmabuf)
1419 {
1420    struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
1421    if (!alloc)
1422       goto fail;
1423 
1424    alloc->mem_fd = -1;
1425    alloc->dmabuf_fd = -1;
1426 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1427    if (dmabuf) {
1428       struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1429       alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
1430       alloc->cpu_addr = llvmpipe_resource_alloc_udmabuf(screen, alloc, size);
1431 
1432       if (alloc->cpu_addr)
1433          *fd = os_dupfd_cloexec(alloc->dmabuf_fd);
1434    } else
1435 #endif
1436    {
1437       alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE;
1438       uint64_t alignment;
1439       if (!os_get_page_size(&alignment))
1440          alignment = 256;
1441       alloc->cpu_addr = os_malloc_aligned_fd(size, alignment, fd,
1442             "llvmpipe memory fd", driver_id);
1443    }
1444 
1445    if(alloc && !alloc->cpu_addr) {
1446       free(alloc);
1447       alloc = NULL;
1448    }
1449 
1450 fail:
1451    return (struct pipe_memory_allocation*)alloc;
1452 }
1453 
1454 
1455 static bool
llvmpipe_import_memory_fd(struct pipe_screen * screen,int fd,struct pipe_memory_allocation ** ptr,uint64_t * size,bool dmabuf)1456 llvmpipe_import_memory_fd(struct pipe_screen *screen,
1457                           int fd,
1458                           struct pipe_memory_allocation **ptr,
1459                           uint64_t *size,
1460                           bool dmabuf)
1461 {
1462    struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
1463    alloc->mem_fd = -1;
1464    alloc->dmabuf_fd = -1;
1465 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1466    if (dmabuf) {
1467       off_t mmap_size = lseek(fd, 0, SEEK_END);
1468       lseek(fd, 0, SEEK_SET);
1469       void *cpu_addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1470       if (cpu_addr == MAP_FAILED) {
1471          free(alloc);
1472          *ptr = NULL;
1473          return false;
1474       }
1475 
1476       alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
1477       alloc->cpu_addr = cpu_addr;
1478       alloc->size = mmap_size;
1479       alloc->dmabuf_fd = os_dupfd_cloexec(fd);
1480       *ptr = (struct pipe_memory_allocation*)alloc;
1481       *size = mmap_size;
1482 
1483       return true;
1484    } else
1485 #endif
1486    {
1487       bool ret = os_import_memory_fd(fd, (void**)&alloc->cpu_addr, size, driver_id);
1488 
1489       if (!ret) {
1490          free(alloc);
1491          *ptr = NULL;
1492       } else {
1493          *ptr = (struct pipe_memory_allocation*)alloc;
1494       }
1495 
1496       alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE;
1497       return ret;
1498    }
1499 }
1500 
1501 
1502 static void
llvmpipe_free_memory_fd(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1503 llvmpipe_free_memory_fd(struct pipe_screen *screen,
1504                         struct pipe_memory_allocation *pmem)
1505 {
1506    struct llvmpipe_memory_allocation *alloc = (struct llvmpipe_memory_allocation*)pmem;
1507    if (alloc->type == LLVMPIPE_MEMORY_FD_TYPE_OPAQUE) {
1508       os_free_fd(alloc->cpu_addr);
1509    }
1510 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1511    else {
1512       munmap(alloc->cpu_addr, alloc->size);
1513       if (alloc->dmabuf_fd >= 0)
1514          close(alloc->dmabuf_fd);
1515       if (alloc->mem_fd >= 0)
1516          close(alloc->mem_fd);
1517    }
1518 #endif
1519 
1520    free(alloc);
1521 }
1522 
1523 #endif
1524 
1525 static void *
llvmpipe_map_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1526 llvmpipe_map_memory(struct pipe_screen *screen,
1527                     struct pipe_memory_allocation *pmem)
1528 {
1529    struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1530 
1531 #if DETECT_OS_LINUX
1532    if (mem->cpu_addr != MAP_FAILED)
1533       return mem->cpu_addr;
1534 
1535    /* create a "CPU" mapping */
1536    mem->cpu_addr = mmap(NULL, mem->size, PROT_READ|PROT_WRITE, MAP_SHARED,
1537                         mem->fd, mem->offset);
1538    assert(mem->cpu_addr != MAP_FAILED);
1539 #endif
1540 
1541    return mem->cpu_addr;
1542 }
1543 
1544 static void
llvmpipe_unmap_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1545 llvmpipe_unmap_memory(struct pipe_screen *screen,
1546                       struct pipe_memory_allocation *pmem)
1547 {
1548 }
1549 
1550 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)1551 llvmpipe_resource_bind_backing(struct pipe_screen *pscreen,
1552                                struct pipe_resource *pt,
1553                                struct pipe_memory_allocation *pmem,
1554                                uint64_t fd_offset,
1555                                uint64_t size,
1556                                uint64_t offset)
1557 {
1558    struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1559    struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
1560    struct sw_winsys *winsys = screen->winsys;
1561 
1562    void *addr;
1563    if (!lpr->backable)
1564       return false;
1565 
1566    if ((lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) && offset < lpr->size_required) {
1567 #if DETECT_OS_LINUX
1568       struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1569       if (mem) {
1570          if (llvmpipe_resource_is_texture(&lpr->base)) {
1571             mmap((char *)lpr->tex_data + offset, size, PROT_READ|PROT_WRITE,
1572                  MAP_SHARED|MAP_FIXED, mem->fd, mem->offset + fd_offset);
1573             BITSET_SET(lpr->residency, offset / (64 * 1024));
1574          } else {
1575             mmap((char *)lpr->data + offset, size, PROT_READ|PROT_WRITE,
1576                  MAP_SHARED|MAP_FIXED, mem->fd, mem->offset + fd_offset);
1577          }
1578       } else {
1579          if (llvmpipe_resource_is_texture(&lpr->base)) {
1580             mmap((char *)lpr->tex_data + offset, size, PROT_READ|PROT_WRITE,
1581                  MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1582             BITSET_CLEAR(lpr->residency, offset / (64 * 1024));
1583          } else {
1584             mmap((char *)lpr->data + offset, size, PROT_READ|PROT_WRITE,
1585                  MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1586          }
1587       }
1588 #endif
1589 
1590       return true;
1591    }
1592 
1593    addr = llvmpipe_map_memory(pscreen, pmem);
1594 
1595    if (llvmpipe_resource_is_texture(&lpr->base)) {
1596       if (lpr->size_required > LP_MAX_TEXTURE_SIZE)
1597          return false;
1598 
1599       lpr->tex_data = (char *)addr + offset;
1600 
1601       if (lpr->dmabuf) {
1602          if (lpr->dt)
1603             winsys->displaytarget_destroy(winsys, lpr->dt);
1604          if (pmem) {
1605             /* Round up the surface size to a multiple of the tile size to
1606              * avoid tile clipping.
1607              */
1608             const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
1609             const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
1610 
1611             lpr->dt = winsys->displaytarget_create_mapped(winsys,
1612                                                           lpr->base.bind,
1613                                                           lpr->base.format,
1614                                                           width, height,
1615                                                           lpr->row_stride[0],
1616                                                           lpr->tex_data);
1617          }
1618       }
1619    } else
1620       lpr->data = (char *)addr + offset;
1621    lpr->backing_offset = offset;
1622 
1623    return true;
1624 }
1625 
1626 
1627 
1628 #if MESA_DEBUG
1629 void
llvmpipe_print_resources(void)1630 llvmpipe_print_resources(void)
1631 {
1632    struct llvmpipe_resource *lpr;
1633    unsigned n = 0, total = 0;
1634 
1635    debug_printf("LLVMPIPE: current resources:\n");
1636    simple_mtx_lock(&resource_list_mutex);
1637    LIST_FOR_EACH_ENTRY(lpr, &resource_list.list, list) {
1638       unsigned size = llvmpipe_resource_size(&lpr->base);
1639       debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
1640                    lpr->id, (void *) lpr,
1641                    lpr->base.width0, lpr->base.height0, lpr->base.depth0,
1642                    size, lpr->base.reference.count);
1643       total += size;
1644       n++;
1645    }
1646    simple_mtx_unlock(&resource_list_mutex);
1647    debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
1648 }
1649 #endif
1650 
1651 
1652 static void
llvmpipe_get_resource_info(struct pipe_screen * screen,struct pipe_resource * resource,unsigned * stride,unsigned * offset)1653 llvmpipe_get_resource_info(struct pipe_screen *screen,
1654                            struct pipe_resource *resource,
1655                            unsigned *stride,
1656                            unsigned *offset)
1657 {
1658    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1659 
1660    *stride = lpr->row_stride[0];
1661    *offset = 0;
1662 }
1663 
1664 
1665 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)1666 llvmpipe_resource_get_param(struct pipe_screen *screen,
1667                             struct pipe_context *context,
1668                             struct pipe_resource *resource,
1669                             unsigned plane,
1670                             unsigned layer,
1671                             unsigned level,
1672                             enum pipe_resource_param param,
1673                             unsigned handle_usage,
1674                             uint64_t *value)
1675 {
1676    struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1677    struct winsys_handle whandle;
1678 
1679    switch (param) {
1680    case PIPE_RESOURCE_PARAM_NPLANES:
1681       *value = lpr->dmabuf ? util_format_get_num_planes(lpr->dt_format) : 1;
1682       return true;
1683    case PIPE_RESOURCE_PARAM_STRIDE:
1684       *value = lpr->row_stride[level];
1685       return true;
1686    case PIPE_RESOURCE_PARAM_OFFSET:
1687       *value = lpr->mip_offsets[level] + (lpr->img_stride[level] * layer);
1688       return true;
1689    case PIPE_RESOURCE_PARAM_LAYER_STRIDE:
1690       *value = lpr->img_stride[level];
1691       return true;
1692 #ifndef _WIN32
1693    case PIPE_RESOURCE_PARAM_MODIFIER:
1694       *value = lpr->dmabuf ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
1695       return true;
1696 #endif
1697    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
1698    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
1699    case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
1700       if (!lpr->dt)
1701          return false;
1702 
1703       memset(&whandle, 0, sizeof(whandle));
1704       if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED)
1705          whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1706       else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS)
1707          whandle.type = WINSYS_HANDLE_TYPE_KMS;
1708       else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD)
1709          whandle.type = WINSYS_HANDLE_TYPE_FD;
1710 
1711       if (!llvmpipe_resource_get_handle(screen, context, resource,
1712                                         &whandle, handle_usage)) {
1713          return false;
1714       }
1715       *value = (uint64_t)(uintptr_t)whandle.handle;
1716       return true;
1717    default:
1718       break;
1719    }
1720    assert(0);
1721    *value = 0;
1722    return false;
1723 }
1724 
1725 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1726 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)1727 llvmpipe_query_dmabuf_modifiers(struct pipe_screen *pscreen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count)
1728 {
1729    *count = 1;
1730 
1731    if (max)
1732       *modifiers = DRM_FORMAT_MOD_LINEAR;
1733 }
1734 
1735 static bool
llvmpipe_is_dmabuf_modifier_supported(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format,bool * external_only)1736 llvmpipe_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format, bool *external_only)
1737 {
1738    return modifier == DRM_FORMAT_MOD_LINEAR;
1739 }
1740 
1741 static unsigned
llvmpipe_get_dmabuf_modifier_planes(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format)1742 llvmpipe_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format)
1743 {
1744    return modifier == DRM_FORMAT_MOD_LINEAR;
1745 }
1746 #endif
1747 
1748 void
llvmpipe_init_screen_resource_funcs(struct pipe_screen * screen)1749 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
1750 {
1751 #if MESA_DEBUG
1752    /* init linked list for tracking resources */
1753    {
1754       static bool first_call = true;
1755       if (first_call) {
1756          memset(&resource_list, 0, sizeof(resource_list));
1757          list_inithead(&resource_list.list);
1758          first_call = false;
1759       }
1760    }
1761 #endif
1762 
1763    screen->resource_create = llvmpipe_resource_create;
1764 /*   screen->resource_create_front = llvmpipe_resource_create_front; */
1765    screen->resource_destroy = llvmpipe_resource_destroy;
1766    screen->resource_from_handle = llvmpipe_resource_from_handle;
1767    screen->resource_from_memobj = llvmpipe_resource_from_memobj;
1768    screen->resource_get_handle = llvmpipe_resource_get_handle;
1769    screen->can_create_resource = llvmpipe_can_create_resource;
1770 
1771    screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
1772 
1773    screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle;
1774    screen->memobj_destroy = llvmpipe_memobj_destroy;
1775 
1776    screen->resource_get_info = llvmpipe_get_resource_info;
1777    screen->resource_get_param = llvmpipe_resource_get_param;
1778    screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
1779    screen->allocate_memory = llvmpipe_allocate_memory;
1780    screen->free_memory = llvmpipe_free_memory;
1781 #ifdef PIPE_MEMORY_FD
1782    screen->allocate_memory_fd = llvmpipe_allocate_memory_fd;
1783    screen->import_memory_fd = llvmpipe_import_memory_fd;
1784    screen->free_memory_fd = llvmpipe_free_memory_fd;
1785 #endif
1786 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1787    screen->query_dmabuf_modifiers = llvmpipe_query_dmabuf_modifiers;
1788    screen->is_dmabuf_modifier_supported = llvmpipe_is_dmabuf_modifier_supported;
1789    screen->get_dmabuf_modifier_planes = llvmpipe_get_dmabuf_modifier_planes;
1790    screen->resource_create_with_modifiers = llvmpipe_resource_create_with_modifiers;
1791 #endif
1792    screen->map_memory = llvmpipe_map_memory;
1793    screen->unmap_memory = llvmpipe_unmap_memory;
1794 
1795    screen->resource_bind_backing = llvmpipe_resource_bind_backing;
1796 }
1797 
1798 
1799 void
llvmpipe_init_context_resource_funcs(struct pipe_context * pipe)1800 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
1801 {
1802    pipe->buffer_map = llvmpipe_transfer_map;
1803    pipe->buffer_unmap = llvmpipe_transfer_unmap;
1804    pipe->texture_map = llvmpipe_transfer_map;
1805    pipe->texture_unmap = llvmpipe_transfer_unmap;
1806 
1807    pipe->transfer_flush_region = u_default_transfer_flush_region;
1808    pipe->buffer_subdata = u_default_buffer_subdata;
1809    pipe->texture_subdata = u_default_texture_subdata;
1810 
1811    pipe->memory_barrier = llvmpipe_memory_barrier;
1812 }
1813