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