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 invalidated;
198   boolean needCopyResource;
199
200   SVGA_DBG(DEBUG_PERF,
201            "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
202            layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
203
204   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW);
205
206   key->flags = flags;
207   key->format = format;
208   key->numMipLevels = num_mip;
209   key->size.width = u_minify(tex->b.width0, start_mip);
210   key->size.height = u_minify(tex->b.height0, start_mip);
211   key->size.depth = zslice_pick < 0 ? u_minify(tex->b.depth0, start_mip) : 1;
212   key->cachable = 1;
213   key->arraySize = 1;
214   key->numFaces = 1;
215
216   /* single sample surface can be treated as non-multisamples surface */
217   key->sampleCount = tex->b.nr_samples > 1 ? tex->b.nr_samples : 0;
218
219   if (key->sampleCount > 1) {
220      assert(ss->sws->have_sm4_1);
221      key->flags |= SVGA3D_SURFACE_MULTISAMPLE;
222   }
223
224   if (tex->b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
225      key->flags |= SVGA3D_SURFACE_CUBEMAP;
226      key->numFaces = 6;
227   } else if (tex->b.target == PIPE_TEXTURE_1D_ARRAY ||
228              tex->b.target == PIPE_TEXTURE_2D_ARRAY) {
229      key->arraySize = num_layers;
230   }
231
232   if (key->format == SVGA3D_FORMAT_INVALID) {
233      key->cachable = 0;
234      goto done;
235   }
236
237   if (cacheable && tex->backed_handle &&
238       memcmp(key, &tex->backed_key, sizeof *key) == 0) {
239      handle = tex->backed_handle;
240      needCopyResource = tex->backed_age < tex->age;
241   } else {
242      SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
243      handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
244                                          &invalidated, key);
245      needCopyResource = TRUE;
246
247      if (cacheable && !tex->backed_handle) {
248         tex->backed_handle = handle;
249         memcpy(&tex->backed_key, key, sizeof *key);
250      }
251   }
252
253   if (!handle) {
254      key->cachable = 0;
255      goto done;
256   }
257
258   SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
259
260   if (layer_pick < 0)
261      layer_pick = 0;
262
263   if (needCopyResource) {
264      svga_texture_copy_handle_resource(svga, tex, handle,
265                                        key->numMipLevels,
266                                        key->numFaces * key->arraySize,
267                                        zslice_pick, start_mip, layer_pick);
268      tex->backed_age = tex->age;
269   }
270
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_COMPUTE; shader++) {
555      if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
556         SVGA_DBG(DEBUG_VIEWS,
557                  "same resource used in shaderResource and renderTarget 0x%x\n",
558                  s->handle);
559         s = create_backed_surface_view(svga, s, TRUE);
560
561         if (s)
562            svga->state.hw_draw.has_backed_views = TRUE;
563
564         /* s may be null here if the function failed */
565         break;
566      }
567   }
568
569   /**
570    * Create an alternate surface view for the specified context if the
571    * view was created for another context.
572    */
573   if (s && s->base.context != &svga->pipe) {
574      s = create_backed_surface_view(svga, s, FALSE);
575
576      if (s)
577         svga->state.hw_draw.has_backed_views = TRUE;
578   }
579
580   if (s && s->view_id == SVGA3D_INVALID_ID) {
581      SVGA3dResourceType resType;
582      SVGA3dRenderTargetViewDesc desc;
583      struct svga_texture *stex = svga_texture(s->base.texture);
584
585      if (stex->surface_state < SVGA_SURFACE_STATE_INVALIDATED) {
586         assert(stex->handle);
587
588         /* We are about to render into a surface that has not been validated.
589          * First invalidate the surface so that the device does not
590          * need to update the host-side copy with the invalid
591          * content when the associated mob is first bound to the surface.
592          */
593         SVGA_RETRY(svga, SVGA3D_InvalidateGBSurface(svga->swc, stex->handle));
594         stex->surface_state = SVGA_SURFACE_STATE_INVALIDATED;
595      }
596
597      desc.tex.mipSlice = s->real_level;
598      desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
599      desc.tex.arraySize =
600         s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
601
602      resType = svga_resource_type(s->base.texture->target);
603
604      if (util_format_is_depth_or_stencil(s->base.format)) {
605
606         /* Create depth stencil view only if the resource is created
607          * with depth stencil bind flag.
608          */
609         if (stex->key.flags & SVGA3D_SURFACE_BIND_DEPTH_STENCIL) {
610            s->view_id = util_bitmask_add(svga->surface_view_id_bm);
611            ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
612                                                       s->view_id,
613                                                       s->handle,
614                                                       s->key.format,
615                                                       resType,
616                                                       &desc);
617         }
618      }
619      else {
620         /* Create render target view only if the resource is created
621          * with render target bind flag.
622          */
623         if (stex->key.flags & SVGA3D_SURFACE_BIND_RENDER_TARGET) {
624            SVGA3dSurfaceFormat view_format = s->key.format;
625
626            /* Can't create RGBA render target view of a RGBX surface so adjust
627             * the view format.  We do something similar for texture samplers in
628             * svga_validate_pipe_sampler_view().
629             */
630            if (view_format == SVGA3D_B8G8R8A8_UNORM &&
631                (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
632                 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
633               view_format = SVGA3D_B8G8R8X8_UNORM;
634            }
635
636            s->view_id = util_bitmask_add(svga->surface_view_id_bm);
637            ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
638                                                       s->view_id,
639                                                       s->handle,
640                                                       view_format,
641                                                       resType,
642                                                       &desc);
643         }
644      }
645
646      if (ret != PIPE_OK) {
647         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
648         s->view_id = SVGA3D_INVALID_ID;
649         s = NULL;
650      }
651   }
652
653   SVGA_STATS_TIME_POP(svga_sws(svga));
654
655   return s ? &s->base : NULL;
656}
657
658
659
660static void
661svga_surface_destroy(struct pipe_context *pipe,
662                     struct pipe_surface *surf)
663{
664   struct svga_context *svga = svga_context(pipe);
665   struct svga_surface *s = svga_surface(surf);
666   struct svga_texture *t = svga_texture(surf->texture);
667   struct svga_screen *ss = svga_screen(surf->texture->screen);
668
669   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
670
671   /* Destroy the backed view surface if it exists */
672   if (s->backed) {
673      svga_surface_destroy(pipe, &s->backed->base);
674      s->backed = NULL;
675   }
676
677   /* Destroy the surface handle if this is a backed handle and
678    * it is not being cached in the texture.
679    */
680   if (s->handle != t->handle && s->handle != t->backed_handle) {
681      SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
682      svga_screen_surface_destroy(ss, &s->key,
683                                  svga_was_texture_rendered_to(t),
684                                  &s->handle);
685   }
686
687   if (s->view_id != SVGA3D_INVALID_ID) {
688      /* The SVGA3D device will generate a device error if the
689       * render target view or depth stencil view is destroyed from
690       * a context other than the one it was created with.
691       * Similar to shader resource view, in this case, we will skip
692       * the destroy for now.
693       */
694      if (surf->context != pipe) {
695         _debug_printf("context mismatch in %s\n", __func__);
696      }
697      else {
698         assert(svga_have_vgpu10(svga));
699         if (util_format_is_depth_or_stencil(s->base.format)) {
700            SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc,
701                                                                   s->view_id));
702         }
703         else {
704            SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc,
705                                                                   s->view_id));
706         }
707         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
708      }
709   }
710
711   pipe_resource_reference(&surf->texture, NULL);
712   FREE(surf);
713
714   svga->hud.num_surface_views--;
715   SVGA_STATS_TIME_POP(ss->sws);
716}
717
718
719static void
720svga_mark_surface_dirty(struct pipe_surface *surf)
721{
722   struct svga_surface *s = svga_surface(surf);
723   struct svga_texture *tex = svga_texture(surf->texture);
724
725   if (!s->dirty) {
726      s->dirty = TRUE;
727
728      if (s->handle == tex->handle) {
729         /* hmm so 3d textures always have all their slices marked ? */
730         svga_define_texture_level(tex, surf->u.tex.first_layer,
731                                   surf->u.tex.level);
732      }
733      else {
734         /* this will happen later in svga_propagate_surface */
735      }
736   }
737
738   /* Increment the view_age and texture age for this surface's mipmap
739    * level so that any sampler views into the texture are re-validated too.
740    * Note: we age the texture for backed surface view only when the
741    *       backed surface is propagated to the original surface.
742    */
743   if (s->handle == tex->handle)
744      svga_age_texture_view(tex, surf->u.tex.level);
745}
746
747
748void
749svga_mark_surfaces_dirty(struct svga_context *svga)
750{
751   unsigned i;
752   struct svga_hw_clear_state *hw = &svga->state.hw_clear;
753
754   if (svga_have_vgpu10(svga)) {
755
756      /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface.
757       * This surface can be the backed surface.
758       */
759      for (i = 0; i < hw->num_rendertargets; i++) {
760         if (hw->rtv[i])
761            svga_mark_surface_dirty(hw->rtv[i]);
762      }
763      if (hw->dsv)
764         svga_mark_surface_dirty(hw->dsv);
765   } else {
766      for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
767         if (svga->curr.framebuffer.cbufs[i])
768            svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
769      }
770      if (svga->curr.framebuffer.zsbuf)
771         svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
772   }
773}
774
775
776/**
777 * Progagate any changes from surfaces to texture.
778 * pipe is optional context to inline the blit command in.
779 */
780void
781svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
782                       boolean reset)
783{
784   struct svga_surface *s = svga_surface(surf);
785   struct svga_texture *tex = svga_texture(surf->texture);
786   struct svga_screen *ss = svga_screen(surf->texture->screen);
787
788   if (!s->dirty)
789      return;
790
791   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
792
793   /* Reset the dirty flag if specified. This is to ensure that
794    * the dirty flag will not be reset and stay unset when the backing
795    * surface is still being bound and rendered to.
796    * The reset flag will be set to TRUE when the surface is propagated
797    * and will be unbound.
798    */
799   s->dirty = !reset;
800
801   ss->texture_timestamp++;
802   svga_age_texture_view(tex, surf->u.tex.level);
803
804   if (s->handle != tex->handle) {
805      unsigned zslice, layer;
806      unsigned nlayers = 1;
807      unsigned i;
808      unsigned numMipLevels = tex->b.last_level + 1;
809      unsigned srcLevel = s->real_level;
810      unsigned dstLevel = surf->u.tex.level;
811      unsigned width = u_minify(tex->b.width0, dstLevel);
812      unsigned height = u_minify(tex->b.height0, dstLevel);
813
814      if (surf->texture->target == PIPE_TEXTURE_CUBE) {
815         zslice = 0;
816         layer = surf->u.tex.first_layer;
817      }
818      else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
819               surf->texture->target == PIPE_TEXTURE_2D_ARRAY ||
820               surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
821         zslice = 0;
822         layer = surf->u.tex.first_layer;
823         nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
824      }
825      else {
826         zslice = surf->u.tex.first_layer;
827         layer = 0;
828      }
829
830      SVGA_DBG(DEBUG_VIEWS,
831               "Propagate surface %p to resource %p, level %u\n",
832               surf, tex, surf->u.tex.level);
833
834      if (svga_have_vgpu10(svga)) {
835         unsigned srcSubResource, dstSubResource;
836
837         for (i = 0; i < nlayers; i++) {
838            srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel;
839            dstSubResource = (layer + i) * numMipLevels + dstLevel;
840
841            svga_texture_copy_region(svga,
842                                     s->handle, srcSubResource, 0, 0, 0,
843                                     tex->handle, dstSubResource, 0, 0, zslice,
844                                     width, height, 1);
845            svga_define_texture_level(tex, layer + i, dstLevel);
846         }
847      }
848      else {
849         for (i = 0; i < nlayers; i++) {
850            svga_texture_copy_handle(svga,
851                                     s->handle, 0, 0, 0, srcLevel,
852                                     s->real_layer + i,
853                                     tex->handle, 0, 0, zslice, dstLevel,
854                                     layer + i,
855                                     width, height, 1);
856
857            svga_define_texture_level(tex, layer + i, dstLevel);
858         }
859      }
860
861      /* Sync the surface view age with the texture age */
862      s->age = tex->age;
863
864      /* If this backed surface is cached in the texture,
865       * update the backed age as well.
866       */
867      if (tex->backed_handle == s->handle) {
868         tex->backed_age = tex->age;
869      }
870   }
871
872   SVGA_STATS_TIME_POP(ss->sws);
873}
874
875
876/**
877 * If any of the render targets are in backing texture views, propagate any
878 * changes to them back to the original texture.
879 */
880void
881svga_propagate_rendertargets(struct svga_context *svga)
882{
883   unsigned i;
884
885   /* Early exit if there is no backing texture views in use */
886   if (!svga->state.hw_draw.has_backed_views)
887      return;
888
889   /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
890    * not the svga->curr.framebuffer surfaces, because it's the former
891    * surfaces which may be backing surface views (the actual render targets).
892    */
893   for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) {
894      struct pipe_surface *s = svga->state.hw_clear.rtv[i];
895      if (s) {
896         svga_propagate_surface(svga, s, FALSE);
897      }
898   }
899
900   if (svga->state.hw_clear.dsv) {
901      svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE);
902   }
903}
904
905
906/**
907 * Check if we should call svga_propagate_surface on the surface.
908 */
909boolean
910svga_surface_needs_propagation(const struct pipe_surface *surf)
911{
912   const struct svga_surface *s = svga_surface_const(surf);
913   struct svga_texture *tex = svga_texture(surf->texture);
914
915   return s->dirty && s->handle != tex->handle;
916}
917
918
919static void
920svga_get_sample_position(struct pipe_context *context,
921                         unsigned sample_count, unsigned sample_index,
922                         float *pos_out)
923{
924   /* We can't actually query the device to learn the sample positions.
925    * These were grabbed from nvidia's driver.
926    */
927   static const float pos1[1][2] = {
928      { 0.5, 0.5 }
929   };
930   static const float pos2[2][2] = {
931      { 0.75, 0.75 },
932      { 0.25, 0.25 }
933   };
934   static const float pos4[4][2] = {
935      { 0.375000, 0.125000 },
936      { 0.875000, 0.375000 },
937      { 0.125000, 0.625000 },
938      { 0.625000, 0.875000 }
939   };
940   static const float pos8[8][2] = {
941      { 0.562500, 0.312500 },
942      { 0.437500, 0.687500 },
943      { 0.812500, 0.562500 },
944      { 0.312500, 0.187500 },
945      { 0.187500, 0.812500 },
946      { 0.062500, 0.437500 },
947      { 0.687500, 0.937500 },
948      { 0.937500, 0.062500 }
949   };
950   static const float pos16[16][2] = {
951      { 0.187500, 0.062500 },
952      { 0.437500, 0.187500 },
953      { 0.062500, 0.312500 },
954      { 0.312500, 0.437500 },
955      { 0.687500, 0.062500 },
956      { 0.937500, 0.187500 },
957      { 0.562500, 0.312500 },
958      { 0.812500, 0.437500 },
959      { 0.187500, 0.562500 },
960      { 0.437500, 0.687500 },
961      { 0.062500, 0.812500 },
962      { 0.312500, 0.937500 },
963      { 0.687500, 0.562500 },
964      { 0.937500, 0.687500 },
965      { 0.562500, 0.812500 },
966      { 0.812500, 0.937500 }
967   };
968   const float (*positions)[2];
969
970   switch (sample_count) {
971   case 2:
972      positions = pos2;
973      break;
974   case 4:
975      positions = pos4;
976      break;
977   case 8:
978      positions = pos8;
979      break;
980   case 16:
981      positions = pos16;
982      break;
983   default:
984      positions = pos1;
985   }
986
987   pos_out[0] = positions[sample_index][0];
988   pos_out[1] = positions[sample_index][1];
989}
990
991
992void
993svga_init_surface_functions(struct svga_context *svga)
994{
995   svga->pipe.create_surface = svga_create_surface;
996   svga->pipe.surface_destroy = svga_surface_destroy;
997   svga->pipe.get_sample_position = svga_get_sample_position;
998}
999