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