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    if (transfer == SVGA3D_WRITE_HOST_VRAM) {
443       region_flags = SVGA_RELOC_READ;
444       surface_flags = SVGA_RELOC_WRITE;
445    }
446    else if (transfer == SVGA3D_READ_HOST_VRAM) {
447       region_flags = SVGA_RELOC_WRITE;
448       surface_flags = SVGA_RELOC_READ;
449    }
450    else {
451       assert(0);
452       return PIPE_ERROR_BAD_INPUT;
453    }
454 
455    cmd = SVGA3D_FIFOReserve(swc,
456                             SVGA_3D_CMD_SURFACE_DMA,
457                             sizeof *cmd + boxesSize + sizeof *pSuffix,
458                             2);
459    if (!cmd)
460       return PIPE_ERROR_OUT_OF_MEMORY;
461 
462    swc->region_relocation(swc, &cmd->guest.ptr, st->hwbuf, 0, region_flags);
463    cmd->guest.pitch = st->base.stride;
464 
465    swc->surface_relocation(swc, &cmd->host.sid, NULL,
466                            texture->handle, surface_flags);
467    cmd->host.face = st->slice; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
468    cmd->host.mipmap = st->base.level;
469 
470    cmd->transfer = transfer;
471 
472    memcpy(&cmd[1], boxes, boxesSize);
473 
474    pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize);
475    pSuffix->suffixSize = sizeof *pSuffix;
476    pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride;
477    pSuffix->flags = flags;
478 
479    swc->commit(swc);
480    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
481 
482    return PIPE_OK;
483 }
484 
485 
486 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)487 SVGA3D_BufferDMA(struct svga_winsys_context *swc,
488                  struct svga_winsys_buffer *guest,
489                  struct svga_winsys_surface *host,
490                  SVGA3dTransferType transfer,      // IN
491                  uint32 size,                      // IN
492                  uint32 guest_offset,              // IN
493                  uint32 host_offset,               // IN
494                  SVGA3dSurfaceDMAFlags flags)      // IN
495 {
496    SVGA3dCmdSurfaceDMA *cmd;
497    SVGA3dCopyBox *box;
498    SVGA3dCmdSurfaceDMASuffix *pSuffix;
499    unsigned region_flags;
500    unsigned surface_flags;
501 
502    assert(!swc->have_gb_objects);
503 
504    if (transfer == SVGA3D_WRITE_HOST_VRAM) {
505       region_flags = SVGA_RELOC_READ;
506       surface_flags = SVGA_RELOC_WRITE;
507    }
508    else if (transfer == SVGA3D_READ_HOST_VRAM) {
509       region_flags = SVGA_RELOC_WRITE;
510       surface_flags = SVGA_RELOC_READ;
511    }
512    else {
513       assert(0);
514       return PIPE_ERROR_BAD_INPUT;
515    }
516 
517    cmd = SVGA3D_FIFOReserve(swc,
518                             SVGA_3D_CMD_SURFACE_DMA,
519                             sizeof *cmd + sizeof *box + sizeof *pSuffix,
520                             2);
521    if (!cmd)
522       return PIPE_ERROR_OUT_OF_MEMORY;
523 
524    swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
525    cmd->guest.pitch = 0;
526 
527    swc->surface_relocation(swc, &cmd->host.sid,
528                            NULL, host, surface_flags);
529    cmd->host.face = 0;
530    cmd->host.mipmap = 0;
531 
532    cmd->transfer = transfer;
533 
534    box = (SVGA3dCopyBox *)&cmd[1];
535    box->x = host_offset;
536    box->y = 0;
537    box->z = 0;
538    box->w = size;
539    box->h = 1;
540    box->d = 1;
541    box->srcx = guest_offset;
542    box->srcy = 0;
543    box->srcz = 0;
544 
545    pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box);
546    pSuffix->suffixSize = sizeof *pSuffix;
547    pSuffix->maximumOffset = guest_offset + size;
548    pSuffix->flags = flags;
549 
550    swc->commit(swc);
551    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
552 
553    return PIPE_OK;
554 }
555 
556 
557 /*
558  *----------------------------------------------------------------------
559  *
560  * SVGA3D_SetRenderTarget --
561  *
562  *      Bind a surface object to a particular render target attachment
563  *      point on the current context. Render target attachment points
564  *      exist for color buffers, a depth buffer, and a stencil buffer.
565  *
566  *      The SVGA3D device is quite lenient about the types of surfaces
567  *      that may be used as render targets. The color buffers must
568  *      all be the same size, but the depth and stencil buffers do not
569  *      have to be the same size as the color buffer. All attachments
570  *      are optional.
571  *
572  *      Some combinations of render target formats may require software
573  *      emulation, depending on the capabilities of the host graphics
574  *      API and graphics hardware.
575  *
576  * Results:
577  *      None.
578  *
579  * Side effects:
580  *      None.
581  *
582  *----------------------------------------------------------------------
583  */
584 
585 enum pipe_error
SVGA3D_SetRenderTarget(struct svga_winsys_context * swc,SVGA3dRenderTargetType type,struct pipe_surface * surface)586 SVGA3D_SetRenderTarget(struct svga_winsys_context *swc,
587                        SVGA3dRenderTargetType type,   // IN
588                        struct pipe_surface *surface)  // IN
589 {
590    SVGA3dCmdSetRenderTarget *cmd;
591 
592    cmd = SVGA3D_FIFOReserve(swc,
593                             SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd, 1);
594    if (!cmd)
595       return PIPE_ERROR_OUT_OF_MEMORY;
596 
597    cmd->cid = swc->cid;
598    cmd->type = type;
599    surface_to_surfaceid(swc, surface, &cmd->target, SVGA_RELOC_WRITE);
600    swc->commit(swc);
601 
602    return PIPE_OK;
603 }
604 
605 
606 /*
607  *----------------------------------------------------------------------
608  *
609  * SVGA3D_DefineShader --
610  *
611  *      Upload the bytecode for a new shader. The bytecode is "SVGA3D
612  *      format", which is theoretically a binary-compatible superset
613  *      of Microsoft's DirectX shader bytecode. In practice, the
614  *      SVGA3D bytecode doesn't yet have any extensions to DirectX's
615  *      bytecode format.
616  *
617  *      The SVGA3D device supports shader models 1.1 through 2.0.
618  *
619  *      The caller chooses a shader ID (small positive integer) by
620  *      which this shader will be identified in future commands. This
621  *      ID is in a namespace which is per-context and per-shader-type.
622  *
623  *      'bytecodeLen' is specified in bytes. It must be a multiple of 4.
624  *
625  * Results:
626  *      None.
627  *
628  * Side effects:
629  *      None.
630  *
631  *----------------------------------------------------------------------
632  */
633 
634 enum pipe_error
SVGA3D_DefineShader(struct svga_winsys_context * swc,uint32 shid,SVGA3dShaderType type,const uint32 * bytecode,uint32 bytecodeLen)635 SVGA3D_DefineShader(struct svga_winsys_context *swc,
636                     uint32 shid,                  // IN
637                     SVGA3dShaderType type,        // IN
638                     const uint32 *bytecode,       // IN
639                     uint32 bytecodeLen)           // IN
640 {
641    SVGA3dCmdDefineShader *cmd;
642 
643    assert(bytecodeLen % 4 == 0);
644 
645    cmd = SVGA3D_FIFOReserve(swc,
646                             SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen,
647                             0);
648    if (!cmd)
649       return PIPE_ERROR_OUT_OF_MEMORY;
650 
651    cmd->cid = swc->cid;
652    cmd->shid = shid;
653    cmd->type = type;
654    memcpy(&cmd[1], bytecode, bytecodeLen);
655    swc->commit(swc);
656 
657    return PIPE_OK;
658 }
659 
660 
661 /*
662  *----------------------------------------------------------------------
663  *
664  * SVGA3D_DestroyShader --
665  *
666  *      Delete a shader that was created by SVGA3D_DefineShader. If
667  *      the shader was the current vertex or pixel shader for its
668  *      context, rendering results are undefined until a new shader is
669  *      bound.
670  *
671  * Results:
672  *      None.
673  *
674  * Side effects:
675  *      None.
676  *
677  *----------------------------------------------------------------------
678  */
679 
680 enum pipe_error
SVGA3D_DestroyShader(struct svga_winsys_context * swc,uint32 shid,SVGA3dShaderType type)681 SVGA3D_DestroyShader(struct svga_winsys_context *swc,
682                      uint32 shid,            // IN
683                      SVGA3dShaderType type)  // IN
684 {
685    SVGA3dCmdDestroyShader *cmd;
686 
687    cmd = SVGA3D_FIFOReserve(swc,
688                             SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd,
689                             0);
690    if (!cmd)
691       return PIPE_ERROR_OUT_OF_MEMORY;
692 
693    cmd->cid = swc->cid;
694    cmd->shid = shid;
695    cmd->type = type;
696    swc->commit(swc);
697 
698    return PIPE_OK;
699 }
700 
701 
702 /*
703  *----------------------------------------------------------------------
704  *
705  * SVGA3D_SetShaderConst --
706  *
707  *      Set the value of a shader constant.
708  *
709  *      Shader constants are analogous to uniform variables in GLSL,
710  *      except that they belong to the render context rather than to
711  *      an individual shader.
712  *
713  *      Constants may have one of three types: A 4-vector of floats,
714  *      a 4-vector of integers, or a single boolean flag.
715  *
716  * Results:
717  *      None.
718  *
719  * Side effects:
720  *      None.
721  *
722  *----------------------------------------------------------------------
723  */
724 
725 enum pipe_error
SVGA3D_SetShaderConst(struct svga_winsys_context * swc,uint32 reg,SVGA3dShaderType type,SVGA3dShaderConstType ctype,const void * value)726 SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
727                       uint32 reg,                   // IN
728                       SVGA3dShaderType type,        // IN
729                       SVGA3dShaderConstType ctype,  // IN
730                       const void *value)            // IN
731 {
732    SVGA3dCmdSetShaderConst *cmd;
733 
734    cmd = SVGA3D_FIFOReserve(swc,
735                             SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd,
736                             0);
737    if (!cmd)
738       return PIPE_ERROR_OUT_OF_MEMORY;
739 
740    cmd->cid = swc->cid;
741    cmd->reg = reg;
742    cmd->type = type;
743    cmd->ctype = ctype;
744 
745    switch (ctype) {
746 
747    case SVGA3D_CONST_TYPE_FLOAT:
748    case SVGA3D_CONST_TYPE_INT:
749       memcpy(&cmd->values, value, sizeof cmd->values);
750       break;
751 
752    case SVGA3D_CONST_TYPE_BOOL:
753       memset(&cmd->values, 0, sizeof cmd->values);
754       cmd->values[0] = *(uint32*)value;
755       break;
756 
757    default:
758       assert(0);
759       break;
760 
761    }
762    swc->commit(swc);
763 
764    return PIPE_OK;
765 }
766 
767 
768 /*
769  *----------------------------------------------------------------------
770  *
771  * SVGA3D_SetShaderConsts --
772  *
773  *      Set the value of successive shader constants.
774  *
775  *      Shader constants are analogous to uniform variables in GLSL,
776  *      except that they belong to the render context rather than to
777  *      an individual shader.
778  *
779  *      Constants may have one of three types: A 4-vector of floats,
780  *      a 4-vector of integers, or a single boolean flag.
781  *
782  * Results:
783  *      None.
784  *
785  * Side effects:
786  *      None.
787  *
788  *----------------------------------------------------------------------
789  */
790 
791 enum pipe_error
SVGA3D_SetShaderConsts(struct svga_winsys_context * swc,uint32 reg,uint32 numRegs,SVGA3dShaderType type,SVGA3dShaderConstType ctype,const void * values)792 SVGA3D_SetShaderConsts(struct svga_winsys_context *swc,
793                         uint32 reg,                   // IN
794                         uint32 numRegs,               // IN
795                         SVGA3dShaderType type,        // IN
796                         SVGA3dShaderConstType ctype,  // IN
797                         const void *values)           // IN
798 {
799    SVGA3dCmdSetShaderConst *cmd;
800 
801    cmd = SVGA3D_FIFOReserve(swc,
802                             SVGA_3D_CMD_SET_SHADER_CONST,
803                             sizeof *cmd + (numRegs - 1) * sizeof cmd->values,
804                             0);
805    if (!cmd)
806       return PIPE_ERROR_OUT_OF_MEMORY;
807 
808    cmd->cid = swc->cid;
809    cmd->reg = reg;
810    cmd->type = type;
811    cmd->ctype = ctype;
812 
813    memcpy(&cmd->values, values, numRegs * sizeof cmd->values);
814 
815    swc->commit(swc);
816 
817    return PIPE_OK;
818 }
819 
820 
821 
822 
823 
824 /*
825  *----------------------------------------------------------------------
826  *
827  * SVGA3D_SetShader --
828  *
829  *      Switch active shaders. This binds a new vertex or pixel shader
830  *      to the specified context.
831  *
832  *      A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
833  *      back to the fixed function vertex or pixel pipeline.
834  *
835  * Results:
836  *      None.
837  *
838  * Side effects:
839  *      None.
840  *
841  *----------------------------------------------------------------------
842  */
843 
844 enum pipe_error
SVGA3D_SetShader(struct svga_winsys_context * swc,SVGA3dShaderType type,uint32 shid)845 SVGA3D_SetShader(struct svga_winsys_context *swc,
846                  SVGA3dShaderType type,  // IN
847                  uint32 shid)            // IN
848 {
849    SVGA3dCmdSetShader *cmd;
850 
851    assert(type == SVGA3D_SHADERTYPE_VS || type == SVGA3D_SHADERTYPE_PS);
852 
853    cmd = SVGA3D_FIFOReserve(swc,
854                             SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
855                             0);
856    if (!cmd)
857       return PIPE_ERROR_OUT_OF_MEMORY;
858 
859    cmd->cid = swc->cid;
860    cmd->type = type;
861    cmd->shid = shid;
862    swc->commit(swc);
863 
864    return PIPE_OK;
865 }
866 
867 
868 /*
869  *----------------------------------------------------------------------
870  *
871  * SVGA3D_BeginClear --
872  *
873  *      Begin a CLEAR command. This reserves space for it in the FIFO,
874  *      and returns a pointer to the command's rectangle array.  This
875  *      function must be paired with SVGA_FIFOCommitAll().
876  *
877  *      Clear is a rendering operation which fills a list of
878  *      rectangles with constant values on all render target types
879  *      indicated by 'flags'.
880  *
881  *      Clear is not affected by clipping, depth test, or other
882  *      render state which affects the fragment pipeline.
883  *
884  * Results:
885  *      None.
886  *
887  * Side effects:
888  *      May write to attached render target surfaces.
889  *
890  *----------------------------------------------------------------------
891  */
892 
893 enum pipe_error
SVGA3D_BeginClear(struct svga_winsys_context * swc,SVGA3dClearFlag flags,uint32 color,float depth,uint32 stencil,SVGA3dRect ** rects,uint32 numRects)894 SVGA3D_BeginClear(struct svga_winsys_context *swc,
895                   SVGA3dClearFlag flags,  // IN
896                   uint32 color,           // IN
897                   float depth,            // IN
898                   uint32 stencil,         // IN
899                   SVGA3dRect **rects,     // OUT
900                   uint32 numRects)        // IN
901 {
902    SVGA3dCmdClear *cmd;
903 
904    cmd = SVGA3D_FIFOReserve(swc,
905                             SVGA_3D_CMD_CLEAR,
906                             sizeof *cmd + sizeof **rects * numRects,
907                             0);
908    if (!cmd)
909       return PIPE_ERROR_OUT_OF_MEMORY;
910 
911    cmd->cid = swc->cid;
912    cmd->clearFlag = flags;
913    cmd->color = color;
914    cmd->depth = depth;
915    cmd->stencil = stencil;
916    *rects = (SVGA3dRect*) &cmd[1];
917 
918    return PIPE_OK;
919 }
920 
921 
922 /*
923  *----------------------------------------------------------------------
924  *
925  * SVGA3D_ClearRect --
926  *
927  *      This is a simplified version of SVGA3D_BeginClear().
928  *
929  * Results:
930  *      None.
931  *
932  * Side effects:
933  *      None.
934  *
935  *----------------------------------------------------------------------
936  */
937 
938 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)939 SVGA3D_ClearRect(struct svga_winsys_context *swc,
940                  SVGA3dClearFlag flags,  // IN
941                  uint32 color,           // IN
942                  float depth,            // IN
943                  uint32 stencil,         // IN
944                  uint32 x,               // IN
945                  uint32 y,               // IN
946                  uint32 w,               // IN
947                  uint32 h)               // IN
948 {
949    SVGA3dRect *rect;
950    enum pipe_error ret;
951 
952    ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
953    if (ret != PIPE_OK)
954       return PIPE_ERROR_OUT_OF_MEMORY;
955 
956    memset(rect, 0, sizeof *rect);
957    rect->x = x;
958    rect->y = y;
959    rect->w = w;
960    rect->h = h;
961    swc->commit(swc);
962 
963    return PIPE_OK;
964 }
965 
966 
967 /*
968  *----------------------------------------------------------------------
969  *
970  * SVGA3D_BeginDrawPrimitives --
971  *
972  *      Begin a DRAW_PRIMITIVES command. This reserves space for it in
973  *      the FIFO, and returns a pointer to the command's arrays.
974  *      This function must be paired with SVGA_FIFOCommitAll().
975  *
976  *      Drawing commands consist of two variable-length arrays:
977  *      SVGA3dVertexDecl elements declare a set of vertex buffers to
978  *      use while rendering, and SVGA3dPrimitiveRange elements specify
979  *      groups of primitives each with an optional index buffer.
980  *
981  *      The decls and ranges arrays are initialized to zero.
982  *
983  * Results:
984  *      None.
985  *
986  * Side effects:
987  *      May write to attached render target surfaces.
988  *
989  *----------------------------------------------------------------------
990  */
991 
992 enum pipe_error
SVGA3D_BeginDrawPrimitives(struct svga_winsys_context * swc,SVGA3dVertexDecl ** decls,uint32 numVertexDecls,SVGA3dPrimitiveRange ** ranges,uint32 numRanges)993 SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
994                            SVGA3dVertexDecl **decls,      // OUT
995                            uint32 numVertexDecls,         // IN
996                            SVGA3dPrimitiveRange **ranges, // OUT
997                            uint32 numRanges)              // IN
998 {
999    SVGA3dCmdDrawPrimitives *cmd;
1000    SVGA3dVertexDecl *declArray;
1001    SVGA3dPrimitiveRange *rangeArray;
1002    uint32 declSize = sizeof **decls * numVertexDecls;
1003    uint32 rangeSize = sizeof **ranges * numRanges;
1004 
1005    cmd = SVGA3D_FIFOReserve(swc,
1006                             SVGA_3D_CMD_DRAW_PRIMITIVES,
1007                             sizeof *cmd + declSize + rangeSize,
1008                             numVertexDecls + numRanges);
1009    if (!cmd)
1010       return PIPE_ERROR_OUT_OF_MEMORY;
1011 
1012    cmd->cid = swc->cid;
1013    cmd->numVertexDecls = numVertexDecls;
1014    cmd->numRanges = numRanges;
1015 
1016    declArray = (SVGA3dVertexDecl*) &cmd[1];
1017    rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
1018 
1019    memset(declArray, 0, declSize);
1020    memset(rangeArray, 0, rangeSize);
1021 
1022    *decls = declArray;
1023    *ranges = rangeArray;
1024 
1025    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1026 
1027    swc->num_draw_commands++;
1028 
1029    return PIPE_OK;
1030 }
1031 
1032 
1033 /*
1034  *----------------------------------------------------------------------
1035  *
1036  * SVGA3D_BeginSurfaceCopy --
1037  *
1038  *      Begin a SURFACE_COPY command. This reserves space for it in
1039  *      the FIFO, and returns a pointer to the command's arrays.  This
1040  *      function must be paired with SVGA_FIFOCommitAll().
1041  *
1042  *      The box array is initialized with zeroes.
1043  *
1044  * Results:
1045  *      None.
1046  *
1047  * Side effects:
1048  *      Asynchronously copies a list of boxes from surface to surface.
1049  *
1050  *----------------------------------------------------------------------
1051  */
1052 
1053 enum pipe_error
SVGA3D_BeginSurfaceCopy(struct svga_winsys_context * swc,struct pipe_surface * src,struct pipe_surface * dest,SVGA3dCopyBox ** boxes,uint32 numBoxes)1054 SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
1055                         struct pipe_surface *src,    // IN
1056                         struct pipe_surface *dest,   // IN
1057                         SVGA3dCopyBox **boxes,       // OUT
1058                         uint32 numBoxes)             // IN
1059 {
1060    SVGA3dCmdSurfaceCopy *cmd;
1061    uint32 boxesSize = sizeof **boxes * numBoxes;
1062 
1063    cmd = SVGA3D_FIFOReserve(swc,
1064                             SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
1065                             2);
1066    if (!cmd)
1067       return PIPE_ERROR_OUT_OF_MEMORY;
1068 
1069    surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1070    surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1071    *boxes = (SVGA3dCopyBox*) &cmd[1];
1072 
1073    memset(*boxes, 0, boxesSize);
1074 
1075    return PIPE_OK;
1076 }
1077 
1078 
1079 /*
1080  *----------------------------------------------------------------------
1081  *
1082  * SVGA3D_SurfaceStretchBlt --
1083  *
1084  *      Issue a SURFACE_STRETCHBLT command: an asynchronous
1085  *      surface-to-surface blit, with scaling.
1086  *
1087  * Results:
1088  *      None.
1089  *
1090  * Side effects:
1091  *      Asynchronously copies one box from surface to surface.
1092  *
1093  *----------------------------------------------------------------------
1094  */
1095 
1096 enum pipe_error
SVGA3D_SurfaceStretchBlt(struct svga_winsys_context * swc,struct pipe_surface * src,struct pipe_surface * dest,SVGA3dBox * boxSrc,SVGA3dBox * boxDest,SVGA3dStretchBltMode mode)1097 SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
1098                          struct pipe_surface *src,    // IN
1099                          struct pipe_surface *dest,   // IN
1100                          SVGA3dBox *boxSrc,           // IN
1101                          SVGA3dBox *boxDest,          // IN
1102                          SVGA3dStretchBltMode mode)   // IN
1103 {
1104    SVGA3dCmdSurfaceStretchBlt *cmd;
1105 
1106    cmd = SVGA3D_FIFOReserve(swc,
1107                             SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
1108                             2);
1109    if (!cmd)
1110       return PIPE_ERROR_OUT_OF_MEMORY;
1111 
1112    surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1113    surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1114    cmd->boxSrc = *boxSrc;
1115    cmd->boxDest = *boxDest;
1116    cmd->mode = mode;
1117    swc->commit(swc);
1118 
1119    return PIPE_OK;
1120 }
1121 
1122 
1123 /*
1124  *----------------------------------------------------------------------
1125  *
1126  * SVGA3D_SetViewport --
1127  *
1128  *      Set the current context's viewport rectangle. The viewport
1129  *      is clipped to the dimensions of the current render target,
1130  *      then all rendering is clipped to the viewport.
1131  *
1132  * Results:
1133  *      None.
1134  *
1135  * Side effects:
1136  *      None.
1137  *
1138  *----------------------------------------------------------------------
1139  */
1140 
1141 enum pipe_error
SVGA3D_SetViewport(struct svga_winsys_context * swc,SVGA3dRect * rect)1142 SVGA3D_SetViewport(struct svga_winsys_context *swc,
1143                    SVGA3dRect *rect)  // IN
1144 {
1145    SVGA3dCmdSetViewport *cmd;
1146 
1147    cmd = SVGA3D_FIFOReserve(swc,
1148                             SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
1149                             0);
1150    if (!cmd)
1151       return PIPE_ERROR_OUT_OF_MEMORY;
1152 
1153    cmd->cid = swc->cid;
1154    cmd->rect = *rect;
1155    swc->commit(swc);
1156 
1157    return PIPE_OK;
1158 }
1159 
1160 
1161 
1162 
1163 /*
1164  *----------------------------------------------------------------------
1165  *
1166  * SVGA3D_SetScissorRect --
1167  *
1168  *      Set the current context's scissor rectangle. If scissoring
1169  *      is enabled then all rendering is clipped to the scissor bounds.
1170  *
1171  * Results:
1172  *      None.
1173  *
1174  * Side effects:
1175  *      None.
1176  *
1177  *----------------------------------------------------------------------
1178  */
1179 
1180 enum pipe_error
SVGA3D_SetScissorRect(struct svga_winsys_context * swc,SVGA3dRect * rect)1181 SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
1182                       SVGA3dRect *rect)  // IN
1183 {
1184    SVGA3dCmdSetScissorRect *cmd;
1185 
1186    cmd = SVGA3D_FIFOReserve(swc,
1187                             SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
1188                             0);
1189    if (!cmd)
1190       return PIPE_ERROR_OUT_OF_MEMORY;
1191 
1192    cmd->cid = swc->cid;
1193    cmd->rect = *rect;
1194    swc->commit(swc);
1195 
1196    return PIPE_OK;
1197 }
1198 
1199 /*
1200  *----------------------------------------------------------------------
1201  *
1202  * SVGA3D_SetClipPlane --
1203  *
1204  *      Set one of the current context's clip planes. If the clip
1205  *      plane is enabled then all 3d rendering is clipped against
1206  *      the plane.
1207  *
1208  * Results:
1209  *      None.
1210  *
1211  * Side effects:
1212  *      None.
1213  *
1214  *----------------------------------------------------------------------
1215  */
1216 
1217 enum pipe_error
SVGA3D_SetClipPlane(struct svga_winsys_context * swc,uint32 index,const float * plane)1218 SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
1219                     uint32 index, const float *plane)
1220 {
1221    SVGA3dCmdSetClipPlane *cmd;
1222 
1223    cmd = SVGA3D_FIFOReserve(swc,
1224                             SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
1225                             0);
1226    if (!cmd)
1227       return PIPE_ERROR_OUT_OF_MEMORY;
1228 
1229    cmd->cid = swc->cid;
1230    cmd->index = index;
1231    cmd->plane[0] = plane[0];
1232    cmd->plane[1] = plane[1];
1233    cmd->plane[2] = plane[2];
1234    cmd->plane[3] = plane[3];
1235    swc->commit(swc);
1236 
1237    return PIPE_OK;
1238 }
1239 
1240 /*
1241  *----------------------------------------------------------------------
1242  *
1243  * SVGA3D_SetZRange --
1244  *
1245  *      Set the range of the depth buffer to use. 'min' and 'max'
1246  *      are values between 0.0 and 1.0.
1247  *
1248  * Results:
1249  *      None.
1250  *
1251  * Side effects:
1252  *      None.
1253  *
1254  *----------------------------------------------------------------------
1255  */
1256 
1257 enum pipe_error
SVGA3D_SetZRange(struct svga_winsys_context * swc,float zMin,float zMax)1258 SVGA3D_SetZRange(struct svga_winsys_context *swc,
1259                  float zMin,  // IN
1260                  float zMax)  // IN
1261 {
1262    SVGA3dCmdSetZRange *cmd;
1263 
1264    cmd = SVGA3D_FIFOReserve(swc,
1265                             SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
1266                             0);
1267    if (!cmd)
1268       return PIPE_ERROR_OUT_OF_MEMORY;
1269 
1270    cmd->cid = swc->cid;
1271    cmd->zRange.min = zMin;
1272    cmd->zRange.max = zMax;
1273    swc->commit(swc);
1274 
1275    return PIPE_OK;
1276 }
1277 
1278 
1279 /*
1280  *----------------------------------------------------------------------
1281  *
1282  * SVGA3D_BeginSetTextureState --
1283  *
1284  *      Begin a SETTEXTURESTATE command. This reserves space for it in
1285  *      the FIFO, and returns a pointer to the command's texture state
1286  *      array.  This function must be paired with SVGA_FIFOCommitAll().
1287  *
1288  *      This command sets rendering state which is per-texture-unit.
1289  *
1290  *      XXX: Individual texture states need documentation. However,
1291  *           they are very similar to the texture states defined by
1292  *           Direct3D. The D3D documentation is a good starting point
1293  *           for understanding SVGA3D texture states.
1294  *
1295  * Results:
1296  *      None.
1297  *
1298  * Side effects:
1299  *      None.
1300  *
1301  *----------------------------------------------------------------------
1302  */
1303 
1304 enum pipe_error
SVGA3D_BeginSetTextureState(struct svga_winsys_context * swc,SVGA3dTextureState ** states,uint32 numStates)1305 SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
1306                             SVGA3dTextureState **states,  // OUT
1307                             uint32 numStates)             // IN
1308 {
1309    SVGA3dCmdSetTextureState *cmd;
1310 
1311    cmd = SVGA3D_FIFOReserve(swc,
1312                             SVGA_3D_CMD_SETTEXTURESTATE,
1313                             sizeof *cmd + sizeof **states * numStates,
1314                             numStates);
1315    if (!cmd)
1316       return PIPE_ERROR_OUT_OF_MEMORY;
1317 
1318    cmd->cid = swc->cid;
1319    *states = (SVGA3dTextureState*) &cmd[1];
1320 
1321    return PIPE_OK;
1322 }
1323 
1324 
1325 /*
1326  *----------------------------------------------------------------------
1327  *
1328  * SVGA3D_BeginSetRenderState --
1329  *
1330  *      Begin a SETRENDERSTATE command. This reserves space for it in
1331  *      the FIFO, and returns a pointer to the command's texture state
1332  *      array.  This function must be paired with SVGA_FIFOCommitAll().
1333  *
1334  *      This command sets rendering state which is global to the context.
1335  *
1336  *      XXX: Individual render states need documentation. However,
1337  *           they are very similar to the render states defined by
1338  *           Direct3D. The D3D documentation is a good starting point
1339  *           for understanding SVGA3D render states.
1340  *
1341  * Results:
1342  *      None.
1343  *
1344  * Side effects:
1345  *      None.
1346  *
1347  *----------------------------------------------------------------------
1348  */
1349 
1350 enum pipe_error
SVGA3D_BeginSetRenderState(struct svga_winsys_context * swc,SVGA3dRenderState ** states,uint32 numStates)1351 SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
1352                            SVGA3dRenderState **states,  // OUT
1353                            uint32 numStates)            // IN
1354 {
1355    SVGA3dCmdSetRenderState *cmd;
1356 
1357    cmd = SVGA3D_FIFOReserve(swc,
1358                             SVGA_3D_CMD_SETRENDERSTATE,
1359                             sizeof *cmd + sizeof **states * numStates,
1360                             0);
1361    if (!cmd)
1362       return PIPE_ERROR_OUT_OF_MEMORY;
1363 
1364    cmd->cid = swc->cid;
1365    *states = (SVGA3dRenderState*) &cmd[1];
1366 
1367    return PIPE_OK;
1368 }
1369 
1370 
1371 /*
1372  *----------------------------------------------------------------------
1373  *
1374  * SVGA3D_BeginGBQuery--
1375  *
1376  *      GB resource version of SVGA3D_BeginQuery.
1377  *
1378  * Results:
1379  *      None.
1380  *
1381  * Side effects:
1382  *      Commits space in the FIFO memory.
1383  *
1384  *----------------------------------------------------------------------
1385  */
1386 
1387 static enum pipe_error
SVGA3D_BeginGBQuery(struct svga_winsys_context * swc,SVGA3dQueryType type)1388 SVGA3D_BeginGBQuery(struct svga_winsys_context *swc,
1389 		    SVGA3dQueryType type) // IN
1390 {
1391    SVGA3dCmdBeginGBQuery *cmd;
1392 
1393    cmd = SVGA3D_FIFOReserve(swc,
1394                             SVGA_3D_CMD_BEGIN_GB_QUERY,
1395                             sizeof *cmd,
1396                             1);
1397    if (!cmd)
1398       return PIPE_ERROR_OUT_OF_MEMORY;
1399 
1400    cmd->cid = swc->cid;
1401    cmd->type = type;
1402 
1403    swc->commit(swc);
1404 
1405    return PIPE_OK;
1406 }
1407 
1408 
1409 /*
1410  *----------------------------------------------------------------------
1411  *
1412  * SVGA3D_BeginQuery--
1413  *
1414  *      Issues a SVGA_3D_CMD_BEGIN_QUERY command.
1415  *
1416  * Results:
1417  *      None.
1418  *
1419  * Side effects:
1420  *      Commits space in the FIFO memory.
1421  *
1422  *----------------------------------------------------------------------
1423  */
1424 
1425 enum pipe_error
SVGA3D_BeginQuery(struct svga_winsys_context * swc,SVGA3dQueryType type)1426 SVGA3D_BeginQuery(struct svga_winsys_context *swc,
1427                   SVGA3dQueryType type) // IN
1428 {
1429    SVGA3dCmdBeginQuery *cmd;
1430 
1431    if (swc->have_gb_objects)
1432       return SVGA3D_BeginGBQuery(swc, type);
1433 
1434    cmd = SVGA3D_FIFOReserve(swc,
1435                             SVGA_3D_CMD_BEGIN_QUERY,
1436                             sizeof *cmd,
1437                             0);
1438    if (!cmd)
1439       return PIPE_ERROR_OUT_OF_MEMORY;
1440 
1441    cmd->cid = swc->cid;
1442    cmd->type = type;
1443 
1444    swc->commit(swc);
1445 
1446    return PIPE_OK;
1447 }
1448 
1449 
1450 /*
1451  *----------------------------------------------------------------------
1452  *
1453  * SVGA3D_EndGBQuery--
1454  *
1455  *      GB resource version of SVGA3D_EndQuery.
1456  *
1457  * Results:
1458  *      None.
1459  *
1460  * Side effects:
1461  *      Commits space in the FIFO memory.
1462  *
1463  *----------------------------------------------------------------------
1464  */
1465 
1466 static enum pipe_error
SVGA3D_EndGBQuery(struct svga_winsys_context * swc,SVGA3dQueryType type,struct svga_winsys_buffer * buffer)1467 SVGA3D_EndGBQuery(struct svga_winsys_context *swc,
1468 		  SVGA3dQueryType type,              // IN
1469 		  struct svga_winsys_buffer *buffer) // IN/OUT
1470 {
1471    SVGA3dCmdEndGBQuery *cmd;
1472 
1473    cmd = SVGA3D_FIFOReserve(swc,
1474                             SVGA_3D_CMD_END_GB_QUERY,
1475                             sizeof *cmd,
1476                             2);
1477    if (!cmd)
1478       return PIPE_ERROR_OUT_OF_MEMORY;
1479 
1480    cmd->cid = swc->cid;
1481    cmd->type = type;
1482 
1483    swc->mob_relocation(swc, &cmd->mobid, &cmd->offset, buffer,
1484 		       0, SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1485 
1486    swc->commit(swc);
1487 
1488    return PIPE_OK;
1489 }
1490 
1491 
1492 /*
1493  *----------------------------------------------------------------------
1494  *
1495  * SVGA3D_EndQuery--
1496  *
1497  *      Issues a SVGA_3D_CMD_END_QUERY command.
1498  *
1499  * Results:
1500  *      None.
1501  *
1502  * Side effects:
1503  *      Commits space in the FIFO memory.
1504  *
1505  *----------------------------------------------------------------------
1506  */
1507 
1508 enum pipe_error
SVGA3D_EndQuery(struct svga_winsys_context * swc,SVGA3dQueryType type,struct svga_winsys_buffer * buffer)1509 SVGA3D_EndQuery(struct svga_winsys_context *swc,
1510                 SVGA3dQueryType type,              // IN
1511                 struct svga_winsys_buffer *buffer) // IN/OUT
1512 {
1513    SVGA3dCmdEndQuery *cmd;
1514 
1515    if (swc->have_gb_objects)
1516       return SVGA3D_EndGBQuery(swc, type, buffer);
1517 
1518    cmd = SVGA3D_FIFOReserve(swc,
1519                             SVGA_3D_CMD_END_QUERY,
1520                             sizeof *cmd,
1521                             1);
1522    if (!cmd)
1523       return PIPE_ERROR_OUT_OF_MEMORY;
1524 
1525    cmd->cid = swc->cid;
1526    cmd->type = type;
1527 
1528    swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1529                           SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1530 
1531    swc->commit(swc);
1532 
1533    return PIPE_OK;
1534 }
1535 
1536 
1537 /*
1538  *----------------------------------------------------------------------
1539  *
1540  * SVGA3D_WaitForGBQuery--
1541  *
1542  *      GB resource version of SVGA3D_WaitForQuery.
1543  *
1544  * Results:
1545  *      None.
1546  *
1547  * Side effects:
1548  *      Commits space in the FIFO memory.
1549  *
1550  *----------------------------------------------------------------------
1551  */
1552 
1553 static enum pipe_error
SVGA3D_WaitForGBQuery(struct svga_winsys_context * swc,SVGA3dQueryType type,struct svga_winsys_buffer * buffer)1554 SVGA3D_WaitForGBQuery(struct svga_winsys_context *swc,
1555 		      SVGA3dQueryType type,              // IN
1556 		      struct svga_winsys_buffer *buffer) // IN/OUT
1557 {
1558    SVGA3dCmdWaitForGBQuery *cmd;
1559 
1560    cmd = SVGA3D_FIFOReserve(swc,
1561                             SVGA_3D_CMD_WAIT_FOR_GB_QUERY,
1562                             sizeof *cmd,
1563                             2);
1564    if (!cmd)
1565       return PIPE_ERROR_OUT_OF_MEMORY;
1566 
1567    cmd->cid = swc->cid;
1568    cmd->type = type;
1569 
1570    swc->mob_relocation(swc, &cmd->mobid, &cmd->offset, buffer,
1571 		       0, SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1572 
1573    swc->commit(swc);
1574 
1575    return PIPE_OK;
1576 }
1577 
1578 
1579 /*
1580  *----------------------------------------------------------------------
1581  *
1582  * SVGA3D_WaitForQuery--
1583  *
1584  *      Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command.  This reserves space
1585  *      for it in the FIFO.  This doesn't actually wait for the query to
1586  *      finish but instead tells the host to start a wait at the driver
1587  *      level.  The caller can wait on the status variable in the
1588  *      guestPtr memory or send an insert fence instruction after this
1589  *      command and wait on the fence.
1590  *
1591  * Results:
1592  *      None.
1593  *
1594  * Side effects:
1595  *      Commits space in the FIFO memory.
1596  *
1597  *----------------------------------------------------------------------
1598  */
1599 
1600 enum pipe_error
SVGA3D_WaitForQuery(struct svga_winsys_context * swc,SVGA3dQueryType type,struct svga_winsys_buffer * buffer)1601 SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
1602                     SVGA3dQueryType type,              // IN
1603                     struct svga_winsys_buffer *buffer) // IN/OUT
1604 {
1605    SVGA3dCmdWaitForQuery *cmd;
1606 
1607    if (swc->have_gb_objects)
1608       return SVGA3D_WaitForGBQuery(swc, type, buffer);
1609 
1610    cmd = SVGA3D_FIFOReserve(swc,
1611                             SVGA_3D_CMD_WAIT_FOR_QUERY,
1612                             sizeof *cmd,
1613                             1);
1614    if (!cmd)
1615       return PIPE_ERROR_OUT_OF_MEMORY;
1616 
1617    cmd->cid = swc->cid;
1618    cmd->type = type;
1619 
1620    swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1621                           SVGA_RELOC_READ | SVGA_RELOC_WRITE);
1622 
1623    swc->commit(swc);
1624 
1625    return PIPE_OK;
1626 }
1627 
1628 
1629 enum pipe_error
SVGA3D_BindGBShader(struct svga_winsys_context * swc,struct svga_winsys_gb_shader * gbshader)1630 SVGA3D_BindGBShader(struct svga_winsys_context *swc,
1631                     struct svga_winsys_gb_shader *gbshader)
1632 {
1633    SVGA3dCmdBindGBShader *cmd =
1634       SVGA3D_FIFOReserve(swc,
1635                          SVGA_3D_CMD_BIND_GB_SHADER,
1636                          sizeof *cmd,
1637                          2);  /* two relocations */
1638 
1639    if (!cmd)
1640       return PIPE_ERROR_OUT_OF_MEMORY;
1641 
1642    swc->shader_relocation(swc, &cmd->shid, &cmd->mobid,
1643 			  &cmd->offsetInBytes, gbshader, 0);
1644 
1645    swc->commit(swc);
1646 
1647    return PIPE_OK;
1648 }
1649 
1650 
1651 enum pipe_error
SVGA3D_SetGBShader(struct svga_winsys_context * swc,SVGA3dShaderType type,struct svga_winsys_gb_shader * gbshader)1652 SVGA3D_SetGBShader(struct svga_winsys_context *swc,
1653                    SVGA3dShaderType type,  // IN
1654                    struct svga_winsys_gb_shader *gbshader)
1655 {
1656    SVGA3dCmdSetShader *cmd;
1657 
1658    assert(type == SVGA3D_SHADERTYPE_VS || type == SVGA3D_SHADERTYPE_PS);
1659 
1660    cmd = SVGA3D_FIFOReserve(swc,
1661                             SVGA_3D_CMD_SET_SHADER,
1662                             sizeof *cmd,
1663                             2);  /* two relocations */
1664    if (!cmd)
1665       return PIPE_ERROR_OUT_OF_MEMORY;
1666 
1667    cmd->cid = swc->cid;
1668    cmd->type = type;
1669    if (gbshader)
1670       swc->shader_relocation(swc, &cmd->shid, NULL, NULL, gbshader, 0);
1671    else
1672       cmd->shid = SVGA_ID_INVALID;
1673    swc->commit(swc);
1674 
1675    return PIPE_OK;
1676 }
1677 
1678 
1679 /**
1680  * \param flags  mask of SVGA_RELOC_READ / _WRITE
1681  */
1682 enum pipe_error
SVGA3D_BindGBSurface(struct svga_winsys_context * swc,struct svga_winsys_surface * surface)1683 SVGA3D_BindGBSurface(struct svga_winsys_context *swc,
1684                      struct svga_winsys_surface *surface)
1685 {
1686    SVGA3dCmdBindGBSurface *cmd =
1687       SVGA3D_FIFOReserve(swc,
1688                          SVGA_3D_CMD_BIND_GB_SURFACE,
1689                          sizeof *cmd,
1690                          2);  /* two relocations */
1691 
1692    if (!cmd)
1693       return PIPE_ERROR_OUT_OF_MEMORY;
1694 
1695    swc->surface_relocation(swc, &cmd->sid, &cmd->mobid, surface,
1696                            SVGA_RELOC_READ);
1697 
1698    swc->commit(swc);
1699 
1700    return PIPE_OK;
1701 }
1702 
1703 
1704 /**
1705  * Update an image in a guest-backed surface.
1706  * (Inform the device that the guest-contents have been updated.)
1707  */
1708 enum pipe_error
SVGA3D_UpdateGBImage(struct svga_winsys_context * swc,struct svga_winsys_surface * surface,const SVGA3dBox * box,unsigned face,unsigned mipLevel)1709 SVGA3D_UpdateGBImage(struct svga_winsys_context *swc,
1710                      struct svga_winsys_surface *surface,
1711                      const SVGA3dBox *box,
1712                      unsigned face, unsigned mipLevel)
1713 
1714 {
1715    SVGA3dCmdUpdateGBImage *cmd =
1716       SVGA3D_FIFOReserve(swc,
1717                          SVGA_3D_CMD_UPDATE_GB_IMAGE,
1718                          sizeof *cmd,
1719                          1);  /* one relocation */
1720 
1721    if (!cmd)
1722       return PIPE_ERROR_OUT_OF_MEMORY;
1723 
1724    swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1725                            SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
1726    cmd->image.face = face;
1727    cmd->image.mipmap = mipLevel;
1728    cmd->box = *box;
1729 
1730    swc->commit(swc);
1731    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1732 
1733    return PIPE_OK;
1734 }
1735 
1736 
1737 /**
1738  * Update an entire guest-backed surface.
1739  * (Inform the device that the guest-contents have been updated.)
1740  */
1741 enum pipe_error
SVGA3D_UpdateGBSurface(struct svga_winsys_context * swc,struct svga_winsys_surface * surface)1742 SVGA3D_UpdateGBSurface(struct svga_winsys_context *swc,
1743                        struct svga_winsys_surface *surface)
1744 {
1745    SVGA3dCmdUpdateGBSurface *cmd =
1746       SVGA3D_FIFOReserve(swc,
1747                          SVGA_3D_CMD_UPDATE_GB_SURFACE,
1748                          sizeof *cmd,
1749                          1);  /* one relocation */
1750 
1751    if (!cmd)
1752       return PIPE_ERROR_OUT_OF_MEMORY;
1753 
1754    swc->surface_relocation(swc, &cmd->sid, NULL, surface,
1755                            SVGA_RELOC_WRITE | SVGA_RELOC_INTERNAL);
1756 
1757    swc->commit(swc);
1758    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1759 
1760    return PIPE_OK;
1761 }
1762 
1763 
1764 /**
1765  * Readback an image in a guest-backed surface.
1766  * (Request the device to flush the dirty contents into the guest.)
1767  */
1768 enum pipe_error
SVGA3D_ReadbackGBImage(struct svga_winsys_context * swc,struct svga_winsys_surface * surface,unsigned face,unsigned mipLevel)1769 SVGA3D_ReadbackGBImage(struct svga_winsys_context *swc,
1770                        struct svga_winsys_surface *surface,
1771                        unsigned face, unsigned mipLevel)
1772 {
1773    SVGA3dCmdReadbackGBImage *cmd =
1774       SVGA3D_FIFOReserve(swc,
1775                          SVGA_3D_CMD_READBACK_GB_IMAGE,
1776                          sizeof *cmd,
1777                          1);  /* one relocation */
1778 
1779    if (!cmd)
1780       return PIPE_ERROR_OUT_OF_MEMORY;
1781 
1782    swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1783                            SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1784    cmd->image.face = face;
1785    cmd->image.mipmap = mipLevel;
1786 
1787    swc->commit(swc);
1788    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1789 
1790    return PIPE_OK;
1791 }
1792 
1793 
1794 /**
1795  * Readback an entire guest-backed surface.
1796  * (Request the device to flush the dirty contents into the guest.)
1797  */
1798 enum pipe_error
SVGA3D_ReadbackGBSurface(struct svga_winsys_context * swc,struct svga_winsys_surface * surface)1799 SVGA3D_ReadbackGBSurface(struct svga_winsys_context *swc,
1800                          struct svga_winsys_surface *surface)
1801 {
1802    SVGA3dCmdReadbackGBSurface *cmd =
1803       SVGA3D_FIFOReserve(swc,
1804                          SVGA_3D_CMD_READBACK_GB_SURFACE,
1805                          sizeof *cmd,
1806                          1);  /* one relocation */
1807 
1808    if (!cmd)
1809       return PIPE_ERROR_OUT_OF_MEMORY;
1810 
1811    swc->surface_relocation(swc, &cmd->sid, NULL, surface,
1812                            SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1813 
1814    swc->commit(swc);
1815    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1816 
1817    return PIPE_OK;
1818 }
1819 
1820 
1821 enum pipe_error
SVGA3D_ReadbackGBImagePartial(struct svga_winsys_context * swc,struct svga_winsys_surface * surface,unsigned face,unsigned mipLevel,const SVGA3dBox * box,bool invertBox)1822 SVGA3D_ReadbackGBImagePartial(struct svga_winsys_context *swc,
1823                               struct svga_winsys_surface *surface,
1824                               unsigned face, unsigned mipLevel,
1825                               const SVGA3dBox *box,
1826                               bool invertBox)
1827 {
1828    SVGA3dCmdReadbackGBImagePartial *cmd =
1829       SVGA3D_FIFOReserve(swc,
1830                          SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL,
1831                          sizeof *cmd,
1832                          1);  /* one relocation */
1833    if (!cmd)
1834       return PIPE_ERROR_OUT_OF_MEMORY;
1835 
1836    swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1837                            SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1838    cmd->image.face = face;
1839    cmd->image.mipmap = mipLevel;
1840    cmd->box = *box;
1841    cmd->invertBox = invertBox;
1842 
1843    swc->commit(swc);
1844    swc->hints |= SVGA_HINT_FLAG_CAN_PRE_FLUSH;
1845 
1846    return PIPE_OK;
1847 }
1848 
1849 
1850 enum pipe_error
SVGA3D_InvalidateGBImagePartial(struct svga_winsys_context * swc,struct svga_winsys_surface * surface,unsigned face,unsigned mipLevel,const SVGA3dBox * box,bool invertBox)1851 SVGA3D_InvalidateGBImagePartial(struct svga_winsys_context *swc,
1852                                 struct svga_winsys_surface *surface,
1853                                 unsigned face, unsigned mipLevel,
1854                                 const SVGA3dBox *box,
1855                                 bool invertBox)
1856 {
1857    SVGA3dCmdInvalidateGBImagePartial *cmd =
1858       SVGA3D_FIFOReserve(swc,
1859                          SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL,
1860                          sizeof *cmd,
1861                          1);  /* one relocation */
1862    if (!cmd)
1863       return PIPE_ERROR_OUT_OF_MEMORY;
1864 
1865    swc->surface_relocation(swc, &cmd->image.sid, NULL, surface,
1866                            SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1867    cmd->image.face = face;
1868    cmd->image.mipmap = mipLevel;
1869    cmd->box = *box;
1870    cmd->invertBox = invertBox;
1871 
1872    swc->commit(swc);
1873 
1874    return PIPE_OK;
1875 }
1876 
1877 enum pipe_error
SVGA3D_InvalidateGBSurface(struct svga_winsys_context * swc,struct svga_winsys_surface * surface)1878 SVGA3D_InvalidateGBSurface(struct svga_winsys_context *swc,
1879                            struct svga_winsys_surface *surface)
1880 {
1881    SVGA3dCmdInvalidateGBSurface *cmd =
1882       SVGA3D_FIFOReserve(swc,
1883                          SVGA_3D_CMD_INVALIDATE_GB_SURFACE,
1884                          sizeof *cmd,
1885                          1);  /* one relocation */
1886    if (!cmd)
1887       return PIPE_ERROR_OUT_OF_MEMORY;
1888 
1889    swc->surface_relocation(swc, &cmd->sid, NULL, surface,
1890                            SVGA_RELOC_READ | SVGA_RELOC_INTERNAL);
1891    swc->commit(swc);
1892 
1893    return PIPE_OK;
1894 }
1895 
1896 enum pipe_error
SVGA3D_SetGBShaderConstsInline(struct svga_winsys_context * swc,unsigned regStart,unsigned numRegs,SVGA3dShaderType shaderType,SVGA3dShaderConstType constType,const void * values)1897 SVGA3D_SetGBShaderConstsInline(struct svga_winsys_context *swc,
1898                               unsigned regStart,
1899                               unsigned numRegs,
1900                               SVGA3dShaderType shaderType,
1901                               SVGA3dShaderConstType constType,
1902                               const void *values)
1903 {
1904    SVGA3dCmdSetGBShaderConstInline *cmd;
1905 
1906    assert(numRegs > 0);
1907 
1908    cmd = SVGA3D_FIFOReserve(swc,
1909                             SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE,
1910                             sizeof *cmd + numRegs * sizeof(float[4]),
1911                             0); /* no relocations */
1912    if (!cmd)
1913       return PIPE_ERROR_OUT_OF_MEMORY;
1914 
1915    cmd->cid = swc->cid;
1916    cmd->regStart = regStart;
1917    cmd->shaderType = shaderType;
1918    cmd->constType = constType;
1919 
1920    memcpy(&cmd[1], values, numRegs * sizeof(float[4]));
1921 
1922    swc->commit(swc);
1923 
1924    return PIPE_OK;
1925 }
1926