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_handle(struct svga_context *svga, 49 struct svga_winsys_surface *src_handle, 50 unsigned src_x, unsigned src_y, unsigned src_z, 51 unsigned src_level, unsigned src_layer, 52 struct svga_winsys_surface *dst_handle, 53 unsigned dst_x, unsigned dst_y, unsigned dst_z, 54 unsigned dst_level, unsigned dst_layer, 55 unsigned width, unsigned height, unsigned depth) 56{ 57 struct svga_surface dst, src; 58 enum pipe_error ret; 59 SVGA3dCopyBox box, *boxes; 60 61 assert(svga); 62 63 src.handle = src_handle; 64 src.real_level = src_level; 65 src.real_layer = src_layer; 66 src.real_zslice = 0; 67 68 dst.handle = dst_handle; 69 dst.real_level = dst_level; 70 dst.real_layer = dst_layer; 71 dst.real_zslice = 0; 72 73 box.x = dst_x; 74 box.y = dst_y; 75 box.z = dst_z; 76 box.w = width; 77 box.h = height; 78 box.d = depth; 79 box.srcx = src_x; 80 box.srcy = src_y; 81 box.srcz = src_z; 82 83/* 84 SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n", 85 src_handle, src_level, src_x, src_y, src_z, 86 dst_handle, dst_level, dst_x, dst_y, dst_z); 87*/ 88 89 ret = SVGA3D_BeginSurfaceCopy(svga->swc, 90 &src.base, 91 &dst.base, 92 &boxes, 1); 93 if (ret != PIPE_OK) { 94 svga_context_flush(svga, NULL); 95 ret = SVGA3D_BeginSurfaceCopy(svga->swc, 96 &src.base, 97 &dst.base, 98 &boxes, 1); 99 assert(ret == PIPE_OK); 100 } 101 *boxes = box; 102 SVGA_FIFOCommitAll(svga->swc); 103} 104 105 106struct svga_winsys_surface * 107svga_texture_view_surface(struct svga_context *svga, 108 struct svga_texture *tex, 109 unsigned bind_flags, 110 SVGA3dSurfaceFlags flags, 111 SVGA3dSurfaceFormat format, 112 unsigned start_mip, 113 unsigned num_mip, 114 int layer_pick, 115 unsigned num_layers, 116 int zslice_pick, 117 struct svga_host_surface_cache_key *key) /* OUT */ 118{ 119 struct svga_screen *ss = svga_screen(svga->pipe.screen); 120 struct svga_winsys_surface *handle; 121 uint32_t i, j; 122 unsigned z_offset = 0; 123 boolean validated; 124 125 SVGA_DBG(DEBUG_PERF, 126 "svga: Create surface view: layer %d zslice %d mips %d..%d\n", 127 layer_pick, zslice_pick, start_mip, start_mip+num_mip-1); 128 129 key->flags = flags; 130 key->format = format; 131 key->numMipLevels = num_mip; 132 key->size.width = u_minify(tex->b.b.width0, start_mip); 133 key->size.height = u_minify(tex->b.b.height0, start_mip); 134 key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1; 135 key->cachable = 1; 136 key->arraySize = 1; 137 key->numFaces = 1; 138 139 /* single sample surface can be treated as non-multisamples surface */ 140 key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0; 141 142 if (key->sampleCount > 1) { 143 key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS; 144 } 145 146 if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { 147 key->flags |= SVGA3D_SURFACE_CUBEMAP; 148 key->numFaces = 6; 149 } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY || 150 tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) { 151 key->arraySize = num_layers; 152 } 153 154 if (key->format == SVGA3D_FORMAT_INVALID) { 155 key->cachable = 0; 156 return NULL; 157 } 158 159 SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); 160 handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, 161 &validated, key); 162 if (!handle) { 163 key->cachable = 0; 164 return NULL; 165 } 166 167 SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); 168 169 if (layer_pick < 0) 170 layer_pick = 0; 171 172 if (zslice_pick >= 0) 173 z_offset = zslice_pick; 174 175 for (i = 0; i < key->numMipLevels; i++) { 176 for (j = 0; j < key->numFaces * key->arraySize; j++) { 177 if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) { 178 unsigned depth = (zslice_pick < 0 ? 179 u_minify(tex->b.b.depth0, i + start_mip) : 180 1); 181 182 svga_texture_copy_handle(svga, 183 tex->handle, 184 0, 0, z_offset, 185 i + start_mip, 186 j + layer_pick, 187 handle, 0, 0, 0, i, j, 188 u_minify(tex->b.b.width0, i + start_mip), 189 u_minify(tex->b.b.height0, i + start_mip), 190 depth); 191 } 192 } 193 } 194 195 return handle; 196} 197 198 199/** 200 * A helper function to create a surface view. 201 * The view boolean flag specifies whether svga_texture_view_surface() 202 * will be called to create a cloned surface and resource for the view. 203 */ 204static struct pipe_surface * 205svga_create_surface_view(struct pipe_context *pipe, 206 struct pipe_resource *pt, 207 const struct pipe_surface *surf_tmpl, 208 boolean view) 209{ 210 struct svga_context *svga = svga_context(pipe); 211 struct svga_texture *tex = svga_texture(pt); 212 struct pipe_screen *screen = pipe->screen; 213 struct svga_screen *ss = svga_screen(screen); 214 struct svga_surface *s; 215 unsigned layer, zslice, bind; 216 unsigned nlayers = 1; 217 SVGA3dSurfaceFlags flags = 0; 218 SVGA3dSurfaceFormat format; 219 struct pipe_surface *retVal = NULL; 220 221 s = CALLOC_STRUCT(svga_surface); 222 if (!s) 223 return NULL; 224 225 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW); 226 227 if (pt->target == PIPE_TEXTURE_CUBE) { 228 layer = surf_tmpl->u.tex.first_layer; 229 zslice = 0; 230 } 231 else if (pt->target == PIPE_TEXTURE_1D_ARRAY || 232 pt->target == PIPE_TEXTURE_2D_ARRAY) { 233 layer = surf_tmpl->u.tex.first_layer; 234 zslice = 0; 235 nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1; 236 } 237 else { 238 layer = 0; 239 zslice = surf_tmpl->u.tex.first_layer; 240 } 241 242 pipe_reference_init(&s->base.reference, 1); 243 pipe_resource_reference(&s->base.texture, pt); 244 s->base.context = pipe; 245 s->base.format = surf_tmpl->format; 246 s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level); 247 s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level); 248 s->base.u.tex.level = surf_tmpl->u.tex.level; 249 s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; 250 s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; 251 s->view_id = SVGA3D_INVALID_ID; 252 253 s->backed = NULL; 254 255 if (util_format_is_depth_or_stencil(surf_tmpl->format)) { 256 flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL | 257 SVGA3D_SURFACE_BIND_DEPTH_STENCIL; 258 bind = PIPE_BIND_DEPTH_STENCIL; 259 } 260 else { 261 flags = SVGA3D_SURFACE_HINT_RENDERTARGET | 262 SVGA3D_SURFACE_BIND_RENDER_TARGET; 263 bind = PIPE_BIND_RENDER_TARGET; 264 } 265 266 if (tex->imported) 267 format = tex->key.format; 268 else 269 format = svga_translate_format(ss, surf_tmpl->format, bind); 270 271 assert(format != SVGA3D_FORMAT_INVALID); 272 273 if (view) { 274 SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n", 275 pt, surf_tmpl->u.tex.level, layer, zslice, s); 276 277 if (svga_have_vgpu10(svga)) { 278 switch (pt->target) { 279 case PIPE_TEXTURE_1D: 280 flags |= SVGA3D_SURFACE_1D; 281 break; 282 case PIPE_TEXTURE_1D_ARRAY: 283 flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY; 284 break; 285 case PIPE_TEXTURE_2D_ARRAY: 286 flags |= SVGA3D_SURFACE_ARRAY; 287 break; 288 case PIPE_TEXTURE_3D: 289 flags |= SVGA3D_SURFACE_VOLUME; 290 break; 291 case PIPE_TEXTURE_CUBE: 292 if (nlayers == 6) 293 flags |= SVGA3D_SURFACE_CUBEMAP; 294 break; 295 default: 296 break; 297 } 298 } 299 300 /* When we clone the surface view resource, use the format used in 301 * the creation of the original resource. 302 */ 303 s->handle = svga_texture_view_surface(svga, tex, bind, flags, 304 tex->key.format, 305 surf_tmpl->u.tex.level, 1, 306 layer, nlayers, zslice, &s->key); 307 if (!s->handle) { 308 FREE(s); 309 goto done; 310 } 311 312 s->key.format = format; 313 s->real_layer = 0; 314 s->real_level = 0; 315 s->real_zslice = 0; 316 } else { 317 SVGA_DBG(DEBUG_VIEWS, 318 "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n", 319 pt, surf_tmpl->u.tex.level, layer, zslice, s); 320 321 memset(&s->key, 0, sizeof s->key); 322 s->key.format = format; 323 s->handle = tex->handle; 324 s->real_layer = layer; 325 s->real_zslice = zslice; 326 s->real_level = surf_tmpl->u.tex.level; 327 } 328 329 svga->hud.num_surface_views++; 330 retVal = &s->base; 331 332done: 333 SVGA_STATS_TIME_POP(ss->sws); 334 return retVal; 335} 336 337 338static struct pipe_surface * 339svga_create_surface(struct pipe_context *pipe, 340 struct pipe_resource *pt, 341 const struct pipe_surface *surf_tmpl) 342{ 343 struct svga_context *svga = svga_context(pipe); 344 struct pipe_screen *screen = pipe->screen; 345 struct pipe_surface *surf = NULL; 346 boolean view = FALSE; 347 348 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE); 349 350 if (svga_screen(screen)->debug.force_surface_view) 351 view = TRUE; 352 353 if (surf_tmpl->u.tex.level != 0 && 354 svga_screen(screen)->debug.force_level_surface_view) 355 view = TRUE; 356 357 if (pt->target == PIPE_TEXTURE_3D) 358 view = TRUE; 359 360 if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view) 361 view = FALSE; 362 363 surf = svga_create_surface_view(pipe, pt, surf_tmpl, view); 364 365 SVGA_STATS_TIME_POP(svga_sws(svga)); 366 367 return surf; 368} 369 370 371/** 372 * Clone the surface view and its associated resource. 373 */ 374static struct svga_surface * 375create_backed_surface_view(struct svga_context *svga, struct svga_surface *s) 376{ 377 SVGA_STATS_TIME_PUSH(svga_sws(svga), 378 SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW); 379 380 if (!s->backed) { 381 struct svga_texture *tex = svga_texture(s->base.texture); 382 struct pipe_surface *backed_view; 383 384 backed_view = svga_create_surface_view(&svga->pipe, 385 &tex->b.b, 386 &s->base, 387 TRUE); 388 if (!backed_view) 389 return NULL; 390 391 s->backed = svga_surface(backed_view); 392 } 393 394 svga_mark_surface_dirty(&s->backed->base); 395 396 SVGA_STATS_TIME_POP(svga_sws(svga)); 397 398 return s->backed; 399} 400 401/** 402 * Create a DX RenderTarget/DepthStencil View for the given surface, 403 * if needed. 404 */ 405struct pipe_surface * 406svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) 407{ 408 enum pipe_error ret = PIPE_OK; 409 enum pipe_shader_type shader; 410 411 assert(svga_have_vgpu10(svga)); 412 assert(s); 413 414 SVGA_STATS_TIME_PUSH(svga_sws(svga), 415 SVGA_STATS_TIME_VALIDATESURFACEVIEW); 416 417 /** 418 * DX spec explicitly specifies that no resource can be bound to a render 419 * target view and a shader resource view simultanously. 420 * So first check if the resource bound to this surface view collides with 421 * a sampler view. If so, then we will clone this surface view and its 422 * associated resource. We will then use the cloned surface view for 423 * render target. 424 */ 425 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { 426 if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) { 427 SVGA_DBG(DEBUG_VIEWS, 428 "same resource used in shaderResource and renderTarget 0x%x\n", 429 s->handle); 430 s = create_backed_surface_view(svga, s); 431 /* s may be null here if the function failed */ 432 break; 433 } 434 } 435 436 if (s && s->view_id == SVGA3D_INVALID_ID) { 437 SVGA3dResourceType resType; 438 SVGA3dRenderTargetViewDesc desc; 439 struct svga_texture *stex = svga_texture(s->base.texture); 440 441 if (stex->validated == FALSE) { 442 assert(stex->handle); 443 444 /* We are about to render into a surface that has not been validated. 445 * First invalidate the surface so that the device does not 446 * need to update the host-side copy with the invalid 447 * content when the associated mob is first bound to the surface. 448 */ 449 ret = SVGA3D_InvalidateGBSurface(svga->swc, stex->handle); 450 if (ret != PIPE_OK) { 451 s = NULL; 452 goto done; 453 } 454 stex->validated = TRUE; 455 } 456 457 desc.tex.mipSlice = s->real_level; 458 desc.tex.firstArraySlice = s->real_layer + s->real_zslice; 459 desc.tex.arraySize = 460 s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1; 461 462 s->view_id = util_bitmask_add(svga->surface_view_id_bm); 463 464 resType = svga_resource_type(s->base.texture->target); 465 466 if (util_format_is_depth_or_stencil(s->base.format)) { 467 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, 468 s->view_id, 469 s->handle, 470 s->key.format, 471 resType, 472 &desc); 473 } 474 else { 475 SVGA3dSurfaceFormat view_format = s->key.format; 476 const struct svga_texture *stex = svga_texture(s->base.texture); 477 478 /* Can't create RGBA render target view of a RGBX surface so adjust 479 * the view format. We do something similar for texture samplers in 480 * svga_validate_pipe_sampler_view(). 481 */ 482 if (view_format == SVGA3D_B8G8R8A8_UNORM && 483 (stex->key.format == SVGA3D_B8G8R8X8_UNORM || 484 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) { 485 view_format = SVGA3D_B8G8R8X8_UNORM; 486 } 487 488 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, 489 s->view_id, 490 s->handle, 491 view_format, 492 resType, 493 &desc); 494 } 495 496 if (ret != PIPE_OK) { 497 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 498 s->view_id = SVGA3D_INVALID_ID; 499 s = NULL; 500 } 501 } 502 503done: 504 SVGA_STATS_TIME_POP(svga_sws(svga)); 505 506 return s ? &s->base : NULL; 507} 508 509 510 511static void 512svga_surface_destroy(struct pipe_context *pipe, 513 struct pipe_surface *surf) 514{ 515 struct svga_context *svga = svga_context(pipe); 516 struct svga_surface *s = svga_surface(surf); 517 struct svga_texture *t = svga_texture(surf->texture); 518 struct svga_screen *ss = svga_screen(surf->texture->screen); 519 enum pipe_error ret = PIPE_OK; 520 521 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE); 522 523 /* Destroy the backed view surface if it exists */ 524 if (s->backed) { 525 svga_surface_destroy(pipe, &s->backed->base); 526 s->backed = NULL; 527 } 528 529 if (s->handle != t->handle) { 530 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); 531 svga_screen_surface_destroy(ss, &s->key, &s->handle); 532 } 533 534 if (s->view_id != SVGA3D_INVALID_ID) { 535 unsigned try; 536 537 assert(svga_have_vgpu10(svga)); 538 for (try = 0; try < 2; try++) { 539 if (util_format_is_depth_or_stencil(s->base.format)) { 540 ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id); 541 } 542 else { 543 ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id); 544 } 545 if (ret == PIPE_OK) 546 break; 547 svga_context_flush(svga, NULL); 548 } 549 assert(ret == PIPE_OK); 550 util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 551 } 552 553 pipe_resource_reference(&surf->texture, NULL); 554 FREE(surf); 555 556 svga->hud.num_surface_views--; 557 SVGA_STATS_TIME_POP(ss->sws); 558} 559 560 561static void 562svga_mark_surface_dirty(struct pipe_surface *surf) 563{ 564 struct svga_surface *s = svga_surface(surf); 565 struct svga_texture *tex = svga_texture(surf->texture); 566 567 if (!s->dirty) { 568 s->dirty = TRUE; 569 570 if (s->handle == tex->handle) { 571 /* hmm so 3d textures always have all their slices marked ? */ 572 svga_define_texture_level(tex, surf->u.tex.first_layer, 573 surf->u.tex.level); 574 } 575 else { 576 /* this will happen later in svga_propagate_surface */ 577 } 578 } 579 580 /* Increment the view_age and texture age for this surface's mipmap 581 * level so that any sampler views into the texture are re-validated too. 582 */ 583 svga_age_texture_view(tex, surf->u.tex.level); 584} 585 586 587void 588svga_mark_surfaces_dirty(struct svga_context *svga) 589{ 590 unsigned i; 591 592 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { 593 if (svga->curr.framebuffer.cbufs[i]) 594 svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]); 595 } 596 if (svga->curr.framebuffer.zsbuf) 597 svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf); 598} 599 600 601/** 602 * Progagate any changes from surfaces to texture. 603 * pipe is optional context to inline the blit command in. 604 */ 605void 606svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) 607{ 608 struct svga_surface *s = svga_surface(surf); 609 struct svga_texture *tex = svga_texture(surf->texture); 610 struct svga_screen *ss = svga_screen(surf->texture->screen); 611 612 if (!s->dirty) 613 return; 614 615 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE); 616 617 s->dirty = FALSE; 618 ss->texture_timestamp++; 619 svga_age_texture_view(tex, surf->u.tex.level); 620 621 if (s->handle != tex->handle) { 622 unsigned zslice, layer; 623 unsigned nlayers = 1; 624 unsigned i; 625 626 if (surf->texture->target == PIPE_TEXTURE_CUBE) { 627 zslice = 0; 628 layer = surf->u.tex.first_layer; 629 } 630 else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || 631 surf->texture->target == PIPE_TEXTURE_2D_ARRAY) { 632 zslice = 0; 633 layer = surf->u.tex.first_layer; 634 nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; 635 } 636 else { 637 zslice = surf->u.tex.first_layer; 638 layer = 0; 639 } 640 641 SVGA_DBG(DEBUG_VIEWS, 642 "svga: Surface propagate: tex %p, level %u, from %p\n", 643 tex, surf->u.tex.level, surf); 644 for (i = 0; i < nlayers; i++) { 645 svga_texture_copy_handle(svga, 646 s->handle, 0, 0, 0, s->real_level, 647 s->real_layer + i, 648 tex->handle, 0, 0, zslice, surf->u.tex.level, 649 layer + i, 650 u_minify(tex->b.b.width0, surf->u.tex.level), 651 u_minify(tex->b.b.height0, surf->u.tex.level), 652 1); 653 svga_define_texture_level(tex, layer + i, surf->u.tex.level); 654 } 655 } 656 657 SVGA_STATS_TIME_POP(ss->sws); 658} 659 660 661/** 662 * If any of the render targets are in backing texture views, propagate any 663 * changes to them back to the original texture. 664 */ 665void 666svga_propagate_rendertargets(struct svga_context *svga) 667{ 668 unsigned i; 669 670 /* Note that we examine the svga->state.hw_draw.framebuffer surfaces, 671 * not the svga->curr.framebuffer surfaces, because it's the former 672 * surfaces which may be backing surface views (the actual render targets). 673 */ 674 for (i = 0; i < svga->state.hw_draw.num_rendertargets; i++) { 675 struct pipe_surface *s = svga->state.hw_draw.rtv[i]; 676 if (s) { 677 svga_propagate_surface(svga, s); 678 } 679 } 680 681 if (svga->state.hw_draw.dsv) { 682 svga_propagate_surface(svga, svga->state.hw_draw.dsv); 683 } 684} 685 686 687/** 688 * Check if we should call svga_propagate_surface on the surface. 689 */ 690boolean 691svga_surface_needs_propagation(const struct pipe_surface *surf) 692{ 693 const struct svga_surface *s = svga_surface_const(surf); 694 struct svga_texture *tex = svga_texture(surf->texture); 695 696 return s->dirty && s->handle != tex->handle; 697} 698 699 700static void 701svga_get_sample_position(struct pipe_context *context, 702 unsigned sample_count, unsigned sample_index, 703 float *pos_out) 704{ 705 /* We can't actually query the device to learn the sample positions. 706 * These were grabbed from nvidia's driver. 707 */ 708 static const float pos1[1][2] = { 709 { 0.5, 0.5 } 710 }; 711 static const float pos4[4][2] = { 712 { 0.375000, 0.125000 }, 713 { 0.875000, 0.375000 }, 714 { 0.125000, 0.625000 }, 715 { 0.625000, 0.875000 } 716 }; 717 static const float pos8[8][2] = { 718 { 0.562500, 0.312500 }, 719 { 0.437500, 0.687500 }, 720 { 0.812500, 0.562500 }, 721 { 0.312500, 0.187500 }, 722 { 0.187500, 0.812500 }, 723 { 0.062500, 0.437500 }, 724 { 0.687500, 0.937500 }, 725 { 0.937500, 0.062500 } 726 }; 727 static const float pos16[16][2] = { 728 { 0.187500, 0.062500 }, 729 { 0.437500, 0.187500 }, 730 { 0.062500, 0.312500 }, 731 { 0.312500, 0.437500 }, 732 { 0.687500, 0.062500 }, 733 { 0.937500, 0.187500 }, 734 { 0.562500, 0.312500 }, 735 { 0.812500, 0.437500 }, 736 { 0.187500, 0.562500 }, 737 { 0.437500, 0.687500 }, 738 { 0.062500, 0.812500 }, 739 { 0.312500, 0.937500 }, 740 { 0.687500, 0.562500 }, 741 { 0.937500, 0.687500 }, 742 { 0.562500, 0.812500 }, 743 { 0.812500, 0.937500 } 744 }; 745 const float (*positions)[2]; 746 747 switch (sample_count) { 748 case 4: 749 positions = pos4; 750 break; 751 case 8: 752 positions = pos8; 753 break; 754 case 16: 755 positions = pos16; 756 break; 757 default: 758 positions = pos1; 759 } 760 761 pos_out[0] = positions[sample_index][0]; 762 pos_out[1] = positions[sample_index][1]; 763} 764 765 766void 767svga_init_surface_functions(struct svga_context *svga) 768{ 769 svga->pipe.create_surface = svga_create_surface; 770 svga->pipe.surface_destroy = svga_surface_destroy; 771 svga->pipe.get_sample_position = svga_get_sample_position; 772} 773