1848b8605Smrg/********************************************************** 2848b8605Smrg * Copyright 2008-2009 VMware, Inc. All rights reserved. 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person 5848b8605Smrg * obtaining a copy of this software and associated documentation 6848b8605Smrg * files (the "Software"), to deal in the Software without 7848b8605Smrg * restriction, including without limitation the rights to use, copy, 8848b8605Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies 9848b8605Smrg * of the Software, and to permit persons to whom the Software is 10848b8605Smrg * furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice shall be 13848b8605Smrg * included in all copies or substantial portions of the Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19848b8605Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20848b8605Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21848b8605Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22848b8605Smrg * SOFTWARE. 23848b8605Smrg * 24848b8605Smrg **********************************************************/ 25848b8605Smrg 26848b8605Smrg#include "svga_cmd.h" 27848b8605Smrg 28848b8605Smrg#include "pipe/p_state.h" 29848b8605Smrg#include "pipe/p_defines.h" 30848b8605Smrg#include "util/u_inlines.h" 31848b8605Smrg#include "os/os_thread.h" 32b8e80941Smrg#include "util/u_bitmask.h" 33848b8605Smrg#include "util/u_format.h" 34848b8605Smrg#include "util/u_math.h" 35848b8605Smrg#include "util/u_memory.h" 36848b8605Smrg 37848b8605Smrg#include "svga_format.h" 38848b8605Smrg#include "svga_screen.h" 39848b8605Smrg#include "svga_context.h" 40b8e80941Smrg#include "svga_sampler_view.h" 41848b8605Smrg#include "svga_resource_texture.h" 42848b8605Smrg#include "svga_surface.h" 43848b8605Smrg#include "svga_debug.h" 44848b8605Smrg 45b8e80941Smrgstatic void svga_mark_surface_dirty(struct pipe_surface *surf); 46b8e80941Smrg 47b8e80941Smrgvoid 48b8e80941Smrgsvga_texture_copy_region(struct svga_context *svga, 49b8e80941Smrg struct svga_winsys_surface *src_handle, 50b8e80941Smrg unsigned srcSubResource, 51b8e80941Smrg unsigned src_x, unsigned src_y, unsigned src_z, 52b8e80941Smrg struct svga_winsys_surface *dst_handle, 53b8e80941Smrg unsigned dstSubResource, 54b8e80941Smrg unsigned dst_x, unsigned dst_y, unsigned dst_z, 55b8e80941Smrg unsigned width, unsigned height, unsigned depth) 56b8e80941Smrg{ 57b8e80941Smrg enum pipe_error ret; 58b8e80941Smrg SVGA3dCopyBox box; 59b8e80941Smrg 60b8e80941Smrg assert(svga_have_vgpu10(svga)); 61b8e80941Smrg 62b8e80941Smrg box.x = dst_x; 63b8e80941Smrg box.y = dst_y; 64b8e80941Smrg box.z = dst_z; 65b8e80941Smrg box.w = width; 66b8e80941Smrg box.h = height; 67b8e80941Smrg box.d = depth; 68b8e80941Smrg box.srcx = src_x; 69b8e80941Smrg box.srcy = src_y; 70b8e80941Smrg box.srcz = src_z; 71b8e80941Smrg 72b8e80941Smrg ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, 73b8e80941Smrg dst_handle, dstSubResource, 74b8e80941Smrg src_handle, srcSubResource, &box); 75b8e80941Smrg if (ret != PIPE_OK) { 76b8e80941Smrg svga_context_flush(svga, NULL); 77b8e80941Smrg ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, 78b8e80941Smrg dst_handle, dstSubResource, 79b8e80941Smrg src_handle, srcSubResource, &box); 80b8e80941Smrg assert(ret == PIPE_OK); 81b8e80941Smrg } 82b8e80941Smrg} 83b8e80941Smrg 84848b8605Smrg 85848b8605Smrgvoid 86848b8605Smrgsvga_texture_copy_handle(struct svga_context *svga, 87848b8605Smrg struct svga_winsys_surface *src_handle, 88848b8605Smrg unsigned src_x, unsigned src_y, unsigned src_z, 89b8e80941Smrg unsigned src_level, unsigned src_layer, 90848b8605Smrg struct svga_winsys_surface *dst_handle, 91848b8605Smrg unsigned dst_x, unsigned dst_y, unsigned dst_z, 92b8e80941Smrg unsigned dst_level, unsigned dst_layer, 93848b8605Smrg unsigned width, unsigned height, unsigned depth) 94848b8605Smrg{ 95848b8605Smrg struct svga_surface dst, src; 96848b8605Smrg enum pipe_error ret; 97848b8605Smrg SVGA3dCopyBox box, *boxes; 98848b8605Smrg 99848b8605Smrg assert(svga); 100848b8605Smrg 101848b8605Smrg src.handle = src_handle; 102848b8605Smrg src.real_level = src_level; 103b8e80941Smrg src.real_layer = src_layer; 104848b8605Smrg src.real_zslice = 0; 105848b8605Smrg 106848b8605Smrg dst.handle = dst_handle; 107848b8605Smrg dst.real_level = dst_level; 108b8e80941Smrg dst.real_layer = dst_layer; 109848b8605Smrg dst.real_zslice = 0; 110848b8605Smrg 111848b8605Smrg box.x = dst_x; 112848b8605Smrg box.y = dst_y; 113848b8605Smrg box.z = dst_z; 114848b8605Smrg box.w = width; 115848b8605Smrg box.h = height; 116848b8605Smrg box.d = depth; 117848b8605Smrg box.srcx = src_x; 118848b8605Smrg box.srcy = src_y; 119848b8605Smrg box.srcz = src_z; 120848b8605Smrg 121848b8605Smrg/* 122848b8605Smrg SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n", 123848b8605Smrg src_handle, src_level, src_x, src_y, src_z, 124848b8605Smrg dst_handle, dst_level, dst_x, dst_y, dst_z); 125848b8605Smrg*/ 126848b8605Smrg 127848b8605Smrg ret = SVGA3D_BeginSurfaceCopy(svga->swc, 128848b8605Smrg &src.base, 129848b8605Smrg &dst.base, 130848b8605Smrg &boxes, 1); 131848b8605Smrg if (ret != PIPE_OK) { 132848b8605Smrg svga_context_flush(svga, NULL); 133848b8605Smrg ret = SVGA3D_BeginSurfaceCopy(svga->swc, 134848b8605Smrg &src.base, 135848b8605Smrg &dst.base, 136848b8605Smrg &boxes, 1); 137848b8605Smrg assert(ret == PIPE_OK); 138848b8605Smrg } 139848b8605Smrg *boxes = box; 140848b8605Smrg SVGA_FIFOCommitAll(svga->swc); 141848b8605Smrg} 142848b8605Smrg 143848b8605Smrg 144b8e80941Smrg/* A helper function to sync up the two surface handles. 145b8e80941Smrg */ 146b8e80941Smrgstatic void 147b8e80941Smrgsvga_texture_copy_handle_resource(struct svga_context *svga, 148b8e80941Smrg struct svga_texture *src_tex, 149b8e80941Smrg struct svga_winsys_surface *dst, 150b8e80941Smrg unsigned int numMipLevels, 151b8e80941Smrg unsigned int numLayers, 152b8e80941Smrg int zslice_pick, 153b8e80941Smrg unsigned int mipoffset, 154b8e80941Smrg unsigned int layeroffset) 155b8e80941Smrg{ 156b8e80941Smrg unsigned int i, j; 157b8e80941Smrg unsigned int zoffset = 0; 158b8e80941Smrg 159b8e80941Smrg /* A negative zslice_pick implies zoffset at 0, and depth to copy is 160b8e80941Smrg * from the depth of the texture at the particular mipmap level. 161b8e80941Smrg */ 162b8e80941Smrg if (zslice_pick >= 0) 163b8e80941Smrg zoffset = zslice_pick; 164b8e80941Smrg 165b8e80941Smrg for (i = 0; i < numMipLevels; i++) { 166b8e80941Smrg unsigned int miplevel = i + mipoffset; 167b8e80941Smrg 168b8e80941Smrg for (j = 0; j < numLayers; j++) { 169b8e80941Smrg if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) { 170b8e80941Smrg unsigned depth = (zslice_pick < 0 ? 171b8e80941Smrg u_minify(src_tex->b.b.depth0, miplevel) : 1); 172b8e80941Smrg 173b8e80941Smrg if (src_tex->b.b.nr_samples > 1) { 174b8e80941Smrg unsigned subResource = j * numMipLevels + i; 175b8e80941Smrg svga_texture_copy_region(svga, src_tex->handle, 176b8e80941Smrg subResource, 0, 0, zoffset, 177b8e80941Smrg dst, subResource, 0, 0, 0, 178b8e80941Smrg src_tex->b.b.width0, src_tex->b.b.height0, depth); 179b8e80941Smrg } 180b8e80941Smrg else { 181b8e80941Smrg svga_texture_copy_handle(svga, 182b8e80941Smrg src_tex->handle, 183b8e80941Smrg 0, 0, zoffset, 184b8e80941Smrg miplevel, 185b8e80941Smrg j + layeroffset, 186b8e80941Smrg dst, 0, 0, 0, i, j, 187b8e80941Smrg u_minify(src_tex->b.b.width0, miplevel), 188b8e80941Smrg u_minify(src_tex->b.b.height0, miplevel), 189b8e80941Smrg depth); 190b8e80941Smrg } 191b8e80941Smrg } 192b8e80941Smrg } 193b8e80941Smrg } 194b8e80941Smrg} 195b8e80941Smrg 196b8e80941Smrg 197848b8605Smrgstruct svga_winsys_surface * 198848b8605Smrgsvga_texture_view_surface(struct svga_context *svga, 199848b8605Smrg struct svga_texture *tex, 200b8e80941Smrg unsigned bind_flags, 201b8e80941Smrg SVGA3dSurfaceAllFlags flags, 202848b8605Smrg SVGA3dSurfaceFormat format, 203848b8605Smrg unsigned start_mip, 204848b8605Smrg unsigned num_mip, 205b8e80941Smrg int layer_pick, 206b8e80941Smrg unsigned num_layers, 207848b8605Smrg int zslice_pick, 208b8e80941Smrg boolean cacheable, 209848b8605Smrg struct svga_host_surface_cache_key *key) /* OUT */ 210848b8605Smrg{ 211848b8605Smrg struct svga_screen *ss = svga_screen(svga->pipe.screen); 212b8e80941Smrg struct svga_winsys_surface *handle = NULL; 213b8e80941Smrg boolean validated; 214b8e80941Smrg boolean needCopyResource; 215848b8605Smrg 216b8e80941Smrg SVGA_DBG(DEBUG_PERF, 217b8e80941Smrg "svga: Create surface view: layer %d zslice %d mips %d..%d\n", 218b8e80941Smrg layer_pick, zslice_pick, start_mip, start_mip+num_mip-1); 219b8e80941Smrg 220b8e80941Smrg SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_EMULATESURFACEVIEW); 221848b8605Smrg 222848b8605Smrg key->flags = flags; 223848b8605Smrg key->format = format; 224848b8605Smrg key->numMipLevels = num_mip; 225848b8605Smrg key->size.width = u_minify(tex->b.b.width0, start_mip); 226848b8605Smrg key->size.height = u_minify(tex->b.b.height0, start_mip); 227848b8605Smrg key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1; 228848b8605Smrg key->cachable = 1; 229b8e80941Smrg key->arraySize = 1; 230b8e80941Smrg key->numFaces = 1; 231b8e80941Smrg 232b8e80941Smrg /* single sample surface can be treated as non-multisamples surface */ 233b8e80941Smrg key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0; 234b8e80941Smrg 235b8e80941Smrg if (key->sampleCount > 1) { 236b8e80941Smrg assert(ss->sws->have_sm4_1); 237b8e80941Smrg key->flags |= SVGA3D_SURFACE_MULTISAMPLE; 238b8e80941Smrg } 239b8e80941Smrg 240b8e80941Smrg if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { 241848b8605Smrg key->flags |= SVGA3D_SURFACE_CUBEMAP; 242848b8605Smrg key->numFaces = 6; 243b8e80941Smrg } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY || 244b8e80941Smrg tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) { 245b8e80941Smrg key->arraySize = num_layers; 246848b8605Smrg } 247848b8605Smrg 248848b8605Smrg if (key->format == SVGA3D_FORMAT_INVALID) { 249848b8605Smrg key->cachable = 0; 250b8e80941Smrg goto done; 251b8e80941Smrg } 252b8e80941Smrg 253b8e80941Smrg if (cacheable && tex->backed_handle && 254b8e80941Smrg memcmp(key, &tex->backed_key, sizeof *key) == 0) { 255b8e80941Smrg handle = tex->backed_handle; 256b8e80941Smrg needCopyResource = tex->backed_age < tex->age; 257b8e80941Smrg } else { 258b8e80941Smrg SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); 259b8e80941Smrg handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, 260b8e80941Smrg &validated, key); 261b8e80941Smrg needCopyResource = TRUE; 262b8e80941Smrg 263b8e80941Smrg if (cacheable && !tex->backed_handle) { 264b8e80941Smrg tex->backed_handle = handle; 265b8e80941Smrg memcpy(&tex->backed_key, key, sizeof *key); 266b8e80941Smrg } 267848b8605Smrg } 268848b8605Smrg 269848b8605Smrg if (!handle) { 270848b8605Smrg key->cachable = 0; 271b8e80941Smrg goto done; 272848b8605Smrg } 273848b8605Smrg 274848b8605Smrg SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); 275848b8605Smrg 276b8e80941Smrg if (layer_pick < 0) 277b8e80941Smrg layer_pick = 0; 278848b8605Smrg 279b8e80941Smrg if (needCopyResource) { 280b8e80941Smrg svga_texture_copy_handle_resource(svga, tex, handle, 281b8e80941Smrg key->numMipLevels, 282b8e80941Smrg key->numFaces * key->arraySize, 283b8e80941Smrg zslice_pick, start_mip, layer_pick); 284b8e80941Smrg tex->backed_age = tex->age; 285848b8605Smrg } 286848b8605Smrg 287b8e80941Smrgdone: 288b8e80941Smrg SVGA_STATS_TIME_POP(ss->sws); 289b8e80941Smrg 290848b8605Smrg return handle; 291848b8605Smrg} 292848b8605Smrg 293848b8605Smrg 294b8e80941Smrg/** 295b8e80941Smrg * A helper function to create a surface view. 296b8e80941Smrg * The view boolean flag specifies whether svga_texture_view_surface() 297b8e80941Smrg * will be called to create a cloned surface and resource for the view. 298b8e80941Smrg */ 299848b8605Smrgstatic struct pipe_surface * 300b8e80941Smrgsvga_create_surface_view(struct pipe_context *pipe, 301b8e80941Smrg struct pipe_resource *pt, 302b8e80941Smrg const struct pipe_surface *surf_tmpl, 303b8e80941Smrg boolean view) 304848b8605Smrg{ 305848b8605Smrg struct svga_context *svga = svga_context(pipe); 306848b8605Smrg struct svga_texture *tex = svga_texture(pt); 307848b8605Smrg struct pipe_screen *screen = pipe->screen; 308848b8605Smrg struct svga_screen *ss = svga_screen(screen); 309848b8605Smrg struct svga_surface *s; 310b8e80941Smrg unsigned layer, zslice, bind; 311b8e80941Smrg unsigned nlayers = 1; 312b8e80941Smrg SVGA3dSurfaceAllFlags flags = 0; 313848b8605Smrg SVGA3dSurfaceFormat format; 314b8e80941Smrg struct pipe_surface *retVal = NULL; 315848b8605Smrg 316848b8605Smrg s = CALLOC_STRUCT(svga_surface); 317848b8605Smrg if (!s) 318848b8605Smrg return NULL; 319848b8605Smrg 320b8e80941Smrg SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW); 321b8e80941Smrg 322848b8605Smrg if (pt->target == PIPE_TEXTURE_CUBE) { 323b8e80941Smrg layer = surf_tmpl->u.tex.first_layer; 324848b8605Smrg zslice = 0; 325848b8605Smrg } 326b8e80941Smrg else if (pt->target == PIPE_TEXTURE_1D_ARRAY || 327b8e80941Smrg pt->target == PIPE_TEXTURE_2D_ARRAY || 328b8e80941Smrg pt->target == PIPE_TEXTURE_CUBE_ARRAY) { 329b8e80941Smrg layer = surf_tmpl->u.tex.first_layer; 330b8e80941Smrg zslice = 0; 331b8e80941Smrg nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1; 332b8e80941Smrg } 333848b8605Smrg else { 334b8e80941Smrg layer = 0; 335848b8605Smrg zslice = surf_tmpl->u.tex.first_layer; 336848b8605Smrg } 337848b8605Smrg 338848b8605Smrg pipe_reference_init(&s->base.reference, 1); 339848b8605Smrg pipe_resource_reference(&s->base.texture, pt); 340848b8605Smrg s->base.context = pipe; 341848b8605Smrg s->base.format = surf_tmpl->format; 342848b8605Smrg s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level); 343848b8605Smrg s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level); 344848b8605Smrg s->base.u.tex.level = surf_tmpl->u.tex.level; 345848b8605Smrg s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; 346848b8605Smrg s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; 347b8e80941Smrg s->view_id = SVGA3D_INVALID_ID; 348b8e80941Smrg 349b8e80941Smrg s->backed = NULL; 350848b8605Smrg 351848b8605Smrg if (util_format_is_depth_or_stencil(surf_tmpl->format)) { 352b8e80941Smrg flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL | 353b8e80941Smrg SVGA3D_SURFACE_BIND_DEPTH_STENCIL; 354b8e80941Smrg bind = PIPE_BIND_DEPTH_STENCIL; 355848b8605Smrg } 356848b8605Smrg else { 357b8e80941Smrg flags = SVGA3D_SURFACE_HINT_RENDERTARGET | 358b8e80941Smrg SVGA3D_SURFACE_BIND_RENDER_TARGET; 359b8e80941Smrg bind = PIPE_BIND_RENDER_TARGET; 360b8e80941Smrg } 361b8e80941Smrg 362b8e80941Smrg if (tex->imported) { 363b8e80941Smrg /* imported resource (a window) */ 364b8e80941Smrg format = tex->key.format; 365b8e80941Smrg if (util_format_is_srgb(surf_tmpl->format)) { 366b8e80941Smrg /* sRGB rendering to window */ 367b8e80941Smrg format = svga_linear_to_srgb(format); 368b8e80941Smrg } 369b8e80941Smrg } 370b8e80941Smrg else { 371b8e80941Smrg format = svga_translate_format(ss, surf_tmpl->format, bind); 372848b8605Smrg } 373848b8605Smrg 374848b8605Smrg assert(format != SVGA3D_FORMAT_INVALID); 375848b8605Smrg 376b8e80941Smrg if (view) { 377b8e80941Smrg SVGA_DBG(DEBUG_VIEWS, 378b8e80941Smrg "New backed surface view: resource %p, level %u layer %u z %u, %p\n", 379b8e80941Smrg pt, surf_tmpl->u.tex.level, layer, zslice, s); 380b8e80941Smrg 381b8e80941Smrg if (svga_have_vgpu10(svga)) { 382b8e80941Smrg switch (pt->target) { 383b8e80941Smrg case PIPE_TEXTURE_1D: 384b8e80941Smrg flags |= SVGA3D_SURFACE_1D; 385b8e80941Smrg break; 386b8e80941Smrg case PIPE_TEXTURE_1D_ARRAY: 387b8e80941Smrg flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY; 388b8e80941Smrg break; 389b8e80941Smrg case PIPE_TEXTURE_2D_ARRAY: 390b8e80941Smrg flags |= SVGA3D_SURFACE_ARRAY; 391b8e80941Smrg break; 392b8e80941Smrg case PIPE_TEXTURE_3D: 393b8e80941Smrg flags |= SVGA3D_SURFACE_VOLUME; 394b8e80941Smrg break; 395b8e80941Smrg case PIPE_TEXTURE_CUBE: 396b8e80941Smrg if (nlayers == 6) 397b8e80941Smrg flags |= SVGA3D_SURFACE_CUBEMAP; 398b8e80941Smrg break; 399b8e80941Smrg case PIPE_TEXTURE_CUBE_ARRAY: 400b8e80941Smrg if (nlayers % 6 == 0) 401b8e80941Smrg flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY; 402b8e80941Smrg break; 403b8e80941Smrg default: 404b8e80941Smrg break; 405b8e80941Smrg } 406b8e80941Smrg } 407848b8605Smrg 408b8e80941Smrg /* When we clone the surface view resource, use the format used in 409b8e80941Smrg * the creation of the original resource. 410b8e80941Smrg */ 411b8e80941Smrg s->handle = svga_texture_view_surface(svga, tex, bind, flags, 412b8e80941Smrg tex->key.format, 413b8e80941Smrg surf_tmpl->u.tex.level, 1, 414b8e80941Smrg layer, nlayers, zslice, 415b8e80941Smrg TRUE, &s->key); 416b8e80941Smrg if (!s->handle) { 417b8e80941Smrg FREE(s); 418b8e80941Smrg goto done; 419b8e80941Smrg } 420b8e80941Smrg 421b8e80941Smrg s->key.format = format; 422b8e80941Smrg s->real_layer = 0; 423b8e80941Smrg s->real_level = 0; 424b8e80941Smrg s->real_zslice = 0; 425b8e80941Smrg } else { 426b8e80941Smrg SVGA_DBG(DEBUG_VIEWS, 427b8e80941Smrg "New surface view: resource %p, level %u, layer %u, z %u, %p\n", 428b8e80941Smrg pt, surf_tmpl->u.tex.level, layer, zslice, s); 429b8e80941Smrg 430b8e80941Smrg memset(&s->key, 0, sizeof s->key); 431b8e80941Smrg s->key.format = format; 432b8e80941Smrg s->handle = tex->handle; 433b8e80941Smrg s->real_layer = layer; 434b8e80941Smrg s->real_zslice = zslice; 435b8e80941Smrg s->real_level = surf_tmpl->u.tex.level; 436848b8605Smrg } 437848b8605Smrg 438b8e80941Smrg svga->hud.num_surface_views++; 439b8e80941Smrg retVal = &s->base; 440b8e80941Smrg 441b8e80941Smrgdone: 442b8e80941Smrg SVGA_STATS_TIME_POP(ss->sws); 443b8e80941Smrg return retVal; 444b8e80941Smrg} 445b8e80941Smrg 446b8e80941Smrg 447b8e80941Smrgstatic struct pipe_surface * 448b8e80941Smrgsvga_create_surface(struct pipe_context *pipe, 449b8e80941Smrg struct pipe_resource *pt, 450b8e80941Smrg const struct pipe_surface *surf_tmpl) 451b8e80941Smrg{ 452b8e80941Smrg struct svga_context *svga = svga_context(pipe); 453b8e80941Smrg struct pipe_screen *screen = pipe->screen; 454b8e80941Smrg struct pipe_surface *surf = NULL; 455b8e80941Smrg boolean view = FALSE; 456b8e80941Smrg 457b8e80941Smrg SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE); 458b8e80941Smrg 459b8e80941Smrg if (svga_screen(screen)->debug.force_surface_view) 460b8e80941Smrg view = TRUE; 461b8e80941Smrg 462848b8605Smrg if (surf_tmpl->u.tex.level != 0 && 463848b8605Smrg svga_screen(screen)->debug.force_level_surface_view) 464848b8605Smrg view = TRUE; 465848b8605Smrg 466848b8605Smrg if (pt->target == PIPE_TEXTURE_3D) 467848b8605Smrg view = TRUE; 468848b8605Smrg 469b8e80941Smrg if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view) 470848b8605Smrg view = FALSE; 471848b8605Smrg 472b8e80941Smrg surf = svga_create_surface_view(pipe, pt, surf_tmpl, view); 473848b8605Smrg 474b8e80941Smrg SVGA_STATS_TIME_POP(svga_sws(svga)); 475848b8605Smrg 476b8e80941Smrg return surf; 477b8e80941Smrg} 478b8e80941Smrg 479b8e80941Smrg 480b8e80941Smrg/** 481b8e80941Smrg * Clone the surface view and its associated resource. 482b8e80941Smrg */ 483b8e80941Smrgstatic struct svga_surface * 484b8e80941Smrgcreate_backed_surface_view(struct svga_context *svga, struct svga_surface *s) 485b8e80941Smrg{ 486b8e80941Smrg struct svga_texture *tex = svga_texture(s->base.texture); 487b8e80941Smrg 488b8e80941Smrg if (!s->backed) { 489b8e80941Smrg struct pipe_surface *backed_view; 490b8e80941Smrg 491b8e80941Smrg SVGA_STATS_TIME_PUSH(svga_sws(svga), 492b8e80941Smrg SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW); 493b8e80941Smrg 494b8e80941Smrg backed_view = svga_create_surface_view(&svga->pipe, 495b8e80941Smrg &tex->b.b, 496b8e80941Smrg &s->base, 497b8e80941Smrg TRUE); 498b8e80941Smrg if (!backed_view) 499b8e80941Smrg goto done; 500b8e80941Smrg 501b8e80941Smrg s->backed = svga_surface(backed_view); 502b8e80941Smrg 503b8e80941Smrg SVGA_STATS_TIME_POP(svga_sws(svga)); 504b8e80941Smrg } 505b8e80941Smrg else if (s->backed->age < tex->age) { 506b8e80941Smrg /* 507b8e80941Smrg * There is already an existing backing surface, but we still need to 508b8e80941Smrg * sync the backing resource if the original resource has been modified 509b8e80941Smrg * since the last copy. 510b8e80941Smrg */ 511b8e80941Smrg struct svga_surface *bs = s->backed; 512b8e80941Smrg unsigned int layer, zslice; 513b8e80941Smrg 514b8e80941Smrg assert(bs->handle); 515b8e80941Smrg 516b8e80941Smrg switch (tex->b.b.target) { 517b8e80941Smrg case PIPE_TEXTURE_CUBE: 518b8e80941Smrg case PIPE_TEXTURE_CUBE_ARRAY: 519b8e80941Smrg case PIPE_TEXTURE_1D_ARRAY: 520b8e80941Smrg case PIPE_TEXTURE_2D_ARRAY: 521b8e80941Smrg layer = s->base.u.tex.first_layer; 522b8e80941Smrg zslice = 0; 523b8e80941Smrg break; 524b8e80941Smrg default: 525b8e80941Smrg layer = 0; 526b8e80941Smrg zslice = s->base.u.tex.first_layer; 527b8e80941Smrg } 528b8e80941Smrg 529b8e80941Smrg svga_texture_copy_handle_resource(svga, tex, bs->handle, 530b8e80941Smrg bs->key.numMipLevels, 531b8e80941Smrg bs->key.numFaces * bs->key.arraySize, 532b8e80941Smrg zslice, s->base.u.tex.level, layer); 533b8e80941Smrg } 534b8e80941Smrg 535b8e80941Smrg svga_mark_surface_dirty(&s->backed->base); 536b8e80941Smrg s->backed->age = tex->age; 537b8e80941Smrg 538b8e80941Smrgdone: 539b8e80941Smrg return s->backed; 540b8e80941Smrg} 541b8e80941Smrg 542b8e80941Smrg/** 543b8e80941Smrg * Create a DX RenderTarget/DepthStencil View for the given surface, 544b8e80941Smrg * if needed. 545b8e80941Smrg */ 546b8e80941Smrgstruct pipe_surface * 547b8e80941Smrgsvga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) 548b8e80941Smrg{ 549b8e80941Smrg enum pipe_error ret = PIPE_OK; 550b8e80941Smrg enum pipe_shader_type shader; 551b8e80941Smrg 552b8e80941Smrg assert(svga_have_vgpu10(svga)); 553b8e80941Smrg assert(s); 554b8e80941Smrg 555b8e80941Smrg SVGA_STATS_TIME_PUSH(svga_sws(svga), 556b8e80941Smrg SVGA_STATS_TIME_VALIDATESURFACEVIEW); 557b8e80941Smrg 558b8e80941Smrg /** 559b8e80941Smrg * DX spec explicitly specifies that no resource can be bound to a render 560b8e80941Smrg * target view and a shader resource view simultanously. 561b8e80941Smrg * So first check if the resource bound to this surface view collides with 562b8e80941Smrg * a sampler view. If so, then we will clone this surface view and its 563b8e80941Smrg * associated resource. We will then use the cloned surface view for 564b8e80941Smrg * render target. 565b8e80941Smrg */ 566b8e80941Smrg for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { 567b8e80941Smrg if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) { 568b8e80941Smrg SVGA_DBG(DEBUG_VIEWS, 569b8e80941Smrg "same resource used in shaderResource and renderTarget 0x%x\n", 570b8e80941Smrg s->handle); 571b8e80941Smrg s = create_backed_surface_view(svga, s); 572b8e80941Smrg 573b8e80941Smrg if (s) 574b8e80941Smrg svga->state.hw_draw.has_backed_views = TRUE; 575b8e80941Smrg 576b8e80941Smrg /* s may be null here if the function failed */ 577b8e80941Smrg break; 578b8e80941Smrg } 579848b8605Smrg } 580848b8605Smrg 581b8e80941Smrg if (s && s->view_id == SVGA3D_INVALID_ID) { 582b8e80941Smrg SVGA3dResourceType resType; 583b8e80941Smrg SVGA3dRenderTargetViewDesc desc; 584b8e80941Smrg struct svga_texture *stex = svga_texture(s->base.texture); 585b8e80941Smrg 586b8e80941Smrg if (stex->validated == FALSE) { 587b8e80941Smrg assert(stex->handle); 588b8e80941Smrg 589b8e80941Smrg /* We are about to render into a surface that has not been validated. 590b8e80941Smrg * First invalidate the surface so that the device does not 591b8e80941Smrg * need to update the host-side copy with the invalid 592b8e80941Smrg * content when the associated mob is first bound to the surface. 593b8e80941Smrg */ 594b8e80941Smrg if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) { 595b8e80941Smrg svga_context_flush(svga, NULL); 596b8e80941Smrg ret = svga->swc->surface_invalidate(svga->swc, stex->handle); 597b8e80941Smrg assert(ret == PIPE_OK); 598b8e80941Smrg } 599b8e80941Smrg stex->validated = TRUE; 600b8e80941Smrg } 601b8e80941Smrg 602b8e80941Smrg desc.tex.mipSlice = s->real_level; 603b8e80941Smrg desc.tex.firstArraySlice = s->real_layer + s->real_zslice; 604b8e80941Smrg desc.tex.arraySize = 605b8e80941Smrg s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1; 606b8e80941Smrg 607b8e80941Smrg s->view_id = util_bitmask_add(svga->surface_view_id_bm); 608b8e80941Smrg 609b8e80941Smrg resType = svga_resource_type(s->base.texture->target); 610b8e80941Smrg 611b8e80941Smrg if (util_format_is_depth_or_stencil(s->base.format)) { 612b8e80941Smrg ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, 613b8e80941Smrg s->view_id, 614b8e80941Smrg s->handle, 615b8e80941Smrg s->key.format, 616b8e80941Smrg resType, 617b8e80941Smrg &desc); 618b8e80941Smrg } 619b8e80941Smrg else { 620b8e80941Smrg SVGA3dSurfaceFormat view_format = s->key.format; 621b8e80941Smrg const struct svga_texture *stex = svga_texture(s->base.texture); 622b8e80941Smrg 623b8e80941Smrg /* Can't create RGBA render target view of a RGBX surface so adjust 624b8e80941Smrg * the view format. We do something similar for texture samplers in 625b8e80941Smrg * svga_validate_pipe_sampler_view(). 626b8e80941Smrg */ 627b8e80941Smrg if (view_format == SVGA3D_B8G8R8A8_UNORM && 628b8e80941Smrg (stex->key.format == SVGA3D_B8G8R8X8_UNORM || 629b8e80941Smrg stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) { 630b8e80941Smrg view_format = SVGA3D_B8G8R8X8_UNORM; 631b8e80941Smrg } 632b8e80941Smrg 633b8e80941Smrg ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, 634b8e80941Smrg s->view_id, 635b8e80941Smrg s->handle, 636b8e80941Smrg view_format, 637b8e80941Smrg resType, 638b8e80941Smrg &desc); 639b8e80941Smrg } 640b8e80941Smrg 641b8e80941Smrg if (ret != PIPE_OK) { 642b8e80941Smrg util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 643b8e80941Smrg s->view_id = SVGA3D_INVALID_ID; 644b8e80941Smrg s = NULL; 645b8e80941Smrg } 646b8e80941Smrg } 647b8e80941Smrg 648b8e80941Smrg SVGA_STATS_TIME_POP(svga_sws(svga)); 649b8e80941Smrg 650b8e80941Smrg return s ? &s->base : NULL; 651848b8605Smrg} 652848b8605Smrg 653848b8605Smrg 654b8e80941Smrg 655848b8605Smrgstatic void 656848b8605Smrgsvga_surface_destroy(struct pipe_context *pipe, 657848b8605Smrg struct pipe_surface *surf) 658848b8605Smrg{ 659b8e80941Smrg struct svga_context *svga = svga_context(pipe); 660848b8605Smrg struct svga_surface *s = svga_surface(surf); 661848b8605Smrg struct svga_texture *t = svga_texture(surf->texture); 662848b8605Smrg struct svga_screen *ss = svga_screen(surf->texture->screen); 663b8e80941Smrg enum pipe_error ret = PIPE_OK; 664b8e80941Smrg 665b8e80941Smrg SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE); 666b8e80941Smrg 667b8e80941Smrg /* Destroy the backed view surface if it exists */ 668b8e80941Smrg if (s->backed) { 669b8e80941Smrg svga_surface_destroy(pipe, &s->backed->base); 670b8e80941Smrg s->backed = NULL; 671b8e80941Smrg } 672848b8605Smrg 673b8e80941Smrg /* Destroy the surface handle if this is a backed handle and 674b8e80941Smrg * it is not being cached in the texture. 675b8e80941Smrg */ 676b8e80941Smrg if (s->handle != t->handle && s->handle != t->backed_handle) { 677848b8605Smrg SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); 678848b8605Smrg svga_screen_surface_destroy(ss, &s->key, &s->handle); 679848b8605Smrg } 680848b8605Smrg 681b8e80941Smrg if (s->view_id != SVGA3D_INVALID_ID) { 682b8e80941Smrg unsigned try; 683b8e80941Smrg 684b8e80941Smrg /* The SVGA3D device will generate a device error if the 685b8e80941Smrg * render target view or depth stencil view is destroyed from 686b8e80941Smrg * a context other than the one it was created with. 687b8e80941Smrg * Similar to shader resource view, in this case, we will skip 688b8e80941Smrg * the destroy for now. 689b8e80941Smrg */ 690b8e80941Smrg if (surf->context != pipe) { 691b8e80941Smrg _debug_printf("context mismatch in %s\n", __func__); 692b8e80941Smrg } 693b8e80941Smrg else { 694b8e80941Smrg assert(svga_have_vgpu10(svga)); 695b8e80941Smrg for (try = 0; try < 2; try++) { 696b8e80941Smrg if (util_format_is_depth_or_stencil(s->base.format)) { 697b8e80941Smrg ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id); 698b8e80941Smrg } 699b8e80941Smrg else { 700b8e80941Smrg ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id); 701b8e80941Smrg } 702b8e80941Smrg if (ret == PIPE_OK) 703b8e80941Smrg break; 704b8e80941Smrg svga_context_flush(svga, NULL); 705b8e80941Smrg } 706b8e80941Smrg assert(ret == PIPE_OK); 707b8e80941Smrg util_bitmask_clear(svga->surface_view_id_bm, s->view_id); 708b8e80941Smrg } 709b8e80941Smrg } 710b8e80941Smrg 711848b8605Smrg pipe_resource_reference(&surf->texture, NULL); 712848b8605Smrg FREE(surf); 713b8e80941Smrg 714b8e80941Smrg svga->hud.num_surface_views--; 715b8e80941Smrg SVGA_STATS_TIME_POP(ss->sws); 716848b8605Smrg} 717848b8605Smrg 718848b8605Smrg 719b8e80941Smrgstatic void 720848b8605Smrgsvga_mark_surface_dirty(struct pipe_surface *surf) 721848b8605Smrg{ 722848b8605Smrg struct svga_surface *s = svga_surface(surf); 723b8e80941Smrg struct svga_texture *tex = svga_texture(surf->texture); 724848b8605Smrg 725848b8605Smrg if (!s->dirty) { 726848b8605Smrg s->dirty = TRUE; 727848b8605Smrg 728848b8605Smrg if (s->handle == tex->handle) { 729848b8605Smrg /* hmm so 3d textures always have all their slices marked ? */ 730b8e80941Smrg svga_define_texture_level(tex, surf->u.tex.first_layer, 731b8e80941Smrg surf->u.tex.level); 732848b8605Smrg } 733848b8605Smrg else { 734848b8605Smrg /* this will happen later in svga_propagate_surface */ 735848b8605Smrg } 736b8e80941Smrg } 737848b8605Smrg 738b8e80941Smrg /* Increment the view_age and texture age for this surface's mipmap 739b8e80941Smrg * level so that any sampler views into the texture are re-validated too. 740b8e80941Smrg * Note: we age the texture for backed surface view only when the 741b8e80941Smrg * backed surface is propagated to the original surface. 742b8e80941Smrg */ 743b8e80941Smrg if (s->handle == tex->handle) 744848b8605Smrg svga_age_texture_view(tex, surf->u.tex.level); 745848b8605Smrg} 746848b8605Smrg 747848b8605Smrg 748848b8605Smrgvoid 749848b8605Smrgsvga_mark_surfaces_dirty(struct svga_context *svga) 750848b8605Smrg{ 751848b8605Smrg unsigned i; 752b8e80941Smrg struct svga_hw_clear_state *hw = &svga->state.hw_clear; 753848b8605Smrg 754b8e80941Smrg if (svga_have_vgpu10(svga)) { 755b8e80941Smrg 756b8e80941Smrg /* For VGPU10, mark the dirty bit in the rendertarget/depth stencil view surface. 757b8e80941Smrg * This surface can be the backed surface. 758b8e80941Smrg */ 759b8e80941Smrg for (i = 0; i < hw->num_rendertargets; i++) { 760b8e80941Smrg if (hw->rtv[i]) 761b8e80941Smrg svga_mark_surface_dirty(hw->rtv[i]); 762b8e80941Smrg } 763b8e80941Smrg if (hw->dsv) 764b8e80941Smrg svga_mark_surface_dirty(hw->dsv); 765b8e80941Smrg } else { 766b8e80941Smrg for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { 767b8e80941Smrg if (svga->curr.framebuffer.cbufs[i]) 768b8e80941Smrg svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]); 769b8e80941Smrg } 770b8e80941Smrg if (svga->curr.framebuffer.zsbuf) 771b8e80941Smrg svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf); 772848b8605Smrg } 773848b8605Smrg} 774848b8605Smrg 775848b8605Smrg 776848b8605Smrg/** 777848b8605Smrg * Progagate any changes from surfaces to texture. 778848b8605Smrg * pipe is optional context to inline the blit command in. 779848b8605Smrg */ 780848b8605Smrgvoid 781b8e80941Smrgsvga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf, 782b8e80941Smrg boolean reset) 783848b8605Smrg{ 784848b8605Smrg struct svga_surface *s = svga_surface(surf); 785848b8605Smrg struct svga_texture *tex = svga_texture(surf->texture); 786848b8605Smrg struct svga_screen *ss = svga_screen(surf->texture->screen); 787848b8605Smrg 788848b8605Smrg if (!s->dirty) 789848b8605Smrg return; 790848b8605Smrg 791b8e80941Smrg SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE); 792b8e80941Smrg 793b8e80941Smrg /* Reset the dirty flag if specified. This is to ensure that 794b8e80941Smrg * the dirty flag will not be reset and stay unset when the backing 795b8e80941Smrg * surface is still being bound and rendered to. 796b8e80941Smrg * The reset flag will be set to TRUE when the surface is propagated 797b8e80941Smrg * and will be unbound. 798b8e80941Smrg */ 799b8e80941Smrg s->dirty = !reset; 800848b8605Smrg 801848b8605Smrg ss->texture_timestamp++; 802848b8605Smrg svga_age_texture_view(tex, surf->u.tex.level); 803848b8605Smrg 804848b8605Smrg if (s->handle != tex->handle) { 805b8e80941Smrg unsigned zslice, layer; 806b8e80941Smrg unsigned nlayers = 1; 807b8e80941Smrg unsigned i; 808b8e80941Smrg unsigned numMipLevels = tex->b.b.last_level + 1; 809b8e80941Smrg unsigned srcLevel = s->real_level; 810b8e80941Smrg unsigned dstLevel = surf->u.tex.level; 811b8e80941Smrg unsigned width = u_minify(tex->b.b.width0, dstLevel); 812b8e80941Smrg unsigned height = u_minify(tex->b.b.height0, dstLevel); 813b8e80941Smrg 814b8e80941Smrg if (surf->texture->target == PIPE_TEXTURE_CUBE) { 815b8e80941Smrg zslice = 0; 816b8e80941Smrg layer = surf->u.tex.first_layer; 817b8e80941Smrg } 818b8e80941Smrg else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || 819b8e80941Smrg surf->texture->target == PIPE_TEXTURE_2D_ARRAY || 820b8e80941Smrg surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) { 821b8e80941Smrg zslice = 0; 822b8e80941Smrg layer = surf->u.tex.first_layer; 823b8e80941Smrg nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; 824b8e80941Smrg } 825b8e80941Smrg else { 826b8e80941Smrg zslice = surf->u.tex.first_layer; 827b8e80941Smrg layer = 0; 828b8e80941Smrg } 829b8e80941Smrg 830848b8605Smrg SVGA_DBG(DEBUG_VIEWS, 831b8e80941Smrg "Propagate surface %p to resource %p, level %u\n", 832b8e80941Smrg surf, tex, surf->u.tex.level); 833b8e80941Smrg 834b8e80941Smrg if (svga_have_vgpu10(svga)) { 835b8e80941Smrg unsigned srcSubResource, dstSubResource; 836b8e80941Smrg 837b8e80941Smrg for (i = 0; i < nlayers; i++) { 838b8e80941Smrg srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel; 839b8e80941Smrg dstSubResource = (layer + i) * numMipLevels + dstLevel; 840b8e80941Smrg 841b8e80941Smrg svga_texture_copy_region(svga, 842b8e80941Smrg s->handle, srcSubResource, 0, 0, 0, 843b8e80941Smrg tex->handle, dstSubResource, 0, 0, zslice, 844b8e80941Smrg width, height, 1); 845b8e80941Smrg svga_define_texture_level(tex, layer + i, dstLevel); 846b8e80941Smrg } 847b8e80941Smrg } 848b8e80941Smrg else { 849b8e80941Smrg for (i = 0; i < nlayers; i++) { 850b8e80941Smrg svga_texture_copy_handle(svga, 851b8e80941Smrg s->handle, 0, 0, 0, srcLevel, 852b8e80941Smrg s->real_layer + i, 853b8e80941Smrg tex->handle, 0, 0, zslice, dstLevel, 854b8e80941Smrg layer + i, 855b8e80941Smrg width, height, 1); 856b8e80941Smrg 857b8e80941Smrg svga_define_texture_level(tex, layer + i, dstLevel); 858b8e80941Smrg } 859b8e80941Smrg } 860b8e80941Smrg 861b8e80941Smrg /* Sync the surface view age with the texture age */ 862b8e80941Smrg s->age = tex->age; 863b8e80941Smrg 864b8e80941Smrg /* If this backed surface is cached in the texture, 865b8e80941Smrg * update the backed age as well. 866b8e80941Smrg */ 867b8e80941Smrg if (tex->backed_handle == s->handle) { 868b8e80941Smrg tex->backed_age = tex->age; 869b8e80941Smrg } 870b8e80941Smrg } 871b8e80941Smrg 872b8e80941Smrg SVGA_STATS_TIME_POP(ss->sws); 873b8e80941Smrg} 874b8e80941Smrg 875b8e80941Smrg 876b8e80941Smrg/** 877b8e80941Smrg * If any of the render targets are in backing texture views, propagate any 878b8e80941Smrg * changes to them back to the original texture. 879b8e80941Smrg */ 880b8e80941Smrgvoid 881b8e80941Smrgsvga_propagate_rendertargets(struct svga_context *svga) 882b8e80941Smrg{ 883b8e80941Smrg unsigned i; 884b8e80941Smrg 885b8e80941Smrg /* Early exit if there is no backing texture views in use */ 886b8e80941Smrg if (!svga->state.hw_draw.has_backed_views) 887b8e80941Smrg return; 888b8e80941Smrg 889b8e80941Smrg /* Note that we examine the svga->state.hw_draw.framebuffer surfaces, 890b8e80941Smrg * not the svga->curr.framebuffer surfaces, because it's the former 891b8e80941Smrg * surfaces which may be backing surface views (the actual render targets). 892b8e80941Smrg */ 893b8e80941Smrg for (i = 0; i < svga->state.hw_clear.num_rendertargets; i++) { 894b8e80941Smrg struct pipe_surface *s = svga->state.hw_clear.rtv[i]; 895b8e80941Smrg if (s) { 896b8e80941Smrg svga_propagate_surface(svga, s, FALSE); 897b8e80941Smrg } 898b8e80941Smrg } 899b8e80941Smrg 900b8e80941Smrg if (svga->state.hw_clear.dsv) { 901b8e80941Smrg svga_propagate_surface(svga, svga->state.hw_clear.dsv, FALSE); 902848b8605Smrg } 903848b8605Smrg} 904848b8605Smrg 905848b8605Smrg 906848b8605Smrg/** 907848b8605Smrg * Check if we should call svga_propagate_surface on the surface. 908848b8605Smrg */ 909848b8605Smrgboolean 910848b8605Smrgsvga_surface_needs_propagation(const struct pipe_surface *surf) 911848b8605Smrg{ 912848b8605Smrg const struct svga_surface *s = svga_surface_const(surf); 913848b8605Smrg struct svga_texture *tex = svga_texture(surf->texture); 914848b8605Smrg 915848b8605Smrg return s->dirty && s->handle != tex->handle; 916848b8605Smrg} 917848b8605Smrg 918848b8605Smrg 919b8e80941Smrgstatic void 920b8e80941Smrgsvga_get_sample_position(struct pipe_context *context, 921b8e80941Smrg unsigned sample_count, unsigned sample_index, 922b8e80941Smrg float *pos_out) 923b8e80941Smrg{ 924b8e80941Smrg /* We can't actually query the device to learn the sample positions. 925b8e80941Smrg * These were grabbed from nvidia's driver. 926b8e80941Smrg */ 927b8e80941Smrg static const float pos1[1][2] = { 928b8e80941Smrg { 0.5, 0.5 } 929b8e80941Smrg }; 930b8e80941Smrg static const float pos2[2][2] = { 931b8e80941Smrg { 0.75, 0.75 }, 932b8e80941Smrg { 0.25, 0.25 } 933b8e80941Smrg }; 934b8e80941Smrg static const float pos4[4][2] = { 935b8e80941Smrg { 0.375000, 0.125000 }, 936b8e80941Smrg { 0.875000, 0.375000 }, 937b8e80941Smrg { 0.125000, 0.625000 }, 938b8e80941Smrg { 0.625000, 0.875000 } 939b8e80941Smrg }; 940b8e80941Smrg static const float pos8[8][2] = { 941b8e80941Smrg { 0.562500, 0.312500 }, 942b8e80941Smrg { 0.437500, 0.687500 }, 943b8e80941Smrg { 0.812500, 0.562500 }, 944b8e80941Smrg { 0.312500, 0.187500 }, 945b8e80941Smrg { 0.187500, 0.812500 }, 946b8e80941Smrg { 0.062500, 0.437500 }, 947b8e80941Smrg { 0.687500, 0.937500 }, 948b8e80941Smrg { 0.937500, 0.062500 } 949b8e80941Smrg }; 950b8e80941Smrg static const float pos16[16][2] = { 951b8e80941Smrg { 0.187500, 0.062500 }, 952b8e80941Smrg { 0.437500, 0.187500 }, 953b8e80941Smrg { 0.062500, 0.312500 }, 954b8e80941Smrg { 0.312500, 0.437500 }, 955b8e80941Smrg { 0.687500, 0.062500 }, 956b8e80941Smrg { 0.937500, 0.187500 }, 957b8e80941Smrg { 0.562500, 0.312500 }, 958b8e80941Smrg { 0.812500, 0.437500 }, 959b8e80941Smrg { 0.187500, 0.562500 }, 960b8e80941Smrg { 0.437500, 0.687500 }, 961b8e80941Smrg { 0.062500, 0.812500 }, 962b8e80941Smrg { 0.312500, 0.937500 }, 963b8e80941Smrg { 0.687500, 0.562500 }, 964b8e80941Smrg { 0.937500, 0.687500 }, 965b8e80941Smrg { 0.562500, 0.812500 }, 966b8e80941Smrg { 0.812500, 0.937500 } 967b8e80941Smrg }; 968b8e80941Smrg const float (*positions)[2]; 969b8e80941Smrg 970b8e80941Smrg switch (sample_count) { 971b8e80941Smrg case 2: 972b8e80941Smrg positions = pos2; 973b8e80941Smrg break; 974b8e80941Smrg case 4: 975b8e80941Smrg positions = pos4; 976b8e80941Smrg break; 977b8e80941Smrg case 8: 978b8e80941Smrg positions = pos8; 979b8e80941Smrg break; 980b8e80941Smrg case 16: 981b8e80941Smrg positions = pos16; 982b8e80941Smrg break; 983b8e80941Smrg default: 984b8e80941Smrg positions = pos1; 985b8e80941Smrg } 986b8e80941Smrg 987b8e80941Smrg pos_out[0] = positions[sample_index][0]; 988b8e80941Smrg pos_out[1] = positions[sample_index][1]; 989b8e80941Smrg} 990b8e80941Smrg 991848b8605Smrg 992848b8605Smrgvoid 993848b8605Smrgsvga_init_surface_functions(struct svga_context *svga) 994848b8605Smrg{ 995848b8605Smrg svga->pipe.create_surface = svga_create_surface; 996848b8605Smrg svga->pipe.surface_destroy = svga_surface_destroy; 997b8e80941Smrg svga->pipe.get_sample_position = svga_get_sample_position; 998848b8605Smrg} 999