1848b8605Smrg/**********************************************************
2848b8605Smrg * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person
5848b8605Smrg * obtaining a copy of this software and associated documentation
6848b8605Smrg * files (the "Software"), to deal in the Software without
7848b8605Smrg * restriction, including without limitation the rights to use, copy,
8848b8605Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies
9848b8605Smrg * of the Software, and to permit persons to whom the Software is
10848b8605Smrg * furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice shall be
13848b8605Smrg * included in all copies or substantial portions of the Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19848b8605Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20848b8605Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21848b8605Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22848b8605Smrg * SOFTWARE.
23848b8605Smrg *
24848b8605Smrg **********************************************************/
25848b8605Smrg
26848b8605Smrg#include "svga_cmd.h"
27848b8605Smrg
28848b8605Smrg#include "pipe/p_state.h"
29848b8605Smrg#include "pipe/p_defines.h"
30848b8605Smrg#include "util/u_inlines.h"
31848b8605Smrg#include "os/os_thread.h"
32b8e80941Smrg#include "util/u_bitmask.h"
33848b8605Smrg#include "util/u_format.h"
34848b8605Smrg#include "util/u_math.h"
35848b8605Smrg#include "util/u_memory.h"
36848b8605Smrg
37848b8605Smrg#include "svga_format.h"
38848b8605Smrg#include "svga_screen.h"
39848b8605Smrg#include "svga_context.h"
40b8e80941Smrg#include "svga_sampler_view.h"
41848b8605Smrg#include "svga_resource_texture.h"
42848b8605Smrg#include "svga_surface.h"
43848b8605Smrg#include "svga_debug.h"
44848b8605Smrg
45b8e80941Smrgstatic void svga_mark_surface_dirty(struct pipe_surface *surf);
46b8e80941Smrg
47b8e80941Smrgvoid
48b8e80941Smrgsvga_texture_copy_region(struct svga_context *svga,
49b8e80941Smrg                         struct svga_winsys_surface *src_handle,
50b8e80941Smrg                         unsigned srcSubResource,
51b8e80941Smrg                         unsigned src_x, unsigned src_y, unsigned src_z,
52b8e80941Smrg                         struct svga_winsys_surface *dst_handle,
53b8e80941Smrg                         unsigned dstSubResource,
54b8e80941Smrg                         unsigned dst_x, unsigned dst_y, unsigned dst_z,
55b8e80941Smrg                         unsigned width, unsigned height, unsigned depth)
56b8e80941Smrg{
57b8e80941Smrg   enum pipe_error ret;
58b8e80941Smrg   SVGA3dCopyBox box;
59b8e80941Smrg
60b8e80941Smrg   assert(svga_have_vgpu10(svga));
61b8e80941Smrg
62b8e80941Smrg   box.x = dst_x;
63b8e80941Smrg   box.y = dst_y;
64b8e80941Smrg   box.z = dst_z;
65b8e80941Smrg   box.w = width;
66b8e80941Smrg   box.h = height;
67b8e80941Smrg   box.d = depth;
68b8e80941Smrg   box.srcx = src_x;
69b8e80941Smrg   box.srcy = src_y;
70b8e80941Smrg   box.srcz = src_z;
71b8e80941Smrg
72b8e80941Smrg   ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc,
73b8e80941Smrg                                      dst_handle, dstSubResource,
74b8e80941Smrg                                      src_handle, srcSubResource, &box);
75b8e80941Smrg   if (ret != PIPE_OK) {
76b8e80941Smrg      svga_context_flush(svga, NULL);
77b8e80941Smrg      ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc,
78b8e80941Smrg                                         dst_handle, dstSubResource,
79b8e80941Smrg                                         src_handle, srcSubResource, &box);
80b8e80941Smrg      assert(ret == PIPE_OK);
81b8e80941Smrg   }
82b8e80941Smrg}
83b8e80941Smrg
84848b8605Smrg
85848b8605Smrgvoid
86848b8605Smrgsvga_texture_copy_handle(struct svga_context *svga,
87848b8605Smrg                         struct svga_winsys_surface *src_handle,
88848b8605Smrg                         unsigned src_x, unsigned src_y, unsigned src_z,
89b8e80941Smrg                         unsigned src_level, unsigned src_layer,
90848b8605Smrg                         struct svga_winsys_surface *dst_handle,
91848b8605Smrg                         unsigned dst_x, unsigned dst_y, unsigned dst_z,
92b8e80941Smrg                         unsigned dst_level, unsigned dst_layer,
93848b8605Smrg                         unsigned width, unsigned height, unsigned depth)
94848b8605Smrg{
95848b8605Smrg   struct svga_surface dst, src;
96848b8605Smrg   enum pipe_error ret;
97848b8605Smrg   SVGA3dCopyBox box, *boxes;
98848b8605Smrg
99848b8605Smrg   assert(svga);
100848b8605Smrg
101848b8605Smrg   src.handle = src_handle;
102848b8605Smrg   src.real_level = src_level;
103b8e80941Smrg   src.real_layer = src_layer;
104848b8605Smrg   src.real_zslice = 0;
105848b8605Smrg
106848b8605Smrg   dst.handle = dst_handle;
107848b8605Smrg   dst.real_level = dst_level;
108b8e80941Smrg   dst.real_layer = dst_layer;
109848b8605Smrg   dst.real_zslice = 0;
110848b8605Smrg
111848b8605Smrg   box.x = dst_x;
112848b8605Smrg   box.y = dst_y;
113848b8605Smrg   box.z = dst_z;
114848b8605Smrg   box.w = width;
115848b8605Smrg   box.h = height;
116848b8605Smrg   box.d = depth;
117848b8605Smrg   box.srcx = src_x;
118848b8605Smrg   box.srcy = src_y;
119848b8605Smrg   box.srcz = src_z;
120848b8605Smrg
121848b8605Smrg/*
122848b8605Smrg   SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
123848b8605Smrg            src_handle, src_level, src_x, src_y, src_z,
124848b8605Smrg            dst_handle, dst_level, dst_x, dst_y, dst_z);
125848b8605Smrg*/
126848b8605Smrg
127848b8605Smrg   ret = SVGA3D_BeginSurfaceCopy(svga->swc,
128848b8605Smrg                                 &src.base,
129848b8605Smrg                                 &dst.base,
130848b8605Smrg                                 &boxes, 1);
131848b8605Smrg   if (ret != PIPE_OK) {
132848b8605Smrg      svga_context_flush(svga, NULL);
133848b8605Smrg      ret = SVGA3D_BeginSurfaceCopy(svga->swc,
134848b8605Smrg                                    &src.base,
135848b8605Smrg                                    &dst.base,
136848b8605Smrg                                    &boxes, 1);
137848b8605Smrg      assert(ret == PIPE_OK);
138848b8605Smrg   }
139848b8605Smrg   *boxes = box;
140848b8605Smrg   SVGA_FIFOCommitAll(svga->swc);
141848b8605Smrg}
142848b8605Smrg
143848b8605Smrg
144b8e80941Smrg/* A helper function to sync up the two surface handles.
145b8e80941Smrg */
146b8e80941Smrgstatic void
147b8e80941Smrgsvga_texture_copy_handle_resource(struct svga_context *svga,
148b8e80941Smrg                                  struct svga_texture *src_tex,
149b8e80941Smrg                                  struct svga_winsys_surface *dst,
150b8e80941Smrg                                  unsigned int numMipLevels,
151b8e80941Smrg                                  unsigned int numLayers,
152b8e80941Smrg                                  int zslice_pick,
153b8e80941Smrg                                  unsigned int mipoffset,
154b8e80941Smrg                                  unsigned int layeroffset)
155b8e80941Smrg{
156b8e80941Smrg   unsigned int i, j;
157b8e80941Smrg   unsigned int zoffset = 0;
158b8e80941Smrg
159b8e80941Smrg   /* A negative zslice_pick implies zoffset at 0, and depth to copy is
160b8e80941Smrg    * from the depth of the texture at the particular mipmap level.
161b8e80941Smrg    */
162b8e80941Smrg   if (zslice_pick >= 0)
163b8e80941Smrg      zoffset = zslice_pick;
164b8e80941Smrg
165b8e80941Smrg   for (i = 0; i < numMipLevels; i++) {
166b8e80941Smrg      unsigned int miplevel = i + mipoffset;
167b8e80941Smrg
168b8e80941Smrg      for (j = 0; j < numLayers; j++) {
169b8e80941Smrg         if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) {
170b8e80941Smrg            unsigned depth = (zslice_pick < 0 ?
171b8e80941Smrg                              u_minify(src_tex->b.b.depth0, miplevel) : 1);
172b8e80941Smrg
173b8e80941Smrg            if (src_tex->b.b.nr_samples > 1) {
174b8e80941Smrg               unsigned subResource = j * numMipLevels + i;
175b8e80941Smrg               svga_texture_copy_region(svga, src_tex->handle,
176b8e80941Smrg                                        subResource, 0, 0, zoffset,
177b8e80941Smrg                                        dst, subResource, 0, 0, 0,
178b8e80941Smrg                                        src_tex->b.b.width0, src_tex->b.b.height0, depth);
179b8e80941Smrg            }
180b8e80941Smrg            else {
181b8e80941Smrg               svga_texture_copy_handle(svga,
182b8e80941Smrg                                        src_tex->handle,
183b8e80941Smrg                                        0, 0, zoffset,
184b8e80941Smrg                                        miplevel,
185b8e80941Smrg                                        j + layeroffset,
186b8e80941Smrg                                        dst, 0, 0, 0, i, j,
187b8e80941Smrg                                        u_minify(src_tex->b.b.width0, miplevel),
188b8e80941Smrg                                        u_minify(src_tex->b.b.height0, miplevel),
189b8e80941Smrg                                        depth);
190b8e80941Smrg            }
191b8e80941Smrg         }
192b8e80941Smrg      }
193b8e80941Smrg   }
194b8e80941Smrg}
195b8e80941Smrg
196b8e80941Smrg
197848b8605Smrgstruct svga_winsys_surface *
198848b8605Smrgsvga_texture_view_surface(struct svga_context *svga,
199848b8605Smrg                          struct svga_texture *tex,
200b8e80941Smrg                          unsigned bind_flags,
201b8e80941Smrg                          SVGA3dSurfaceAllFlags flags,
202848b8605Smrg                          SVGA3dSurfaceFormat format,
203848b8605Smrg                          unsigned start_mip,
204848b8605Smrg                          unsigned num_mip,
205b8e80941Smrg                          int layer_pick,
206b8e80941Smrg                          unsigned num_layers,
207848b8605Smrg                          int zslice_pick,
208b8e80941Smrg                          boolean cacheable,
209848b8605Smrg                          struct svga_host_surface_cache_key *key) /* OUT */
210848b8605Smrg{
211848b8605Smrg   struct svga_screen *ss = svga_screen(svga->pipe.screen);
212b8e80941Smrg   struct svga_winsys_surface *handle = NULL;
213b8e80941Smrg   boolean validated;
214b8e80941Smrg   boolean needCopyResource;
215848b8605Smrg
216b8e80941Smrg   SVGA_DBG(DEBUG_PERF,
217b8e80941Smrg            "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
218b8e80941Smrg            layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
219b8e80941Smrg
220b8e80941Smrg   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW);
221848b8605Smrg
222848b8605Smrg   key->flags = flags;
223848b8605Smrg   key->format = format;
224848b8605Smrg   key->numMipLevels = num_mip;
225848b8605Smrg   key->size.width = u_minify(tex->b.b.width0, start_mip);
226848b8605Smrg   key->size.height = u_minify(tex->b.b.height0, start_mip);
227848b8605Smrg   key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
228848b8605Smrg   key->cachable = 1;
229b8e80941Smrg   key->arraySize = 1;
230b8e80941Smrg   key->numFaces = 1;
231b8e80941Smrg
232b8e80941Smrg   /* single sample surface can be treated as non-multisamples surface */
233b8e80941Smrg   key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
234b8e80941Smrg
235b8e80941Smrg   if (key->sampleCount > 1) {
236b8e80941Smrg      assert(ss->sws->have_sm4_1);
237b8e80941Smrg      key->flags |= SVGA3D_SURFACE_MULTISAMPLE;
238b8e80941Smrg   }
239b8e80941Smrg
240b8e80941Smrg   if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
241848b8605Smrg      key->flags |= SVGA3D_SURFACE_CUBEMAP;
242848b8605Smrg      key->numFaces = 6;
243b8e80941Smrg   } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
244b8e80941Smrg              tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
245b8e80941Smrg      key->arraySize = num_layers;
246848b8605Smrg   }
247848b8605Smrg
248848b8605Smrg   if (key->format == SVGA3D_FORMAT_INVALID) {
249848b8605Smrg      key->cachable = 0;
250b8e80941Smrg      goto done;
251b8e80941Smrg   }
252b8e80941Smrg
253b8e80941Smrg   if (cacheable && tex->backed_handle &&
254b8e80941Smrg       memcmp(key, &tex->backed_key, sizeof *key) == 0) {
255b8e80941Smrg      handle = tex->backed_handle;
256b8e80941Smrg      needCopyResource = tex->backed_age < tex->age;
257b8e80941Smrg   } else {
258b8e80941Smrg      SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
259b8e80941Smrg      handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
260b8e80941Smrg                                          &validated, key);
261b8e80941Smrg      needCopyResource = TRUE;
262b8e80941Smrg
263b8e80941Smrg      if (cacheable && !tex->backed_handle) {
264b8e80941Smrg         tex->backed_handle = handle;
265b8e80941Smrg         memcpy(&tex->backed_key, key, sizeof *key);
266b8e80941Smrg      }
267848b8605Smrg   }
268848b8605Smrg
269848b8605Smrg   if (!handle) {
270848b8605Smrg      key->cachable = 0;
271b8e80941Smrg      goto done;
272848b8605Smrg   }
273848b8605Smrg
274848b8605Smrg   SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
275848b8605Smrg
276b8e80941Smrg   if (layer_pick < 0)
277b8e80941Smrg      layer_pick = 0;
278848b8605Smrg
279b8e80941Smrg   if (needCopyResource) {
280b8e80941Smrg      svga_texture_copy_handle_resource(svga, tex, handle,
281b8e80941Smrg                                        key->numMipLevels,
282b8e80941Smrg                                        key->numFaces * key->arraySize,
283b8e80941Smrg                                        zslice_pick, start_mip, layer_pick);
284b8e80941Smrg      tex->backed_age = tex->age;
285848b8605Smrg   }
286848b8605Smrg
287b8e80941Smrgdone:
288b8e80941Smrg   SVGA_STATS_TIME_POP(ss->sws);
289b8e80941Smrg
290848b8605Smrg   return handle;
291848b8605Smrg}
292848b8605Smrg
293848b8605Smrg
294b8e80941Smrg/**
295b8e80941Smrg * A helper function to create a surface view.
296b8e80941Smrg * The view boolean flag specifies whether svga_texture_view_surface()
297b8e80941Smrg * will be called to create a cloned surface and resource for the view.
298b8e80941Smrg */
299848b8605Smrgstatic struct pipe_surface *
300b8e80941Smrgsvga_create_surface_view(struct pipe_context *pipe,
301b8e80941Smrg                         struct pipe_resource *pt,
302b8e80941Smrg                         const struct pipe_surface *surf_tmpl,
303b8e80941Smrg                         boolean view)
304848b8605Smrg{
305848b8605Smrg   struct svga_context *svga = svga_context(pipe);
306848b8605Smrg   struct svga_texture *tex = svga_texture(pt);
307848b8605Smrg   struct pipe_screen *screen = pipe->screen;
308848b8605Smrg   struct svga_screen *ss = svga_screen(screen);
309848b8605Smrg   struct svga_surface *s;
310b8e80941Smrg   unsigned layer, zslice, bind;
311b8e80941Smrg   unsigned nlayers = 1;
312b8e80941Smrg   SVGA3dSurfaceAllFlags flags = 0;
313848b8605Smrg   SVGA3dSurfaceFormat format;
314b8e80941Smrg   struct pipe_surface *retVal = NULL;
315848b8605Smrg
316848b8605Smrg   s = CALLOC_STRUCT(svga_surface);
317848b8605Smrg   if (!s)
318848b8605Smrg      return NULL;
319848b8605Smrg
320b8e80941Smrg   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
321b8e80941Smrg
322848b8605Smrg   if (pt->target == PIPE_TEXTURE_CUBE) {
323b8e80941Smrg      layer = surf_tmpl->u.tex.first_layer;
324848b8605Smrg      zslice = 0;
325848b8605Smrg   }
326b8e80941Smrg   else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
327b8e80941Smrg            pt->target == PIPE_TEXTURE_2D_ARRAY ||
328b8e80941Smrg            pt->target == PIPE_TEXTURE_CUBE_ARRAY) {
329b8e80941Smrg      layer = surf_tmpl->u.tex.first_layer;
330b8e80941Smrg      zslice = 0;
331b8e80941Smrg      nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
332b8e80941Smrg   }
333848b8605Smrg   else {
334b8e80941Smrg      layer = 0;
335848b8605Smrg      zslice = surf_tmpl->u.tex.first_layer;
336848b8605Smrg   }
337848b8605Smrg
338848b8605Smrg   pipe_reference_init(&s->base.reference, 1);
339848b8605Smrg   pipe_resource_reference(&s->base.texture, pt);
340848b8605Smrg   s->base.context = pipe;
341848b8605Smrg   s->base.format = surf_tmpl->format;
342848b8605Smrg   s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
343848b8605Smrg   s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
344848b8605Smrg   s->base.u.tex.level = surf_tmpl->u.tex.level;
345848b8605Smrg   s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
346848b8605Smrg   s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
347b8e80941Smrg   s->view_id = SVGA3D_INVALID_ID;
348b8e80941Smrg
349b8e80941Smrg   s->backed = NULL;
350848b8605Smrg
351848b8605Smrg   if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
352b8e80941Smrg      flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
353b8e80941Smrg              SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
354b8e80941Smrg      bind = PIPE_BIND_DEPTH_STENCIL;
355848b8605Smrg   }
356848b8605Smrg   else {
357b8e80941Smrg      flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
358b8e80941Smrg              SVGA3D_SURFACE_BIND_RENDER_TARGET;
359b8e80941Smrg      bind = PIPE_BIND_RENDER_TARGET;
360b8e80941Smrg   }
361b8e80941Smrg
362b8e80941Smrg   if (tex->imported) {
363b8e80941Smrg      /* imported resource (a window) */
364b8e80941Smrg      format = tex->key.format;
365b8e80941Smrg      if (util_format_is_srgb(surf_tmpl->format)) {
366b8e80941Smrg         /* sRGB rendering to window */
367b8e80941Smrg         format = svga_linear_to_srgb(format);
368b8e80941Smrg      }
369b8e80941Smrg   }
370b8e80941Smrg   else {
371b8e80941Smrg      format = svga_translate_format(ss, surf_tmpl->format, bind);
372848b8605Smrg   }
373848b8605Smrg
374848b8605Smrg   assert(format != SVGA3D_FORMAT_INVALID);
375848b8605Smrg
376b8e80941Smrg   if (view) {
377b8e80941Smrg      SVGA_DBG(DEBUG_VIEWS,
378b8e80941Smrg               "New backed surface view: resource %p, level %u layer %u z %u, %p\n",
379b8e80941Smrg               pt, surf_tmpl->u.tex.level, layer, zslice, s);
380b8e80941Smrg
381b8e80941Smrg      if (svga_have_vgpu10(svga)) {
382b8e80941Smrg         switch (pt->target) {
383b8e80941Smrg         case PIPE_TEXTURE_1D:
384b8e80941Smrg            flags |= SVGA3D_SURFACE_1D;
385b8e80941Smrg            break;
386b8e80941Smrg         case PIPE_TEXTURE_1D_ARRAY:
387b8e80941Smrg            flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
388b8e80941Smrg            break;
389b8e80941Smrg         case PIPE_TEXTURE_2D_ARRAY:
390b8e80941Smrg            flags |= SVGA3D_SURFACE_ARRAY;
391b8e80941Smrg            break;
392b8e80941Smrg         case PIPE_TEXTURE_3D:
393b8e80941Smrg            flags |= SVGA3D_SURFACE_VOLUME;
394b8e80941Smrg            break;
395b8e80941Smrg         case PIPE_TEXTURE_CUBE:
396b8e80941Smrg            if (nlayers == 6)
397b8e80941Smrg               flags |= SVGA3D_SURFACE_CUBEMAP;
398b8e80941Smrg            break;
399b8e80941Smrg         case PIPE_TEXTURE_CUBE_ARRAY:
400b8e80941Smrg            if (nlayers % 6 == 0)
401b8e80941Smrg               flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY;
402b8e80941Smrg            break;
403b8e80941Smrg         default:
404b8e80941Smrg            break;
405b8e80941Smrg         }
406b8e80941Smrg      }
407848b8605Smrg
408b8e80941Smrg      /* When we clone the surface view resource, use the format used in
409b8e80941Smrg       * the creation of the original resource.
410b8e80941Smrg       */
411b8e80941Smrg      s->handle = svga_texture_view_surface(svga, tex, bind, flags,
412b8e80941Smrg                                            tex->key.format,
413b8e80941Smrg                                            surf_tmpl->u.tex.level, 1,
414b8e80941Smrg                                            layer, nlayers, zslice,
415b8e80941Smrg                                            TRUE, &s->key);
416b8e80941Smrg      if (!s->handle) {
417b8e80941Smrg         FREE(s);
418b8e80941Smrg         goto done;
419b8e80941Smrg      }
420b8e80941Smrg
421b8e80941Smrg      s->key.format = format;
422b8e80941Smrg      s->real_layer = 0;
423b8e80941Smrg      s->real_level = 0;
424b8e80941Smrg      s->real_zslice = 0;
425b8e80941Smrg   } else {
426b8e80941Smrg      SVGA_DBG(DEBUG_VIEWS,
427b8e80941Smrg               "New surface view: resource %p, level %u, layer %u, z %u, %p\n",
428b8e80941Smrg               pt, surf_tmpl->u.tex.level, layer, zslice, s);
429b8e80941Smrg
430b8e80941Smrg      memset(&s->key, 0, sizeof s->key);
431b8e80941Smrg      s->key.format = format;
432b8e80941Smrg      s->handle = tex->handle;
433b8e80941Smrg      s->real_layer = layer;
434b8e80941Smrg      s->real_zslice = zslice;
435b8e80941Smrg      s->real_level = surf_tmpl->u.tex.level;
436848b8605Smrg   }
437848b8605Smrg
438b8e80941Smrg   svga->hud.num_surface_views++;
439b8e80941Smrg   retVal = &s->base;
440b8e80941Smrg
441b8e80941Smrgdone:
442b8e80941Smrg   SVGA_STATS_TIME_POP(ss->sws);
443b8e80941Smrg   return retVal;
444b8e80941Smrg}
445b8e80941Smrg
446b8e80941Smrg
447b8e80941Smrgstatic struct pipe_surface *
448b8e80941Smrgsvga_create_surface(struct pipe_context *pipe,
449b8e80941Smrg                    struct pipe_resource *pt,
450b8e80941Smrg                    const struct pipe_surface *surf_tmpl)
451b8e80941Smrg{
452b8e80941Smrg   struct svga_context *svga = svga_context(pipe);
453b8e80941Smrg   struct pipe_screen *screen = pipe->screen;
454b8e80941Smrg   struct pipe_surface *surf = NULL;
455b8e80941Smrg   boolean view = FALSE;
456b8e80941Smrg
457b8e80941Smrg   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
458b8e80941Smrg
459b8e80941Smrg   if (svga_screen(screen)->debug.force_surface_view)
460b8e80941Smrg      view = TRUE;
461b8e80941Smrg
462848b8605Smrg   if (surf_tmpl->u.tex.level != 0 &&
463848b8605Smrg       svga_screen(screen)->debug.force_level_surface_view)
464848b8605Smrg      view = TRUE;
465848b8605Smrg
466848b8605Smrg   if (pt->target == PIPE_TEXTURE_3D)
467848b8605Smrg      view = TRUE;
468848b8605Smrg
469b8e80941Smrg   if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
470848b8605Smrg      view = FALSE;
471848b8605Smrg
472b8e80941Smrg   surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
473848b8605Smrg
474b8e80941Smrg   SVGA_STATS_TIME_POP(svga_sws(svga));
475848b8605Smrg
476b8e80941Smrg   return surf;
477b8e80941Smrg}
478b8e80941Smrg
479b8e80941Smrg
480b8e80941Smrg/**
481b8e80941Smrg * Clone the surface view and its associated resource.
482b8e80941Smrg */
483b8e80941Smrgstatic struct svga_surface *
484b8e80941Smrgcreate_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
485b8e80941Smrg{
486b8e80941Smrg   struct svga_texture *tex = svga_texture(s->base.texture);
487b8e80941Smrg
488b8e80941Smrg   if (!s->backed) {
489b8e80941Smrg      struct pipe_surface *backed_view;
490b8e80941Smrg
491b8e80941Smrg      SVGA_STATS_TIME_PUSH(svga_sws(svga),
492b8e80941Smrg                           SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
493b8e80941Smrg
494b8e80941Smrg      backed_view = svga_create_surface_view(&svga->pipe,
495b8e80941Smrg                                             &tex->b.b,
496b8e80941Smrg                                             &s->base,
497b8e80941Smrg                                             TRUE);
498b8e80941Smrg      if (!backed_view)
499b8e80941Smrg         goto done;
500b8e80941Smrg
501b8e80941Smrg      s->backed = svga_surface(backed_view);
502b8e80941Smrg
503b8e80941Smrg      SVGA_STATS_TIME_POP(svga_sws(svga));
504b8e80941Smrg   }
505b8e80941Smrg   else if (s->backed->age < tex->age) {
506b8e80941Smrg      /*
507b8e80941Smrg       * There is already an existing backing surface, but we still need to
508b8e80941Smrg       * sync the backing resource if the original resource has been modified
509b8e80941Smrg       * since the last copy.
510b8e80941Smrg       */
511b8e80941Smrg      struct svga_surface *bs = s->backed;
512b8e80941Smrg      unsigned int layer, zslice;
513b8e80941Smrg
514b8e80941Smrg      assert(bs->handle);
515b8e80941Smrg
516b8e80941Smrg      switch (tex->b.b.target) {
517b8e80941Smrg      case PIPE_TEXTURE_CUBE:
518b8e80941Smrg      case PIPE_TEXTURE_CUBE_ARRAY:
519b8e80941Smrg      case PIPE_TEXTURE_1D_ARRAY:
520b8e80941Smrg      case PIPE_TEXTURE_2D_ARRAY:
521b8e80941Smrg         layer = s->base.u.tex.first_layer;
522b8e80941Smrg         zslice = 0;
523b8e80941Smrg         break;
524b8e80941Smrg      default:
525b8e80941Smrg         layer = 0;
526b8e80941Smrg         zslice = s->base.u.tex.first_layer;
527b8e80941Smrg      }
528b8e80941Smrg
529b8e80941Smrg      svga_texture_copy_handle_resource(svga, tex, bs->handle,
530b8e80941Smrg                                        bs->key.numMipLevels,
531b8e80941Smrg                                        bs->key.numFaces * bs->key.arraySize,
532b8e80941Smrg                                        zslice, s->base.u.tex.level, layer);
533b8e80941Smrg   }
534b8e80941Smrg
535b8e80941Smrg   svga_mark_surface_dirty(&s->backed->base);
536b8e80941Smrg   s->backed->age = tex->age;
537b8e80941Smrg
538b8e80941Smrgdone:
539b8e80941Smrg   return s->backed;
540b8e80941Smrg}
541b8e80941Smrg
542b8e80941Smrg/**
543b8e80941Smrg * Create a DX RenderTarget/DepthStencil View for the given surface,
544b8e80941Smrg * if needed.
545b8e80941Smrg */
546b8e80941Smrgstruct pipe_surface *
547b8e80941Smrgsvga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
548b8e80941Smrg{
549b8e80941Smrg   enum pipe_error ret = PIPE_OK;
550b8e80941Smrg   enum pipe_shader_type shader;
551b8e80941Smrg
552b8e80941Smrg   assert(svga_have_vgpu10(svga));
553b8e80941Smrg   assert(s);
554b8e80941Smrg
555b8e80941Smrg   SVGA_STATS_TIME_PUSH(svga_sws(svga),
556b8e80941Smrg                        SVGA_STATS_TIME_VALIDATESURFACEVIEW);
557b8e80941Smrg
558b8e80941Smrg   /**
559b8e80941Smrg    * DX spec explicitly specifies that no resource can be bound to a render
560b8e80941Smrg    * target view and a shader resource view simultanously.
561b8e80941Smrg    * So first check if the resource bound to this surface view collides with
562b8e80941Smrg    * a sampler view. If so, then we will clone this surface view and its
563b8e80941Smrg    * associated resource. We will then use the cloned surface view for
564b8e80941Smrg    * render target.
565b8e80941Smrg    */
566b8e80941Smrg   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
567b8e80941Smrg      if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
568b8e80941Smrg         SVGA_DBG(DEBUG_VIEWS,
569b8e80941Smrg                  "same resource used in shaderResource and renderTarget 0x%x\n",
570b8e80941Smrg                  s->handle);
571b8e80941Smrg         s = create_backed_surface_view(svga, s);
572b8e80941Smrg
573b8e80941Smrg         if (s)
574b8e80941Smrg            svga->state.hw_draw.has_backed_views = TRUE;
575b8e80941Smrg
576b8e80941Smrg         /* s may be null here if the function failed */
577b8e80941Smrg         break;
578b8e80941Smrg      }
579848b8605Smrg   }
580848b8605Smrg
581b8e80941Smrg   if (s && s->view_id == SVGA3D_INVALID_ID) {
582b8e80941Smrg      SVGA3dResourceType resType;
583b8e80941Smrg      SVGA3dRenderTargetViewDesc desc;
584b8e80941Smrg      struct svga_texture *stex = svga_texture(s->base.texture);
585b8e80941Smrg
586b8e80941Smrg      if (stex->validated == FALSE) {
587b8e80941Smrg         assert(stex->handle);
588b8e80941Smrg
589b8e80941Smrg         /* We are about to render into a surface that has not been validated.
590b8e80941Smrg          * First invalidate the surface so that the device does not
591b8e80941Smrg          * need to update the host-side copy with the invalid
592b8e80941Smrg          * content when the associated mob is first bound to the surface.
593b8e80941Smrg          */
594b8e80941Smrg         if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) {
595b8e80941Smrg            svga_context_flush(svga, NULL);
596b8e80941Smrg            ret = svga->swc->surface_invalidate(svga->swc, stex->handle);
597b8e80941Smrg            assert(ret == PIPE_OK);
598b8e80941Smrg         }
599b8e80941Smrg         stex->validated = TRUE;
600b8e80941Smrg      }
601b8e80941Smrg
602b8e80941Smrg      desc.tex.mipSlice = s->real_level;
603b8e80941Smrg      desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
604b8e80941Smrg      desc.tex.arraySize =
605b8e80941Smrg         s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
606b8e80941Smrg
607b8e80941Smrg      s->view_id = util_bitmask_add(svga->surface_view_id_bm);
608b8e80941Smrg
609b8e80941Smrg      resType = svga_resource_type(s->base.texture->target);
610b8e80941Smrg
611b8e80941Smrg      if (util_format_is_depth_or_stencil(s->base.format)) {
612b8e80941Smrg         ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
613b8e80941Smrg                                                    s->view_id,
614b8e80941Smrg                                                    s->handle,
615b8e80941Smrg                                                    s->key.format,
616b8e80941Smrg                                                    resType,
617b8e80941Smrg                                                    &desc);
618b8e80941Smrg      }
619b8e80941Smrg      else {
620b8e80941Smrg         SVGA3dSurfaceFormat view_format = s->key.format;
621b8e80941Smrg         const struct svga_texture *stex = svga_texture(s->base.texture);
622b8e80941Smrg
623b8e80941Smrg         /* Can't create RGBA render target view of a RGBX surface so adjust
624b8e80941Smrg          * the view format.  We do something similar for texture samplers in
625b8e80941Smrg          * svga_validate_pipe_sampler_view().
626b8e80941Smrg          */
627b8e80941Smrg         if (view_format == SVGA3D_B8G8R8A8_UNORM &&
628b8e80941Smrg             (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
629b8e80941Smrg              stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
630b8e80941Smrg            view_format = SVGA3D_B8G8R8X8_UNORM;
631b8e80941Smrg         }
632b8e80941Smrg
633b8e80941Smrg         ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
634b8e80941Smrg                                                    s->view_id,
635b8e80941Smrg                                                    s->handle,
636b8e80941Smrg                                                    view_format,
637b8e80941Smrg                                                    resType,
638b8e80941Smrg                                                    &desc);
639b8e80941Smrg      }
640b8e80941Smrg
641b8e80941Smrg      if (ret != PIPE_OK) {
642b8e80941Smrg         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
643b8e80941Smrg         s->view_id = SVGA3D_INVALID_ID;
644b8e80941Smrg         s = NULL;
645b8e80941Smrg      }
646b8e80941Smrg   }
647b8e80941Smrg
648b8e80941Smrg   SVGA_STATS_TIME_POP(svga_sws(svga));
649b8e80941Smrg
650b8e80941Smrg   return s ? &s->base : NULL;
651848b8605Smrg}
652848b8605Smrg
653848b8605Smrg
654b8e80941Smrg
655848b8605Smrgstatic void
656848b8605Smrgsvga_surface_destroy(struct pipe_context *pipe,
657848b8605Smrg                     struct pipe_surface *surf)
658848b8605Smrg{
659b8e80941Smrg   struct svga_context *svga = svga_context(pipe);
660848b8605Smrg   struct svga_surface *s = svga_surface(surf);
661848b8605Smrg   struct svga_texture *t = svga_texture(surf->texture);
662848b8605Smrg   struct svga_screen *ss = svga_screen(surf->texture->screen);
663b8e80941Smrg   enum pipe_error ret = PIPE_OK;
664b8e80941Smrg
665b8e80941Smrg   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
666b8e80941Smrg
667b8e80941Smrg   /* Destroy the backed view surface if it exists */
668b8e80941Smrg   if (s->backed) {
669b8e80941Smrg      svga_surface_destroy(pipe, &s->backed->base);
670b8e80941Smrg      s->backed = NULL;
671b8e80941Smrg   }
672848b8605Smrg
673b8e80941Smrg   /* Destroy the surface handle if this is a backed handle and
674b8e80941Smrg    * it is not being cached in the texture.
675b8e80941Smrg    */
676b8e80941Smrg   if (s->handle != t->handle && s->handle != t->backed_handle) {
677848b8605Smrg      SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
678848b8605Smrg      svga_screen_surface_destroy(ss, &s->key, &s->handle);
679848b8605Smrg   }
680848b8605Smrg
681b8e80941Smrg   if (s->view_id != SVGA3D_INVALID_ID) {
682b8e80941Smrg      unsigned try;
683b8e80941Smrg
684b8e80941Smrg      /* The SVGA3D device will generate a device error if the
685b8e80941Smrg       * render target view or depth stencil view is destroyed from
686b8e80941Smrg       * a context other than the one it was created with.
687b8e80941Smrg       * Similar to shader resource view, in this case, we will skip
688b8e80941Smrg       * the destroy for now.
689b8e80941Smrg       */
690b8e80941Smrg      if (surf->context != pipe) {
691b8e80941Smrg         _debug_printf("context mismatch in %s\n", __func__);
692b8e80941Smrg      }
693b8e80941Smrg      else {
694b8e80941Smrg         assert(svga_have_vgpu10(svga));
695b8e80941Smrg         for (try = 0; try < 2; try++) {
696b8e80941Smrg            if (util_format_is_depth_or_stencil(s->base.format)) {
697b8e80941Smrg               ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
698b8e80941Smrg            }
699b8e80941Smrg            else {
700b8e80941Smrg               ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
701b8e80941Smrg            }
702b8e80941Smrg            if (ret == PIPE_OK)
703b8e80941Smrg               break;
704b8e80941Smrg            svga_context_flush(svga, NULL);
705b8e80941Smrg         }
706b8e80941Smrg         assert(ret == PIPE_OK);
707b8e80941Smrg         util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
708b8e80941Smrg      }
709b8e80941Smrg   }
710b8e80941Smrg
711848b8605Smrg   pipe_resource_reference(&surf->texture, NULL);
712848b8605Smrg   FREE(surf);
713b8e80941Smrg
714b8e80941Smrg   svga->hud.num_surface_views--;
715b8e80941Smrg   SVGA_STATS_TIME_POP(ss->sws);
716848b8605Smrg}
717848b8605Smrg
718848b8605Smrg
719b8e80941Smrgstatic void
720848b8605Smrgsvga_mark_surface_dirty(struct pipe_surface *surf)
721848b8605Smrg{
722848b8605Smrg   struct svga_surface *s = svga_surface(surf);
723b8e80941Smrg   struct svga_texture *tex = svga_texture(surf->texture);
724848b8605Smrg
725848b8605Smrg   if (!s->dirty) {
726848b8605Smrg      s->dirty = TRUE;
727848b8605Smrg
728848b8605Smrg      if (s->handle == tex->handle) {
729848b8605Smrg         /* hmm so 3d textures always have all their slices marked ? */
730b8e80941Smrg         svga_define_texture_level(tex, surf->u.tex.first_layer,
731b8e80941Smrg                                   surf->u.tex.level);
732848b8605Smrg      }
733848b8605Smrg      else {
734848b8605Smrg         /* this will happen later in svga_propagate_surface */
735848b8605Smrg      }
736b8e80941Smrg   }
737848b8605Smrg
738b8e80941Smrg   /* Increment the view_age and texture age for this surface's mipmap
739b8e80941Smrg    * level so that any sampler views into the texture are re-validated too.
740b8e80941Smrg    * Note: we age the texture for backed surface view only when the
741b8e80941Smrg    *       backed surface is propagated to the original surface.
742b8e80941Smrg    */
743b8e80941Smrg   if (s->handle == tex->handle)
744848b8605Smrg      svga_age_texture_view(tex, surf->u.tex.level);
745848b8605Smrg}
746848b8605Smrg
747848b8605Smrg
748848b8605Smrgvoid
749848b8605Smrgsvga_mark_surfaces_dirty(struct svga_context *svga)
750848b8605Smrg{
751848b8605Smrg   unsigned i;
752b8e80941Smrg   struct svga_hw_clear_state *hw = &svga->state.hw_clear;
753848b8605Smrg
754b8e80941Smrg   if (svga_have_vgpu10(svga)) {
755b8e80941Smrg
756b8e80941Smrg      /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface.
757b8e80941Smrg       * This surface can be the backed surface.
758b8e80941Smrg       */
759b8e80941Smrg      for (i = 0; i < hw->num_rendertargets; i++) {
760b8e80941Smrg         if (hw->rtv[i])
761b8e80941Smrg            svga_mark_surface_dirty(hw->rtv[i]);
762b8e80941Smrg      }
763b8e80941Smrg      if (hw->dsv)
764b8e80941Smrg         svga_mark_surface_dirty(hw->dsv);
765b8e80941Smrg   } else {
766b8e80941Smrg      for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
767b8e80941Smrg         if (svga->curr.framebuffer.cbufs[i])
768b8e80941Smrg            svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
769b8e80941Smrg      }
770b8e80941Smrg      if (svga->curr.framebuffer.zsbuf)
771b8e80941Smrg         svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
772848b8605Smrg   }
773848b8605Smrg}
774848b8605Smrg
775848b8605Smrg
776848b8605Smrg/**
777848b8605Smrg * Progagate any changes from surfaces to texture.
778848b8605Smrg * pipe is optional context to inline the blit command in.
779848b8605Smrg */
780848b8605Smrgvoid
781b8e80941Smrgsvga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
782b8e80941Smrg                       boolean reset)
783848b8605Smrg{
784848b8605Smrg   struct svga_surface *s = svga_surface(surf);
785848b8605Smrg   struct svga_texture *tex = svga_texture(surf->texture);
786848b8605Smrg   struct svga_screen *ss = svga_screen(surf->texture->screen);
787848b8605Smrg
788848b8605Smrg   if (!s->dirty)
789848b8605Smrg      return;
790848b8605Smrg
791b8e80941Smrg   SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
792b8e80941Smrg
793b8e80941Smrg   /* Reset the dirty flag if specified. This is to ensure that
794b8e80941Smrg    * the dirty flag will not be reset and stay unset when the backing
795b8e80941Smrg    * surface is still being bound and rendered to.
796b8e80941Smrg    * The reset flag will be set to TRUE when the surface is propagated
797b8e80941Smrg    * and will be unbound.
798b8e80941Smrg    */
799b8e80941Smrg   s->dirty = !reset;
800848b8605Smrg
801848b8605Smrg   ss->texture_timestamp++;
802848b8605Smrg   svga_age_texture_view(tex, surf->u.tex.level);
803848b8605Smrg
804848b8605Smrg   if (s->handle != tex->handle) {
805b8e80941Smrg      unsigned zslice, layer;
806b8e80941Smrg      unsigned nlayers = 1;
807b8e80941Smrg      unsigned i;
808b8e80941Smrg      unsigned numMipLevels = tex->b.b.last_level + 1;
809b8e80941Smrg      unsigned srcLevel = s->real_level;
810b8e80941Smrg      unsigned dstLevel = surf->u.tex.level;
811b8e80941Smrg      unsigned width = u_minify(tex->b.b.width0, dstLevel);
812b8e80941Smrg      unsigned height = u_minify(tex->b.b.height0, dstLevel);
813b8e80941Smrg
814b8e80941Smrg      if (surf->texture->target == PIPE_TEXTURE_CUBE) {
815b8e80941Smrg         zslice = 0;
816b8e80941Smrg         layer = surf->u.tex.first_layer;
817b8e80941Smrg      }
818b8e80941Smrg      else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
819b8e80941Smrg               surf->texture->target == PIPE_TEXTURE_2D_ARRAY ||
820b8e80941Smrg               surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
821b8e80941Smrg         zslice = 0;
822b8e80941Smrg         layer = surf->u.tex.first_layer;
823b8e80941Smrg         nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
824b8e80941Smrg      }
825b8e80941Smrg      else {
826b8e80941Smrg         zslice = surf->u.tex.first_layer;
827b8e80941Smrg         layer = 0;
828b8e80941Smrg      }
829b8e80941Smrg
830848b8605Smrg      SVGA_DBG(DEBUG_VIEWS,
831b8e80941Smrg               "Propagate surface %p to resource %p, level %u\n",
832b8e80941Smrg               surf, tex, surf->u.tex.level);
833b8e80941Smrg
834b8e80941Smrg      if (svga_have_vgpu10(svga)) {
835b8e80941Smrg         unsigned srcSubResource, dstSubResource;
836b8e80941Smrg
837b8e80941Smrg         for (i = 0; i < nlayers; i++) {
838b8e80941Smrg            srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel;
839b8e80941Smrg            dstSubResource = (layer + i) * numMipLevels + dstLevel;
840b8e80941Smrg
841b8e80941Smrg            svga_texture_copy_region(svga,
842b8e80941Smrg                                     s->handle, srcSubResource, 0, 0, 0,
843b8e80941Smrg                                     tex->handle, dstSubResource, 0, 0, zslice,
844b8e80941Smrg                                     width, height, 1);
845b8e80941Smrg            svga_define_texture_level(tex, layer + i, dstLevel);
846b8e80941Smrg         }
847b8e80941Smrg      }
848b8e80941Smrg      else {
849b8e80941Smrg         for (i = 0; i < nlayers; i++) {
850b8e80941Smrg            svga_texture_copy_handle(svga,
851b8e80941Smrg                                     s->handle, 0, 0, 0, srcLevel,
852b8e80941Smrg                                     s->real_layer + i,
853b8e80941Smrg                                     tex->handle, 0, 0, zslice, dstLevel,
854b8e80941Smrg                                     layer + i,
855b8e80941Smrg                                     width, height, 1);
856b8e80941Smrg
857b8e80941Smrg            svga_define_texture_level(tex, layer + i, dstLevel);
858b8e80941Smrg         }
859b8e80941Smrg      }
860b8e80941Smrg
861b8e80941Smrg      /* Sync the surface view age with the texture age */
862b8e80941Smrg      s->age = tex->age;
863b8e80941Smrg
864b8e80941Smrg      /* If this backed surface is cached in the texture,
865b8e80941Smrg       * update the backed age as well.
866b8e80941Smrg       */
867b8e80941Smrg      if (tex->backed_handle == s->handle) {
868b8e80941Smrg         tex->backed_age = tex->age;
869b8e80941Smrg      }
870b8e80941Smrg   }
871b8e80941Smrg
872b8e80941Smrg   SVGA_STATS_TIME_POP(ss->sws);
873b8e80941Smrg}
874b8e80941Smrg
875b8e80941Smrg
876b8e80941Smrg/**
877b8e80941Smrg * If any of the render targets are in backing texture views, propagate any
878b8e80941Smrg * changes to them back to the original texture.
879b8e80941Smrg */
880b8e80941Smrgvoid
881b8e80941Smrgsvga_propagate_rendertargets(struct svga_context *svga)
882b8e80941Smrg{
883b8e80941Smrg   unsigned i;
884b8e80941Smrg
885b8e80941Smrg   /* Early exit if there is no backing texture views in use */
886b8e80941Smrg   if (!svga->state.hw_draw.has_backed_views)
887b8e80941Smrg      return;
888b8e80941Smrg
889b8e80941Smrg   /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
890b8e80941Smrg    * not the svga->curr.framebuffer surfaces, because it's the former
891b8e80941Smrg    * surfaces which may be backing surface views (the actual render targets).
892b8e80941Smrg    */
893b8e80941Smrg   for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) {
894b8e80941Smrg      struct pipe_surface *s = svga->state.hw_clear.rtv[i];
895b8e80941Smrg      if (s) {
896b8e80941Smrg         svga_propagate_surface(svga, s, FALSE);
897b8e80941Smrg      }
898b8e80941Smrg   }
899b8e80941Smrg
900b8e80941Smrg   if (svga->state.hw_clear.dsv) {
901b8e80941Smrg      svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE);
902848b8605Smrg   }
903848b8605Smrg}
904848b8605Smrg
905848b8605Smrg
906848b8605Smrg/**
907848b8605Smrg * Check if we should call svga_propagate_surface on the surface.
908848b8605Smrg */
909848b8605Smrgboolean
910848b8605Smrgsvga_surface_needs_propagation(const struct pipe_surface *surf)
911848b8605Smrg{
912848b8605Smrg   const struct svga_surface *s = svga_surface_const(surf);
913848b8605Smrg   struct svga_texture *tex = svga_texture(surf->texture);
914848b8605Smrg
915848b8605Smrg   return s->dirty && s->handle != tex->handle;
916848b8605Smrg}
917848b8605Smrg
918848b8605Smrg
919b8e80941Smrgstatic void
920b8e80941Smrgsvga_get_sample_position(struct pipe_context *context,
921b8e80941Smrg                         unsigned sample_count, unsigned sample_index,
922b8e80941Smrg                         float *pos_out)
923b8e80941Smrg{
924b8e80941Smrg   /* We can't actually query the device to learn the sample positions.
925b8e80941Smrg    * These were grabbed from nvidia's driver.
926b8e80941Smrg    */
927b8e80941Smrg   static const float pos1[1][2] = {
928b8e80941Smrg      { 0.5, 0.5 }
929b8e80941Smrg   };
930b8e80941Smrg   static const float pos2[2][2] = {
931b8e80941Smrg      { 0.75, 0.75 },
932b8e80941Smrg      { 0.25, 0.25 }
933b8e80941Smrg   };
934b8e80941Smrg   static const float pos4[4][2] = {
935b8e80941Smrg      { 0.375000, 0.125000 },
936b8e80941Smrg      { 0.875000, 0.375000 },
937b8e80941Smrg      { 0.125000, 0.625000 },
938b8e80941Smrg      { 0.625000, 0.875000 }
939b8e80941Smrg   };
940b8e80941Smrg   static const float pos8[8][2] = {
941b8e80941Smrg      { 0.562500, 0.312500 },
942b8e80941Smrg      { 0.437500, 0.687500 },
943b8e80941Smrg      { 0.812500, 0.562500 },
944b8e80941Smrg      { 0.312500, 0.187500 },
945b8e80941Smrg      { 0.187500, 0.812500 },
946b8e80941Smrg      { 0.062500, 0.437500 },
947b8e80941Smrg      { 0.687500, 0.937500 },
948b8e80941Smrg      { 0.937500, 0.062500 }
949b8e80941Smrg   };
950b8e80941Smrg   static const float pos16[16][2] = {
951b8e80941Smrg      { 0.187500, 0.062500 },
952b8e80941Smrg      { 0.437500, 0.187500 },
953b8e80941Smrg      { 0.062500, 0.312500 },
954b8e80941Smrg      { 0.312500, 0.437500 },
955b8e80941Smrg      { 0.687500, 0.062500 },
956b8e80941Smrg      { 0.937500, 0.187500 },
957b8e80941Smrg      { 0.562500, 0.312500 },
958b8e80941Smrg      { 0.812500, 0.437500 },
959b8e80941Smrg      { 0.187500, 0.562500 },
960b8e80941Smrg      { 0.437500, 0.687500 },
961b8e80941Smrg      { 0.062500, 0.812500 },
962b8e80941Smrg      { 0.312500, 0.937500 },
963b8e80941Smrg      { 0.687500, 0.562500 },
964b8e80941Smrg      { 0.937500, 0.687500 },
965b8e80941Smrg      { 0.562500, 0.812500 },
966b8e80941Smrg      { 0.812500, 0.937500 }
967b8e80941Smrg   };
968b8e80941Smrg   const float (*positions)[2];
969b8e80941Smrg
970b8e80941Smrg   switch (sample_count) {
971b8e80941Smrg   case 2:
972b8e80941Smrg      positions = pos2;
973b8e80941Smrg      break;
974b8e80941Smrg   case 4:
975b8e80941Smrg      positions = pos4;
976b8e80941Smrg      break;
977b8e80941Smrg   case 8:
978b8e80941Smrg      positions = pos8;
979b8e80941Smrg      break;
980b8e80941Smrg   case 16:
981b8e80941Smrg      positions = pos16;
982b8e80941Smrg      break;
983b8e80941Smrg   default:
984b8e80941Smrg      positions = pos1;
985b8e80941Smrg   }
986b8e80941Smrg
987b8e80941Smrg   pos_out[0] = positions[sample_index][0];
988b8e80941Smrg   pos_out[1] = positions[sample_index][1];
989b8e80941Smrg}
990b8e80941Smrg
991848b8605Smrg
992848b8605Smrgvoid
993848b8605Smrgsvga_init_surface_functions(struct svga_context *svga)
994848b8605Smrg{
995848b8605Smrg   svga->pipe.create_surface = svga_create_surface;
996848b8605Smrg   svga->pipe.surface_destroy = svga_surface_destroy;
997b8e80941Smrg   svga->pipe.get_sample_position = svga_get_sample_position;
998848b8605Smrg}
999