1 /**********************************************************
2 * Copyright 2008-2023 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26 #include "svga3d_reg.h"
27 #include "svga3d_surfacedefs.h"
28
29 #include "pipe/p_state.h"
30 #include "pipe/p_defines.h"
31 #include "util/u_thread.h"
32 #include "util/format/u_format.h"
33 #include "util/u_inlines.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
36 #include "util/u_resource.h"
37 #include "util/u_upload_mgr.h"
38
39 #include "svga_cmd.h"
40 #include "svga_format.h"
41 #include "svga_screen.h"
42 #include "svga_context.h"
43 #include "svga_resource_texture.h"
44 #include "svga_resource_buffer.h"
45 #include "svga_sampler_view.h"
46 #include "svga_surface.h"
47 #include "svga_winsys.h"
48 #include "svga_debug.h"
49
50
51 static void
svga_transfer_dma_band(struct svga_context * svga,struct svga_transfer * st,SVGA3dTransferType transfer,unsigned x,unsigned y,unsigned z,unsigned w,unsigned h,unsigned d,unsigned srcx,unsigned srcy,unsigned srcz,SVGA3dSurfaceDMAFlags flags)52 svga_transfer_dma_band(struct svga_context *svga,
53 struct svga_transfer *st,
54 SVGA3dTransferType transfer,
55 unsigned x, unsigned y, unsigned z,
56 unsigned w, unsigned h, unsigned d,
57 unsigned srcx, unsigned srcy, unsigned srcz,
58 SVGA3dSurfaceDMAFlags flags)
59 {
60 struct svga_texture *texture = svga_texture(st->base.resource);
61 SVGA3dCopyBox box;
62
63 assert(!st->use_direct_map);
64
65 box.x = x;
66 box.y = y;
67 box.z = z;
68 box.w = w;
69 box.h = h;
70 box.d = d;
71 box.srcx = srcx;
72 box.srcy = srcy;
73 box.srcz = srcz;
74
75 SVGA_DBG(DEBUG_DMA, "dma %s sid %p, face %u, (%u, %u, %u) - "
76 "(%u, %u, %u), %ubpp\n",
77 transfer == SVGA3D_WRITE_HOST_VRAM ? "to" : "from",
78 texture->handle,
79 st->slice,
80 x,
81 y,
82 z,
83 x + w,
84 y + h,
85 z + 1,
86 util_format_get_blocksize(texture->b.format) * 8 /
87 (util_format_get_blockwidth(texture->b.format)
88 * util_format_get_blockheight(texture->b.format)));
89
90 SVGA_RETRY(svga, SVGA3D_SurfaceDMA(svga->swc, st, transfer, &box, 1, flags));
91 }
92
93
94 static void
svga_transfer_dma(struct svga_context * svga,struct svga_transfer * st,SVGA3dTransferType transfer,SVGA3dSurfaceDMAFlags flags)95 svga_transfer_dma(struct svga_context *svga,
96 struct svga_transfer *st,
97 SVGA3dTransferType transfer,
98 SVGA3dSurfaceDMAFlags flags)
99 {
100 struct svga_texture *texture = svga_texture(st->base.resource);
101 struct svga_screen *screen = svga_screen(texture->b.screen);
102 struct svga_winsys_screen *sws = screen->sws;
103 struct pipe_fence_handle *fence = NULL;
104
105 assert(!st->use_direct_map);
106
107 if (transfer == SVGA3D_READ_HOST_VRAM) {
108 SVGA_DBG(DEBUG_PERF, "%s: readback transfer\n", __func__);
109 }
110
111 /* Ensure any pending operations on host surfaces are queued on the command
112 * buffer first.
113 */
114 svga_surfaces_flush(svga);
115
116 if (!st->swbuf) {
117 /* Do the DMA transfer in a single go */
118 svga_transfer_dma_band(svga, st, transfer,
119 st->box.x, st->box.y, st->box.z,
120 st->box.w, st->box.h, st->box.d,
121 0, 0, 0,
122 flags);
123
124 if (transfer == SVGA3D_READ_HOST_VRAM) {
125 svga_context_flush(svga, &fence);
126 sws->fence_finish(sws, fence, OS_TIMEOUT_INFINITE, 0);
127 sws->fence_reference(sws, &fence, NULL);
128 }
129 }
130 else {
131 int y, h, srcy;
132 unsigned blockheight =
133 util_format_get_blockheight(st->base.resource->format);
134
135 h = st->hw_nblocksy * blockheight;
136 srcy = 0;
137
138 for (y = 0; y < st->box.h; y += h) {
139 unsigned offset, length;
140 void *hw, *sw;
141
142 if (y + h > st->box.h)
143 h = st->box.h - y;
144
145 /* Transfer band must be aligned to pixel block boundaries */
146 assert(y % blockheight == 0);
147 assert(h % blockheight == 0);
148
149 offset = y * st->base.stride / blockheight;
150 length = h * st->base.stride / blockheight;
151
152 sw = (uint8_t *) st->swbuf + offset;
153
154 if (transfer == SVGA3D_WRITE_HOST_VRAM) {
155 unsigned usage = PIPE_MAP_WRITE;
156
157 /* Wait for the previous DMAs to complete */
158 /* TODO: keep one DMA (at half the size) in the background */
159 if (y) {
160 svga_context_flush(svga, NULL);
161 usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE;
162 }
163
164 hw = sws->buffer_map(sws, st->hwbuf, usage);
165 assert(hw);
166 if (hw) {
167 memcpy(hw, sw, length);
168 sws->buffer_unmap(sws, st->hwbuf);
169 }
170 }
171
172 svga_transfer_dma_band(svga, st, transfer,
173 st->box.x, y, st->box.z,
174 st->box.w, h, st->box.d,
175 0, srcy, 0, flags);
176
177 /*
178 * Prevent the texture contents to be discarded on the next band
179 * upload.
180 */
181 flags.discard = false;
182
183 if (transfer == SVGA3D_READ_HOST_VRAM) {
184 svga_context_flush(svga, &fence);
185 sws->fence_finish(sws, fence, OS_TIMEOUT_INFINITE, 0);
186
187 hw = sws->buffer_map(sws, st->hwbuf, PIPE_MAP_READ);
188 assert(hw);
189 if (hw) {
190 memcpy(sw, hw, length);
191 sws->buffer_unmap(sws, st->hwbuf);
192 }
193 }
194 }
195 }
196 }
197
198
199
200 bool
svga_resource_get_handle(struct pipe_screen * screen,struct pipe_context * context,struct pipe_resource * texture,struct winsys_handle * whandle,unsigned usage)201 svga_resource_get_handle(struct pipe_screen *screen,
202 struct pipe_context *context,
203 struct pipe_resource *texture,
204 struct winsys_handle *whandle,
205 unsigned usage)
206 {
207 struct svga_winsys_screen *sws = svga_winsys_screen(texture->screen);
208 unsigned stride;
209
210 if (texture->target == PIPE_BUFFER)
211 return false;
212
213 SVGA_DBG(DEBUG_DMA, "%s: texture=%p cachable=%d\n", __FUNCTION__,
214 texture, svga_texture(texture)->key.cachable);
215
216 svga_texture(texture)->key.cachable = 0;
217
218 stride = util_format_get_nblocksx(texture->format, texture->width0) *
219 util_format_get_blocksize(texture->format);
220
221 return sws->surface_get_handle(sws, svga_texture(texture)->handle,
222 stride, whandle);
223 }
224
225
226 /**
227 * Determine if we need to read back a texture image before mapping it.
228 */
229 static inline bool
need_tex_readback(struct svga_transfer * st)230 need_tex_readback(struct svga_transfer *st)
231 {
232 if (st->base.usage & PIPE_MAP_READ)
233 return true;
234
235 if ((st->base.usage & PIPE_MAP_WRITE) &&
236 ((st->base.usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) == 0)) {
237 return svga_was_texture_rendered_to(svga_texture(st->base.resource));
238 }
239
240 return false;
241 }
242
243
244 static void
readback_texture_surface(struct svga_context * svga,struct svga_texture * tex,struct svga_winsys_surface * surf)245 readback_texture_surface(struct svga_context *svga,
246 struct svga_texture *tex,
247 struct svga_winsys_surface *surf)
248 {
249 SVGA_RETRY(svga, SVGA3D_ReadbackGBSurface(svga->swc, surf));
250
251 /* Mark the texture surface as UPDATED */
252 tex->surface_state = SVGA_SURFACE_STATE_UPDATED;
253
254 svga->hud.num_readbacks++;
255 SVGA_STATS_COUNT_INC(svga_sws(svga), SVGA_STATS_COUNT_TEXREADBACK);
256 }
257
258 /**
259 * Use DMA for the transfer request
260 */
261 static void *
svga_texture_transfer_map_dma(struct svga_context * svga,struct svga_transfer * st)262 svga_texture_transfer_map_dma(struct svga_context *svga,
263 struct svga_transfer *st)
264 {
265 struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
266 struct pipe_resource *texture = st->base.resource;
267 unsigned nblocksx, nblocksy;
268 unsigned d;
269 unsigned usage = st->base.usage;
270
271 /* we'll put the data into a tightly packed buffer */
272 nblocksx = util_format_get_nblocksx(texture->format, st->box.w);
273 nblocksy = util_format_get_nblocksy(texture->format, st->box.h);
274 d = st->box.d;
275
276 st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
277 st->base.layer_stride = st->base.stride * nblocksy;
278 st->hw_nblocksy = nblocksy;
279
280 st->hwbuf = svga_winsys_buffer_create(svga, 1, 0,
281 st->hw_nblocksy * st->base.stride * d);
282
283 while (!st->hwbuf && (st->hw_nblocksy /= 2)) {
284 st->hwbuf =
285 svga_winsys_buffer_create(svga, 1, 0,
286 st->hw_nblocksy * st->base.stride * d);
287 }
288
289 if (!st->hwbuf)
290 return NULL;
291
292 if (st->hw_nblocksy < nblocksy) {
293 /* We couldn't allocate a hardware buffer big enough for the transfer,
294 * so allocate regular malloc memory instead
295 */
296 if (0) {
297 debug_printf("%s: failed to allocate %u KB of DMA, "
298 "splitting into %u x %u KB DMA transfers\n",
299 __func__,
300 (nblocksy * st->base.stride + 1023) / 1024,
301 (nblocksy + st->hw_nblocksy - 1) / st->hw_nblocksy,
302 (st->hw_nblocksy * st->base.stride + 1023) / 1024);
303 }
304
305 st->swbuf = MALLOC(nblocksy * st->base.stride * d);
306 if (!st->swbuf) {
307 sws->buffer_destroy(sws, st->hwbuf);
308 return NULL;
309 }
310 }
311
312 if (usage & PIPE_MAP_READ) {
313 SVGA3dSurfaceDMAFlags flags;
314 memset(&flags, 0, sizeof flags);
315 svga_transfer_dma(svga, st, SVGA3D_READ_HOST_VRAM, flags);
316 }
317
318 if (st->swbuf) {
319 return st->swbuf;
320 }
321 else {
322 return sws->buffer_map(sws, st->hwbuf, usage);
323 }
324 }
325
326
327 /**
328 * Use direct map for the transfer request
329 */
330 static void *
svga_texture_transfer_map_direct(struct svga_context * svga,struct svga_transfer * st)331 svga_texture_transfer_map_direct(struct svga_context *svga,
332 struct svga_transfer *st)
333 {
334 struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
335 struct pipe_transfer *transfer = &st->base;
336 struct pipe_resource *texture = transfer->resource;
337 struct svga_texture *tex = svga_texture(texture);
338 struct svga_winsys_surface *surf = tex->handle;
339 unsigned level = st->base.level;
340 unsigned w, h, nblocksx, nblocksy;
341 unsigned usage = st->base.usage;
342
343 if (need_tex_readback(st)) {
344 svga_surfaces_flush(svga);
345
346 if (!svga->swc->force_coherent || tex->imported) {
347 /* Readback the whole surface */
348 readback_texture_surface(svga, tex, surf);
349
350 svga_context_finish(svga);
351 }
352 /*
353 * Note: if PIPE_MAP_DISCARD_WHOLE_RESOURCE were specified
354 * we could potentially clear the flag for all faces/layers/mips.
355 */
356 svga_clear_texture_rendered_to(tex);
357 }
358 else {
359 assert(usage & PIPE_MAP_WRITE);
360 if ((usage & PIPE_MAP_UNSYNCHRONIZED) == 0) {
361 if (svga_is_texture_level_dirty(tex, st->slice, level)) {
362 /*
363 * do a surface flush if the subresource has been modified
364 * in this command buffer.
365 */
366 svga_surfaces_flush(svga);
367 if (!sws->surface_is_flushed(sws, surf)) {
368 svga->hud.surface_write_flushes++;
369 SVGA_STATS_COUNT_INC(sws, SVGA_STATS_COUNT_SURFACEWRITEFLUSH);
370 svga_context_flush(svga, NULL);
371 }
372 }
373 }
374 }
375
376 /* we'll directly access the guest-backed surface */
377 w = u_minify(texture->width0, level);
378 h = u_minify(texture->height0, level);
379 nblocksx = util_format_get_nblocksx(texture->format, w);
380 nblocksy = util_format_get_nblocksy(texture->format, h);
381 st->hw_nblocksy = nblocksy;
382 st->base.stride = nblocksx*util_format_get_blocksize(texture->format);
383 st->base.layer_stride = st->base.stride * nblocksy;
384
385 /*
386 * Begin mapping code
387 */
388 {
389 SVGA3dSize baseLevelSize;
390 uint8_t *map;
391 bool retry, rebind;
392 unsigned offset, mip_width, mip_height;
393 struct svga_winsys_context *swc = svga->swc;
394
395 if (swc->force_coherent) {
396 usage |= PIPE_MAP_PERSISTENT | PIPE_MAP_COHERENT;
397 }
398
399 map = SVGA_TRY_MAP(svga->swc->surface_map
400 (svga->swc, surf, usage, &retry, &rebind), retry);
401
402 if (map == NULL && retry) {
403 /*
404 * At this point, the svga_surfaces_flush() should already have
405 * called in svga_texture_get_transfer().
406 */
407 svga->hud.surface_write_flushes++;
408 svga_retry_enter(svga);
409 svga_context_flush(svga, NULL);
410 map = svga->swc->surface_map(svga->swc, surf, usage, &retry, &rebind);
411 svga_retry_exit(svga);
412 }
413 if (map && rebind) {
414 enum pipe_error ret;
415
416 ret = SVGA3D_BindGBSurface(swc, surf);
417 if (ret != PIPE_OK) {
418 svga_context_flush(svga, NULL);
419 ret = SVGA3D_BindGBSurface(swc, surf);
420 assert(ret == PIPE_OK);
421 }
422 svga_context_flush(svga, NULL);
423 }
424
425 /*
426 * Make sure we return NULL if the map fails
427 */
428 if (!map) {
429 return NULL;
430 }
431
432 /**
433 * Compute the offset to the specific texture slice in the buffer.
434 */
435 baseLevelSize.width = tex->b.width0;
436 baseLevelSize.height = tex->b.height0;
437 baseLevelSize.depth = tex->b.depth0;
438
439 if ((tex->b.target == PIPE_TEXTURE_1D_ARRAY) ||
440 (tex->b.target == PIPE_TEXTURE_2D_ARRAY) ||
441 (tex->b.target == PIPE_TEXTURE_CUBE_ARRAY)) {
442 st->base.layer_stride =
443 svga3dsurface_get_image_offset(tex->key.format, baseLevelSize,
444 tex->b.last_level + 1, 1, 0);
445 }
446
447 offset = svga3dsurface_get_image_offset(tex->key.format, baseLevelSize,
448 tex->b.last_level + 1, /* numMips */
449 st->slice, level);
450 if (level > 0) {
451 assert(offset > 0);
452 }
453
454 mip_width = u_minify(tex->b.width0, level);
455 mip_height = u_minify(tex->b.height0, level);
456
457 offset += svga3dsurface_get_pixel_offset(tex->key.format,
458 mip_width, mip_height,
459 st->box.x,
460 st->box.y,
461 st->box.z);
462
463 return (void *) (map + offset);
464 }
465 }
466
467
468 /**
469 * Request a transfer map to the texture resource
470 */
471 void *
svga_texture_transfer_map(struct pipe_context * pipe,struct pipe_resource * texture,unsigned level,unsigned usage,const struct pipe_box * box,struct pipe_transfer ** ptransfer)472 svga_texture_transfer_map(struct pipe_context *pipe,
473 struct pipe_resource *texture,
474 unsigned level,
475 unsigned usage,
476 const struct pipe_box *box,
477 struct pipe_transfer **ptransfer)
478 {
479 struct svga_context *svga = svga_context(pipe);
480 struct svga_winsys_screen *sws = svga_screen(pipe->screen)->sws;
481 struct svga_texture *tex = svga_texture(texture);
482 struct svga_transfer *st;
483 struct svga_winsys_surface *surf = tex->handle;
484 bool use_direct_map = svga_have_gb_objects(svga) &&
485 (!svga_have_gb_dma(svga) || (usage & PIPE_MAP_WRITE));
486 void *map = NULL;
487 int64_t begin = svga_get_time(svga);
488
489 SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_TEXTRANSFERMAP);
490
491 if (!surf)
492 goto done;
493
494 /* We can't map texture storage directly unless we have GB objects */
495 if (usage & PIPE_MAP_DIRECTLY) {
496 if (svga_have_gb_objects(svga))
497 use_direct_map = true;
498 else
499 goto done;
500 }
501
502 st = CALLOC_STRUCT(svga_transfer);
503 if (!st)
504 goto done;
505
506 st->base.level = level;
507 st->base.usage = usage;
508 st->base.box = *box;
509
510 /* The modified transfer map box with the array index removed from z.
511 * The array index is specified in slice.
512 */
513 st->box.x = box->x;
514 st->box.y = box->y;
515 st->box.z = box->z;
516 st->box.w = box->width;
517 st->box.h = box->height;
518 st->box.d = box->depth;
519
520 switch (tex->b.target) {
521 case PIPE_TEXTURE_CUBE:
522 st->slice = st->base.box.z;
523 st->box.z = 0; /* so we don't apply double offsets below */
524 break;
525 case PIPE_TEXTURE_1D_ARRAY:
526 case PIPE_TEXTURE_2D_ARRAY:
527 case PIPE_TEXTURE_CUBE_ARRAY:
528 st->slice = st->base.box.z;
529 st->box.z = 0; /* so we don't apply double offsets below */
530
531 /* Force direct map for transfering multiple slices */
532 if (st->base.box.depth > 1)
533 use_direct_map = svga_have_gb_objects(svga);
534
535 break;
536 default:
537 st->slice = 0;
538 break;
539 }
540
541 /* We never want to use DMA transfers on systems with GBObjects because
542 * it causes serialization issues and in SVGAv3 vram is gone which
543 * makes it impossible to support both at the same time.
544 */
545 if (svga_have_gb_objects(svga)) {
546 use_direct_map = true;
547 }
548
549 st->use_direct_map = use_direct_map;
550 pipe_resource_reference(&st->base.resource, texture);
551
552 /* If this is the first time mapping to the surface in this
553 * command buffer and there is no pending primitives, clear
554 * the dirty masks of this surface.
555 */
556 if (sws->surface_is_flushed(sws, surf) &&
557 (svga_have_vgpu10(svga) ||
558 !svga_hwtnl_has_pending_prim(svga->hwtnl))) {
559 svga_clear_texture_dirty(tex);
560 }
561
562 if (!use_direct_map) {
563 /* upload to the DMA buffer */
564 map = svga_texture_transfer_map_dma(svga, st);
565 }
566 else {
567 bool can_use_upload = tex->can_use_upload &&
568 !(st->base.usage & PIPE_MAP_READ);
569 bool was_rendered_to =
570 svga_was_texture_rendered_to(svga_texture(texture));
571 bool is_dirty = svga_is_texture_dirty(svga_texture(texture));
572
573 /* If the texture was already rendered to or has pending changes and
574 * upload buffer is supported, then we will use upload buffer to
575 * avoid the need to read back the texture content; otherwise,
576 * we'll first try to map directly to the GB surface, if it is blocked,
577 * then we'll try the upload buffer.
578 */
579 if ((was_rendered_to || is_dirty) && can_use_upload) {
580 map = svga_texture_transfer_map_upload(svga, st);
581 }
582 else {
583 unsigned orig_usage = st->base.usage;
584
585 /* First try directly map to the GB surface */
586 if (can_use_upload)
587 st->base.usage |= PIPE_MAP_DONTBLOCK;
588 map = svga_texture_transfer_map_direct(svga, st);
589 st->base.usage = orig_usage;
590
591 if (!map && can_use_upload) {
592 /* if direct map with DONTBLOCK fails, then try upload to the
593 * texture upload buffer.
594 */
595 map = svga_texture_transfer_map_upload(svga, st);
596 }
597 }
598
599 /* If upload fails, then try direct map again without forcing it
600 * to DONTBLOCK.
601 */
602 if (!map) {
603 map = svga_texture_transfer_map_direct(svga, st);
604 }
605 }
606
607 if (!map) {
608 FREE(st);
609 }
610 else {
611 *ptransfer = &st->base;
612 svga->hud.num_textures_mapped++;
613 if (usage & PIPE_MAP_WRITE) {
614 /* record texture upload for HUD */
615 svga->hud.num_bytes_uploaded +=
616 st->base.layer_stride * st->box.d;
617
618 /* mark this texture level as dirty */
619 svga_set_texture_dirty(tex, st->slice, level);
620 }
621 }
622
623 done:
624 svga->hud.map_buffer_time += (svga_get_time(svga) - begin);
625 SVGA_STATS_TIME_POP(sws);
626 (void) sws;
627
628 return map;
629 }
630
631 /**
632 * Unmap a GB texture surface.
633 */
634 static void
svga_texture_surface_unmap(struct svga_context * svga,struct pipe_transfer * transfer)635 svga_texture_surface_unmap(struct svga_context *svga,
636 struct pipe_transfer *transfer)
637 {
638 struct svga_winsys_surface *surf = svga_texture(transfer->resource)->handle;
639 struct svga_winsys_context *swc = svga->swc;
640 bool rebind;
641
642 assert(surf);
643
644 swc->surface_unmap(swc, surf, &rebind);
645 if (rebind) {
646 SVGA_RETRY(svga, SVGA3D_BindGBSurface(swc, surf));
647 }
648 }
649
650
651 static void
update_image_vgpu9(struct svga_context * svga,struct svga_winsys_surface * surf,const SVGA3dBox * box,unsigned slice,unsigned level)652 update_image_vgpu9(struct svga_context *svga,
653 struct svga_winsys_surface *surf,
654 const SVGA3dBox *box,
655 unsigned slice,
656 unsigned level)
657 {
658 SVGA_RETRY(svga, SVGA3D_UpdateGBImage(svga->swc, surf, box, slice, level));
659 }
660
661
662 static void
update_image_vgpu10(struct svga_context * svga,struct svga_winsys_surface * surf,const SVGA3dBox * box,unsigned slice,unsigned level,unsigned numMipLevels)663 update_image_vgpu10(struct svga_context *svga,
664 struct svga_winsys_surface *surf,
665 const SVGA3dBox *box,
666 unsigned slice,
667 unsigned level,
668 unsigned numMipLevels)
669 {
670 unsigned subResource;
671
672 subResource = slice * numMipLevels + level;
673
674 SVGA_RETRY(svga, SVGA3D_vgpu10_UpdateSubResource(svga->swc, surf, box,
675 subResource));
676 }
677
678
679 /**
680 * unmap DMA transfer request
681 */
682 static void
svga_texture_transfer_unmap_dma(struct svga_context * svga,struct svga_transfer * st)683 svga_texture_transfer_unmap_dma(struct svga_context *svga,
684 struct svga_transfer *st)
685 {
686 struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
687
688 if (!st->swbuf)
689 sws->buffer_unmap(sws, st->hwbuf);
690
691 if (st->base.usage & PIPE_MAP_WRITE) {
692 /* Use DMA to transfer texture data */
693 SVGA3dSurfaceDMAFlags flags;
694 struct pipe_resource *texture = st->base.resource;
695 struct svga_texture *tex = svga_texture(texture);
696
697
698 memset(&flags, 0, sizeof flags);
699 if (st->base.usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) {
700 flags.discard = true;
701 }
702 if (st->base.usage & PIPE_MAP_UNSYNCHRONIZED) {
703 flags.unsynchronized = true;
704 }
705
706 svga_transfer_dma(svga, st, SVGA3D_WRITE_HOST_VRAM, flags);
707 svga_set_texture_rendered_to(tex);
708 }
709
710 FREE(st->swbuf);
711 sws->buffer_destroy(sws, st->hwbuf);
712 }
713
714
715 /**
716 * unmap direct map transfer request
717 */
718 static void
svga_texture_transfer_unmap_direct(struct svga_context * svga,struct svga_transfer * st)719 svga_texture_transfer_unmap_direct(struct svga_context *svga,
720 struct svga_transfer *st)
721 {
722 struct pipe_transfer *transfer = &st->base;
723 struct svga_texture *tex = svga_texture(transfer->resource);
724
725 svga_texture_surface_unmap(svga, transfer);
726
727 /* Now send an update command to update the content in the backend. */
728 if (st->base.usage & PIPE_MAP_WRITE) {
729 struct svga_winsys_surface *surf = tex->handle;
730
731 assert(svga_have_gb_objects(svga));
732
733 /* update the effected region */
734 SVGA3dBox box = st->box;
735 unsigned nlayers;
736
737 switch (tex->b.target) {
738 case PIPE_TEXTURE_2D_ARRAY:
739 case PIPE_TEXTURE_CUBE_ARRAY:
740 case PIPE_TEXTURE_1D_ARRAY:
741 nlayers = box.d;
742 box.d = 1;
743 break;
744 default:
745 nlayers = 1;
746 break;
747 }
748
749
750 if (0)
751 debug_printf("%s %d, %d, %d %d x %d x %d\n",
752 __func__,
753 box.x, box.y, box.z,
754 box.w, box.h, box.d);
755
756 if (!svga->swc->force_coherent || tex->imported) {
757 if (svga_have_vgpu10(svga)) {
758 unsigned i;
759
760 for (i = 0; i < nlayers; i++) {
761 update_image_vgpu10(svga, surf, &box,
762 st->slice + i, transfer->level,
763 tex->b.last_level + 1);
764 }
765 } else {
766 assert(nlayers == 1);
767 update_image_vgpu9(svga, surf, &box, st->slice,
768 transfer->level);
769 }
770 }
771
772 /* Mark the texture surface state as UPDATED */
773 tex->surface_state = SVGA_SURFACE_STATE_UPDATED;
774 }
775 }
776
777
778 void
svga_texture_transfer_unmap(struct pipe_context * pipe,struct pipe_transfer * transfer)779 svga_texture_transfer_unmap(struct pipe_context *pipe,
780 struct pipe_transfer *transfer)
781 {
782 struct svga_context *svga = svga_context(pipe);
783 struct svga_screen *ss = svga_screen(pipe->screen);
784 struct svga_winsys_screen *sws = ss->sws;
785 struct svga_transfer *st = svga_transfer(transfer);
786 struct svga_texture *tex = svga_texture(transfer->resource);
787
788 SVGA_STATS_TIME_PUSH(sws, SVGA_STATS_TIME_TEXTRANSFERUNMAP);
789
790 if (!st->use_direct_map) {
791 svga_texture_transfer_unmap_dma(svga, st);
792 }
793 else if (st->upload.buf) {
794 svga_texture_transfer_unmap_upload(svga, st);
795 }
796 else {
797 svga_texture_transfer_unmap_direct(svga, st);
798 }
799
800 if (st->base.usage & PIPE_MAP_WRITE) {
801 svga->hud.num_resource_updates++;
802
803 /* Mark the texture level as dirty */
804 ss->texture_timestamp++;
805 svga_age_texture_view(tex, transfer->level);
806 if (transfer->resource->target == PIPE_TEXTURE_CUBE)
807 svga_define_texture_level(tex, st->slice, transfer->level);
808 else
809 svga_define_texture_level(tex, 0, transfer->level);
810 }
811
812 pipe_resource_reference(&st->base.resource, NULL);
813 FREE(st);
814 SVGA_STATS_TIME_POP(sws);
815 (void) sws;
816 }
817
818
819 /**
820 * Does format store depth values?
821 */
822 static inline bool
format_has_depth(enum pipe_format format)823 format_has_depth(enum pipe_format format)
824 {
825 const struct util_format_description *desc = util_format_description(format);
826 return util_format_has_depth(desc);
827 }
828
829 struct pipe_resource *
svga_texture_create(struct pipe_screen * screen,const struct pipe_resource * template)830 svga_texture_create(struct pipe_screen *screen,
831 const struct pipe_resource *template)
832 {
833 struct svga_screen *svgascreen = svga_screen(screen);
834 struct svga_texture *tex;
835 unsigned bindings = template->bind;
836
837 SVGA_STATS_TIME_PUSH(svgascreen->sws,
838 SVGA_STATS_TIME_CREATETEXTURE);
839
840 assert(template->last_level < SVGA_MAX_TEXTURE_LEVELS);
841 if (template->last_level >= SVGA_MAX_TEXTURE_LEVELS) {
842 goto fail_notex;
843 }
844
845 /* Verify the number of mipmap levels isn't impossibly large. For example,
846 * if the base 2D image is 16x16, we can't have 8 mipmap levels.
847 * the gallium frontend should never ask us to create a resource with invalid
848 * parameters.
849 */
850 {
851 unsigned max_dim = template->width0;
852
853 switch (template->target) {
854 case PIPE_TEXTURE_1D:
855 case PIPE_TEXTURE_1D_ARRAY:
856 // nothing
857 break;
858 case PIPE_TEXTURE_2D:
859 case PIPE_TEXTURE_CUBE:
860 case PIPE_TEXTURE_CUBE_ARRAY:
861 case PIPE_TEXTURE_2D_ARRAY:
862 max_dim = MAX2(max_dim, template->height0);
863 break;
864 case PIPE_TEXTURE_3D:
865 max_dim = MAX3(max_dim, template->height0, template->depth0);
866 break;
867 case PIPE_TEXTURE_RECT:
868 case PIPE_BUFFER:
869 assert(template->last_level == 0);
870 /* the assertion below should always pass */
871 break;
872 default:
873 debug_printf("Unexpected texture target type\n");
874 }
875 assert(1 << template->last_level <= max_dim);
876 }
877
878 tex = CALLOC_STRUCT(svga_texture);
879 if (!tex) {
880 goto fail_notex;
881 }
882
883 tex->defined = CALLOC(template->depth0 * template->array_size,
884 sizeof(tex->defined[0]));
885 if (!tex->defined) {
886 FREE(tex);
887 goto fail_notex;
888 }
889
890 tex->dirty = CALLOC(template->depth0 * template->array_size,
891 sizeof(tex->dirty[0]));
892 if (!tex->dirty) {
893 goto fail;
894 }
895
896 tex->b = *template;
897 pipe_reference_init(&tex->b.reference, 1);
898 tex->b.screen = screen;
899
900 tex->key.flags = 0;
901 tex->key.size.width = template->width0;
902 tex->key.size.height = template->height0;
903 tex->key.size.depth = template->depth0;
904 tex->key.arraySize = 1;
905 tex->key.numFaces = 1;
906
907 /* nr_samples=1 must be treated as a non-multisample texture */
908 if (tex->b.nr_samples == 1) {
909 tex->b.nr_samples = 0;
910 }
911 else if (tex->b.nr_samples > 1) {
912 assert(svgascreen->sws->have_sm4_1);
913 tex->key.flags |= SVGA3D_SURFACE_MULTISAMPLE;
914 }
915
916 tex->key.sampleCount = tex->b.nr_samples;
917
918 if (svgascreen->sws->have_vgpu10) {
919 switch (template->target) {
920 case PIPE_TEXTURE_1D:
921 tex->key.flags |= SVGA3D_SURFACE_1D;
922 break;
923 case PIPE_TEXTURE_1D_ARRAY:
924 tex->key.flags |= SVGA3D_SURFACE_1D;
925 FALLTHROUGH;
926 case PIPE_TEXTURE_2D_ARRAY:
927 tex->key.flags |= SVGA3D_SURFACE_ARRAY;
928 tex->key.arraySize = template->array_size;
929 break;
930 case PIPE_TEXTURE_3D:
931 tex->key.flags |= SVGA3D_SURFACE_VOLUME;
932 break;
933 case PIPE_TEXTURE_CUBE:
934 tex->key.flags |= (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY);
935 tex->key.numFaces = 6;
936 break;
937 case PIPE_TEXTURE_CUBE_ARRAY:
938 assert(svgascreen->sws->have_sm4_1);
939 tex->key.flags |= (SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY);
940 tex->key.numFaces = 1; // arraySize already includes the 6 faces
941 tex->key.arraySize = template->array_size;
942 break;
943 default:
944 break;
945 }
946 }
947 else {
948 switch (template->target) {
949 case PIPE_TEXTURE_3D:
950 tex->key.flags |= SVGA3D_SURFACE_VOLUME;
951 break;
952 case PIPE_TEXTURE_CUBE:
953 tex->key.flags |= SVGA3D_SURFACE_CUBEMAP;
954 tex->key.numFaces = 6;
955 break;
956 default:
957 break;
958 }
959 }
960
961 tex->key.cachable = 1;
962
963 if ((bindings & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL)) &&
964 !(bindings & PIPE_BIND_SAMPLER_VIEW)) {
965 /* Also check if the format can be sampled from */
966 if (screen->is_format_supported(screen, template->format,
967 template->target,
968 template->nr_samples,
969 template->nr_storage_samples,
970 PIPE_BIND_SAMPLER_VIEW)) {
971 bindings |= PIPE_BIND_SAMPLER_VIEW;
972 }
973 }
974
975 if (bindings & PIPE_BIND_SAMPLER_VIEW) {
976 tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE;
977 tex->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
978
979 if (!(bindings & PIPE_BIND_RENDER_TARGET)) {
980 /* Also check if the format is color renderable */
981 if (screen->is_format_supported(screen, template->format,
982 template->target,
983 template->nr_samples,
984 template->nr_storage_samples,
985 PIPE_BIND_RENDER_TARGET)) {
986 bindings |= PIPE_BIND_RENDER_TARGET;
987 }
988 }
989
990 if (!(bindings & PIPE_BIND_DEPTH_STENCIL)) {
991 /* Also check if the format is depth/stencil renderable */
992 if (screen->is_format_supported(screen, template->format,
993 template->target,
994 template->nr_samples,
995 template->nr_storage_samples,
996 PIPE_BIND_DEPTH_STENCIL)) {
997 bindings |= PIPE_BIND_DEPTH_STENCIL;
998 }
999 }
1000 }
1001
1002 if (bindings & PIPE_BIND_DISPLAY_TARGET) {
1003 tex->key.cachable = 0;
1004 }
1005
1006 if (bindings & PIPE_BIND_SHARED) {
1007 tex->key.cachable = 0;
1008 }
1009
1010 if (bindings & (PIPE_BIND_SCANOUT | PIPE_BIND_CURSOR)) {
1011 tex->key.scanout = 1;
1012 tex->key.cachable = 0;
1013 }
1014
1015 /*
1016 * Note: Previously we never passed the
1017 * SVGA3D_SURFACE_HINT_RENDERTARGET hint. Mesa cannot
1018 * know beforehand whether a texture will be used as a rendertarget or not
1019 * and it always requests PIPE_BIND_RENDER_TARGET, therefore
1020 * passing the SVGA3D_SURFACE_HINT_RENDERTARGET here defeats its purpose.
1021 *
1022 * However, this was changed since other gallium frontends
1023 * (XA for example) uses it accurately and certain device versions
1024 * relies on it in certain situations to render correctly.
1025 */
1026 if ((bindings & PIPE_BIND_RENDER_TARGET) &&
1027 !util_format_is_s3tc(template->format)) {
1028 tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
1029 tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET;
1030 }
1031
1032 if (bindings & PIPE_BIND_DEPTH_STENCIL) {
1033 tex->key.flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
1034 tex->key.flags |= SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
1035 }
1036
1037 tex->key.numMipLevels = template->last_level + 1;
1038
1039 tex->key.format = svga_translate_format(svgascreen, template->format,
1040 bindings);
1041 if (tex->key.format == SVGA3D_FORMAT_INVALID) {
1042 goto fail;
1043 }
1044
1045 bool use_typeless = false;
1046 if (svgascreen->sws->have_gl43) {
1047 /* Do not use typeless for SHARED, SCANOUT or DISPLAY_TARGET surfaces. */
1048 use_typeless = !(bindings & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT |
1049 PIPE_BIND_DISPLAY_TARGET));
1050 } else if (svgascreen->sws->have_vgpu10) {
1051 /* For VGPU10 device, use typeless formats only for sRGB and depth resources
1052 * if they do not have SHARED, SCANOUT or DISPLAY_TARGET bind flags
1053 */
1054 use_typeless = (util_format_is_srgb(template->format) ||
1055 format_has_depth(template->format)) &&
1056 !(bindings & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT |
1057 PIPE_BIND_DISPLAY_TARGET));
1058 }
1059
1060 if (use_typeless) {
1061 SVGA3dSurfaceFormat typeless = svga_typeless_format(tex->key.format);
1062 if (0) {
1063 debug_printf("Convert resource type %s -> %s (bind 0x%x)\n",
1064 svga_format_name(tex->key.format),
1065 svga_format_name(typeless),
1066 bindings);
1067 }
1068
1069 if (svga_format_is_uncompressed_snorm(tex->key.format)) {
1070 /* We can't normally render to snorm surfaces, but once we
1071 * substitute a typeless format, we can if the rendertarget view
1072 * is unorm. This can happen with GL_ARB_copy_image.
1073 */
1074 tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
1075 tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET;
1076 }
1077
1078 tex->key.format = typeless;
1079 }
1080
1081 if (svgascreen->sws->have_sm5 &&
1082 bindings & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET)) {
1083 if (template->nr_samples < 2 &&
1084 screen->is_format_supported(screen, template->format,
1085 template->target,
1086 template->nr_samples,
1087 template->nr_storage_samples,
1088 PIPE_BIND_SHADER_IMAGE)) {
1089 /* Any non multi-samples texture that can be used as a render target
1090 * or sampler view can be bound to an image unit.
1091 * So make sure to set the UAV flag here.
1092 */
1093 tex->key.flags |= SVGA3D_SURFACE_BIND_UAVIEW;
1094 }
1095 }
1096
1097 SVGA_DBG(DEBUG_DMA, "surface_create for texture\n");
1098 bool invalidated;
1099 tex->handle = svga_screen_surface_create(svgascreen, bindings,
1100 tex->b.usage,
1101 &invalidated, &tex->key);
1102 if (!tex->handle) {
1103 goto fail;
1104 }
1105 if (invalidated) {
1106 tex->surface_state = SVGA_SURFACE_STATE_INVALIDATED;
1107 } else {
1108 tex->surface_state = SVGA_SURFACE_STATE_CREATED;
1109 }
1110
1111 SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture)\n", tex->handle);
1112
1113 debug_reference(&tex->b.reference,
1114 (debug_reference_descriptor)debug_describe_resource, 0);
1115
1116 tex->size = util_resource_size(template);
1117
1118 /* Determine if texture upload buffer can be used to upload this texture */
1119 tex->can_use_upload = svga_texture_transfer_map_can_upload(svgascreen,
1120 &tex->b);
1121
1122 /* Initialize the backing resource cache */
1123 tex->backed_handle = NULL;
1124
1125 svgascreen->hud.total_resource_bytes += tex->size;
1126 svgascreen->hud.num_resources++;
1127
1128 SVGA_STATS_TIME_POP(svgascreen->sws);
1129
1130 return &tex->b;
1131
1132 fail:
1133 if (tex->dirty)
1134 FREE(tex->dirty);
1135 if (tex->defined)
1136 FREE(tex->defined);
1137 FREE(tex);
1138 fail_notex:
1139 SVGA_STATS_TIME_POP(svgascreen->sws);
1140 return NULL;
1141 }
1142
1143
1144 struct pipe_resource *
svga_texture_from_handle(struct pipe_screen * screen,const struct pipe_resource * template,struct winsys_handle * whandle)1145 svga_texture_from_handle(struct pipe_screen *screen,
1146 const struct pipe_resource *template,
1147 struct winsys_handle *whandle)
1148 {
1149 struct svga_winsys_screen *sws = svga_winsys_screen(screen);
1150 struct svga_screen *ss = svga_screen(screen);
1151 struct svga_winsys_surface *srf;
1152 struct svga_texture *tex;
1153 enum SVGA3dSurfaceFormat format = 0;
1154 assert(screen);
1155
1156 /* Only supports one type */
1157 if ((template->target != PIPE_TEXTURE_2D &&
1158 template->target != PIPE_TEXTURE_RECT) ||
1159 template->last_level != 0 ||
1160 template->depth0 != 1) {
1161 return NULL;
1162 }
1163
1164 srf = sws->surface_from_handle(sws, whandle, &format);
1165
1166 if (!srf)
1167 return NULL;
1168
1169 if (!svga_format_is_shareable(ss, template->format, format,
1170 template->bind, true))
1171 goto out_unref;
1172
1173 tex = CALLOC_STRUCT(svga_texture);
1174 if (!tex)
1175 goto out_unref;
1176
1177 tex->defined = CALLOC(template->depth0 * template->array_size,
1178 sizeof(tex->defined[0]));
1179 if (!tex->defined)
1180 goto out_no_defined;
1181
1182 tex->b = *template;
1183 pipe_reference_init(&tex->b.reference, 1);
1184 tex->b.screen = screen;
1185
1186 SVGA_DBG(DEBUG_DMA, "wrap surface sid %p\n", srf);
1187
1188 tex->key.cachable = 0;
1189 tex->key.format = format;
1190 tex->handle = srf;
1191
1192
1193 /* set bind flags for the imported texture handle according to the bind
1194 * flags in the template
1195 */
1196 if (template->bind & PIPE_BIND_RENDER_TARGET){
1197 tex->key.flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
1198 tex->key.flags |= SVGA3D_SURFACE_BIND_RENDER_TARGET;
1199 }
1200
1201 if (template->bind & PIPE_BIND_DEPTH_STENCIL) {
1202 tex->key.flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
1203 tex->key.flags |= SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
1204 }
1205
1206 if (template->bind & PIPE_BIND_SAMPLER_VIEW) {
1207 tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE;
1208 tex->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
1209 }
1210
1211 tex->dirty = CALLOC(1, sizeof(tex->dirty[0]));
1212 if (!tex->dirty)
1213 goto out_no_dirty;
1214
1215 tex->imported = true;
1216
1217 ss->hud.num_resources++;
1218
1219 return &tex->b;
1220
1221 out_no_dirty:
1222 FREE(tex->defined);
1223 out_no_defined:
1224 FREE(tex);
1225 out_unref:
1226 sws->surface_reference(sws, &srf, NULL);
1227 return NULL;
1228 }
1229
1230 bool
svga_texture_generate_mipmap(struct pipe_context * pipe,struct pipe_resource * pt,enum pipe_format format,unsigned base_level,unsigned last_level,unsigned first_layer,unsigned last_layer)1231 svga_texture_generate_mipmap(struct pipe_context *pipe,
1232 struct pipe_resource *pt,
1233 enum pipe_format format,
1234 unsigned base_level,
1235 unsigned last_level,
1236 unsigned first_layer,
1237 unsigned last_layer)
1238 {
1239 struct pipe_sampler_view templ, *psv;
1240 struct svga_pipe_sampler_view *sv;
1241 struct svga_context *svga = svga_context(pipe);
1242 struct svga_texture *tex = svga_texture(pt);
1243
1244 assert(svga_have_vgpu10(svga));
1245
1246 /* Fallback to the mipmap generation utility for those formats that
1247 * do not support hw generate mipmap
1248 */
1249 if (!svga_format_support_gen_mips(format))
1250 return false;
1251
1252 /* Make sure the texture surface was created with
1253 * SVGA3D_SURFACE_BIND_RENDER_TARGET
1254 */
1255 if (!tex->handle || !(tex->key.flags & SVGA3D_SURFACE_BIND_RENDER_TARGET))
1256 return false;
1257
1258 templ.format = format;
1259 templ.target = pt->target;
1260 templ.u.tex.first_layer = first_layer;
1261 templ.u.tex.last_layer = last_layer;
1262 templ.u.tex.first_level = base_level;
1263 templ.u.tex.last_level = last_level;
1264
1265 if (pt->target == PIPE_TEXTURE_CUBE) {
1266 /**
1267 * state tracker generates mipmap one face at a time.
1268 * But SVGA generates mipmap for the entire cubemap.
1269 */
1270 templ.u.tex.first_layer = 0;
1271 templ.u.tex.last_layer = 5;
1272 }
1273
1274 psv = pipe->create_sampler_view(pipe, pt, &templ);
1275 if (psv == NULL)
1276 return false;
1277
1278 sv = svga_pipe_sampler_view(psv);
1279 SVGA_RETRY(svga, svga_validate_pipe_sampler_view(svga, sv));
1280
1281 SVGA_RETRY(svga, SVGA3D_vgpu10_GenMips(svga->swc, sv->id, tex->handle));
1282 pipe_sampler_view_reference(&psv, NULL);
1283
1284 /* Mark the texture surface as RENDERED */
1285 svga_set_texture_rendered_to(tex);
1286
1287 svga->hud.num_generate_mipmap++;
1288
1289 return true;
1290 }
1291
1292
1293 /* texture upload buffer default size in bytes */
1294 #define TEX_UPLOAD_DEFAULT_SIZE (1024 * 1024)
1295
1296 /**
1297 * Create a texture upload buffer
1298 */
1299 bool
svga_texture_transfer_map_upload_create(struct svga_context * svga)1300 svga_texture_transfer_map_upload_create(struct svga_context *svga)
1301 {
1302 svga->tex_upload = u_upload_create(&svga->pipe, TEX_UPLOAD_DEFAULT_SIZE,
1303 PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, 0);
1304 if (svga->tex_upload)
1305 u_upload_disable_persistent(svga->tex_upload);
1306
1307 return svga->tex_upload != NULL;
1308 }
1309
1310
1311 /**
1312 * Destroy the texture upload buffer
1313 */
1314 void
svga_texture_transfer_map_upload_destroy(struct svga_context * svga)1315 svga_texture_transfer_map_upload_destroy(struct svga_context *svga)
1316 {
1317 u_upload_destroy(svga->tex_upload);
1318 }
1319
1320
1321 /**
1322 * Returns true if this transfer map request can use the upload buffer.
1323 */
1324 bool
svga_texture_transfer_map_can_upload(const struct svga_screen * svgascreen,const struct pipe_resource * texture)1325 svga_texture_transfer_map_can_upload(const struct svga_screen *svgascreen,
1326 const struct pipe_resource *texture)
1327 {
1328 if (svgascreen->sws->have_transfer_from_buffer_cmd == false)
1329 return false;
1330
1331 /* TransferFromBuffer command is not well supported with multi-samples surface */
1332 if (texture->nr_samples > 1)
1333 return false;
1334
1335 if (util_format_is_compressed(texture->format)) {
1336 /* XXX Need to take a closer look to see why texture upload
1337 * with 3D texture with compressed format fails
1338 */
1339 if (texture->target == PIPE_TEXTURE_3D)
1340 return false;
1341 }
1342 else if (texture->format == PIPE_FORMAT_R9G9B9E5_FLOAT) {
1343 return false;
1344 }
1345
1346 return true;
1347 }
1348
1349
1350 /**
1351 * Return TRUE if the same texture is bound to the specified
1352 * surface view and a backing resource is created for the surface view.
1353 */
1354 static bool
need_update_texture_resource(struct pipe_surface * surf,struct svga_texture * tex)1355 need_update_texture_resource(struct pipe_surface *surf,
1356 struct svga_texture *tex)
1357 {
1358 struct svga_texture *stex = svga_texture(surf->texture);
1359 struct svga_surface *s = svga_surface(surf);
1360
1361 return (stex == tex && s->handle != tex->handle);
1362 }
1363
1364
1365 /**
1366 * Make sure the texture resource is up-to-date. If the texture is
1367 * currently bound to a render target view and a backing resource is
1368 * created, we will need to update the original resource with the
1369 * changes in the backing resource.
1370 */
1371 static void
svga_validate_texture_resource(struct svga_context * svga,struct svga_texture * tex)1372 svga_validate_texture_resource(struct svga_context *svga,
1373 struct svga_texture *tex)
1374 {
1375 if (svga_was_texture_rendered_to(tex) == false)
1376 return;
1377
1378 if ((svga->state.hw_draw.has_backed_views == false) ||
1379 (tex->backed_handle == NULL))
1380 return;
1381
1382 struct pipe_surface *s;
1383 for (unsigned i = 0; i < svga->state.hw_clear.num_rendertargets; i++) {
1384 s = svga->state.hw_clear.rtv[i];
1385 if (s && need_update_texture_resource(s, tex))
1386 svga_propagate_surface(svga, s, true);
1387 }
1388
1389 s = svga->state.hw_clear.dsv;
1390 if (s && need_update_texture_resource(s, tex))
1391 svga_propagate_surface(svga, s, true);
1392 }
1393
1394
1395 /**
1396 * Use upload buffer for the transfer map request.
1397 */
1398 void *
svga_texture_transfer_map_upload(struct svga_context * svga,struct svga_transfer * st)1399 svga_texture_transfer_map_upload(struct svga_context *svga,
1400 struct svga_transfer *st)
1401 {
1402 struct pipe_resource *texture = st->base.resource;
1403 struct pipe_resource *tex_buffer = NULL;
1404 struct svga_texture *tex = svga_texture(texture);
1405 void *tex_map;
1406 unsigned nblocksx, nblocksy;
1407 unsigned offset;
1408 unsigned upload_size;
1409
1410 assert(svga->tex_upload);
1411
1412 /* Validate the texture resource in case there is any changes
1413 * in the backing resource that needs to be updated to the original
1414 * texture resource first before the transfer upload occurs, otherwise,
1415 * the later update from backing resource to original will overwrite the
1416 * changes in this transfer map update.
1417 */
1418 svga_validate_texture_resource(svga, tex);
1419
1420 st->upload.box.x = st->base.box.x;
1421 st->upload.box.y = st->base.box.y;
1422 st->upload.box.z = st->base.box.z;
1423 st->upload.box.w = st->base.box.width;
1424 st->upload.box.h = st->base.box.height;
1425 st->upload.box.d = st->base.box.depth;
1426 st->upload.nlayers = 1;
1427
1428 switch (texture->target) {
1429 case PIPE_TEXTURE_CUBE:
1430 st->upload.box.z = 0;
1431 break;
1432 case PIPE_TEXTURE_2D_ARRAY:
1433 case PIPE_TEXTURE_CUBE_ARRAY:
1434 st->upload.nlayers = st->base.box.depth;
1435 st->upload.box.z = 0;
1436 st->upload.box.d = 1;
1437 break;
1438 case PIPE_TEXTURE_1D_ARRAY:
1439 st->upload.nlayers = st->base.box.depth;
1440 st->upload.box.y = st->upload.box.z = 0;
1441 st->upload.box.d = 1;
1442 break;
1443 default:
1444 break;
1445 }
1446
1447 nblocksx = util_format_get_nblocksx(texture->format, st->base.box.width);
1448 nblocksy = util_format_get_nblocksy(texture->format, st->base.box.height);
1449
1450 st->base.stride = nblocksx * util_format_get_blocksize(texture->format);
1451 st->base.layer_stride = st->base.stride * nblocksy;
1452
1453 /* In order to use the TransferFromBuffer command to update the
1454 * texture content from the buffer, the layer stride for a multi-layers
1455 * surface needs to be in multiples of 16 bytes.
1456 */
1457 if (st->upload.nlayers > 1 && st->base.layer_stride & 15)
1458 return NULL;
1459
1460 upload_size = st->base.layer_stride * st->base.box.depth;
1461 upload_size = align(upload_size, 16);
1462
1463 #ifdef DEBUG
1464 if (util_format_is_compressed(texture->format)) {
1465 unsigned blockw, blockh, bytesPerBlock;
1466
1467 svga_format_size(tex->key.format, &blockw, &blockh, &bytesPerBlock);
1468
1469 /* dest box must start on block boundary */
1470 assert((st->base.box.x % blockw) == 0);
1471 assert((st->base.box.y % blockh) == 0);
1472 }
1473 #endif
1474
1475 /* If the upload size exceeds the default buffer size, the
1476 * upload buffer manager code will try to allocate a new buffer
1477 * with the new buffer size.
1478 */
1479 u_upload_alloc(svga->tex_upload, 0, upload_size, 16,
1480 &offset, &tex_buffer, &tex_map);
1481
1482 if (!tex_map) {
1483 return NULL;
1484 }
1485
1486 st->upload.buf = tex_buffer;
1487 st->upload.map = tex_map;
1488 st->upload.offset = offset;
1489
1490 return tex_map;
1491 }
1492
1493
1494 /**
1495 * Unmap upload map transfer request
1496 */
1497 void
svga_texture_transfer_unmap_upload(struct svga_context * svga,struct svga_transfer * st)1498 svga_texture_transfer_unmap_upload(struct svga_context *svga,
1499 struct svga_transfer *st)
1500 {
1501 struct svga_winsys_surface *srcsurf;
1502 struct svga_winsys_surface *dstsurf;
1503 struct pipe_resource *texture = st->base.resource;
1504 struct svga_texture *tex = svga_texture(texture);
1505 unsigned subResource;
1506 unsigned numMipLevels;
1507 unsigned i, layer;
1508 unsigned offset = st->upload.offset;
1509
1510 assert(svga->tex_upload);
1511 assert(st->upload.buf);
1512
1513 /* unmap the texture upload buffer */
1514 u_upload_unmap(svga->tex_upload);
1515
1516 srcsurf = svga_buffer_handle(svga, st->upload.buf, 0);
1517 dstsurf = svga_texture(texture)->handle;
1518 assert(dstsurf);
1519
1520 numMipLevels = texture->last_level + 1;
1521
1522 for (i = 0, layer = st->slice; i < st->upload.nlayers; i++, layer++) {
1523 subResource = layer * numMipLevels + st->base.level;
1524
1525 /* send a transferFromBuffer command to update the host texture surface */
1526 assert((offset & 15) == 0);
1527
1528 SVGA_RETRY(svga, SVGA3D_vgpu10_TransferFromBuffer(svga->swc, srcsurf,
1529 offset,
1530 st->base.stride,
1531 st->base.layer_stride,
1532 dstsurf, subResource,
1533 &st->upload.box));
1534 offset += st->base.layer_stride;
1535 }
1536
1537 /* Mark the texture surface state as RENDERED */
1538 svga_set_texture_rendered_to(tex);
1539
1540 pipe_resource_reference(&st->upload.buf, NULL);
1541 }
1542
1543 /**
1544 * Does the device format backing this surface have an
1545 * alpha channel?
1546 *
1547 * \param texture[in] The texture whose format we're querying
1548 * \return TRUE if the format has an alpha channel, FALSE otherwise
1549 *
1550 * For locally created textures, the device (svga) format is typically
1551 * identical to svga_format(texture->format), and we can use the gallium
1552 * format tests to determine whether the device format has an alpha channel
1553 * or not. However, for textures backed by imported svga surfaces that is
1554 * not always true, and we have to look at the SVGA3D utilities.
1555 */
1556 bool
svga_texture_device_format_has_alpha(struct pipe_resource * texture)1557 svga_texture_device_format_has_alpha(struct pipe_resource *texture)
1558 {
1559 /* the svga_texture() call below is invalid for PIPE_BUFFER resources */
1560 assert(texture->target != PIPE_BUFFER);
1561
1562 const struct svga3d_surface_desc *surf_desc =
1563 svga3dsurface_get_desc(svga_texture(texture)->key.format);
1564
1565 enum svga3d_block_desc block_desc = surf_desc->block_desc;
1566
1567 return !!((block_desc & SVGA3DBLOCKDESC_ALPHA) ||
1568 ((block_desc == SVGA3DBLOCKDESC_TYPELESS) &&
1569 (surf_desc->bitDepth.alpha > 0)));
1570 }
1571