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