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