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