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