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