1/********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26#include "svga_cmd.h" 27 28#include "pipe/p_state.h" 29#include "pipe/p_defines.h" 30#include "util/u_inlines.h" 31#include "os/os_thread.h" 32#include "util/u_bitmask.h" 33#include "util/u_format.h" 34#include "util/u_math.h" 35#include "util/u_memory.h" 36 37#include "svga_format.h" 38#include "svga_screen.h" 39#include "svga_context.h" 40#include "svga_sampler_view.h" 41#include "svga_resource_texture.h" 42#include "svga_surface.h" 43#include "svga_debug.h" 44 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 enum pipe_error ret; 58 SVGA3dCopyBox box; 59 60 assert(svga_have_vgpu10(svga)); 61 62 box.x = dst_x; 63 box.y = dst_y; 64 box.z = dst_z; 65 box.w = width; 66 box.h = height; 67 box.d = depth; 68 box.srcx = src_x; 69 box.srcy = src_y; 70 box.srcz = src_z; 71 72 ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, 73 dst_handle, dstSubResource, 74 src_handle, srcSubResource, &box); 75 if (ret != PIPE_OK) { 76 svga_context_flush(svga, NULL); 77 ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, 78 dst_handle, dstSubResource, 79 src_handle, srcSubResource, &box); 80 assert(ret == PIPE_OK); 81 } 82} 83 84 85void 86svga_texture_copy_handle(struct svga_context *svga, 87 struct svga_winsys_surface *src_handle, 88 unsigned src_x, unsigned src_y, unsigned src_z, 89 unsigned src_level, unsigned src_layer, 90 struct svga_winsys_surface *dst_handle, 91 unsigned dst_x, unsigned dst_y, unsigned dst_z, 92 unsigned dst_level, unsigned dst_layer, 93 unsigned width, unsigned height, unsigned depth) 94{ 95 struct svga_surface dst, src; 96 enum pipe_error ret; 97 SVGA3dCopyBox box, *boxes; 98 99 assert(svga); 100 101 src.handle = src_handle; 102 src.real_level = src_level; 103 src.real_layer = src_layer; 104 src.real_zslice = 0; 105 106 dst.handle = dst_handle; 107 dst.real_level = dst_level; 108 dst.real_layer = dst_layer; 109 dst.real_zslice = 0; 110 111 box.x = dst_x; 112 box.y = dst_y; 113 box.z = dst_z; 114 box.w = width; 115 box.h = height; 116 box.d = depth; 117 box.srcx = src_x; 118 box.srcy = src_y; 119 box.srcz = src_z; 120 121/* 122 SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n", 123 src_handle, src_level, src_x, src_y, src_z, 124 dst_handle, dst_level, dst_x, dst_y, dst_z); 125*/ 126 127 ret = SVGA3D_BeginSurfaceCopy(svga->swc, 128 &src.base, 129 &dst.base, 130 &boxes, 1); 131 if (ret != PIPE_OK) { 132 svga_context_flush(svga, NULL); 133 ret = SVGA3D_BeginSurfaceCopy(svga->swc, 134 &src.base, 135 &dst.base, 136 &boxes, 1); 137 assert(ret == PIPE_OK); 138 } 139 *boxes = box; 140 SVGA_FIFOCommitAll(svga->swc); 141} 142 143 144/* A helper function to sync up the two surface handles. 145 */ 146static void 147svga_texture_copy_handle_resource(struct svga_context *svga, 148 struct svga_texture *src_tex, 149 struct svga_winsys_surface *dst, 150 unsigned int numMipLevels, 151 unsigned int numLayers, 152 int zslice_pick, 153 unsigned int mipoffset, 154 unsigned int layeroffset) 155{ 156 unsigned int i, j; 157 unsigned int zoffset = 0; 158 159 /* A negative zslice_pick implies zoffset at 0, and depth to copy is 160 * from the depth of the texture at the particular mipmap level. 161 */ 162 if (zslice_pick >= 0) 163 zoffset = zslice_pick; 164 165 for (i = 0; i < numMipLevels; i++) { 166 unsigned int miplevel = i + mipoffset; 167 168 for (j = 0; j < numLayers; j++) { 169 if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) { 170 unsigned depth = (zslice_pick < 0 ? 171 u_minify(src_tex->b.b.depth0, miplevel) : 1); 172 173 if (src_tex->b.b.nr_samples > 1) { 174 unsigned subResource = j * numMipLevels + i; 175 svga_texture_copy_region(svga, src_tex->handle, 176 subResource, 0, 0, zoffset, 177 dst, subResource, 0, 0, 0, 178 src_tex->b.b.width0, src_tex->b.b.height0, depth); 179 } 180 else { 181 svga_texture_copy_handle(svga, 182 src_tex->handle, 183 0, 0, zoffset, 184 miplevel, 185 j + layeroffset, 186 dst, 0, 0, 0, i, j, 187 u_minify(src_tex->b.b.width0, miplevel), 188 u_minify(src_tex->b.b.height0, miplevel), 189 depth); 190 } 191 } 192 } 193 } 194} 195 196 197struct svga_winsys_surface * 198svga_texture_view_surface(struct svga_context *svga, 199 struct svga_texture *tex, 200 unsigned bind_flags, 201 SVGA3dSurfaceAllFlags flags, 202 SVGA3dSurfaceFormat format, 203 unsigned start_mip, 204 unsigned num_mip, 205 int layer_pick, 206 unsigned num_layers, 207 int zslice_pick, 208 boolean cacheable, 209 struct svga_host_surface_cache_key *key) /* OUT */ 210{ 211 struct svga_screen *ss = svga_screen(svga->pipe.screen); 212 struct svga_winsys_surface *handle = NULL; 213 boolean validated; 214 boolean needCopyResource; 215 216 SVGA_DBG(DEBUG_PERF, 217 "svga: Create surface view: layer %d zslice %d mips %d..%d\n", 218 layer_pick, zslice_pick, start_mip, start_mip+num_mip-1); 219 220 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW); 221 222 key->flags = flags; 223 key->format = format; 224 key->numMipLevels = num_mip; 225 key->size.width = u_minify(tex->b.b.width0, start_mip); 226 key->size.height = u_minify(tex->b.b.height0, start_mip); 227 key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1; 228 key->cachable = 1; 229 key->arraySize = 1; 230 key->numFaces = 1; 231 232 /* single sample surface can be treated as non-multisamples surface */ 233 key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0; 234 235 if (key->sampleCount > 1) { 236 assert(ss->sws->have_sm4_1); 237 key->flags |= SVGA3D_SURFACE_MULTISAMPLE; 238 } 239 240 if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { 241 key->flags |= SVGA3D_SURFACE_CUBEMAP; 242 key->numFaces = 6; 243 } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY || 244 tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) { 245 key->arraySize = num_layers; 246 } 247 248 if (key->format == SVGA3D_FORMAT_INVALID) { 249 key->cachable = 0; 250 goto done; 251 } 252 253 if (cacheable && tex->backed_handle && 254 memcmp(key, &tex->backed_key, sizeof *key) == 0) { 255 handle = tex->backed_handle; 256 needCopyResource = tex->backed_age < tex->age; 257 } else { 258 SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); 259 handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, 260 &validated, key); 261 needCopyResource = TRUE; 262 263 if (cacheable && !tex->backed_handle) { 264 tex->backed_handle = handle; 265 memcpy(&tex->backed_key, key, sizeof *key); 266 } 267 } 268 269 if (!handle) { 270 key->cachable = 0; 271 goto done; 272 } 273 274 SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); 275 276 if (layer_pick < 0) 277 layer_pick = 0; 278 279 if (needCopyResource) { 280 svga_texture_copy_handle_resource(svga, tex, handle, 281 key->numMipLevels, 282 key->numFaces * key->arraySize, 283 zslice_pick, start_mip, layer_pick); 284 tex->backed_age = tex->age; 285 } 286 287done: 288 SVGA_STATS_TIME_POP(ss->sws); 289 290 return handle; 291} 292 293 294/** 295 * A helper function to create a surface view. 296 * The view boolean flag specifies whether svga_texture_view_surface() 297 * will be called to create a cloned surface and resource for the view. 298 */ 299static struct pipe_surface * 300svga_create_surface_view(struct pipe_context *pipe, 301 struct pipe_resource *pt, 302 const struct pipe_surface *surf_tmpl, 303 boolean view) 304{ 305 struct svga_context *svga = svga_context(pipe); 306 struct svga_texture *tex = svga_texture(pt); 307 struct pipe_screen *screen = pipe->screen; 308 struct svga_screen *ss = svga_screen(screen); 309 struct svga_surface *s; 310 unsigned layer, zslice, bind; 311 unsigned nlayers = 1; 312 SVGA3dSurfaceAllFlags flags = 0; 313 SVGA3dSurfaceFormat format; 314 struct pipe_surface *retVal = NULL; 315 316 s = CALLOC_STRUCT(svga_surface); 317 if (!s) 318 return NULL; 319 320 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW); 321 322 if (pt->target == PIPE_TEXTURE_CUBE) { 323 layer = surf_tmpl->u.tex.first_layer; 324 zslice = 0; 325 } 326 else if (pt->target == PIPE_TEXTURE_1D_ARRAY || 327 pt->target == PIPE_TEXTURE_2D_ARRAY || 328 pt->target == PIPE_TEXTURE_CUBE_ARRAY) { 329 layer = surf_tmpl->u.tex.first_layer; 330 zslice = 0; 331 nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1; 332 } 333 else { 334 layer = 0; 335 zslice = surf_tmpl->u.tex.first_layer; 336 } 337 338 pipe_reference_init(&s->base.reference, 1); 339 pipe_resource_reference(&s->base.texture, pt); 340 s->base.context = pipe; 341 s->base.format = surf_tmpl->format; 342 s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level); 343 s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level); 344 s->base.u.tex.level = surf_tmpl->u.tex.level; 345 s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; 346 s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; 347 s->view_id = SVGA3D_INVALID_ID; 348 349 s->backed = NULL; 350 351 if (util_format_is_depth_or_stencil(surf_tmpl->format)) { 352 flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL | 353 SVGA3D_SURFACE_BIND_DEPTH_STENCIL; 354 bind = PIPE_BIND_DEPTH_STENCIL; 355 } 356 else { 357 flags = SVGA3D_SURFACE_HINT_RENDERTARGET | 358 SVGA3D_SURFACE_BIND_RENDER_TARGET; 359 bind = PIPE_BIND_RENDER_TARGET; 360 } 361 362 if (tex->imported) { 363 /* imported resource (a window) */ 364 format = tex->key.format; 365 if (util_format_is_srgb(surf_tmpl->format)) { 366 /* sRGB rendering to window */ 367 format = svga_linear_to_srgb(format); 368 } 369 } 370 else { 371 format = svga_translate_format(ss, surf_tmpl->format, bind); 372 } 373 374 assert(format != SVGA3D_FORMAT_INVALID); 375 376 if (view) { 377 SVGA_DBG(DEBUG_VIEWS, 378 "New backed surface view: resource %p, level %u layer %u z %u, %p\n", 379 pt, surf_tmpl->u.tex.level, layer, zslice, s); 380 381 if (svga_have_vgpu10(svga)) { 382 switch (pt->target) { 383 case PIPE_TEXTURE_1D: 384 flags |= SVGA3D_SURFACE_1D; 385 break; 386 case PIPE_TEXTURE_1D_ARRAY: 387 flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY; 388 break; 389 case PIPE_TEXTURE_2D_ARRAY: 390 flags |= SVGA3D_SURFACE_ARRAY; 391 break; 392 case PIPE_TEXTURE_3D: 393 flags |= SVGA3D_SURFACE_VOLUME; 394 break; 395 case PIPE_TEXTURE_CUBE: 396 if (nlayers == 6) 397 flags |= SVGA3D_SURFACE_CUBEMAP; 398 break; 399 case PIPE_TEXTURE_CUBE_ARRAY: 400 if (nlayers % 6 == 0) 401 flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY; 402 break; 403 default: 404 break; 405 } 406 } 407 408 /* When we clone the surface view resource, use the format used in 409 * the creation of the original resource. 410 */ 411 s->handle = svga_texture_view_surface(svga, tex, bind, flags, 412 tex->key.format, 413 surf_tmpl->u.tex.level, 1, 414 layer, nlayers, zslice, 415 TRUE, &s->key); 416 if (!s->handle) { 417 FREE(s); 418 goto done; 419 } 420 421 s->key.format = format; 422 s->real_layer = 0; 423 s->real_level = 0; 424 s->real_zslice = 0; 425 } else { 426 SVGA_DBG(DEBUG_VIEWS, 427 "New surface view: resource %p, level %u, layer %u, z %u, %p\n", 428 pt, surf_tmpl->u.tex.level, layer, zslice, s); 429 430 memset(&s->key, 0, sizeof s->key); 431 s->key.format = format; 432 s->handle = tex->handle; 433 s->real_layer = layer; 434 s->real_zslice = zslice; 435 s->real_level = surf_tmpl->u.tex.level; 436 } 437 438 svga->hud.num_surface_views++; 439 retVal = &s->base; 440 441done: 442 SVGA_STATS_TIME_POP(ss->sws); 443 return retVal; 444} 445 446 447static struct pipe_surface * 448svga_create_surface(struct pipe_context *pipe, 449 struct pipe_resource *pt, 450 const struct pipe_surface *surf_tmpl) 451{ 452 struct svga_context *svga = svga_context(pipe); 453 struct pipe_screen *screen = pipe->screen; 454 struct pipe_surface *surf = NULL; 455 boolean view = FALSE; 456 457 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE); 458 459 if (svga_screen(screen)->debug.force_surface_view) 460 view = TRUE; 461 462 if (surf_tmpl->u.tex.level != 0 && 463 svga_screen(screen)->debug.force_level_surface_view) 464 view = TRUE; 465 466 if (pt->target == PIPE_TEXTURE_3D) 467 view = TRUE; 468 469 if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view) 470 view = FALSE; 471 472 surf = svga_create_surface_view(pipe, pt, surf_tmpl, view); 473 474 SVGA_STATS_TIME_POP(svga_sws(svga)); 475 476 return surf; 477} 478 479 480/** 481 * Clone the surface view and its associated resource. 482 */ 483static struct svga_surface * 484create_backed_surface_view(struct svga_context *svga, struct svga_surface *s) 485{ 486 struct svga_texture *tex = svga_texture(s->base.texture); 487 488 if (!s->backed) { 489 struct pipe_surface *backed_view; 490 491 SVGA_STATS_TIME_PUSH(svga_sws(svga), 492 SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW); 493 494 backed_view = svga_create_surface_view(&svga->pipe, 495 &tex->b.b, 496 &s->base, 497 TRUE); 498 if (!backed_view) 499 goto done; 500 501 s->backed = svga_surface(backed_view); 502 503 SVGA_STATS_TIME_POP(svga_sws(svga)); 504 } 505 else if (s->backed->age < tex->age) { 506 /* 507 * There is already an existing backing surface, but we still need to 508 * sync the backing resource if the original resource has been modified 509 * since the last copy. 510 */ 511 struct svga_surface *bs = s->backed; 512 unsigned int layer, zslice; 513 514 assert(bs->handle); 515 516 switch (tex->b.b.target) { 517 case PIPE_TEXTURE_CUBE: 518 case PIPE_TEXTURE_CUBE_ARRAY: 519 case PIPE_TEXTURE_1D_ARRAY: 520 case PIPE_TEXTURE_2D_ARRAY: 521 layer = s->base.u.tex.first_layer; 522 zslice = 0; 523 break; 524 default: 525 layer = 0; 526 zslice = s->base.u.tex.first_layer; 527 } 528 529 svga_texture_copy_handle_resource(svga, tex, bs->handle, 530 bs->key.numMipLevels, 531 bs->key.numFaces * bs->key.arraySize, 532 zslice, s->base.u.tex.level, layer); 533 } 534 535 svga_mark_surface_dirty(&s->backed->base); 536 s->backed->age = tex->age; 537 538done: 539 return s->backed; 540} 541 542/** 543 * Create a DX RenderTarget/DepthStencil View for the given surface, 544 * if needed. 545 */ 546struct pipe_surface * 547svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) 548{ 549 enum pipe_error ret = PIPE_OK; 550 enum pipe_shader_type shader; 551 552 assert(svga_have_vgpu10(svga)); 553 assert(s); 554 555 SVGA_STATS_TIME_PUSH(svga_sws(svga), 556 SVGA_STATS_TIME_VALIDATESURFACEVIEW); 557 558 /** 559 * DX spec explicitly specifies that no resource can be bound to a render 560 * target view and a shader resource view simultanously. 561 * So first check if the resource bound to this surface view collides with 562 * a sampler view. If so, then we will clone this surface view and its 563 * associated resource. We will then use the cloned surface view for 564 * render target. 565 */ 566 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { 567 if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) { 568 SVGA_DBG(DEBUG_VIEWS, 569 "same resource used in shaderResource and renderTarget 0x%x\n", 570 s->handle); 571 s = create_backed_surface_view(svga, s); 572 573 if (s) 574 svga->state.hw_draw.has_backed_views = TRUE; 575 576 /* s may be null here if the function failed */ 577 break; 578 } 579 } 580 581 if (s && s->view_id == SVGA3D_INVALID_ID) { 582 SVGA3dResourceType resType; 583 SVGA3dRenderTargetViewDesc desc; 584 struct svga_texture *stex = svga_texture(s->base.texture); 585 586 if (stex->validated == FALSE) { 587 assert(stex->handle); 588 589 /* We are about to render into a surface that has not been validated. 590 * First invalidate the surface so that the device does not 591 * need to update the host-side copy with the invalid 592 * content when the associated mob is first bound to the surface. 593 */ 594 if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) { 595 svga_context_flush(svga, NULL); 596 ret = svga->swc->surface_invalidate(svga->swc, stex->handle); 597 assert(ret == PIPE_OK); 598 } 599 stex->validated = TRUE; 600 } 601 602 desc.tex.mipSlice = s->real_level; 603 desc.tex.firstArraySlice = s->real_layer + s->real_zslice; 604 desc.tex.arraySize = 605 s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1; 606 607 s->view_id = util_bitmask_add(svga->surface_view_id_bm); 608 609 resType = svga_resource_type(s->base.texture->target); 610 611 if (util_format_is_depth_or_stencil(s->base.format)) { 612 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, 613 s->view_id, 614 s->handle, 615 s->key.format, 616 resType, 617 &desc); 618 } 619 else { 620 SVGA3dSurfaceFormat view_format = s->key.format; 621 const struct svga_texture *stex = svga_texture(s->base.texture); 622 623 /* Can't create RGBA render target view of a RGBX surface so adjust 624 * the view format. We do something similar for texture samplers in 625 * svga_validate_pipe_sampler_view(). 626 */ 627 if (view_format == SVGA3D_B8G8R8A8_UNORM && 628 (stex->key.format == SVGA3D_B8G8R8X8_UNORM || 629 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) { 630 view_format = SVGA3D_B8G8R8X8_UNORM; 631 } 632 633 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, 634 s->view_id, 635 s->handle, 636 view_format, 637 resType, 638 &desc); 639 } 640 641 if (ret != PIPE_OK) { 642 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 643 s->view_id = SVGA3D_INVALID_ID; 644 s = NULL; 645 } 646 } 647 648 SVGA_STATS_TIME_POP(svga_sws(svga)); 649 650 return s ? &s->base : NULL; 651} 652 653 654 655static void 656svga_surface_destroy(struct pipe_context *pipe, 657 struct pipe_surface *surf) 658{ 659 struct svga_context *svga = svga_context(pipe); 660 struct svga_surface *s = svga_surface(surf); 661 struct svga_texture *t = svga_texture(surf->texture); 662 struct svga_screen *ss = svga_screen(surf->texture->screen); 663 enum pipe_error ret = PIPE_OK; 664 665 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE); 666 667 /* Destroy the backed view surface if it exists */ 668 if (s->backed) { 669 svga_surface_destroy(pipe, &s->backed->base); 670 s->backed = NULL; 671 } 672 673 /* Destroy the surface handle if this is a backed handle and 674 * it is not being cached in the texture. 675 */ 676 if (s->handle != t->handle && s->handle != t->backed_handle) { 677 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); 678 svga_screen_surface_destroy(ss, &s->key, &s->handle); 679 } 680 681 if (s->view_id != SVGA3D_INVALID_ID) { 682 unsigned try; 683 684 /* The SVGA3D device will generate a device error if the 685 * render target view or depth stencil view is destroyed from 686 * a context other than the one it was created with. 687 * Similar to shader resource view, in this case, we will skip 688 * the destroy for now. 689 */ 690 if (surf->context != pipe) { 691 _debug_printf("context mismatch in %s\n", __func__); 692 } 693 else { 694 assert(svga_have_vgpu10(svga)); 695 for (try = 0; try < 2; try++) { 696 if (util_format_is_depth_or_stencil(s->base.format)) { 697 ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id); 698 } 699 else { 700 ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id); 701 } 702 if (ret == PIPE_OK) 703 break; 704 svga_context_flush(svga, NULL); 705 } 706 assert(ret == PIPE_OK); 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.b.last_level + 1; 809 unsigned srcLevel = s->real_level; 810 unsigned dstLevel = surf->u.tex.level; 811 unsigned width = u_minify(tex->b.b.width0, dstLevel); 812 unsigned height = u_minify(tex->b.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