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