svga: try to emit fewer buffer rebind commands
[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 *
49 * param flags mask of SVGA_RELOC_READ / _WRITE
50 *
51 * Results:
52 * id is filled out.
53 *
54 * Side effects:
55 * One surface relocation is performed for texture handle.
56 *
57 *----------------------------------------------------------------------
58 */
59
60 static inline void
61 surface_to_surfaceid(struct svga_winsys_context *swc, // IN
62 struct pipe_surface *surface, // IN
63 SVGA3dSurfaceImageId *id, // OUT
64 unsigned flags) // IN
65 {
66 if (surface) {
67 struct svga_surface *s = svga_surface(surface);
68 swc->surface_relocation(swc, &id->sid, NULL, s->handle, flags);
69 id->face = s->real_layer; /* faces have the same order */
70 id->mipmap = s->real_level;
71 }
72 else {
73 swc->surface_relocation(swc, &id->sid, NULL, NULL, flags);
74 id->face = 0;
75 id->mipmap = 0;
76 }
77 }
78
79
80 /*
81 *----------------------------------------------------------------------
82 *
83 * SVGA3D_FIFOReserve --
84 *
85 * Reserve space for an SVGA3D FIFO command.
86 *
87 * The 2D SVGA commands have been around for a while, so they
88 * have a rather asymmetric structure. The SVGA3D protocol is
89 * more uniform: each command begins with a header containing the
90 * command number and the full size.
91 *
92 * This is a convenience wrapper around SVGA_FIFOReserve. We
93 * reserve space for the whole command, and write the header.
94 *
95 * This function must be paired with SVGA_FIFOCommitAll().
96 *
97 * Results:
98 * Returns a pointer to the space reserved for command-specific
99 * data. It must be 'cmdSize' bytes long.
100 *
101 * Side effects:
102 * Begins a FIFO reservation.
103 *
104 *----------------------------------------------------------------------
105 */
106
107 void *
108 SVGA3D_FIFOReserve(struct svga_winsys_context *swc,
109 uint32 cmd, // IN
110 uint32 cmdSize, // IN
111 uint32 nr_relocs) // IN
112 {
113 SVGA3dCmdHeader *header;
114
115 header = swc->reserve(swc, sizeof *header + cmdSize, nr_relocs);
116 if (!header)
117 return NULL;
118
119 header->id = cmd;
120 header->size = cmdSize;
121
122 swc->last_command = cmd;
123
124 return &header[1];
125 }
126
127
128 void
129 SVGA_FIFOCommitAll(struct svga_winsys_context *swc)
130 {
131 swc->commit(swc);
132 }
133
134
135 /*
136 *----------------------------------------------------------------------
137 *
138 * SVGA3D_DefineContext --
139 *
140 * Create a new context, to be referred to with the provided ID.
141 *
142 * Context objects encapsulate all render state, and shader
143 * objects are per-context.
144 *
145 * Surfaces are not per-context. The same surface can be shared
146 * between multiple contexts, and surface operations can occur
147 * without a context.
148 *
149 * If the provided context ID already existed, it is redefined.
150 *
151 * Context IDs are arbitrary small non-negative integers,
152 * global to the entire SVGA device.
153 *
154 * Results:
155 * None.
156 *
157 * Side effects:
158 * None.
159 *
160 *----------------------------------------------------------------------
161 */
162
163 enum pipe_error
164 SVGA3D_DefineContext(struct svga_winsys_context *swc) // IN
165 {
166 SVGA3dCmdDefineContext *cmd;
167
168 cmd = SVGA3D_FIFOReserve(swc,
169 SVGA_3D_CMD_CONTEXT_DEFINE, sizeof *cmd, 0);
170 if (!cmd)
171 return PIPE_ERROR_OUT_OF_MEMORY;
172
173 cmd->cid = swc->cid;
174
175 swc->commit(swc);
176
177 return PIPE_OK;
178 }
179
180
181 /*
182 *----------------------------------------------------------------------
183 *
184 * SVGA3D_DestroyContext --
185 *
186 * Delete a context created with SVGA3D_DefineContext.
187 *
188 * Results:
189 * None.
190 *
191 * Side effects:
192 * None.
193 *
194 *----------------------------------------------------------------------
195 */
196
197 enum pipe_error
198 SVGA3D_DestroyContext(struct svga_winsys_context *swc) // IN
199 {
200 SVGA3dCmdDestroyContext *cmd;
201
202 cmd = SVGA3D_FIFOReserve(swc,
203 SVGA_3D_CMD_CONTEXT_DESTROY, sizeof *cmd, 0);
204 if (!cmd)
205 return PIPE_ERROR_OUT_OF_MEMORY;
206
207 cmd->cid = swc->cid;
208
209 swc->commit(swc);
210
211 return PIPE_OK;
212 }
213
214
215 /*
216 *----------------------------------------------------------------------
217 *
218 * SVGA3D_BeginDefineSurface --
219 *
220 * Begin a SURFACE_DEFINE command. This reserves space for it in
221 * the FIFO, and returns pointers to the command's faces and
222 * mipsizes arrays.
223 *
224 * This function must be paired with SVGA_FIFOCommitAll().
225 * The faces and mipSizes arrays are initialized to zero.
226 *
227 * This creates a "surface" object in the SVGA3D device,
228 * with the provided surface ID (sid). Surfaces are generic
229 * containers for host VRAM objects like textures, vertex
230 * buffers, and depth/stencil buffers.
231 *
232 * Surfaces are hierarchical:
233 *
234 * - Surface may have multiple faces (for cube maps)
235 *
236 * - Each face has a list of mipmap levels
237 *
238 * - Each mipmap image may have multiple volume
239 * slices, if the image is three dimensional.
240 *
241 * - Each slice is a 2D array of 'blocks'
242 *
243 * - Each block may be one or more pixels.
244 * (Usually 1, more for DXT or YUV formats.)
245 *
246 * Surfaces are generic host VRAM objects. The SVGA3D device
247 * may optimize surfaces according to the format they were
248 * created with, but this format does not limit the ways in
249 * which the surface may be used. For example, a depth surface
250 * can be used as a texture, or a floating point image may
251 * be used as a vertex buffer. Some surface usages may be
252 * lower performance, due to software emulation, but any
253 * usage should work with any surface.
254 *
255 * If 'sid' is already defined, the old surface is deleted
256 * and this new surface replaces it.
257 *
258 * Surface IDs are arbitrary small non-negative integers,
259 * global to the entire SVGA device.
260 *
261 * Results:
262 * Returns pointers to arrays allocated in the FIFO for 'faces'
263 * and 'mipSizes'.
264 *
265 * Side effects:
266 * Begins a FIFO reservation.
267 *
268 *----------------------------------------------------------------------
269 */
270
271 enum pipe_error
272 SVGA3D_BeginDefineSurface(struct svga_winsys_context *swc,
273 struct svga_winsys_surface *sid, // IN
274 SVGA3dSurfaceFlags flags, // IN
275 SVGA3dSurfaceFormat format, // IN
276 SVGA3dSurfaceFace **faces, // OUT
277 SVGA3dSize **mipSizes, // OUT
278 uint32 numMipSizes) // IN
279 {
280 SVGA3dCmdDefineSurface *cmd;
281
282 cmd = SVGA3D_FIFOReserve(swc,
283 SVGA_3D_CMD_SURFACE_DEFINE, sizeof *cmd +
284 sizeof **mipSizes * numMipSizes, 1);
285 if (!cmd)
286 return PIPE_ERROR_OUT_OF_MEMORY;
287
288 swc->surface_relocation(swc, &cmd->sid, NULL, sid,
289 SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
290 cmd->surfaceFlags = flags;
291 cmd->format = format;
292
293 *faces = &cmd->face[0];
294 *mipSizes = (SVGA3dSize*) &cmd[1];
295
296 memset(*faces, 0, sizeof **faces * SVGA3D_MAX_SURFACE_FACES);
297 memset(*mipSizes, 0, sizeof **mipSizes * numMipSizes);
298
299 return PIPE_OK;
300 }
301
302
303 /*
304 *----------------------------------------------------------------------
305 *
306 * SVGA3D_DefineSurface2D --
307 *
308 * This is a simplified version of SVGA3D_BeginDefineSurface(),
309 * which does not support cube maps, mipmaps, or volume textures.
310 *
311 * Results:
312 * None.
313 *
314 * Side effects:
315 * None.
316 *
317 *----------------------------------------------------------------------
318 */
319
320 enum pipe_error
321 SVGA3D_DefineSurface2D(struct svga_winsys_context *swc, // IN
322 struct svga_winsys_surface *sid, // IN
323 uint32 width, // IN
324 uint32 height, // IN
325 SVGA3dSurfaceFormat format) // IN
326 {
327 SVGA3dSize *mipSizes;
328 SVGA3dSurfaceFace *faces;
329 enum pipe_error ret;
330
331 ret = SVGA3D_BeginDefineSurface(swc,
332 sid, 0, format, &faces, &mipSizes, 1);
333 if (ret != PIPE_OK)
334 return ret;
335
336 faces[0].numMipLevels = 1;
337
338 mipSizes[0].width = width;
339 mipSizes[0].height = height;
340 mipSizes[0].depth = 1;
341
342 swc->commit(swc);
343
344 return PIPE_OK;
345 }
346
347
348 /*
349 *----------------------------------------------------------------------
350 *
351 * SVGA3D_DestroySurface --
352 *
353 * Release the host VRAM encapsulated by a particular surface ID.
354 *
355 * Results:
356 * None.
357 *
358 * Side effects:
359 * None.
360 *
361 *----------------------------------------------------------------------
362 */
363
364 enum pipe_error
365 SVGA3D_DestroySurface(struct svga_winsys_context *swc,
366 struct svga_winsys_surface *sid) // IN
367 {
368 SVGA3dCmdDestroySurface *cmd;
369
370 cmd = SVGA3D_FIFOReserve(swc,
371 SVGA_3D_CMD_SURFACE_DESTROY, sizeof *cmd, 1);
372 if (!cmd)
373 return PIPE_ERROR_OUT_OF_MEMORY;
374
375 swc->surface_relocation(swc, &cmd->sid, NULL, sid,
376 SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
377 swc->commit(swc);
378
379 return PIPE_OK;
380 }
381
382
383 /*
384 *----------------------------------------------------------------------
385 *
386 * SVGA3D_SurfaceDMA--
387 *
388 * Emit a SURFACE_DMA command.
389 *
390 * When the SVGA3D device asynchronously processes this FIFO
391 * command, a DMA operation is performed between host VRAM and
392 * a generic SVGAGuestPtr. The guest pointer may refer to guest
393 * VRAM (provided by the SVGA PCI device) or to guest system
394 * memory that has been set up as a Guest Memory Region (GMR)
395 * by the SVGA device.
396 *
397 * The guest's DMA buffer must remain valid (not freed, paged out,
398 * or overwritten) until the host has finished processing this
399 * command. The guest can determine that the host has finished
400 * by using the SVGA device's FIFO Fence mechanism.
401 *
402 * The guest's image buffer can be an arbitrary size and shape.
403 * Guest image data is interpreted according to the SVGA3D surface
404 * format specified when the surface was defined.
405 *
406 * The caller may optionally define the guest image's pitch.
407 * guestImage->pitch can either be zero (assume image is tightly
408 * packed) or it must be the number of bytes between vertically
409 * adjacent image blocks.
410 *
411 * The provided copybox list specifies which regions of the source
412 * image are to be copied, and where they appear on the destination.
413 *
414 * NOTE: srcx/srcy are always on the guest image and x/y are
415 * always on the host image, regardless of the actual transfer
416 * direction!
417 *
418 * For efficiency, the SVGA3D device is free to copy more data
419 * than specified. For example, it may round copy boxes outwards
420 * such that they lie on particular alignment boundaries.
421 *
422 *----------------------------------------------------------------------
423 */
424
425 enum pipe_error
426 SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
427 struct svga_transfer *st, // IN
428 SVGA3dTransferType transfer, // IN
429 const SVGA3dCopyBox *boxes, // IN
430 uint32 numBoxes, // IN
431 SVGA3dSurfaceDMAFlags flags) // IN
432 {
433 struct svga_texture *texture = svga_texture(st->base.resource);
434 SVGA3dCmdSurfaceDMA *cmd;
435 SVGA3dCmdSurfaceDMASuffix *pSuffix;
436 uint32 boxesSize = sizeof *boxes * numBoxes;
437 unsigned region_flags;
438 unsigned surface_flags;
439
440 if (transfer == SVGA3D_WRITE_HOST_VRAM) {
441 region_flags = SVGA_RELOC_READ;
442 surface_flags = SVGA_RELOC_WRITE;
443 }
444 else if (transfer == SVGA3D_READ_HOST_VRAM) {
445 region_flags = SVGA_RELOC_WRITE;
446 surface_flags = SVGA_RELOC_READ;
447 }
448 else {
449 assert(0);
450 return PIPE_ERROR_BAD_INPUT;
451 }
452
453 cmd = SVGA3D_FIFOReserve(swc,
454 SVGA_3D_CMD_SURFACE_DMA,
455 sizeof *cmd + boxesSize + sizeof *pSuffix,
456 2);
457 if (!cmd)
458 return PIPE_ERROR_OUT_OF_MEMORY;
459
460 swc->region_relocation(swc, &cmd->guest.ptr, st->hwbuf, 0, region_flags);
461 cmd->guest.pitch = st->base.stride;
462
463 swc->surface_relocation(swc, &cmd->host.sid, NULL,
464 texture->handle, surface_flags);
465 cmd->host.face = st->slice; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
466 cmd->host.mipmap = st->base.level;
467
468 cmd->transfer = transfer;
469
470 memcpy(&cmd[1], boxes, boxesSize);
471
472 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize);
473 pSuffix->suffixSize = sizeof *pSuffix;
474 pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride;
475 pSuffix->flags = flags;
476
477 swc->commit(swc);
478 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
479
480 return PIPE_OK;
481 }
482
483
484 enum pipe_error
485 SVGA3D_BufferDMA(struct svga_winsys_context *swc,
486 struct svga_winsys_buffer *guest,
487 struct svga_winsys_surface *host,
488 SVGA3dTransferType transfer, // IN
489 uint32 size, // IN
490 uint32 guest_offset, // IN
491 uint32 host_offset, // IN
492 SVGA3dSurfaceDMAFlags flags) // IN
493 {
494 SVGA3dCmdSurfaceDMA *cmd;
495 SVGA3dCopyBox *box;
496 SVGA3dCmdSurfaceDMASuffix *pSuffix;
497 unsigned region_flags;
498 unsigned surface_flags;
499
500 assert(!swc->have_gb_objects);
501
502 if (transfer == SVGA3D_WRITE_HOST_VRAM) {
503 region_flags = SVGA_RELOC_READ;
504 surface_flags = SVGA_RELOC_WRITE;
505 }
506 else if (transfer == SVGA3D_READ_HOST_VRAM) {
507 region_flags = SVGA_RELOC_WRITE;
508 surface_flags = SVGA_RELOC_READ;
509 }
510 else {
511 assert(0);
512 return PIPE_ERROR_BAD_INPUT;
513 }
514
515 cmd = SVGA3D_FIFOReserve(swc,
516 SVGA_3D_CMD_SURFACE_DMA,
517 sizeof *cmd + sizeof *box + sizeof *pSuffix,
518 2);
519 if (!cmd)
520 return PIPE_ERROR_OUT_OF_MEMORY;
521
522 swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
523 cmd->guest.pitch = 0;
524
525 swc->surface_relocation(swc, &cmd->host.sid,
526 NULL, host, surface_flags);
527 cmd->host.face = 0;
528 cmd->host.mipmap = 0;
529
530 cmd->transfer = transfer;
531
532 box = (SVGA3dCopyBox *)&cmd[1];
533 box->x = host_offset;
534 box->y = 0;
535 box->z = 0;
536 box->w = size;
537 box->h = 1;
538 box->d = 1;
539 box->srcx = guest_offset;
540 box->srcy = 0;
541 box->srcz = 0;
542
543 pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box);
544 pSuffix->suffixSize = sizeof *pSuffix;
545 pSuffix->maximumOffset = guest_offset + size;
546 pSuffix->flags = flags;
547
548 swc->commit(swc);
549 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
550
551 return PIPE_OK;
552 }
553
554
555 /*
556 *----------------------------------------------------------------------
557 *
558 * SVGA3D_SetRenderTarget --
559 *
560 * Bind a surface object to a particular render target attachment
561 * point on the current context. Render target attachment points
562 * exist for color buffers, a depth buffer, and a stencil buffer.
563 *
564 * The SVGA3D device is quite lenient about the types of surfaces
565 * that may be used as render targets. The color buffers must
566 * all be the same size, but the depth and stencil buffers do not
567 * have to be the same size as the color buffer. All attachments
568 * are optional.
569 *
570 * Some combinations of render target formats may require software
571 * emulation, depending on the capabilities of the host graphics
572 * API and graphics hardware.
573 *
574 * Results:
575 * None.
576 *
577 * Side effects:
578 * None.
579 *
580 *----------------------------------------------------------------------
581 */
582
583 enum pipe_error
584 SVGA3D_SetRenderTarget(struct svga_winsys_context *swc,
585 SVGA3dRenderTargetType type, // IN
586 struct pipe_surface *surface) // IN
587 {
588 SVGA3dCmdSetRenderTarget *cmd;
589
590 cmd = SVGA3D_FIFOReserve(swc,
591 SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd, 1);
592 if (!cmd)
593 return PIPE_ERROR_OUT_OF_MEMORY;
594
595 cmd->cid = swc->cid;
596 cmd->type = type;
597 surface_to_surfaceid(swc, surface, &cmd->target, SVGA_RELOC_WRITE);
598 swc->commit(swc);
599
600 return PIPE_OK;
601 }
602
603
604 /*
605 *----------------------------------------------------------------------
606 *
607 * SVGA3D_DefineShader --
608 *
609 * Upload the bytecode for a new shader. The bytecode is "SVGA3D
610 * format", which is theoretically a binary-compatible superset
611 * of Microsoft's DirectX shader bytecode. In practice, the
612 * SVGA3D bytecode doesn't yet have any extensions to DirectX's
613 * bytecode format.
614 *
615 * The SVGA3D device supports shader models 1.1 through 2.0.
616 *
617 * The caller chooses a shader ID (small positive integer) by
618 * which this shader will be identified in future commands. This
619 * ID is in a namespace which is per-context and per-shader-type.
620 *
621 * 'bytecodeLen' is specified in bytes. It must be a multiple of 4.
622 *
623 * Results:
624 * None.
625 *
626 * Side effects:
627 * None.
628 *
629 *----------------------------------------------------------------------
630 */
631
632 enum pipe_error
633 SVGA3D_DefineShader(struct svga_winsys_context *swc,
634 uint32 shid, // IN
635 SVGA3dShaderType type, // IN
636 const uint32 *bytecode, // IN
637 uint32 bytecodeLen) // IN
638 {
639 SVGA3dCmdDefineShader *cmd;
640
641 assert(bytecodeLen % 4 == 0);
642
643 cmd = SVGA3D_FIFOReserve(swc,
644 SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen,
645 0);
646 if (!cmd)
647 return PIPE_ERROR_OUT_OF_MEMORY;
648
649 cmd->cid = swc->cid;
650 cmd->shid = shid;
651 cmd->type = type;
652 memcpy(&cmd[1], bytecode, bytecodeLen);
653 swc->commit(swc);
654
655 return PIPE_OK;
656 }
657
658
659 /*
660 *----------------------------------------------------------------------
661 *
662 * SVGA3D_DestroyShader --
663 *
664 * Delete a shader that was created by SVGA3D_DefineShader. If
665 * the shader was the current vertex or pixel shader for its
666 * context, rendering results are undefined until a new shader is
667 * bound.
668 *
669 * Results:
670 * None.
671 *
672 * Side effects:
673 * None.
674 *
675 *----------------------------------------------------------------------
676 */
677
678 enum pipe_error
679 SVGA3D_DestroyShader(struct svga_winsys_context *swc,
680 uint32 shid, // IN
681 SVGA3dShaderType type) // IN
682 {
683 SVGA3dCmdDestroyShader *cmd;
684
685 cmd = SVGA3D_FIFOReserve(swc,
686 SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd,
687 0);
688 if (!cmd)
689 return PIPE_ERROR_OUT_OF_MEMORY;
690
691 cmd->cid = swc->cid;
692 cmd->shid = shid;
693 cmd->type = type;
694 swc->commit(swc);
695
696 return PIPE_OK;
697 }
698
699
700 /*
701 *----------------------------------------------------------------------
702 *
703 * SVGA3D_SetShaderConst --
704 *
705 * Set the value of a shader constant.
706 *
707 * Shader constants are analogous to uniform variables in GLSL,
708 * except that they belong to the render context rather than to
709 * an individual shader.
710 *
711 * Constants may have one of three types: A 4-vector of floats,
712 * a 4-vector of integers, or a single boolean flag.
713 *
714 * Results:
715 * None.
716 *
717 * Side effects:
718 * None.
719 *
720 *----------------------------------------------------------------------
721 */
722
723 enum pipe_error
724 SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
725 uint32 reg, // IN
726 SVGA3dShaderType type, // IN
727 SVGA3dShaderConstType ctype, // IN
728 const void *value) // IN
729 {
730 SVGA3dCmdSetShaderConst *cmd;
731
732 cmd = SVGA3D_FIFOReserve(swc,
733 SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd,
734 0);
735 if (!cmd)
736 return PIPE_ERROR_OUT_OF_MEMORY;
737
738 cmd->cid = swc->cid;
739 cmd->reg = reg;
740 cmd->type = type;
741 cmd->ctype = ctype;
742
743 switch (ctype) {
744
745 case SVGA3D_CONST_TYPE_FLOAT:
746 case SVGA3D_CONST_TYPE_INT:
747 memcpy(&cmd->values, value, sizeof cmd->values);
748 break;
749
750 case SVGA3D_CONST_TYPE_BOOL:
751 memset(&cmd->values, 0, sizeof cmd->values);
752 cmd->values[0] = *(uint32*)value;
753 break;
754
755 default:
756 assert(0);
757 break;
758
759 }
760 swc->commit(swc);
761
762 return PIPE_OK;
763 }
764
765
766 /*
767 *----------------------------------------------------------------------
768 *
769 * SVGA3D_SetShaderConsts --
770 *
771 * Set the value of successive shader constants.
772 *
773 * Shader constants are analogous to uniform variables in GLSL,
774 * except that they belong to the render context rather than to
775 * an individual shader.
776 *
777 * Constants may have one of three types: A 4-vector of floats,
778 * a 4-vector of integers, or a single boolean flag.
779 *
780 * Results:
781 * None.
782 *
783 * Side effects:
784 * None.
785 *
786 *----------------------------------------------------------------------
787 */
788
789 enum pipe_error
790 SVGA3D_SetShaderConsts(struct svga_winsys_context *swc,
791 uint32 reg, // IN
792 uint32 numRegs, // IN
793 SVGA3dShaderType type, // IN
794 SVGA3dShaderConstType ctype, // IN
795 const void *values) // IN
796 {
797 SVGA3dCmdSetShaderConst *cmd;
798
799 cmd = SVGA3D_FIFOReserve(swc,
800 SVGA_3D_CMD_SET_SHADER_CONST,
801 sizeof *cmd + (numRegs - 1) * sizeof cmd->values,
802 0);
803 if (!cmd)
804 return PIPE_ERROR_OUT_OF_MEMORY;
805
806 cmd->cid = swc->cid;
807 cmd->reg = reg;
808 cmd->type = type;
809 cmd->ctype = ctype;
810
811 memcpy(&cmd->values, values, numRegs * sizeof cmd->values);
812
813 swc->commit(swc);
814
815 return PIPE_OK;
816 }
817
818
819
820
821
822 /*
823 *----------------------------------------------------------------------
824 *
825 * SVGA3D_SetShader --
826 *
827 * Switch active shaders. This binds a new vertex or pixel shader
828 * to the specified context.
829 *
830 * A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
831 * back to the fixed function vertex or pixel pipeline.
832 *
833 * Results:
834 * None.
835 *
836 * Side effects:
837 * None.
838 *
839 *----------------------------------------------------------------------
840 */
841
842 enum pipe_error
843 SVGA3D_SetShader(struct svga_winsys_context *swc,
844 SVGA3dShaderType type, // IN
845 uint32 shid) // IN
846 {
847 SVGA3dCmdSetShader *cmd;
848
849 assert(type == SVGA3D_SHADERTYPE_VS || type == SVGA3D_SHADERTYPE_PS);
850
851 cmd = SVGA3D_FIFOReserve(swc,
852 SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
853 0);
854 if (!cmd)
855 return PIPE_ERROR_OUT_OF_MEMORY;
856
857 cmd->cid = swc->cid;
858 cmd->type = type;
859 cmd->shid = shid;
860 swc->commit(swc);
861
862 return PIPE_OK;
863 }
864
865
866 /*
867 *----------------------------------------------------------------------
868 *
869 * SVGA3D_BeginClear --
870 *
871 * Begin a CLEAR command. This reserves space for it in the FIFO,
872 * and returns a pointer to the command's rectangle array. This
873 * function must be paired with SVGA_FIFOCommitAll().
874 *
875 * Clear is a rendering operation which fills a list of
876 * rectangles with constant values on all render target types
877 * indicated by 'flags'.
878 *
879 * Clear is not affected by clipping, depth test, or other
880 * render state which affects the fragment pipeline.
881 *
882 * Results:
883 * None.
884 *
885 * Side effects:
886 * May write to attached render target surfaces.
887 *
888 *----------------------------------------------------------------------
889 */
890
891 enum pipe_error
892 SVGA3D_BeginClear(struct svga_winsys_context *swc,
893 SVGA3dClearFlag flags, // IN
894 uint32 color, // IN
895 float depth, // IN
896 uint32 stencil, // IN
897 SVGA3dRect **rects, // OUT
898 uint32 numRects) // IN
899 {
900 SVGA3dCmdClear *cmd;
901
902 cmd = SVGA3D_FIFOReserve(swc,
903 SVGA_3D_CMD_CLEAR,
904 sizeof *cmd + sizeof **rects * numRects,
905 0);
906 if (!cmd)
907 return PIPE_ERROR_OUT_OF_MEMORY;
908
909 cmd->cid = swc->cid;
910 cmd->clearFlag = flags;
911 cmd->color = color;
912 cmd->depth = depth;
913 cmd->stencil = stencil;
914 *rects = (SVGA3dRect*) &cmd[1];
915
916 return PIPE_OK;
917 }
918
919
920 /*
921 *----------------------------------------------------------------------
922 *
923 * SVGA3D_ClearRect --
924 *
925 * This is a simplified version of SVGA3D_BeginClear().
926 *
927 * Results:
928 * None.
929 *
930 * Side effects:
931 * None.
932 *
933 *----------------------------------------------------------------------
934 */
935
936 enum pipe_error
937 SVGA3D_ClearRect(struct svga_winsys_context *swc,
938 SVGA3dClearFlag flags, // IN
939 uint32 color, // IN
940 float depth, // IN
941 uint32 stencil, // IN
942 uint32 x, // IN
943 uint32 y, // IN
944 uint32 w, // IN
945 uint32 h) // IN
946 {
947 SVGA3dRect *rect;
948 enum pipe_error ret;
949
950 ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
951 if (ret != PIPE_OK)
952 return PIPE_ERROR_OUT_OF_MEMORY;
953
954 memset(rect, 0, sizeof *rect);
955 rect->x = x;
956 rect->y = y;
957 rect->w = w;
958 rect->h = h;
959 swc->commit(swc);
960
961 return PIPE_OK;
962 }
963
964
965 /*
966 *----------------------------------------------------------------------
967 *
968 * SVGA3D_BeginDrawPrimitives --
969 *
970 * Begin a DRAW_PRIMITIVES command. This reserves space for it in
971 * the FIFO, and returns a pointer to the command's arrays.
972 * This function must be paired with SVGA_FIFOCommitAll().
973 *
974 * Drawing commands consist of two variable-length arrays:
975 * SVGA3dVertexDecl elements declare a set of vertex buffers to
976 * use while rendering, and SVGA3dPrimitiveRange elements specify
977 * groups of primitives each with an optional index buffer.
978 *
979 * The decls and ranges arrays are initialized to zero.
980 *
981 * Results:
982 * None.
983 *
984 * Side effects:
985 * May write to attached render target surfaces.
986 *
987 *----------------------------------------------------------------------
988 */
989
990 enum pipe_error
991 SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
992 SVGA3dVertexDecl **decls, // OUT
993 uint32 numVertexDecls, // IN
994 SVGA3dPrimitiveRange **ranges, // OUT
995 uint32 numRanges) // IN
996 {
997 SVGA3dCmdDrawPrimitives *cmd;
998 SVGA3dVertexDecl *declArray;
999 SVGA3dPrimitiveRange *rangeArray;
1000 uint32 declSize = sizeof **decls * numVertexDecls;
1001 uint32 rangeSize = sizeof **ranges * numRanges;
1002
1003 cmd = SVGA3D_FIFOReserve(swc,
1004 SVGA_3D_CMD_DRAW_PRIMITIVES,
1005 sizeof *cmd + declSize + rangeSize,
1006 numVertexDecls + numRanges);
1007 if (!cmd)
1008 return PIPE_ERROR_OUT_OF_MEMORY;
1009
1010 cmd->cid = swc->cid;
1011 cmd->numVertexDecls = numVertexDecls;
1012 cmd->numRanges = numRanges;
1013
1014 declArray = (SVGA3dVertexDecl*) &cmd[1];
1015 rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
1016
1017 memset(declArray, 0, declSize);
1018 memset(rangeArray, 0, rangeSize);
1019
1020 *decls = declArray;
1021 *ranges = rangeArray;
1022
1023 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1024
1025 return PIPE_OK;
1026 }
1027
1028
1029 /*
1030 *----------------------------------------------------------------------
1031 *
1032 * SVGA3D_BeginSurfaceCopy --
1033 *
1034 * Begin a SURFACE_COPY command. This reserves space for it in
1035 * the FIFO, and returns a pointer to the command's arrays. This
1036 * function must be paired with SVGA_FIFOCommitAll().
1037 *
1038 * The box array is initialized with zeroes.
1039 *
1040 * Results:
1041 * None.
1042 *
1043 * Side effects:
1044 * Asynchronously copies a list of boxes from surface to surface.
1045 *
1046 *----------------------------------------------------------------------
1047 */
1048
1049 enum pipe_error
1050 SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
1051 struct pipe_surface *src, // IN
1052 struct pipe_surface *dest, // IN
1053 SVGA3dCopyBox **boxes, // OUT
1054 uint32 numBoxes) // IN
1055 {
1056 SVGA3dCmdSurfaceCopy *cmd;
1057 uint32 boxesSize = sizeof **boxes * numBoxes;
1058
1059 cmd = SVGA3D_FIFOReserve(swc,
1060 SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
1061 2);
1062 if (!cmd)
1063 return PIPE_ERROR_OUT_OF_MEMORY;
1064
1065 surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1066 surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1067 *boxes = (SVGA3dCopyBox*) &cmd[1];
1068
1069 memset(*boxes, 0, boxesSize);
1070
1071 return PIPE_OK;
1072 }
1073
1074
1075 /*
1076 *----------------------------------------------------------------------
1077 *
1078 * SVGA3D_SurfaceStretchBlt --
1079 *
1080 * Issue a SURFACE_STRETCHBLT command: an asynchronous
1081 * surface-to-surface blit, with scaling.
1082 *
1083 * Results:
1084 * None.
1085 *
1086 * Side effects:
1087 * Asynchronously copies one box from surface to surface.
1088 *
1089 *----------------------------------------------------------------------
1090 */
1091
1092 enum pipe_error
1093 SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
1094 struct pipe_surface *src, // IN
1095 struct pipe_surface *dest, // IN
1096 SVGA3dBox *boxSrc, // IN
1097 SVGA3dBox *boxDest, // IN
1098 SVGA3dStretchBltMode mode) // IN
1099 {
1100 SVGA3dCmdSurfaceStretchBlt *cmd;
1101
1102 cmd = SVGA3D_FIFOReserve(swc,
1103 SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
1104 2);
1105 if (!cmd)
1106 return PIPE_ERROR_OUT_OF_MEMORY;
1107
1108 surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1109 surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1110 cmd->boxSrc = *boxSrc;
1111 cmd->boxDest = *boxDest;
1112 cmd->mode = mode;
1113 swc->commit(swc);
1114
1115 return PIPE_OK;
1116 }
1117
1118
1119 /*
1120 *----------------------------------------------------------------------
1121 *
1122 * SVGA3D_SetViewport --
1123 *
1124 * Set the current context's viewport rectangle. The viewport
1125 * is clipped to the dimensions of the current render target,
1126 * then all rendering is clipped to the viewport.
1127 *
1128 * Results:
1129 * None.
1130 *
1131 * Side effects:
1132 * None.
1133 *
1134 *----------------------------------------------------------------------
1135 */
1136
1137 enum pipe_error
1138 SVGA3D_SetViewport(struct svga_winsys_context *swc,
1139 SVGA3dRect *rect) // IN
1140 {
1141 SVGA3dCmdSetViewport *cmd;
1142
1143 cmd = SVGA3D_FIFOReserve(swc,
1144 SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
1145 0);
1146 if (!cmd)
1147 return PIPE_ERROR_OUT_OF_MEMORY;
1148
1149 cmd->cid = swc->cid;
1150 cmd->rect = *rect;
1151 swc->commit(swc);
1152
1153 return PIPE_OK;
1154 }
1155
1156
1157
1158
1159 /*
1160 *----------------------------------------------------------------------
1161 *
1162 * SVGA3D_SetScissorRect --
1163 *
1164 * Set the current context's scissor rectangle. If scissoring
1165 * is enabled then all rendering is clipped to the scissor bounds.
1166 *
1167 * Results:
1168 * None.
1169 *
1170 * Side effects:
1171 * None.
1172 *
1173 *----------------------------------------------------------------------
1174 */
1175
1176 enum pipe_error
1177 SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
1178 SVGA3dRect *rect) // IN
1179 {
1180 SVGA3dCmdSetScissorRect *cmd;
1181
1182 cmd = SVGA3D_FIFOReserve(swc,
1183 SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
1184 0);
1185 if (!cmd)
1186 return PIPE_ERROR_OUT_OF_MEMORY;
1187
1188 cmd->cid = swc->cid;
1189 cmd->rect = *rect;
1190 swc->commit(swc);
1191
1192 return PIPE_OK;
1193 }
1194
1195 /*
1196 *----------------------------------------------------------------------
1197 *
1198 * SVGA3D_SetClipPlane --
1199 *
1200 * Set one of the current context's clip planes. If the clip
1201 * plane is enabled then all 3d rendering is clipped against
1202 * the plane.
1203 *
1204 * Results:
1205 * None.
1206 *
1207 * Side effects:
1208 * None.
1209 *
1210 *----------------------------------------------------------------------
1211 */
1212
1213 enum pipe_error
1214 SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
1215 uint32 index, const float *plane)
1216 {
1217 SVGA3dCmdSetClipPlane *cmd;
1218
1219 cmd = SVGA3D_FIFOReserve(swc,
1220 SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
1221 0);
1222 if (!cmd)
1223 return PIPE_ERROR_OUT_OF_MEMORY;
1224
1225 cmd->cid = swc->cid;
1226 cmd->index = index;
1227 cmd->plane[0] = plane[0];
1228 cmd->plane[1] = plane[1];
1229 cmd->plane[2] = plane[2];
1230 cmd->plane[3] = plane[3];
1231 swc->commit(swc);
1232
1233 return PIPE_OK;
1234 }
1235
1236 /*
1237 *----------------------------------------------------------------------
1238 *
1239 * SVGA3D_SetZRange --
1240 *
1241 * Set the range of the depth buffer to use. 'min' and 'max'
1242 * are values between 0.0 and 1.0.
1243 *
1244 * Results:
1245 * None.
1246 *
1247 * Side effects:
1248 * None.
1249 *
1250 *----------------------------------------------------------------------
1251 */
1252
1253 enum pipe_error
1254 SVGA3D_SetZRange(struct svga_winsys_context *swc,
1255 float zMin, // IN
1256 float zMax) // IN
1257 {
1258 SVGA3dCmdSetZRange *cmd;
1259
1260 cmd = SVGA3D_FIFOReserve(swc,
1261 SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
1262 0);
1263 if (!cmd)
1264 return PIPE_ERROR_OUT_OF_MEMORY;
1265
1266 cmd->cid = swc->cid;
1267 cmd->zRange.min = zMin;
1268 cmd->zRange.max = zMax;
1269 swc->commit(swc);
1270
1271 return PIPE_OK;
1272 }
1273
1274
1275 /*
1276 *----------------------------------------------------------------------
1277 *
1278 * SVGA3D_BeginSetTextureState --
1279 *
1280 * Begin a SETTEXTURESTATE command. This reserves space for it in
1281 * the FIFO, and returns a pointer to the command's texture state
1282 * array. This function must be paired with SVGA_FIFOCommitAll().
1283 *
1284 * This command sets rendering state which is per-texture-unit.
1285 *
1286 * XXX: Individual texture states need documentation. However,
1287 * they are very similar to the texture states defined by
1288 * Direct3D. The D3D documentation is a good starting point
1289 * for understanding SVGA3D texture states.
1290 *
1291 * Results:
1292 * None.
1293 *
1294 * Side effects:
1295 * None.
1296 *
1297 *----------------------------------------------------------------------
1298 */
1299
1300 enum pipe_error
1301 SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
1302 SVGA3dTextureState **states, // OUT
1303 uint32 numStates) // IN
1304 {
1305 SVGA3dCmdSetTextureState *cmd;
1306
1307 cmd = SVGA3D_FIFOReserve(swc,
1308 SVGA_3D_CMD_SETTEXTURESTATE,
1309 sizeof *cmd + sizeof **states * numStates,
1310 numStates);
1311 if (!cmd)
1312 return PIPE_ERROR_OUT_OF_MEMORY;
1313
1314 cmd->cid = swc->cid;
1315 *states = (SVGA3dTextureState*) &cmd[1];
1316
1317 return PIPE_OK;
1318 }
1319
1320
1321 /*
1322 *----------------------------------------------------------------------
1323 *
1324 * SVGA3D_BeginSetRenderState --
1325 *
1326 * Begin a SETRENDERSTATE command. This reserves space for it in
1327 * the FIFO, and returns a pointer to the command's texture state
1328 * array. This function must be paired with SVGA_FIFOCommitAll().
1329 *
1330 * This command sets rendering state which is global to the context.
1331 *
1332 * XXX: Individual render states need documentation. However,
1333 * they are very similar to the render states defined by
1334 * Direct3D. The D3D documentation is a good starting point
1335 * for understanding SVGA3D render states.
1336 *
1337 * Results:
1338 * None.
1339 *
1340 * Side effects:
1341 * None.
1342 *
1343 *----------------------------------------------------------------------
1344 */
1345
1346 enum pipe_error
1347 SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
1348 SVGA3dRenderState **states, // OUT
1349 uint32 numStates) // IN
1350 {
1351 SVGA3dCmdSetRenderState *cmd;
1352
1353 cmd = SVGA3D_FIFOReserve(swc,
1354 SVGA_3D_CMD_SETRENDERSTATE,
1355 sizeof *cmd + sizeof **states * numStates,
1356 0);
1357 if (!cmd)
1358 return PIPE_ERROR_OUT_OF_MEMORY;
1359
1360 cmd->cid = swc->cid;
1361 *states = (SVGA3dRenderState*) &cmd[1];
1362
1363 return PIPE_OK;
1364 }
1365
1366
1367 /*
1368 *----------------------------------------------------------------------
1369 *
1370 * SVGA3D_BeginGBQuery--
1371 *
1372 * GB resource version of SVGA3D_BeginQuery.
1373 *
1374 * Results:
1375 * None.
1376 *
1377 * Side effects:
1378 * Commits space in the FIFO memory.
1379 *
1380 *----------------------------------------------------------------------
1381 */
1382
1383 static enum pipe_error
1384 SVGA3D_BeginGBQuery(struct svga_winsys_context *swc,
1385 SVGA3dQueryType type) // IN
1386 {
1387 SVGA3dCmdBeginGBQuery *cmd;
1388
1389 cmd = SVGA3D_FIFOReserve(swc,
1390 SVGA_3D_CMD_BEGIN_GB_QUERY,
1391 sizeof *cmd,
1392 1);
1393 if (!cmd)
1394 return PIPE_ERROR_OUT_OF_MEMORY;
1395
1396 cmd->cid = swc->cid;
1397 cmd->type = type;
1398
1399 swc->commit(swc);
1400
1401 return PIPE_OK;
1402 }
1403
1404
1405 /*
1406 *----------------------------------------------------------------------
1407 *
1408 * SVGA3D_BeginQuery--
1409 *
1410 * Issues a SVGA_3D_CMD_BEGIN_QUERY command.
1411 *
1412 * Results:
1413 * None.
1414 *
1415 * Side effects:
1416 * Commits space in the FIFO memory.
1417 *
1418 *----------------------------------------------------------------------
1419 */
1420
1421 enum pipe_error
1422 SVGA3D_BeginQuery(struct svga_winsys_context *swc,
1423 SVGA3dQueryType type) // IN
1424 {
1425 SVGA3dCmdBeginQuery *cmd;
1426
1427 if (swc->have_gb_objects)
1428 return SVGA3D_BeginGBQuery(swc, type);
1429
1430 cmd = SVGA3D_FIFOReserve(swc,
1431 SVGA_3D_CMD_BEGIN_QUERY,
1432 sizeof *cmd,
1433 0);
1434 if (!cmd)
1435 return PIPE_ERROR_OUT_OF_MEMORY;
1436
1437 cmd->cid = swc->cid;
1438 cmd->type = type;
1439
1440 swc->commit(swc);
1441
1442 return PIPE_OK;
1443 }
1444
1445
1446 /*
1447 *----------------------------------------------------------------------
1448 *
1449 * SVGA3D_EndGBQuery--
1450 *
1451 * GB resource version of SVGA3D_EndQuery.
1452 *
1453 * Results:
1454 * None.
1455 *
1456 * Side effects:
1457 * Commits space in the FIFO memory.
1458 *
1459 *----------------------------------------------------------------------
1460 */
1461
1462 static enum pipe_error
1463 SVGA3D_EndGBQuery(struct svga_winsys_context *swc,
1464 SVGA3dQueryType type, // IN
1465 struct svga_winsys_buffer *buffer) // IN/OUT
1466 {
1467 SVGA3dCmdEndGBQuery *cmd;
1468
1469 cmd = SVGA3D_FIFOReserve(swc,
1470 SVGA_3D_CMD_END_GB_QUERY,
1471 sizeof *cmd,
1472 2);
1473 if (!cmd)
1474 return PIPE_ERROR_OUT_OF_MEMORY;
1475
1476 cmd->cid = swc->cid;
1477 cmd->type = type;
1478
1479 swc->mob_relocation(swc, &cmd->mobid, &cmd->offset, buffer,
1480 0, SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1481
1482 swc->commit(swc);
1483
1484 return PIPE_OK;
1485 }
1486
1487
1488 /*
1489 *----------------------------------------------------------------------
1490 *
1491 * SVGA3D_EndQuery--
1492 *
1493 * Issues a SVGA_3D_CMD_END_QUERY command.
1494 *
1495 * Results:
1496 * None.
1497 *
1498 * Side effects:
1499 * Commits space in the FIFO memory.
1500 *
1501 *----------------------------------------------------------------------
1502 */
1503
1504 enum pipe_error
1505 SVGA3D_EndQuery(struct svga_winsys_context *swc,
1506 SVGA3dQueryType type, // IN
1507 struct svga_winsys_buffer *buffer) // IN/OUT
1508 {
1509 SVGA3dCmdEndQuery *cmd;
1510
1511 if (swc->have_gb_objects)
1512 return SVGA3D_EndGBQuery(swc, type, buffer);
1513
1514 cmd = SVGA3D_FIFOReserve(swc,
1515 SVGA_3D_CMD_END_QUERY,
1516 sizeof *cmd,
1517 1);
1518 if (!cmd)
1519 return PIPE_ERROR_OUT_OF_MEMORY;
1520
1521 cmd->cid = swc->cid;
1522 cmd->type = type;
1523
1524 swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1525 SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1526
1527 swc->commit(swc);
1528
1529 return PIPE_OK;
1530 }
1531
1532
1533 /*
1534 *----------------------------------------------------------------------
1535 *
1536 * SVGA3D_WaitForGBQuery--
1537 *
1538 * GB resource version of SVGA3D_WaitForQuery.
1539 *
1540 * Results:
1541 * None.
1542 *
1543 * Side effects:
1544 * Commits space in the FIFO memory.
1545 *
1546 *----------------------------------------------------------------------
1547 */
1548
1549 static enum pipe_error
1550 SVGA3D_WaitForGBQuery(struct svga_winsys_context *swc,
1551 SVGA3dQueryType type, // IN
1552 struct svga_winsys_buffer *buffer) // IN/OUT
1553 {
1554 SVGA3dCmdWaitForGBQuery *cmd;
1555
1556 cmd = SVGA3D_FIFOReserve(swc,
1557 SVGA_3D_CMD_WAIT_FOR_GB_QUERY,
1558 sizeof *cmd,
1559 2);
1560 if (!cmd)
1561 return PIPE_ERROR_OUT_OF_MEMORY;
1562
1563 cmd->cid = swc->cid;
1564 cmd->type = type;
1565
1566 swc->mob_relocation(swc, &cmd->mobid, &cmd->offset, buffer,
1567 0, SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1568
1569 swc->commit(swc);
1570
1571 return PIPE_OK;
1572 }
1573
1574
1575 /*
1576 *----------------------------------------------------------------------
1577 *
1578 * SVGA3D_WaitForQuery--
1579 *
1580 * Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command. This reserves space
1581 * for it in the FIFO. This doesn't actually wait for the query to
1582 * finish but instead tells the host to start a wait at the driver
1583 * level. The caller can wait on the status variable in the
1584 * guestPtr memory or send an insert fence instruction after this
1585 * command and wait on the fence.
1586 *
1587 * Results:
1588 * None.
1589 *
1590 * Side effects:
1591 * Commits space in the FIFO memory.
1592 *
1593 *----------------------------------------------------------------------
1594 */
1595
1596 enum pipe_error
1597 SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
1598 SVGA3dQueryType type, // IN
1599 struct svga_winsys_buffer *buffer) // IN/OUT
1600 {
1601 SVGA3dCmdWaitForQuery *cmd;
1602
1603 if (swc->have_gb_objects)
1604 return SVGA3D_WaitForGBQuery(swc, type, buffer);
1605
1606 cmd = SVGA3D_FIFOReserve(swc,
1607 SVGA_3D_CMD_WAIT_FOR_QUERY,
1608 sizeof *cmd,
1609 1);
1610 if (!cmd)
1611 return PIPE_ERROR_OUT_OF_MEMORY;
1612
1613 cmd->cid = swc->cid;
1614 cmd->type = type;
1615
1616 swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1617 SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1618
1619 swc->commit(swc);
1620
1621 return PIPE_OK;
1622 }
1623
1624
1625 enum pipe_error
1626 SVGA3D_BindGBShader(struct svga_winsys_context *swc,
1627 struct svga_winsys_gb_shader *gbshader)
1628 {
1629 SVGA3dCmdBindGBShader *cmd =
1630 SVGA3D_FIFOReserve(swc,
1631 SVGA_3D_CMD_BIND_GB_SHADER,
1632 sizeof *cmd,
1633 2); /* two relocations */
1634
1635 if (!cmd)
1636 return PIPE_ERROR_OUT_OF_MEMORY;
1637
1638 swc->shader_relocation(swc, &cmd->shid, &cmd->mobid,
1639 &cmd->offsetInBytes, gbshader, 0);
1640
1641 swc->commit(swc);
1642
1643 return PIPE_OK;
1644 }
1645
1646
1647 enum pipe_error
1648 SVGA3D_SetGBShader(struct svga_winsys_context *swc,
1649 SVGA3dShaderType type, // IN
1650 struct svga_winsys_gb_shader *gbshader)
1651 {
1652 SVGA3dCmdSetShader *cmd;
1653
1654 assert(type == SVGA3D_SHADERTYPE_VS || type == SVGA3D_SHADERTYPE_PS);
1655
1656 cmd = SVGA3D_FIFOReserve(swc,
1657 SVGA_3D_CMD_SET_SHADER,
1658 sizeof *cmd,
1659 2); /* two relocations */
1660 if (!cmd)
1661 return PIPE_ERROR_OUT_OF_MEMORY;
1662
1663 cmd->cid = swc->cid;
1664 cmd->type = type;
1665 if (gbshader)
1666 swc->shader_relocation(swc, &cmd->shid, NULL, NULL, gbshader, 0);
1667 else
1668 cmd->shid = SVGA_ID_INVALID;
1669 swc->commit(swc);
1670
1671 return PIPE_OK;
1672 }
1673
1674
1675 /**
1676 * \param flags mask of SVGA_RELOC_READ / _WRITE
1677 */
1678 enum pipe_error
1679 SVGA3D_BindGBSurface(struct svga_winsys_context *swc,
1680 struct svga_winsys_surface *surface)
1681 {
1682 SVGA3dCmdBindGBSurface *cmd =
1683 SVGA3D_FIFOReserve(swc,
1684 SVGA_3D_CMD_BIND_GB_SURFACE,
1685 sizeof *cmd,
1686 2); /* two relocations */
1687
1688 if (!cmd)
1689 return PIPE_ERROR_OUT_OF_MEMORY;
1690
1691 swc->surface_relocation(swc, &cmd->sid, &cmd->mobid, surface,
1692 SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1693
1694 swc->commit(swc);
1695
1696 return PIPE_OK;
1697 }
1698
1699
1700 /**
1701 * Update an image in a guest-backed surface.
1702 * (Inform the device that the guest-contents have been updated.)
1703 */
1704 enum pipe_error
1705 SVGA3D_UpdateGBImage(struct svga_winsys_context *swc,
1706 struct svga_winsys_surface *surface,
1707 const SVGA3dBox *box,
1708 unsigned face, unsigned mipLevel)
1709
1710 {
1711 SVGA3dCmdUpdateGBImage *cmd =
1712 SVGA3D_FIFOReserve(swc,
1713 SVGA_3D_CMD_UPDATE_GB_IMAGE,
1714 sizeof *cmd,
1715 1); /* one relocation */
1716
1717 if (!cmd)
1718 return PIPE_ERROR_OUT_OF_MEMORY;
1719
1720 swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1721 SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
1722 cmd->image.face = face;
1723 cmd->image.mipmap = mipLevel;
1724 cmd->box = *box;
1725
1726 swc->commit(swc);
1727 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1728
1729 return PIPE_OK;
1730 }
1731
1732
1733 /**
1734 * Update an entire guest-backed surface.
1735 * (Inform the device that the guest-contents have been updated.)
1736 */
1737 enum pipe_error
1738 SVGA3D_UpdateGBSurface(struct svga_winsys_context *swc,
1739 struct svga_winsys_surface *surface)
1740 {
1741 SVGA3dCmdUpdateGBSurface *cmd =
1742 SVGA3D_FIFOReserve(swc,
1743 SVGA_3D_CMD_UPDATE_GB_SURFACE,
1744 sizeof *cmd,
1745 1); /* one relocation */
1746
1747 if (!cmd)
1748 return PIPE_ERROR_OUT_OF_MEMORY;
1749
1750 swc->surface_relocation(swc, &cmd->sid, NULL, surface,
1751 SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
1752
1753 swc->commit(swc);
1754 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1755
1756 return PIPE_OK;
1757 }
1758
1759
1760 /**
1761 * Readback an image in a guest-backed surface.
1762 * (Request the device to flush the dirty contents into the guest.)
1763 */
1764 enum pipe_error
1765 SVGA3D_ReadbackGBImage(struct svga_winsys_context *swc,
1766 struct svga_winsys_surface *surface,
1767 unsigned face, unsigned mipLevel)
1768 {
1769 SVGA3dCmdReadbackGBImage *cmd =
1770 SVGA3D_FIFOReserve(swc,
1771 SVGA_3D_CMD_READBACK_GB_IMAGE,
1772 sizeof *cmd,
1773 1); /* one relocation */
1774
1775 if (!cmd)
1776 return PIPE_ERROR_OUT_OF_MEMORY;
1777
1778 swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1779 SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1780 cmd->image.face = face;
1781 cmd->image.mipmap = mipLevel;
1782
1783 swc->commit(swc);
1784 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1785
1786 return PIPE_OK;
1787 }
1788
1789
1790 /**
1791 * Readback an entire guest-backed surface.
1792 * (Request the device to flush the dirty contents into the guest.)
1793 */
1794 enum pipe_error
1795 SVGA3D_ReadbackGBSurface(struct svga_winsys_context *swc,
1796 struct svga_winsys_surface *surface)
1797 {
1798 SVGA3dCmdReadbackGBSurface *cmd =
1799 SVGA3D_FIFOReserve(swc,
1800 SVGA_3D_CMD_READBACK_GB_SURFACE,
1801 sizeof *cmd,
1802 1); /* one relocation */
1803
1804 if (!cmd)
1805 return PIPE_ERROR_OUT_OF_MEMORY;
1806
1807 swc->surface_relocation(swc, &cmd->sid, NULL, surface,
1808 SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1809
1810 swc->commit(swc);
1811 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1812
1813 return PIPE_OK;
1814 }
1815
1816
1817 enum pipe_error
1818 SVGA3D_ReadbackGBImagePartial(struct svga_winsys_context *swc,
1819 struct svga_winsys_surface *surface,
1820 unsigned face, unsigned mipLevel,
1821 const SVGA3dBox *box,
1822 bool invertBox)
1823 {
1824 SVGA3dCmdReadbackGBImagePartial *cmd =
1825 SVGA3D_FIFOReserve(swc,
1826 SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL,
1827 sizeof *cmd,
1828 1); /* one relocation */
1829 if (!cmd)
1830 return PIPE_ERROR_OUT_OF_MEMORY;
1831
1832 swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1833 SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1834 cmd->image.face = face;
1835 cmd->image.mipmap = mipLevel;
1836 cmd->box = *box;
1837 cmd->invertBox = invertBox;
1838
1839 swc->commit(swc);
1840 swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1841
1842 return PIPE_OK;
1843 }
1844
1845
1846 enum pipe_error
1847 SVGA3D_InvalidateGBImagePartial(struct svga_winsys_context *swc,
1848 struct svga_winsys_surface *surface,
1849 unsigned face, unsigned mipLevel,
1850 const SVGA3dBox *box,
1851 bool invertBox)
1852 {
1853 SVGA3dCmdInvalidateGBImagePartial *cmd =
1854 SVGA3D_FIFOReserve(swc,
1855 SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL,
1856 sizeof *cmd,
1857 1); /* one relocation */
1858 if (!cmd)
1859 return PIPE_ERROR_OUT_OF_MEMORY;
1860
1861 swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1862 SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1863 cmd->image.face = face;
1864 cmd->image.mipmap = mipLevel;
1865 cmd->box = *box;
1866 cmd->invertBox = invertBox;
1867
1868 swc->commit(swc);
1869
1870 return PIPE_OK;
1871 }
1872
1873
1874 enum pipe_error
1875 SVGA3D_SetGBShaderConstsInline(struct svga_winsys_context *swc,
1876 unsigned regStart,
1877 unsigned numRegs,
1878 SVGA3dShaderType shaderType,
1879 SVGA3dShaderConstType constType,
1880 const void *values)
1881 {
1882 SVGA3dCmdSetGBShaderConstInline *cmd;
1883
1884 assert(numRegs > 0);
1885
1886 cmd = SVGA3D_FIFOReserve(swc,
1887 SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE,
1888 sizeof *cmd + numRegs * sizeof(float[4]),
1889 0); /* no relocations */
1890 if (!cmd)
1891 return PIPE_ERROR_OUT_OF_MEMORY;
1892
1893 cmd->cid = swc->cid;
1894 cmd->regStart = regStart;
1895 cmd->shaderType = shaderType;
1896 cmd->constType = constType;
1897
1898 memcpy(&cmd[1], values, numRegs * sizeof(float[4]));
1899
1900 swc->commit(swc);
1901
1902 return PIPE_OK;
1903 }