svga_surface.c revision 7ec681f3
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 45static void svga_mark_surface_dirty(struct pipe_surface *surf); 46 47void 48svga_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 77void 78svga_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 */ 130static void 131svga_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.depth0, miplevel) : 1); 156 157 if (src_tex->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.width0, src_tex->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.width0, miplevel), 172 u_minify(src_tex->b.height0, miplevel), 173 depth); 174 } 175 } 176 } 177 } 178} 179 180 181struct svga_winsys_surface * 182svga_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.width0, start_mip); 210 key->size.height = u_minify(tex->b.height0, start_mip); 211 key->size.depth = zslice_pick < 0 ? u_minify(tex->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.nr_samples > 1 ? tex->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.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { 225 key->flags |= SVGA3D_SURFACE_CUBEMAP; 226 key->numFaces = 6; 227 } else if (tex->b.target == PIPE_TEXTURE_1D_ARRAY || 228 tex->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 271done: 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 clone_resource boolean flag specifies whether to clone the resource 281 * for the surface view. 282 */ 283static struct pipe_surface * 284svga_create_surface_view(struct pipe_context *pipe, 285 struct pipe_resource *pt, 286 const struct pipe_surface *surf_tmpl, 287 boolean clone_resource) 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 (clone_resource) { 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 425done: 426 SVGA_STATS_TIME_POP(ss->sws); 427 return retVal; 428} 429 430 431static struct pipe_surface * 432svga_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 * Create an alternate surface view and clone the resource if specified 466 */ 467static struct svga_surface * 468create_backed_surface_view(struct svga_context *svga, struct svga_surface *s, 469 boolean clone_resource) 470{ 471 struct svga_texture *tex = svga_texture(s->base.texture); 472 473 if (!s->backed) { 474 struct pipe_surface *backed_view; 475 476 SVGA_STATS_TIME_PUSH(svga_sws(svga), 477 SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW); 478 479 backed_view = svga_create_surface_view(&svga->pipe, 480 &tex->b, 481 &s->base, 482 clone_resource); 483 if (!backed_view) 484 goto done; 485 486 s->backed = svga_surface(backed_view); 487 488 SVGA_STATS_TIME_POP(svga_sws(svga)); 489 } 490 else if (s->backed->handle != tex->handle && 491 s->backed->age < tex->age) { 492 /* 493 * There is already an existing backing surface, but we still need to 494 * sync the backing resource if the original resource has been modified 495 * since the last copy. 496 */ 497 struct svga_surface *bs = s->backed; 498 unsigned int layer, zslice; 499 500 assert(bs->handle); 501 502 switch (tex->b.target) { 503 case PIPE_TEXTURE_CUBE: 504 case PIPE_TEXTURE_CUBE_ARRAY: 505 case PIPE_TEXTURE_1D_ARRAY: 506 case PIPE_TEXTURE_2D_ARRAY: 507 layer = s->base.u.tex.first_layer; 508 zslice = 0; 509 break; 510 default: 511 layer = 0; 512 zslice = s->base.u.tex.first_layer; 513 } 514 515 svga_texture_copy_handle_resource(svga, tex, bs->handle, 516 bs->key.numMipLevels, 517 bs->key.numFaces * bs->key.arraySize, 518 zslice, s->base.u.tex.level, layer); 519 } 520 521 svga_mark_surface_dirty(&s->backed->base); 522 s->backed->age = tex->age; 523 524 assert(s->backed->base.context == &svga->pipe); 525 526done: 527 return s->backed; 528} 529 530/** 531 * Create a DX RenderTarget/DepthStencil View for the given surface, 532 * if needed. 533 */ 534struct pipe_surface * 535svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) 536{ 537 enum pipe_error ret = PIPE_OK; 538 enum pipe_shader_type shader; 539 540 assert(svga_have_vgpu10(svga)); 541 assert(s); 542 543 SVGA_STATS_TIME_PUSH(svga_sws(svga), 544 SVGA_STATS_TIME_VALIDATESURFACEVIEW); 545 546 /** 547 * DX spec explicitly specifies that no resource can be bound to a render 548 * target view and a shader resource view simultaneously. 549 * So first check if the resource bound to this surface view collides with 550 * a sampler view. If so, then we will clone this surface view and its 551 * associated resource. We will then use the cloned surface view for 552 * render target. 553 */ 554 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) { 555 if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) { 556 SVGA_DBG(DEBUG_VIEWS, 557 "same resource used in shaderResource and renderTarget 0x%x\n", 558 s->handle); 559 s = create_backed_surface_view(svga, s, TRUE); 560 561 if (s) 562 svga->state.hw_draw.has_backed_views = TRUE; 563 564 /* s may be null here if the function failed */ 565 break; 566 } 567 } 568 569 /** 570 * Create an alternate surface view for the specified context if the 571 * view was created for another context. 572 */ 573 if (s && s->base.context != &svga->pipe) { 574 s = create_backed_surface_view(svga, s, FALSE); 575 576 if (s) 577 svga->state.hw_draw.has_backed_views = TRUE; 578 } 579 580 if (s && s->view_id == SVGA3D_INVALID_ID) { 581 SVGA3dResourceType resType; 582 SVGA3dRenderTargetViewDesc desc; 583 struct svga_texture *stex = svga_texture(s->base.texture); 584 585 if (stex->validated == FALSE) { 586 assert(stex->handle); 587 588 /* We are about to render into a surface that has not been validated. 589 * First invalidate the surface so that the device does not 590 * need to update the host-side copy with the invalid 591 * content when the associated mob is first bound to the surface. 592 */ 593 SVGA_RETRY(svga, SVGA3D_InvalidateGBSurface(svga->swc, stex->handle)); 594 stex->validated = TRUE; 595 } 596 597 desc.tex.mipSlice = s->real_level; 598 desc.tex.firstArraySlice = s->real_layer + s->real_zslice; 599 desc.tex.arraySize = 600 s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1; 601 602 s->view_id = util_bitmask_add(svga->surface_view_id_bm); 603 604 resType = svga_resource_type(s->base.texture->target); 605 606 if (util_format_is_depth_or_stencil(s->base.format)) { 607 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, 608 s->view_id, 609 s->handle, 610 s->key.format, 611 resType, 612 &desc); 613 } 614 else { 615 SVGA3dSurfaceFormat view_format = s->key.format; 616 const struct svga_texture *stex = svga_texture(s->base.texture); 617 618 /* Can't create RGBA render target view of a RGBX surface so adjust 619 * the view format. We do something similar for texture samplers in 620 * svga_validate_pipe_sampler_view(). 621 */ 622 if (view_format == SVGA3D_B8G8R8A8_UNORM && 623 (stex->key.format == SVGA3D_B8G8R8X8_UNORM || 624 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) { 625 view_format = SVGA3D_B8G8R8X8_UNORM; 626 } 627 628 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, 629 s->view_id, 630 s->handle, 631 view_format, 632 resType, 633 &desc); 634 } 635 636 if (ret != PIPE_OK) { 637 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 638 s->view_id = SVGA3D_INVALID_ID; 639 s = NULL; 640 } 641 } 642 643 SVGA_STATS_TIME_POP(svga_sws(svga)); 644 645 return s ? &s->base : NULL; 646} 647 648 649 650static void 651svga_surface_destroy(struct pipe_context *pipe, 652 struct pipe_surface *surf) 653{ 654 struct svga_context *svga = svga_context(pipe); 655 struct svga_surface *s = svga_surface(surf); 656 struct svga_texture *t = svga_texture(surf->texture); 657 struct svga_screen *ss = svga_screen(surf->texture->screen); 658 659 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE); 660 661 /* Destroy the backed view surface if it exists */ 662 if (s->backed) { 663 svga_surface_destroy(pipe, &s->backed->base); 664 s->backed = NULL; 665 } 666 667 /* Destroy the surface handle if this is a backed handle and 668 * it is not being cached in the texture. 669 */ 670 if (s->handle != t->handle && s->handle != t->backed_handle) { 671 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); 672 svga_screen_surface_destroy(ss, &s->key, &s->handle); 673 } 674 675 if (s->view_id != SVGA3D_INVALID_ID) { 676 /* The SVGA3D device will generate a device error if the 677 * render target view or depth stencil view is destroyed from 678 * a context other than the one it was created with. 679 * Similar to shader resource view, in this case, we will skip 680 * the destroy for now. 681 */ 682 if (surf->context != pipe) { 683 _debug_printf("context mismatch in %s\n", __func__); 684 } 685 else { 686 assert(svga_have_vgpu10(svga)); 687 if (util_format_is_depth_or_stencil(s->base.format)) { 688 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, 689 s->view_id)); 690 } 691 else { 692 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, 693 s->view_id)); 694 } 695 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 696 } 697 } 698 699 pipe_resource_reference(&surf->texture, NULL); 700 FREE(surf); 701 702 svga->hud.num_surface_views--; 703 SVGA_STATS_TIME_POP(ss->sws); 704} 705 706 707static void 708svga_mark_surface_dirty(struct pipe_surface *surf) 709{ 710 struct svga_surface *s = svga_surface(surf); 711 struct svga_texture *tex = svga_texture(surf->texture); 712 713 if (!s->dirty) { 714 s->dirty = TRUE; 715 716 if (s->handle == tex->handle) { 717 /* hmm so 3d textures always have all their slices marked ? */ 718 svga_define_texture_level(tex, surf->u.tex.first_layer, 719 surf->u.tex.level); 720 } 721 else { 722 /* this will happen later in svga_propagate_surface */ 723 } 724 } 725 726 /* Increment the view_age and texture age for this surface's mipmap 727 * level so that any sampler views into the texture are re-validated too. 728 * Note: we age the texture for backed surface view only when the 729 * backed surface is propagated to the original surface. 730 */ 731 if (s->handle == tex->handle) 732 svga_age_texture_view(tex, surf->u.tex.level); 733} 734 735 736void 737svga_mark_surfaces_dirty(struct svga_context *svga) 738{ 739 unsigned i; 740 struct svga_hw_clear_state *hw = &svga->state.hw_clear; 741 742 if (svga_have_vgpu10(svga)) { 743 744 /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface. 745 * This surface can be the backed surface. 746 */ 747 for (i = 0; i < hw->num_rendertargets; i++) { 748 if (hw->rtv[i]) 749 svga_mark_surface_dirty(hw->rtv[i]); 750 } 751 if (hw->dsv) 752 svga_mark_surface_dirty(hw->dsv); 753 } else { 754 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { 755 if (svga->curr.framebuffer.cbufs[i]) 756 svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]); 757 } 758 if (svga->curr.framebuffer.zsbuf) 759 svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf); 760 } 761} 762 763 764/** 765 * Progagate any changes from surfaces to texture. 766 * pipe is optional context to inline the blit command in. 767 */ 768void 769svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf, 770 boolean reset) 771{ 772 struct svga_surface *s = svga_surface(surf); 773 struct svga_texture *tex = svga_texture(surf->texture); 774 struct svga_screen *ss = svga_screen(surf->texture->screen); 775 776 if (!s->dirty) 777 return; 778 779 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE); 780 781 /* Reset the dirty flag if specified. This is to ensure that 782 * the dirty flag will not be reset and stay unset when the backing 783 * surface is still being bound and rendered to. 784 * The reset flag will be set to TRUE when the surface is propagated 785 * and will be unbound. 786 */ 787 s->dirty = !reset; 788 789 ss->texture_timestamp++; 790 svga_age_texture_view(tex, surf->u.tex.level); 791 792 if (s->handle != tex->handle) { 793 unsigned zslice, layer; 794 unsigned nlayers = 1; 795 unsigned i; 796 unsigned numMipLevels = tex->b.last_level + 1; 797 unsigned srcLevel = s->real_level; 798 unsigned dstLevel = surf->u.tex.level; 799 unsigned width = u_minify(tex->b.width0, dstLevel); 800 unsigned height = u_minify(tex->b.height0, dstLevel); 801 802 if (surf->texture->target == PIPE_TEXTURE_CUBE) { 803 zslice = 0; 804 layer = surf->u.tex.first_layer; 805 } 806 else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || 807 surf->texture->target == PIPE_TEXTURE_2D_ARRAY || 808 surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) { 809 zslice = 0; 810 layer = surf->u.tex.first_layer; 811 nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; 812 } 813 else { 814 zslice = surf->u.tex.first_layer; 815 layer = 0; 816 } 817 818 SVGA_DBG(DEBUG_VIEWS, 819 "Propagate surface %p to resource %p, level %u\n", 820 surf, tex, surf->u.tex.level); 821 822 if (svga_have_vgpu10(svga)) { 823 unsigned srcSubResource, dstSubResource; 824 825 for (i = 0; i < nlayers; i++) { 826 srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel; 827 dstSubResource = (layer + i) * numMipLevels + dstLevel; 828 829 svga_texture_copy_region(svga, 830 s->handle, srcSubResource, 0, 0, 0, 831 tex->handle, dstSubResource, 0, 0, zslice, 832 width, height, 1); 833 svga_define_texture_level(tex, layer + i, dstLevel); 834 } 835 } 836 else { 837 for (i = 0; i < nlayers; i++) { 838 svga_texture_copy_handle(svga, 839 s->handle, 0, 0, 0, srcLevel, 840 s->real_layer + i, 841 tex->handle, 0, 0, zslice, dstLevel, 842 layer + i, 843 width, height, 1); 844 845 svga_define_texture_level(tex, layer + i, dstLevel); 846 } 847 } 848 849 /* Sync the surface view age with the texture age */ 850 s->age = tex->age; 851 852 /* If this backed surface is cached in the texture, 853 * update the backed age as well. 854 */ 855 if (tex->backed_handle == s->handle) { 856 tex->backed_age = tex->age; 857 } 858 } 859 860 SVGA_STATS_TIME_POP(ss->sws); 861} 862 863 864/** 865 * If any of the render targets are in backing texture views, propagate any 866 * changes to them back to the original texture. 867 */ 868void 869svga_propagate_rendertargets(struct svga_context *svga) 870{ 871 unsigned i; 872 873 /* Early exit if there is no backing texture views in use */ 874 if (!svga->state.hw_draw.has_backed_views) 875 return; 876 877 /* Note that we examine the svga->state.hw_draw.framebuffer surfaces, 878 * not the svga->curr.framebuffer surfaces, because it's the former 879 * surfaces which may be backing surface views (the actual render targets). 880 */ 881 for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) { 882 struct pipe_surface *s = svga->state.hw_clear.rtv[i]; 883 if (s) { 884 svga_propagate_surface(svga, s, FALSE); 885 } 886 } 887 888 if (svga->state.hw_clear.dsv) { 889 svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE); 890 } 891} 892 893 894/** 895 * Check if we should call svga_propagate_surface on the surface. 896 */ 897boolean 898svga_surface_needs_propagation(const struct pipe_surface *surf) 899{ 900 const struct svga_surface *s = svga_surface_const(surf); 901 struct svga_texture *tex = svga_texture(surf->texture); 902 903 return s->dirty && s->handle != tex->handle; 904} 905 906 907static void 908svga_get_sample_position(struct pipe_context *context, 909 unsigned sample_count, unsigned sample_index, 910 float *pos_out) 911{ 912 /* We can't actually query the device to learn the sample positions. 913 * These were grabbed from nvidia's driver. 914 */ 915 static const float pos1[1][2] = { 916 { 0.5, 0.5 } 917 }; 918 static const float pos2[2][2] = { 919 { 0.75, 0.75 }, 920 { 0.25, 0.25 } 921 }; 922 static const float pos4[4][2] = { 923 { 0.375000, 0.125000 }, 924 { 0.875000, 0.375000 }, 925 { 0.125000, 0.625000 }, 926 { 0.625000, 0.875000 } 927 }; 928 static const float pos8[8][2] = { 929 { 0.562500, 0.312500 }, 930 { 0.437500, 0.687500 }, 931 { 0.812500, 0.562500 }, 932 { 0.312500, 0.187500 }, 933 { 0.187500, 0.812500 }, 934 { 0.062500, 0.437500 }, 935 { 0.687500, 0.937500 }, 936 { 0.937500, 0.062500 } 937 }; 938 static const float pos16[16][2] = { 939 { 0.187500, 0.062500 }, 940 { 0.437500, 0.187500 }, 941 { 0.062500, 0.312500 }, 942 { 0.312500, 0.437500 }, 943 { 0.687500, 0.062500 }, 944 { 0.937500, 0.187500 }, 945 { 0.562500, 0.312500 }, 946 { 0.812500, 0.437500 }, 947 { 0.187500, 0.562500 }, 948 { 0.437500, 0.687500 }, 949 { 0.062500, 0.812500 }, 950 { 0.312500, 0.937500 }, 951 { 0.687500, 0.562500 }, 952 { 0.937500, 0.687500 }, 953 { 0.562500, 0.812500 }, 954 { 0.812500, 0.937500 } 955 }; 956 const float (*positions)[2]; 957 958 switch (sample_count) { 959 case 2: 960 positions = pos2; 961 break; 962 case 4: 963 positions = pos4; 964 break; 965 case 8: 966 positions = pos8; 967 break; 968 case 16: 969 positions = pos16; 970 break; 971 default: 972 positions = pos1; 973 } 974 975 pos_out[0] = positions[sample_index][0]; 976 pos_out[1] = positions[sample_index][1]; 977} 978 979 980void 981svga_init_surface_functions(struct svga_context *svga) 982{ 983 svga->pipe.create_surface = svga_create_surface; 984 svga->pipe.surface_destroy = svga_surface_destroy; 985 svga->pipe.get_sample_position = svga_get_sample_position; 986} 987