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