svga_draw.c revision 28486880ca3ec39419ccee0cb1a3bedc9ef7117c
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 "pipe/p_compiler.h" 27#include "util/u_inlines.h" 28#include "pipe/p_defines.h" 29#include "util/u_memory.h" 30#include "util/u_math.h" 31 32#include "svga_context.h" 33#include "svga_draw.h" 34#include "svga_draw_private.h" 35#include "svga_debug.h" 36#include "svga_screen.h" 37#include "svga_screen_buffer.h" 38#include "svga_screen_texture.h" 39#include "svga_winsys.h" 40#include "svga_cmd.h" 41 42 43struct svga_hwtnl *svga_hwtnl_create( struct svga_context *svga, 44 struct u_upload_mgr *upload_ib, 45 struct svga_winsys_context *swc ) 46{ 47 struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl); 48 if (hwtnl == NULL) 49 goto fail; 50 51 hwtnl->svga = svga; 52 hwtnl->upload_ib = upload_ib; 53 54 hwtnl->cmd.swc = swc; 55 56 return hwtnl; 57 58fail: 59 return NULL; 60} 61 62void svga_hwtnl_destroy( struct svga_hwtnl *hwtnl ) 63{ 64 int i, j; 65 66 for (i = 0; i < PIPE_PRIM_MAX; i++) { 67 for (j = 0; j < IDX_CACHE_MAX; j++) { 68 pipe_buffer_reference( &hwtnl->index_cache[i][j].buffer, 69 NULL ); 70 } 71 } 72 73 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) 74 pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i], NULL); 75 76 for (i = 0; i < hwtnl->cmd.prim_count; i++) 77 pipe_buffer_reference(&hwtnl->cmd.prim_ib[i], NULL); 78 79 80 FREE(hwtnl); 81} 82 83 84void svga_hwtnl_set_flatshade( struct svga_hwtnl *hwtnl, 85 boolean flatshade, 86 boolean flatshade_first ) 87{ 88 hwtnl->hw_pv = PV_FIRST; 89 hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST; 90} 91 92void svga_hwtnl_set_unfilled( struct svga_hwtnl *hwtnl, 93 unsigned mode ) 94{ 95 hwtnl->api_fillmode = mode; 96} 97 98void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl, 99 unsigned count ) 100{ 101 unsigned i; 102 103 assert(hwtnl->cmd.prim_count == 0); 104 105 for (i = count; i < hwtnl->cmd.vdecl_count; i++) { 106 pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i], 107 NULL); 108 } 109 110 hwtnl->cmd.vdecl_count = count; 111} 112 113 114void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl, 115 unsigned i, 116 const SVGA3dVertexDecl *decl, 117 struct pipe_buffer *vb) 118{ 119 assert(hwtnl->cmd.prim_count == 0); 120 121 assert( i < hwtnl->cmd.vdecl_count ); 122 123 hwtnl->cmd.vdecl[i] = *decl; 124 125 pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i], 126 vb); 127} 128 129 130 131enum pipe_error 132svga_hwtnl_flush( struct svga_hwtnl *hwtnl ) 133{ 134 struct svga_winsys_context *swc = hwtnl->cmd.swc; 135 struct svga_context *svga = hwtnl->svga; 136 enum pipe_error ret; 137 138 if (hwtnl->cmd.prim_count) { 139 struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX]; 140 struct svga_winsys_surface *ib_handle[QSZ]; 141 struct svga_winsys_surface *handle; 142 SVGA3dVertexDecl *vdecl; 143 SVGA3dPrimitiveRange *prim; 144 unsigned i; 145 146 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 147 handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]); 148 if (handle == NULL) 149 return PIPE_ERROR_OUT_OF_MEMORY; 150 151 vb_handle[i] = handle; 152 } 153 154 for (i = 0; i < hwtnl->cmd.prim_count; i++) { 155 if (hwtnl->cmd.prim_ib[i]) { 156 handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]); 157 if (handle == NULL) 158 return PIPE_ERROR_OUT_OF_MEMORY; 159 } 160 else 161 handle = NULL; 162 163 ib_handle[i] = handle; 164 } 165 166 SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n", 167 svga->curr.framebuffer.cbufs[0] ? 168 svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL, 169 hwtnl->cmd.prim_count); 170 171 ret = SVGA3D_BeginDrawPrimitives(swc, 172 &vdecl, 173 hwtnl->cmd.vdecl_count, 174 &prim, 175 hwtnl->cmd.prim_count); 176 if (ret != PIPE_OK) 177 return ret; 178 179 180 memcpy( vdecl, 181 hwtnl->cmd.vdecl, 182 hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]); 183 184 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 185 /* Given rangeHint is considered to be relative to indexBias, and 186 * indexBias varies per primitive, we cannot accurately supply an 187 * rangeHint when emitting more than one primitive per draw command. 188 */ 189 if (hwtnl->cmd.prim_count == 1) { 190 vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0]; 191 vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1; 192 } 193 else { 194 vdecl[i].rangeHint.first = 0; 195 vdecl[i].rangeHint.last = 0; 196 } 197 198 swc->surface_relocation(swc, 199 &vdecl[i].array.surfaceId, 200 vb_handle[i], 201 PIPE_BUFFER_USAGE_GPU_READ); 202 } 203 204 memcpy( prim, 205 hwtnl->cmd.prim, 206 hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]); 207 208 for (i = 0; i < hwtnl->cmd.prim_count; i++) { 209 swc->surface_relocation(swc, 210 &prim[i].indexArray.surfaceId, 211 ib_handle[i], 212 PIPE_BUFFER_USAGE_GPU_READ); 213 pipe_buffer_reference(&hwtnl->cmd.prim_ib[i], NULL); 214 } 215 216 SVGA_FIFOCommitAll( swc ); 217 hwtnl->cmd.prim_count = 0; 218 } 219 220 return PIPE_OK; 221} 222 223 224 225 226 227/*********************************************************************** 228 * Internal functions: 229 */ 230 231enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl, 232 const SVGA3dPrimitiveRange *range, 233 unsigned min_index, 234 unsigned max_index, 235 struct pipe_buffer *ib ) 236{ 237 int ret = PIPE_OK; 238 239#ifdef DEBUG 240 { 241 unsigned i; 242 for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 243 struct pipe_buffer *vb = hwtnl->cmd.vdecl_vb[i]; 244 unsigned size = vb ? vb->size : 0; 245 unsigned offset = hwtnl->cmd.vdecl[i].array.offset; 246 unsigned stride = hwtnl->cmd.vdecl[i].array.stride; 247 unsigned index_bias = range->indexBias; 248 unsigned width; 249 250 assert(vb); 251 assert(size); 252 assert(offset < size); 253 assert(index_bias >= 0); 254 assert(min_index <= max_index); 255 assert(offset + index_bias*stride < size); 256 assert(offset + (index_bias + min_index)*stride < size); 257 258 switch (hwtnl->cmd.vdecl[i].identity.type) { 259 case SVGA3D_DECLTYPE_FLOAT1: 260 width = 4; 261 break; 262 case SVGA3D_DECLTYPE_FLOAT2: 263 width = 4*2; 264 break; 265 case SVGA3D_DECLTYPE_FLOAT3: 266 width = 4*3; 267 break; 268 case SVGA3D_DECLTYPE_FLOAT4: 269 width = 4*4; 270 break; 271 case SVGA3D_DECLTYPE_D3DCOLOR: 272 width = 4; 273 break; 274 case SVGA3D_DECLTYPE_UBYTE4: 275 width = 1*4; 276 break; 277 case SVGA3D_DECLTYPE_SHORT2: 278 width = 2*2; 279 break; 280 case SVGA3D_DECLTYPE_SHORT4: 281 width = 2*4; 282 break; 283 case SVGA3D_DECLTYPE_UBYTE4N: 284 width = 1*4; 285 break; 286 case SVGA3D_DECLTYPE_SHORT2N: 287 width = 2*2; 288 break; 289 case SVGA3D_DECLTYPE_SHORT4N: 290 width = 2*4; 291 break; 292 case SVGA3D_DECLTYPE_USHORT2N: 293 width = 2*2; 294 break; 295 case SVGA3D_DECLTYPE_USHORT4N: 296 width = 2*4; 297 break; 298 case SVGA3D_DECLTYPE_UDEC3: 299 width = 4; 300 break; 301 case SVGA3D_DECLTYPE_DEC3N: 302 width = 4; 303 break; 304 case SVGA3D_DECLTYPE_FLOAT16_2: 305 width = 2*2; 306 break; 307 case SVGA3D_DECLTYPE_FLOAT16_4: 308 width = 2*4; 309 break; 310 default: 311 assert(0); 312 width = 0; 313 break; 314 } 315 316 assert(!stride || width <= stride); 317 assert(offset + (index_bias + max_index)*stride + width <= size); 318 } 319 320 assert(range->indexWidth == range->indexArray.stride); 321 322 if(ib) { 323 unsigned size = ib->size; 324 unsigned offset = range->indexArray.offset; 325 unsigned stride = range->indexArray.stride; 326 unsigned count; 327 328 assert(size); 329 assert(offset < size); 330 assert(stride); 331 332 switch (range->primType) { 333 case SVGA3D_PRIMITIVE_POINTLIST: 334 count = range->primitiveCount; 335 break; 336 case SVGA3D_PRIMITIVE_LINELIST: 337 count = range->primitiveCount * 2; 338 break; 339 case SVGA3D_PRIMITIVE_LINESTRIP: 340 count = range->primitiveCount + 1; 341 break; 342 case SVGA3D_PRIMITIVE_TRIANGLELIST: 343 count = range->primitiveCount * 3; 344 break; 345 case SVGA3D_PRIMITIVE_TRIANGLESTRIP: 346 count = range->primitiveCount + 2; 347 break; 348 case SVGA3D_PRIMITIVE_TRIANGLEFAN: 349 count = range->primitiveCount + 2; 350 break; 351 default: 352 assert(0); 353 count = 0; 354 break; 355 } 356 357 assert(offset + count*stride <= size); 358 } 359 } 360#endif 361 362 if (hwtnl->cmd.prim_count+1 >= QSZ) { 363 ret = svga_hwtnl_flush( hwtnl ); 364 if (ret != PIPE_OK) 365 return ret; 366 } 367 368 /* min/max indices are relative to bias */ 369 hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index; 370 hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index; 371 372 hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range; 373 374 pipe_buffer_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib); 375 hwtnl->cmd.prim_count++; 376 377 return ret; 378} 379