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