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