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