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