svga: Propagate discard/unsynchronized flags to the host when doing texture DMAs.
[mesa.git] / src / gallium / drivers / svga / svga_cmd.c
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 filld out.
50 *
51 * Side effects:
52 * One surface relocation is preformed 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 hierarchial:
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_BeginSurfaceDMA--
380 *
381 * Begin a SURFACE_DMA command. This reserves space for it in
382 * the FIFO, and returns a pointer to the command's box array.
383 * This function must be paired with SVGA_FIFOCommitAll().
384 *
385 * When the SVGA3D device asynchronously processes this FIFO
386 * command, a DMA operation is performed between host VRAM and
387 * a generic SVGAGuestPtr. The guest pointer may refer to guest
388 * VRAM (provided by the SVGA PCI device) or to guest system
389 * memory that has been set up as a Guest Memory Region (GMR)
390 * by the SVGA device.
391 *
392 * The guest's DMA buffer must remain valid (not freed, paged out,
393 * or overwritten) until the host has finished processing this
394 * command. The guest can determine that the host has finished
395 * by using the SVGA device's FIFO Fence mechanism.
396 *
397 * The guest's image buffer can be an arbitrary size and shape.
398 * Guest image data is interpreted according to the SVGA3D surface
399 * format specified when the surface was defined.
400 *
401 * The caller may optionally define the guest image's pitch.
402 * guestImage->pitch can either be zero (assume image is tightly
403 * packed) or it must be the number of bytes between vertically
404 * adjacent image blocks.
405 *
406 * The provided copybox list specifies which regions of the source
407 * image are to be copied, and where they appear on the destination.
408 *
409 * NOTE: srcx/srcy are always on the guest image and x/y are
410 * always on the host image, regardless of the actual transfer
411 * direction!
412 *
413 * For efficiency, the SVGA3D device is free to copy more data
414 * than specified. For example, it may round copy boxes outwards
415 * such that they lie on particular alignment boundaries.
416 *
417 *----------------------------------------------------------------------
418 */
419
420 enum pipe_error
421 SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
422 struct svga_transfer *st, // IN
423 SVGA3dTransferType transfer, // IN
424 const SVGA3dCopyBox *boxes, // IN
425 uint32 numBoxes, // IN
426 SVGA3dSurfaceDMAFlags flags) // IN
427 {
428 struct svga_texture *texture = svga_texture(st->base.resource);
429 SVGA3dCmdSurfaceDMA *cmd;
430 SVGA3dCmdSurfaceDMASuffix *pSuffix;
431 uint32 boxesSize = sizeof *boxes * numBoxes;
432 unsigned region_flags;
433 unsigned surface_flags;
434
435 if(transfer == SVGA3D_WRITE_HOST_VRAM) {
436 region_flags = SVGA_RELOC_READ;
437 surface_flags = SVGA_RELOC_WRITE;
438 }
439 else if(transfer == SVGA3D_READ_HOST_VRAM) {
440 region_flags = SVGA_RELOC_WRITE;
441 surface_flags = SVGA_RELOC_READ;
442 }
443 else {
444 assert(0);
445 return PIPE_ERROR_BAD_INPUT;
446 }
447
448 cmd = SVGA3D_FIFOReserve(swc,
449 SVGA_3D_CMD_SURFACE_DMA,
450 sizeof *cmd + boxesSize + sizeof *pSuffix,
451 2);
452 if(!cmd)
453 return PIPE_ERROR_OUT_OF_MEMORY;
454
455 swc->region_relocation(swc, &cmd->guest.ptr, st->hwbuf, 0, region_flags);
456 cmd->guest.pitch = st->base.stride;
457
458 swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags);
459 cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
460 cmd->host.mipmap = st->base.level;
461
462 cmd->transfer = transfer;
463
464 memcpy(&cmd[1], boxes, boxesSize);
465
466 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize);
467 pSuffix->suffixSize = sizeof *pSuffix;
468 pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride;
469 pSuffix->flags = flags;
470
471 swc->commit(swc);
472
473 return PIPE_OK;
474 }
475
476
477 enum pipe_error
478 SVGA3D_BufferDMA(struct svga_winsys_context *swc,
479 struct svga_winsys_buffer *guest,
480 struct svga_winsys_surface *host,
481 SVGA3dTransferType transfer, // IN
482 uint32 size, // IN
483 uint32 guest_offset, // IN
484 uint32 host_offset, // IN
485 SVGA3dSurfaceDMAFlags flags) // IN
486 {
487 SVGA3dCmdSurfaceDMA *cmd;
488 SVGA3dCopyBox *box;
489 SVGA3dCmdSurfaceDMASuffix *pSuffix;
490 unsigned region_flags;
491 unsigned surface_flags;
492
493 if(transfer == SVGA3D_WRITE_HOST_VRAM) {
494 region_flags = SVGA_RELOC_READ;
495 surface_flags = SVGA_RELOC_WRITE;
496 }
497 else if(transfer == SVGA3D_READ_HOST_VRAM) {
498 region_flags = SVGA_RELOC_WRITE;
499 surface_flags = SVGA_RELOC_READ;
500 }
501 else {
502 assert(0);
503 return PIPE_ERROR_BAD_INPUT;
504 }
505
506 cmd = SVGA3D_FIFOReserve(swc,
507 SVGA_3D_CMD_SURFACE_DMA,
508 sizeof *cmd + sizeof *box + sizeof *pSuffix,
509 2);
510 if(!cmd)
511 return PIPE_ERROR_OUT_OF_MEMORY;
512
513 swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
514 cmd->guest.pitch = 0;
515
516 swc->surface_relocation(swc, &cmd->host.sid, host, surface_flags);
517 cmd->host.face = 0;
518 cmd->host.mipmap = 0;
519
520 cmd->transfer = transfer;
521
522 box = (SVGA3dCopyBox *)&cmd[1];
523 box->x = host_offset;
524 box->y = 0;
525 box->z = 0;
526 box->w = size;
527 box->h = 1;
528 box->d = 1;
529 box->srcx = guest_offset;
530 box->srcy = 0;
531 box->srcz = 0;
532
533 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box);
534 pSuffix->suffixSize = sizeof *pSuffix;
535 pSuffix->maximumOffset = guest_offset + size;
536 pSuffix->flags = flags;
537
538 swc->commit(swc);
539
540 return PIPE_OK;
541 }
542
543
544 /*
545 *----------------------------------------------------------------------
546 *
547 * SVGA3D_SetRenderTarget --
548 *
549 * Bind a surface object to a particular render target attachment
550 * point on the current context. Render target attachment points
551 * exist for color buffers, a depth buffer, and a stencil buffer.
552 *
553 * The SVGA3D device is quite lenient about the types of surfaces
554 * that may be used as render targets. The color buffers must
555 * all be the same size, but the depth and stencil buffers do not
556 * have to be the same size as the color buffer. All attachments
557 * are optional.
558 *
559 * Some combinations of render target formats may require software
560 * emulation, depending on the capabilities of the host graphics
561 * API and graphics hardware.
562 *
563 * Results:
564 * None.
565 *
566 * Side effects:
567 * None.
568 *
569 *----------------------------------------------------------------------
570 */
571
572 enum pipe_error
573 SVGA3D_SetRenderTarget(struct svga_winsys_context *swc,
574 SVGA3dRenderTargetType type, // IN
575 struct pipe_surface *surface) // IN
576 {
577 SVGA3dCmdSetRenderTarget *cmd;
578
579 cmd = SVGA3D_FIFOReserve(swc,
580 SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd, 1);
581 if(!cmd)
582 return PIPE_ERROR_OUT_OF_MEMORY;
583
584
585 cmd->cid = swc->cid;
586
587 cmd->type = type;
588
589 surface_to_surfaceid(swc, surface, &cmd->target, SVGA_RELOC_WRITE);
590
591 swc->commit(swc);
592
593 return PIPE_OK;
594 }
595
596
597
598
599
600
601 /*
602 *----------------------------------------------------------------------
603 *
604 * SVGA3D_DefineShader --
605 *
606 * Upload the bytecode for a new shader. The bytecode is "SVGA3D
607 * format", which is theoretically a binary-compatible superset
608 * of Microsoft's DirectX shader bytecode. In practice, the
609 * SVGA3D bytecode doesn't yet have any extensions to DirectX's
610 * bytecode format.
611 *
612 * The SVGA3D device supports shader models 1.1 through 2.0.
613 *
614 * The caller chooses a shader ID (small positive integer) by
615 * which this shader will be identified in future commands. This
616 * ID is in a namespace which is per-context and per-shader-type.
617 *
618 * 'bytecodeLen' is specified in bytes. It must be a multiple of 4.
619 *
620 * Results:
621 * None.
622 *
623 * Side effects:
624 * None.
625 *
626 *----------------------------------------------------------------------
627 */
628
629 enum pipe_error
630 SVGA3D_DefineShader(struct svga_winsys_context *swc,
631 uint32 shid, // IN
632 SVGA3dShaderType type, // IN
633 const uint32 *bytecode, // IN
634 uint32 bytecodeLen) // IN
635 {
636 SVGA3dCmdDefineShader *cmd;
637
638 assert(bytecodeLen % 4 == 0);
639
640 cmd = SVGA3D_FIFOReserve(swc,
641 SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen,
642 0);
643 if(!cmd)
644 return PIPE_ERROR_OUT_OF_MEMORY;
645
646 cmd->cid = swc->cid;
647 cmd->shid = shid;
648 cmd->type = type;
649 memcpy(&cmd[1], bytecode, bytecodeLen);
650 swc->commit(swc);
651
652 return PIPE_OK;
653 }
654
655
656 /*
657 *----------------------------------------------------------------------
658 *
659 * SVGA3D_DestroyShader --
660 *
661 * Delete a shader that was created by SVGA3D_DefineShader. If
662 * the shader was the current vertex or pixel shader for its
663 * context, rendering results are undefined until a new shader is
664 * bound.
665 *
666 * Results:
667 * None.
668 *
669 * Side effects:
670 * None.
671 *
672 *----------------------------------------------------------------------
673 */
674
675 enum pipe_error
676 SVGA3D_DestroyShader(struct svga_winsys_context *swc,
677 uint32 shid, // IN
678 SVGA3dShaderType type) // IN
679 {
680 SVGA3dCmdDestroyShader *cmd;
681
682 cmd = SVGA3D_FIFOReserve(swc,
683 SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd,
684 0);
685 if(!cmd)
686 return PIPE_ERROR_OUT_OF_MEMORY;
687
688 cmd->cid = swc->cid;
689 cmd->shid = shid;
690 cmd->type = type;
691 swc->commit(swc);
692
693 return PIPE_OK;
694 }
695
696
697 /*
698 *----------------------------------------------------------------------
699 *
700 * SVGA3D_SetShaderConst --
701 *
702 * Set the value of a shader constant.
703 *
704 * Shader constants are analogous to uniform variables in GLSL,
705 * except that they belong to the render context rather than to
706 * an individual shader.
707 *
708 * Constants may have one of three types: A 4-vector of floats,
709 * a 4-vector of integers, or a single boolean flag.
710 *
711 * Results:
712 * None.
713 *
714 * Side effects:
715 * None.
716 *
717 *----------------------------------------------------------------------
718 */
719
720 enum pipe_error
721 SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
722 uint32 reg, // IN
723 SVGA3dShaderType type, // IN
724 SVGA3dShaderConstType ctype, // IN
725 const void *value) // IN
726 {
727 SVGA3dCmdSetShaderConst *cmd;
728
729 cmd = SVGA3D_FIFOReserve(swc,
730 SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd,
731 0);
732 if(!cmd)
733 return PIPE_ERROR_OUT_OF_MEMORY;
734
735 cmd->cid = swc->cid;
736 cmd->reg = reg;
737 cmd->type = type;
738 cmd->ctype = ctype;
739
740 switch (ctype) {
741
742 case SVGA3D_CONST_TYPE_FLOAT:
743 case SVGA3D_CONST_TYPE_INT:
744 memcpy(&cmd->values, value, sizeof cmd->values);
745 break;
746
747 case SVGA3D_CONST_TYPE_BOOL:
748 memset(&cmd->values, 0, sizeof cmd->values);
749 cmd->values[0] = *(uint32*)value;
750 break;
751
752 default:
753 assert(0);
754 break;
755
756 }
757 swc->commit(swc);
758
759 return PIPE_OK;
760 }
761
762
763
764
765
766 /*
767 *----------------------------------------------------------------------
768 *
769 * SVGA3D_SetShader --
770 *
771 * Switch active shaders. This binds a new vertex or pixel shader
772 * to the specified context.
773 *
774 * A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
775 * back to the fixed function vertex or pixel pipeline.
776 *
777 * Results:
778 * None.
779 *
780 * Side effects:
781 * None.
782 *
783 *----------------------------------------------------------------------
784 */
785
786 enum pipe_error
787 SVGA3D_SetShader(struct svga_winsys_context *swc,
788 SVGA3dShaderType type, // IN
789 uint32 shid) // IN
790 {
791 SVGA3dCmdSetShader *cmd;
792
793 cmd = SVGA3D_FIFOReserve(swc,
794 SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
795 0);
796 if(!cmd)
797 return PIPE_ERROR_OUT_OF_MEMORY;
798
799 cmd->cid = swc->cid;
800 cmd->type = type;
801 cmd->shid = shid;
802 swc->commit(swc);
803
804 return PIPE_OK;
805 }
806
807
808 /*
809 *----------------------------------------------------------------------
810 *
811 * SVGA3D_BeginClear --
812 *
813 * Begin a CLEAR command. This reserves space for it in the FIFO,
814 * and returns a pointer to the command's rectangle array. This
815 * function must be paired with SVGA_FIFOCommitAll().
816 *
817 * Clear is a rendering operation which fills a list of
818 * rectangles with constant values on all render target types
819 * indicated by 'flags'.
820 *
821 * Clear is not affected by clipping, depth test, or other
822 * render state which affects the fragment pipeline.
823 *
824 * Results:
825 * None.
826 *
827 * Side effects:
828 * May write to attached render target surfaces.
829 *
830 *----------------------------------------------------------------------
831 */
832
833 enum pipe_error
834 SVGA3D_BeginClear(struct svga_winsys_context *swc,
835 SVGA3dClearFlag flags, // IN
836 uint32 color, // IN
837 float depth, // IN
838 uint32 stencil, // IN
839 SVGA3dRect **rects, // OUT
840 uint32 numRects) // IN
841 {
842 SVGA3dCmdClear *cmd;
843
844 cmd = SVGA3D_FIFOReserve(swc,
845 SVGA_3D_CMD_CLEAR,
846 sizeof *cmd + sizeof **rects * numRects,
847 0);
848 if(!cmd)
849 return PIPE_ERROR_OUT_OF_MEMORY;
850
851 cmd->cid = swc->cid;
852 cmd->clearFlag = flags;
853 cmd->color = color;
854 cmd->depth = depth;
855 cmd->stencil = stencil;
856 *rects = (SVGA3dRect*) &cmd[1];
857
858 return PIPE_OK;
859 }
860
861
862 /*
863 *----------------------------------------------------------------------
864 *
865 * SVGA3D_ClearRect --
866 *
867 * This is a simplified version of SVGA3D_BeginClear().
868 *
869 * Results:
870 * None.
871 *
872 * Side effects:
873 * None.
874 *
875 *----------------------------------------------------------------------
876 */
877
878 enum pipe_error
879 SVGA3D_ClearRect(struct svga_winsys_context *swc,
880 SVGA3dClearFlag flags, // IN
881 uint32 color, // IN
882 float depth, // IN
883 uint32 stencil, // IN
884 uint32 x, // IN
885 uint32 y, // IN
886 uint32 w, // IN
887 uint32 h) // IN
888 {
889 SVGA3dRect *rect;
890 enum pipe_error ret;
891
892 ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
893 if(ret != PIPE_OK)
894 return PIPE_ERROR_OUT_OF_MEMORY;
895
896 memset(rect, 0, sizeof *rect);
897 rect->x = x;
898 rect->y = y;
899 rect->w = w;
900 rect->h = h;
901 swc->commit(swc);
902
903 return PIPE_OK;
904 }
905
906
907 /*
908 *----------------------------------------------------------------------
909 *
910 * SVGA3D_BeginDrawPrimitives --
911 *
912 * Begin a DRAW_PRIMITIVES command. This reserves space for it in
913 * the FIFO, and returns a pointer to the command's arrays.
914 * This function must be paired with SVGA_FIFOCommitAll().
915 *
916 * Drawing commands consist of two variable-length arrays:
917 * SVGA3dVertexDecl elements declare a set of vertex buffers to
918 * use while rendering, and SVGA3dPrimitiveRange elements specify
919 * groups of primitives each with an optional index buffer.
920 *
921 * The decls and ranges arrays are initialized to zero.
922 *
923 * Results:
924 * None.
925 *
926 * Side effects:
927 * May write to attached render target surfaces.
928 *
929 *----------------------------------------------------------------------
930 */
931
932 enum pipe_error
933 SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
934 SVGA3dVertexDecl **decls, // OUT
935 uint32 numVertexDecls, // IN
936 SVGA3dPrimitiveRange **ranges, // OUT
937 uint32 numRanges) // IN
938 {
939 SVGA3dCmdDrawPrimitives *cmd;
940 SVGA3dVertexDecl *declArray;
941 SVGA3dPrimitiveRange *rangeArray;
942 uint32 declSize = sizeof **decls * numVertexDecls;
943 uint32 rangeSize = sizeof **ranges * numRanges;
944
945 cmd = SVGA3D_FIFOReserve(swc,
946 SVGA_3D_CMD_DRAW_PRIMITIVES,
947 sizeof *cmd + declSize + rangeSize,
948 numVertexDecls + numRanges);
949 if(!cmd)
950 return PIPE_ERROR_OUT_OF_MEMORY;
951
952 cmd->cid = swc->cid;
953 cmd->numVertexDecls = numVertexDecls;
954 cmd->numRanges = numRanges;
955
956 declArray = (SVGA3dVertexDecl*) &cmd[1];
957 rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
958
959 memset(declArray, 0, declSize);
960 memset(rangeArray, 0, rangeSize);
961
962 *decls = declArray;
963 *ranges = rangeArray;
964
965 return PIPE_OK;
966 }
967
968
969 /*
970 *----------------------------------------------------------------------
971 *
972 * SVGA3D_BeginSurfaceCopy --
973 *
974 * Begin a SURFACE_COPY command. This reserves space for it in
975 * the FIFO, and returns a pointer to the command's arrays. This
976 * function must be paired with SVGA_FIFOCommitAll().
977 *
978 * The box array is initialized with zeroes.
979 *
980 * Results:
981 * None.
982 *
983 * Side effects:
984 * Asynchronously copies a list of boxes from surface to surface.
985 *
986 *----------------------------------------------------------------------
987 */
988
989 enum pipe_error
990 SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
991 struct pipe_surface *src, // IN
992 struct pipe_surface *dest, // IN
993 SVGA3dCopyBox **boxes, // OUT
994 uint32 numBoxes) // IN
995 {
996 SVGA3dCmdSurfaceCopy *cmd;
997 uint32 boxesSize = sizeof **boxes * numBoxes;
998
999 cmd = SVGA3D_FIFOReserve(swc,
1000 SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
1001 2);
1002 if(!cmd)
1003 return PIPE_ERROR_OUT_OF_MEMORY;
1004
1005 surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1006 surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1007 *boxes = (SVGA3dCopyBox*) &cmd[1];
1008
1009 memset(*boxes, 0, boxesSize);
1010
1011 return PIPE_OK;
1012 }
1013
1014
1015 /*
1016 *----------------------------------------------------------------------
1017 *
1018 * SVGA3D_SurfaceStretchBlt --
1019 *
1020 * Issue a SURFACE_STRETCHBLT command: an asynchronous
1021 * surface-to-surface blit, with scaling.
1022 *
1023 * Results:
1024 * None.
1025 *
1026 * Side effects:
1027 * Asynchronously copies one box from surface to surface.
1028 *
1029 *----------------------------------------------------------------------
1030 */
1031
1032 enum pipe_error
1033 SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
1034 struct pipe_surface *src, // IN
1035 struct pipe_surface *dest, // IN
1036 SVGA3dBox *boxSrc, // IN
1037 SVGA3dBox *boxDest, // IN
1038 SVGA3dStretchBltMode mode) // IN
1039 {
1040 SVGA3dCmdSurfaceStretchBlt *cmd;
1041
1042 cmd = SVGA3D_FIFOReserve(swc,
1043 SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
1044 2);
1045 if(!cmd)
1046 return PIPE_ERROR_OUT_OF_MEMORY;
1047
1048 surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1049 surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1050 cmd->boxSrc = *boxSrc;
1051 cmd->boxDest = *boxDest;
1052 cmd->mode = mode;
1053 swc->commit(swc);
1054
1055 return PIPE_OK;
1056 }
1057
1058
1059 /*
1060 *----------------------------------------------------------------------
1061 *
1062 * SVGA3D_SetViewport --
1063 *
1064 * Set the current context's viewport rectangle. The viewport
1065 * is clipped to the dimensions of the current render target,
1066 * then all rendering is clipped to the viewport.
1067 *
1068 * Results:
1069 * None.
1070 *
1071 * Side effects:
1072 * None.
1073 *
1074 *----------------------------------------------------------------------
1075 */
1076
1077 enum pipe_error
1078 SVGA3D_SetViewport(struct svga_winsys_context *swc,
1079 SVGA3dRect *rect) // IN
1080 {
1081 SVGA3dCmdSetViewport *cmd;
1082
1083 cmd = SVGA3D_FIFOReserve(swc,
1084 SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
1085 0);
1086 if(!cmd)
1087 return PIPE_ERROR_OUT_OF_MEMORY;
1088
1089 cmd->cid = swc->cid;
1090 cmd->rect = *rect;
1091 swc->commit(swc);
1092
1093 return PIPE_OK;
1094 }
1095
1096
1097
1098
1099 /*
1100 *----------------------------------------------------------------------
1101 *
1102 * SVGA3D_SetScissorRect --
1103 *
1104 * Set the current context's scissor rectangle. If scissor
1105 * is enabled then all rendering is clipped to the scissor.
1106 *
1107 * Results:
1108 * None.
1109 *
1110 * Side effects:
1111 * None.
1112 *
1113 *----------------------------------------------------------------------
1114 */
1115
1116 enum pipe_error
1117 SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
1118 SVGA3dRect *rect) // IN
1119 {
1120 SVGA3dCmdSetScissorRect *cmd;
1121
1122 cmd = SVGA3D_FIFOReserve(swc,
1123 SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
1124 0);
1125 if(!cmd)
1126 return PIPE_ERROR_OUT_OF_MEMORY;
1127
1128 cmd->cid = swc->cid;
1129 cmd->rect = *rect;
1130 swc->commit(swc);
1131
1132 return PIPE_OK;
1133 }
1134
1135 /*
1136 *----------------------------------------------------------------------
1137 *
1138 * SVGA3D_SetClipPlane --
1139 *
1140 * Set one of the current context's clip planes. If the clip
1141 * plane is enabled then all 3d rendering is clipped to against
1142 * the plane.
1143 *
1144 * Results:
1145 * None.
1146 *
1147 * Side effects:
1148 * None.
1149 *
1150 *----------------------------------------------------------------------
1151 */
1152
1153 enum pipe_error SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
1154 uint32 index, const float *plane)
1155 {
1156 SVGA3dCmdSetClipPlane *cmd;
1157
1158 cmd = SVGA3D_FIFOReserve(swc,
1159 SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
1160 0);
1161 if(!cmd)
1162 return PIPE_ERROR_OUT_OF_MEMORY;
1163
1164 cmd->cid = swc->cid;
1165 cmd->index = index;
1166 cmd->plane[0] = plane[0];
1167 cmd->plane[1] = plane[1];
1168 cmd->plane[2] = plane[2];
1169 cmd->plane[3] = plane[3];
1170 swc->commit(swc);
1171
1172 return PIPE_OK;
1173 }
1174
1175 /*
1176 *----------------------------------------------------------------------
1177 *
1178 * SVGA3D_SetZRange --
1179 *
1180 * Set the range of the depth buffer to use. 'min' and 'max'
1181 * are values between 0.0 and 1.0.
1182 *
1183 * Results:
1184 * None.
1185 *
1186 * Side effects:
1187 * None.
1188 *
1189 *----------------------------------------------------------------------
1190 */
1191
1192 enum pipe_error
1193 SVGA3D_SetZRange(struct svga_winsys_context *swc,
1194 float zMin, // IN
1195 float zMax) // IN
1196 {
1197 SVGA3dCmdSetZRange *cmd;
1198
1199 cmd = SVGA3D_FIFOReserve(swc,
1200 SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
1201 0);
1202 if(!cmd)
1203 return PIPE_ERROR_OUT_OF_MEMORY;
1204
1205 cmd->cid = swc->cid;
1206 cmd->zRange.min = zMin;
1207 cmd->zRange.max = zMax;
1208 swc->commit(swc);
1209
1210 return PIPE_OK;
1211 }
1212
1213
1214 /*
1215 *----------------------------------------------------------------------
1216 *
1217 * SVGA3D_BeginSetTextureState --
1218 *
1219 * Begin a SETTEXTURESTATE command. This reserves space for it in
1220 * the FIFO, and returns a pointer to the command's texture state
1221 * array. This function must be paired with SVGA_FIFOCommitAll().
1222 *
1223 * This command sets rendering state which is per-texture-unit.
1224 *
1225 * XXX: Individual texture states need documentation. However,
1226 * they are very similar to the texture states defined by
1227 * Direct3D. The D3D documentation is a good starting point
1228 * for understanding SVGA3D texture states.
1229 *
1230 * Results:
1231 * None.
1232 *
1233 * Side effects:
1234 * None.
1235 *
1236 *----------------------------------------------------------------------
1237 */
1238
1239 enum pipe_error
1240 SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
1241 SVGA3dTextureState **states, // OUT
1242 uint32 numStates) // IN
1243 {
1244 SVGA3dCmdSetTextureState *cmd;
1245
1246 cmd = SVGA3D_FIFOReserve(swc,
1247 SVGA_3D_CMD_SETTEXTURESTATE,
1248 sizeof *cmd + sizeof **states * numStates,
1249 numStates);
1250 if(!cmd)
1251 return PIPE_ERROR_OUT_OF_MEMORY;
1252
1253 cmd->cid = swc->cid;
1254 *states = (SVGA3dTextureState*) &cmd[1];
1255
1256 return PIPE_OK;
1257 }
1258
1259
1260 /*
1261 *----------------------------------------------------------------------
1262 *
1263 * SVGA3D_BeginSetRenderState --
1264 *
1265 * Begin a SETRENDERSTATE command. This reserves space for it in
1266 * the FIFO, and returns a pointer to the command's texture state
1267 * array. This function must be paired with SVGA_FIFOCommitAll().
1268 *
1269 * This command sets rendering state which is global to the context.
1270 *
1271 * XXX: Individual render states need documentation. However,
1272 * they are very similar to the render states defined by
1273 * Direct3D. The D3D documentation is a good starting point
1274 * for understanding SVGA3D render states.
1275 *
1276 * Results:
1277 * None.
1278 *
1279 * Side effects:
1280 * None.
1281 *
1282 *----------------------------------------------------------------------
1283 */
1284
1285 enum pipe_error
1286 SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
1287 SVGA3dRenderState **states, // OUT
1288 uint32 numStates) // IN
1289 {
1290 SVGA3dCmdSetRenderState *cmd;
1291
1292 cmd = SVGA3D_FIFOReserve(swc,
1293 SVGA_3D_CMD_SETRENDERSTATE,
1294 sizeof *cmd + sizeof **states * numStates,
1295 0);
1296 if(!cmd)
1297 return PIPE_ERROR_OUT_OF_MEMORY;
1298
1299 cmd->cid = swc->cid;
1300 *states = (SVGA3dRenderState*) &cmd[1];
1301
1302 return PIPE_OK;
1303 }
1304
1305
1306 /*
1307 *----------------------------------------------------------------------
1308 *
1309 * SVGA3D_BeginQuery--
1310 *
1311 * Issues a SVGA_3D_CMD_BEGIN_QUERY command.
1312 *
1313 * Results:
1314 * None.
1315 *
1316 * Side effects:
1317 * Commits space in the FIFO memory.
1318 *
1319 *----------------------------------------------------------------------
1320 */
1321
1322 enum pipe_error
1323 SVGA3D_BeginQuery(struct svga_winsys_context *swc,
1324 SVGA3dQueryType type) // IN
1325 {
1326 SVGA3dCmdBeginQuery *cmd;
1327
1328 cmd = SVGA3D_FIFOReserve(swc,
1329 SVGA_3D_CMD_BEGIN_QUERY,
1330 sizeof *cmd,
1331 0);
1332 if(!cmd)
1333 return PIPE_ERROR_OUT_OF_MEMORY;
1334
1335 cmd->cid = swc->cid;
1336 cmd->type = type;
1337
1338 swc->commit(swc);
1339
1340 return PIPE_OK;
1341 }
1342
1343
1344 /*
1345 *----------------------------------------------------------------------
1346 *
1347 * SVGA3D_EndQuery--
1348 *
1349 * Issues a SVGA_3D_CMD_END_QUERY command.
1350 *
1351 * Results:
1352 * None.
1353 *
1354 * Side effects:
1355 * Commits space in the FIFO memory.
1356 *
1357 *----------------------------------------------------------------------
1358 */
1359
1360 enum pipe_error
1361 SVGA3D_EndQuery(struct svga_winsys_context *swc,
1362 SVGA3dQueryType type, // IN
1363 struct svga_winsys_buffer *buffer) // IN/OUT
1364 {
1365 SVGA3dCmdEndQuery *cmd;
1366
1367 cmd = SVGA3D_FIFOReserve(swc,
1368 SVGA_3D_CMD_END_QUERY,
1369 sizeof *cmd,
1370 1);
1371 if(!cmd)
1372 return PIPE_ERROR_OUT_OF_MEMORY;
1373
1374 cmd->cid = swc->cid;
1375 cmd->type = type;
1376
1377 swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1378 SVGA_RELOC_WRITE);
1379
1380 swc->commit(swc);
1381
1382 return PIPE_OK;
1383 }
1384
1385
1386 /*
1387 *----------------------------------------------------------------------
1388 *
1389 * SVGA3D_WaitForQuery--
1390 *
1391 * Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command. This reserves space
1392 * for it in the FIFO. This doesn't actually wait for the query to
1393 * finish but instead tells the host to start a wait at the driver
1394 * level. The caller can wait on the status variable in the
1395 * guestPtr memory or send an insert fence instruction after this
1396 * command and wait on the fence.
1397 *
1398 * Results:
1399 * None.
1400 *
1401 * Side effects:
1402 * Commits space in the FIFO memory.
1403 *
1404 *----------------------------------------------------------------------
1405 */
1406
1407 enum pipe_error
1408 SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
1409 SVGA3dQueryType type, // IN
1410 struct svga_winsys_buffer *buffer) // IN/OUT
1411 {
1412 SVGA3dCmdWaitForQuery *cmd;
1413
1414 cmd = SVGA3D_FIFOReserve(swc,
1415 SVGA_3D_CMD_WAIT_FOR_QUERY,
1416 sizeof *cmd,
1417 1);
1418 if(!cmd)
1419 return PIPE_ERROR_OUT_OF_MEMORY;
1420
1421 cmd->cid = swc->cid;
1422 cmd->type = type;
1423
1424 swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1425 SVGA_RELOC_WRITE);
1426
1427 swc->commit(swc);
1428
1429 return PIPE_OK;
1430 }