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