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