xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_cmd.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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