• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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