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