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 * Results:
49 *      id is filled out.
50 *
51 * Side effects:
52 *      One surface relocation is performed for texture handle.
53 *
54 *----------------------------------------------------------------------
55 */
56
57static INLINE
58void surface_to_surfaceid(struct svga_winsys_context *swc, // IN
59                          struct pipe_surface *surface,    // IN
60                          SVGA3dSurfaceImageId *id,        // OUT
61                          unsigned flags)                  // IN
62{
63   if(surface) {
64      struct svga_surface *s = svga_surface(surface);
65      swc->surface_relocation(swc, &id->sid, s->handle, flags);
66      id->face = s->real_face; /* faces have the same order */
67      id->mipmap = s->real_level;
68   }
69   else {
70      swc->surface_relocation(swc, &id->sid, NULL, flags);
71      id->face = 0;
72      id->mipmap = 0;
73   }
74}
75
76
77/*
78 *----------------------------------------------------------------------
79 *
80 * SVGA3D_FIFOReserve --
81 *
82 *      Reserve space for an SVGA3D FIFO command.
83 *
84 *      The 2D SVGA commands have been around for a while, so they
85 *      have a rather asymmetric structure. The SVGA3D protocol is
86 *      more uniform: each command begins with a header containing the
87 *      command number and the full size.
88 *
89 *      This is a convenience wrapper around SVGA_FIFOReserve. We
90 *      reserve space for the whole command, and write the header.
91 *
92 *      This function must be paired with SVGA_FIFOCommitAll().
93 *
94 * Results:
95 *      Returns a pointer to the space reserved for command-specific
96 *      data. It must be 'cmdSize' bytes long.
97 *
98 * Side effects:
99 *      Begins a FIFO reservation.
100 *
101 *----------------------------------------------------------------------
102 */
103
104void *
105SVGA3D_FIFOReserve(struct svga_winsys_context *swc,
106                   uint32 cmd,       // IN
107                   uint32 cmdSize,   // IN
108                   uint32 nr_relocs) // IN
109{
110   SVGA3dCmdHeader *header;
111
112   header = swc->reserve(swc, sizeof *header + cmdSize, nr_relocs);
113   if(!header)
114      return NULL;
115
116   header->id = cmd;
117   header->size = cmdSize;
118
119   return &header[1];
120}
121
122
123void
124SVGA_FIFOCommitAll(struct svga_winsys_context *swc)
125{
126   swc->commit(swc);
127}
128
129
130/*
131 *----------------------------------------------------------------------
132 *
133 * SVGA3D_DefineContext --
134 *
135 *      Create a new context, to be referred to with the provided ID.
136 *
137 *      Context objects encapsulate all render state, and shader
138 *      objects are per-context.
139 *
140 *      Surfaces are not per-context. The same surface can be shared
141 *      between multiple contexts, and surface operations can occur
142 *      without a context.
143 *
144 *      If the provided context ID already existed, it is redefined.
145 *
146 *      Context IDs are arbitrary small non-negative integers,
147 *      global to the entire SVGA device.
148 *
149 * Results:
150 *      None.
151 *
152 * Side effects:
153 *      None.
154 *
155 *----------------------------------------------------------------------
156 */
157
158enum pipe_error
159SVGA3D_DefineContext(struct svga_winsys_context *swc)  // IN
160{
161   SVGA3dCmdDefineContext *cmd;
162
163   cmd = SVGA3D_FIFOReserve(swc,
164                            SVGA_3D_CMD_CONTEXT_DEFINE, sizeof *cmd, 0);
165   if(!cmd)
166      return PIPE_ERROR_OUT_OF_MEMORY;
167
168   cmd->cid = swc->cid;
169
170   swc->commit(swc);
171
172   return PIPE_OK;
173}
174
175
176/*
177 *----------------------------------------------------------------------
178 *
179 * SVGA3D_DestroyContext --
180 *
181 *      Delete a context created with SVGA3D_DefineContext.
182 *
183 * Results:
184 *      None.
185 *
186 * Side effects:
187 *      None.
188 *
189 *----------------------------------------------------------------------
190 */
191
192enum pipe_error
193SVGA3D_DestroyContext(struct svga_winsys_context *swc)  // IN
194{
195   SVGA3dCmdDestroyContext *cmd;
196
197   cmd = SVGA3D_FIFOReserve(swc,
198                            SVGA_3D_CMD_CONTEXT_DESTROY, sizeof *cmd, 0);
199   if(!cmd)
200      return PIPE_ERROR_OUT_OF_MEMORY;
201
202   cmd->cid = swc->cid;
203
204   swc->commit(swc);
205
206   return PIPE_OK;
207}
208
209
210/*
211 *----------------------------------------------------------------------
212 *
213 * SVGA3D_BeginDefineSurface --
214 *
215 *      Begin a SURFACE_DEFINE command. This reserves space for it in
216 *      the FIFO, and returns pointers to the command's faces and
217 *      mipsizes arrays.
218 *
219 *      This function must be paired with SVGA_FIFOCommitAll().
220 *      The faces and mipSizes arrays are initialized to zero.
221 *
222 *      This creates a "surface" object in the SVGA3D device,
223 *      with the provided surface ID (sid). Surfaces are generic
224 *      containers for host VRAM objects like textures, vertex
225 *      buffers, and depth/stencil buffers.
226 *
227 *      Surfaces are hierarchical:
228 *
229 *        - Surface may have multiple faces (for cube maps)
230 *
231 *          - Each face has a list of mipmap levels
232 *
233 *             - Each mipmap image may have multiple volume
234 *               slices, if the image is three dimensional.
235 *
236 *                - Each slice is a 2D array of 'blocks'
237 *
238 *                   - Each block may be one or more pixels.
239 *                     (Usually 1, more for DXT or YUV formats.)
240 *
241 *      Surfaces are generic host VRAM objects. The SVGA3D device
242 *      may optimize surfaces according to the format they were
243 *      created with, but this format does not limit the ways in
244 *      which the surface may be used. For example, a depth surface
245 *      can be used as a texture, or a floating point image may
246 *      be used as a vertex buffer. Some surface usages may be
247 *      lower performance, due to software emulation, but any
248 *      usage should work with any surface.
249 *
250 *      If 'sid' is already defined, the old surface is deleted
251 *      and this new surface replaces it.
252 *
253 *      Surface IDs are arbitrary small non-negative integers,
254 *      global to the entire SVGA device.
255 *
256 * Results:
257 *      Returns pointers to arrays allocated in the FIFO for 'faces'
258 *      and 'mipSizes'.
259 *
260 * Side effects:
261 *      Begins a FIFO reservation.
262 *
263 *----------------------------------------------------------------------
264 */
265
266enum pipe_error
267SVGA3D_BeginDefineSurface(struct svga_winsys_context *swc,
268                          struct svga_winsys_surface *sid, // IN
269                          SVGA3dSurfaceFlags flags,    // IN
270                          SVGA3dSurfaceFormat format,  // IN
271                          SVGA3dSurfaceFace **faces,   // OUT
272                          SVGA3dSize **mipSizes,       // OUT
273                          uint32 numMipSizes)          // IN
274{
275   SVGA3dCmdDefineSurface *cmd;
276
277   cmd = SVGA3D_FIFOReserve(swc,
278                            SVGA_3D_CMD_SURFACE_DEFINE, sizeof *cmd +
279                            sizeof **mipSizes * numMipSizes, 1);
280   if(!cmd)
281      return PIPE_ERROR_OUT_OF_MEMORY;
282
283   swc->surface_relocation(swc, &cmd->sid, sid, SVGA_RELOC_WRITE);
284   cmd->surfaceFlags = flags;
285   cmd->format = format;
286
287   *faces = &cmd->face[0];
288   *mipSizes = (SVGA3dSize*) &cmd[1];
289
290   memset(*faces, 0, sizeof **faces * SVGA3D_MAX_SURFACE_FACES);
291   memset(*mipSizes, 0, sizeof **mipSizes * numMipSizes);
292
293   return PIPE_OK;
294}
295
296
297/*
298 *----------------------------------------------------------------------
299 *
300 * SVGA3D_DefineSurface2D --
301 *
302 *      This is a simplified version of SVGA3D_BeginDefineSurface(),
303 *      which does not support cube maps, mipmaps, or volume textures.
304 *
305 * Results:
306 *      None.
307 *
308 * Side effects:
309 *      None.
310 *
311 *----------------------------------------------------------------------
312 */
313
314enum pipe_error
315SVGA3D_DefineSurface2D(struct svga_winsys_context *swc,    // IN
316                       struct svga_winsys_surface *sid, // IN
317                       uint32 width,                // IN
318                       uint32 height,               // IN
319                       SVGA3dSurfaceFormat format)  // IN
320{
321   SVGA3dSize *mipSizes;
322   SVGA3dSurfaceFace *faces;
323   enum pipe_error ret;
324
325   ret = SVGA3D_BeginDefineSurface(swc,
326                                   sid, 0, format, &faces, &mipSizes, 1);
327   if(ret != PIPE_OK)
328      return ret;
329
330   faces[0].numMipLevels = 1;
331
332   mipSizes[0].width = width;
333   mipSizes[0].height = height;
334   mipSizes[0].depth = 1;
335
336   swc->commit(swc);;
337
338   return PIPE_OK;
339}
340
341
342/*
343 *----------------------------------------------------------------------
344 *
345 * SVGA3D_DestroySurface --
346 *
347 *      Release the host VRAM encapsulated by a particular surface ID.
348 *
349 * Results:
350 *      None.
351 *
352 * Side effects:
353 *      None.
354 *
355 *----------------------------------------------------------------------
356 */
357
358enum pipe_error
359SVGA3D_DestroySurface(struct svga_winsys_context *swc,
360                      struct svga_winsys_surface *sid)  // IN
361{
362   SVGA3dCmdDestroySurface *cmd;
363
364   cmd = SVGA3D_FIFOReserve(swc,
365                            SVGA_3D_CMD_SURFACE_DESTROY, sizeof *cmd, 1);
366   if(!cmd)
367      return PIPE_ERROR_OUT_OF_MEMORY;
368
369   swc->surface_relocation(swc, &cmd->sid, sid, SVGA_RELOC_READ);
370   swc->commit(swc);;
371
372   return PIPE_OK;
373}
374
375
376/*
377 *----------------------------------------------------------------------
378 *
379 * SVGA3D_SurfaceDMA--
380 *
381 *      Emit a SURFACE_DMA command.
382 *
383 *      When the SVGA3D device asynchronously processes this FIFO
384 *      command, a DMA operation is performed between host VRAM and
385 *      a generic SVGAGuestPtr. The guest pointer may refer to guest
386 *      VRAM (provided by the SVGA PCI device) or to guest system
387 *      memory that has been set up as a Guest Memory Region (GMR)
388 *      by the SVGA device.
389 *
390 *      The guest's DMA buffer must remain valid (not freed, paged out,
391 *      or overwritten) until the host has finished processing this
392 *      command. The guest can determine that the host has finished
393 *      by using the SVGA device's FIFO Fence mechanism.
394 *
395 *      The guest's image buffer can be an arbitrary size and shape.
396 *      Guest image data is interpreted according to the SVGA3D surface
397 *      format specified when the surface was defined.
398 *
399 *      The caller may optionally define the guest image's pitch.
400 *      guestImage->pitch can either be zero (assume image is tightly
401 *      packed) or it must be the number of bytes between vertically
402 *      adjacent image blocks.
403 *
404 *      The provided copybox list specifies which regions of the source
405 *      image are to be copied, and where they appear on the destination.
406 *
407 *      NOTE: srcx/srcy are always on the guest image and x/y are
408 *      always on the host image, regardless of the actual transfer
409 *      direction!
410 *
411 *      For efficiency, the SVGA3D device is free to copy more data
412 *      than specified. For example, it may round copy boxes outwards
413 *      such that they lie on particular alignment boundaries.
414 *
415 *----------------------------------------------------------------------
416 */
417
418enum pipe_error
419SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
420                  struct svga_transfer *st,         // IN
421                  SVGA3dTransferType transfer,      // IN
422                  const SVGA3dCopyBox *boxes,       // IN
423                  uint32 numBoxes,                  // IN
424                  SVGA3dSurfaceDMAFlags flags)      // IN
425{
426   struct svga_texture *texture = svga_texture(st->base.resource);
427   SVGA3dCmdSurfaceDMA *cmd;
428   SVGA3dCmdSurfaceDMASuffix *pSuffix;
429   uint32 boxesSize = sizeof *boxes * numBoxes;
430   unsigned region_flags;
431   unsigned surface_flags;
432
433   if(transfer == SVGA3D_WRITE_HOST_VRAM) {
434      region_flags = SVGA_RELOC_READ;
435      surface_flags = SVGA_RELOC_WRITE;
436   }
437   else if(transfer == SVGA3D_READ_HOST_VRAM) {
438      region_flags = SVGA_RELOC_WRITE;
439      surface_flags = SVGA_RELOC_READ;
440   }
441   else {
442      assert(0);
443      return PIPE_ERROR_BAD_INPUT;
444   }
445
446   cmd = SVGA3D_FIFOReserve(swc,
447                            SVGA_3D_CMD_SURFACE_DMA,
448                            sizeof *cmd + boxesSize + sizeof *pSuffix,
449                            2);
450   if(!cmd)
451      return PIPE_ERROR_OUT_OF_MEMORY;
452
453   swc->region_relocation(swc, &cmd->guest.ptr, st->hwbuf, 0, region_flags);
454   cmd->guest.pitch = st->base.stride;
455
456   swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags);
457   cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
458   cmd->host.mipmap = st->base.level;
459
460   cmd->transfer = transfer;
461
462   memcpy(&cmd[1], boxes, boxesSize);
463
464   pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize);
465   pSuffix->suffixSize = sizeof *pSuffix;
466   pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride;
467   pSuffix->flags = flags;
468
469   swc->commit(swc);
470
471   return PIPE_OK;
472}
473
474
475enum pipe_error
476SVGA3D_BufferDMA(struct svga_winsys_context *swc,
477                 struct svga_winsys_buffer *guest,
478                 struct svga_winsys_surface *host,
479                 SVGA3dTransferType transfer,      // IN
480                 uint32 size,                      // IN
481                 uint32 guest_offset,              // IN
482                 uint32 host_offset,               // IN
483                 SVGA3dSurfaceDMAFlags flags)      // IN
484{
485   SVGA3dCmdSurfaceDMA *cmd;
486   SVGA3dCopyBox *box;
487   SVGA3dCmdSurfaceDMASuffix *pSuffix;
488   unsigned region_flags;
489   unsigned surface_flags;
490
491   if(transfer == SVGA3D_WRITE_HOST_VRAM) {
492      region_flags = SVGA_RELOC_READ;
493      surface_flags = SVGA_RELOC_WRITE;
494   }
495   else if(transfer == SVGA3D_READ_HOST_VRAM) {
496      region_flags = SVGA_RELOC_WRITE;
497      surface_flags = SVGA_RELOC_READ;
498   }
499   else {
500      assert(0);
501      return PIPE_ERROR_BAD_INPUT;
502   }
503
504   cmd = SVGA3D_FIFOReserve(swc,
505                            SVGA_3D_CMD_SURFACE_DMA,
506                            sizeof *cmd + sizeof *box + sizeof *pSuffix,
507                            2);
508   if(!cmd)
509      return PIPE_ERROR_OUT_OF_MEMORY;
510
511   swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
512   cmd->guest.pitch = 0;
513
514   swc->surface_relocation(swc, &cmd->host.sid, host, surface_flags);
515   cmd->host.face = 0;
516   cmd->host.mipmap = 0;
517
518   cmd->transfer = transfer;
519
520   box = (SVGA3dCopyBox *)&cmd[1];
521   box->x = host_offset;
522   box->y = 0;
523   box->z = 0;
524   box->w = size;
525   box->h = 1;
526   box->d = 1;
527   box->srcx = guest_offset;
528   box->srcy = 0;
529   box->srcz = 0;
530
531   pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box);
532   pSuffix->suffixSize = sizeof *pSuffix;
533   pSuffix->maximumOffset = guest_offset + size;
534   pSuffix->flags = flags;
535
536   swc->commit(swc);
537
538   return PIPE_OK;
539}
540
541
542/*
543 *----------------------------------------------------------------------
544 *
545 * SVGA3D_SetRenderTarget --
546 *
547 *      Bind a surface object to a particular render target attachment
548 *      point on the current context. Render target attachment points
549 *      exist for color buffers, a depth buffer, and a stencil buffer.
550 *
551 *      The SVGA3D device is quite lenient about the types of surfaces
552 *      that may be used as render targets. The color buffers must
553 *      all be the same size, but the depth and stencil buffers do not
554 *      have to be the same size as the color buffer. All attachments
555 *      are optional.
556 *
557 *      Some combinations of render target formats may require software
558 *      emulation, depending on the capabilities of the host graphics
559 *      API and graphics hardware.
560 *
561 * Results:
562 *      None.
563 *
564 * Side effects:
565 *      None.
566 *
567 *----------------------------------------------------------------------
568 */
569
570enum pipe_error
571SVGA3D_SetRenderTarget(struct svga_winsys_context *swc,
572                       SVGA3dRenderTargetType type,   // IN
573                       struct pipe_surface *surface)  // IN
574{
575   SVGA3dCmdSetRenderTarget *cmd;
576
577   cmd = SVGA3D_FIFOReserve(swc,
578                            SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd, 1);
579   if(!cmd)
580      return PIPE_ERROR_OUT_OF_MEMORY;
581
582
583   cmd->cid = swc->cid;
584
585   cmd->type = type;
586
587   surface_to_surfaceid(swc, surface, &cmd->target, SVGA_RELOC_WRITE);
588
589   swc->commit(swc);
590
591   return PIPE_OK;
592}
593
594
595
596
597
598
599/*
600 *----------------------------------------------------------------------
601 *
602 * SVGA3D_DefineShader --
603 *
604 *      Upload the bytecode for a new shader. The bytecode is "SVGA3D
605 *      format", which is theoretically a binary-compatible superset
606 *      of Microsoft's DirectX shader bytecode. In practice, the
607 *      SVGA3D bytecode doesn't yet have any extensions to DirectX's
608 *      bytecode format.
609 *
610 *      The SVGA3D device supports shader models 1.1 through 2.0.
611 *
612 *      The caller chooses a shader ID (small positive integer) by
613 *      which this shader will be identified in future commands. This
614 *      ID is in a namespace which is per-context and per-shader-type.
615 *
616 *      'bytecodeLen' is specified in bytes. It must be a multiple of 4.
617 *
618 * Results:
619 *      None.
620 *
621 * Side effects:
622 *      None.
623 *
624 *----------------------------------------------------------------------
625 */
626
627enum pipe_error
628SVGA3D_DefineShader(struct svga_winsys_context *swc,
629                    uint32 shid,                  // IN
630                    SVGA3dShaderType type,        // IN
631                    const uint32 *bytecode,       // IN
632                    uint32 bytecodeLen)           // IN
633{
634   SVGA3dCmdDefineShader *cmd;
635
636   assert(bytecodeLen % 4 == 0);
637
638   cmd = SVGA3D_FIFOReserve(swc,
639                            SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen,
640                            0);
641   if(!cmd)
642      return PIPE_ERROR_OUT_OF_MEMORY;
643
644   cmd->cid = swc->cid;
645   cmd->shid = shid;
646   cmd->type = type;
647   memcpy(&cmd[1], bytecode, bytecodeLen);
648   swc->commit(swc);
649
650   return PIPE_OK;
651}
652
653
654/*
655 *----------------------------------------------------------------------
656 *
657 * SVGA3D_DestroyShader --
658 *
659 *      Delete a shader that was created by SVGA3D_DefineShader. If
660 *      the shader was the current vertex or pixel shader for its
661 *      context, rendering results are undefined until a new shader is
662 *      bound.
663 *
664 * Results:
665 *      None.
666 *
667 * Side effects:
668 *      None.
669 *
670 *----------------------------------------------------------------------
671 */
672
673enum pipe_error
674SVGA3D_DestroyShader(struct svga_winsys_context *swc,
675                     uint32 shid,            // IN
676                     SVGA3dShaderType type)  // IN
677{
678   SVGA3dCmdDestroyShader *cmd;
679
680   cmd = SVGA3D_FIFOReserve(swc,
681                            SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd,
682                            0);
683   if(!cmd)
684      return PIPE_ERROR_OUT_OF_MEMORY;
685
686   cmd->cid = swc->cid;
687   cmd->shid = shid;
688   cmd->type = type;
689   swc->commit(swc);
690
691   return PIPE_OK;
692}
693
694
695/*
696 *----------------------------------------------------------------------
697 *
698 * SVGA3D_SetShaderConst --
699 *
700 *      Set the value of a shader constant.
701 *
702 *      Shader constants are analogous to uniform variables in GLSL,
703 *      except that they belong to the render context rather than to
704 *      an individual shader.
705 *
706 *      Constants may have one of three types: A 4-vector of floats,
707 *      a 4-vector of integers, or a single boolean flag.
708 *
709 * Results:
710 *      None.
711 *
712 * Side effects:
713 *      None.
714 *
715 *----------------------------------------------------------------------
716 */
717
718enum pipe_error
719SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
720                      uint32 reg,                   // IN
721                      SVGA3dShaderType type,        // IN
722                      SVGA3dShaderConstType ctype,  // IN
723                      const void *value)            // IN
724{
725   SVGA3dCmdSetShaderConst *cmd;
726
727   cmd = SVGA3D_FIFOReserve(swc,
728                            SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd,
729                            0);
730   if(!cmd)
731      return PIPE_ERROR_OUT_OF_MEMORY;
732
733   cmd->cid = swc->cid;
734   cmd->reg = reg;
735   cmd->type = type;
736   cmd->ctype = ctype;
737
738   switch (ctype) {
739
740   case SVGA3D_CONST_TYPE_FLOAT:
741   case SVGA3D_CONST_TYPE_INT:
742      memcpy(&cmd->values, value, sizeof cmd->values);
743      break;
744
745   case SVGA3D_CONST_TYPE_BOOL:
746      memset(&cmd->values, 0, sizeof cmd->values);
747      cmd->values[0] = *(uint32*)value;
748      break;
749
750   default:
751      assert(0);
752      break;
753
754   }
755   swc->commit(swc);
756
757   return PIPE_OK;
758}
759
760
761/*
762 *----------------------------------------------------------------------
763 *
764 * SVGA3D_SetShaderConsts --
765 *
766 *      Set the value of successive shader constants.
767 *
768 *      Shader constants are analogous to uniform variables in GLSL,
769 *      except that they belong to the render context rather than to
770 *      an individual shader.
771 *
772 *      Constants may have one of three types: A 4-vector of floats,
773 *      a 4-vector of integers, or a single boolean flag.
774 *
775 * Results:
776 *      None.
777 *
778 * Side effects:
779 *      None.
780 *
781 *----------------------------------------------------------------------
782 */
783
784enum pipe_error
785SVGA3D_SetShaderConsts(struct svga_winsys_context *swc,
786                        uint32 reg,                   // IN
787                        uint32 numRegs,               // IN
788                        SVGA3dShaderType type,        // IN
789                        SVGA3dShaderConstType ctype,  // IN
790                        const void *values)           // IN
791{
792   SVGA3dCmdSetShaderConst *cmd;
793
794   cmd = SVGA3D_FIFOReserve(swc,
795                            SVGA_3D_CMD_SET_SHADER_CONST,
796                            sizeof *cmd + (numRegs - 1) * sizeof cmd->values,
797                            0);
798   if(!cmd)
799      return PIPE_ERROR_OUT_OF_MEMORY;
800
801   cmd->cid = swc->cid;
802   cmd->reg = reg;
803   cmd->type = type;
804   cmd->ctype = ctype;
805
806   memcpy(&cmd->values, values, numRegs * sizeof cmd->values);
807
808   swc->commit(swc);
809
810   return PIPE_OK;
811}
812
813
814
815
816
817/*
818 *----------------------------------------------------------------------
819 *
820 * SVGA3D_SetShader --
821 *
822 *      Switch active shaders. This binds a new vertex or pixel shader
823 *      to the specified context.
824 *
825 *      A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
826 *      back to the fixed function vertex or pixel pipeline.
827 *
828 * Results:
829 *      None.
830 *
831 * Side effects:
832 *      None.
833 *
834 *----------------------------------------------------------------------
835 */
836
837enum pipe_error
838SVGA3D_SetShader(struct svga_winsys_context *swc,
839                 SVGA3dShaderType type,  // IN
840                 uint32 shid)            // IN
841{
842   SVGA3dCmdSetShader *cmd;
843
844   cmd = SVGA3D_FIFOReserve(swc,
845                            SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
846                            0);
847   if(!cmd)
848      return PIPE_ERROR_OUT_OF_MEMORY;
849
850   cmd->cid = swc->cid;
851   cmd->type = type;
852   cmd->shid = shid;
853   swc->commit(swc);
854
855   return PIPE_OK;
856}
857
858
859/*
860 *----------------------------------------------------------------------
861 *
862 * SVGA3D_BeginClear --
863 *
864 *      Begin a CLEAR command. This reserves space for it in the FIFO,
865 *      and returns a pointer to the command's rectangle array.  This
866 *      function must be paired with SVGA_FIFOCommitAll().
867 *
868 *      Clear is a rendering operation which fills a list of
869 *      rectangles with constant values on all render target types
870 *      indicated by 'flags'.
871 *
872 *      Clear is not affected by clipping, depth test, or other
873 *      render state which affects the fragment pipeline.
874 *
875 * Results:
876 *      None.
877 *
878 * Side effects:
879 *      May write to attached render target surfaces.
880 *
881 *----------------------------------------------------------------------
882 */
883
884enum pipe_error
885SVGA3D_BeginClear(struct svga_winsys_context *swc,
886                  SVGA3dClearFlag flags,  // IN
887                  uint32 color,           // IN
888                  float depth,            // IN
889                  uint32 stencil,         // IN
890                  SVGA3dRect **rects,     // OUT
891                  uint32 numRects)        // IN
892{
893   SVGA3dCmdClear *cmd;
894
895   cmd = SVGA3D_FIFOReserve(swc,
896                            SVGA_3D_CMD_CLEAR,
897                            sizeof *cmd + sizeof **rects * numRects,
898                            0);
899   if(!cmd)
900      return PIPE_ERROR_OUT_OF_MEMORY;
901
902   cmd->cid = swc->cid;
903   cmd->clearFlag = flags;
904   cmd->color = color;
905   cmd->depth = depth;
906   cmd->stencil = stencil;
907   *rects = (SVGA3dRect*) &cmd[1];
908
909   return PIPE_OK;
910}
911
912
913/*
914 *----------------------------------------------------------------------
915 *
916 * SVGA3D_ClearRect --
917 *
918 *      This is a simplified version of SVGA3D_BeginClear().
919 *
920 * Results:
921 *      None.
922 *
923 * Side effects:
924 *      None.
925 *
926 *----------------------------------------------------------------------
927 */
928
929enum pipe_error
930SVGA3D_ClearRect(struct svga_winsys_context *swc,
931                 SVGA3dClearFlag flags,  // IN
932                 uint32 color,           // IN
933                 float depth,            // IN
934                 uint32 stencil,         // IN
935                 uint32 x,               // IN
936                 uint32 y,               // IN
937                 uint32 w,               // IN
938                 uint32 h)               // IN
939{
940   SVGA3dRect *rect;
941   enum pipe_error ret;
942
943   ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
944   if(ret != PIPE_OK)
945      return PIPE_ERROR_OUT_OF_MEMORY;
946
947   memset(rect, 0, sizeof *rect);
948   rect->x = x;
949   rect->y = y;
950   rect->w = w;
951   rect->h = h;
952   swc->commit(swc);
953
954   return PIPE_OK;
955}
956
957
958/*
959 *----------------------------------------------------------------------
960 *
961 * SVGA3D_BeginDrawPrimitives --
962 *
963 *      Begin a DRAW_PRIMITIVES command. This reserves space for it in
964 *      the FIFO, and returns a pointer to the command's arrays.
965 *      This function must be paired with SVGA_FIFOCommitAll().
966 *
967 *      Drawing commands consist of two variable-length arrays:
968 *      SVGA3dVertexDecl elements declare a set of vertex buffers to
969 *      use while rendering, and SVGA3dPrimitiveRange elements specify
970 *      groups of primitives each with an optional index buffer.
971 *
972 *      The decls and ranges arrays are initialized to zero.
973 *
974 * Results:
975 *      None.
976 *
977 * Side effects:
978 *      May write to attached render target surfaces.
979 *
980 *----------------------------------------------------------------------
981 */
982
983enum pipe_error
984SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
985                           SVGA3dVertexDecl **decls,      // OUT
986                           uint32 numVertexDecls,         // IN
987                           SVGA3dPrimitiveRange **ranges, // OUT
988                           uint32 numRanges)              // IN
989{
990   SVGA3dCmdDrawPrimitives *cmd;
991   SVGA3dVertexDecl *declArray;
992   SVGA3dPrimitiveRange *rangeArray;
993   uint32 declSize = sizeof **decls * numVertexDecls;
994   uint32 rangeSize = sizeof **ranges * numRanges;
995
996   cmd = SVGA3D_FIFOReserve(swc,
997                            SVGA_3D_CMD_DRAW_PRIMITIVES,
998                            sizeof *cmd + declSize + rangeSize,
999                            numVertexDecls + numRanges);
1000   if(!cmd)
1001      return PIPE_ERROR_OUT_OF_MEMORY;
1002
1003   cmd->cid = swc->cid;
1004   cmd->numVertexDecls = numVertexDecls;
1005   cmd->numRanges = numRanges;
1006
1007   declArray = (SVGA3dVertexDecl*) &cmd[1];
1008   rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
1009
1010   memset(declArray, 0, declSize);
1011   memset(rangeArray, 0, rangeSize);
1012
1013   *decls = declArray;
1014   *ranges = rangeArray;
1015
1016   return PIPE_OK;
1017}
1018
1019
1020/*
1021 *----------------------------------------------------------------------
1022 *
1023 * SVGA3D_BeginSurfaceCopy --
1024 *
1025 *      Begin a SURFACE_COPY command. This reserves space for it in
1026 *      the FIFO, and returns a pointer to the command's arrays.  This
1027 *      function must be paired with SVGA_FIFOCommitAll().
1028 *
1029 *      The box array is initialized with zeroes.
1030 *
1031 * Results:
1032 *      None.
1033 *
1034 * Side effects:
1035 *      Asynchronously copies a list of boxes from surface to surface.
1036 *
1037 *----------------------------------------------------------------------
1038 */
1039
1040enum pipe_error
1041SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
1042                        struct pipe_surface *src,    // IN
1043                        struct pipe_surface *dest,   // IN
1044                        SVGA3dCopyBox **boxes,       // OUT
1045                        uint32 numBoxes)             // IN
1046{
1047   SVGA3dCmdSurfaceCopy *cmd;
1048   uint32 boxesSize = sizeof **boxes * numBoxes;
1049
1050   cmd = SVGA3D_FIFOReserve(swc,
1051                            SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
1052                            2);
1053   if(!cmd)
1054      return PIPE_ERROR_OUT_OF_MEMORY;
1055
1056   surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1057   surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1058   *boxes = (SVGA3dCopyBox*) &cmd[1];
1059
1060   memset(*boxes, 0, boxesSize);
1061
1062   return PIPE_OK;
1063}
1064
1065
1066/*
1067 *----------------------------------------------------------------------
1068 *
1069 * SVGA3D_SurfaceStretchBlt --
1070 *
1071 *      Issue a SURFACE_STRETCHBLT command: an asynchronous
1072 *      surface-to-surface blit, with scaling.
1073 *
1074 * Results:
1075 *      None.
1076 *
1077 * Side effects:
1078 *      Asynchronously copies one box from surface to surface.
1079 *
1080 *----------------------------------------------------------------------
1081 */
1082
1083enum pipe_error
1084SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
1085                         struct pipe_surface *src,    // IN
1086                         struct pipe_surface *dest,   // IN
1087                         SVGA3dBox *boxSrc,           // IN
1088                         SVGA3dBox *boxDest,          // IN
1089                         SVGA3dStretchBltMode mode)   // IN
1090{
1091   SVGA3dCmdSurfaceStretchBlt *cmd;
1092
1093   cmd = SVGA3D_FIFOReserve(swc,
1094                            SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
1095                            2);
1096   if(!cmd)
1097      return PIPE_ERROR_OUT_OF_MEMORY;
1098
1099   surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
1100   surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
1101   cmd->boxSrc = *boxSrc;
1102   cmd->boxDest = *boxDest;
1103   cmd->mode = mode;
1104   swc->commit(swc);
1105
1106   return PIPE_OK;
1107}
1108
1109
1110/*
1111 *----------------------------------------------------------------------
1112 *
1113 * SVGA3D_SetViewport --
1114 *
1115 *      Set the current context's viewport rectangle. The viewport
1116 *      is clipped to the dimensions of the current render target,
1117 *      then all rendering is clipped to the viewport.
1118 *
1119 * Results:
1120 *      None.
1121 *
1122 * Side effects:
1123 *      None.
1124 *
1125 *----------------------------------------------------------------------
1126 */
1127
1128enum pipe_error
1129SVGA3D_SetViewport(struct svga_winsys_context *swc,
1130                   SVGA3dRect *rect)  // IN
1131{
1132   SVGA3dCmdSetViewport *cmd;
1133
1134   cmd = SVGA3D_FIFOReserve(swc,
1135                            SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
1136                            0);
1137   if(!cmd)
1138      return PIPE_ERROR_OUT_OF_MEMORY;
1139
1140   cmd->cid = swc->cid;
1141   cmd->rect = *rect;
1142   swc->commit(swc);
1143
1144   return PIPE_OK;
1145}
1146
1147
1148
1149
1150/*
1151 *----------------------------------------------------------------------
1152 *
1153 * SVGA3D_SetScissorRect --
1154 *
1155 *      Set the current context's scissor rectangle. If scissor
1156 *      is enabled then all rendering is clipped to the scissor.
1157 *
1158 * Results:
1159 *      None.
1160 *
1161 * Side effects:
1162 *      None.
1163 *
1164 *----------------------------------------------------------------------
1165 */
1166
1167enum pipe_error
1168SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
1169                      SVGA3dRect *rect)  // IN
1170{
1171   SVGA3dCmdSetScissorRect *cmd;
1172
1173   cmd = SVGA3D_FIFOReserve(swc,
1174                            SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
1175                            0);
1176   if(!cmd)
1177      return PIPE_ERROR_OUT_OF_MEMORY;
1178
1179   cmd->cid = swc->cid;
1180   cmd->rect = *rect;
1181   swc->commit(swc);
1182
1183   return PIPE_OK;
1184}
1185
1186/*
1187 *----------------------------------------------------------------------
1188 *
1189 * SVGA3D_SetClipPlane --
1190 *
1191 *      Set one of the current context's clip planes. If the clip
1192 *      plane is enabled then all 3d rendering is clipped to against
1193 *      the plane.
1194 *
1195 * Results:
1196 *      None.
1197 *
1198 * Side effects:
1199 *      None.
1200 *
1201 *----------------------------------------------------------------------
1202 */
1203
1204enum pipe_error
1205SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
1206                    uint32 index, const float *plane)
1207{
1208   SVGA3dCmdSetClipPlane *cmd;
1209
1210   cmd = SVGA3D_FIFOReserve(swc,
1211                            SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
1212                            0);
1213   if(!cmd)
1214      return PIPE_ERROR_OUT_OF_MEMORY;
1215
1216   cmd->cid = swc->cid;
1217   cmd->index = index;
1218   cmd->plane[0] = plane[0];
1219   cmd->plane[1] = plane[1];
1220   cmd->plane[2] = plane[2];
1221   cmd->plane[3] = plane[3];
1222   swc->commit(swc);
1223
1224   return PIPE_OK;
1225}
1226
1227/*
1228 *----------------------------------------------------------------------
1229 *
1230 * SVGA3D_SetZRange --
1231 *
1232 *      Set the range of the depth buffer to use. 'min' and 'max'
1233 *      are values between 0.0 and 1.0.
1234 *
1235 * Results:
1236 *      None.
1237 *
1238 * Side effects:
1239 *      None.
1240 *
1241 *----------------------------------------------------------------------
1242 */
1243
1244enum pipe_error
1245SVGA3D_SetZRange(struct svga_winsys_context *swc,
1246                 float zMin,  // IN
1247                 float zMax)  // IN
1248{
1249   SVGA3dCmdSetZRange *cmd;
1250
1251   cmd = SVGA3D_FIFOReserve(swc,
1252                            SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
1253                            0);
1254   if(!cmd)
1255      return PIPE_ERROR_OUT_OF_MEMORY;
1256
1257   cmd->cid = swc->cid;
1258   cmd->zRange.min = zMin;
1259   cmd->zRange.max = zMax;
1260   swc->commit(swc);
1261
1262   return PIPE_OK;
1263}
1264
1265
1266/*
1267 *----------------------------------------------------------------------
1268 *
1269 * SVGA3D_BeginSetTextureState --
1270 *
1271 *      Begin a SETTEXTURESTATE command. This reserves space for it in
1272 *      the FIFO, and returns a pointer to the command's texture state
1273 *      array.  This function must be paired with SVGA_FIFOCommitAll().
1274 *
1275 *      This command sets rendering state which is per-texture-unit.
1276 *
1277 *      XXX: Individual texture states need documentation. However,
1278 *           they are very similar to the texture states defined by
1279 *           Direct3D. The D3D documentation is a good starting point
1280 *           for understanding SVGA3D texture states.
1281 *
1282 * Results:
1283 *      None.
1284 *
1285 * Side effects:
1286 *      None.
1287 *
1288 *----------------------------------------------------------------------
1289 */
1290
1291enum pipe_error
1292SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
1293                            SVGA3dTextureState **states,  // OUT
1294                            uint32 numStates)             // IN
1295{
1296   SVGA3dCmdSetTextureState *cmd;
1297
1298   cmd = SVGA3D_FIFOReserve(swc,
1299                            SVGA_3D_CMD_SETTEXTURESTATE,
1300                            sizeof *cmd + sizeof **states * numStates,
1301                            numStates);
1302   if(!cmd)
1303      return PIPE_ERROR_OUT_OF_MEMORY;
1304
1305   cmd->cid = swc->cid;
1306   *states = (SVGA3dTextureState*) &cmd[1];
1307
1308   return PIPE_OK;
1309}
1310
1311
1312/*
1313 *----------------------------------------------------------------------
1314 *
1315 * SVGA3D_BeginSetRenderState --
1316 *
1317 *      Begin a SETRENDERSTATE command. This reserves space for it in
1318 *      the FIFO, and returns a pointer to the command's texture state
1319 *      array.  This function must be paired with SVGA_FIFOCommitAll().
1320 *
1321 *      This command sets rendering state which is global to the context.
1322 *
1323 *      XXX: Individual render states need documentation. However,
1324 *           they are very similar to the render states defined by
1325 *           Direct3D. The D3D documentation is a good starting point
1326 *           for understanding SVGA3D render states.
1327 *
1328 * Results:
1329 *      None.
1330 *
1331 * Side effects:
1332 *      None.
1333 *
1334 *----------------------------------------------------------------------
1335 */
1336
1337enum pipe_error
1338SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
1339                           SVGA3dRenderState **states,  // OUT
1340                           uint32 numStates)            // IN
1341{
1342   SVGA3dCmdSetRenderState *cmd;
1343
1344   cmd = SVGA3D_FIFOReserve(swc,
1345                            SVGA_3D_CMD_SETRENDERSTATE,
1346                            sizeof *cmd + sizeof **states * numStates,
1347                            0);
1348   if(!cmd)
1349      return PIPE_ERROR_OUT_OF_MEMORY;
1350
1351   cmd->cid = swc->cid;
1352   *states = (SVGA3dRenderState*) &cmd[1];
1353
1354   return PIPE_OK;
1355}
1356
1357
1358/*
1359 *----------------------------------------------------------------------
1360 *
1361 * SVGA3D_BeginQuery--
1362 *
1363 *      Issues a SVGA_3D_CMD_BEGIN_QUERY command.
1364 *
1365 * Results:
1366 *      None.
1367 *
1368 * Side effects:
1369 *      Commits space in the FIFO memory.
1370 *
1371 *----------------------------------------------------------------------
1372 */
1373
1374enum pipe_error
1375SVGA3D_BeginQuery(struct svga_winsys_context *swc,
1376                  SVGA3dQueryType type) // IN
1377{
1378   SVGA3dCmdBeginQuery *cmd;
1379
1380   cmd = SVGA3D_FIFOReserve(swc,
1381                            SVGA_3D_CMD_BEGIN_QUERY,
1382                            sizeof *cmd,
1383                            0);
1384   if(!cmd)
1385      return PIPE_ERROR_OUT_OF_MEMORY;
1386
1387   cmd->cid = swc->cid;
1388   cmd->type = type;
1389
1390   swc->commit(swc);
1391
1392   return PIPE_OK;
1393}
1394
1395
1396/*
1397 *----------------------------------------------------------------------
1398 *
1399 * SVGA3D_EndQuery--
1400 *
1401 *      Issues a SVGA_3D_CMD_END_QUERY command.
1402 *
1403 * Results:
1404 *      None.
1405 *
1406 * Side effects:
1407 *      Commits space in the FIFO memory.
1408 *
1409 *----------------------------------------------------------------------
1410 */
1411
1412enum pipe_error
1413SVGA3D_EndQuery(struct svga_winsys_context *swc,
1414                SVGA3dQueryType type,              // IN
1415                struct svga_winsys_buffer *buffer) // IN/OUT
1416{
1417   SVGA3dCmdEndQuery *cmd;
1418
1419   cmd = SVGA3D_FIFOReserve(swc,
1420                            SVGA_3D_CMD_END_QUERY,
1421                            sizeof *cmd,
1422                            1);
1423   if(!cmd)
1424      return PIPE_ERROR_OUT_OF_MEMORY;
1425
1426   cmd->cid = swc->cid;
1427   cmd->type = type;
1428
1429   swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1430                          SVGA_RELOC_WRITE);
1431
1432   swc->commit(swc);
1433
1434   return PIPE_OK;
1435}
1436
1437
1438/*
1439 *----------------------------------------------------------------------
1440 *
1441 * SVGA3D_WaitForQuery--
1442 *
1443 *      Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command.  This reserves space
1444 *      for it in the FIFO.  This doesn't actually wait for the query to
1445 *      finish but instead tells the host to start a wait at the driver
1446 *      level.  The caller can wait on the status variable in the
1447 *      guestPtr memory or send an insert fence instruction after this
1448 *      command and wait on the fence.
1449 *
1450 * Results:
1451 *      None.
1452 *
1453 * Side effects:
1454 *      Commits space in the FIFO memory.
1455 *
1456 *----------------------------------------------------------------------
1457 */
1458
1459enum pipe_error
1460SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
1461                    SVGA3dQueryType type,              // IN
1462                    struct svga_winsys_buffer *buffer) // IN/OUT
1463{
1464   SVGA3dCmdWaitForQuery *cmd;
1465
1466   cmd = SVGA3D_FIFOReserve(swc,
1467                            SVGA_3D_CMD_WAIT_FOR_QUERY,
1468                            sizeof *cmd,
1469                            1);
1470   if(!cmd)
1471      return PIPE_ERROR_OUT_OF_MEMORY;
1472
1473   cmd->cid = swc->cid;
1474   cmd->type = type;
1475
1476   swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1477                          SVGA_RELOC_WRITE);
1478
1479   swc->commit(swc);
1480
1481   return PIPE_OK;
1482}
1483