1/********************************************************** 2 * Copyright 2009-2015 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 27#include "svga_cmd.h" 28#include "util/u_debug.h" 29#include "util/u_memory.h" 30#include "pipe/p_defines.h" 31#include "vmw_surface.h" 32#include "vmw_screen.h" 33#include "vmw_buffer.h" 34#include "vmw_context.h" 35#include "pipebuffer/pb_bufmgr.h" 36 37void 38vmw_svga_winsys_surface_init(struct svga_winsys_screen *sws, 39 struct svga_winsys_surface *srf, 40 unsigned surf_size, SVGA3dSurfaceAllFlags flags) 41{ 42 struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); 43 void *data = NULL; 44 struct pb_buffer *pb_buf; 45 uint32_t pb_flags; 46 struct vmw_winsys_screen *vws = vsrf->screen; 47 pb_flags = PIPE_MAP_WRITE | PIPE_MAP_DISCARD_WHOLE_RESOURCE; 48 49 struct pb_manager *provider; 50 struct pb_desc desc; 51 52 mtx_lock(&vsrf->mutex); 53 data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, pb_flags); 54 if (data) 55 goto out_mapped; 56 57 provider = vws->pools.mob_fenced; 58 memset(&desc, 0, sizeof(desc)); 59 desc.alignment = 4096; 60 pb_buf = provider->create_buffer(provider, vsrf->size, &desc); 61 if (pb_buf != NULL) { 62 struct svga_winsys_buffer *vbuf = 63 vmw_svga_winsys_buffer_wrap(pb_buf); 64 65 data = vmw_svga_winsys_buffer_map(&vws->base, vbuf, pb_flags); 66 if (data) { 67 vsrf->rebind = TRUE; 68 if (vsrf->buf) 69 vmw_svga_winsys_buffer_destroy(&vws->base, vsrf->buf); 70 vsrf->buf = vbuf; 71 goto out_mapped; 72 } else { 73 vmw_svga_winsys_buffer_destroy(&vws->base, vbuf); 74 goto out_unlock; 75 } 76 } 77 else { 78 /* Cannot create a buffer, just unlock */ 79 goto out_unlock; 80 } 81 82out_mapped: 83 mtx_unlock(&vsrf->mutex); 84 85 if (data) { 86 if (flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) { 87 memset(data, 0, surf_size + sizeof(SVGA3dDXSOState)); 88 } 89 else { 90 memset(data, 0, surf_size); 91 } 92 } 93 94 mtx_lock(&vsrf->mutex); 95 vmw_svga_winsys_buffer_unmap(&vsrf->screen->base, vsrf->buf); 96out_unlock: 97 mtx_unlock(&vsrf->mutex); 98} 99 100 101 102void * 103vmw_svga_winsys_surface_map(struct svga_winsys_context *swc, 104 struct svga_winsys_surface *srf, 105 unsigned flags, boolean *retry, 106 boolean *rebind) 107{ 108 struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); 109 void *data = NULL; 110 struct pb_buffer *pb_buf; 111 uint32_t pb_flags; 112 struct vmw_winsys_screen *vws = vsrf->screen; 113 114 *retry = FALSE; 115 *rebind = FALSE; 116 assert((flags & (PIPE_MAP_READ | PIPE_MAP_WRITE)) != 0); 117 mtx_lock(&vsrf->mutex); 118 119 if (vsrf->mapcount) { 120 /* Other mappers will get confused if we discard. */ 121 flags &= ~PIPE_MAP_DISCARD_WHOLE_RESOURCE; 122 } 123 124 vsrf->rebind = FALSE; 125 126 /* 127 * If we intend to read, there's no point discarding the 128 * data if busy. 129 */ 130 if (flags & PIPE_MAP_READ || vsrf->shared) 131 flags &= ~PIPE_MAP_DISCARD_WHOLE_RESOURCE; 132 133 /* 134 * Discard is a hint to a synchronized map. 135 */ 136 if (flags & PIPE_MAP_DISCARD_WHOLE_RESOURCE) 137 flags &= ~PIPE_MAP_UNSYNCHRONIZED; 138 139 /* 140 * The surface is allowed to be referenced on the command stream iff 141 * we're mapping unsynchronized or discard. This is an early check. 142 * We need to recheck after a failing discard map. 143 */ 144 if (!(flags & (PIPE_MAP_DISCARD_WHOLE_RESOURCE | 145 PIPE_MAP_UNSYNCHRONIZED)) && 146 p_atomic_read(&vsrf->validated)) { 147 *retry = TRUE; 148 goto out_unlock; 149 } 150 151 pb_flags = flags & (PIPE_MAP_READ_WRITE | PIPE_MAP_UNSYNCHRONIZED | 152 PIPE_MAP_PERSISTENT); 153 154 if (flags & PIPE_MAP_DISCARD_WHOLE_RESOURCE) { 155 struct pb_manager *provider; 156 struct pb_desc desc; 157 158 /* 159 * First, if possible, try to map existing storage with DONTBLOCK. 160 */ 161 if (!p_atomic_read(&vsrf->validated)) { 162 data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, 163 PIPE_MAP_DONTBLOCK | pb_flags); 164 if (data) 165 goto out_mapped; 166 } 167 168 /* 169 * Attempt to get a new buffer. 170 */ 171 provider = vws->pools.mob_fenced; 172 memset(&desc, 0, sizeof(desc)); 173 desc.alignment = 4096; 174 pb_buf = provider->create_buffer(provider, vsrf->size, &desc); 175 if (pb_buf != NULL) { 176 struct svga_winsys_buffer *vbuf = 177 vmw_svga_winsys_buffer_wrap(pb_buf); 178 179 data = vmw_svga_winsys_buffer_map(&vws->base, vbuf, pb_flags); 180 if (data) { 181 vsrf->rebind = TRUE; 182 /* 183 * We've discarded data on this surface and thus 184 * it's data is no longer consider referenced. 185 */ 186 vmw_swc_surface_clear_reference(swc, vsrf); 187 if (vsrf->buf) 188 vmw_svga_winsys_buffer_destroy(&vws->base, vsrf->buf); 189 vsrf->buf = vbuf; 190 191 /* Rebind persistent maps immediately */ 192 if (flags & PIPE_MAP_PERSISTENT) { 193 *rebind = TRUE; 194 vsrf->rebind = FALSE; 195 } 196 goto out_mapped; 197 } else 198 vmw_svga_winsys_buffer_destroy(&vws->base, vbuf); 199 } 200 /* 201 * We couldn't get and map a new buffer for some reason. 202 * Fall through to an ordinary map. 203 * But tell pipe driver to flush now if already on validate list, 204 * Otherwise we'll overwrite previous contents. 205 */ 206 if (!(flags & PIPE_MAP_UNSYNCHRONIZED) && 207 p_atomic_read(&vsrf->validated)) { 208 *retry = TRUE; 209 goto out_unlock; 210 } 211 } 212 213 pb_flags |= (flags & PIPE_MAP_DONTBLOCK); 214 data = vmw_svga_winsys_buffer_map(&vws->base, vsrf->buf, pb_flags); 215 if (data == NULL) 216 goto out_unlock; 217 218out_mapped: 219 ++vsrf->mapcount; 220 vsrf->data = data; 221 vsrf->map_mode = flags & (PIPE_MAP_READ | PIPE_MAP_WRITE); 222out_unlock: 223 mtx_unlock(&vsrf->mutex); 224 return data; 225} 226 227 228void 229vmw_svga_winsys_surface_unmap(struct svga_winsys_context *swc, 230 struct svga_winsys_surface *srf, 231 boolean *rebind) 232{ 233 struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf); 234 mtx_lock(&vsrf->mutex); 235 if (--vsrf->mapcount == 0) { 236 *rebind = vsrf->rebind; 237 vsrf->rebind = FALSE; 238 } else { 239 *rebind = FALSE; 240 } 241 vmw_svga_winsys_buffer_unmap(&vsrf->screen->base, vsrf->buf); 242 mtx_unlock(&vsrf->mutex); 243} 244 245void 246vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst, 247 struct vmw_svga_winsys_surface *src) 248{ 249 struct pipe_reference *src_ref; 250 struct pipe_reference *dst_ref; 251 struct vmw_svga_winsys_surface *dst; 252 253 if(pdst == NULL || *pdst == src) 254 return; 255 256 dst = *pdst; 257 258 src_ref = src ? &src->refcnt : NULL; 259 dst_ref = dst ? &dst->refcnt : NULL; 260 261 if (pipe_reference(dst_ref, src_ref)) { 262 if (dst->buf) 263 vmw_svga_winsys_buffer_destroy(&dst->screen->base, dst->buf); 264 vmw_ioctl_surface_destroy(dst->screen, dst->sid); 265#ifdef DEBUG 266 /* to detect dangling pointers */ 267 assert(p_atomic_read(&dst->validated) == 0); 268 dst->sid = SVGA3D_INVALID_ID; 269#endif 270 mtx_destroy(&dst->mutex); 271 FREE(dst); 272 } 273 274 *pdst = src; 275} 276