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