1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2009-2015 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "svga_cmd.h" 28bf215546Sopenharmony_ci#include "util/u_debug.h" 29bf215546Sopenharmony_ci#include "util/u_memory.h" 30bf215546Sopenharmony_ci#include "pipe/p_defines.h" 31bf215546Sopenharmony_ci#include "vmw_surface.h" 32bf215546Sopenharmony_ci#include "vmw_screen.h" 33bf215546Sopenharmony_ci#include "vmw_buffer.h" 34bf215546Sopenharmony_ci#include "vmw_context.h" 35bf215546Sopenharmony_ci#include "pipebuffer/pb_bufmgr.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_civoid 38bf215546Sopenharmony_civmw_svga_winsys_surface_init(struct svga_winsys_screen *sws, 39bf215546Sopenharmony_ci struct svga_winsys_surface *srf, 40bf215546Sopenharmony_ci unsigned surf_size, SVGA3dSurfaceAllFlags flags) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); 43bf215546Sopenharmony_ci void *data = NULL; 44bf215546Sopenharmony_ci struct pb_buffer *pb_buf; 45bf215546Sopenharmony_ci uint32_t pb_flags; 46bf215546Sopenharmony_ci struct vmw_winsys_screen *vws = vsrf->screen; 47bf215546Sopenharmony_ci pb_flags = PIPE_MAP_WRITE | PIPE_MAP_DISCARD_WHOLE_RESOURCE; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci struct pb_manager *provider; 50bf215546Sopenharmony_ci struct pb_desc desc; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci mtx_lock(&vsrf->mutex); 53bf215546Sopenharmony_ci data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, pb_flags); 54bf215546Sopenharmony_ci if (data) 55bf215546Sopenharmony_ci goto out_mapped; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci provider = vws->pools.mob_fenced; 58bf215546Sopenharmony_ci memset(&desc, 0, sizeof(desc)); 59bf215546Sopenharmony_ci desc.alignment = 4096; 60bf215546Sopenharmony_ci pb_buf = provider->create_buffer(provider, vsrf->size, &desc); 61bf215546Sopenharmony_ci if (pb_buf != NULL) { 62bf215546Sopenharmony_ci struct svga_winsys_buffer *vbuf = 63bf215546Sopenharmony_ci vmw_svga_winsys_buffer_wrap(pb_buf); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci data = vmw_svga_winsys_buffer_map(&vws->base, vbuf, pb_flags); 66bf215546Sopenharmony_ci if (data) { 67bf215546Sopenharmony_ci vsrf->rebind = TRUE; 68bf215546Sopenharmony_ci if (vsrf->buf) 69bf215546Sopenharmony_ci vmw_svga_winsys_buffer_destroy(&vws->base, vsrf->buf); 70bf215546Sopenharmony_ci vsrf->buf = vbuf; 71bf215546Sopenharmony_ci goto out_mapped; 72bf215546Sopenharmony_ci } else { 73bf215546Sopenharmony_ci vmw_svga_winsys_buffer_destroy(&vws->base, vbuf); 74bf215546Sopenharmony_ci goto out_unlock; 75bf215546Sopenharmony_ci } 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci else { 78bf215546Sopenharmony_ci /* Cannot create a buffer, just unlock */ 79bf215546Sopenharmony_ci goto out_unlock; 80bf215546Sopenharmony_ci } 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ciout_mapped: 83bf215546Sopenharmony_ci mtx_unlock(&vsrf->mutex); 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci if (data) { 86bf215546Sopenharmony_ci if (flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) { 87bf215546Sopenharmony_ci memset(data, 0, surf_size + sizeof(SVGA3dDXSOState)); 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci else { 90bf215546Sopenharmony_ci memset(data, 0, surf_size); 91bf215546Sopenharmony_ci } 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci mtx_lock(&vsrf->mutex); 95bf215546Sopenharmony_ci vmw_svga_winsys_buffer_unmap(&vsrf->screen->base, vsrf->buf); 96bf215546Sopenharmony_ciout_unlock: 97bf215546Sopenharmony_ci mtx_unlock(&vsrf->mutex); 98bf215546Sopenharmony_ci} 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_civoid * 103bf215546Sopenharmony_civmw_svga_winsys_surface_map(struct svga_winsys_context *swc, 104bf215546Sopenharmony_ci struct svga_winsys_surface *srf, 105bf215546Sopenharmony_ci unsigned flags, boolean *retry, 106bf215546Sopenharmony_ci boolean *rebind) 107bf215546Sopenharmony_ci{ 108bf215546Sopenharmony_ci struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); 109bf215546Sopenharmony_ci void *data = NULL; 110bf215546Sopenharmony_ci struct pb_buffer *pb_buf; 111bf215546Sopenharmony_ci uint32_t pb_flags; 112bf215546Sopenharmony_ci struct vmw_winsys_screen *vws = vsrf->screen; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci *retry = FALSE; 115bf215546Sopenharmony_ci *rebind = FALSE; 116bf215546Sopenharmony_ci assert((flags & (PIPE_MAP_READ | PIPE_MAP_WRITE)) != 0); 117bf215546Sopenharmony_ci mtx_lock(&vsrf->mutex); 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci if (vsrf->mapcount) { 120bf215546Sopenharmony_ci /* Other mappers will get confused if we discard. */ 121bf215546Sopenharmony_ci flags &= ~PIPE_MAP_DISCARD_WHOLE_RESOURCE; 122bf215546Sopenharmony_ci } 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci vsrf->rebind = FALSE; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* 127bf215546Sopenharmony_ci * If we intend to read, there's no point discarding the 128bf215546Sopenharmony_ci * data if busy. 129bf215546Sopenharmony_ci */ 130bf215546Sopenharmony_ci if (flags & PIPE_MAP_READ || vsrf->shared) 131bf215546Sopenharmony_ci flags &= ~PIPE_MAP_DISCARD_WHOLE_RESOURCE; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* 134bf215546Sopenharmony_ci * Discard is a hint to a synchronized map. 135bf215546Sopenharmony_ci */ 136bf215546Sopenharmony_ci if (flags & PIPE_MAP_DISCARD_WHOLE_RESOURCE) 137bf215546Sopenharmony_ci flags &= ~PIPE_MAP_UNSYNCHRONIZED; 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci /* 140bf215546Sopenharmony_ci * The surface is allowed to be referenced on the command stream iff 141bf215546Sopenharmony_ci * we're mapping unsynchronized or discard. This is an early check. 142bf215546Sopenharmony_ci * We need to recheck after a failing discard map. 143bf215546Sopenharmony_ci */ 144bf215546Sopenharmony_ci if (!(flags & (PIPE_MAP_DISCARD_WHOLE_RESOURCE | 145bf215546Sopenharmony_ci PIPE_MAP_UNSYNCHRONIZED)) && 146bf215546Sopenharmony_ci p_atomic_read(&vsrf->validated)) { 147bf215546Sopenharmony_ci *retry = TRUE; 148bf215546Sopenharmony_ci goto out_unlock; 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci pb_flags = flags & (PIPE_MAP_READ_WRITE | PIPE_MAP_UNSYNCHRONIZED | 152bf215546Sopenharmony_ci PIPE_MAP_PERSISTENT); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci if (flags & PIPE_MAP_DISCARD_WHOLE_RESOURCE) { 155bf215546Sopenharmony_ci struct pb_manager *provider; 156bf215546Sopenharmony_ci struct pb_desc desc; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci /* 159bf215546Sopenharmony_ci * First, if possible, try to map existing storage with DONTBLOCK. 160bf215546Sopenharmony_ci */ 161bf215546Sopenharmony_ci if (!p_atomic_read(&vsrf->validated)) { 162bf215546Sopenharmony_ci data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, 163bf215546Sopenharmony_ci PIPE_MAP_DONTBLOCK | pb_flags); 164bf215546Sopenharmony_ci if (data) 165bf215546Sopenharmony_ci goto out_mapped; 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci /* 169bf215546Sopenharmony_ci * Attempt to get a new buffer. 170bf215546Sopenharmony_ci */ 171bf215546Sopenharmony_ci provider = vws->pools.mob_fenced; 172bf215546Sopenharmony_ci memset(&desc, 0, sizeof(desc)); 173bf215546Sopenharmony_ci desc.alignment = 4096; 174bf215546Sopenharmony_ci pb_buf = provider->create_buffer(provider, vsrf->size, &desc); 175bf215546Sopenharmony_ci if (pb_buf != NULL) { 176bf215546Sopenharmony_ci struct svga_winsys_buffer *vbuf = 177bf215546Sopenharmony_ci vmw_svga_winsys_buffer_wrap(pb_buf); 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci data = vmw_svga_winsys_buffer_map(&vws->base, vbuf, pb_flags); 180bf215546Sopenharmony_ci if (data) { 181bf215546Sopenharmony_ci vsrf->rebind = TRUE; 182bf215546Sopenharmony_ci /* 183bf215546Sopenharmony_ci * We've discarded data on this surface and thus 184bf215546Sopenharmony_ci * it's data is no longer consider referenced. 185bf215546Sopenharmony_ci */ 186bf215546Sopenharmony_ci vmw_swc_surface_clear_reference(swc, vsrf); 187bf215546Sopenharmony_ci if (vsrf->buf) 188bf215546Sopenharmony_ci vmw_svga_winsys_buffer_destroy(&vws->base, vsrf->buf); 189bf215546Sopenharmony_ci vsrf->buf = vbuf; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci /* Rebind persistent maps immediately */ 192bf215546Sopenharmony_ci if (flags & PIPE_MAP_PERSISTENT) { 193bf215546Sopenharmony_ci *rebind = TRUE; 194bf215546Sopenharmony_ci vsrf->rebind = FALSE; 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci goto out_mapped; 197bf215546Sopenharmony_ci } else 198bf215546Sopenharmony_ci vmw_svga_winsys_buffer_destroy(&vws->base, vbuf); 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci /* 201bf215546Sopenharmony_ci * We couldn't get and map a new buffer for some reason. 202bf215546Sopenharmony_ci * Fall through to an ordinary map. 203bf215546Sopenharmony_ci * But tell pipe driver to flush now if already on validate list, 204bf215546Sopenharmony_ci * Otherwise we'll overwrite previous contents. 205bf215546Sopenharmony_ci */ 206bf215546Sopenharmony_ci if (!(flags & PIPE_MAP_UNSYNCHRONIZED) && 207bf215546Sopenharmony_ci p_atomic_read(&vsrf->validated)) { 208bf215546Sopenharmony_ci *retry = TRUE; 209bf215546Sopenharmony_ci goto out_unlock; 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci } 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci pb_flags |= (flags & PIPE_MAP_DONTBLOCK); 214bf215546Sopenharmony_ci data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, pb_flags); 215bf215546Sopenharmony_ci if (data == NULL) 216bf215546Sopenharmony_ci goto out_unlock; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ciout_mapped: 219bf215546Sopenharmony_ci ++vsrf->mapcount; 220bf215546Sopenharmony_ci vsrf->data = data; 221bf215546Sopenharmony_ci vsrf->map_mode = flags & (PIPE_MAP_READ | PIPE_MAP_WRITE); 222bf215546Sopenharmony_ciout_unlock: 223bf215546Sopenharmony_ci mtx_unlock(&vsrf->mutex); 224bf215546Sopenharmony_ci return data; 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_civoid 229bf215546Sopenharmony_civmw_svga_winsys_surface_unmap(struct svga_winsys_context *swc, 230bf215546Sopenharmony_ci struct svga_winsys_surface *srf, 231bf215546Sopenharmony_ci boolean *rebind) 232bf215546Sopenharmony_ci{ 233bf215546Sopenharmony_ci struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); 234bf215546Sopenharmony_ci mtx_lock(&vsrf->mutex); 235bf215546Sopenharmony_ci if (--vsrf->mapcount == 0) { 236bf215546Sopenharmony_ci *rebind = vsrf->rebind; 237bf215546Sopenharmony_ci vsrf->rebind = FALSE; 238bf215546Sopenharmony_ci } else { 239bf215546Sopenharmony_ci *rebind = FALSE; 240bf215546Sopenharmony_ci } 241bf215546Sopenharmony_ci vmw_svga_winsys_buffer_unmap(&vsrf->screen->base, vsrf->buf); 242bf215546Sopenharmony_ci mtx_unlock(&vsrf->mutex); 243bf215546Sopenharmony_ci} 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_civoid 246bf215546Sopenharmony_civmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst, 247bf215546Sopenharmony_ci struct vmw_svga_winsys_surface *src) 248bf215546Sopenharmony_ci{ 249bf215546Sopenharmony_ci struct pipe_reference *src_ref; 250bf215546Sopenharmony_ci struct pipe_reference *dst_ref; 251bf215546Sopenharmony_ci struct vmw_svga_winsys_surface *dst; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if(pdst == NULL || *pdst == src) 254bf215546Sopenharmony_ci return; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci dst = *pdst; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci src_ref = src ? &src->refcnt : NULL; 259bf215546Sopenharmony_ci dst_ref = dst ? &dst->refcnt : NULL; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (pipe_reference(dst_ref, src_ref)) { 262bf215546Sopenharmony_ci if (dst->buf) 263bf215546Sopenharmony_ci vmw_svga_winsys_buffer_destroy(&dst->screen->base, dst->buf); 264bf215546Sopenharmony_ci vmw_ioctl_surface_destroy(dst->screen, dst->sid); 265bf215546Sopenharmony_ci#ifdef DEBUG 266bf215546Sopenharmony_ci /* to detect dangling pointers */ 267bf215546Sopenharmony_ci assert(p_atomic_read(&dst->validated) == 0); 268bf215546Sopenharmony_ci dst->sid = SVGA3D_INVALID_ID; 269bf215546Sopenharmony_ci#endif 270bf215546Sopenharmony_ci mtx_destroy(&dst->mutex); 271bf215546Sopenharmony_ci FREE(dst); 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci *pdst = src; 275bf215546Sopenharmony_ci} 276