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 #ifndef SVGA_BUFFER_H 27 #define SVGA_BUFFER_H 28 29 30 #include "pipe/p_compiler.h" 31 #include "pipe/p_state.h" 32 #include "util/u_transfer.h" 33 34 #include "svga_screen_cache.h" 35 #include "svga_screen.h" 36 #include "svga_cmd.h" 37 #include "svga_context.h" 38 39 40 /** 41 * Maximum number of discontiguous ranges 42 */ 43 #define SVGA_BUFFER_MAX_RANGES 32 44 45 46 struct svga_context; 47 struct svga_winsys_buffer; 48 struct svga_winsys_surface; 49 50 51 extern struct u_resource_vtbl svga_buffer_vtbl; 52 53 struct svga_buffer_range 54 { 55 unsigned start; 56 unsigned end; 57 }; 58 59 struct svga_3d_update_gb_image; 60 61 /** 62 * This structure describes the bind flags and cache key associated 63 * with the host surface. 64 */ 65 struct svga_buffer_surface 66 { 67 struct list_head list; 68 unsigned bind_flags; 69 struct svga_host_surface_cache_key key; 70 struct svga_winsys_surface *handle; 71 }; 72 73 /** 74 * SVGA pipe buffer. 75 */ 76 struct svga_buffer 77 { 78 struct u_resource b; 79 80 /** This is a superset of b.b.bind */ 81 unsigned bind_flags; 82 83 /** 84 * Regular (non DMA'able) memory. 85 * 86 * Used for user buffers or for buffers which we know before hand that can 87 * never be used by the virtual hardware directly, such as constant buffers. 88 */ 89 void *swbuf; 90 91 /** 92 * Whether swbuf was created by the user or not. 93 */ 94 boolean user; 95 96 /** 97 * Creation key for the host surface handle. 98 * 99 * This structure describes all the host surface characteristics so that it 100 * can be looked up in cache, since creating a host surface is often a slow 101 * operation. 102 */ 103 struct svga_host_surface_cache_key key; 104 105 /** 106 * Host surface handle. 107 * 108 * This is a platform independent abstraction for host SID. We create when 109 * trying to bind. 110 * 111 * Only set for non-user buffers. 112 */ 113 struct svga_winsys_surface *handle; 114 115 /** 116 * List of surfaces created for this buffer resource to support 117 * incompatible bind flags. 118 */ 119 struct list_head surfaces; 120 121 /** 122 * Information about ongoing and past map operations. 123 */ 124 struct { 125 /** 126 * Number of concurrent mappings. 127 */ 128 unsigned count; 129 130 /** 131 * Dirty ranges. 132 * 133 * Ranges that were touched by the application and need to be uploaded to 134 * the host. 135 * 136 * This information will be copied into dma.boxes, when emiting the 137 * SVGA3dCmdSurfaceDMA command. 138 */ 139 struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES]; 140 unsigned num_ranges; 141 } map; 142 143 /** 144 * Information about uploaded version of user buffers. 145 */ 146 struct { 147 struct pipe_resource *buffer; 148 149 /** 150 * We combine multiple user buffers into the same hardware buffer. This 151 * is the relative offset within that buffer. 152 */ 153 unsigned offset; 154 155 /** 156 * Range of user buffer that is uploaded in @buffer at @offset. 157 */ 158 unsigned start; 159 unsigned end; 160 } uploaded; 161 162 /** 163 * DMA'ble memory. 164 * 165 * A piece of GMR memory, with the same size of the buffer. It is created 166 * when mapping the buffer, and will be used to upload vertex data to the 167 * host. 168 * 169 * Only set for non-user buffers. 170 */ 171 struct svga_winsys_buffer *hwbuf; 172 173 /** 174 * Information about pending DMA uploads. 175 * 176 */ 177 struct { 178 /** 179 * Whether this buffer has an unfinished DMA upload command. 180 * 181 * If not set then the rest of the information is null. 182 */ 183 boolean pending; 184 185 SVGA3dSurfaceDMAFlags flags; 186 187 /** 188 * Pointer to the DMA copy box *inside* the command buffer. 189 */ 190 SVGA3dCopyBox *boxes; 191 192 /** 193 * Pointer to the sequence of update commands 194 * *inside* the command buffer. 195 */ 196 struct svga_3d_update_gb_image *updates; 197 198 /** 199 * Context that has the pending DMA to this buffer. 200 */ 201 struct svga_context *svga; 202 } dma; 203 204 /** 205 * Linked list head, used to gather all buffers with pending dma uploads on 206 * a context. It is only valid if the dma.pending is set above. 207 */ 208 struct list_head head; 209 210 unsigned size; /**< Approximate size in bytes */ 211 212 boolean dirty; /**< Need to do a readback before mapping? */ 213 214 /** In some cases we try to keep the results of the translate_indices() 215 * function from svga_draw_elements.c 216 */ 217 struct { 218 enum pipe_prim_type orig_prim, new_prim; 219 struct pipe_resource *buffer; 220 unsigned index_size; 221 unsigned offset; /**< first index */ 222 unsigned count; /**< num indices */ 223 } translated_indices; 224 }; 225 226 227 static inline struct svga_buffer * 228 svga_buffer(struct pipe_resource *resource) 229 { 230 struct svga_buffer *buf = (struct svga_buffer *) resource; 231 assert(buf == NULL || buf->b.vtbl == &svga_buffer_vtbl); 232 return buf; 233 } 234 235 236 /** 237 * Returns TRUE for user buffers. We may 238 * decide to use an alternate upload path for these buffers. 239 */ 240 static inline boolean 241 svga_buffer_is_user_buffer( struct pipe_resource *buffer ) 242 { 243 if (buffer) { 244 return svga_buffer(buffer)->user; 245 } else { 246 return FALSE; 247 } 248 } 249 250 /** 251 * Returns a pointer to a struct svga_winsys_screen given a 252 * struct svga_buffer. 253 */ 254 static inline struct svga_winsys_screen * 255 svga_buffer_winsys_screen(struct svga_buffer *sbuf) 256 { 257 return svga_screen(sbuf->b.b.screen)->sws; 258 } 259 260 261 /** 262 * Returns whether a buffer has hardware storage that is 263 * visible to the GPU. 264 */ 265 static inline boolean 266 svga_buffer_has_hw_storage(struct svga_buffer *sbuf) 267 { 268 if (svga_buffer_winsys_screen(sbuf)->have_gb_objects) 269 return (sbuf->handle ? TRUE : FALSE); 270 else 271 return (sbuf->hwbuf ? TRUE : FALSE); 272 } 273 274 /** 275 * Map the hardware storage of a buffer. 276 * \param flags bitmask of PIPE_TRANSFER_* flags 277 */ 278 static inline void * 279 svga_buffer_hw_storage_map(struct svga_context *svga, 280 struct svga_buffer *sbuf, 281 unsigned flags, boolean *retry) 282 { 283 struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf); 284 285 svga->hud.num_buffers_mapped++; 286 287 if (sws->have_gb_objects) { 288 return svga->swc->surface_map(svga->swc, sbuf->handle, flags, retry); 289 } else { 290 *retry = FALSE; 291 return sws->buffer_map(sws, sbuf->hwbuf, flags); 292 } 293 } 294 295 /** 296 * Unmap the hardware storage of a buffer. 297 */ 298 static inline void 299 svga_buffer_hw_storage_unmap(struct svga_context *svga, 300 struct svga_buffer *sbuf) 301 { 302 struct svga_winsys_screen *sws = svga_buffer_winsys_screen(sbuf); 303 304 if (sws->have_gb_objects) { 305 struct svga_winsys_context *swc = svga->swc; 306 boolean rebind; 307 swc->surface_unmap(swc, sbuf->handle, &rebind); 308 if (rebind) { 309 enum pipe_error ret; 310 ret = SVGA3D_BindGBSurface(swc, sbuf->handle); 311 if (ret != PIPE_OK) { 312 /* flush and retry */ 313 svga_context_flush(svga, NULL); 314 ret = SVGA3D_BindGBSurface(swc, sbuf->handle); 315 assert(ret == PIPE_OK); 316 } 317 } 318 } else 319 sws->buffer_unmap(sws, sbuf->hwbuf); 320 } 321 322 323 struct pipe_resource * 324 svga_user_buffer_create(struct pipe_screen *screen, 325 void *ptr, 326 unsigned bytes, 327 unsigned usage); 328 329 struct pipe_resource * 330 svga_buffer_create(struct pipe_screen *screen, 331 const struct pipe_resource *template); 332 333 334 335 /** 336 * Get the host surface handle for this buffer. 337 * 338 * This will ensure the host surface is updated, issuing DMAs as needed. 339 * 340 * NOTE: This may insert new commands in the context, so it *must* be called 341 * before reserving command buffer space. And, in order to insert commands 342 * it may need to call svga_context_flush(). 343 */ 344 struct svga_winsys_surface * 345 svga_buffer_handle(struct svga_context *svga, 346 struct pipe_resource *buf, 347 unsigned tobind_flags); 348 349 void 350 svga_context_flush_buffers(struct svga_context *svga); 351 352 struct svga_winsys_buffer * 353 svga_winsys_buffer_create(struct svga_context *svga, 354 unsigned alignment, 355 unsigned usage, 356 unsigned size); 357 358 #endif /* SVGA_BUFFER_H */ 359