04307d17fe0cd59fe078f6a6887bdaaa8ce4ee96
[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 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 = PIPE_BUFFER_USAGE_GPU_READ;
493 surface_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
494 }
495 else if(transfer == SVGA3D_READ_HOST_VRAM) {
496 region_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
497 surface_flags = PIPE_BUFFER_USAGE_GPU_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, PIPE_BUFFER_USAGE_GPU_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 /*
765 *----------------------------------------------------------------------
766 *
767 * SVGA3D_SetShader --
768 *
769 * Switch active shaders. This binds a new vertex or pixel shader
770 * to the specified context.
771 *
772 * A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
773 * back to the fixed function vertex or pixel pipeline.
774 *
775 * Results:
776 * None.
777 *
778 * Side effects:
779 * None.
780 *
781 *----------------------------------------------------------------------
782 */
783
784 enum pipe_error
785 SVGA3D_SetShader(struct svga_winsys_context *swc,
786 SVGA3dShaderType type, // IN
787 uint32 shid) // IN
788 {
789 SVGA3dCmdSetShader *cmd;
790
791 cmd = SVGA3D_FIFOReserve(swc,
792 SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
793 0);
794 if(!cmd)
795 return PIPE_ERROR_OUT_OF_MEMORY;
796
797 cmd->cid = swc->cid;
798 cmd->type = type;
799 cmd->shid = shid;
800 swc->commit(swc);
801
802 return PIPE_OK;
803 }
804
805
806 /*
807 *----------------------------------------------------------------------
808 *
809 * SVGA3D_BeginClear --
810 *
811 * Begin a CLEAR command. This reserves space for it in the FIFO,
812 * and returns a pointer to the command's rectangle array. This
813 * function must be paired with SVGA_FIFOCommitAll().
814 *
815 * Clear is a rendering operation which fills a list of
816 * rectangles with constant values on all render target types
817 * indicated by 'flags'.
818 *
819 * Clear is not affected by clipping, depth test, or other
820 * render state which affects the fragment pipeline.
821 *
822 * Results:
823 * None.
824 *
825 * Side effects:
826 * May write to attached render target surfaces.
827 *
828 *----------------------------------------------------------------------
829 */
830
831 enum pipe_error
832 SVGA3D_BeginClear(struct svga_winsys_context *swc,
833 SVGA3dClearFlag flags, // IN
834 uint32 color, // IN
835 float depth, // IN
836 uint32 stencil, // IN
837 SVGA3dRect **rects, // OUT
838 uint32 numRects) // IN
839 {
840 SVGA3dCmdClear *cmd;
841
842 cmd = SVGA3D_FIFOReserve(swc,
843 SVGA_3D_CMD_CLEAR,
844 sizeof *cmd + sizeof **rects * numRects,
845 0);
846 if(!cmd)
847 return PIPE_ERROR_OUT_OF_MEMORY;
848
849 cmd->cid = swc->cid;
850 cmd->clearFlag = flags;
851 cmd->color = color;
852 cmd->depth = depth;
853 cmd->stencil = stencil;
854 *rects = (SVGA3dRect*) &cmd[1];
855
856 return PIPE_OK;
857 }
858
859
860 /*
861 *----------------------------------------------------------------------
862 *
863 * SVGA3D_ClearRect --
864 *
865 * This is a simplified version of SVGA3D_BeginClear().
866 *
867 * Results:
868 * None.
869 *
870 * Side effects:
871 * None.
872 *
873 *----------------------------------------------------------------------
874 */
875
876 enum pipe_error
877 SVGA3D_ClearRect(struct svga_winsys_context *swc,
878 SVGA3dClearFlag flags, // IN
879 uint32 color, // IN
880 float depth, // IN
881 uint32 stencil, // IN
882 uint32 x, // IN
883 uint32 y, // IN
884 uint32 w, // IN
885 uint32 h) // IN
886 {
887 SVGA3dRect *rect;
888 enum pipe_error ret;
889
890 ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
891 if(ret != PIPE_OK)
892 return PIPE_ERROR_OUT_OF_MEMORY;
893
894 memset(rect, 0, sizeof *rect);
895 rect->x = x;
896 rect->y = y;
897 rect->w = w;
898 rect->h = h;
899 swc->commit(swc);
900
901 return PIPE_OK;
902 }
903
904
905 /*
906 *----------------------------------------------------------------------
907 *
908 * SVGA3D_BeginDrawPrimitives --
909 *
910 * Begin a DRAW_PRIMITIVES command. This reserves space for it in
911 * the FIFO, and returns a pointer to the command's arrays.
912 * This function must be paired with SVGA_FIFOCommitAll().
913 *
914 * Drawing commands consist of two variable-length arrays:
915 * SVGA3dVertexDecl elements declare a set of vertex buffers to
916 * use while rendering, and SVGA3dPrimitiveRange elements specify
917 * groups of primitives each with an optional index buffer.
918 *
919 * The decls and ranges arrays are initialized to zero.
920 *
921 * Results:
922 * None.
923 *
924 * Side effects:
925 * May write to attached render target surfaces.
926 *
927 *----------------------------------------------------------------------
928 */
929
930 enum pipe_error
931 SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
932 SVGA3dVertexDecl **decls, // OUT
933 uint32 numVertexDecls, // IN
934 SVGA3dPrimitiveRange **ranges, // OUT
935 uint32 numRanges) // IN
936 {
937 SVGA3dCmdDrawPrimitives *cmd;
938 SVGA3dVertexDecl *declArray;
939 SVGA3dPrimitiveRange *rangeArray;
940 uint32 declSize = sizeof **decls * numVertexDecls;
941 uint32 rangeSize = sizeof **ranges * numRanges;
942
943 cmd = SVGA3D_FIFOReserve(swc,
944 SVGA_3D_CMD_DRAW_PRIMITIVES,
945 sizeof *cmd + declSize + rangeSize,
946 numVertexDecls + numRanges);
947 if(!cmd)
948 return PIPE_ERROR_OUT_OF_MEMORY;
949
950 cmd->cid = swc->cid;
951 cmd->numVertexDecls = numVertexDecls;
952 cmd->numRanges = numRanges;
953
954 declArray = (SVGA3dVertexDecl*) &cmd[1];
955 rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
956
957 memset(declArray, 0, declSize);
958 memset(rangeArray, 0, rangeSize);
959
960 *decls = declArray;
961 *ranges = rangeArray;
962
963 return PIPE_OK;
964 }
965
966
967 /*
968 *----------------------------------------------------------------------
969 *
970 * SVGA3D_BeginSurfaceCopy --
971 *
972 * Begin a SURFACE_COPY command. This reserves space for it in
973 * the FIFO, and returns a pointer to the command's arrays. This
974 * function must be paired with SVGA_FIFOCommitAll().
975 *
976 * The box array is initialized with zeroes.
977 *
978 * Results:
979 * None.
980 *
981 * Side effects:
982 * Asynchronously copies a list of boxes from surface to surface.
983 *
984 *----------------------------------------------------------------------
985 */
986
987 enum pipe_error
988 SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
989 struct pipe_surface *src, // IN
990 struct pipe_surface *dest, // IN
991 SVGA3dCopyBox **boxes, // OUT
992 uint32 numBoxes) // IN
993 {
994 SVGA3dCmdSurfaceCopy *cmd;
995 uint32 boxesSize = sizeof **boxes * numBoxes;
996
997 cmd = SVGA3D_FIFOReserve(swc,
998 SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
999 2);
1000 if(!cmd)
1001 return PIPE_ERROR_OUT_OF_MEMORY;
1002
1003 surface_to_surfaceid(swc, src, &cmd->src, PIPE_BUFFER_USAGE_GPU_READ);
1004 surface_to_surfaceid(swc, dest, &cmd->dest, PIPE_BUFFER_USAGE_GPU_WRITE);
1005 *boxes = (SVGA3dCopyBox*) &cmd[1];
1006
1007 memset(*boxes, 0, boxesSize);
1008
1009 return PIPE_OK;
1010 }
1011
1012
1013 /*
1014 *----------------------------------------------------------------------
1015 *
1016 * SVGA3D_SurfaceStretchBlt --
1017 *
1018 * Issue a SURFACE_STRETCHBLT command: an asynchronous
1019 * surface-to-surface blit, with scaling.
1020 *
1021 * Results:
1022 * None.
1023 *
1024 * Side effects:
1025 * Asynchronously copies one box from surface to surface.
1026 *
1027 *----------------------------------------------------------------------
1028 */
1029
1030 enum pipe_error
1031 SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
1032 struct pipe_surface *src, // IN
1033 struct pipe_surface *dest, // IN
1034 SVGA3dBox *boxSrc, // IN
1035 SVGA3dBox *boxDest, // IN
1036 SVGA3dStretchBltMode mode) // IN
1037 {
1038 SVGA3dCmdSurfaceStretchBlt *cmd;
1039
1040 cmd = SVGA3D_FIFOReserve(swc,
1041 SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
1042 2);
1043 if(!cmd)
1044 return PIPE_ERROR_OUT_OF_MEMORY;
1045
1046 surface_to_surfaceid(swc, src, &cmd->src, PIPE_BUFFER_USAGE_GPU_READ);
1047 surface_to_surfaceid(swc, dest, &cmd->dest, PIPE_BUFFER_USAGE_GPU_WRITE);
1048 cmd->boxSrc = *boxSrc;
1049 cmd->boxDest = *boxDest;
1050 cmd->mode = mode;
1051 swc->commit(swc);
1052
1053 return PIPE_OK;
1054 }
1055
1056
1057 /*
1058 *----------------------------------------------------------------------
1059 *
1060 * SVGA3D_SetViewport --
1061 *
1062 * Set the current context's viewport rectangle. The viewport
1063 * is clipped to the dimensions of the current render target,
1064 * then all rendering is clipped to the viewport.
1065 *
1066 * Results:
1067 * None.
1068 *
1069 * Side effects:
1070 * None.
1071 *
1072 *----------------------------------------------------------------------
1073 */
1074
1075 enum pipe_error
1076 SVGA3D_SetViewport(struct svga_winsys_context *swc,
1077 SVGA3dRect *rect) // IN
1078 {
1079 SVGA3dCmdSetViewport *cmd;
1080
1081 cmd = SVGA3D_FIFOReserve(swc,
1082 SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
1083 0);
1084 if(!cmd)
1085 return PIPE_ERROR_OUT_OF_MEMORY;
1086
1087 cmd->cid = swc->cid;
1088 cmd->rect = *rect;
1089 swc->commit(swc);
1090
1091 return PIPE_OK;
1092 }
1093
1094
1095
1096
1097 /*
1098 *----------------------------------------------------------------------
1099 *
1100 * SVGA3D_SetScissorRect --
1101 *
1102 * Set the current context's scissor rectangle. If scissor
1103 * is enabled then all rendering is clipped to the scissor.
1104 *
1105 * Results:
1106 * None.
1107 *
1108 * Side effects:
1109 * None.
1110 *
1111 *----------------------------------------------------------------------
1112 */
1113
1114 enum pipe_error
1115 SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
1116 SVGA3dRect *rect) // IN
1117 {
1118 SVGA3dCmdSetScissorRect *cmd;
1119
1120 cmd = SVGA3D_FIFOReserve(swc,
1121 SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
1122 0);
1123 if(!cmd)
1124 return PIPE_ERROR_OUT_OF_MEMORY;
1125
1126 cmd->cid = swc->cid;
1127 cmd->rect = *rect;
1128 swc->commit(swc);
1129
1130 return PIPE_OK;
1131 }
1132
1133 /*
1134 *----------------------------------------------------------------------
1135 *
1136 * SVGA3D_SetClipPlane --
1137 *
1138 * Set one of the current context's clip planes. If the clip
1139 * plane is enabled then all 3d rendering is clipped to against
1140 * the plane.
1141 *
1142 * Results:
1143 * None.
1144 *
1145 * Side effects:
1146 * None.
1147 *
1148 *----------------------------------------------------------------------
1149 */
1150
1151 enum pipe_error SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
1152 uint32 index, const float *plane)
1153 {
1154 SVGA3dCmdSetClipPlane *cmd;
1155
1156 cmd = SVGA3D_FIFOReserve(swc,
1157 SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
1158 0);
1159 if(!cmd)
1160 return PIPE_ERROR_OUT_OF_MEMORY;
1161
1162 cmd->cid = swc->cid;
1163 cmd->index = index;
1164 cmd->plane[0] = plane[0];
1165 cmd->plane[1] = plane[1];
1166 cmd->plane[2] = plane[2];
1167 cmd->plane[3] = plane[3];
1168 swc->commit(swc);
1169
1170 return PIPE_OK;
1171 }
1172
1173 /*
1174 *----------------------------------------------------------------------
1175 *
1176 * SVGA3D_SetZRange --
1177 *
1178 * Set the range of the depth buffer to use. 'min' and 'max'
1179 * are values between 0.0 and 1.0.
1180 *
1181 * Results:
1182 * None.
1183 *
1184 * Side effects:
1185 * None.
1186 *
1187 *----------------------------------------------------------------------
1188 */
1189
1190 enum pipe_error
1191 SVGA3D_SetZRange(struct svga_winsys_context *swc,
1192 float zMin, // IN
1193 float zMax) // IN
1194 {
1195 SVGA3dCmdSetZRange *cmd;
1196
1197 cmd = SVGA3D_FIFOReserve(swc,
1198 SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
1199 0);
1200 if(!cmd)
1201 return PIPE_ERROR_OUT_OF_MEMORY;
1202
1203 cmd->cid = swc->cid;
1204 cmd->zRange.min = zMin;
1205 cmd->zRange.max = zMax;
1206 swc->commit(swc);
1207
1208 return PIPE_OK;
1209 }
1210
1211
1212 /*
1213 *----------------------------------------------------------------------
1214 *
1215 * SVGA3D_BeginSetTextureState --
1216 *
1217 * Begin a SETTEXTURESTATE command. This reserves space for it in
1218 * the FIFO, and returns a pointer to the command's texture state
1219 * array. This function must be paired with SVGA_FIFOCommitAll().
1220 *
1221 * This command sets rendering state which is per-texture-unit.
1222 *
1223 * XXX: Individual texture states need documentation. However,
1224 * they are very similar to the texture states defined by
1225 * Direct3D. The D3D documentation is a good starting point
1226 * for understanding SVGA3D texture states.
1227 *
1228 * Results:
1229 * None.
1230 *
1231 * Side effects:
1232 * None.
1233 *
1234 *----------------------------------------------------------------------
1235 */
1236
1237 enum pipe_error
1238 SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
1239 SVGA3dTextureState **states, // OUT
1240 uint32 numStates) // IN
1241 {
1242 SVGA3dCmdSetTextureState *cmd;
1243
1244 cmd = SVGA3D_FIFOReserve(swc,
1245 SVGA_3D_CMD_SETTEXTURESTATE,
1246 sizeof *cmd + sizeof **states * numStates,
1247 numStates);
1248 if(!cmd)
1249 return PIPE_ERROR_OUT_OF_MEMORY;
1250
1251 cmd->cid = swc->cid;
1252 *states = (SVGA3dTextureState*) &cmd[1];
1253
1254 return PIPE_OK;
1255 }
1256
1257
1258 /*
1259 *----------------------------------------------------------------------
1260 *
1261 * SVGA3D_BeginSetRenderState --
1262 *
1263 * Begin a SETRENDERSTATE command. This reserves space for it in
1264 * the FIFO, and returns a pointer to the command's texture state
1265 * array. This function must be paired with SVGA_FIFOCommitAll().
1266 *
1267 * This command sets rendering state which is global to the context.
1268 *
1269 * XXX: Individual render states need documentation. However,
1270 * they are very similar to the render states defined by
1271 * Direct3D. The D3D documentation is a good starting point
1272 * for understanding SVGA3D render states.
1273 *
1274 * Results:
1275 * None.
1276 *
1277 * Side effects:
1278 * None.
1279 *
1280 *----------------------------------------------------------------------
1281 */
1282
1283 enum pipe_error
1284 SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
1285 SVGA3dRenderState **states, // OUT
1286 uint32 numStates) // IN
1287 {
1288 SVGA3dCmdSetRenderState *cmd;
1289
1290 cmd = SVGA3D_FIFOReserve(swc,
1291 SVGA_3D_CMD_SETRENDERSTATE,
1292 sizeof *cmd + sizeof **states * numStates,
1293 0);
1294 if(!cmd)
1295 return PIPE_ERROR_OUT_OF_MEMORY;
1296
1297 cmd->cid = swc->cid;
1298 *states = (SVGA3dRenderState*) &cmd[1];
1299
1300 return PIPE_OK;
1301 }
1302
1303
1304 /*
1305 *----------------------------------------------------------------------
1306 *
1307 * SVGA3D_BeginQuery--
1308 *
1309 * Issues a SVGA_3D_CMD_BEGIN_QUERY command.
1310 *
1311 * Results:
1312 * None.
1313 *
1314 * Side effects:
1315 * Commits space in the FIFO memory.
1316 *
1317 *----------------------------------------------------------------------
1318 */
1319
1320 enum pipe_error
1321 SVGA3D_BeginQuery(struct svga_winsys_context *swc,
1322 SVGA3dQueryType type) // IN
1323 {
1324 SVGA3dCmdBeginQuery *cmd;
1325
1326 cmd = SVGA3D_FIFOReserve(swc,
1327 SVGA_3D_CMD_BEGIN_QUERY,
1328 sizeof *cmd,
1329 0);
1330 if(!cmd)
1331 return PIPE_ERROR_OUT_OF_MEMORY;
1332
1333 cmd->cid = swc->cid;
1334 cmd->type = type;
1335
1336 swc->commit(swc);
1337
1338 return PIPE_OK;
1339 }
1340
1341
1342 /*
1343 *----------------------------------------------------------------------
1344 *
1345 * SVGA3D_EndQuery--
1346 *
1347 * Issues a SVGA_3D_CMD_END_QUERY command.
1348 *
1349 * Results:
1350 * None.
1351 *
1352 * Side effects:
1353 * Commits space in the FIFO memory.
1354 *
1355 *----------------------------------------------------------------------
1356 */
1357
1358 enum pipe_error
1359 SVGA3D_EndQuery(struct svga_winsys_context *swc,
1360 SVGA3dQueryType type, // IN
1361 struct svga_winsys_buffer *buffer) // IN/OUT
1362 {
1363 SVGA3dCmdEndQuery *cmd;
1364
1365 cmd = SVGA3D_FIFOReserve(swc,
1366 SVGA_3D_CMD_END_QUERY,
1367 sizeof *cmd,
1368 1);
1369 if(!cmd)
1370 return PIPE_ERROR_OUT_OF_MEMORY;
1371
1372 cmd->cid = swc->cid;
1373 cmd->type = type;
1374
1375 swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1376 PIPE_BUFFER_USAGE_GPU_WRITE);
1377
1378 swc->commit(swc);
1379
1380 return PIPE_OK;
1381 }
1382
1383
1384 /*
1385 *----------------------------------------------------------------------
1386 *
1387 * SVGA3D_WaitForQuery--
1388 *
1389 * Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command. This reserves space
1390 * for it in the FIFO. This doesn't actually wait for the query to
1391 * finish but instead tells the host to start a wait at the driver
1392 * level. The caller can wait on the status variable in the
1393 * guestPtr memory or send an insert fence instruction after this
1394 * command and wait on the fence.
1395 *
1396 * Results:
1397 * None.
1398 *
1399 * Side effects:
1400 * Commits space in the FIFO memory.
1401 *
1402 *----------------------------------------------------------------------
1403 */
1404
1405 enum pipe_error
1406 SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
1407 SVGA3dQueryType type, // IN
1408 struct svga_winsys_buffer *buffer) // IN/OUT
1409 {
1410 SVGA3dCmdWaitForQuery *cmd;
1411
1412 cmd = SVGA3D_FIFOReserve(swc,
1413 SVGA_3D_CMD_WAIT_FOR_QUERY,
1414 sizeof *cmd,
1415 1);
1416 if(!cmd)
1417 return PIPE_ERROR_OUT_OF_MEMORY;
1418
1419 cmd->cid = swc->cid;
1420 cmd->type = type;
1421
1422 swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1423 PIPE_BUFFER_USAGE_GPU_WRITE);
1424
1425 swc->commit(swc);
1426
1427 return PIPE_OK;
1428 }