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 <[email protected]>
30 * Michel Dänzer <[email protected]>
31 */
32
33 #include <stdio.h>
34
35 #include "pipe/p_context.h"
36 #include "pipe/p_defines.h"
37
38 #include "util/detect_os.h"
39 #include "util/simple_mtx.h"
40 #include "util/u_inlines.h"
41 #include "util/u_cpu_detect.h"
42 #include "util/format/u_format.h"
43 #include "util/u_math.h"
44 #include "util/u_memory.h"
45 #include "util/u_transfer.h"
46
47 #if DETECT_OS_POSIX
48 #include "util/os_mman.h"
49 #endif
50
51 #include "lp_context.h"
52 #include "lp_flush.h"
53 #include "lp_screen.h"
54 #include "lp_texture.h"
55 #include "lp_setup.h"
56 #include "lp_state.h"
57 #include "lp_rast.h"
58
59 #include "frontend/sw_winsys.h"
60 #include "git_sha1.h"
61
62 #ifndef _WIN32
63 #include "drm-uapi/drm_fourcc.h"
64 #endif
65
66 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
67 #include <fcntl.h>
68 #include <sys/mman.h>
69 #include <sys/ioctl.h>
70 #include <linux/udmabuf.h>
71 #include <util/os_file.h>
72 #endif
73
74 #if MESA_DEBUG
75 static struct llvmpipe_resource resource_list;
76 static simple_mtx_t resource_list_mutex = SIMPLE_MTX_INITIALIZER;
77 #endif
78 static unsigned id_counter = 0;
79
80
81 #ifdef PIPE_MEMORY_FD
82
83 static const char *driver_id = "llvmpipe" MESA_GIT_SHA1;
84
85 #endif
86
87 /**
88 * Conventional allocation path for non-display textures:
89 * Compute strides and allocate data (unless asked not to).
90 */
91 static bool
llvmpipe_texture_layout(struct llvmpipe_screen * screen,struct llvmpipe_resource * lpr,bool allocate)92 llvmpipe_texture_layout(struct llvmpipe_screen *screen,
93 struct llvmpipe_resource *lpr,
94 bool allocate)
95 {
96 struct pipe_resource *pt = &lpr->base;
97 unsigned width = pt->width0;
98 unsigned height = pt->height0;
99 unsigned depth = pt->depth0;
100 uint64_t total_size = 0;
101 unsigned layers = pt->array_size;
102 unsigned num_samples = util_res_sample_count(pt);
103
104 /* XXX: This alignment here (same for displaytarget) was added for the
105 * purpose of ARB_map_buffer_alignment. I am not convinced it's needed for
106 * non-buffer resources. Otherwise we'd want the max of cacheline size and
107 * 16 (max size of a block for all formats) though this should not be
108 * strictly necessary neither. In any case it can only affect compressed or
109 * 1d textures.
110 */
111 uint64_t mip_align = MAX2(64, util_get_cpu_caps()->cacheline);
112
113 /* KVM on Linux requires memory mapping to be aligned to the page size,
114 * otherwise Linux kernel errors out on trying to map host GPU mapping
115 * to guest (ARB_map_buffer_range). The improper alignment creates trouble
116 * for the virgl driver when host uses llvmpipe, causing Qemu and crosvm to
117 * bail out on the KVM error.
118 */
119 if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE)
120 mip_align = 64 * 1024;
121 else if (lpr->base.flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
122 os_get_page_size(&mip_align);
123
124 assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
125 assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
126
127 uint32_t dimensions = 1;
128 switch (pt->target) {
129 case PIPE_TEXTURE_2D:
130 case PIPE_TEXTURE_CUBE:
131 case PIPE_TEXTURE_RECT:
132 case PIPE_TEXTURE_2D_ARRAY:
133 dimensions = 2;
134 break;
135 case PIPE_TEXTURE_3D:
136 dimensions = 3;
137 break;
138 default:
139 break;
140 }
141
142 uint32_t sparse_tile_size[3] = {
143 util_format_get_tilesize(pt->format, dimensions, pt->nr_samples, 0),
144 util_format_get_tilesize(pt->format, dimensions, pt->nr_samples, 1),
145 util_format_get_tilesize(pt->format, dimensions, pt->nr_samples, 2),
146 };
147
148 for (unsigned level = 0; level <= pt->last_level; level++) {
149 uint64_t mipsize;
150 unsigned align_x, align_y, align_z, nblocksx, nblocksy, block_size, num_slices;
151
152 /* Row stride and image stride */
153
154 /* For non-compressed formats we need 4x4 pixel alignment
155 * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
156 * We also want cache line size in x direction,
157 * otherwise same cache line could end up in multiple threads.
158 * For explicit 1d resources however we reduce this to 4x1 and
159 * handle specially in render output code (as we need to do special
160 * handling there for buffers in any case).
161 */
162 if (util_format_is_compressed(pt->format)) {
163 align_x = align_y = 1;
164 } else {
165 align_x = LP_RASTER_BLOCK_SIZE;
166 if (llvmpipe_resource_is_1d(&lpr->base))
167 align_y = 1;
168 else
169 align_y = LP_RASTER_BLOCK_SIZE;
170 }
171 align_z = 1;
172
173 nblocksx = util_format_get_nblocksx(pt->format,
174 align(width, align_x));
175 nblocksy = util_format_get_nblocksy(pt->format,
176 align(height, align_y));
177 block_size = util_format_get_blocksize(pt->format);
178
179 if (pt->flags & PIPE_RESOURCE_FLAG_SPARSE) {
180 nblocksx = align(nblocksx, sparse_tile_size[0]);
181 nblocksy = align(nblocksy, sparse_tile_size[1]);
182 align_z = MAX2(align_z, sparse_tile_size[2]);
183 }
184
185 if (util_format_is_compressed(pt->format))
186 lpr->row_stride[level] = nblocksx * block_size;
187 else
188 lpr->row_stride[level] = align(nblocksx * block_size,
189 util_get_cpu_caps()->cacheline);
190
191 lpr->img_stride[level] = (uint64_t)lpr->row_stride[level] * nblocksy;
192
193 /* Number of 3D image slices, cube faces or texture array layers */
194 if (lpr->base.target == PIPE_TEXTURE_CUBE) {
195 assert(layers == 6);
196 }
197
198 if (lpr->base.target == PIPE_TEXTURE_3D)
199 num_slices = align(depth, align_z);
200 else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
201 lpr->base.target == PIPE_TEXTURE_2D_ARRAY ||
202 lpr->base.target == PIPE_TEXTURE_CUBE ||
203 lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY)
204 num_slices = layers;
205 else
206 num_slices = 1;
207
208 mipsize = lpr->img_stride[level] * num_slices;
209 lpr->mip_offsets[level] = total_size;
210
211 total_size += align64(mipsize, mip_align);
212
213 /* Compute size of next mipmap level */
214 width = u_minify(width, 1);
215 height = u_minify(height, 1);
216 depth = u_minify(depth, 1);
217 }
218
219 lpr->sample_stride = total_size;
220 total_size *= num_samples;
221
222 lpr->size_required = total_size;
223 if (allocate) {
224 if (total_size > LP_MAX_TEXTURE_SIZE)
225 goto fail;
226
227 lpr->tex_data = align_malloc(total_size, mip_align);
228 if (!lpr->tex_data) {
229 return false;
230 } else {
231 memset(lpr->tex_data, 0, total_size);
232 }
233 }
234 if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) {
235 uint64_t page_align;
236 os_get_page_size(&page_align);
237 lpr->size_required = align64(lpr->size_required, page_align);
238 }
239
240 return true;
241
242 fail:
243 return false;
244 }
245
246
247 /**
248 * Check the size of the texture specified by 'res'.
249 * \return TRUE if OK, FALSE if too large.
250 */
251 static bool
llvmpipe_can_create_resource(struct pipe_screen * screen,const struct pipe_resource * res)252 llvmpipe_can_create_resource(struct pipe_screen *screen,
253 const struct pipe_resource *res)
254 {
255 struct llvmpipe_resource lpr;
256 memset(&lpr, 0, sizeof(lpr));
257 lpr.base = *res;
258 if (!llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false))
259 return false;
260
261 return lpr.size_required <= LP_MAX_TEXTURE_SIZE;
262 }
263
264
265 static bool
llvmpipe_displaytarget_layout(struct llvmpipe_screen * screen,struct llvmpipe_resource * lpr,const void * map_front_private)266 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
267 struct llvmpipe_resource *lpr,
268 const void *map_front_private)
269 {
270 struct sw_winsys *winsys = screen->winsys;
271
272 /* Round up the surface size to a multiple of the tile size to
273 * avoid tile clipping.
274 */
275 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
276 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
277
278 lpr->dt = winsys->displaytarget_create(winsys,
279 lpr->base.bind,
280 lpr->base.format,
281 width, height,
282 64,
283 map_front_private,
284 &lpr->row_stride[0] );
285
286 return lpr->dt != NULL;
287 }
288
289
290 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)291 llvmpipe_resource_create_all(struct pipe_screen *_screen,
292 const struct pipe_resource *templat,
293 const void *map_front_private,
294 bool alloc_backing)
295 {
296 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
297 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
298 if (!lpr)
299 return NULL;
300
301 lpr->base = *templat;
302 lpr->screen = screen;
303 pipe_reference_init(&lpr->base.reference, 1);
304 lpr->base.screen = &screen->base;
305
306 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
307 lpr->dmabuf_alloc = NULL;
308 #endif
309
310 /* assert(lpr->base.bind); */
311
312 if (llvmpipe_resource_is_texture(&lpr->base)) {
313 if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
314 PIPE_BIND_SCANOUT |
315 PIPE_BIND_SHARED)) {
316 /* displayable surface */
317 if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private))
318 goto fail;
319 } else {
320 /* texture map */
321 if (!llvmpipe_texture_layout(screen, lpr, alloc_backing))
322 goto fail;
323
324 if (templat->flags & PIPE_RESOURCE_FLAG_SPARSE) {
325 #if DETECT_OS_LINUX
326 lpr->tex_data = os_mmap(NULL, lpr->size_required, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED,
327 -1, 0);
328 madvise(lpr->tex_data, lpr->size_required, MADV_DONTNEED);
329 #endif
330
331 lpr->residency = calloc(DIV_ROUND_UP(lpr->size_required, 64 * 1024 * sizeof(uint32_t) * 8), sizeof(uint32_t));
332 }
333 }
334 } else {
335 /* other data (vertex buffer, const buffer, etc) */
336 const uint bytes = templat->width0;
337 assert(util_format_get_blocksize(templat->format) == 1);
338 assert(templat->height0 == 1);
339 assert(templat->depth0 == 1);
340 assert(templat->last_level == 0);
341 /*
342 * Reserve some extra storage since if we'd render to a buffer we
343 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
344 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
345 */
346 /*
347 * buffers don't really have stride but it's probably safer
348 * (for code doing same calculations for buffers and textures)
349 * to put something sane in there.
350 */
351 lpr->row_stride[0] = bytes;
352
353 lpr->size_required = bytes;
354 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
355 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
356
357 uint64_t alignment = sizeof(uint64_t) * 16;
358 if (alloc_backing) {
359 if (templat->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
360 os_get_page_size(&alignment);
361
362 lpr->data = align_malloc(lpr->size_required, alignment);
363
364 if (!lpr->data)
365 goto fail;
366 memset(lpr->data, 0, bytes);
367 }
368
369 if (templat->flags & PIPE_RESOURCE_FLAG_SPARSE) {
370 os_get_page_size(&alignment);
371 lpr->size_required = align64(lpr->size_required, alignment);
372 #if DETECT_OS_LINUX
373 lpr->data = os_mmap(NULL, lpr->size_required, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED,
374 -1, 0);
375 madvise(lpr->data, lpr->size_required, MADV_DONTNEED);
376 #endif
377 }
378 }
379
380 lpr->id = id_counter++;
381
382 #if MESA_DEBUG
383 simple_mtx_lock(&resource_list_mutex);
384 list_addtail(&lpr->list, &resource_list.list);
385 simple_mtx_unlock(&resource_list_mutex);
386 #endif
387
388 return &lpr->base;
389
390 fail:
391 FREE(lpr);
392 return NULL;
393 }
394
395
396 static struct pipe_resource *
llvmpipe_resource_create_front(struct pipe_screen * _screen,const struct pipe_resource * templat,const void * map_front_private)397 llvmpipe_resource_create_front(struct pipe_screen *_screen,
398 const struct pipe_resource *templat,
399 const void *map_front_private)
400 {
401 return llvmpipe_resource_create_all(_screen, templat,
402 map_front_private, true);
403 }
404
405
406 static struct pipe_resource *
llvmpipe_resource_create(struct pipe_screen * _screen,const struct pipe_resource * templat)407 llvmpipe_resource_create(struct pipe_screen *_screen,
408 const struct pipe_resource *templat)
409 {
410 return llvmpipe_resource_create_front(_screen, templat, NULL);
411 }
412
413 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
414 static struct pipe_resource *
llvmpipe_resource_create_with_modifiers(struct pipe_screen * _screen,const struct pipe_resource * templat,const uint64_t * modifiers,int count)415 llvmpipe_resource_create_with_modifiers(struct pipe_screen *_screen,
416 const struct pipe_resource *templat,
417 const uint64_t *modifiers, int count)
418 {
419 bool has_linear = false;
420 for (unsigned i = 0; i < count; i++)
421 if (modifiers[i] == DRM_FORMAT_MOD_LINEAR)
422 has_linear = true;
423 if (!has_linear)
424 return NULL;
425 return llvmpipe_resource_create_front(_screen, templat, NULL);
426 }
427 #endif
428
429 static struct pipe_resource *
llvmpipe_resource_create_unbacked(struct pipe_screen * _screen,const struct pipe_resource * templat,uint64_t * size_required)430 llvmpipe_resource_create_unbacked(struct pipe_screen *_screen,
431 const struct pipe_resource *templat,
432 uint64_t *size_required)
433 {
434 struct pipe_resource *pt =
435 llvmpipe_resource_create_all(_screen, templat, NULL, false);
436 if (!pt)
437 return pt;
438 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
439 lpr->backable = true;
440 *size_required = lpr->size_required;
441 return pt;
442 }
443
444
445 static struct pipe_memory_object *
llvmpipe_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * handle,bool dedicated)446 llvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen,
447 struct winsys_handle *handle,
448 bool dedicated)
449 {
450 #ifdef PIPE_MEMORY_FD
451 struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object);
452
453 if (handle->type == WINSYS_HANDLE_TYPE_FD &&
454 pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size, false)) {
455 return &memobj->b;
456 }
457 free(memobj);
458 #endif
459 return NULL;
460 }
461
462
463 static void
llvmpipe_memobj_destroy(struct pipe_screen * pscreen,struct pipe_memory_object * memobj)464 llvmpipe_memobj_destroy(struct pipe_screen *pscreen,
465 struct pipe_memory_object *memobj)
466 {
467 if (!memobj)
468 return;
469 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
470 #ifdef PIPE_MEMORY_FD
471 pscreen->free_memory_fd(pscreen, lpmo->data);
472 #endif
473 free(lpmo);
474 }
475
476
477 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)478 llvmpipe_resource_from_memobj(struct pipe_screen *pscreen,
479 const struct pipe_resource *templat,
480 struct pipe_memory_object *memobj,
481 uint64_t offset)
482 {
483 if (!memobj)
484 return NULL;
485 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
486 struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
487 struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
488 lpr->base = *templat;
489
490 lpr->screen = screen;
491 pipe_reference_init(&lpr->base.reference, 1);
492 lpr->base.screen = &screen->base;
493
494 if (llvmpipe_resource_is_texture(&lpr->base)) {
495 /* texture map */
496 if (!llvmpipe_texture_layout(screen, lpr, false))
497 goto fail;
498 if (lpmo->size < lpr->size_required)
499 goto fail;
500 lpr->tex_data = lpmo->data;
501 } else {
502 /* other data (vertex buffer, const buffer, etc) */
503 const uint bytes = templat->width0;
504 assert(util_format_get_blocksize(templat->format) == 1);
505 assert(templat->height0 == 1);
506 assert(templat->depth0 == 1);
507 assert(templat->last_level == 0);
508 /*
509 * Reserve some extra storage since if we'd render to a buffer we
510 * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
511 * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
512 */
513 /*
514 * buffers don't really have stride but it's probably safer
515 * (for code doing same calculations for buffers and textures)
516 * to put something reasonable in there.
517 */
518 lpr->row_stride[0] = bytes;
519
520 lpr->size_required = bytes;
521 if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
522 lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
523
524 if (lpmo->size < lpr->size_required)
525 goto fail;
526 lpr->data = lpmo->data;
527 }
528 lpr->id = id_counter++;
529 lpr->imported_memory = true;
530
531 #if MESA_DEBUG
532 simple_mtx_lock(&resource_list_mutex);
533 list_addtail(&lpr->list, &resource_list.list);
534 simple_mtx_unlock(&resource_list_mutex);
535 #endif
536
537 return &lpr->base;
538
539 fail:
540 free(lpr);
541 return NULL;
542 }
543
544 static void
llvmpipe_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * pt)545 llvmpipe_resource_destroy(struct pipe_screen *pscreen,
546 struct pipe_resource *pt)
547 {
548 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
549 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
550
551 if (!lpr->backable && !lpr->user_ptr) {
552 if (lpr->dt) {
553 /* display target */
554 struct sw_winsys *winsys = screen->winsys;
555 winsys->displaytarget_destroy(winsys, lpr->dt);
556 } else if (llvmpipe_resource_is_texture(pt)) {
557 /* free linear image data */
558 if (lpr->tex_data) {
559 if (!lpr->imported_memory)
560 align_free(lpr->tex_data);
561 lpr->tex_data = NULL;
562 }
563 } else if (lpr->data) {
564 if (!lpr->imported_memory)
565 align_free(lpr->data);
566 }
567 }
568
569 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
570 if (lpr->dmabuf_alloc)
571 pscreen->free_memory_fd(pscreen, (struct pipe_memory_allocation*)lpr->dmabuf_alloc);
572 #endif
573
574 if (lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) {
575 #if DETECT_OS_LINUX
576 if (llvmpipe_resource_is_texture(pt))
577 munmap(lpr->tex_data, lpr->size_required);
578 else
579 munmap(lpr->data, lpr->size_required);
580 #endif
581 }
582
583 free(lpr->residency);
584
585 #if MESA_DEBUG
586 simple_mtx_lock(&resource_list_mutex);
587 if (!list_is_empty(&lpr->list))
588 list_del(&lpr->list);
589 simple_mtx_unlock(&resource_list_mutex);
590 #endif
591
592 FREE(lpr);
593 }
594
595
596 /**
597 * Map a resource for read/write.
598 */
599 void *
llvmpipe_resource_map(struct pipe_resource * resource,unsigned level,unsigned layer,enum lp_texture_usage tex_usage)600 llvmpipe_resource_map(struct pipe_resource *resource,
601 unsigned level,
602 unsigned layer,
603 enum lp_texture_usage tex_usage)
604 {
605 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
606 uint8_t *map;
607
608 assert(level < LP_MAX_TEXTURE_LEVELS);
609 assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
610
611 assert(tex_usage == LP_TEX_USAGE_READ ||
612 tex_usage == LP_TEX_USAGE_READ_WRITE ||
613 tex_usage == LP_TEX_USAGE_WRITE_ALL);
614
615 if (lpr->dt) {
616 if (lpr->dmabuf)
617 return lpr->tex_data;
618 /* display target */
619 struct llvmpipe_screen *screen = lpr->screen;
620 struct sw_winsys *winsys = screen->winsys;
621 unsigned dt_usage;
622
623 if (tex_usage == LP_TEX_USAGE_READ) {
624 dt_usage = PIPE_MAP_READ;
625 } else {
626 dt_usage = PIPE_MAP_READ_WRITE;
627 }
628
629 assert(level == 0);
630 assert(layer == 0);
631
632 /* FIXME: keep map count? */
633 map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
634
635 /* install this linear image in texture data structure */
636 lpr->tex_data = map;
637
638 return map;
639 } else if (llvmpipe_resource_is_texture(resource)) {
640
641 map = llvmpipe_get_texture_image_address(lpr, layer, level);
642 return map;
643 } else {
644 return lpr->data;
645 }
646 }
647
648
649 /**
650 * Unmap a resource.
651 */
652 void
llvmpipe_resource_unmap(struct pipe_resource * resource,unsigned level,unsigned layer)653 llvmpipe_resource_unmap(struct pipe_resource *resource,
654 unsigned level,
655 unsigned layer)
656 {
657 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
658
659 if (lpr->dt) {
660 if (lpr->dmabuf)
661 return;
662 /* display target */
663 struct llvmpipe_screen *lp_screen = lpr->screen;
664 struct sw_winsys *winsys = lp_screen->winsys;
665
666 assert(level == 0);
667 assert(layer == 0);
668
669 winsys->displaytarget_unmap(winsys, lpr->dt);
670 }
671 }
672
673
674 void *
llvmpipe_resource_data(struct pipe_resource * resource)675 llvmpipe_resource_data(struct pipe_resource *resource)
676 {
677 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
678
679 assert(!llvmpipe_resource_is_texture(resource));
680
681 return lpr->data;
682 }
683
684
685 static struct pipe_resource *
llvmpipe_resource_from_handle(struct pipe_screen * _screen,const struct pipe_resource * template,struct winsys_handle * whandle,unsigned usage)686 llvmpipe_resource_from_handle(struct pipe_screen *_screen,
687 const struct pipe_resource *template,
688 struct winsys_handle *whandle,
689 unsigned usage)
690 {
691 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
692 struct sw_winsys *winsys = screen->winsys;
693 struct llvmpipe_resource *lpr;
694
695 /* no multisampled */
696 assert(template->nr_samples < 2);
697 /* no miplevels */
698 assert(template->last_level == 0);
699
700 /* Multiplanar surfaces are not supported */
701 if (whandle->plane > 0)
702 return NULL;
703
704 lpr = CALLOC_STRUCT(llvmpipe_resource);
705 if (!lpr) {
706 goto no_lpr;
707 }
708
709 lpr->base = *template;
710 lpr->screen = screen;
711 lpr->dt_format = whandle->format;
712 pipe_reference_init(&lpr->base.reference, 1);
713 lpr->base.screen = _screen;
714
715 /*
716 * Looks like unaligned displaytargets work just fine,
717 * at least sampler/render ones.
718 */
719 #if 0
720 assert(lpr->base.width0 == width);
721 assert(lpr->base.height0 == height);
722 #endif
723
724 unsigned nblocksy = util_format_get_nblocksy(template->format, align(template->height0, LP_RASTER_BLOCK_SIZE));
725 if (whandle->type == WINSYS_HANDLE_TYPE_UNBACKED && whandle->image_stride)
726 lpr->img_stride[0] = whandle->image_stride;
727 else
728 lpr->img_stride[0] = whandle->stride * nblocksy;
729 lpr->sample_stride = lpr->img_stride[0];
730 lpr->size_required = lpr->sample_stride;
731
732 if (whandle->type != WINSYS_HANDLE_TYPE_UNBACKED) {
733 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
734 struct llvmpipe_memory_allocation *alloc;
735 uint64_t size;
736 /* Not all winsys implement displaytarget_create_mapped so we need to check
737 * that is available (not null).
738 */
739 if (winsys->displaytarget_create_mapped &&
740 _screen->import_memory_fd(_screen, whandle->handle,
741 (struct pipe_memory_allocation**)&alloc,
742 &size, true)) {
743 void *data = alloc->cpu_addr;
744 lpr->dt = winsys->displaytarget_create_mapped(winsys, template->bind,
745 template->format, template->width0, template->height0,
746 whandle->stride, data);
747 if (!lpr->dt)
748 goto no_dt;
749 lpr->dmabuf_alloc = alloc;
750 lpr->dmabuf = true;
751 lpr->tex_data = data;
752 lpr->row_stride[0] = whandle->stride;
753 whandle->size = size;
754 } else
755 #endif
756 {
757 lpr->dt = winsys->displaytarget_from_handle(winsys,
758 template,
759 whandle,
760 &lpr->row_stride[0]);
761 if (!lpr->dt)
762 goto no_dt;
763 }
764
765 assert(llvmpipe_resource_is_texture(&lpr->base));
766 } else {
767 whandle->size = lpr->size_required;
768 lpr->row_stride[0] = whandle->stride;
769 lpr->backable = true;
770 }
771
772
773 lpr->id = id_counter++;
774
775 #if MESA_DEBUG
776 simple_mtx_lock(&resource_list_mutex);
777 list_addtail(&lpr->list, &resource_list.list);
778 simple_mtx_unlock(&resource_list_mutex);
779 #endif
780
781 return &lpr->base;
782
783 no_dt:
784 FREE(lpr);
785 no_lpr:
786 return NULL;
787 }
788
789
790 static bool
llvmpipe_resource_get_handle(struct pipe_screen * _screen,struct pipe_context * ctx,struct pipe_resource * pt,struct winsys_handle * whandle,unsigned usage)791 llvmpipe_resource_get_handle(struct pipe_screen *_screen,
792 struct pipe_context *ctx,
793 struct pipe_resource *pt,
794 struct winsys_handle *whandle,
795 unsigned usage)
796 {
797 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
798 struct sw_winsys *winsys = screen->winsys;
799 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
800
801 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
802 if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_FD) {
803 if (!lpr->dmabuf_alloc) {
804 lpr->dmabuf_alloc = (struct llvmpipe_memory_allocation*)_screen->allocate_memory_fd(_screen, lpr->size_required, (int*)&whandle->handle, true);
805 if (!lpr->dmabuf_alloc)
806 return false;
807
808 /* replace existing backing with fd backing */
809 bool is_tex = llvmpipe_resource_is_texture(pt);
810 if (is_tex) {
811 if (lpr->tex_data)
812 memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->tex_data, lpr->size_required);
813 } else {
814 if (lpr->data)
815 memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->data, lpr->size_required);
816 }
817 if (!lpr->imported_memory)
818 align_free(is_tex ? lpr->tex_data : lpr->data);
819 if (is_tex)
820 lpr->tex_data = lpr->dmabuf_alloc->cpu_addr;
821 else
822 lpr->data = lpr->dmabuf_alloc->cpu_addr;
823 /* reuse lavapipe codepath to handle destruction */
824 lpr->backable = true;
825 } else {
826 whandle->handle = os_dupfd_cloexec(lpr->dmabuf_alloc->dmabuf_fd);
827 }
828 whandle->modifier = DRM_FORMAT_MOD_LINEAR;
829 whandle->stride = lpr->row_stride[0];
830 return true;
831 } else if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_KMS) {
832 /* dri winsys code will use this to query the drm modifiers
833 * We can just return an null handle and return DRM_FORMAT_MOD_LINEAR */
834 whandle->handle = 0;
835 whandle->modifier = DRM_FORMAT_MOD_LINEAR;
836 return true;
837 }
838 #endif
839 assert(lpr->dt);
840 if (!lpr->dt)
841 return false;
842
843 return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
844 }
845
846
847 static struct pipe_resource *
llvmpipe_resource_from_user_memory(struct pipe_screen * _screen,const struct pipe_resource * resource,void * user_memory)848 llvmpipe_resource_from_user_memory(struct pipe_screen *_screen,
849 const struct pipe_resource *resource,
850 void *user_memory)
851 {
852 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
853 struct llvmpipe_resource *lpr;
854
855 lpr = CALLOC_STRUCT(llvmpipe_resource);
856 if (!lpr) {
857 return NULL;
858 }
859
860 lpr->base = *resource;
861 lpr->screen = screen;
862 pipe_reference_init(&lpr->base.reference, 1);
863 lpr->base.screen = _screen;
864
865 if (llvmpipe_resource_is_texture(&lpr->base)) {
866 if (!llvmpipe_texture_layout(screen, lpr, false))
867 goto fail;
868
869 lpr->tex_data = user_memory;
870 } else
871 lpr->data = user_memory;
872 lpr->user_ptr = true;
873 #if MESA_DEBUG
874 simple_mtx_lock(&resource_list_mutex);
875 list_addtail(&lpr->list, &resource_list.list);
876 simple_mtx_unlock(&resource_list_mutex);
877 #endif
878 return &lpr->base;
879 fail:
880 FREE(lpr);
881 return NULL;
882 }
883
884
885 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)886 llvmpipe_transfer_map_ms(struct pipe_context *pipe,
887 struct pipe_resource *resource,
888 unsigned level,
889 unsigned usage,
890 unsigned sample,
891 const struct pipe_box *box,
892 struct pipe_transfer **transfer)
893 {
894 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
895 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
896 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
897 struct llvmpipe_transfer *lpt;
898 struct pipe_transfer *pt;
899 uint8_t *map;
900 enum pipe_format format;
901
902 assert(resource);
903 assert(level <= resource->last_level);
904
905 /*
906 * Transfers, like other pipe operations, must happen in order, so flush
907 * the context if necessary.
908 */
909 if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
910 bool read_only = !(usage & PIPE_MAP_WRITE);
911 bool do_not_block = !!(usage & PIPE_MAP_DONTBLOCK);
912 if (!llvmpipe_flush_resource(pipe, resource,
913 level,
914 read_only,
915 true, /* cpu_access */
916 do_not_block,
917 __func__)) {
918 /*
919 * It would have blocked, but gallium frontend requested no to.
920 */
921 assert(do_not_block);
922 return NULL;
923 }
924 }
925
926 /* Check if we're mapping a current constant buffer */
927 if ((usage & PIPE_MAP_WRITE) &&
928 (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
929 unsigned i;
930 for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
931 if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
932 /* constants may have changed */
933 llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
934 break;
935 }
936 }
937 }
938
939 lpt = CALLOC_STRUCT(llvmpipe_transfer);
940 if (!lpt)
941 return NULL;
942 pt = &lpt->base;
943 pipe_resource_reference(&pt->resource, resource);
944 pt->box = *box;
945 pt->level = level;
946 pt->stride = lpr->row_stride[level];
947 pt->layer_stride = lpr->img_stride[level];
948 pt->usage = usage;
949 *transfer = pt;
950
951 assert(level < LP_MAX_TEXTURE_LEVELS);
952
953 /*
954 printf("tex_transfer_map(%d, %d %d x %d of %d x %d, usage %d)\n",
955 transfer->x, transfer->y, transfer->width, transfer->height,
956 transfer->texture->width0,
957 transfer->texture->height0,
958 transfer->usage);
959 */
960
961 enum lp_texture_usage tex_usage;
962 const char *mode;
963 if (usage == PIPE_MAP_READ) {
964 tex_usage = LP_TEX_USAGE_READ;
965 mode = "read";
966 } else {
967 tex_usage = LP_TEX_USAGE_READ_WRITE;
968 mode = "read/write";
969 }
970
971 if (0) {
972 printf("transfer map tex %u mode %s\n", lpr->id, mode);
973 }
974
975 format = lpr->base.format;
976
977 if (llvmpipe_resource_is_texture(resource) && (resource->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
978 map = llvmpipe_resource_map(resource, 0, 0, tex_usage);
979
980 lpt->block_box = (struct pipe_box) {
981 .x = box->x / util_format_get_blockwidth(format),
982 .width = DIV_ROUND_UP(box->x + box->width, util_format_get_blockwidth(format)),
983 .y = box->y / util_format_get_blockheight(format),
984 .height = DIV_ROUND_UP(box->y + box->height, util_format_get_blockheight(format)),
985 .z = box->z / util_format_get_blockdepth(format),
986 .depth = DIV_ROUND_UP(box->z + box->depth, util_format_get_blockdepth(format)),
987 };
988
989 lpt->block_box.width -= lpt->block_box.x;
990 lpt->block_box.height -= lpt->block_box.y;
991 lpt->block_box.depth -= lpt->block_box.z;
992
993 uint32_t block_stride = util_format_get_blocksize(format);
994 pt->stride = lpt->block_box.width * block_stride;
995 pt->layer_stride = pt->stride * lpt->block_box.height;
996
997 uint8_t *staging_map = malloc(pt->layer_stride * lpt->block_box.depth);
998 lpt->map = staging_map;
999
1000 if (usage & PIPE_MAP_READ) {
1001 for (uint32_t z = 0; z < lpt->block_box.depth; z++) {
1002 for (uint32_t y = 0; y < lpt->block_box.height; y++) {
1003 for (uint32_t x = 0; x < lpt->block_box.width; x++) {
1004 memcpy(staging_map,
1005 map + llvmpipe_get_texel_offset(resource, level,
1006 lpt->block_box.x + x,
1007 lpt->block_box.y + y,
1008 lpt->block_box.z + z),
1009 block_stride);
1010 staging_map += block_stride;
1011 }
1012 }
1013 }
1014 }
1015
1016 return lpt->map;
1017 }
1018
1019 map = llvmpipe_resource_map(resource, level, box->z, tex_usage);
1020
1021
1022 /* May want to do different things here depending on read/write nature
1023 * of the map:
1024 */
1025 if (usage & PIPE_MAP_WRITE) {
1026 /* Do something to notify sharing contexts of a texture change.
1027 */
1028 screen->timestamp++;
1029 }
1030
1031 map +=
1032 box->y / util_format_get_blockheight(format) * pt->stride +
1033 box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
1034
1035 map += sample * lpr->sample_stride;
1036 return map;
1037 }
1038
1039 uint32_t
llvmpipe_get_texel_offset(struct pipe_resource * resource,uint32_t level,uint32_t x,uint32_t y,uint32_t z)1040 llvmpipe_get_texel_offset(struct pipe_resource *resource,
1041 uint32_t level, uint32_t x,
1042 uint32_t y, uint32_t z)
1043 {
1044 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1045
1046 uint32_t layer = 0;
1047 if (resource->target != PIPE_TEXTURE_3D) {
1048 layer = z;
1049 z = 0;
1050 }
1051
1052 uint32_t dimensions = 1;
1053 switch (resource->target) {
1054 case PIPE_TEXTURE_2D:
1055 case PIPE_TEXTURE_CUBE:
1056 case PIPE_TEXTURE_RECT:
1057 case PIPE_TEXTURE_2D_ARRAY:
1058 dimensions = 2;
1059 break;
1060 case PIPE_TEXTURE_3D:
1061 dimensions = 3;
1062 break;
1063 default:
1064 break;
1065 }
1066
1067 uint32_t sparse_tile_size[3] = {
1068 util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 0),
1069 util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 1),
1070 util_format_get_tilesize(resource->format, dimensions, resource->nr_samples, 2),
1071 };
1072
1073 uint32_t num_tiles_x = DIV_ROUND_UP(u_minify(resource->width0, level),
1074 sparse_tile_size[0] * util_format_get_blockwidth(resource->format));
1075 uint32_t num_tiles_y = DIV_ROUND_UP(u_minify(resource->height0, level),
1076 sparse_tile_size[1] * util_format_get_blockheight(resource->format));
1077
1078 uint32_t offset = (
1079 x / sparse_tile_size[0] +
1080 y / sparse_tile_size[1] * num_tiles_x +
1081 z / sparse_tile_size[2] * num_tiles_x * num_tiles_y
1082 ) * 64 * 1024;
1083
1084 offset += (
1085 x % sparse_tile_size[0] +
1086 (y % sparse_tile_size[1]) * sparse_tile_size[0] +
1087 (z % sparse_tile_size[2]) * sparse_tile_size[0] * sparse_tile_size[1]
1088 ) * util_format_get_blocksize(resource->format);
1089
1090 return offset + lpr->mip_offsets[level] + lpr->img_stride[level] * layer;
1091 }
1092
1093
1094 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)1095 llvmpipe_transfer_map(struct pipe_context *pipe,
1096 struct pipe_resource *resource,
1097 unsigned level,
1098 unsigned usage,
1099 const struct pipe_box *box,
1100 struct pipe_transfer **transfer)
1101 {
1102 return llvmpipe_transfer_map_ms(pipe, resource, level, usage, 0,
1103 box, transfer);
1104 }
1105
1106
1107 static void
llvmpipe_transfer_unmap(struct pipe_context * pipe,struct pipe_transfer * transfer)1108 llvmpipe_transfer_unmap(struct pipe_context *pipe,
1109 struct pipe_transfer *transfer)
1110 {
1111 struct llvmpipe_transfer *lpt = (struct llvmpipe_transfer *)transfer;
1112 struct pipe_resource *resource = transfer->resource;
1113 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1114
1115 assert(resource);
1116
1117 if (llvmpipe_resource_is_texture(resource) && (resource->flags & PIPE_RESOURCE_FLAG_SPARSE) &&
1118 (transfer->usage & PIPE_MAP_WRITE)) {
1119 uint32_t block_stride = util_format_get_blocksize(resource->format);
1120
1121 const uint8_t *src = lpt->map;
1122 uint8_t *dst = lpr->tex_data;
1123
1124 for (uint32_t z = 0; z < lpt->block_box.depth; z++) {
1125 for (uint32_t y = 0; y < lpt->block_box.height; y++) {
1126 for (uint32_t x = 0; x < lpt->block_box.width; x++) {
1127 memcpy(dst + llvmpipe_get_texel_offset(resource, transfer->level,
1128 lpt->block_box.x + x,
1129 lpt->block_box.y + y,
1130 lpt->block_box.z + z),
1131 src, block_stride);
1132 src += block_stride;
1133 }
1134 }
1135 }
1136 }
1137
1138 llvmpipe_resource_unmap(resource,
1139 transfer->level,
1140 transfer->box.z);
1141
1142 pipe_resource_reference(&resource, NULL);
1143 free(lpt->map);
1144 FREE(transfer);
1145 }
1146
1147
1148 unsigned int
llvmpipe_is_resource_referenced(struct pipe_context * pipe,struct pipe_resource * presource,unsigned level)1149 llvmpipe_is_resource_referenced(struct pipe_context *pipe,
1150 struct pipe_resource *presource,
1151 unsigned level)
1152 {
1153 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
1154 if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
1155 PIPE_BIND_RENDER_TARGET |
1156 PIPE_BIND_SAMPLER_VIEW |
1157 PIPE_BIND_CONSTANT_BUFFER |
1158 PIPE_BIND_SHADER_BUFFER |
1159 PIPE_BIND_SHADER_IMAGE)))
1160 return LP_UNREFERENCED;
1161
1162 return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
1163 }
1164
1165
1166 /**
1167 * Returns the largest possible alignment for a format in llvmpipe
1168 */
1169 unsigned
llvmpipe_get_format_alignment(enum pipe_format format)1170 llvmpipe_get_format_alignment(enum pipe_format format)
1171 {
1172 const struct util_format_description *desc = util_format_description(format);
1173 unsigned size = 0;
1174
1175 for (unsigned i = 0; i < desc->nr_channels; ++i) {
1176 size += desc->channel[i].size;
1177 }
1178
1179 unsigned bytes = size / 8;
1180
1181 if (!util_is_power_of_two_or_zero(bytes)) {
1182 bytes /= desc->nr_channels;
1183 }
1184
1185 if (bytes % 2 || bytes < 1) {
1186 return 1;
1187 } else {
1188 return bytes;
1189 }
1190 }
1191
1192
1193 /**
1194 * Create buffer which wraps user-space data.
1195 * XXX unreachable.
1196 */
1197 struct pipe_resource *
llvmpipe_user_buffer_create(struct pipe_screen * screen,void * ptr,unsigned bytes,unsigned bind_flags)1198 llvmpipe_user_buffer_create(struct pipe_screen *screen,
1199 void *ptr,
1200 unsigned bytes,
1201 unsigned bind_flags)
1202 {
1203 struct llvmpipe_resource *buffer;
1204
1205 buffer = CALLOC_STRUCT(llvmpipe_resource);
1206 if (!buffer)
1207 return NULL;
1208
1209 buffer->screen = llvmpipe_screen(screen);
1210 pipe_reference_init(&buffer->base.reference, 1);
1211 buffer->base.screen = screen;
1212 buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
1213 buffer->base.bind = bind_flags;
1214 buffer->base.usage = PIPE_USAGE_IMMUTABLE;
1215 buffer->base.flags = 0;
1216 buffer->base.width0 = bytes;
1217 buffer->base.height0 = 1;
1218 buffer->base.depth0 = 1;
1219 buffer->base.array_size = 1;
1220 buffer->user_ptr = true;
1221 buffer->data = ptr;
1222
1223 return &buffer->base;
1224 }
1225
1226
1227 /**
1228 * Compute size (in bytes) need to store a texture image / mipmap level,
1229 * for just one cube face, one array layer or one 3D texture slice
1230 */
1231 static unsigned
tex_image_face_size(const struct llvmpipe_resource * lpr,unsigned level)1232 tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
1233 {
1234 return lpr->img_stride[level];
1235 }
1236
1237
1238 /**
1239 * Return pointer to a 2D texture image/face/slice.
1240 * No tiled/linear conversion is done.
1241 */
1242 uint8_t *
llvmpipe_get_texture_image_address(struct llvmpipe_resource * lpr,unsigned face_slice,unsigned level)1243 llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
1244 unsigned face_slice, unsigned level)
1245 {
1246 assert(llvmpipe_resource_is_texture(&lpr->base));
1247
1248 unsigned offset = lpr->mip_offsets[level];
1249
1250 if (face_slice > 0)
1251 offset += face_slice * tex_image_face_size(lpr, level);
1252
1253 return (uint8_t *) lpr->tex_data + offset;
1254 }
1255
1256
1257 /**
1258 * Return size of resource in bytes
1259 */
1260 unsigned
llvmpipe_resource_size(const struct pipe_resource * resource)1261 llvmpipe_resource_size(const struct pipe_resource *resource)
1262 {
1263 const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
1264 unsigned size = 0;
1265
1266 if (llvmpipe_resource_is_texture(resource)) {
1267 /* Note this will always return 0 for displaytarget resources */
1268 size = lpr->total_alloc_size;
1269 } else {
1270 size = resource->width0;
1271 }
1272 return size;
1273 }
1274
1275
1276 static void
llvmpipe_memory_barrier(struct pipe_context * pipe,unsigned flags)1277 llvmpipe_memory_barrier(struct pipe_context *pipe,
1278 unsigned flags)
1279 {
1280 /* this may be an overly large hammer for this nut. */
1281 llvmpipe_finish(pipe, "barrier");
1282 }
1283
1284
1285 static struct pipe_memory_allocation *
llvmpipe_allocate_memory(struct pipe_screen * _screen,uint64_t size)1286 llvmpipe_allocate_memory(struct pipe_screen *_screen, uint64_t size)
1287 {
1288 struct llvmpipe_memory_allocation *mem = CALLOC_STRUCT(llvmpipe_memory_allocation);
1289 uint64_t alignment;
1290 if (!os_get_page_size(&alignment))
1291 alignment = 256;
1292
1293 mem->size = align64(size, alignment);
1294
1295 #if DETECT_OS_LINUX
1296 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
1297
1298 mem->cpu_addr = MAP_FAILED;
1299 mem->fd = screen->fd_mem_alloc;
1300
1301 mtx_lock(&screen->mem_mutex);
1302
1303 mem->offset = util_vma_heap_alloc(&screen->mem_heap, mem->size, alignment);
1304 if (!mem->offset) {
1305 mtx_unlock(&screen->mem_mutex);
1306 FREE(mem);
1307 return NULL;
1308 }
1309
1310 if (mem->offset + mem->size > screen->mem_file_size) {
1311 /* expand the anonymous file */
1312 screen->mem_file_size = mem->offset + mem->size;
1313 ftruncate(screen->fd_mem_alloc, screen->mem_file_size);
1314 }
1315
1316 mtx_unlock(&screen->mem_mutex);
1317 #else
1318 mem->cpu_addr = malloc(mem->size);
1319 #endif
1320
1321 return (struct pipe_memory_allocation *)mem;
1322 }
1323
1324
1325 static void
llvmpipe_free_memory(struct pipe_screen * pscreen,struct pipe_memory_allocation * pmem)1326 llvmpipe_free_memory(struct pipe_screen *pscreen,
1327 struct pipe_memory_allocation *pmem)
1328 {
1329 struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1330
1331 #if DETECT_OS_LINUX
1332 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1333
1334 if (mem->fd) {
1335 mtx_lock(&screen->mem_mutex);
1336 util_vma_heap_free(&screen->mem_heap, mem->offset, mem->size);
1337 mtx_unlock(&screen->mem_mutex);
1338 }
1339
1340 if (mem->cpu_addr != MAP_FAILED)
1341 munmap(mem->cpu_addr, mem->size);
1342 #else
1343 free(mem->cpu_addr);
1344 #endif
1345
1346 FREE(mem);
1347 }
1348
1349
1350 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1351 static void*
llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen * screen,struct llvmpipe_memory_allocation * alloc,size_t size)1352 llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen *screen,
1353 struct llvmpipe_memory_allocation *alloc,
1354 size_t size)
1355 {
1356 int mem_fd = -1;
1357 int dmabuf_fd = -1;
1358 if (screen->udmabuf_fd != -1) {
1359 uint64_t alignment;
1360 if (!os_get_page_size(&alignment))
1361 alignment = 256;
1362
1363 size = align(size, alignment);
1364
1365 int mem_fd = memfd_create("lp_dma_buf", MFD_ALLOW_SEALING);
1366 if (mem_fd == -1)
1367 goto fail;
1368
1369 int res = ftruncate(mem_fd, size);
1370 if (res == -1)
1371 goto fail;
1372
1373 /* udmabuf create requires that the memfd have
1374 * have the F_SEAL_SHRINK seal added and must not
1375 * have the F_SEAL_WRITE seal added */
1376 if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0)
1377 goto fail;
1378
1379 struct udmabuf_create create = {
1380 .memfd = mem_fd,
1381 .flags = UDMABUF_FLAGS_CLOEXEC,
1382 .offset = 0,
1383 .size = size
1384 };
1385
1386 int dmabuf_fd = ioctl(screen->udmabuf_fd, UDMABUF_CREATE, &create);
1387 if (dmabuf_fd < 0)
1388 goto fail;
1389
1390 struct pipe_memory_allocation *data =
1391 mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0);
1392
1393 if (!data)
1394 goto fail;
1395
1396 alloc->mem_fd = mem_fd;
1397 alloc->dmabuf_fd = dmabuf_fd;
1398 alloc->size = size;
1399 return data;
1400 }
1401
1402 fail:
1403 if (mem_fd != -1)
1404 close(mem_fd);
1405 if (dmabuf_fd != -1)
1406 close(dmabuf_fd);
1407 /* If we don't have access to the udmabuf device
1408 * or something else fails we return NULL */
1409 return NULL;
1410 }
1411 #endif
1412
1413 #ifdef PIPE_MEMORY_FD
1414 static struct pipe_memory_allocation *
llvmpipe_allocate_memory_fd(struct pipe_screen * pscreen,uint64_t size,int * fd,bool dmabuf)1415 llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen,
1416 uint64_t size,
1417 int *fd,
1418 bool dmabuf)
1419 {
1420 struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
1421 if (!alloc)
1422 goto fail;
1423
1424 alloc->mem_fd = -1;
1425 alloc->dmabuf_fd = -1;
1426 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1427 if (dmabuf) {
1428 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1429 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
1430 alloc->cpu_addr = llvmpipe_resource_alloc_udmabuf(screen, alloc, size);
1431
1432 if (alloc->cpu_addr)
1433 *fd = os_dupfd_cloexec(alloc->dmabuf_fd);
1434 } else
1435 #endif
1436 {
1437 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE;
1438 uint64_t alignment;
1439 if (!os_get_page_size(&alignment))
1440 alignment = 256;
1441 alloc->cpu_addr = os_malloc_aligned_fd(size, alignment, fd,
1442 "llvmpipe memory fd", driver_id);
1443 }
1444
1445 if(alloc && !alloc->cpu_addr) {
1446 free(alloc);
1447 alloc = NULL;
1448 }
1449
1450 fail:
1451 return (struct pipe_memory_allocation*)alloc;
1452 }
1453
1454
1455 static bool
llvmpipe_import_memory_fd(struct pipe_screen * screen,int fd,struct pipe_memory_allocation ** ptr,uint64_t * size,bool dmabuf)1456 llvmpipe_import_memory_fd(struct pipe_screen *screen,
1457 int fd,
1458 struct pipe_memory_allocation **ptr,
1459 uint64_t *size,
1460 bool dmabuf)
1461 {
1462 struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
1463 alloc->mem_fd = -1;
1464 alloc->dmabuf_fd = -1;
1465 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1466 if (dmabuf) {
1467 off_t mmap_size = lseek(fd, 0, SEEK_END);
1468 lseek(fd, 0, SEEK_SET);
1469 void *cpu_addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1470 if (cpu_addr == MAP_FAILED) {
1471 free(alloc);
1472 *ptr = NULL;
1473 return false;
1474 }
1475
1476 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
1477 alloc->cpu_addr = cpu_addr;
1478 alloc->size = mmap_size;
1479 alloc->dmabuf_fd = os_dupfd_cloexec(fd);
1480 *ptr = (struct pipe_memory_allocation*)alloc;
1481 *size = mmap_size;
1482
1483 return true;
1484 } else
1485 #endif
1486 {
1487 bool ret = os_import_memory_fd(fd, (void**)&alloc->cpu_addr, size, driver_id);
1488
1489 if (!ret) {
1490 free(alloc);
1491 *ptr = NULL;
1492 } else {
1493 *ptr = (struct pipe_memory_allocation*)alloc;
1494 }
1495
1496 alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE;
1497 return ret;
1498 }
1499 }
1500
1501
1502 static void
llvmpipe_free_memory_fd(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1503 llvmpipe_free_memory_fd(struct pipe_screen *screen,
1504 struct pipe_memory_allocation *pmem)
1505 {
1506 struct llvmpipe_memory_allocation *alloc = (struct llvmpipe_memory_allocation*)pmem;
1507 if (alloc->type == LLVMPIPE_MEMORY_FD_TYPE_OPAQUE) {
1508 os_free_fd(alloc->cpu_addr);
1509 }
1510 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1511 else {
1512 munmap(alloc->cpu_addr, alloc->size);
1513 if (alloc->dmabuf_fd >= 0)
1514 close(alloc->dmabuf_fd);
1515 if (alloc->mem_fd >= 0)
1516 close(alloc->mem_fd);
1517 }
1518 #endif
1519
1520 free(alloc);
1521 }
1522
1523 #endif
1524
1525 static void *
llvmpipe_map_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1526 llvmpipe_map_memory(struct pipe_screen *screen,
1527 struct pipe_memory_allocation *pmem)
1528 {
1529 struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1530
1531 #if DETECT_OS_LINUX
1532 if (mem->cpu_addr != MAP_FAILED)
1533 return mem->cpu_addr;
1534
1535 /* create a "CPU" mapping */
1536 mem->cpu_addr = mmap(NULL, mem->size, PROT_READ|PROT_WRITE, MAP_SHARED,
1537 mem->fd, mem->offset);
1538 assert(mem->cpu_addr != MAP_FAILED);
1539 #endif
1540
1541 return mem->cpu_addr;
1542 }
1543
1544 static void
llvmpipe_unmap_memory(struct pipe_screen * screen,struct pipe_memory_allocation * pmem)1545 llvmpipe_unmap_memory(struct pipe_screen *screen,
1546 struct pipe_memory_allocation *pmem)
1547 {
1548 }
1549
1550 static bool
llvmpipe_resource_bind_backing(struct pipe_screen * pscreen,struct pipe_resource * pt,struct pipe_memory_allocation * pmem,uint64_t fd_offset,uint64_t size,uint64_t offset)1551 llvmpipe_resource_bind_backing(struct pipe_screen *pscreen,
1552 struct pipe_resource *pt,
1553 struct pipe_memory_allocation *pmem,
1554 uint64_t fd_offset,
1555 uint64_t size,
1556 uint64_t offset)
1557 {
1558 struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
1559 struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
1560 struct sw_winsys *winsys = screen->winsys;
1561
1562 void *addr;
1563 if (!lpr->backable)
1564 return false;
1565
1566 if ((lpr->base.flags & PIPE_RESOURCE_FLAG_SPARSE) && offset < lpr->size_required) {
1567 #if DETECT_OS_LINUX
1568 struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
1569 if (mem) {
1570 if (llvmpipe_resource_is_texture(&lpr->base)) {
1571 mmap((char *)lpr->tex_data + offset, size, PROT_READ|PROT_WRITE,
1572 MAP_SHARED|MAP_FIXED, mem->fd, mem->offset + fd_offset);
1573 BITSET_SET(lpr->residency, offset / (64 * 1024));
1574 } else {
1575 mmap((char *)lpr->data + offset, size, PROT_READ|PROT_WRITE,
1576 MAP_SHARED|MAP_FIXED, mem->fd, mem->offset + fd_offset);
1577 }
1578 } else {
1579 if (llvmpipe_resource_is_texture(&lpr->base)) {
1580 mmap((char *)lpr->tex_data + offset, size, PROT_READ|PROT_WRITE,
1581 MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1582 BITSET_CLEAR(lpr->residency, offset / (64 * 1024));
1583 } else {
1584 mmap((char *)lpr->data + offset, size, PROT_READ|PROT_WRITE,
1585 MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
1586 }
1587 }
1588 #endif
1589
1590 return true;
1591 }
1592
1593 addr = llvmpipe_map_memory(pscreen, pmem);
1594
1595 if (llvmpipe_resource_is_texture(&lpr->base)) {
1596 if (lpr->size_required > LP_MAX_TEXTURE_SIZE)
1597 return false;
1598
1599 lpr->tex_data = (char *)addr + offset;
1600
1601 if (lpr->dmabuf) {
1602 if (lpr->dt)
1603 winsys->displaytarget_destroy(winsys, lpr->dt);
1604 if (pmem) {
1605 /* Round up the surface size to a multiple of the tile size to
1606 * avoid tile clipping.
1607 */
1608 const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
1609 const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
1610
1611 lpr->dt = winsys->displaytarget_create_mapped(winsys,
1612 lpr->base.bind,
1613 lpr->base.format,
1614 width, height,
1615 lpr->row_stride[0],
1616 lpr->tex_data);
1617 }
1618 }
1619 } else
1620 lpr->data = (char *)addr + offset;
1621 lpr->backing_offset = offset;
1622
1623 return true;
1624 }
1625
1626
1627
1628 #if MESA_DEBUG
1629 void
llvmpipe_print_resources(void)1630 llvmpipe_print_resources(void)
1631 {
1632 struct llvmpipe_resource *lpr;
1633 unsigned n = 0, total = 0;
1634
1635 debug_printf("LLVMPIPE: current resources:\n");
1636 simple_mtx_lock(&resource_list_mutex);
1637 LIST_FOR_EACH_ENTRY(lpr, &resource_list.list, list) {
1638 unsigned size = llvmpipe_resource_size(&lpr->base);
1639 debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
1640 lpr->id, (void *) lpr,
1641 lpr->base.width0, lpr->base.height0, lpr->base.depth0,
1642 size, lpr->base.reference.count);
1643 total += size;
1644 n++;
1645 }
1646 simple_mtx_unlock(&resource_list_mutex);
1647 debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
1648 }
1649 #endif
1650
1651
1652 static void
llvmpipe_get_resource_info(struct pipe_screen * screen,struct pipe_resource * resource,unsigned * stride,unsigned * offset)1653 llvmpipe_get_resource_info(struct pipe_screen *screen,
1654 struct pipe_resource *resource,
1655 unsigned *stride,
1656 unsigned *offset)
1657 {
1658 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1659
1660 *stride = lpr->row_stride[0];
1661 *offset = 0;
1662 }
1663
1664
1665 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)1666 llvmpipe_resource_get_param(struct pipe_screen *screen,
1667 struct pipe_context *context,
1668 struct pipe_resource *resource,
1669 unsigned plane,
1670 unsigned layer,
1671 unsigned level,
1672 enum pipe_resource_param param,
1673 unsigned handle_usage,
1674 uint64_t *value)
1675 {
1676 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1677 struct winsys_handle whandle;
1678
1679 switch (param) {
1680 case PIPE_RESOURCE_PARAM_NPLANES:
1681 *value = lpr->dmabuf ? util_format_get_num_planes(lpr->dt_format) : 1;
1682 return true;
1683 case PIPE_RESOURCE_PARAM_STRIDE:
1684 *value = lpr->row_stride[level];
1685 return true;
1686 case PIPE_RESOURCE_PARAM_OFFSET:
1687 *value = lpr->mip_offsets[level] + (lpr->img_stride[level] * layer);
1688 return true;
1689 case PIPE_RESOURCE_PARAM_LAYER_STRIDE:
1690 *value = lpr->img_stride[level];
1691 return true;
1692 #ifndef _WIN32
1693 case PIPE_RESOURCE_PARAM_MODIFIER:
1694 *value = lpr->dmabuf ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
1695 return true;
1696 #endif
1697 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
1698 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
1699 case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
1700 if (!lpr->dt)
1701 return false;
1702
1703 memset(&whandle, 0, sizeof(whandle));
1704 if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED)
1705 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1706 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS)
1707 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1708 else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD)
1709 whandle.type = WINSYS_HANDLE_TYPE_FD;
1710
1711 if (!llvmpipe_resource_get_handle(screen, context, resource,
1712 &whandle, handle_usage)) {
1713 return false;
1714 }
1715 *value = (uint64_t)(uintptr_t)whandle.handle;
1716 return true;
1717 default:
1718 break;
1719 }
1720 assert(0);
1721 *value = 0;
1722 return false;
1723 }
1724
1725 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1726 static void
llvmpipe_query_dmabuf_modifiers(struct pipe_screen * pscreen,enum pipe_format format,int max,uint64_t * modifiers,unsigned int * external_only,int * count)1727 llvmpipe_query_dmabuf_modifiers(struct pipe_screen *pscreen, enum pipe_format format, int max, uint64_t *modifiers, unsigned int *external_only, int *count)
1728 {
1729 *count = 1;
1730
1731 if (max)
1732 *modifiers = DRM_FORMAT_MOD_LINEAR;
1733 }
1734
1735 static bool
llvmpipe_is_dmabuf_modifier_supported(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format,bool * external_only)1736 llvmpipe_is_dmabuf_modifier_supported(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format, bool *external_only)
1737 {
1738 return modifier == DRM_FORMAT_MOD_LINEAR;
1739 }
1740
1741 static unsigned
llvmpipe_get_dmabuf_modifier_planes(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format)1742 llvmpipe_get_dmabuf_modifier_planes(struct pipe_screen *pscreen, uint64_t modifier, enum pipe_format format)
1743 {
1744 return modifier == DRM_FORMAT_MOD_LINEAR;
1745 }
1746 #endif
1747
1748 void
llvmpipe_init_screen_resource_funcs(struct pipe_screen * screen)1749 llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
1750 {
1751 #if MESA_DEBUG
1752 /* init linked list for tracking resources */
1753 {
1754 static bool first_call = true;
1755 if (first_call) {
1756 memset(&resource_list, 0, sizeof(resource_list));
1757 list_inithead(&resource_list.list);
1758 first_call = false;
1759 }
1760 }
1761 #endif
1762
1763 screen->resource_create = llvmpipe_resource_create;
1764 /* screen->resource_create_front = llvmpipe_resource_create_front; */
1765 screen->resource_destroy = llvmpipe_resource_destroy;
1766 screen->resource_from_handle = llvmpipe_resource_from_handle;
1767 screen->resource_from_memobj = llvmpipe_resource_from_memobj;
1768 screen->resource_get_handle = llvmpipe_resource_get_handle;
1769 screen->can_create_resource = llvmpipe_can_create_resource;
1770
1771 screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
1772
1773 screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle;
1774 screen->memobj_destroy = llvmpipe_memobj_destroy;
1775
1776 screen->resource_get_info = llvmpipe_get_resource_info;
1777 screen->resource_get_param = llvmpipe_resource_get_param;
1778 screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
1779 screen->allocate_memory = llvmpipe_allocate_memory;
1780 screen->free_memory = llvmpipe_free_memory;
1781 #ifdef PIPE_MEMORY_FD
1782 screen->allocate_memory_fd = llvmpipe_allocate_memory_fd;
1783 screen->import_memory_fd = llvmpipe_import_memory_fd;
1784 screen->free_memory_fd = llvmpipe_free_memory_fd;
1785 #endif
1786 #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H)
1787 screen->query_dmabuf_modifiers = llvmpipe_query_dmabuf_modifiers;
1788 screen->is_dmabuf_modifier_supported = llvmpipe_is_dmabuf_modifier_supported;
1789 screen->get_dmabuf_modifier_planes = llvmpipe_get_dmabuf_modifier_planes;
1790 screen->resource_create_with_modifiers = llvmpipe_resource_create_with_modifiers;
1791 #endif
1792 screen->map_memory = llvmpipe_map_memory;
1793 screen->unmap_memory = llvmpipe_unmap_memory;
1794
1795 screen->resource_bind_backing = llvmpipe_resource_bind_backing;
1796 }
1797
1798
1799 void
llvmpipe_init_context_resource_funcs(struct pipe_context * pipe)1800 llvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
1801 {
1802 pipe->buffer_map = llvmpipe_transfer_map;
1803 pipe->buffer_unmap = llvmpipe_transfer_unmap;
1804 pipe->texture_map = llvmpipe_transfer_map;
1805 pipe->texture_unmap = llvmpipe_transfer_unmap;
1806
1807 pipe->transfer_flush_region = u_default_transfer_flush_region;
1808 pipe->buffer_subdata = u_default_buffer_subdata;
1809 pipe->texture_subdata = u_default_texture_subdata;
1810
1811 pipe->memory_barrier = llvmpipe_memory_barrier;
1812 }
1813