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