svga: fix cubemap array rendering with backed surface view
[mesa.git] / src / gallium / drivers / svga / svga_surface.c
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
45 static void svga_mark_surface_dirty(struct pipe_surface *surf);
46
47 void
48 svga_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
85 void
86 svga_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 */
146 static void
147 svga_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 svga_texture_copy_handle(svga,
174 src_tex->handle,
175 0, 0, zoffset,
176 miplevel,
177 j + layeroffset,
178 dst, 0, 0, 0, i, j,
179 u_minify(src_tex->b.b.width0, miplevel),
180 u_minify(src_tex->b.b.height0, miplevel),
181 depth);
182 }
183 }
184 }
185 }
186
187
188 struct svga_winsys_surface *
189 svga_texture_view_surface(struct svga_context *svga,
190 struct svga_texture *tex,
191 unsigned bind_flags,
192 SVGA3dSurfaceAllFlags flags,
193 SVGA3dSurfaceFormat format,
194 unsigned start_mip,
195 unsigned num_mip,
196 int layer_pick,
197 unsigned num_layers,
198 int zslice_pick,
199 boolean cacheable,
200 struct svga_host_surface_cache_key *key) /* OUT */
201 {
202 struct svga_screen *ss = svga_screen(svga->pipe.screen);
203 struct svga_winsys_surface *handle = NULL;
204 boolean validated;
205 boolean needCopyResource;
206
207 SVGA_DBG(DEBUG_PERF,
208 "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
209 layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
210
211 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW);
212
213 key->flags = flags;
214 key->format = format;
215 key->numMipLevels = num_mip;
216 key->size.width = u_minify(tex->b.b.width0, start_mip);
217 key->size.height = u_minify(tex->b.b.height0, start_mip);
218 key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
219 key->cachable = 1;
220 key->arraySize = 1;
221 key->numFaces = 1;
222
223 /* single sample surface can be treated as non-multisamples surface */
224 key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
225
226 if (key->sampleCount > 1) {
227 assert(ss->sws->have_sm4_1);
228 key->flags |= SVGA3D_SURFACE_MULTISAMPLE;
229 }
230
231 if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
232 key->flags |= SVGA3D_SURFACE_CUBEMAP;
233 key->numFaces = 6;
234 } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
235 tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
236 key->arraySize = num_layers;
237 }
238
239 if (key->format == SVGA3D_FORMAT_INVALID) {
240 key->cachable = 0;
241 goto done;
242 }
243
244 if (cacheable && tex->backed_handle &&
245 memcmp(key, &tex->backed_key, sizeof *key) == 0) {
246 handle = tex->backed_handle;
247 needCopyResource = tex->backed_age < tex->age;
248 } else {
249 SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
250 handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
251 &validated, key);
252 needCopyResource = TRUE;
253
254 if (cacheable && !tex->backed_handle) {
255 tex->backed_handle = handle;
256 memcpy(&tex->backed_key, key, sizeof *key);
257 }
258 }
259
260 if (!handle) {
261 key->cachable = 0;
262 goto done;
263 }
264
265 SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
266
267 if (layer_pick < 0)
268 layer_pick = 0;
269
270 if (needCopyResource) {
271 svga_texture_copy_handle_resource(svga, tex, handle,
272 key->numMipLevels,
273 key->numFaces * key->arraySize,
274 zslice_pick, start_mip, layer_pick);
275 tex->backed_age = tex->age;
276 }
277
278 done:
279 SVGA_STATS_TIME_POP(ss->sws);
280
281 return handle;
282 }
283
284
285 /**
286 * A helper function to create a surface view.
287 * The view boolean flag specifies whether svga_texture_view_surface()
288 * will be called to create a cloned surface and resource for the view.
289 */
290 static struct pipe_surface *
291 svga_create_surface_view(struct pipe_context *pipe,
292 struct pipe_resource *pt,
293 const struct pipe_surface *surf_tmpl,
294 boolean view)
295 {
296 struct svga_context *svga = svga_context(pipe);
297 struct svga_texture *tex = svga_texture(pt);
298 struct pipe_screen *screen = pipe->screen;
299 struct svga_screen *ss = svga_screen(screen);
300 struct svga_surface *s;
301 unsigned layer, zslice, bind;
302 unsigned nlayers = 1;
303 SVGA3dSurfaceAllFlags flags = 0;
304 SVGA3dSurfaceFormat format;
305 struct pipe_surface *retVal = NULL;
306
307 s = CALLOC_STRUCT(svga_surface);
308 if (!s)
309 return NULL;
310
311 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
312
313 if (pt->target == PIPE_TEXTURE_CUBE) {
314 layer = surf_tmpl->u.tex.first_layer;
315 zslice = 0;
316 }
317 else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
318 pt->target == PIPE_TEXTURE_2D_ARRAY ||
319 pt->target == PIPE_TEXTURE_CUBE_ARRAY) {
320 layer = surf_tmpl->u.tex.first_layer;
321 zslice = 0;
322 nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
323 }
324 else {
325 layer = 0;
326 zslice = surf_tmpl->u.tex.first_layer;
327 }
328
329 pipe_reference_init(&s->base.reference, 1);
330 pipe_resource_reference(&s->base.texture, pt);
331 s->base.context = pipe;
332 s->base.format = surf_tmpl->format;
333 s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
334 s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
335 s->base.u.tex.level = surf_tmpl->u.tex.level;
336 s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
337 s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
338 s->view_id = SVGA3D_INVALID_ID;
339
340 s->backed = NULL;
341
342 if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
343 flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
344 SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
345 bind = PIPE_BIND_DEPTH_STENCIL;
346 }
347 else {
348 flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
349 SVGA3D_SURFACE_BIND_RENDER_TARGET;
350 bind = PIPE_BIND_RENDER_TARGET;
351 }
352
353 if (tex->imported) {
354 /* imported resource (a window) */
355 format = tex->key.format;
356 if (util_format_is_srgb(surf_tmpl->format)) {
357 /* sRGB rendering to window */
358 format = svga_linear_to_srgb(format);
359 }
360 }
361 else {
362 format = svga_translate_format(ss, surf_tmpl->format, bind);
363 }
364
365 assert(format != SVGA3D_FORMAT_INVALID);
366
367 if (view) {
368 SVGA_DBG(DEBUG_VIEWS,
369 "New backed surface view: resource %p, level %u layer %u z %u, %p\n",
370 pt, surf_tmpl->u.tex.level, layer, zslice, s);
371
372 if (svga_have_vgpu10(svga)) {
373 switch (pt->target) {
374 case PIPE_TEXTURE_1D:
375 flags |= SVGA3D_SURFACE_1D;
376 break;
377 case PIPE_TEXTURE_1D_ARRAY:
378 flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
379 break;
380 case PIPE_TEXTURE_2D_ARRAY:
381 flags |= SVGA3D_SURFACE_ARRAY;
382 break;
383 case PIPE_TEXTURE_3D:
384 flags |= SVGA3D_SURFACE_VOLUME;
385 break;
386 case PIPE_TEXTURE_CUBE:
387 if (nlayers == 6)
388 flags |= SVGA3D_SURFACE_CUBEMAP;
389 break;
390 case PIPE_TEXTURE_CUBE_ARRAY:
391 if (nlayers % 6 == 0)
392 flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY;
393 break;
394 default:
395 break;
396 }
397 }
398
399 /* When we clone the surface view resource, use the format used in
400 * the creation of the original resource.
401 */
402 s->handle = svga_texture_view_surface(svga, tex, bind, flags,
403 tex->key.format,
404 surf_tmpl->u.tex.level, 1,
405 layer, nlayers, zslice,
406 TRUE, &s->key);
407 if (!s->handle) {
408 FREE(s);
409 goto done;
410 }
411
412 s->key.format = format;
413 s->real_layer = 0;
414 s->real_level = 0;
415 s->real_zslice = 0;
416 } else {
417 SVGA_DBG(DEBUG_VIEWS,
418 "New surface view: resource %p, level %u, layer %u, z %u, %p\n",
419 pt, surf_tmpl->u.tex.level, layer, zslice, s);
420
421 memset(&s->key, 0, sizeof s->key);
422 s->key.format = format;
423 s->handle = tex->handle;
424 s->real_layer = layer;
425 s->real_zslice = zslice;
426 s->real_level = surf_tmpl->u.tex.level;
427 }
428
429 svga->hud.num_surface_views++;
430 retVal = &s->base;
431
432 done:
433 SVGA_STATS_TIME_POP(ss->sws);
434 return retVal;
435 }
436
437
438 static struct pipe_surface *
439 svga_create_surface(struct pipe_context *pipe,
440 struct pipe_resource *pt,
441 const struct pipe_surface *surf_tmpl)
442 {
443 struct svga_context *svga = svga_context(pipe);
444 struct pipe_screen *screen = pipe->screen;
445 struct pipe_surface *surf = NULL;
446 boolean view = FALSE;
447
448 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
449
450 if (svga_screen(screen)->debug.force_surface_view)
451 view = TRUE;
452
453 if (surf_tmpl->u.tex.level != 0 &&
454 svga_screen(screen)->debug.force_level_surface_view)
455 view = TRUE;
456
457 if (pt->target == PIPE_TEXTURE_3D)
458 view = TRUE;
459
460 if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
461 view = FALSE;
462
463 surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
464
465 SVGA_STATS_TIME_POP(svga_sws(svga));
466
467 return surf;
468 }
469
470
471 /**
472 * Clone the surface view and its associated resource.
473 */
474 static struct svga_surface *
475 create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
476 {
477 struct svga_texture *tex = svga_texture(s->base.texture);
478
479 if (!s->backed) {
480 struct pipe_surface *backed_view;
481
482 SVGA_STATS_TIME_PUSH(svga_sws(svga),
483 SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
484
485 backed_view = svga_create_surface_view(&svga->pipe,
486 &tex->b.b,
487 &s->base,
488 TRUE);
489 if (!backed_view)
490 goto done;
491
492 s->backed = svga_surface(backed_view);
493
494 SVGA_STATS_TIME_POP(svga_sws(svga));
495 }
496 else if (s->backed->age < tex->age) {
497 /*
498 * There is already an existing backing surface, but we still need to
499 * sync the backing resource if the original resource has been modified
500 * since the last copy.
501 */
502 struct svga_surface *bs = s->backed;
503 unsigned int layer, zslice;
504
505 assert(bs->handle);
506
507 switch (tex->b.b.target) {
508 case PIPE_TEXTURE_CUBE:
509 case PIPE_TEXTURE_CUBE_ARRAY:
510 case PIPE_TEXTURE_1D_ARRAY:
511 case PIPE_TEXTURE_2D_ARRAY:
512 layer = s->base.u.tex.first_layer;
513 zslice = 0;
514 break;
515 default:
516 layer = 0;
517 zslice = s->base.u.tex.first_layer;
518 }
519
520 svga_texture_copy_handle_resource(svga, tex, bs->handle,
521 bs->key.numMipLevels,
522 bs->key.numFaces * bs->key.arraySize,
523 zslice, s->base.u.tex.level, layer);
524 }
525
526 svga_mark_surface_dirty(&s->backed->base);
527 s->backed->age = tex->age;
528
529 done:
530 return s->backed;
531 }
532
533 /**
534 * Create a DX RenderTarget/DepthStencil View for the given surface,
535 * if needed.
536 */
537 struct pipe_surface *
538 svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
539 {
540 enum pipe_error ret = PIPE_OK;
541 enum pipe_shader_type shader;
542
543 assert(svga_have_vgpu10(svga));
544 assert(s);
545
546 SVGA_STATS_TIME_PUSH(svga_sws(svga),
547 SVGA_STATS_TIME_VALIDATESURFACEVIEW);
548
549 /**
550 * DX spec explicitly specifies that no resource can be bound to a render
551 * target view and a shader resource view simultanously.
552 * So first check if the resource bound to this surface view collides with
553 * a sampler view. If so, then we will clone this surface view and its
554 * associated resource. We will then use the cloned surface view for
555 * render target.
556 */
557 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
558 if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
559 SVGA_DBG(DEBUG_VIEWS,
560 "same resource used in shaderResource and renderTarget 0x%x\n",
561 s->handle);
562 s = create_backed_surface_view(svga, s);
563
564 if (s)
565 svga->state.hw_draw.has_backed_views = TRUE;
566
567 /* s may be null here if the function failed */
568 break;
569 }
570 }
571
572 if (s && s->view_id == SVGA3D_INVALID_ID) {
573 SVGA3dResourceType resType;
574 SVGA3dRenderTargetViewDesc desc;
575 struct svga_texture *stex = svga_texture(s->base.texture);
576
577 if (stex->validated == FALSE) {
578 assert(stex->handle);
579
580 /* We are about to render into a surface that has not been validated.
581 * First invalidate the surface so that the device does not
582 * need to update the host-side copy with the invalid
583 * content when the associated mob is first bound to the surface.
584 */
585 if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) {
586 svga_context_flush(svga, NULL);
587 ret = svga->swc->surface_invalidate(svga->swc, stex->handle);
588 assert(ret == PIPE_OK);
589 }
590 stex->validated = TRUE;
591 }
592
593 desc.tex.mipSlice = s->real_level;
594 desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
595 desc.tex.arraySize =
596 s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
597
598 s->view_id = util_bitmask_add(svga->surface_view_id_bm);
599
600 resType = svga_resource_type(s->base.texture->target);
601
602 if (util_format_is_depth_or_stencil(s->base.format)) {
603 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
604 s->view_id,
605 s->handle,
606 s->key.format,
607 resType,
608 &desc);
609 }
610 else {
611 SVGA3dSurfaceFormat view_format = s->key.format;
612 const struct svga_texture *stex = svga_texture(s->base.texture);
613
614 /* Can't create RGBA render target view of a RGBX surface so adjust
615 * the view format. We do something similar for texture samplers in
616 * svga_validate_pipe_sampler_view().
617 */
618 if (view_format == SVGA3D_B8G8R8A8_UNORM &&
619 (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
620 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
621 view_format = SVGA3D_B8G8R8X8_UNORM;
622 }
623
624 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
625 s->view_id,
626 s->handle,
627 view_format,
628 resType,
629 &desc);
630 }
631
632 if (ret != PIPE_OK) {
633 util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
634 s->view_id = SVGA3D_INVALID_ID;
635 s = NULL;
636 }
637 }
638
639 SVGA_STATS_TIME_POP(svga_sws(svga));
640
641 return s ? &s->base : NULL;
642 }
643
644
645
646 static void
647 svga_surface_destroy(struct pipe_context *pipe,
648 struct pipe_surface *surf)
649 {
650 struct svga_context *svga = svga_context(pipe);
651 struct svga_surface *s = svga_surface(surf);
652 struct svga_texture *t = svga_texture(surf->texture);
653 struct svga_screen *ss = svga_screen(surf->texture->screen);
654 enum pipe_error ret = PIPE_OK;
655
656 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
657
658 /* Destroy the backed view surface if it exists */
659 if (s->backed) {
660 svga_surface_destroy(pipe, &s->backed->base);
661 s->backed = NULL;
662 }
663
664 /* Destroy the surface handle if this is a backed handle and
665 * it is not being cached in the texture.
666 */
667 if (s->handle != t->handle && s->handle != t->backed_handle) {
668 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
669 svga_screen_surface_destroy(ss, &s->key, &s->handle);
670 }
671
672 if (s->view_id != SVGA3D_INVALID_ID) {
673 unsigned try;
674
675 /* The SVGA3D device will generate a device error if the
676 * render target view or depth stencil view is destroyed from
677 * a context other than the one it was created with.
678 * Similar to shader resource view, in this case, we will skip
679 * the destroy for now.
680 */
681 if (surf->context != pipe) {
682 _debug_printf("context mismatch in %s\n", __func__);
683 }
684 else {
685 assert(svga_have_vgpu10(svga));
686 for (try = 0; try < 2; try++) {
687 if (util_format_is_depth_or_stencil(s->base.format)) {
688 ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
689 }
690 else {
691 ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
692 }
693 if (ret == PIPE_OK)
694 break;
695 svga_context_flush(svga, NULL);
696 }
697 assert(ret == PIPE_OK);
698 util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
699 }
700 }
701
702 pipe_resource_reference(&surf->texture, NULL);
703 FREE(surf);
704
705 svga->hud.num_surface_views--;
706 SVGA_STATS_TIME_POP(ss->sws);
707 }
708
709
710 static void
711 svga_mark_surface_dirty(struct pipe_surface *surf)
712 {
713 struct svga_surface *s = svga_surface(surf);
714 struct svga_texture *tex = svga_texture(surf->texture);
715
716 if (!s->dirty) {
717 s->dirty = TRUE;
718
719 if (s->handle == tex->handle) {
720 /* hmm so 3d textures always have all their slices marked ? */
721 svga_define_texture_level(tex, surf->u.tex.first_layer,
722 surf->u.tex.level);
723 }
724 else {
725 /* this will happen later in svga_propagate_surface */
726 }
727 }
728
729 /* Increment the view_age and texture age for this surface's mipmap
730 * level so that any sampler views into the texture are re-validated too.
731 * Note: we age the texture for backed surface view only when the
732 * backed surface is propagated to the original surface.
733 */
734 if (s->handle == tex->handle)
735 svga_age_texture_view(tex, surf->u.tex.level);
736 }
737
738
739 void
740 svga_mark_surfaces_dirty(struct svga_context *svga)
741 {
742 unsigned i;
743 struct svga_hw_clear_state *hw = &svga->state.hw_clear;
744
745 if (svga_have_vgpu10(svga)) {
746
747 /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface.
748 * This surface can be the backed surface.
749 */
750 for (i = 0; i < hw->num_rendertargets; i++) {
751 if (hw->rtv[i])
752 svga_mark_surface_dirty(hw->rtv[i]);
753 }
754 if (hw->dsv)
755 svga_mark_surface_dirty(hw->dsv);
756 } else {
757 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
758 if (svga->curr.framebuffer.cbufs[i])
759 svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
760 }
761 if (svga->curr.framebuffer.zsbuf)
762 svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
763 }
764 }
765
766
767 /**
768 * Progagate any changes from surfaces to texture.
769 * pipe is optional context to inline the blit command in.
770 */
771 void
772 svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
773 boolean reset)
774 {
775 struct svga_surface *s = svga_surface(surf);
776 struct svga_texture *tex = svga_texture(surf->texture);
777 struct svga_screen *ss = svga_screen(surf->texture->screen);
778
779 if (!s->dirty)
780 return;
781
782 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
783
784 /* Reset the dirty flag if specified. This is to ensure that
785 * the dirty flag will not be reset and stay unset when the backing
786 * surface is still being bound and rendered to.
787 * The reset flag will be set to TRUE when the surface is propagated
788 * and will be unbound.
789 */
790 s->dirty = !reset;
791
792 ss->texture_timestamp++;
793 svga_age_texture_view(tex, surf->u.tex.level);
794
795 if (s->handle != tex->handle) {
796 unsigned zslice, layer;
797 unsigned nlayers = 1;
798 unsigned i;
799 unsigned numMipLevels = tex->b.b.last_level + 1;
800 unsigned srcLevel = s->real_level;
801 unsigned dstLevel = surf->u.tex.level;
802 unsigned width = u_minify(tex->b.b.width0, dstLevel);
803 unsigned height = u_minify(tex->b.b.height0, dstLevel);
804
805 if (surf->texture->target == PIPE_TEXTURE_CUBE) {
806 zslice = 0;
807 layer = surf->u.tex.first_layer;
808 }
809 else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
810 surf->texture->target == PIPE_TEXTURE_2D_ARRAY ||
811 surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
812 zslice = 0;
813 layer = surf->u.tex.first_layer;
814 nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
815 }
816 else {
817 zslice = surf->u.tex.first_layer;
818 layer = 0;
819 }
820
821 SVGA_DBG(DEBUG_VIEWS,
822 "Propagate surface %p to resource %p, level %u\n",
823 surf, tex, surf->u.tex.level);
824
825 if (svga_have_vgpu10(svga)) {
826 unsigned srcSubResource, dstSubResource;
827
828 for (i = 0; i < nlayers; i++) {
829 srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel;
830 dstSubResource = (layer + i) * numMipLevels + dstLevel;
831
832 svga_texture_copy_region(svga,
833 s->handle, srcSubResource, 0, 0, 0,
834 tex->handle, dstSubResource, 0, 0, zslice,
835 width, height, 1);
836 svga_define_texture_level(tex, layer + i, dstLevel);
837 }
838 }
839 else {
840 for (i = 0; i < nlayers; i++) {
841 svga_texture_copy_handle(svga,
842 s->handle, 0, 0, 0, srcLevel,
843 s->real_layer + i,
844 tex->handle, 0, 0, zslice, dstLevel,
845 layer + i,
846 width, height, 1);
847
848 svga_define_texture_level(tex, layer + i, dstLevel);
849 }
850 }
851
852 /* Sync the surface view age with the texture age */
853 s->age = tex->age;
854
855 /* If this backed surface is cached in the texture,
856 * update the backed age as well.
857 */
858 if (tex->backed_handle == s->handle) {
859 tex->backed_age = tex->age;
860 }
861 }
862
863 SVGA_STATS_TIME_POP(ss->sws);
864 }
865
866
867 /**
868 * If any of the render targets are in backing texture views, propagate any
869 * changes to them back to the original texture.
870 */
871 void
872 svga_propagate_rendertargets(struct svga_context *svga)
873 {
874 unsigned i;
875
876 /* Early exit if there is no backing texture views in use */
877 if (!svga->state.hw_draw.has_backed_views)
878 return;
879
880 /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
881 * not the svga->curr.framebuffer surfaces, because it's the former
882 * surfaces which may be backing surface views (the actual render targets).
883 */
884 for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) {
885 struct pipe_surface *s = svga->state.hw_clear.rtv[i];
886 if (s) {
887 svga_propagate_surface(svga, s, FALSE);
888 }
889 }
890
891 if (svga->state.hw_clear.dsv) {
892 svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE);
893 }
894 }
895
896
897 /**
898 * Check if we should call svga_propagate_surface on the surface.
899 */
900 boolean
901 svga_surface_needs_propagation(const struct pipe_surface *surf)
902 {
903 const struct svga_surface *s = svga_surface_const(surf);
904 struct svga_texture *tex = svga_texture(surf->texture);
905
906 return s->dirty && s->handle != tex->handle;
907 }
908
909
910 static void
911 svga_get_sample_position(struct pipe_context *context,
912 unsigned sample_count, unsigned sample_index,
913 float *pos_out)
914 {
915 /* We can't actually query the device to learn the sample positions.
916 * These were grabbed from nvidia's driver.
917 */
918 static const float pos1[1][2] = {
919 { 0.5, 0.5 }
920 };
921 static const float pos4[4][2] = {
922 { 0.375000, 0.125000 },
923 { 0.875000, 0.375000 },
924 { 0.125000, 0.625000 },
925 { 0.625000, 0.875000 }
926 };
927 static const float pos8[8][2] = {
928 { 0.562500, 0.312500 },
929 { 0.437500, 0.687500 },
930 { 0.812500, 0.562500 },
931 { 0.312500, 0.187500 },
932 { 0.187500, 0.812500 },
933 { 0.062500, 0.437500 },
934 { 0.687500, 0.937500 },
935 { 0.937500, 0.062500 }
936 };
937 static const float pos16[16][2] = {
938 { 0.187500, 0.062500 },
939 { 0.437500, 0.187500 },
940 { 0.062500, 0.312500 },
941 { 0.312500, 0.437500 },
942 { 0.687500, 0.062500 },
943 { 0.937500, 0.187500 },
944 { 0.562500, 0.312500 },
945 { 0.812500, 0.437500 },
946 { 0.187500, 0.562500 },
947 { 0.437500, 0.687500 },
948 { 0.062500, 0.812500 },
949 { 0.312500, 0.937500 },
950 { 0.687500, 0.562500 },
951 { 0.937500, 0.687500 },
952 { 0.562500, 0.812500 },
953 { 0.812500, 0.937500 }
954 };
955 const float (*positions)[2];
956
957 switch (sample_count) {
958 case 4:
959 positions = pos4;
960 break;
961 case 8:
962 positions = pos8;
963 break;
964 case 16:
965 positions = pos16;
966 break;
967 default:
968 positions = pos1;
969 }
970
971 pos_out[0] = positions[sample_index][0];
972 pos_out[1] = positions[sample_index][1];
973 }
974
975
976 void
977 svga_init_surface_functions(struct svga_context *svga)
978 {
979 svga->pipe.create_surface = svga_create_surface;
980 svga->pipe.surface_destroy = svga_surface_destroy;
981 svga->pipe.get_sample_position = svga_get_sample_position;
982 }