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 /** 27 * svga_cmd.c -- 28 * 29 * Command construction utility for the SVGA3D protocol used by 30 * the VMware SVGA device, based on the svgautil library. 31 */ 32 33 #include "svga_winsys.h" 34 #include "svga_resource_buffer.h" 35 #include "svga_resource_texture.h" 36 #include "svga_surface.h" 37 #include "svga_cmd.h" 38 39 /* 40 *---------------------------------------------------------------------- 41 * 42 * surface_to_surfaceid -- 43 * 44 * Utility function for surface ids. 45 * Can handle null surface. Does a surface_reallocation so you need 46 * to have allocated the fifo space before converting. 47 * 48 * Results: 49 * id is filled out. 50 * 51 * Side effects: 52 * One surface relocation is performed for texture handle. 53 * 54 *---------------------------------------------------------------------- 55 */ 56 57 static INLINE 58 void surface_to_surfaceid(struct svga_winsys_context *swc, // IN 59 struct pipe_surface *surface, // IN 60 SVGA3dSurfaceImageId *id, // OUT 61 unsigned flags) // IN 62 { 63 if(surface) { 64 struct svga_surface *s = svga_surface(surface); 65 swc->surface_relocation(swc, &id->sid, s->handle, flags); 66 id->face = s->real_face; /* faces have the same order */ 67 id->mipmap = s->real_level; 68 } 69 else { 70 swc->surface_relocation(swc, &id->sid, NULL, flags); 71 id->face = 0; 72 id->mipmap = 0; 73 } 74 } 75 76 77 /* 78 *---------------------------------------------------------------------- 79 * 80 * SVGA3D_FIFOReserve -- 81 * 82 * Reserve space for an SVGA3D FIFO command. 83 * 84 * The 2D SVGA commands have been around for a while, so they 85 * have a rather asymmetric structure. The SVGA3D protocol is 86 * more uniform: each command begins with a header containing the 87 * command number and the full size. 88 * 89 * This is a convenience wrapper around SVGA_FIFOReserve. We 90 * reserve space for the whole command, and write the header. 91 * 92 * This function must be paired with SVGA_FIFOCommitAll(). 93 * 94 * Results: 95 * Returns a pointer to the space reserved for command-specific 96 * data. It must be 'cmdSize' bytes long. 97 * 98 * Side effects: 99 * Begins a FIFO reservation. 100 * 101 *---------------------------------------------------------------------- 102 */ 103 104 void * 105 SVGA3D_FIFOReserve(struct svga_winsys_context *swc, 106 uint32 cmd, // IN 107 uint32 cmdSize, // IN 108 uint32 nr_relocs) // IN 109 { 110 SVGA3dCmdHeader *header; 111 112 header = swc->reserve(swc, sizeof *header + cmdSize, nr_relocs); 113 if(!header) 114 return NULL; 115 116 header->id = cmd; 117 header->size = cmdSize; 118 119 return &header[1]; 120 } 121 122 123 void 124 SVGA_FIFOCommitAll(struct svga_winsys_context *swc) 125 { 126 swc->commit(swc); 127 } 128 129 130 /* 131 *---------------------------------------------------------------------- 132 * 133 * SVGA3D_DefineContext -- 134 * 135 * Create a new context, to be referred to with the provided ID. 136 * 137 * Context objects encapsulate all render state, and shader 138 * objects are per-context. 139 * 140 * Surfaces are not per-context. The same surface can be shared 141 * between multiple contexts, and surface operations can occur 142 * without a context. 143 * 144 * If the provided context ID already existed, it is redefined. 145 * 146 * Context IDs are arbitrary small non-negative integers, 147 * global to the entire SVGA device. 148 * 149 * Results: 150 * None. 151 * 152 * Side effects: 153 * None. 154 * 155 *---------------------------------------------------------------------- 156 */ 157 158 enum pipe_error 159 SVGA3D_DefineContext(struct svga_winsys_context *swc) // IN 160 { 161 SVGA3dCmdDefineContext *cmd; 162 163 cmd = SVGA3D_FIFOReserve(swc, 164 SVGA_3D_CMD_CONTEXT_DEFINE, sizeof *cmd, 0); 165 if(!cmd) 166 return PIPE_ERROR_OUT_OF_MEMORY; 167 168 cmd->cid = swc->cid; 169 170 swc->commit(swc); 171 172 return PIPE_OK; 173 } 174 175 176 /* 177 *---------------------------------------------------------------------- 178 * 179 * SVGA3D_DestroyContext -- 180 * 181 * Delete a context created with SVGA3D_DefineContext. 182 * 183 * Results: 184 * None. 185 * 186 * Side effects: 187 * None. 188 * 189 *---------------------------------------------------------------------- 190 */ 191 192 enum pipe_error 193 SVGA3D_DestroyContext(struct svga_winsys_context *swc) // IN 194 { 195 SVGA3dCmdDestroyContext *cmd; 196 197 cmd = SVGA3D_FIFOReserve(swc, 198 SVGA_3D_CMD_CONTEXT_DESTROY, sizeof *cmd, 0); 199 if(!cmd) 200 return PIPE_ERROR_OUT_OF_MEMORY; 201 202 cmd->cid = swc->cid; 203 204 swc->commit(swc); 205 206 return PIPE_OK; 207 } 208 209 210 /* 211 *---------------------------------------------------------------------- 212 * 213 * SVGA3D_BeginDefineSurface -- 214 * 215 * Begin a SURFACE_DEFINE command. This reserves space for it in 216 * the FIFO, and returns pointers to the command's faces and 217 * mipsizes arrays. 218 * 219 * This function must be paired with SVGA_FIFOCommitAll(). 220 * The faces and mipSizes arrays are initialized to zero. 221 * 222 * This creates a "surface" object in the SVGA3D device, 223 * with the provided surface ID (sid). Surfaces are generic 224 * containers for host VRAM objects like textures, vertex 225 * buffers, and depth/stencil buffers. 226 * 227 * Surfaces are hierarchical: 228 * 229 * - Surface may have multiple faces (for cube maps) 230 * 231 * - Each face has a list of mipmap levels 232 * 233 * - Each mipmap image may have multiple volume 234 * slices, if the image is three dimensional. 235 * 236 * - Each slice is a 2D array of 'blocks' 237 * 238 * - Each block may be one or more pixels. 239 * (Usually 1, more for DXT or YUV formats.) 240 * 241 * Surfaces are generic host VRAM objects. The SVGA3D device 242 * may optimize surfaces according to the format they were 243 * created with, but this format does not limit the ways in 244 * which the surface may be used. For example, a depth surface 245 * can be used as a texture, or a floating point image may 246 * be used as a vertex buffer. Some surface usages may be 247 * lower performance, due to software emulation, but any 248 * usage should work with any surface. 249 * 250 * If 'sid' is already defined, the old surface is deleted 251 * and this new surface replaces it. 252 * 253 * Surface IDs are arbitrary small non-negative integers, 254 * global to the entire SVGA device. 255 * 256 * Results: 257 * Returns pointers to arrays allocated in the FIFO for 'faces' 258 * and 'mipSizes'. 259 * 260 * Side effects: 261 * Begins a FIFO reservation. 262 * 263 *---------------------------------------------------------------------- 264 */ 265 266 enum pipe_error 267 SVGA3D_BeginDefineSurface(struct svga_winsys_context *swc, 268 struct svga_winsys_surface *sid, // IN 269 SVGA3dSurfaceFlags flags, // IN 270 SVGA3dSurfaceFormat format, // IN 271 SVGA3dSurfaceFace **faces, // OUT 272 SVGA3dSize **mipSizes, // OUT 273 uint32 numMipSizes) // IN 274 { 275 SVGA3dCmdDefineSurface *cmd; 276 277 cmd = SVGA3D_FIFOReserve(swc, 278 SVGA_3D_CMD_SURFACE_DEFINE, sizeof *cmd + 279 sizeof **mipSizes * numMipSizes, 1); 280 if(!cmd) 281 return PIPE_ERROR_OUT_OF_MEMORY; 282 283 swc->surface_relocation(swc, &cmd->sid, sid, SVGA_RELOC_WRITE); 284 cmd->surfaceFlags = flags; 285 cmd->format = format; 286 287 *faces = &cmd->face[0]; 288 *mipSizes = (SVGA3dSize*) &cmd[1]; 289 290 memset(*faces, 0, sizeof **faces * SVGA3D_MAX_SURFACE_FACES); 291 memset(*mipSizes, 0, sizeof **mipSizes * numMipSizes); 292 293 return PIPE_OK; 294 } 295 296 297 /* 298 *---------------------------------------------------------------------- 299 * 300 * SVGA3D_DefineSurface2D -- 301 * 302 * This is a simplified version of SVGA3D_BeginDefineSurface(), 303 * which does not support cube maps, mipmaps, or volume textures. 304 * 305 * Results: 306 * None. 307 * 308 * Side effects: 309 * None. 310 * 311 *---------------------------------------------------------------------- 312 */ 313 314 enum pipe_error 315 SVGA3D_DefineSurface2D(struct svga_winsys_context *swc, // IN 316 struct svga_winsys_surface *sid, // IN 317 uint32 width, // IN 318 uint32 height, // IN 319 SVGA3dSurfaceFormat format) // IN 320 { 321 SVGA3dSize *mipSizes; 322 SVGA3dSurfaceFace *faces; 323 enum pipe_error ret; 324 325 ret = SVGA3D_BeginDefineSurface(swc, 326 sid, 0, format, &faces, &mipSizes, 1); 327 if(ret != PIPE_OK) 328 return ret; 329 330 faces[0].numMipLevels = 1; 331 332 mipSizes[0].width = width; 333 mipSizes[0].height = height; 334 mipSizes[0].depth = 1; 335 336 swc->commit(swc);; 337 338 return PIPE_OK; 339 } 340 341 342 /* 343 *---------------------------------------------------------------------- 344 * 345 * SVGA3D_DestroySurface -- 346 * 347 * Release the host VRAM encapsulated by a particular surface ID. 348 * 349 * Results: 350 * None. 351 * 352 * Side effects: 353 * None. 354 * 355 *---------------------------------------------------------------------- 356 */ 357 358 enum pipe_error 359 SVGA3D_DestroySurface(struct svga_winsys_context *swc, 360 struct svga_winsys_surface *sid) // IN 361 { 362 SVGA3dCmdDestroySurface *cmd; 363 364 cmd = SVGA3D_FIFOReserve(swc, 365 SVGA_3D_CMD_SURFACE_DESTROY, sizeof *cmd, 1); 366 if(!cmd) 367 return PIPE_ERROR_OUT_OF_MEMORY; 368 369 swc->surface_relocation(swc, &cmd->sid, sid, SVGA_RELOC_READ); 370 swc->commit(swc);; 371 372 return PIPE_OK; 373 } 374 375 376 /* 377 *---------------------------------------------------------------------- 378 * 379 * SVGA3D_SurfaceDMA-- 380 * 381 * Emit a SURFACE_DMA command. 382 * 383 * When the SVGA3D device asynchronously processes this FIFO 384 * command, a DMA operation is performed between host VRAM and 385 * a generic SVGAGuestPtr. The guest pointer may refer to guest 386 * VRAM (provided by the SVGA PCI device) or to guest system 387 * memory that has been set up as a Guest Memory Region (GMR) 388 * by the SVGA device. 389 * 390 * The guest's DMA buffer must remain valid (not freed, paged out, 391 * or overwritten) until the host has finished processing this 392 * command. The guest can determine that the host has finished 393 * by using the SVGA device's FIFO Fence mechanism. 394 * 395 * The guest's image buffer can be an arbitrary size and shape. 396 * Guest image data is interpreted according to the SVGA3D surface 397 * format specified when the surface was defined. 398 * 399 * The caller may optionally define the guest image's pitch. 400 * guestImage->pitch can either be zero (assume image is tightly 401 * packed) or it must be the number of bytes between vertically 402 * adjacent image blocks. 403 * 404 * The provided copybox list specifies which regions of the source 405 * image are to be copied, and where they appear on the destination. 406 * 407 * NOTE: srcx/srcy are always on the guest image and x/y are 408 * always on the host image, regardless of the actual transfer 409 * direction! 410 * 411 * For efficiency, the SVGA3D device is free to copy more data 412 * than specified. For example, it may round copy boxes outwards 413 * such that they lie on particular alignment boundaries. 414 * 415 *---------------------------------------------------------------------- 416 */ 417 418 enum pipe_error 419 SVGA3D_SurfaceDMA(struct svga_winsys_context *swc, 420 struct svga_transfer *st, // IN 421 SVGA3dTransferType transfer, // IN 422 const SVGA3dCopyBox *boxes, // IN 423 uint32 numBoxes, // IN 424 SVGA3dSurfaceDMAFlags flags) // IN 425 { 426 struct svga_texture *texture = svga_texture(st->base.resource); 427 SVGA3dCmdSurfaceDMA *cmd; 428 SVGA3dCmdSurfaceDMASuffix *pSuffix; 429 uint32 boxesSize = sizeof *boxes * numBoxes; 430 unsigned region_flags; 431 unsigned surface_flags; 432 433 if(transfer == SVGA3D_WRITE_HOST_VRAM) { 434 region_flags = SVGA_RELOC_READ; 435 surface_flags = SVGA_RELOC_WRITE; 436 } 437 else if(transfer == SVGA3D_READ_HOST_VRAM) { 438 region_flags = SVGA_RELOC_WRITE; 439 surface_flags = SVGA_RELOC_READ; 440 } 441 else { 442 assert(0); 443 return PIPE_ERROR_BAD_INPUT; 444 } 445 446 cmd = SVGA3D_FIFOReserve(swc, 447 SVGA_3D_CMD_SURFACE_DMA, 448 sizeof *cmd + boxesSize + sizeof *pSuffix, 449 2); 450 if(!cmd) 451 return PIPE_ERROR_OUT_OF_MEMORY; 452 453 swc->region_relocation(swc, &cmd->guest.ptr, st->hwbuf, 0, region_flags); 454 cmd->guest.pitch = st->base.stride; 455 456 swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags); 457 cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */ 458 cmd->host.mipmap = st->base.level; 459 460 cmd->transfer = transfer; 461 462 memcpy(&cmd[1], boxes, boxesSize); 463 464 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize); 465 pSuffix->suffixSize = sizeof *pSuffix; 466 pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride; 467 pSuffix->flags = flags; 468 469 swc->commit(swc); 470 471 return PIPE_OK; 472 } 473 474 475 enum pipe_error 476 SVGA3D_BufferDMA(struct svga_winsys_context *swc, 477 struct svga_winsys_buffer *guest, 478 struct svga_winsys_surface *host, 479 SVGA3dTransferType transfer, // IN 480 uint32 size, // IN 481 uint32 guest_offset, // IN 482 uint32 host_offset, // IN 483 SVGA3dSurfaceDMAFlags flags) // IN 484 { 485 SVGA3dCmdSurfaceDMA *cmd; 486 SVGA3dCopyBox *box; 487 SVGA3dCmdSurfaceDMASuffix *pSuffix; 488 unsigned region_flags; 489 unsigned surface_flags; 490 491 if(transfer == SVGA3D_WRITE_HOST_VRAM) { 492 region_flags = SVGA_RELOC_READ; 493 surface_flags = SVGA_RELOC_WRITE; 494 } 495 else if(transfer == SVGA3D_READ_HOST_VRAM) { 496 region_flags = SVGA_RELOC_WRITE; 497 surface_flags = SVGA_RELOC_READ; 498 } 499 else { 500 assert(0); 501 return PIPE_ERROR_BAD_INPUT; 502 } 503 504 cmd = SVGA3D_FIFOReserve(swc, 505 SVGA_3D_CMD_SURFACE_DMA, 506 sizeof *cmd + sizeof *box + sizeof *pSuffix, 507 2); 508 if(!cmd) 509 return PIPE_ERROR_OUT_OF_MEMORY; 510 511 swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags); 512 cmd->guest.pitch = 0; 513 514 swc->surface_relocation(swc, &cmd->host.sid, host, surface_flags); 515 cmd->host.face = 0; 516 cmd->host.mipmap = 0; 517 518 cmd->transfer = transfer; 519 520 box = (SVGA3dCopyBox *)&cmd[1]; 521 box->x = host_offset; 522 box->y = 0; 523 box->z = 0; 524 box->w = size; 525 box->h = 1; 526 box->d = 1; 527 box->srcx = guest_offset; 528 box->srcy = 0; 529 box->srcz = 0; 530 531 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box); 532 pSuffix->suffixSize = sizeof *pSuffix; 533 pSuffix->maximumOffset = guest_offset + size; 534 pSuffix->flags = flags; 535 536 swc->commit(swc); 537 538 return PIPE_OK; 539 } 540 541 542 /* 543 *---------------------------------------------------------------------- 544 * 545 * SVGA3D_SetRenderTarget -- 546 * 547 * Bind a surface object to a particular render target attachment 548 * point on the current context. Render target attachment points 549 * exist for color buffers, a depth buffer, and a stencil buffer. 550 * 551 * The SVGA3D device is quite lenient about the types of surfaces 552 * that may be used as render targets. The color buffers must 553 * all be the same size, but the depth and stencil buffers do not 554 * have to be the same size as the color buffer. All attachments 555 * are optional. 556 * 557 * Some combinations of render target formats may require software 558 * emulation, depending on the capabilities of the host graphics 559 * API and graphics hardware. 560 * 561 * Results: 562 * None. 563 * 564 * Side effects: 565 * None. 566 * 567 *---------------------------------------------------------------------- 568 */ 569 570 enum pipe_error 571 SVGA3D_SetRenderTarget(struct svga_winsys_context *swc, 572 SVGA3dRenderTargetType type, // IN 573 struct pipe_surface *surface) // IN 574 { 575 SVGA3dCmdSetRenderTarget *cmd; 576 577 cmd = SVGA3D_FIFOReserve(swc, 578 SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd, 1); 579 if(!cmd) 580 return PIPE_ERROR_OUT_OF_MEMORY; 581 582 583 cmd->cid = swc->cid; 584 585 cmd->type = type; 586 587 surface_to_surfaceid(swc, surface, &cmd->target, SVGA_RELOC_WRITE); 588 589 swc->commit(swc); 590 591 return PIPE_OK; 592 } 593 594 595 596 597 598 599 /* 600 *---------------------------------------------------------------------- 601 * 602 * SVGA3D_DefineShader -- 603 * 604 * Upload the bytecode for a new shader. The bytecode is "SVGA3D 605 * format", which is theoretically a binary-compatible superset 606 * of Microsoft's DirectX shader bytecode. In practice, the 607 * SVGA3D bytecode doesn't yet have any extensions to DirectX's 608 * bytecode format. 609 * 610 * The SVGA3D device supports shader models 1.1 through 2.0. 611 * 612 * The caller chooses a shader ID (small positive integer) by 613 * which this shader will be identified in future commands. This 614 * ID is in a namespace which is per-context and per-shader-type. 615 * 616 * 'bytecodeLen' is specified in bytes. It must be a multiple of 4. 617 * 618 * Results: 619 * None. 620 * 621 * Side effects: 622 * None. 623 * 624 *---------------------------------------------------------------------- 625 */ 626 627 enum pipe_error 628 SVGA3D_DefineShader(struct svga_winsys_context *swc, 629 uint32 shid, // IN 630 SVGA3dShaderType type, // IN 631 const uint32 *bytecode, // IN 632 uint32 bytecodeLen) // IN 633 { 634 SVGA3dCmdDefineShader *cmd; 635 636 assert(bytecodeLen % 4 == 0); 637 638 cmd = SVGA3D_FIFOReserve(swc, 639 SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen, 640 0); 641 if(!cmd) 642 return PIPE_ERROR_OUT_OF_MEMORY; 643 644 cmd->cid = swc->cid; 645 cmd->shid = shid; 646 cmd->type = type; 647 memcpy(&cmd[1], bytecode, bytecodeLen); 648 swc->commit(swc); 649 650 return PIPE_OK; 651 } 652 653 654 /* 655 *---------------------------------------------------------------------- 656 * 657 * SVGA3D_DestroyShader -- 658 * 659 * Delete a shader that was created by SVGA3D_DefineShader. If 660 * the shader was the current vertex or pixel shader for its 661 * context, rendering results are undefined until a new shader is 662 * bound. 663 * 664 * Results: 665 * None. 666 * 667 * Side effects: 668 * None. 669 * 670 *---------------------------------------------------------------------- 671 */ 672 673 enum pipe_error 674 SVGA3D_DestroyShader(struct svga_winsys_context *swc, 675 uint32 shid, // IN 676 SVGA3dShaderType type) // IN 677 { 678 SVGA3dCmdDestroyShader *cmd; 679 680 cmd = SVGA3D_FIFOReserve(swc, 681 SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd, 682 0); 683 if(!cmd) 684 return PIPE_ERROR_OUT_OF_MEMORY; 685 686 cmd->cid = swc->cid; 687 cmd->shid = shid; 688 cmd->type = type; 689 swc->commit(swc); 690 691 return PIPE_OK; 692 } 693 694 695 /* 696 *---------------------------------------------------------------------- 697 * 698 * SVGA3D_SetShaderConst -- 699 * 700 * Set the value of a shader constant. 701 * 702 * Shader constants are analogous to uniform variables in GLSL, 703 * except that they belong to the render context rather than to 704 * an individual shader. 705 * 706 * Constants may have one of three types: A 4-vector of floats, 707 * a 4-vector of integers, or a single boolean flag. 708 * 709 * Results: 710 * None. 711 * 712 * Side effects: 713 * None. 714 * 715 *---------------------------------------------------------------------- 716 */ 717 718 enum pipe_error 719 SVGA3D_SetShaderConst(struct svga_winsys_context *swc, 720 uint32 reg, // IN 721 SVGA3dShaderType type, // IN 722 SVGA3dShaderConstType ctype, // IN 723 const void *value) // IN 724 { 725 SVGA3dCmdSetShaderConst *cmd; 726 727 cmd = SVGA3D_FIFOReserve(swc, 728 SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd, 729 0); 730 if(!cmd) 731 return PIPE_ERROR_OUT_OF_MEMORY; 732 733 cmd->cid = swc->cid; 734 cmd->reg = reg; 735 cmd->type = type; 736 cmd->ctype = ctype; 737 738 switch (ctype) { 739 740 case SVGA3D_CONST_TYPE_FLOAT: 741 case SVGA3D_CONST_TYPE_INT: 742 memcpy(&cmd->values, value, sizeof cmd->values); 743 break; 744 745 case SVGA3D_CONST_TYPE_BOOL: 746 memset(&cmd->values, 0, sizeof cmd->values); 747 cmd->values[0] = *(uint32*)value; 748 break; 749 750 default: 751 assert(0); 752 break; 753 754 } 755 swc->commit(swc); 756 757 return PIPE_OK; 758 } 759 760 761 /* 762 *---------------------------------------------------------------------- 763 * 764 * SVGA3D_SetShaderConsts -- 765 * 766 * Set the value of successive shader constants. 767 * 768 * Shader constants are analogous to uniform variables in GLSL, 769 * except that they belong to the render context rather than to 770 * an individual shader. 771 * 772 * Constants may have one of three types: A 4-vector of floats, 773 * a 4-vector of integers, or a single boolean flag. 774 * 775 * Results: 776 * None. 777 * 778 * Side effects: 779 * None. 780 * 781 *---------------------------------------------------------------------- 782 */ 783 784 enum pipe_error 785 SVGA3D_SetShaderConsts(struct svga_winsys_context *swc, 786 uint32 reg, // IN 787 uint32 numRegs, // IN 788 SVGA3dShaderType type, // IN 789 SVGA3dShaderConstType ctype, // IN 790 const void *values) // IN 791 { 792 SVGA3dCmdSetShaderConst *cmd; 793 794 cmd = SVGA3D_FIFOReserve(swc, 795 SVGA_3D_CMD_SET_SHADER_CONST, 796 sizeof *cmd + (numRegs - 1) * sizeof cmd->values, 797 0); 798 if(!cmd) 799 return PIPE_ERROR_OUT_OF_MEMORY; 800 801 cmd->cid = swc->cid; 802 cmd->reg = reg; 803 cmd->type = type; 804 cmd->ctype = ctype; 805 806 memcpy(&cmd->values, values, numRegs * sizeof cmd->values); 807 808 swc->commit(swc); 809 810 return PIPE_OK; 811 } 812 813 814 815 816 817 /* 818 *---------------------------------------------------------------------- 819 * 820 * SVGA3D_SetShader -- 821 * 822 * Switch active shaders. This binds a new vertex or pixel shader 823 * to the specified context. 824 * 825 * A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching 826 * back to the fixed function vertex or pixel pipeline. 827 * 828 * Results: 829 * None. 830 * 831 * Side effects: 832 * None. 833 * 834 *---------------------------------------------------------------------- 835 */ 836 837 enum pipe_error 838 SVGA3D_SetShader(struct svga_winsys_context *swc, 839 SVGA3dShaderType type, // IN 840 uint32 shid) // IN 841 { 842 SVGA3dCmdSetShader *cmd; 843 844 cmd = SVGA3D_FIFOReserve(swc, 845 SVGA_3D_CMD_SET_SHADER, sizeof *cmd, 846 0); 847 if(!cmd) 848 return PIPE_ERROR_OUT_OF_MEMORY; 849 850 cmd->cid = swc->cid; 851 cmd->type = type; 852 cmd->shid = shid; 853 swc->commit(swc); 854 855 return PIPE_OK; 856 } 857 858 859 /* 860 *---------------------------------------------------------------------- 861 * 862 * SVGA3D_BeginClear -- 863 * 864 * Begin a CLEAR command. This reserves space for it in the FIFO, 865 * and returns a pointer to the command's rectangle array. This 866 * function must be paired with SVGA_FIFOCommitAll(). 867 * 868 * Clear is a rendering operation which fills a list of 869 * rectangles with constant values on all render target types 870 * indicated by 'flags'. 871 * 872 * Clear is not affected by clipping, depth test, or other 873 * render state which affects the fragment pipeline. 874 * 875 * Results: 876 * None. 877 * 878 * Side effects: 879 * May write to attached render target surfaces. 880 * 881 *---------------------------------------------------------------------- 882 */ 883 884 enum pipe_error 885 SVGA3D_BeginClear(struct svga_winsys_context *swc, 886 SVGA3dClearFlag flags, // IN 887 uint32 color, // IN 888 float depth, // IN 889 uint32 stencil, // IN 890 SVGA3dRect **rects, // OUT 891 uint32 numRects) // IN 892 { 893 SVGA3dCmdClear *cmd; 894 895 cmd = SVGA3D_FIFOReserve(swc, 896 SVGA_3D_CMD_CLEAR, 897 sizeof *cmd + sizeof **rects * numRects, 898 0); 899 if(!cmd) 900 return PIPE_ERROR_OUT_OF_MEMORY; 901 902 cmd->cid = swc->cid; 903 cmd->clearFlag = flags; 904 cmd->color = color; 905 cmd->depth = depth; 906 cmd->stencil = stencil; 907 *rects = (SVGA3dRect*) &cmd[1]; 908 909 return PIPE_OK; 910 } 911 912 913 /* 914 *---------------------------------------------------------------------- 915 * 916 * SVGA3D_ClearRect -- 917 * 918 * This is a simplified version of SVGA3D_BeginClear(). 919 * 920 * Results: 921 * None. 922 * 923 * Side effects: 924 * None. 925 * 926 *---------------------------------------------------------------------- 927 */ 928 929 enum pipe_error 930 SVGA3D_ClearRect(struct svga_winsys_context *swc, 931 SVGA3dClearFlag flags, // IN 932 uint32 color, // IN 933 float depth, // IN 934 uint32 stencil, // IN 935 uint32 x, // IN 936 uint32 y, // IN 937 uint32 w, // IN 938 uint32 h) // IN 939 { 940 SVGA3dRect *rect; 941 enum pipe_error ret; 942 943 ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1); 944 if(ret != PIPE_OK) 945 return PIPE_ERROR_OUT_OF_MEMORY; 946 947 memset(rect, 0, sizeof *rect); 948 rect->x = x; 949 rect->y = y; 950 rect->w = w; 951 rect->h = h; 952 swc->commit(swc); 953 954 return PIPE_OK; 955 } 956 957 958 /* 959 *---------------------------------------------------------------------- 960 * 961 * SVGA3D_BeginDrawPrimitives -- 962 * 963 * Begin a DRAW_PRIMITIVES command. This reserves space for it in 964 * the FIFO, and returns a pointer to the command's arrays. 965 * This function must be paired with SVGA_FIFOCommitAll(). 966 * 967 * Drawing commands consist of two variable-length arrays: 968 * SVGA3dVertexDecl elements declare a set of vertex buffers to 969 * use while rendering, and SVGA3dPrimitiveRange elements specify 970 * groups of primitives each with an optional index buffer. 971 * 972 * The decls and ranges arrays are initialized to zero. 973 * 974 * Results: 975 * None. 976 * 977 * Side effects: 978 * May write to attached render target surfaces. 979 * 980 *---------------------------------------------------------------------- 981 */ 982 983 enum pipe_error 984 SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc, 985 SVGA3dVertexDecl **decls, // OUT 986 uint32 numVertexDecls, // IN 987 SVGA3dPrimitiveRange **ranges, // OUT 988 uint32 numRanges) // IN 989 { 990 SVGA3dCmdDrawPrimitives *cmd; 991 SVGA3dVertexDecl *declArray; 992 SVGA3dPrimitiveRange *rangeArray; 993 uint32 declSize = sizeof **decls * numVertexDecls; 994 uint32 rangeSize = sizeof **ranges * numRanges; 995 996 cmd = SVGA3D_FIFOReserve(swc, 997 SVGA_3D_CMD_DRAW_PRIMITIVES, 998 sizeof *cmd + declSize + rangeSize, 999 numVertexDecls + numRanges); 1000 if(!cmd) 1001 return PIPE_ERROR_OUT_OF_MEMORY; 1002 1003 cmd->cid = swc->cid; 1004 cmd->numVertexDecls = numVertexDecls; 1005 cmd->numRanges = numRanges; 1006 1007 declArray = (SVGA3dVertexDecl*) &cmd[1]; 1008 rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls]; 1009 1010 memset(declArray, 0, declSize); 1011 memset(rangeArray, 0, rangeSize); 1012 1013 *decls = declArray; 1014 *ranges = rangeArray; 1015 1016 return PIPE_OK; 1017 } 1018 1019 1020 /* 1021 *---------------------------------------------------------------------- 1022 * 1023 * SVGA3D_BeginSurfaceCopy -- 1024 * 1025 * Begin a SURFACE_COPY command. This reserves space for it in 1026 * the FIFO, and returns a pointer to the command's arrays. This 1027 * function must be paired with SVGA_FIFOCommitAll(). 1028 * 1029 * The box array is initialized with zeroes. 1030 * 1031 * Results: 1032 * None. 1033 * 1034 * Side effects: 1035 * Asynchronously copies a list of boxes from surface to surface. 1036 * 1037 *---------------------------------------------------------------------- 1038 */ 1039 1040 enum pipe_error 1041 SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc, 1042 struct pipe_surface *src, // IN 1043 struct pipe_surface *dest, // IN 1044 SVGA3dCopyBox **boxes, // OUT 1045 uint32 numBoxes) // IN 1046 { 1047 SVGA3dCmdSurfaceCopy *cmd; 1048 uint32 boxesSize = sizeof **boxes * numBoxes; 1049 1050 cmd = SVGA3D_FIFOReserve(swc, 1051 SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize, 1052 2); 1053 if(!cmd) 1054 return PIPE_ERROR_OUT_OF_MEMORY; 1055 1056 surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ); 1057 surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE); 1058 *boxes = (SVGA3dCopyBox*) &cmd[1]; 1059 1060 memset(*boxes, 0, boxesSize); 1061 1062 return PIPE_OK; 1063 } 1064 1065 1066 /* 1067 *---------------------------------------------------------------------- 1068 * 1069 * SVGA3D_SurfaceStretchBlt -- 1070 * 1071 * Issue a SURFACE_STRETCHBLT command: an asynchronous 1072 * surface-to-surface blit, with scaling. 1073 * 1074 * Results: 1075 * None. 1076 * 1077 * Side effects: 1078 * Asynchronously copies one box from surface to surface. 1079 * 1080 *---------------------------------------------------------------------- 1081 */ 1082 1083 enum pipe_error 1084 SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc, 1085 struct pipe_surface *src, // IN 1086 struct pipe_surface *dest, // IN 1087 SVGA3dBox *boxSrc, // IN 1088 SVGA3dBox *boxDest, // IN 1089 SVGA3dStretchBltMode mode) // IN 1090 { 1091 SVGA3dCmdSurfaceStretchBlt *cmd; 1092 1093 cmd = SVGA3D_FIFOReserve(swc, 1094 SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd, 1095 2); 1096 if(!cmd) 1097 return PIPE_ERROR_OUT_OF_MEMORY; 1098 1099 surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ); 1100 surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE); 1101 cmd->boxSrc = *boxSrc; 1102 cmd->boxDest = *boxDest; 1103 cmd->mode = mode; 1104 swc->commit(swc); 1105 1106 return PIPE_OK; 1107 } 1108 1109 1110 /* 1111 *---------------------------------------------------------------------- 1112 * 1113 * SVGA3D_SetViewport -- 1114 * 1115 * Set the current context's viewport rectangle. The viewport 1116 * is clipped to the dimensions of the current render target, 1117 * then all rendering is clipped to the viewport. 1118 * 1119 * Results: 1120 * None. 1121 * 1122 * Side effects: 1123 * None. 1124 * 1125 *---------------------------------------------------------------------- 1126 */ 1127 1128 enum pipe_error 1129 SVGA3D_SetViewport(struct svga_winsys_context *swc, 1130 SVGA3dRect *rect) // IN 1131 { 1132 SVGA3dCmdSetViewport *cmd; 1133 1134 cmd = SVGA3D_FIFOReserve(swc, 1135 SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd, 1136 0); 1137 if(!cmd) 1138 return PIPE_ERROR_OUT_OF_MEMORY; 1139 1140 cmd->cid = swc->cid; 1141 cmd->rect = *rect; 1142 swc->commit(swc); 1143 1144 return PIPE_OK; 1145 } 1146 1147 1148 1149 1150 /* 1151 *---------------------------------------------------------------------- 1152 * 1153 * SVGA3D_SetScissorRect -- 1154 * 1155 * Set the current context's scissor rectangle. If scissor 1156 * is enabled then all rendering is clipped to the scissor. 1157 * 1158 * Results: 1159 * None. 1160 * 1161 * Side effects: 1162 * None. 1163 * 1164 *---------------------------------------------------------------------- 1165 */ 1166 1167 enum pipe_error 1168 SVGA3D_SetScissorRect(struct svga_winsys_context *swc, 1169 SVGA3dRect *rect) // IN 1170 { 1171 SVGA3dCmdSetScissorRect *cmd; 1172 1173 cmd = SVGA3D_FIFOReserve(swc, 1174 SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd, 1175 0); 1176 if(!cmd) 1177 return PIPE_ERROR_OUT_OF_MEMORY; 1178 1179 cmd->cid = swc->cid; 1180 cmd->rect = *rect; 1181 swc->commit(swc); 1182 1183 return PIPE_OK; 1184 } 1185 1186 /* 1187 *---------------------------------------------------------------------- 1188 * 1189 * SVGA3D_SetClipPlane -- 1190 * 1191 * Set one of the current context's clip planes. If the clip 1192 * plane is enabled then all 3d rendering is clipped to against 1193 * the plane. 1194 * 1195 * Results: 1196 * None. 1197 * 1198 * Side effects: 1199 * None. 1200 * 1201 *---------------------------------------------------------------------- 1202 */ 1203 1204 enum pipe_error 1205 SVGA3D_SetClipPlane(struct svga_winsys_context *swc, 1206 uint32 index, const float *plane) 1207 { 1208 SVGA3dCmdSetClipPlane *cmd; 1209 1210 cmd = SVGA3D_FIFOReserve(swc, 1211 SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd, 1212 0); 1213 if(!cmd) 1214 return PIPE_ERROR_OUT_OF_MEMORY; 1215 1216 cmd->cid = swc->cid; 1217 cmd->index = index; 1218 cmd->plane[0] = plane[0]; 1219 cmd->plane[1] = plane[1]; 1220 cmd->plane[2] = plane[2]; 1221 cmd->plane[3] = plane[3]; 1222 swc->commit(swc); 1223 1224 return PIPE_OK; 1225 } 1226 1227 /* 1228 *---------------------------------------------------------------------- 1229 * 1230 * SVGA3D_SetZRange -- 1231 * 1232 * Set the range of the depth buffer to use. 'min' and 'max' 1233 * are values between 0.0 and 1.0. 1234 * 1235 * Results: 1236 * None. 1237 * 1238 * Side effects: 1239 * None. 1240 * 1241 *---------------------------------------------------------------------- 1242 */ 1243 1244 enum pipe_error 1245 SVGA3D_SetZRange(struct svga_winsys_context *swc, 1246 float zMin, // IN 1247 float zMax) // IN 1248 { 1249 SVGA3dCmdSetZRange *cmd; 1250 1251 cmd = SVGA3D_FIFOReserve(swc, 1252 SVGA_3D_CMD_SETZRANGE, sizeof *cmd, 1253 0); 1254 if(!cmd) 1255 return PIPE_ERROR_OUT_OF_MEMORY; 1256 1257 cmd->cid = swc->cid; 1258 cmd->zRange.min = zMin; 1259 cmd->zRange.max = zMax; 1260 swc->commit(swc); 1261 1262 return PIPE_OK; 1263 } 1264 1265 1266 /* 1267 *---------------------------------------------------------------------- 1268 * 1269 * SVGA3D_BeginSetTextureState -- 1270 * 1271 * Begin a SETTEXTURESTATE command. This reserves space for it in 1272 * the FIFO, and returns a pointer to the command's texture state 1273 * array. This function must be paired with SVGA_FIFOCommitAll(). 1274 * 1275 * This command sets rendering state which is per-texture-unit. 1276 * 1277 * XXX: Individual texture states need documentation. However, 1278 * they are very similar to the texture states defined by 1279 * Direct3D. The D3D documentation is a good starting point 1280 * for understanding SVGA3D texture states. 1281 * 1282 * Results: 1283 * None. 1284 * 1285 * Side effects: 1286 * None. 1287 * 1288 *---------------------------------------------------------------------- 1289 */ 1290 1291 enum pipe_error 1292 SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc, 1293 SVGA3dTextureState **states, // OUT 1294 uint32 numStates) // IN 1295 { 1296 SVGA3dCmdSetTextureState *cmd; 1297 1298 cmd = SVGA3D_FIFOReserve(swc, 1299 SVGA_3D_CMD_SETTEXTURESTATE, 1300 sizeof *cmd + sizeof **states * numStates, 1301 numStates); 1302 if(!cmd) 1303 return PIPE_ERROR_OUT_OF_MEMORY; 1304 1305 cmd->cid = swc->cid; 1306 *states = (SVGA3dTextureState*) &cmd[1]; 1307 1308 return PIPE_OK; 1309 } 1310 1311 1312 /* 1313 *---------------------------------------------------------------------- 1314 * 1315 * SVGA3D_BeginSetRenderState -- 1316 * 1317 * Begin a SETRENDERSTATE command. This reserves space for it in 1318 * the FIFO, and returns a pointer to the command's texture state 1319 * array. This function must be paired with SVGA_FIFOCommitAll(). 1320 * 1321 * This command sets rendering state which is global to the context. 1322 * 1323 * XXX: Individual render states need documentation. However, 1324 * they are very similar to the render states defined by 1325 * Direct3D. The D3D documentation is a good starting point 1326 * for understanding SVGA3D render states. 1327 * 1328 * Results: 1329 * None. 1330 * 1331 * Side effects: 1332 * None. 1333 * 1334 *---------------------------------------------------------------------- 1335 */ 1336 1337 enum pipe_error 1338 SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc, 1339 SVGA3dRenderState **states, // OUT 1340 uint32 numStates) // IN 1341 { 1342 SVGA3dCmdSetRenderState *cmd; 1343 1344 cmd = SVGA3D_FIFOReserve(swc, 1345 SVGA_3D_CMD_SETRENDERSTATE, 1346 sizeof *cmd + sizeof **states * numStates, 1347 0); 1348 if(!cmd) 1349 return PIPE_ERROR_OUT_OF_MEMORY; 1350 1351 cmd->cid = swc->cid; 1352 *states = (SVGA3dRenderState*) &cmd[1]; 1353 1354 return PIPE_OK; 1355 } 1356 1357 1358 /* 1359 *---------------------------------------------------------------------- 1360 * 1361 * SVGA3D_BeginQuery-- 1362 * 1363 * Issues a SVGA_3D_CMD_BEGIN_QUERY command. 1364 * 1365 * Results: 1366 * None. 1367 * 1368 * Side effects: 1369 * Commits space in the FIFO memory. 1370 * 1371 *---------------------------------------------------------------------- 1372 */ 1373 1374 enum pipe_error 1375 SVGA3D_BeginQuery(struct svga_winsys_context *swc, 1376 SVGA3dQueryType type) // IN 1377 { 1378 SVGA3dCmdBeginQuery *cmd; 1379 1380 cmd = SVGA3D_FIFOReserve(swc, 1381 SVGA_3D_CMD_BEGIN_QUERY, 1382 sizeof *cmd, 1383 0); 1384 if(!cmd) 1385 return PIPE_ERROR_OUT_OF_MEMORY; 1386 1387 cmd->cid = swc->cid; 1388 cmd->type = type; 1389 1390 swc->commit(swc); 1391 1392 return PIPE_OK; 1393 } 1394 1395 1396 /* 1397 *---------------------------------------------------------------------- 1398 * 1399 * SVGA3D_EndQuery-- 1400 * 1401 * Issues a SVGA_3D_CMD_END_QUERY command. 1402 * 1403 * Results: 1404 * None. 1405 * 1406 * Side effects: 1407 * Commits space in the FIFO memory. 1408 * 1409 *---------------------------------------------------------------------- 1410 */ 1411 1412 enum pipe_error 1413 SVGA3D_EndQuery(struct svga_winsys_context *swc, 1414 SVGA3dQueryType type, // IN 1415 struct svga_winsys_buffer *buffer) // IN/OUT 1416 { 1417 SVGA3dCmdEndQuery *cmd; 1418 1419 cmd = SVGA3D_FIFOReserve(swc, 1420 SVGA_3D_CMD_END_QUERY, 1421 sizeof *cmd, 1422 1); 1423 if(!cmd) 1424 return PIPE_ERROR_OUT_OF_MEMORY; 1425 1426 cmd->cid = swc->cid; 1427 cmd->type = type; 1428 1429 swc->region_relocation(swc, &cmd->guestResult, buffer, 0, 1430 SVGA_RELOC_WRITE); 1431 1432 swc->commit(swc); 1433 1434 return PIPE_OK; 1435 } 1436 1437 1438 /* 1439 *---------------------------------------------------------------------- 1440 * 1441 * SVGA3D_WaitForQuery-- 1442 * 1443 * Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command. This reserves space 1444 * for it in the FIFO. This doesn't actually wait for the query to 1445 * finish but instead tells the host to start a wait at the driver 1446 * level. The caller can wait on the status variable in the 1447 * guestPtr memory or send an insert fence instruction after this 1448 * command and wait on the fence. 1449 * 1450 * Results: 1451 * None. 1452 * 1453 * Side effects: 1454 * Commits space in the FIFO memory. 1455 * 1456 *---------------------------------------------------------------------- 1457 */ 1458 1459 enum pipe_error 1460 SVGA3D_WaitForQuery(struct svga_winsys_context *swc, 1461 SVGA3dQueryType type, // IN 1462 struct svga_winsys_buffer *buffer) // IN/OUT 1463 { 1464 SVGA3dCmdWaitForQuery *cmd; 1465 1466 cmd = SVGA3D_FIFOReserve(swc, 1467 SVGA_3D_CMD_WAIT_FOR_QUERY, 1468 sizeof *cmd, 1469 1); 1470 if(!cmd) 1471 return PIPE_ERROR_OUT_OF_MEMORY; 1472 1473 cmd->cid = swc->cid; 1474 cmd->type = type; 1475 1476 swc->region_relocation(swc, &cmd->guestResult, buffer, 0, 1477 SVGA_RELOC_WRITE); 1478 1479 swc->commit(swc); 1480 1481 return PIPE_OK; 1482 } 1483