svga_surface.c revision 7ec681f3
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
45static void svga_mark_surface_dirty(struct pipe_surface *surf);
46
47void
48svga_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
77void
78svga_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 */
130static void
131svga_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
181struct svga_winsys_surface *
182svga_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 validated;
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                                          &validated, 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
271done:
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 */
283static struct pipe_surface *
284svga_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
425done:
426   SVGA_STATS_TIME_POP(ss->sws);
427   return retVal;
428}
429
430
431static struct pipe_surface *
432svga_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 */
467static struct svga_surface *
468create_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
526done:
527   return s->backed;
528}
529
530/**
531 * Create a DX RenderTarget/DepthStencil View for the given surface,
532 * if needed.
533 */
534struct pipe_surface *
535svga_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_TESS_EVAL; 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->validated == FALSE) {
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->validated = TRUE;
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      s->view_id = util_bitmask_add(svga->surface_view_id_bm);
603
604      resType = svga_resource_type(s->base.texture->target);
605
606      if (util_format_is_depth_or_stencil(s->base.format)) {
607         ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
608                                                    s->view_id,
609                                                    s->handle,
610                                                    s->key.format,
611                                                    resType,
612                                                    &desc);
613      }
614      else {
615         SVGA3dSurfaceFormat view_format = s->key.format;
616         const struct svga_texture *stex = svga_texture(s->base.texture);
617
618         /* Can't create RGBA render target view of a RGBX surface so adjust
619          * the view format.  We do something similar for texture samplers in
620          * svga_validate_pipe_sampler_view().
621          */
622         if (view_format == SVGA3D_B8G8R8A8_UNORM &&
623             (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
624              stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
625            view_format = SVGA3D_B8G8R8X8_UNORM;
626         }
627
628         ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
629                                                    s->view_id,
630                                                    s->handle,
631                                                    view_format,
632                                                    resType,
633                                                    &desc);
634      }
635
636      if (ret != PIPE_OK) {
637         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
638         s->view_id = SVGA3D_INVALID_ID;
639         s = NULL;
640      }
641   }
642
643   SVGA_STATS_TIME_POP(svga_sws(svga));
644
645   return s ? &s->base : NULL;
646}
647
648
649
650static void
651svga_surface_destroy(struct pipe_context *pipe,
652                     struct pipe_surface *surf)
653{
654   struct svga_context *svga = svga_context(pipe);
655   struct svga_surface *s = svga_surface(surf);
656   struct svga_texture *t = svga_texture(surf->texture);
657   struct svga_screen *ss = svga_screen(surf->texture->screen);
658
659   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
660
661   /* Destroy the backed view surface if it exists */
662   if (s->backed) {
663      svga_surface_destroy(pipe, &s->backed->base);
664      s->backed = NULL;
665   }
666
667   /* Destroy the surface handle if this is a backed handle and
668    * it is not being cached in the texture.
669    */
670   if (s->handle != t->handle && s->handle != t->backed_handle) {
671      SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
672      svga_screen_surface_destroy(ss, &s->key, &s->handle);
673   }
674
675   if (s->view_id != SVGA3D_INVALID_ID) {
676      /* The SVGA3D device will generate a device error if the
677       * render target view or depth stencil view is destroyed from
678       * a context other than the one it was created with.
679       * Similar to shader resource view, in this case, we will skip
680       * the destroy for now.
681       */
682      if (surf->context != pipe) {
683         _debug_printf("context mismatch in %s\n", __func__);
684      }
685      else {
686         assert(svga_have_vgpu10(svga));
687         if (util_format_is_depth_or_stencil(s->base.format)) {
688            SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc,
689                                                                   s->view_id));
690         }
691         else {
692            SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc,
693                                                                   s->view_id));
694         }
695         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
696      }
697   }
698
699   pipe_resource_reference(&surf->texture, NULL);
700   FREE(surf);
701
702   svga->hud.num_surface_views--;
703   SVGA_STATS_TIME_POP(ss->sws);
704}
705
706
707static void
708svga_mark_surface_dirty(struct pipe_surface *surf)
709{
710   struct svga_surface *s = svga_surface(surf);
711   struct svga_texture *tex = svga_texture(surf->texture);
712
713   if (!s->dirty) {
714      s->dirty = TRUE;
715
716      if (s->handle == tex->handle) {
717         /* hmm so 3d textures always have all their slices marked ? */
718         svga_define_texture_level(tex, surf->u.tex.first_layer,
719                                   surf->u.tex.level);
720      }
721      else {
722         /* this will happen later in svga_propagate_surface */
723      }
724   }
725
726   /* Increment the view_age and texture age for this surface's mipmap
727    * level so that any sampler views into the texture are re-validated too.
728    * Note: we age the texture for backed surface view only when the
729    *       backed surface is propagated to the original surface.
730    */
731   if (s->handle == tex->handle)
732      svga_age_texture_view(tex, surf->u.tex.level);
733}
734
735
736void
737svga_mark_surfaces_dirty(struct svga_context *svga)
738{
739   unsigned i;
740   struct svga_hw_clear_state *hw = &svga->state.hw_clear;
741
742   if (svga_have_vgpu10(svga)) {
743
744      /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface.
745       * This surface can be the backed surface.
746       */
747      for (i = 0; i < hw->num_rendertargets; i++) {
748         if (hw->rtv[i])
749            svga_mark_surface_dirty(hw->rtv[i]);
750      }
751      if (hw->dsv)
752         svga_mark_surface_dirty(hw->dsv);
753   } else {
754      for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
755         if (svga->curr.framebuffer.cbufs[i])
756            svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
757      }
758      if (svga->curr.framebuffer.zsbuf)
759         svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
760   }
761}
762
763
764/**
765 * Progagate any changes from surfaces to texture.
766 * pipe is optional context to inline the blit command in.
767 */
768void
769svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
770                       boolean reset)
771{
772   struct svga_surface *s = svga_surface(surf);
773   struct svga_texture *tex = svga_texture(surf->texture);
774   struct svga_screen *ss = svga_screen(surf->texture->screen);
775
776   if (!s->dirty)
777      return;
778
779   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
780
781   /* Reset the dirty flag if specified. This is to ensure that
782    * the dirty flag will not be reset and stay unset when the backing
783    * surface is still being bound and rendered to.
784    * The reset flag will be set to TRUE when the surface is propagated
785    * and will be unbound.
786    */
787   s->dirty = !reset;
788
789   ss->texture_timestamp++;
790   svga_age_texture_view(tex, surf->u.tex.level);
791
792   if (s->handle != tex->handle) {
793      unsigned zslice, layer;
794      unsigned nlayers = 1;
795      unsigned i;
796      unsigned numMipLevels = tex->b.last_level + 1;
797      unsigned srcLevel = s->real_level;
798      unsigned dstLevel = surf->u.tex.level;
799      unsigned width = u_minify(tex->b.width0, dstLevel);
800      unsigned height = u_minify(tex->b.height0, dstLevel);
801
802      if (surf->texture->target == PIPE_TEXTURE_CUBE) {
803         zslice = 0;
804         layer = surf->u.tex.first_layer;
805      }
806      else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
807               surf->texture->target == PIPE_TEXTURE_2D_ARRAY ||
808               surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
809         zslice = 0;
810         layer = surf->u.tex.first_layer;
811         nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
812      }
813      else {
814         zslice = surf->u.tex.first_layer;
815         layer = 0;
816      }
817
818      SVGA_DBG(DEBUG_VIEWS,
819               "Propagate surface %p to resource %p, level %u\n",
820               surf, tex, surf->u.tex.level);
821
822      if (svga_have_vgpu10(svga)) {
823         unsigned srcSubResource, dstSubResource;
824
825         for (i = 0; i < nlayers; i++) {
826            srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel;
827            dstSubResource = (layer + i) * numMipLevels + dstLevel;
828
829            svga_texture_copy_region(svga,
830                                     s->handle, srcSubResource, 0, 0, 0,
831                                     tex->handle, dstSubResource, 0, 0, zslice,
832                                     width, height, 1);
833            svga_define_texture_level(tex, layer + i, dstLevel);
834         }
835      }
836      else {
837         for (i = 0; i < nlayers; i++) {
838            svga_texture_copy_handle(svga,
839                                     s->handle, 0, 0, 0, srcLevel,
840                                     s->real_layer + i,
841                                     tex->handle, 0, 0, zslice, dstLevel,
842                                     layer + i,
843                                     width, height, 1);
844
845            svga_define_texture_level(tex, layer + i, dstLevel);
846         }
847      }
848
849      /* Sync the surface view age with the texture age */
850      s->age = tex->age;
851
852      /* If this backed surface is cached in the texture,
853       * update the backed age as well.
854       */
855      if (tex->backed_handle == s->handle) {
856         tex->backed_age = tex->age;
857      }
858   }
859
860   SVGA_STATS_TIME_POP(ss->sws);
861}
862
863
864/**
865 * If any of the render targets are in backing texture views, propagate any
866 * changes to them back to the original texture.
867 */
868void
869svga_propagate_rendertargets(struct svga_context *svga)
870{
871   unsigned i;
872
873   /* Early exit if there is no backing texture views in use */
874   if (!svga->state.hw_draw.has_backed_views)
875      return;
876
877   /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
878    * not the svga->curr.framebuffer surfaces, because it's the former
879    * surfaces which may be backing surface views (the actual render targets).
880    */
881   for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) {
882      struct pipe_surface *s = svga->state.hw_clear.rtv[i];
883      if (s) {
884         svga_propagate_surface(svga, s, FALSE);
885      }
886   }
887
888   if (svga->state.hw_clear.dsv) {
889      svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE);
890   }
891}
892
893
894/**
895 * Check if we should call svga_propagate_surface on the surface.
896 */
897boolean
898svga_surface_needs_propagation(const struct pipe_surface *surf)
899{
900   const struct svga_surface *s = svga_surface_const(surf);
901   struct svga_texture *tex = svga_texture(surf->texture);
902
903   return s->dirty && s->handle != tex->handle;
904}
905
906
907static void
908svga_get_sample_position(struct pipe_context *context,
909                         unsigned sample_count, unsigned sample_index,
910                         float *pos_out)
911{
912   /* We can't actually query the device to learn the sample positions.
913    * These were grabbed from nvidia's driver.
914    */
915   static const float pos1[1][2] = {
916      { 0.5, 0.5 }
917   };
918   static const float pos2[2][2] = {
919      { 0.75, 0.75 },
920      { 0.25, 0.25 }
921   };
922   static const float pos4[4][2] = {
923      { 0.375000, 0.125000 },
924      { 0.875000, 0.375000 },
925      { 0.125000, 0.625000 },
926      { 0.625000, 0.875000 }
927   };
928   static const float pos8[8][2] = {
929      { 0.562500, 0.312500 },
930      { 0.437500, 0.687500 },
931      { 0.812500, 0.562500 },
932      { 0.312500, 0.187500 },
933      { 0.187500, 0.812500 },
934      { 0.062500, 0.437500 },
935      { 0.687500, 0.937500 },
936      { 0.937500, 0.062500 }
937   };
938   static const float pos16[16][2] = {
939      { 0.187500, 0.062500 },
940      { 0.437500, 0.187500 },
941      { 0.062500, 0.312500 },
942      { 0.312500, 0.437500 },
943      { 0.687500, 0.062500 },
944      { 0.937500, 0.187500 },
945      { 0.562500, 0.312500 },
946      { 0.812500, 0.437500 },
947      { 0.187500, 0.562500 },
948      { 0.437500, 0.687500 },
949      { 0.062500, 0.812500 },
950      { 0.312500, 0.937500 },
951      { 0.687500, 0.562500 },
952      { 0.937500, 0.687500 },
953      { 0.562500, 0.812500 },
954      { 0.812500, 0.937500 }
955   };
956   const float (*positions)[2];
957
958   switch (sample_count) {
959   case 2:
960      positions = pos2;
961      break;
962   case 4:
963      positions = pos4;
964      break;
965   case 8:
966      positions = pos8;
967      break;
968   case 16:
969      positions = pos16;
970      break;
971   default:
972      positions = pos1;
973   }
974
975   pos_out[0] = positions[sample_index][0];
976   pos_out[1] = positions[sample_index][1];
977}
978
979
980void
981svga_init_surface_functions(struct svga_context *svga)
982{
983   svga->pipe.create_surface = svga_create_surface;
984   svga->pipe.surface_destroy = svga_surface_destroy;
985   svga->pipe.get_sample_position = svga_get_sample_position;
986}
987