• 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 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,struct svga_host_surface_cache_key * key)107 svga_texture_view_surface(struct svga_context *svga,
108                           struct svga_texture *tex,
109                           unsigned bind_flags,
110                           SVGA3dSurfaceFlags flags,
111                           SVGA3dSurfaceFormat format,
112                           unsigned start_mip,
113                           unsigned num_mip,
114                           int layer_pick,
115                           unsigned num_layers,
116                           int zslice_pick,
117                           struct svga_host_surface_cache_key *key) /* OUT */
118 {
119    struct svga_screen *ss = svga_screen(svga->pipe.screen);
120    struct svga_winsys_surface *handle;
121    uint32_t i, j;
122    unsigned z_offset = 0;
123    boolean validated;
124 
125    SVGA_DBG(DEBUG_PERF,
126             "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
127             layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
128 
129    key->flags = flags;
130    key->format = format;
131    key->numMipLevels = num_mip;
132    key->size.width = u_minify(tex->b.b.width0, start_mip);
133    key->size.height = u_minify(tex->b.b.height0, start_mip);
134    key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
135    key->cachable = 1;
136    key->arraySize = 1;
137    key->numFaces = 1;
138 
139    /* single sample surface can be treated as non-multisamples surface */
140    key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
141 
142    if (key->sampleCount > 1) {
143       key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
144    }
145 
146    if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
147       key->flags |= SVGA3D_SURFACE_CUBEMAP;
148       key->numFaces = 6;
149    } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
150               tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
151       key->arraySize = num_layers;
152    }
153 
154    if (key->format == SVGA3D_FORMAT_INVALID) {
155       key->cachable = 0;
156       return NULL;
157    }
158 
159    SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
160    handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
161                                        &validated, key);
162    if (!handle) {
163       key->cachable = 0;
164       return NULL;
165    }
166 
167    SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
168 
169    if (layer_pick < 0)
170       layer_pick = 0;
171 
172    if (zslice_pick >= 0)
173       z_offset = zslice_pick;
174 
175    for (i = 0; i < key->numMipLevels; i++) {
176       for (j = 0; j < key->numFaces * key->arraySize; j++) {
177          if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) {
178             unsigned depth = (zslice_pick < 0 ?
179                               u_minify(tex->b.b.depth0, i + start_mip) :
180                               1);
181 
182             svga_texture_copy_handle(svga,
183                                      tex->handle,
184                                      0, 0, z_offset,
185                                      i + start_mip,
186                                      j + layer_pick,
187                                      handle, 0, 0, 0, i, j,
188                                      u_minify(tex->b.b.width0, i + start_mip),
189                                      u_minify(tex->b.b.height0, i + start_mip),
190                                      depth);
191          }
192       }
193    }
194 
195    return handle;
196 }
197 
198 
199 /**
200  * A helper function to create a surface view.
201  * The view boolean flag specifies whether svga_texture_view_surface()
202  * will be called to create a cloned surface and resource for the view.
203  */
204 static struct pipe_surface *
svga_create_surface_view(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl,boolean view)205 svga_create_surface_view(struct pipe_context *pipe,
206                          struct pipe_resource *pt,
207                          const struct pipe_surface *surf_tmpl,
208                          boolean view)
209 {
210    struct svga_context *svga = svga_context(pipe);
211    struct svga_texture *tex = svga_texture(pt);
212    struct pipe_screen *screen = pipe->screen;
213    struct svga_screen *ss = svga_screen(screen);
214    struct svga_surface *s;
215    unsigned layer, zslice, bind;
216    unsigned nlayers = 1;
217    SVGA3dSurfaceFlags flags = 0;
218    SVGA3dSurfaceFormat format;
219    struct pipe_surface *retVal = NULL;
220 
221    s = CALLOC_STRUCT(svga_surface);
222    if (!s)
223       return NULL;
224 
225    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
226 
227    if (pt->target == PIPE_TEXTURE_CUBE) {
228       layer = surf_tmpl->u.tex.first_layer;
229       zslice = 0;
230    }
231    else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
232             pt->target == PIPE_TEXTURE_2D_ARRAY) {
233       layer = surf_tmpl->u.tex.first_layer;
234       zslice = 0;
235       nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
236    }
237    else {
238       layer = 0;
239       zslice = surf_tmpl->u.tex.first_layer;
240    }
241 
242    pipe_reference_init(&s->base.reference, 1);
243    pipe_resource_reference(&s->base.texture, pt);
244    s->base.context = pipe;
245    s->base.format = surf_tmpl->format;
246    s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
247    s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
248    s->base.u.tex.level = surf_tmpl->u.tex.level;
249    s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
250    s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
251    s->view_id = SVGA3D_INVALID_ID;
252 
253    s->backed = NULL;
254 
255    if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
256       flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
257               SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
258       bind = PIPE_BIND_DEPTH_STENCIL;
259    }
260    else {
261       flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
262               SVGA3D_SURFACE_BIND_RENDER_TARGET;
263       bind = PIPE_BIND_RENDER_TARGET;
264    }
265 
266    if (tex->imported)
267       format = tex->key.format;
268    else
269       format = svga_translate_format(ss, surf_tmpl->format, bind);
270 
271    assert(format != SVGA3D_FORMAT_INVALID);
272 
273    if (view) {
274       SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n",
275                pt, surf_tmpl->u.tex.level, layer, zslice, s);
276 
277       if (svga_have_vgpu10(svga)) {
278          switch (pt->target) {
279          case PIPE_TEXTURE_1D:
280             flags |= SVGA3D_SURFACE_1D;
281             break;
282          case PIPE_TEXTURE_1D_ARRAY:
283             flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
284             break;
285          case PIPE_TEXTURE_2D_ARRAY:
286             flags |= SVGA3D_SURFACE_ARRAY;
287             break;
288          case PIPE_TEXTURE_3D:
289             flags |= SVGA3D_SURFACE_VOLUME;
290             break;
291          case PIPE_TEXTURE_CUBE:
292             if (nlayers == 6)
293                flags |= SVGA3D_SURFACE_CUBEMAP;
294             break;
295          default:
296             break;
297          }
298       }
299 
300       /* When we clone the surface view resource, use the format used in
301        * the creation of the original resource.
302        */
303       s->handle = svga_texture_view_surface(svga, tex, bind, flags,
304                                             tex->key.format,
305                                             surf_tmpl->u.tex.level, 1,
306                                             layer, nlayers, zslice, &s->key);
307       if (!s->handle) {
308          FREE(s);
309          goto done;
310       }
311 
312       s->key.format = format;
313       s->real_layer = 0;
314       s->real_level = 0;
315       s->real_zslice = 0;
316    } else {
317       SVGA_DBG(DEBUG_VIEWS,
318                "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n",
319                pt, surf_tmpl->u.tex.level, layer, zslice, s);
320 
321       memset(&s->key, 0, sizeof s->key);
322       s->key.format = format;
323       s->handle = tex->handle;
324       s->real_layer = layer;
325       s->real_zslice = zslice;
326       s->real_level = surf_tmpl->u.tex.level;
327    }
328 
329    svga->hud.num_surface_views++;
330    retVal = &s->base;
331 
332 done:
333    SVGA_STATS_TIME_POP(ss->sws);
334    return retVal;
335 }
336 
337 
338 static struct pipe_surface *
svga_create_surface(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl)339 svga_create_surface(struct pipe_context *pipe,
340                     struct pipe_resource *pt,
341                     const struct pipe_surface *surf_tmpl)
342 {
343    struct svga_context *svga = svga_context(pipe);
344    struct pipe_screen *screen = pipe->screen;
345    struct pipe_surface *surf = NULL;
346    boolean view = FALSE;
347 
348    SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
349 
350    if (svga_screen(screen)->debug.force_surface_view)
351       view = TRUE;
352 
353    if (surf_tmpl->u.tex.level != 0 &&
354        svga_screen(screen)->debug.force_level_surface_view)
355       view = TRUE;
356 
357    if (pt->target == PIPE_TEXTURE_3D)
358       view = TRUE;
359 
360    if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
361       view = FALSE;
362 
363    surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
364 
365    SVGA_STATS_TIME_POP(svga_sws(svga));
366 
367    return surf;
368 }
369 
370 
371 /**
372  * Clone the surface view and its associated resource.
373  */
374 static struct svga_surface *
create_backed_surface_view(struct svga_context * svga,struct svga_surface * s)375 create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
376 {
377    SVGA_STATS_TIME_PUSH(svga_sws(svga),
378                         SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
379 
380    if (!s->backed) {
381       struct svga_texture *tex = svga_texture(s->base.texture);
382       struct pipe_surface *backed_view;
383 
384       backed_view = svga_create_surface_view(&svga->pipe,
385                                              &tex->b.b,
386                                              &s->base,
387                                              TRUE);
388       if (!backed_view)
389          return NULL;
390 
391       s->backed = svga_surface(backed_view);
392    }
393 
394    svga_mark_surface_dirty(&s->backed->base);
395 
396    SVGA_STATS_TIME_POP(svga_sws(svga));
397 
398    return s->backed;
399 }
400 
401 /**
402  * Create a DX RenderTarget/DepthStencil View for the given surface,
403  * if needed.
404  */
405 struct pipe_surface *
svga_validate_surface_view(struct svga_context * svga,struct svga_surface * s)406 svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
407 {
408    enum pipe_error ret = PIPE_OK;
409    enum pipe_shader_type shader;
410 
411    assert(svga_have_vgpu10(svga));
412    assert(s);
413 
414    SVGA_STATS_TIME_PUSH(svga_sws(svga),
415                         SVGA_STATS_TIME_VALIDATESURFACEVIEW);
416 
417    /**
418     * DX spec explicitly specifies that no resource can be bound to a render
419     * target view and a shader resource view simultanously.
420     * So first check if the resource bound to this surface view collides with
421     * a sampler view. If so, then we will clone this surface view and its
422     * associated resource. We will then use the cloned surface view for
423     * render target.
424     */
425    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
426       if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
427          SVGA_DBG(DEBUG_VIEWS,
428                   "same resource used in shaderResource and renderTarget 0x%x\n",
429                   s->handle);
430          s = create_backed_surface_view(svga, s);
431          /* s may be null here if the function failed */
432          break;
433       }
434    }
435 
436    if (s && s->view_id == SVGA3D_INVALID_ID) {
437       SVGA3dResourceType resType;
438       SVGA3dRenderTargetViewDesc desc;
439       struct svga_texture *stex = svga_texture(s->base.texture);
440 
441       if (stex->validated == FALSE) {
442          assert(stex->handle);
443 
444          /* We are about to render into a surface that has not been validated.
445           * First invalidate the surface so that the device does not
446           * need to update the host-side copy with the invalid
447           * content when the associated mob is first bound to the surface.
448           */
449          ret = SVGA3D_InvalidateGBSurface(svga->swc, stex->handle);
450          if (ret != PIPE_OK) {
451             s = NULL;
452             goto done;
453          }
454          stex->validated = TRUE;
455       }
456 
457       desc.tex.mipSlice = s->real_level;
458       desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
459       desc.tex.arraySize =
460          s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
461 
462       s->view_id = util_bitmask_add(svga->surface_view_id_bm);
463 
464       resType = svga_resource_type(s->base.texture->target);
465 
466       if (util_format_is_depth_or_stencil(s->base.format)) {
467          ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
468                                                     s->view_id,
469                                                     s->handle,
470                                                     s->key.format,
471                                                     resType,
472                                                     &desc);
473       }
474       else {
475          SVGA3dSurfaceFormat view_format = s->key.format;
476          const struct svga_texture *stex = svga_texture(s->base.texture);
477 
478          /* Can't create RGBA render target view of a RGBX surface so adjust
479           * the view format.  We do something similar for texture samplers in
480           * svga_validate_pipe_sampler_view().
481           */
482          if (view_format == SVGA3D_B8G8R8A8_UNORM &&
483              (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
484               stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
485             view_format = SVGA3D_B8G8R8X8_UNORM;
486          }
487 
488          ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
489                                                     s->view_id,
490                                                     s->handle,
491                                                     view_format,
492                                                     resType,
493                                                     &desc);
494       }
495 
496       if (ret != PIPE_OK) {
497          util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
498          s->view_id = SVGA3D_INVALID_ID;
499          s = NULL;
500       }
501    }
502 
503 done:
504    SVGA_STATS_TIME_POP(svga_sws(svga));
505 
506    return s ? &s->base : NULL;
507 }
508 
509 
510 
511 static void
svga_surface_destroy(struct pipe_context * pipe,struct pipe_surface * surf)512 svga_surface_destroy(struct pipe_context *pipe,
513                      struct pipe_surface *surf)
514 {
515    struct svga_context *svga = svga_context(pipe);
516    struct svga_surface *s = svga_surface(surf);
517    struct svga_texture *t = svga_texture(surf->texture);
518    struct svga_screen *ss = svga_screen(surf->texture->screen);
519    enum pipe_error ret = PIPE_OK;
520 
521    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
522 
523    /* Destroy the backed view surface if it exists */
524    if (s->backed) {
525       svga_surface_destroy(pipe, &s->backed->base);
526       s->backed = NULL;
527    }
528 
529    if (s->handle != t->handle) {
530       SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
531       svga_screen_surface_destroy(ss, &s->key, &s->handle);
532    }
533 
534    if (s->view_id != SVGA3D_INVALID_ID) {
535       unsigned try;
536 
537       assert(svga_have_vgpu10(svga));
538       for (try = 0; try < 2; try++) {
539          if (util_format_is_depth_or_stencil(s->base.format)) {
540             ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
541          }
542          else {
543             ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
544          }
545          if (ret == PIPE_OK)
546             break;
547          svga_context_flush(svga, NULL);
548       }
549       assert(ret == PIPE_OK);
550       util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
551    }
552 
553    pipe_resource_reference(&surf->texture, NULL);
554    FREE(surf);
555 
556    svga->hud.num_surface_views--;
557    SVGA_STATS_TIME_POP(ss->sws);
558 }
559 
560 
561 static void
svga_mark_surface_dirty(struct pipe_surface * surf)562 svga_mark_surface_dirty(struct pipe_surface *surf)
563 {
564    struct svga_surface *s = svga_surface(surf);
565    struct svga_texture *tex = svga_texture(surf->texture);
566 
567    if (!s->dirty) {
568       s->dirty = TRUE;
569 
570       if (s->handle == tex->handle) {
571          /* hmm so 3d textures always have all their slices marked ? */
572          svga_define_texture_level(tex, surf->u.tex.first_layer,
573                                    surf->u.tex.level);
574       }
575       else {
576          /* this will happen later in svga_propagate_surface */
577       }
578    }
579 
580    /* Increment the view_age and texture age for this surface's mipmap
581     * level so that any sampler views into the texture are re-validated too.
582     */
583    svga_age_texture_view(tex, surf->u.tex.level);
584 }
585 
586 
587 void
svga_mark_surfaces_dirty(struct svga_context * svga)588 svga_mark_surfaces_dirty(struct svga_context *svga)
589 {
590    unsigned i;
591 
592    for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
593       if (svga->curr.framebuffer.cbufs[i])
594          svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
595    }
596    if (svga->curr.framebuffer.zsbuf)
597       svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
598 }
599 
600 
601 /**
602  * Progagate any changes from surfaces to texture.
603  * pipe is optional context to inline the blit command in.
604  */
605 void
svga_propagate_surface(struct svga_context * svga,struct pipe_surface * surf)606 svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
607 {
608    struct svga_surface *s = svga_surface(surf);
609    struct svga_texture *tex = svga_texture(surf->texture);
610    struct svga_screen *ss = svga_screen(surf->texture->screen);
611 
612    if (!s->dirty)
613       return;
614 
615    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
616 
617    s->dirty = FALSE;
618    ss->texture_timestamp++;
619    svga_age_texture_view(tex, surf->u.tex.level);
620 
621    if (s->handle != tex->handle) {
622       unsigned zslice, layer;
623       unsigned nlayers = 1;
624       unsigned i;
625 
626       if (surf->texture->target == PIPE_TEXTURE_CUBE) {
627          zslice = 0;
628          layer = surf->u.tex.first_layer;
629       }
630       else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
631                surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
632          zslice = 0;
633          layer = surf->u.tex.first_layer;
634          nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
635       }
636       else {
637          zslice = surf->u.tex.first_layer;
638          layer = 0;
639       }
640 
641       SVGA_DBG(DEBUG_VIEWS,
642                "svga: Surface propagate: tex %p, level %u, from %p\n",
643                tex, surf->u.tex.level, surf);
644       for (i = 0; i < nlayers; i++) {
645          svga_texture_copy_handle(svga,
646                                   s->handle, 0, 0, 0, s->real_level,
647                                   s->real_layer + i,
648                                   tex->handle, 0, 0, zslice, surf->u.tex.level,
649                                   layer + i,
650                                   u_minify(tex->b.b.width0, surf->u.tex.level),
651                                   u_minify(tex->b.b.height0, surf->u.tex.level),
652                                   1);
653          svga_define_texture_level(tex, layer + i, surf->u.tex.level);
654       }
655    }
656 
657    SVGA_STATS_TIME_POP(ss->sws);
658 }
659 
660 
661 /**
662  * If any of the render targets are in backing texture views, propagate any
663  * changes to them back to the original texture.
664  */
665 void
svga_propagate_rendertargets(struct svga_context * svga)666 svga_propagate_rendertargets(struct svga_context *svga)
667 {
668    unsigned i;
669 
670    /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
671     * not the svga->curr.framebuffer surfaces, because it's the former
672     * surfaces which may be backing surface views (the actual render targets).
673     */
674    for (i = 0; i < svga->state.hw_draw.num_rendertargets; i++) {
675       struct pipe_surface *s = svga->state.hw_draw.rtv[i];
676       if (s) {
677          svga_propagate_surface(svga, s);
678       }
679    }
680 
681    if (svga->state.hw_draw.dsv) {
682       svga_propagate_surface(svga, svga->state.hw_draw.dsv);
683    }
684 }
685 
686 
687 /**
688  * Check if we should call svga_propagate_surface on the surface.
689  */
690 boolean
svga_surface_needs_propagation(const struct pipe_surface * surf)691 svga_surface_needs_propagation(const struct pipe_surface *surf)
692 {
693    const struct svga_surface *s = svga_surface_const(surf);
694    struct svga_texture *tex = svga_texture(surf->texture);
695 
696    return s->dirty && s->handle != tex->handle;
697 }
698 
699 
700 static void
svga_get_sample_position(struct pipe_context * context,unsigned sample_count,unsigned sample_index,float * pos_out)701 svga_get_sample_position(struct pipe_context *context,
702                          unsigned sample_count, unsigned sample_index,
703                          float *pos_out)
704 {
705    /* We can't actually query the device to learn the sample positions.
706     * These were grabbed from nvidia's driver.
707     */
708    static const float pos1[1][2] = {
709       { 0.5, 0.5 }
710    };
711    static const float pos4[4][2] = {
712       { 0.375000, 0.125000 },
713       { 0.875000, 0.375000 },
714       { 0.125000, 0.625000 },
715       { 0.625000, 0.875000 }
716    };
717    static const float pos8[8][2] = {
718       { 0.562500, 0.312500 },
719       { 0.437500, 0.687500 },
720       { 0.812500, 0.562500 },
721       { 0.312500, 0.187500 },
722       { 0.187500, 0.812500 },
723       { 0.062500, 0.437500 },
724       { 0.687500, 0.937500 },
725       { 0.937500, 0.062500 }
726    };
727    static const float pos16[16][2] = {
728       { 0.187500, 0.062500 },
729       { 0.437500, 0.187500 },
730       { 0.062500, 0.312500 },
731       { 0.312500, 0.437500 },
732       { 0.687500, 0.062500 },
733       { 0.937500, 0.187500 },
734       { 0.562500, 0.312500 },
735       { 0.812500, 0.437500 },
736       { 0.187500, 0.562500 },
737       { 0.437500, 0.687500 },
738       { 0.062500, 0.812500 },
739       { 0.312500, 0.937500 },
740       { 0.687500, 0.562500 },
741       { 0.937500, 0.687500 },
742       { 0.562500, 0.812500 },
743       { 0.812500, 0.937500 }
744    };
745    const float (*positions)[2];
746 
747    switch (sample_count) {
748    case 4:
749       positions = pos4;
750       break;
751    case 8:
752       positions = pos8;
753       break;
754    case 16:
755       positions = pos16;
756       break;
757    default:
758       positions = pos1;
759    }
760 
761    pos_out[0] = positions[sample_index][0];
762    pos_out[1] = positions[sample_index][1];
763 }
764 
765 
766 void
svga_init_surface_functions(struct svga_context * svga)767 svga_init_surface_functions(struct svga_context *svga)
768 {
769    svga->pipe.create_surface = svga_create_surface;
770    svga->pipe.surface_destroy = svga_surface_destroy;
771    svga->pipe.get_sample_position = svga_get_sample_position;
772 }
773