• 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 "svga_cmd.h"
27 
28 #include "pipe/p_state.h"
29 #include "pipe/p_defines.h"
30 #include "util/u_inlines.h"
31 #include "os/os_thread.h"
32 #include "util/u_bitmask.h"
33 #include "util/u_format.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
36 
37 #include "svga_format.h"
38 #include "svga_screen.h"
39 #include "svga_context.h"
40 #include "svga_sampler_view.h"
41 #include "svga_resource_texture.h"
42 #include "svga_surface.h"
43 #include "svga_debug.h"
44 
45 static void svga_mark_surface_dirty(struct pipe_surface *surf);
46 
47 void
svga_texture_copy_handle(struct svga_context * svga,struct svga_winsys_surface * src_handle,unsigned src_x,unsigned src_y,unsigned src_z,unsigned src_level,unsigned src_layer,struct svga_winsys_surface * dst_handle,unsigned dst_x,unsigned dst_y,unsigned dst_z,unsigned dst_level,unsigned dst_layer,unsigned width,unsigned height,unsigned depth)48 svga_texture_copy_handle(struct svga_context *svga,
49                          struct svga_winsys_surface *src_handle,
50                          unsigned src_x, unsigned src_y, unsigned src_z,
51                          unsigned src_level, unsigned src_layer,
52                          struct svga_winsys_surface *dst_handle,
53                          unsigned dst_x, unsigned dst_y, unsigned dst_z,
54                          unsigned dst_level, unsigned dst_layer,
55                          unsigned width, unsigned height, unsigned depth)
56 {
57    struct svga_surface dst, src;
58    enum pipe_error ret;
59    SVGA3dCopyBox box, *boxes;
60 
61    assert(svga);
62 
63    src.handle = src_handle;
64    src.real_level = src_level;
65    src.real_layer = src_layer;
66    src.real_zslice = 0;
67 
68    dst.handle = dst_handle;
69    dst.real_level = dst_level;
70    dst.real_layer = dst_layer;
71    dst.real_zslice = 0;
72 
73    box.x = dst_x;
74    box.y = dst_y;
75    box.z = dst_z;
76    box.w = width;
77    box.h = height;
78    box.d = depth;
79    box.srcx = src_x;
80    box.srcy = src_y;
81    box.srcz = src_z;
82 
83 /*
84    SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
85             src_handle, src_level, src_x, src_y, src_z,
86             dst_handle, dst_level, dst_x, dst_y, dst_z);
87 */
88 
89    ret = SVGA3D_BeginSurfaceCopy(svga->swc,
90                                  &src.base,
91                                  &dst.base,
92                                  &boxes, 1);
93    if (ret != PIPE_OK) {
94       svga_context_flush(svga, NULL);
95       ret = SVGA3D_BeginSurfaceCopy(svga->swc,
96                                     &src.base,
97                                     &dst.base,
98                                     &boxes, 1);
99       assert(ret == PIPE_OK);
100    }
101    *boxes = box;
102    SVGA_FIFOCommitAll(svga->swc);
103 }
104 
105 
106 /* A helper function to sync up the two surface handles.
107  */
108 static void
svga_texture_copy_handle_resource(struct svga_context * svga,struct svga_texture * src_tex,struct svga_winsys_surface * dst,unsigned int numMipLevels,unsigned int numLayers,int zslice_pick,unsigned int mipoffset,unsigned int layeroffset)109 svga_texture_copy_handle_resource(struct svga_context *svga,
110                                   struct svga_texture *src_tex,
111                                   struct svga_winsys_surface *dst,
112                                   unsigned int numMipLevels,
113                                   unsigned int numLayers,
114                                   int zslice_pick,
115                                   unsigned int mipoffset,
116                                   unsigned int layeroffset)
117 {
118    unsigned int i, j;
119    unsigned int zoffset = 0;
120 
121    /* A negative zslice_pick implies zoffset at 0, and depth to copy is
122     * from the depth of the texture at the particular mipmap level.
123     */
124    if (zslice_pick >= 0)
125       zoffset = zslice_pick;
126 
127    for (i = 0; i < numMipLevels; i++) {
128       unsigned int miplevel = i + mipoffset;
129 
130       for (j = 0; j < numLayers; j++) {
131          if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) {
132             unsigned depth = (zslice_pick < 0 ?
133                               u_minify(src_tex->b.b.depth0, miplevel) : 1);
134 
135             svga_texture_copy_handle(svga,
136                                      src_tex->handle,
137                                      0, 0, zoffset,
138                                      miplevel,
139                                      j + layeroffset,
140                                      dst, 0, 0, 0, i, j,
141                                      u_minify(src_tex->b.b.width0, miplevel),
142                                      u_minify(src_tex->b.b.height0, miplevel),
143                                      depth);
144          }
145       }
146    }
147 }
148 
149 
150 struct svga_winsys_surface *
svga_texture_view_surface(struct svga_context * svga,struct svga_texture * tex,unsigned bind_flags,SVGA3dSurfaceFlags flags,SVGA3dSurfaceFormat format,unsigned start_mip,unsigned num_mip,int layer_pick,unsigned num_layers,int zslice_pick,boolean cacheable,struct svga_host_surface_cache_key * key)151 svga_texture_view_surface(struct svga_context *svga,
152                           struct svga_texture *tex,
153                           unsigned bind_flags,
154                           SVGA3dSurfaceFlags flags,
155                           SVGA3dSurfaceFormat format,
156                           unsigned start_mip,
157                           unsigned num_mip,
158                           int layer_pick,
159                           unsigned num_layers,
160                           int zslice_pick,
161                           boolean cacheable,
162                           struct svga_host_surface_cache_key *key) /* OUT */
163 {
164    struct svga_screen *ss = svga_screen(svga->pipe.screen);
165    struct svga_winsys_surface *handle = NULL;
166    boolean validated;
167    boolean needCopyResource;
168 
169    SVGA_DBG(DEBUG_PERF,
170             "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
171             layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
172 
173    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW);
174 
175    key->flags = flags;
176    key->format = format;
177    key->numMipLevels = num_mip;
178    key->size.width = u_minify(tex->b.b.width0, start_mip);
179    key->size.height = u_minify(tex->b.b.height0, start_mip);
180    key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
181    key->cachable = 1;
182    key->arraySize = 1;
183    key->numFaces = 1;
184 
185    /* single sample surface can be treated as non-multisamples surface */
186    key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
187 
188    if (key->sampleCount > 1) {
189       key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
190    }
191 
192    if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
193       key->flags |= SVGA3D_SURFACE_CUBEMAP;
194       key->numFaces = 6;
195    } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
196               tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
197       key->arraySize = num_layers;
198    }
199 
200    if (key->format == SVGA3D_FORMAT_INVALID) {
201       key->cachable = 0;
202       goto done;
203    }
204 
205    if (cacheable && tex->backed_handle &&
206        memcmp(key, &tex->backed_key, sizeof *key) == 0) {
207       handle = tex->backed_handle;
208       needCopyResource = tex->backed_age < tex->age;
209    } else {
210       SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
211       handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
212                                           &validated, key);
213       needCopyResource = TRUE;
214 
215       if (cacheable && !tex->backed_handle) {
216          tex->backed_handle = handle;
217          memcpy(&tex->backed_key, key, sizeof *key);
218       }
219    }
220 
221    if (!handle) {
222       key->cachable = 0;
223       goto done;
224    }
225 
226    SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
227 
228    if (layer_pick < 0)
229       layer_pick = 0;
230 
231    if (needCopyResource) {
232       svga_texture_copy_handle_resource(svga, tex, handle,
233                                         key->numMipLevels,
234                                         key->numFaces * key->arraySize,
235                                         zslice_pick, start_mip, layer_pick);
236       tex->backed_age = tex->age;
237    }
238 
239 done:
240    SVGA_STATS_TIME_POP(ss->sws);
241 
242    return handle;
243 }
244 
245 
246 /**
247  * A helper function to create a surface view.
248  * The view boolean flag specifies whether svga_texture_view_surface()
249  * will be called to create a cloned surface and resource for the view.
250  */
251 static struct pipe_surface *
svga_create_surface_view(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl,boolean view)252 svga_create_surface_view(struct pipe_context *pipe,
253                          struct pipe_resource *pt,
254                          const struct pipe_surface *surf_tmpl,
255                          boolean view)
256 {
257    struct svga_context *svga = svga_context(pipe);
258    struct svga_texture *tex = svga_texture(pt);
259    struct pipe_screen *screen = pipe->screen;
260    struct svga_screen *ss = svga_screen(screen);
261    struct svga_surface *s;
262    unsigned layer, zslice, bind;
263    unsigned nlayers = 1;
264    SVGA3dSurfaceFlags flags = 0;
265    SVGA3dSurfaceFormat format;
266    struct pipe_surface *retVal = NULL;
267 
268    s = CALLOC_STRUCT(svga_surface);
269    if (!s)
270       return NULL;
271 
272    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
273 
274    if (pt->target == PIPE_TEXTURE_CUBE) {
275       layer = surf_tmpl->u.tex.first_layer;
276       zslice = 0;
277    }
278    else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
279             pt->target == PIPE_TEXTURE_2D_ARRAY) {
280       layer = surf_tmpl->u.tex.first_layer;
281       zslice = 0;
282       nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
283    }
284    else {
285       layer = 0;
286       zslice = surf_tmpl->u.tex.first_layer;
287    }
288 
289    pipe_reference_init(&s->base.reference, 1);
290    pipe_resource_reference(&s->base.texture, pt);
291    s->base.context = pipe;
292    s->base.format = surf_tmpl->format;
293    s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
294    s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
295    s->base.u.tex.level = surf_tmpl->u.tex.level;
296    s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
297    s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
298    s->view_id = SVGA3D_INVALID_ID;
299 
300    s->backed = NULL;
301 
302    if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
303       flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
304               SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
305       bind = PIPE_BIND_DEPTH_STENCIL;
306    }
307    else {
308       flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
309               SVGA3D_SURFACE_BIND_RENDER_TARGET;
310       bind = PIPE_BIND_RENDER_TARGET;
311    }
312 
313    if (tex->imported) {
314       /* imported resource (a window) */
315       format = tex->key.format;
316       if (util_format_is_srgb(surf_tmpl->format)) {
317          /* sRGB rendering to window */
318          format = svga_linear_to_srgb(format);
319       }
320    }
321    else {
322       format = svga_translate_format(ss, surf_tmpl->format, bind);
323    }
324 
325    assert(format != SVGA3D_FORMAT_INVALID);
326 
327    if (view) {
328       SVGA_DBG(DEBUG_VIEWS,
329                "New backed surface view: resource %p, level %u layer %u z %u, %p\n",
330                pt, surf_tmpl->u.tex.level, layer, zslice, s);
331 
332       if (svga_have_vgpu10(svga)) {
333          switch (pt->target) {
334          case PIPE_TEXTURE_1D:
335             flags |= SVGA3D_SURFACE_1D;
336             break;
337          case PIPE_TEXTURE_1D_ARRAY:
338             flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
339             break;
340          case PIPE_TEXTURE_2D_ARRAY:
341             flags |= SVGA3D_SURFACE_ARRAY;
342             break;
343          case PIPE_TEXTURE_3D:
344             flags |= SVGA3D_SURFACE_VOLUME;
345             break;
346          case PIPE_TEXTURE_CUBE:
347             if (nlayers == 6)
348                flags |= SVGA3D_SURFACE_CUBEMAP;
349             break;
350          default:
351             break;
352          }
353       }
354 
355       /* When we clone the surface view resource, use the format used in
356        * the creation of the original resource.
357        */
358       s->handle = svga_texture_view_surface(svga, tex, bind, flags,
359                                             tex->key.format,
360                                             surf_tmpl->u.tex.level, 1,
361                                             layer, nlayers, zslice,
362                                             TRUE, &s->key);
363       if (!s->handle) {
364          FREE(s);
365          goto done;
366       }
367 
368       s->key.format = format;
369       s->real_layer = 0;
370       s->real_level = 0;
371       s->real_zslice = 0;
372    } else {
373       SVGA_DBG(DEBUG_VIEWS,
374                "New surface view: resource %p, level %u, layer %u, z %u, %p\n",
375                pt, surf_tmpl->u.tex.level, layer, zslice, s);
376 
377       memset(&s->key, 0, sizeof s->key);
378       s->key.format = format;
379       s->handle = tex->handle;
380       s->real_layer = layer;
381       s->real_zslice = zslice;
382       s->real_level = surf_tmpl->u.tex.level;
383    }
384 
385    svga->hud.num_surface_views++;
386    retVal = &s->base;
387 
388 done:
389    SVGA_STATS_TIME_POP(ss->sws);
390    return retVal;
391 }
392 
393 
394 static struct pipe_surface *
svga_create_surface(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl)395 svga_create_surface(struct pipe_context *pipe,
396                     struct pipe_resource *pt,
397                     const struct pipe_surface *surf_tmpl)
398 {
399    struct svga_context *svga = svga_context(pipe);
400    struct pipe_screen *screen = pipe->screen;
401    struct pipe_surface *surf = NULL;
402    boolean view = FALSE;
403 
404    SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
405 
406    if (svga_screen(screen)->debug.force_surface_view)
407       view = TRUE;
408 
409    if (surf_tmpl->u.tex.level != 0 &&
410        svga_screen(screen)->debug.force_level_surface_view)
411       view = TRUE;
412 
413    if (pt->target == PIPE_TEXTURE_3D)
414       view = TRUE;
415 
416    if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
417       view = FALSE;
418 
419    surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
420 
421    SVGA_STATS_TIME_POP(svga_sws(svga));
422 
423    return surf;
424 }
425 
426 
427 /**
428  * Clone the surface view and its associated resource.
429  */
430 static struct svga_surface *
create_backed_surface_view(struct svga_context * svga,struct svga_surface * s)431 create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
432 {
433    struct svga_texture *tex = svga_texture(s->base.texture);
434 
435    if (!s->backed) {
436       struct pipe_surface *backed_view;
437 
438       SVGA_STATS_TIME_PUSH(svga_sws(svga),
439                            SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
440 
441       backed_view = svga_create_surface_view(&svga->pipe,
442                                              &tex->b.b,
443                                              &s->base,
444                                              TRUE);
445       if (!backed_view)
446          goto done;
447 
448       s->backed = svga_surface(backed_view);
449 
450       SVGA_STATS_TIME_POP(svga_sws(svga));
451    }
452    else if (s->backed->age < tex->age) {
453       /*
454        * There is already an existing backing surface, but we still need to
455        * sync the backing resource if the original resource has been modified
456        * since the last copy.
457        */
458       struct svga_surface *bs = s->backed;
459       unsigned int layer, zslice;
460 
461       assert(bs->handle);
462 
463       switch (tex->b.b.target) {
464       case PIPE_TEXTURE_CUBE:
465       case PIPE_TEXTURE_1D_ARRAY:
466       case PIPE_TEXTURE_2D_ARRAY:
467          layer = s->base.u.tex.first_layer;
468          zslice = 0;
469          break;
470       default:
471          layer = 0;
472          zslice = s->base.u.tex.first_layer;
473       }
474 
475       svga_texture_copy_handle_resource(svga, tex, bs->handle,
476                                         bs->key.numMipLevels,
477                                         bs->key.numFaces * bs->key.arraySize,
478                                         zslice, s->base.u.tex.level, layer);
479    }
480 
481    svga_mark_surface_dirty(&s->backed->base);
482    s->backed->age = tex->age;
483 
484 done:
485    return s->backed;
486 }
487 
488 /**
489  * Create a DX RenderTarget/DepthStencil View for the given surface,
490  * if needed.
491  */
492 struct pipe_surface *
svga_validate_surface_view(struct svga_context * svga,struct svga_surface * s)493 svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
494 {
495    enum pipe_error ret = PIPE_OK;
496    enum pipe_shader_type shader;
497 
498    assert(svga_have_vgpu10(svga));
499    assert(s);
500 
501    SVGA_STATS_TIME_PUSH(svga_sws(svga),
502                         SVGA_STATS_TIME_VALIDATESURFACEVIEW);
503 
504    /**
505     * DX spec explicitly specifies that no resource can be bound to a render
506     * target view and a shader resource view simultanously.
507     * So first check if the resource bound to this surface view collides with
508     * a sampler view. If so, then we will clone this surface view and its
509     * associated resource. We will then use the cloned surface view for
510     * render target.
511     */
512    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
513       if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
514          SVGA_DBG(DEBUG_VIEWS,
515                   "same resource used in shaderResource and renderTarget 0x%x\n",
516                   s->handle);
517          s = create_backed_surface_view(svga, s);
518 
519          if (s)
520             svga->state.hw_draw.has_backed_views = TRUE;
521 
522          /* s may be null here if the function failed */
523          break;
524       }
525    }
526 
527    if (s && s->view_id == SVGA3D_INVALID_ID) {
528       SVGA3dResourceType resType;
529       SVGA3dRenderTargetViewDesc desc;
530       struct svga_texture *stex = svga_texture(s->base.texture);
531 
532       if (stex->validated == FALSE) {
533          assert(stex->handle);
534 
535          /* We are about to render into a surface that has not been validated.
536           * First invalidate the surface so that the device does not
537           * need to update the host-side copy with the invalid
538           * content when the associated mob is first bound to the surface.
539           */
540          if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) {
541             svga_context_flush(svga, NULL);
542             ret = svga->swc->surface_invalidate(svga->swc, stex->handle);
543             assert(ret == PIPE_OK);
544          }
545          stex->validated = TRUE;
546       }
547 
548       desc.tex.mipSlice = s->real_level;
549       desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
550       desc.tex.arraySize =
551          s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
552 
553       s->view_id = util_bitmask_add(svga->surface_view_id_bm);
554 
555       resType = svga_resource_type(s->base.texture->target);
556 
557       if (util_format_is_depth_or_stencil(s->base.format)) {
558          ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
559                                                     s->view_id,
560                                                     s->handle,
561                                                     s->key.format,
562                                                     resType,
563                                                     &desc);
564       }
565       else {
566          SVGA3dSurfaceFormat view_format = s->key.format;
567          const struct svga_texture *stex = svga_texture(s->base.texture);
568 
569          /* Can't create RGBA render target view of a RGBX surface so adjust
570           * the view format.  We do something similar for texture samplers in
571           * svga_validate_pipe_sampler_view().
572           */
573          if (view_format == SVGA3D_B8G8R8A8_UNORM &&
574              (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
575               stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
576             view_format = SVGA3D_B8G8R8X8_UNORM;
577          }
578 
579          ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
580                                                     s->view_id,
581                                                     s->handle,
582                                                     view_format,
583                                                     resType,
584                                                     &desc);
585       }
586 
587       if (ret != PIPE_OK) {
588          util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
589          s->view_id = SVGA3D_INVALID_ID;
590          s = NULL;
591       }
592    }
593 
594    SVGA_STATS_TIME_POP(svga_sws(svga));
595 
596    return s ? &s->base : NULL;
597 }
598 
599 
600 
601 static void
svga_surface_destroy(struct pipe_context * pipe,struct pipe_surface * surf)602 svga_surface_destroy(struct pipe_context *pipe,
603                      struct pipe_surface *surf)
604 {
605    struct svga_context *svga = svga_context(pipe);
606    struct svga_surface *s = svga_surface(surf);
607    struct svga_texture *t = svga_texture(surf->texture);
608    struct svga_screen *ss = svga_screen(surf->texture->screen);
609    enum pipe_error ret = PIPE_OK;
610 
611    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
612 
613    /* Destroy the backed view surface if it exists */
614    if (s->backed) {
615       svga_surface_destroy(pipe, &s->backed->base);
616       s->backed = NULL;
617    }
618 
619    /* Destroy the surface handle if this is a backed handle and
620     * it is not being cached in the texture.
621     */
622    if (s->handle != t->handle && s->handle != t->backed_handle) {
623       SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
624       svga_screen_surface_destroy(ss, &s->key, &s->handle);
625    }
626 
627    if (s->view_id != SVGA3D_INVALID_ID) {
628       unsigned try;
629 
630       /* The SVGA3D device will generate a device error if the
631        * render target view or depth stencil view is destroyed from
632        * a context other than the one it was created with.
633        * Similar to shader resource view, in this case, we will skip
634        * the destroy for now.
635        */
636       if (surf->context != pipe) {
637          _debug_printf("context mismatch in %s\n", __func__);
638       }
639       else {
640          assert(svga_have_vgpu10(svga));
641          for (try = 0; try < 2; try++) {
642             if (util_format_is_depth_or_stencil(s->base.format)) {
643                ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
644             }
645             else {
646                ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
647             }
648             if (ret == PIPE_OK)
649                break;
650             svga_context_flush(svga, NULL);
651          }
652          assert(ret == PIPE_OK);
653          util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
654       }
655    }
656 
657    pipe_resource_reference(&surf->texture, NULL);
658    FREE(surf);
659 
660    svga->hud.num_surface_views--;
661    SVGA_STATS_TIME_POP(ss->sws);
662 }
663 
664 
665 static void
svga_mark_surface_dirty(struct pipe_surface * surf)666 svga_mark_surface_dirty(struct pipe_surface *surf)
667 {
668    struct svga_surface *s = svga_surface(surf);
669    struct svga_texture *tex = svga_texture(surf->texture);
670 
671    if (!s->dirty) {
672       s->dirty = TRUE;
673 
674       if (s->handle == tex->handle) {
675          /* hmm so 3d textures always have all their slices marked ? */
676          svga_define_texture_level(tex, surf->u.tex.first_layer,
677                                    surf->u.tex.level);
678       }
679       else {
680          /* this will happen later in svga_propagate_surface */
681       }
682    }
683 
684    /* Increment the view_age and texture age for this surface's mipmap
685     * level so that any sampler views into the texture are re-validated too.
686     * Note: we age the texture for backed surface view only when the
687     *       backed surface is propagated to the original surface.
688     */
689    if (s->handle == tex->handle)
690       svga_age_texture_view(tex, surf->u.tex.level);
691 }
692 
693 
694 void
svga_mark_surfaces_dirty(struct svga_context * svga)695 svga_mark_surfaces_dirty(struct svga_context *svga)
696 {
697    unsigned i;
698    struct svga_hw_clear_state *hw = &svga->state.hw_clear;
699 
700    if (svga_have_vgpu10(svga)) {
701 
702       /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface.
703        * This surface can be the backed surface.
704        */
705       for (i = 0; i < hw->num_rendertargets; i++) {
706          if (hw->rtv[i])
707             svga_mark_surface_dirty(hw->rtv[i]);
708       }
709       if (hw->dsv)
710          svga_mark_surface_dirty(hw->dsv);
711    } else {
712       for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
713          if (svga->curr.framebuffer.cbufs[i])
714             svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
715       }
716       if (svga->curr.framebuffer.zsbuf)
717          svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
718    }
719 }
720 
721 
722 /**
723  * Progagate any changes from surfaces to texture.
724  * pipe is optional context to inline the blit command in.
725  */
726 void
svga_propagate_surface(struct svga_context * svga,struct pipe_surface * surf,boolean reset)727 svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
728                        boolean reset)
729 {
730    struct svga_surface *s = svga_surface(surf);
731    struct svga_texture *tex = svga_texture(surf->texture);
732    struct svga_screen *ss = svga_screen(surf->texture->screen);
733 
734    if (!s->dirty)
735       return;
736 
737    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
738 
739    /* Reset the dirty flag if specified. This is to ensure that
740     * the dirty flag will not be reset and stay unset when the backing
741     * surface is still being bound and rendered to.
742     * The reset flag will be set to TRUE when the surface is propagated
743     * and will be unbound.
744     */
745    s->dirty = !reset;
746 
747    ss->texture_timestamp++;
748    svga_age_texture_view(tex, surf->u.tex.level);
749 
750    if (s->handle != tex->handle) {
751       unsigned zslice, layer;
752       unsigned nlayers = 1;
753       unsigned i;
754 
755       if (surf->texture->target == PIPE_TEXTURE_CUBE) {
756          zslice = 0;
757          layer = surf->u.tex.first_layer;
758       }
759       else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
760                surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
761          zslice = 0;
762          layer = surf->u.tex.first_layer;
763          nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
764       }
765       else {
766          zslice = surf->u.tex.first_layer;
767          layer = 0;
768       }
769 
770       SVGA_DBG(DEBUG_VIEWS,
771                "Propagate surface %p to resource %p, level %u\n",
772                surf, tex, surf->u.tex.level);
773       for (i = 0; i < nlayers; i++) {
774          svga_texture_copy_handle(svga,
775                                   s->handle, 0, 0, 0, s->real_level,
776                                   s->real_layer + i,
777                                   tex->handle, 0, 0, zslice, surf->u.tex.level,
778                                   layer + i,
779                                   u_minify(tex->b.b.width0, surf->u.tex.level),
780                                   u_minify(tex->b.b.height0, surf->u.tex.level),
781                                   1);
782          svga_define_texture_level(tex, layer + i, surf->u.tex.level);
783       }
784 
785       /* Sync the surface view age with the texture age */
786       s->age = tex->age;
787 
788       /* If this backed surface is cached in the texture,
789        * update the backed age as well.
790        */
791       if (tex->backed_handle == s->handle) {
792          tex->backed_age = tex->age;
793       }
794    }
795 
796    SVGA_STATS_TIME_POP(ss->sws);
797 }
798 
799 
800 /**
801  * If any of the render targets are in backing texture views, propagate any
802  * changes to them back to the original texture.
803  */
804 void
svga_propagate_rendertargets(struct svga_context * svga)805 svga_propagate_rendertargets(struct svga_context *svga)
806 {
807    unsigned i;
808 
809    /* Early exit if there is no backing texture views in use */
810    if (!svga->state.hw_draw.has_backed_views)
811       return;
812 
813    /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
814     * not the svga->curr.framebuffer surfaces, because it's the former
815     * surfaces which may be backing surface views (the actual render targets).
816     */
817    for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) {
818       struct pipe_surface *s = svga->state.hw_clear.rtv[i];
819       if (s) {
820          svga_propagate_surface(svga, s, FALSE);
821       }
822    }
823 
824    if (svga->state.hw_clear.dsv) {
825       svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE);
826    }
827 }
828 
829 
830 /**
831  * Check if we should call svga_propagate_surface on the surface.
832  */
833 boolean
svga_surface_needs_propagation(const struct pipe_surface * surf)834 svga_surface_needs_propagation(const struct pipe_surface *surf)
835 {
836    const struct svga_surface *s = svga_surface_const(surf);
837    struct svga_texture *tex = svga_texture(surf->texture);
838 
839    return s->dirty && s->handle != tex->handle;
840 }
841 
842 
843 static void
svga_get_sample_position(struct pipe_context * context,unsigned sample_count,unsigned sample_index,float * pos_out)844 svga_get_sample_position(struct pipe_context *context,
845                          unsigned sample_count, unsigned sample_index,
846                          float *pos_out)
847 {
848    /* We can't actually query the device to learn the sample positions.
849     * These were grabbed from nvidia's driver.
850     */
851    static const float pos1[1][2] = {
852       { 0.5, 0.5 }
853    };
854    static const float pos4[4][2] = {
855       { 0.375000, 0.125000 },
856       { 0.875000, 0.375000 },
857       { 0.125000, 0.625000 },
858       { 0.625000, 0.875000 }
859    };
860    static const float pos8[8][2] = {
861       { 0.562500, 0.312500 },
862       { 0.437500, 0.687500 },
863       { 0.812500, 0.562500 },
864       { 0.312500, 0.187500 },
865       { 0.187500, 0.812500 },
866       { 0.062500, 0.437500 },
867       { 0.687500, 0.937500 },
868       { 0.937500, 0.062500 }
869    };
870    static const float pos16[16][2] = {
871       { 0.187500, 0.062500 },
872       { 0.437500, 0.187500 },
873       { 0.062500, 0.312500 },
874       { 0.312500, 0.437500 },
875       { 0.687500, 0.062500 },
876       { 0.937500, 0.187500 },
877       { 0.562500, 0.312500 },
878       { 0.812500, 0.437500 },
879       { 0.187500, 0.562500 },
880       { 0.437500, 0.687500 },
881       { 0.062500, 0.812500 },
882       { 0.312500, 0.937500 },
883       { 0.687500, 0.562500 },
884       { 0.937500, 0.687500 },
885       { 0.562500, 0.812500 },
886       { 0.812500, 0.937500 }
887    };
888    const float (*positions)[2];
889 
890    switch (sample_count) {
891    case 4:
892       positions = pos4;
893       break;
894    case 8:
895       positions = pos8;
896       break;
897    case 16:
898       positions = pos16;
899       break;
900    default:
901       positions = pos1;
902    }
903 
904    pos_out[0] = positions[sample_index][0];
905    pos_out[1] = positions[sample_index][1];
906 }
907 
908 
909 void
svga_init_surface_functions(struct svga_context * svga)910 svga_init_surface_functions(struct svga_context *svga)
911 {
912    svga->pipe.create_surface = svga_create_surface;
913    svga->pipe.surface_destroy = svga_surface_destroy;
914    svga->pipe.get_sample_position = svga_get_sample_position;
915 }
916