• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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