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