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
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   enum pipe_error ret;
58   SVGA3dCopyBox box;
59
60   assert(svga_have_vgpu10(svga));
61
62   box.x = dst_x;
63   box.y = dst_y;
64   box.z = dst_z;
65   box.w = width;
66   box.h = height;
67   box.d = depth;
68   box.srcx = src_x;
69   box.srcy = src_y;
70   box.srcz = src_z;
71
72   ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc,
73                                      dst_handle, dstSubResource,
74                                      src_handle, srcSubResource, &box);
75   if (ret != PIPE_OK) {
76      svga_context_flush(svga, NULL);
77      ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc,
78                                         dst_handle, dstSubResource,
79                                         src_handle, srcSubResource, &box);
80      assert(ret == PIPE_OK);
81   }
82}
83
84
85void
86svga_texture_copy_handle(struct svga_context *svga,
87                         struct svga_winsys_surface *src_handle,
88                         unsigned src_x, unsigned src_y, unsigned src_z,
89                         unsigned src_level, unsigned src_layer,
90                         struct svga_winsys_surface *dst_handle,
91                         unsigned dst_x, unsigned dst_y, unsigned dst_z,
92                         unsigned dst_level, unsigned dst_layer,
93                         unsigned width, unsigned height, unsigned depth)
94{
95   struct svga_surface dst, src;
96   enum pipe_error ret;
97   SVGA3dCopyBox box, *boxes;
98
99   assert(svga);
100
101   src.handle = src_handle;
102   src.real_level = src_level;
103   src.real_layer = src_layer;
104   src.real_zslice = 0;
105
106   dst.handle = dst_handle;
107   dst.real_level = dst_level;
108   dst.real_layer = dst_layer;
109   dst.real_zslice = 0;
110
111   box.x = dst_x;
112   box.y = dst_y;
113   box.z = dst_z;
114   box.w = width;
115   box.h = height;
116   box.d = depth;
117   box.srcx = src_x;
118   box.srcy = src_y;
119   box.srcz = src_z;
120
121/*
122   SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
123            src_handle, src_level, src_x, src_y, src_z,
124            dst_handle, dst_level, dst_x, dst_y, dst_z);
125*/
126
127   ret = SVGA3D_BeginSurfaceCopy(svga->swc,
128                                 &src.base,
129                                 &dst.base,
130                                 &boxes, 1);
131   if (ret != PIPE_OK) {
132      svga_context_flush(svga, NULL);
133      ret = SVGA3D_BeginSurfaceCopy(svga->swc,
134                                    &src.base,
135                                    &dst.base,
136                                    &boxes, 1);
137      assert(ret == PIPE_OK);
138   }
139   *boxes = box;
140   SVGA_FIFOCommitAll(svga->swc);
141}
142
143
144/* A helper function to sync up the two surface handles.
145 */
146static void
147svga_texture_copy_handle_resource(struct svga_context *svga,
148                                  struct svga_texture *src_tex,
149                                  struct svga_winsys_surface *dst,
150                                  unsigned int numMipLevels,
151                                  unsigned int numLayers,
152                                  int zslice_pick,
153                                  unsigned int mipoffset,
154                                  unsigned int layeroffset)
155{
156   unsigned int i, j;
157   unsigned int zoffset = 0;
158
159   /* A negative zslice_pick implies zoffset at 0, and depth to copy is
160    * from the depth of the texture at the particular mipmap level.
161    */
162   if (zslice_pick >= 0)
163      zoffset = zslice_pick;
164
165   for (i = 0; i < numMipLevels; i++) {
166      unsigned int miplevel = i + mipoffset;
167
168      for (j = 0; j < numLayers; j++) {
169         if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) {
170            unsigned depth = (zslice_pick < 0 ?
171                              u_minify(src_tex->b.b.depth0, miplevel) : 1);
172
173            if (src_tex->b.b.nr_samples > 1) {
174               unsigned subResource = j * numMipLevels + i;
175               svga_texture_copy_region(svga, src_tex->handle,
176                                        subResource, 0, 0, zoffset,
177                                        dst, subResource, 0, 0, 0,
178                                        src_tex->b.b.width0, src_tex->b.b.height0, depth);
179            }
180            else {
181               svga_texture_copy_handle(svga,
182                                        src_tex->handle,
183                                        0, 0, zoffset,
184                                        miplevel,
185                                        j + layeroffset,
186                                        dst, 0, 0, 0, i, j,
187                                        u_minify(src_tex->b.b.width0, miplevel),
188                                        u_minify(src_tex->b.b.height0, miplevel),
189                                        depth);
190            }
191         }
192      }
193   }
194}
195
196
197struct svga_winsys_surface *
198svga_texture_view_surface(struct svga_context *svga,
199                          struct svga_texture *tex,
200                          unsigned bind_flags,
201                          SVGA3dSurfaceAllFlags flags,
202                          SVGA3dSurfaceFormat format,
203                          unsigned start_mip,
204                          unsigned num_mip,
205                          int layer_pick,
206                          unsigned num_layers,
207                          int zslice_pick,
208                          boolean cacheable,
209                          struct svga_host_surface_cache_key *key) /* OUT */
210{
211   struct svga_screen *ss = svga_screen(svga->pipe.screen);
212   struct svga_winsys_surface *handle = NULL;
213   boolean validated;
214   boolean needCopyResource;
215
216   SVGA_DBG(DEBUG_PERF,
217            "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
218            layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
219
220   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW);
221
222   key->flags = flags;
223   key->format = format;
224   key->numMipLevels = num_mip;
225   key->size.width = u_minify(tex->b.b.width0, start_mip);
226   key->size.height = u_minify(tex->b.b.height0, start_mip);
227   key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
228   key->cachable = 1;
229   key->arraySize = 1;
230   key->numFaces = 1;
231
232   /* single sample surface can be treated as non-multisamples surface */
233   key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
234
235   if (key->sampleCount > 1) {
236      assert(ss->sws->have_sm4_1);
237      key->flags |= SVGA3D_SURFACE_MULTISAMPLE;
238   }
239
240   if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
241      key->flags |= SVGA3D_SURFACE_CUBEMAP;
242      key->numFaces = 6;
243   } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
244              tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
245      key->arraySize = num_layers;
246   }
247
248   if (key->format == SVGA3D_FORMAT_INVALID) {
249      key->cachable = 0;
250      goto done;
251   }
252
253   if (cacheable && tex->backed_handle &&
254       memcmp(key, &tex->backed_key, sizeof *key) == 0) {
255      handle = tex->backed_handle;
256      needCopyResource = tex->backed_age < tex->age;
257   } else {
258      SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
259      handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
260                                          &validated, key);
261      needCopyResource = TRUE;
262
263      if (cacheable && !tex->backed_handle) {
264         tex->backed_handle = handle;
265         memcpy(&tex->backed_key, key, sizeof *key);
266      }
267   }
268
269   if (!handle) {
270      key->cachable = 0;
271      goto done;
272   }
273
274   SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
275
276   if (layer_pick < 0)
277      layer_pick = 0;
278
279   if (needCopyResource) {
280      svga_texture_copy_handle_resource(svga, tex, handle,
281                                        key->numMipLevels,
282                                        key->numFaces * key->arraySize,
283                                        zslice_pick, start_mip, layer_pick);
284      tex->backed_age = tex->age;
285   }
286
287done:
288   SVGA_STATS_TIME_POP(ss->sws);
289
290   return handle;
291}
292
293
294/**
295 * A helper function to create a surface view.
296 * The view boolean flag specifies whether svga_texture_view_surface()
297 * will be called to create a cloned surface and resource for the view.
298 */
299static struct pipe_surface *
300svga_create_surface_view(struct pipe_context *pipe,
301                         struct pipe_resource *pt,
302                         const struct pipe_surface *surf_tmpl,
303                         boolean view)
304{
305   struct svga_context *svga = svga_context(pipe);
306   struct svga_texture *tex = svga_texture(pt);
307   struct pipe_screen *screen = pipe->screen;
308   struct svga_screen *ss = svga_screen(screen);
309   struct svga_surface *s;
310   unsigned layer, zslice, bind;
311   unsigned nlayers = 1;
312   SVGA3dSurfaceAllFlags flags = 0;
313   SVGA3dSurfaceFormat format;
314   struct pipe_surface *retVal = NULL;
315
316   s = CALLOC_STRUCT(svga_surface);
317   if (!s)
318      return NULL;
319
320   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
321
322   if (pt->target == PIPE_TEXTURE_CUBE) {
323      layer = surf_tmpl->u.tex.first_layer;
324      zslice = 0;
325   }
326   else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
327            pt->target == PIPE_TEXTURE_2D_ARRAY ||
328            pt->target == PIPE_TEXTURE_CUBE_ARRAY) {
329      layer = surf_tmpl->u.tex.first_layer;
330      zslice = 0;
331      nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
332   }
333   else {
334      layer = 0;
335      zslice = surf_tmpl->u.tex.first_layer;
336   }
337
338   pipe_reference_init(&s->base.reference, 1);
339   pipe_resource_reference(&s->base.texture, pt);
340   s->base.context = pipe;
341   s->base.format = surf_tmpl->format;
342   s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
343   s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
344   s->base.u.tex.level = surf_tmpl->u.tex.level;
345   s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
346   s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
347   s->view_id = SVGA3D_INVALID_ID;
348
349   s->backed = NULL;
350
351   if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
352      flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
353              SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
354      bind = PIPE_BIND_DEPTH_STENCIL;
355   }
356   else {
357      flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
358              SVGA3D_SURFACE_BIND_RENDER_TARGET;
359      bind = PIPE_BIND_RENDER_TARGET;
360   }
361
362   if (tex->imported) {
363      /* imported resource (a window) */
364      format = tex->key.format;
365      if (util_format_is_srgb(surf_tmpl->format)) {
366         /* sRGB rendering to window */
367         format = svga_linear_to_srgb(format);
368      }
369   }
370   else {
371      format = svga_translate_format(ss, surf_tmpl->format, bind);
372   }
373
374   assert(format != SVGA3D_FORMAT_INVALID);
375
376   if (view) {
377      SVGA_DBG(DEBUG_VIEWS,
378               "New backed surface view: resource %p, level %u layer %u z %u, %p\n",
379               pt, surf_tmpl->u.tex.level, layer, zslice, s);
380
381      if (svga_have_vgpu10(svga)) {
382         switch (pt->target) {
383         case PIPE_TEXTURE_1D:
384            flags |= SVGA3D_SURFACE_1D;
385            break;
386         case PIPE_TEXTURE_1D_ARRAY:
387            flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
388            break;
389         case PIPE_TEXTURE_2D_ARRAY:
390            flags |= SVGA3D_SURFACE_ARRAY;
391            break;
392         case PIPE_TEXTURE_3D:
393            flags |= SVGA3D_SURFACE_VOLUME;
394            break;
395         case PIPE_TEXTURE_CUBE:
396            if (nlayers == 6)
397               flags |= SVGA3D_SURFACE_CUBEMAP;
398            break;
399         case PIPE_TEXTURE_CUBE_ARRAY:
400            if (nlayers % 6 == 0)
401               flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY;
402            break;
403         default:
404            break;
405         }
406      }
407
408      /* When we clone the surface view resource, use the format used in
409       * the creation of the original resource.
410       */
411      s->handle = svga_texture_view_surface(svga, tex, bind, flags,
412                                            tex->key.format,
413                                            surf_tmpl->u.tex.level, 1,
414                                            layer, nlayers, zslice,
415                                            TRUE, &s->key);
416      if (!s->handle) {
417         FREE(s);
418         goto done;
419      }
420
421      s->key.format = format;
422      s->real_layer = 0;
423      s->real_level = 0;
424      s->real_zslice = 0;
425   } else {
426      SVGA_DBG(DEBUG_VIEWS,
427               "New surface view: resource %p, level %u, layer %u, z %u, %p\n",
428               pt, surf_tmpl->u.tex.level, layer, zslice, s);
429
430      memset(&s->key, 0, sizeof s->key);
431      s->key.format = format;
432      s->handle = tex->handle;
433      s->real_layer = layer;
434      s->real_zslice = zslice;
435      s->real_level = surf_tmpl->u.tex.level;
436   }
437
438   svga->hud.num_surface_views++;
439   retVal = &s->base;
440
441done:
442   SVGA_STATS_TIME_POP(ss->sws);
443   return retVal;
444}
445
446
447static struct pipe_surface *
448svga_create_surface(struct pipe_context *pipe,
449                    struct pipe_resource *pt,
450                    const struct pipe_surface *surf_tmpl)
451{
452   struct svga_context *svga = svga_context(pipe);
453   struct pipe_screen *screen = pipe->screen;
454   struct pipe_surface *surf = NULL;
455   boolean view = FALSE;
456
457   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
458
459   if (svga_screen(screen)->debug.force_surface_view)
460      view = TRUE;
461
462   if (surf_tmpl->u.tex.level != 0 &&
463       svga_screen(screen)->debug.force_level_surface_view)
464      view = TRUE;
465
466   if (pt->target == PIPE_TEXTURE_3D)
467      view = TRUE;
468
469   if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
470      view = FALSE;
471
472   surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
473
474   SVGA_STATS_TIME_POP(svga_sws(svga));
475
476   return surf;
477}
478
479
480/**
481 * Clone the surface view and its associated resource.
482 */
483static struct svga_surface *
484create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
485{
486   struct svga_texture *tex = svga_texture(s->base.texture);
487
488   if (!s->backed) {
489      struct pipe_surface *backed_view;
490
491      SVGA_STATS_TIME_PUSH(svga_sws(svga),
492                           SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
493
494      backed_view = svga_create_surface_view(&svga->pipe,
495                                             &tex->b.b,
496                                             &s->base,
497                                             TRUE);
498      if (!backed_view)
499         goto done;
500
501      s->backed = svga_surface(backed_view);
502
503      SVGA_STATS_TIME_POP(svga_sws(svga));
504   }
505   else if (s->backed->age < tex->age) {
506      /*
507       * There is already an existing backing surface, but we still need to
508       * sync the backing resource if the original resource has been modified
509       * since the last copy.
510       */
511      struct svga_surface *bs = s->backed;
512      unsigned int layer, zslice;
513
514      assert(bs->handle);
515
516      switch (tex->b.b.target) {
517      case PIPE_TEXTURE_CUBE:
518      case PIPE_TEXTURE_CUBE_ARRAY:
519      case PIPE_TEXTURE_1D_ARRAY:
520      case PIPE_TEXTURE_2D_ARRAY:
521         layer = s->base.u.tex.first_layer;
522         zslice = 0;
523         break;
524      default:
525         layer = 0;
526         zslice = s->base.u.tex.first_layer;
527      }
528
529      svga_texture_copy_handle_resource(svga, tex, bs->handle,
530                                        bs->key.numMipLevels,
531                                        bs->key.numFaces * bs->key.arraySize,
532                                        zslice, s->base.u.tex.level, layer);
533   }
534
535   svga_mark_surface_dirty(&s->backed->base);
536   s->backed->age = tex->age;
537
538done:
539   return s->backed;
540}
541
542/**
543 * Create a DX RenderTarget/DepthStencil View for the given surface,
544 * if needed.
545 */
546struct pipe_surface *
547svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
548{
549   enum pipe_error ret = PIPE_OK;
550   enum pipe_shader_type shader;
551
552   assert(svga_have_vgpu10(svga));
553   assert(s);
554
555   SVGA_STATS_TIME_PUSH(svga_sws(svga),
556                        SVGA_STATS_TIME_VALIDATESURFACEVIEW);
557
558   /**
559    * DX spec explicitly specifies that no resource can be bound to a render
560    * target view and a shader resource view simultanously.
561    * So first check if the resource bound to this surface view collides with
562    * a sampler view. If so, then we will clone this surface view and its
563    * associated resource. We will then use the cloned surface view for
564    * render target.
565    */
566   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
567      if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
568         SVGA_DBG(DEBUG_VIEWS,
569                  "same resource used in shaderResource and renderTarget 0x%x\n",
570                  s->handle);
571         s = create_backed_surface_view(svga, s);
572
573         if (s)
574            svga->state.hw_draw.has_backed_views = TRUE;
575
576         /* s may be null here if the function failed */
577         break;
578      }
579   }
580
581   if (s && s->view_id == SVGA3D_INVALID_ID) {
582      SVGA3dResourceType resType;
583      SVGA3dRenderTargetViewDesc desc;
584      struct svga_texture *stex = svga_texture(s->base.texture);
585
586      if (stex->validated == FALSE) {
587         assert(stex->handle);
588
589         /* We are about to render into a surface that has not been validated.
590          * First invalidate the surface so that the device does not
591          * need to update the host-side copy with the invalid
592          * content when the associated mob is first bound to the surface.
593          */
594         if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) {
595            svga_context_flush(svga, NULL);
596            ret = svga->swc->surface_invalidate(svga->swc, stex->handle);
597            assert(ret == PIPE_OK);
598         }
599         stex->validated = TRUE;
600      }
601
602      desc.tex.mipSlice = s->real_level;
603      desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
604      desc.tex.arraySize =
605         s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
606
607      s->view_id = util_bitmask_add(svga->surface_view_id_bm);
608
609      resType = svga_resource_type(s->base.texture->target);
610
611      if (util_format_is_depth_or_stencil(s->base.format)) {
612         ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
613                                                    s->view_id,
614                                                    s->handle,
615                                                    s->key.format,
616                                                    resType,
617                                                    &desc);
618      }
619      else {
620         SVGA3dSurfaceFormat view_format = s->key.format;
621         const struct svga_texture *stex = svga_texture(s->base.texture);
622
623         /* Can't create RGBA render target view of a RGBX surface so adjust
624          * the view format.  We do something similar for texture samplers in
625          * svga_validate_pipe_sampler_view().
626          */
627         if (view_format == SVGA3D_B8G8R8A8_UNORM &&
628             (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
629              stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
630            view_format = SVGA3D_B8G8R8X8_UNORM;
631         }
632
633         ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
634                                                    s->view_id,
635                                                    s->handle,
636                                                    view_format,
637                                                    resType,
638                                                    &desc);
639      }
640
641      if (ret != PIPE_OK) {
642         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
643         s->view_id = SVGA3D_INVALID_ID;
644         s = NULL;
645      }
646   }
647
648   SVGA_STATS_TIME_POP(svga_sws(svga));
649
650   return s ? &s->base : NULL;
651}
652
653
654
655static void
656svga_surface_destroy(struct pipe_context *pipe,
657                     struct pipe_surface *surf)
658{
659   struct svga_context *svga = svga_context(pipe);
660   struct svga_surface *s = svga_surface(surf);
661   struct svga_texture *t = svga_texture(surf->texture);
662   struct svga_screen *ss = svga_screen(surf->texture->screen);
663   enum pipe_error ret = PIPE_OK;
664
665   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
666
667   /* Destroy the backed view surface if it exists */
668   if (s->backed) {
669      svga_surface_destroy(pipe, &s->backed->base);
670      s->backed = NULL;
671   }
672
673   /* Destroy the surface handle if this is a backed handle and
674    * it is not being cached in the texture.
675    */
676   if (s->handle != t->handle && s->handle != t->backed_handle) {
677      SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
678      svga_screen_surface_destroy(ss, &s->key, &s->handle);
679   }
680
681   if (s->view_id != SVGA3D_INVALID_ID) {
682      unsigned try;
683
684      /* The SVGA3D device will generate a device error if the
685       * render target view or depth stencil view is destroyed from
686       * a context other than the one it was created with.
687       * Similar to shader resource view, in this case, we will skip
688       * the destroy for now.
689       */
690      if (surf->context != pipe) {
691         _debug_printf("context mismatch in %s\n", __func__);
692      }
693      else {
694         assert(svga_have_vgpu10(svga));
695         for (try = 0; try < 2; try++) {
696            if (util_format_is_depth_or_stencil(s->base.format)) {
697               ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
698            }
699            else {
700               ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
701            }
702            if (ret == PIPE_OK)
703               break;
704            svga_context_flush(svga, NULL);
705         }
706         assert(ret == PIPE_OK);
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.b.last_level + 1;
809      unsigned srcLevel = s->real_level;
810      unsigned dstLevel = surf->u.tex.level;
811      unsigned width = u_minify(tex->b.b.width0, dstLevel);
812      unsigned height = u_minify(tex->b.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