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