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 invalidated; 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 &invalidated, 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_COMPUTE; 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->surface_state < SVGA_SURFACE_STATE_INVALIDATED) { 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->surface_state = SVGA_SURFACE_STATE_INVALIDATED; 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 resType = svga_resource_type(s->base.texture->target); 603 604 if (util_format_is_depth_or_stencil(s->base.format)) { 605 606 /* Create depth stencil view only if the resource is created 607 * with depth stencil bind flag. 608 */ 609 if (stex->key.flags & SVGA3D_SURFACE_BIND_DEPTH_STENCIL) { 610 s->view_id = util_bitmask_add(svga->surface_view_id_bm); 611 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, 612 s->view_id, 613 s->handle, 614 s->key.format, 615 resType, 616 &desc); 617 } 618 } 619 else { 620 /* Create render target view only if the resource is created 621 * with render target bind flag. 622 */ 623 if (stex->key.flags & SVGA3D_SURFACE_BIND_RENDER_TARGET) { 624 SVGA3dSurfaceFormat view_format = s->key.format; 625 626 /* Can't create RGBA render target view of a RGBX surface so adjust 627 * the view format. We do something similar for texture samplers in 628 * svga_validate_pipe_sampler_view(). 629 */ 630 if (view_format == SVGA3D_B8G8R8A8_UNORM && 631 (stex->key.format == SVGA3D_B8G8R8X8_UNORM || 632 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) { 633 view_format = SVGA3D_B8G8R8X8_UNORM; 634 } 635 636 s->view_id = util_bitmask_add(svga->surface_view_id_bm); 637 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, 638 s->view_id, 639 s->handle, 640 view_format, 641 resType, 642 &desc); 643 } 644 } 645 646 if (ret != PIPE_OK) { 647 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 648 s->view_id = SVGA3D_INVALID_ID; 649 s = NULL; 650 } 651 } 652 653 SVGA_STATS_TIME_POP(svga_sws(svga)); 654 655 return s ? &s->base : NULL; 656} 657 658 659 660static void 661svga_surface_destroy(struct pipe_context *pipe, 662 struct pipe_surface *surf) 663{ 664 struct svga_context *svga = svga_context(pipe); 665 struct svga_surface *s = svga_surface(surf); 666 struct svga_texture *t = svga_texture(surf->texture); 667 struct svga_screen *ss = svga_screen(surf->texture->screen); 668 669 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE); 670 671 /* Destroy the backed view surface if it exists */ 672 if (s->backed) { 673 svga_surface_destroy(pipe, &s->backed->base); 674 s->backed = NULL; 675 } 676 677 /* Destroy the surface handle if this is a backed handle and 678 * it is not being cached in the texture. 679 */ 680 if (s->handle != t->handle && s->handle != t->backed_handle) { 681 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); 682 svga_screen_surface_destroy(ss, &s->key, 683 svga_was_texture_rendered_to(t), 684 &s->handle); 685 } 686 687 if (s->view_id != SVGA3D_INVALID_ID) { 688 /* The SVGA3D device will generate a device error if the 689 * render target view or depth stencil view is destroyed from 690 * a context other than the one it was created with. 691 * Similar to shader resource view, in this case, we will skip 692 * the destroy for now. 693 */ 694 if (surf->context != pipe) { 695 _debug_printf("context mismatch in %s\n", __func__); 696 } 697 else { 698 assert(svga_have_vgpu10(svga)); 699 if (util_format_is_depth_or_stencil(s->base.format)) { 700 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, 701 s->view_id)); 702 } 703 else { 704 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, 705 s->view_id)); 706 } 707 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 708 } 709 } 710 711 pipe_resource_reference(&surf->texture, NULL); 712 FREE(surf); 713 714 svga->hud.num_surface_views--; 715 SVGA_STATS_TIME_POP(ss->sws); 716} 717 718 719static void 720svga_mark_surface_dirty(struct pipe_surface *surf) 721{ 722 struct svga_surface *s = svga_surface(surf); 723 struct svga_texture *tex = svga_texture(surf->texture); 724 725 if (!s->dirty) { 726 s->dirty = TRUE; 727 728 if (s->handle == tex->handle) { 729 /* hmm so 3d textures always have all their slices marked ? */ 730 svga_define_texture_level(tex, surf->u.tex.first_layer, 731 surf->u.tex.level); 732 } 733 else { 734 /* this will happen later in svga_propagate_surface */ 735 } 736 } 737 738 /* Increment the view_age and texture age for this surface's mipmap 739 * level so that any sampler views into the texture are re-validated too. 740 * Note: we age the texture for backed surface view only when the 741 * backed surface is propagated to the original surface. 742 */ 743 if (s->handle == tex->handle) 744 svga_age_texture_view(tex, surf->u.tex.level); 745} 746 747 748void 749svga_mark_surfaces_dirty(struct svga_context *svga) 750{ 751 unsigned i; 752 struct svga_hw_clear_state *hw = &svga->state.hw_clear; 753 754 if (svga_have_vgpu10(svga)) { 755 756 /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface. 757 * This surface can be the backed surface. 758 */ 759 for (i = 0; i < hw->num_rendertargets; i++) { 760 if (hw->rtv[i]) 761 svga_mark_surface_dirty(hw->rtv[i]); 762 } 763 if (hw->dsv) 764 svga_mark_surface_dirty(hw->dsv); 765 } else { 766 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { 767 if (svga->curr.framebuffer.cbufs[i]) 768 svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]); 769 } 770 if (svga->curr.framebuffer.zsbuf) 771 svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf); 772 } 773} 774 775 776/** 777 * Progagate any changes from surfaces to texture. 778 * pipe is optional context to inline the blit command in. 779 */ 780void 781svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf, 782 boolean reset) 783{ 784 struct svga_surface *s = svga_surface(surf); 785 struct svga_texture *tex = svga_texture(surf->texture); 786 struct svga_screen *ss = svga_screen(surf->texture->screen); 787 788 if (!s->dirty) 789 return; 790 791 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE); 792 793 /* Reset the dirty flag if specified. This is to ensure that 794 * the dirty flag will not be reset and stay unset when the backing 795 * surface is still being bound and rendered to. 796 * The reset flag will be set to TRUE when the surface is propagated 797 * and will be unbound. 798 */ 799 s->dirty = !reset; 800 801 ss->texture_timestamp++; 802 svga_age_texture_view(tex, surf->u.tex.level); 803 804 if (s->handle != tex->handle) { 805 unsigned zslice, layer; 806 unsigned nlayers = 1; 807 unsigned i; 808 unsigned numMipLevels = tex->b.last_level + 1; 809 unsigned srcLevel = s->real_level; 810 unsigned dstLevel = surf->u.tex.level; 811 unsigned width = u_minify(tex->b.width0, dstLevel); 812 unsigned height = u_minify(tex->b.height0, dstLevel); 813 814 if (surf->texture->target == PIPE_TEXTURE_CUBE) { 815 zslice = 0; 816 layer = surf->u.tex.first_layer; 817 } 818 else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || 819 surf->texture->target == PIPE_TEXTURE_2D_ARRAY || 820 surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) { 821 zslice = 0; 822 layer = surf->u.tex.first_layer; 823 nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; 824 } 825 else { 826 zslice = surf->u.tex.first_layer; 827 layer = 0; 828 } 829 830 SVGA_DBG(DEBUG_VIEWS, 831 "Propagate surface %p to resource %p, level %u\n", 832 surf, tex, surf->u.tex.level); 833 834 if (svga_have_vgpu10(svga)) { 835 unsigned srcSubResource, dstSubResource; 836 837 for (i = 0; i < nlayers; i++) { 838 srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel; 839 dstSubResource = (layer + i) * numMipLevels + dstLevel; 840 841 svga_texture_copy_region(svga, 842 s->handle, srcSubResource, 0, 0, 0, 843 tex->handle, dstSubResource, 0, 0, zslice, 844 width, height, 1); 845 svga_define_texture_level(tex, layer + i, dstLevel); 846 } 847 } 848 else { 849 for (i = 0; i < nlayers; i++) { 850 svga_texture_copy_handle(svga, 851 s->handle, 0, 0, 0, srcLevel, 852 s->real_layer + i, 853 tex->handle, 0, 0, zslice, dstLevel, 854 layer + i, 855 width, height, 1); 856 857 svga_define_texture_level(tex, layer + i, dstLevel); 858 } 859 } 860 861 /* Sync the surface view age with the texture age */ 862 s->age = tex->age; 863 864 /* If this backed surface is cached in the texture, 865 * update the backed age as well. 866 */ 867 if (tex->backed_handle == s->handle) { 868 tex->backed_age = tex->age; 869 } 870 } 871 872 SVGA_STATS_TIME_POP(ss->sws); 873} 874 875 876/** 877 * If any of the render targets are in backing texture views, propagate any 878 * changes to them back to the original texture. 879 */ 880void 881svga_propagate_rendertargets(struct svga_context *svga) 882{ 883 unsigned i; 884 885 /* Early exit if there is no backing texture views in use */ 886 if (!svga->state.hw_draw.has_backed_views) 887 return; 888 889 /* Note that we examine the svga->state.hw_draw.framebuffer surfaces, 890 * not the svga->curr.framebuffer surfaces, because it's the former 891 * surfaces which may be backing surface views (the actual render targets). 892 */ 893 for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) { 894 struct pipe_surface *s = svga->state.hw_clear.rtv[i]; 895 if (s) { 896 svga_propagate_surface(svga, s, FALSE); 897 } 898 } 899 900 if (svga->state.hw_clear.dsv) { 901 svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE); 902 } 903} 904 905 906/** 907 * Check if we should call svga_propagate_surface on the surface. 908 */ 909boolean 910svga_surface_needs_propagation(const struct pipe_surface *surf) 911{ 912 const struct svga_surface *s = svga_surface_const(surf); 913 struct svga_texture *tex = svga_texture(surf->texture); 914 915 return s->dirty && s->handle != tex->handle; 916} 917 918 919static void 920svga_get_sample_position(struct pipe_context *context, 921 unsigned sample_count, unsigned sample_index, 922 float *pos_out) 923{ 924 /* We can't actually query the device to learn the sample positions. 925 * These were grabbed from nvidia's driver. 926 */ 927 static const float pos1[1][2] = { 928 { 0.5, 0.5 } 929 }; 930 static const float pos2[2][2] = { 931 { 0.75, 0.75 }, 932 { 0.25, 0.25 } 933 }; 934 static const float pos4[4][2] = { 935 { 0.375000, 0.125000 }, 936 { 0.875000, 0.375000 }, 937 { 0.125000, 0.625000 }, 938 { 0.625000, 0.875000 } 939 }; 940 static const float pos8[8][2] = { 941 { 0.562500, 0.312500 }, 942 { 0.437500, 0.687500 }, 943 { 0.812500, 0.562500 }, 944 { 0.312500, 0.187500 }, 945 { 0.187500, 0.812500 }, 946 { 0.062500, 0.437500 }, 947 { 0.687500, 0.937500 }, 948 { 0.937500, 0.062500 } 949 }; 950 static const float pos16[16][2] = { 951 { 0.187500, 0.062500 }, 952 { 0.437500, 0.187500 }, 953 { 0.062500, 0.312500 }, 954 { 0.312500, 0.437500 }, 955 { 0.687500, 0.062500 }, 956 { 0.937500, 0.187500 }, 957 { 0.562500, 0.312500 }, 958 { 0.812500, 0.437500 }, 959 { 0.187500, 0.562500 }, 960 { 0.437500, 0.687500 }, 961 { 0.062500, 0.812500 }, 962 { 0.312500, 0.937500 }, 963 { 0.687500, 0.562500 }, 964 { 0.937500, 0.687500 }, 965 { 0.562500, 0.812500 }, 966 { 0.812500, 0.937500 } 967 }; 968 const float (*positions)[2]; 969 970 switch (sample_count) { 971 case 2: 972 positions = pos2; 973 break; 974 case 4: 975 positions = pos4; 976 break; 977 case 8: 978 positions = pos8; 979 break; 980 case 16: 981 positions = pos16; 982 break; 983 default: 984 positions = pos1; 985 } 986 987 pos_out[0] = positions[sample_index][0]; 988 pos_out[1] = positions[sample_index][1]; 989} 990 991 992void 993svga_init_surface_functions(struct svga_context *svga) 994{ 995 svga->pipe.create_surface = svga_create_surface; 996 svga->pipe.surface_destroy = svga_surface_destroy; 997 svga->pipe.get_sample_position = svga_get_sample_position; 998} 999