04307d17fe0cd59fe078f6a6887bdaaa8ce4ee96
[profile/ivi/mesa.git] / src / gallium / drivers / svga / svga_cmd.c
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_screen_buffer.h"
35 #include "svga_screen_texture.h"
36 #include "svga_cmd.h"
37
38 /*
39  *----------------------------------------------------------------------
40  *
41  * surface_to_surfaceid --
42  *
43  *      Utility function for surface ids.
44  *      Can handle null surface. Does a surface_reallocation so you need
45  *      to have allocated the fifo space before converting.
46  *
47  * Results:
48  *      id is filld out.
49  *
50  * Side effects:
51  *      One surface relocation is preformed for texture handle.
52  *
53  *----------------------------------------------------------------------
54  */
55
56 static INLINE
57 void surface_to_surfaceid(struct svga_winsys_context *swc, // IN
58                           struct pipe_surface *surface,    // IN
59                           SVGA3dSurfaceImageId *id,        // OUT
60                           unsigned flags)                  // IN
61 {
62    if(surface) {
63       struct svga_surface *s = svga_surface(surface);
64       swc->surface_relocation(swc, &id->sid, s->handle, flags);
65       id->face = s->real_face; /* faces have the same order */
66       id->mipmap = s->real_level;
67    }
68    else {
69       id->sid = SVGA3D_INVALID_ID;
70       id->face = 0;
71       id->mipmap = 0;
72    }
73 }
74
75
76 /*
77  *----------------------------------------------------------------------
78  *
79  * SVGA3D_FIFOReserve --
80  *
81  *      Reserve space for an SVGA3D FIFO command.
82  *
83  *      The 2D SVGA commands have been around for a while, so they
84  *      have a rather asymmetric structure. The SVGA3D protocol is
85  *      more uniform: each command begins with a header containing the
86  *      command number and the full size.
87  *
88  *      This is a convenience wrapper around SVGA_FIFOReserve. We
89  *      reserve space for the whole command, and write the header.
90  *
91  *      This function must be paired with SVGA_FIFOCommitAll().
92  *
93  * Results:
94  *      Returns a pointer to the space reserved for command-specific
95  *      data. It must be 'cmdSize' bytes long.
96  *
97  * Side effects:
98  *      Begins a FIFO reservation.
99  *
100  *----------------------------------------------------------------------
101  */
102
103 void *
104 SVGA3D_FIFOReserve(struct svga_winsys_context *swc,
105                    uint32 cmd,       // IN
106                    uint32 cmdSize,   // IN
107                    uint32 nr_relocs) // IN
108 {
109    SVGA3dCmdHeader *header;
110
111    header = swc->reserve(swc, sizeof *header + cmdSize, nr_relocs);
112    if(!header)
113       return NULL;
114
115    header->id = cmd;
116    header->size = cmdSize;
117
118    return &header[1];
119 }
120
121
122 void
123 SVGA_FIFOCommitAll(struct svga_winsys_context *swc)
124 {
125    swc->commit(swc);
126 }
127
128
129 /*
130  *----------------------------------------------------------------------
131  *
132  * SVGA3D_DefineContext --
133  *
134  *      Create a new context, to be referred to with the provided ID.
135  *
136  *      Context objects encapsulate all render state, and shader
137  *      objects are per-context.
138  *
139  *      Surfaces are not per-context. The same surface can be shared
140  *      between multiple contexts, and surface operations can occur
141  *      without a context.
142  *
143  *      If the provided context ID already existed, it is redefined.
144  *
145  *      Context IDs are arbitrary small non-negative integers,
146  *      global to the entire SVGA device.
147  *
148  * Results:
149  *      None.
150  *
151  * Side effects:
152  *      None.
153  *
154  *----------------------------------------------------------------------
155  */
156
157 enum pipe_error
158 SVGA3D_DefineContext(struct svga_winsys_context *swc)  // IN
159 {
160    SVGA3dCmdDefineContext *cmd;
161
162    cmd = SVGA3D_FIFOReserve(swc,
163                             SVGA_3D_CMD_CONTEXT_DEFINE, sizeof *cmd, 0);
164    if(!cmd)
165       return PIPE_ERROR_OUT_OF_MEMORY;
166
167    cmd->cid = swc->cid;
168
169    swc->commit(swc);
170    
171    return PIPE_OK;
172 }
173
174
175 /*
176  *----------------------------------------------------------------------
177  *
178  * SVGA3D_DestroyContext --
179  *
180  *      Delete a context created with SVGA3D_DefineContext.
181  *
182  * Results:
183  *      None.
184  *
185  * Side effects:
186  *      None.
187  *
188  *----------------------------------------------------------------------
189  */
190
191 enum pipe_error
192 SVGA3D_DestroyContext(struct svga_winsys_context *swc)  // IN
193 {
194    SVGA3dCmdDestroyContext *cmd;
195    
196    cmd = SVGA3D_FIFOReserve(swc,
197                             SVGA_3D_CMD_CONTEXT_DESTROY, sizeof *cmd, 0);
198    if(!cmd)
199       return PIPE_ERROR_OUT_OF_MEMORY;
200    
201    cmd->cid = swc->cid;
202    
203    swc->commit(swc);
204    
205    return PIPE_OK;
206 }
207
208
209 /*
210  *----------------------------------------------------------------------
211  *
212  * SVGA3D_BeginDefineSurface --
213  *
214  *      Begin a SURFACE_DEFINE command. This reserves space for it in
215  *      the FIFO, and returns pointers to the command's faces and
216  *      mipsizes arrays.
217  *
218  *      This function must be paired with SVGA_FIFOCommitAll().
219  *      The faces and mipSizes arrays are initialized to zero.
220  *
221  *      This creates a "surface" object in the SVGA3D device,
222  *      with the provided surface ID (sid). Surfaces are generic
223  *      containers for host VRAM objects like textures, vertex
224  *      buffers, and depth/stencil buffers.
225  *
226  *      Surfaces are hierarchial:
227  *
228  *        - Surface may have multiple faces (for cube maps)
229  *
230  *          - Each face has a list of mipmap levels
231  *
232  *             - Each mipmap image may have multiple volume
233  *               slices, if the image is three dimensional.
234  *
235  *                - Each slice is a 2D array of 'blocks'
236  *
237  *                   - Each block may be one or more pixels.
238  *                     (Usually 1, more for DXT or YUV formats.)
239  *
240  *      Surfaces are generic host VRAM objects. The SVGA3D device
241  *      may optimize surfaces according to the format they were
242  *      created with, but this format does not limit the ways in
243  *      which the surface may be used. For example, a depth surface
244  *      can be used as a texture, or a floating point image may
245  *      be used as a vertex buffer. Some surface usages may be
246  *      lower performance, due to software emulation, but any
247  *      usage should work with any surface.
248  *
249  *      If 'sid' is already defined, the old surface is deleted
250  *      and this new surface replaces it.
251  *
252  *      Surface IDs are arbitrary small non-negative integers,
253  *      global to the entire SVGA device.
254  *
255  * Results:
256  *      Returns pointers to arrays allocated in the FIFO for 'faces'
257  *      and 'mipSizes'.
258  *
259  * Side effects:
260  *      Begins a FIFO reservation.
261  *
262  *----------------------------------------------------------------------
263  */
264
265 enum pipe_error
266 SVGA3D_BeginDefineSurface(struct svga_winsys_context *swc,
267                           struct svga_winsys_surface *sid, // IN
268                           SVGA3dSurfaceFlags flags,    // IN
269                           SVGA3dSurfaceFormat format,  // IN
270                           SVGA3dSurfaceFace **faces,   // OUT
271                           SVGA3dSize **mipSizes,       // OUT
272                           uint32 numMipSizes)          // IN
273 {
274    SVGA3dCmdDefineSurface *cmd;
275
276    cmd = SVGA3D_FIFOReserve(swc,
277                             SVGA_3D_CMD_SURFACE_DEFINE, sizeof *cmd +
278                             sizeof **mipSizes * numMipSizes, 1);
279    if(!cmd)
280       return PIPE_ERROR_OUT_OF_MEMORY;
281
282    swc->surface_relocation(swc, &cmd->sid, sid, PIPE_BUFFER_USAGE_GPU_WRITE);
283    cmd->surfaceFlags = flags;
284    cmd->format = format;
285
286    *faces = &cmd->face[0];
287    *mipSizes = (SVGA3dSize*) &cmd[1];
288
289    memset(*faces, 0, sizeof **faces * SVGA3D_MAX_SURFACE_FACES);
290    memset(*mipSizes, 0, sizeof **mipSizes * numMipSizes);
291    
292    return PIPE_OK;
293 }
294
295
296 /*
297  *----------------------------------------------------------------------
298  *
299  * SVGA3D_DefineSurface2D --
300  *
301  *      This is a simplified version of SVGA3D_BeginDefineSurface(),
302  *      which does not support cube maps, mipmaps, or volume textures.
303  *
304  * Results:
305  *      None.
306  *
307  * Side effects:
308  *      None.
309  *
310  *----------------------------------------------------------------------
311  */
312
313 enum pipe_error
314 SVGA3D_DefineSurface2D(struct svga_winsys_context *swc,    // IN
315                        struct svga_winsys_surface *sid, // IN
316                        uint32 width,                // IN
317                        uint32 height,               // IN
318                        SVGA3dSurfaceFormat format)  // IN
319 {
320    SVGA3dSize *mipSizes;
321    SVGA3dSurfaceFace *faces;
322    enum pipe_error ret;
323
324    ret = SVGA3D_BeginDefineSurface(swc,
325                                    sid, 0, format, &faces, &mipSizes, 1);
326    if(ret != PIPE_OK)
327       return ret;
328
329    faces[0].numMipLevels = 1;
330
331    mipSizes[0].width = width;
332    mipSizes[0].height = height;
333    mipSizes[0].depth = 1;
334  
335    swc->commit(swc);;
336    
337    return PIPE_OK;
338 }
339
340
341 /*
342  *----------------------------------------------------------------------
343  *
344  * SVGA3D_DestroySurface --
345  *
346  *      Release the host VRAM encapsulated by a particular surface ID.
347  *
348  * Results:
349  *      None.
350  *
351  * Side effects:
352  *      None.
353  *
354  *----------------------------------------------------------------------
355  */
356
357 enum pipe_error
358 SVGA3D_DestroySurface(struct svga_winsys_context *swc,
359                       struct svga_winsys_surface *sid)  // IN
360 {
361    SVGA3dCmdDestroySurface *cmd;
362    
363    cmd = SVGA3D_FIFOReserve(swc,
364                             SVGA_3D_CMD_SURFACE_DESTROY, sizeof *cmd, 1);
365    if(!cmd)
366       return PIPE_ERROR_OUT_OF_MEMORY;
367    
368    swc->surface_relocation(swc, &cmd->sid, sid, PIPE_BUFFER_USAGE_GPU_READ);
369    swc->commit(swc);;
370    
371    return PIPE_OK;
372 }
373
374
375 /*
376  *----------------------------------------------------------------------
377  *
378  * SVGA3D_BeginSurfaceDMA--
379  *
380  *      Begin a SURFACE_DMA command. This reserves space for it in
381  *      the FIFO, and returns a pointer to the command's box array.
382  *      This function must be paired with SVGA_FIFOCommitAll().
383  *
384  *      When the SVGA3D device asynchronously processes this FIFO
385  *      command, a DMA operation is performed between host VRAM and
386  *      a generic SVGAGuestPtr. The guest pointer may refer to guest
387  *      VRAM (provided by the SVGA PCI device) or to guest system
388  *      memory that has been set up as a Guest Memory Region (GMR)
389  *      by the SVGA device.
390  *
391  *      The guest's DMA buffer must remain valid (not freed, paged out,
392  *      or overwritten) until the host has finished processing this
393  *      command. The guest can determine that the host has finished
394  *      by using the SVGA device's FIFO Fence mechanism.
395  *
396  *      The guest's image buffer can be an arbitrary size and shape.
397  *      Guest image data is interpreted according to the SVGA3D surface
398  *      format specified when the surface was defined.
399  *
400  *      The caller may optionally define the guest image's pitch.
401  *      guestImage->pitch can either be zero (assume image is tightly
402  *      packed) or it must be the number of bytes between vertically
403  *      adjacent image blocks.
404  *
405  *      The provided copybox list specifies which regions of the source
406  *      image are to be copied, and where they appear on the destination.
407  *
408  *      NOTE: srcx/srcy are always on the guest image and x/y are
409  *      always on the host image, regardless of the actual transfer
410  *      direction!
411  *
412  *      For efficiency, the SVGA3D device is free to copy more data
413  *      than specified. For example, it may round copy boxes outwards
414  *      such that they lie on particular alignment boundaries.
415  *
416  *----------------------------------------------------------------------
417  */
418
419 enum pipe_error
420 SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
421                   struct svga_transfer *st,         // IN
422                   SVGA3dTransferType transfer,      // IN
423                   const SVGA3dCopyBox *boxes,       // IN
424                   uint32 numBoxes)                  // IN
425 {
426    struct svga_texture *texture = svga_texture(st->base.texture); 
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 = PIPE_BUFFER_USAGE_GPU_READ;
435       surface_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
436    }
437    else if(transfer == SVGA3D_READ_HOST_VRAM) {
438       region_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
439       surface_flags = PIPE_BUFFER_USAGE_GPU_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->base.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    memset(&pSuffix->flags, 0, sizeof pSuffix->flags);
468
469    swc->commit(swc);
470
471    return PIPE_OK;
472 }
473
474
475 enum pipe_error
476 SVGA3D_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 = PIPE_BUFFER_USAGE_GPU_READ;
493       surface_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
494    }
495    else if(transfer == SVGA3D_READ_HOST_VRAM) {
496       region_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
497       surface_flags = PIPE_BUFFER_USAGE_GPU_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
570 enum pipe_error
571 SVGA3D_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, PIPE_BUFFER_USAGE_GPU_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
627 enum pipe_error
628 SVGA3D_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
673 enum pipe_error
674 SVGA3D_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
718 enum pipe_error
719 SVGA3D_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 /*
765  *----------------------------------------------------------------------
766  *
767  * SVGA3D_SetShader --
768  *
769  *      Switch active shaders. This binds a new vertex or pixel shader
770  *      to the specified context.
771  *
772  *      A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
773  *      back to the fixed function vertex or pixel pipeline.
774  *
775  * Results:
776  *      None.
777  *
778  * Side effects:
779  *      None.
780  *
781  *----------------------------------------------------------------------
782  */
783
784 enum pipe_error
785 SVGA3D_SetShader(struct svga_winsys_context *swc,
786                  SVGA3dShaderType type,  // IN
787                  uint32 shid)            // IN
788 {
789    SVGA3dCmdSetShader *cmd;
790    
791    cmd = SVGA3D_FIFOReserve(swc,
792                             SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
793                             0);
794    if(!cmd)
795       return PIPE_ERROR_OUT_OF_MEMORY;
796    
797    cmd->cid = swc->cid;
798    cmd->type = type;
799    cmd->shid = shid;
800    swc->commit(swc);
801
802    return PIPE_OK;
803 }
804
805
806 /*
807  *----------------------------------------------------------------------
808  *
809  * SVGA3D_BeginClear --
810  *
811  *      Begin a CLEAR command. This reserves space for it in the FIFO,
812  *      and returns a pointer to the command's rectangle array.  This
813  *      function must be paired with SVGA_FIFOCommitAll().
814  *
815  *      Clear is a rendering operation which fills a list of
816  *      rectangles with constant values on all render target types
817  *      indicated by 'flags'.
818  *
819  *      Clear is not affected by clipping, depth test, or other
820  *      render state which affects the fragment pipeline.
821  *
822  * Results:
823  *      None.
824  *
825  * Side effects:
826  *      May write to attached render target surfaces.
827  *
828  *----------------------------------------------------------------------
829  */
830
831 enum pipe_error
832 SVGA3D_BeginClear(struct svga_winsys_context *swc,
833                   SVGA3dClearFlag flags,  // IN
834                   uint32 color,           // IN
835                   float depth,            // IN
836                   uint32 stencil,         // IN
837                   SVGA3dRect **rects,     // OUT
838                   uint32 numRects)        // IN
839 {
840    SVGA3dCmdClear *cmd;
841    
842    cmd = SVGA3D_FIFOReserve(swc,
843                             SVGA_3D_CMD_CLEAR, 
844                             sizeof *cmd + sizeof **rects * numRects,
845                             0);
846    if(!cmd)
847       return PIPE_ERROR_OUT_OF_MEMORY;
848
849    cmd->cid = swc->cid;
850    cmd->clearFlag = flags;
851    cmd->color = color;
852    cmd->depth = depth;
853    cmd->stencil = stencil;
854    *rects = (SVGA3dRect*) &cmd[1];
855
856    return PIPE_OK;
857 }
858
859
860 /*
861  *----------------------------------------------------------------------
862  *
863  * SVGA3D_ClearRect --
864  *
865  *      This is a simplified version of SVGA3D_BeginClear().
866  *
867  * Results:
868  *      None.
869  *
870  * Side effects:
871  *      None.
872  *
873  *----------------------------------------------------------------------
874  */
875
876 enum pipe_error
877 SVGA3D_ClearRect(struct svga_winsys_context *swc,
878                  SVGA3dClearFlag flags,  // IN
879                  uint32 color,           // IN
880                  float depth,            // IN
881                  uint32 stencil,         // IN
882                  uint32 x,               // IN
883                  uint32 y,               // IN
884                  uint32 w,               // IN
885                  uint32 h)               // IN
886 {
887    SVGA3dRect *rect;
888    enum pipe_error ret;
889
890    ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
891    if(ret != PIPE_OK)
892       return PIPE_ERROR_OUT_OF_MEMORY;
893
894    memset(rect, 0, sizeof *rect);
895    rect->x = x;
896    rect->y = y;
897    rect->w = w;
898    rect->h = h;
899    swc->commit(swc);
900
901    return PIPE_OK;
902 }
903
904
905 /*
906  *----------------------------------------------------------------------
907  *
908  * SVGA3D_BeginDrawPrimitives --
909  *
910  *      Begin a DRAW_PRIMITIVES command. This reserves space for it in
911  *      the FIFO, and returns a pointer to the command's arrays.
912  *      This function must be paired with SVGA_FIFOCommitAll().
913  *
914  *      Drawing commands consist of two variable-length arrays:
915  *      SVGA3dVertexDecl elements declare a set of vertex buffers to
916  *      use while rendering, and SVGA3dPrimitiveRange elements specify
917  *      groups of primitives each with an optional index buffer.
918  *
919  *      The decls and ranges arrays are initialized to zero.
920  *
921  * Results:
922  *      None.
923  *
924  * Side effects:
925  *      May write to attached render target surfaces.
926  *
927  *----------------------------------------------------------------------
928  */
929
930 enum pipe_error
931 SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
932                            SVGA3dVertexDecl **decls,      // OUT
933                            uint32 numVertexDecls,         // IN
934                            SVGA3dPrimitiveRange **ranges, // OUT
935                            uint32 numRanges)              // IN
936 {
937    SVGA3dCmdDrawPrimitives *cmd;
938    SVGA3dVertexDecl *declArray;
939    SVGA3dPrimitiveRange *rangeArray;
940    uint32 declSize = sizeof **decls * numVertexDecls;
941    uint32 rangeSize = sizeof **ranges * numRanges;
942
943    cmd = SVGA3D_FIFOReserve(swc,
944                             SVGA_3D_CMD_DRAW_PRIMITIVES, 
945                             sizeof *cmd + declSize + rangeSize,
946                             numVertexDecls + numRanges);
947    if(!cmd)
948       return PIPE_ERROR_OUT_OF_MEMORY;
949
950    cmd->cid = swc->cid;
951    cmd->numVertexDecls = numVertexDecls;
952    cmd->numRanges = numRanges;
953
954    declArray = (SVGA3dVertexDecl*) &cmd[1];
955    rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
956
957    memset(declArray, 0, declSize);
958    memset(rangeArray, 0, rangeSize);
959
960    *decls = declArray;
961    *ranges = rangeArray;
962
963    return PIPE_OK;
964 }
965
966
967 /*
968  *----------------------------------------------------------------------
969  *
970  * SVGA3D_BeginSurfaceCopy --
971  *
972  *      Begin a SURFACE_COPY command. This reserves space for it in
973  *      the FIFO, and returns a pointer to the command's arrays.  This
974  *      function must be paired with SVGA_FIFOCommitAll().
975  *
976  *      The box array is initialized with zeroes.
977  *
978  * Results:
979  *      None.
980  *
981  * Side effects:
982  *      Asynchronously copies a list of boxes from surface to surface.
983  *
984  *----------------------------------------------------------------------
985  */
986
987 enum pipe_error
988 SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
989                         struct pipe_surface *src,    // IN
990                         struct pipe_surface *dest,   // IN
991                         SVGA3dCopyBox **boxes,       // OUT
992                         uint32 numBoxes)             // IN
993 {
994    SVGA3dCmdSurfaceCopy *cmd;
995    uint32 boxesSize = sizeof **boxes * numBoxes;
996
997    cmd = SVGA3D_FIFOReserve(swc,
998                             SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
999                             2);
1000    if(!cmd)
1001       return PIPE_ERROR_OUT_OF_MEMORY;
1002
1003    surface_to_surfaceid(swc, src, &cmd->src, PIPE_BUFFER_USAGE_GPU_READ);
1004    surface_to_surfaceid(swc, dest, &cmd->dest, PIPE_BUFFER_USAGE_GPU_WRITE);
1005    *boxes = (SVGA3dCopyBox*) &cmd[1];
1006
1007    memset(*boxes, 0, boxesSize);
1008
1009    return PIPE_OK;
1010 }
1011
1012
1013 /*
1014  *----------------------------------------------------------------------
1015  *
1016  * SVGA3D_SurfaceStretchBlt --
1017  *
1018  *      Issue a SURFACE_STRETCHBLT command: an asynchronous
1019  *      surface-to-surface blit, with scaling.
1020  *
1021  * Results:
1022  *      None.
1023  *
1024  * Side effects:
1025  *      Asynchronously copies one box from surface to surface.
1026  *
1027  *----------------------------------------------------------------------
1028  */
1029
1030 enum pipe_error
1031 SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
1032                          struct pipe_surface *src,    // IN
1033                          struct pipe_surface *dest,   // IN
1034                          SVGA3dBox *boxSrc,           // IN
1035                          SVGA3dBox *boxDest,          // IN
1036                          SVGA3dStretchBltMode mode)   // IN
1037 {
1038    SVGA3dCmdSurfaceStretchBlt *cmd;
1039    
1040    cmd = SVGA3D_FIFOReserve(swc,
1041                             SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
1042                             2);
1043    if(!cmd)
1044       return PIPE_ERROR_OUT_OF_MEMORY;
1045
1046    surface_to_surfaceid(swc, src, &cmd->src, PIPE_BUFFER_USAGE_GPU_READ);
1047    surface_to_surfaceid(swc, dest, &cmd->dest, PIPE_BUFFER_USAGE_GPU_WRITE);
1048    cmd->boxSrc = *boxSrc;
1049    cmd->boxDest = *boxDest;
1050    cmd->mode = mode;
1051    swc->commit(swc);
1052
1053    return PIPE_OK;
1054 }
1055
1056
1057 /*
1058  *----------------------------------------------------------------------
1059  *
1060  * SVGA3D_SetViewport --
1061  *
1062  *      Set the current context's viewport rectangle. The viewport
1063  *      is clipped to the dimensions of the current render target,
1064  *      then all rendering is clipped to the viewport.
1065  *
1066  * Results:
1067  *      None.
1068  *
1069  * Side effects:
1070  *      None.
1071  *
1072  *----------------------------------------------------------------------
1073  */
1074
1075 enum pipe_error
1076 SVGA3D_SetViewport(struct svga_winsys_context *swc,
1077                    SVGA3dRect *rect)  // IN
1078 {
1079    SVGA3dCmdSetViewport *cmd;
1080    
1081    cmd = SVGA3D_FIFOReserve(swc,
1082                             SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
1083                             0);
1084    if(!cmd)
1085       return PIPE_ERROR_OUT_OF_MEMORY;
1086
1087    cmd->cid = swc->cid;
1088    cmd->rect = *rect;
1089    swc->commit(swc);
1090
1091    return PIPE_OK;
1092 }
1093
1094
1095
1096
1097 /*
1098  *----------------------------------------------------------------------
1099  *
1100  * SVGA3D_SetScissorRect --
1101  *
1102  *      Set the current context's scissor rectangle. If scissor
1103  *      is enabled then all rendering is clipped to the scissor.
1104  *
1105  * Results:
1106  *      None.
1107  *
1108  * Side effects:
1109  *      None.
1110  *
1111  *----------------------------------------------------------------------
1112  */
1113
1114 enum pipe_error
1115 SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
1116                       SVGA3dRect *rect)  // IN
1117 {
1118    SVGA3dCmdSetScissorRect *cmd;
1119    
1120    cmd = SVGA3D_FIFOReserve(swc,
1121                             SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
1122                             0);
1123    if(!cmd)
1124       return PIPE_ERROR_OUT_OF_MEMORY;
1125
1126    cmd->cid = swc->cid;
1127    cmd->rect = *rect;
1128    swc->commit(swc);
1129
1130    return PIPE_OK;
1131 }
1132
1133 /*
1134  *----------------------------------------------------------------------
1135  *
1136  * SVGA3D_SetClipPlane --
1137  *
1138  *      Set one of the current context's clip planes. If the clip
1139  *      plane is enabled then all 3d rendering is clipped to against
1140  *      the plane.
1141  *
1142  * Results:
1143  *      None.
1144  *
1145  * Side effects:
1146  *      None.
1147  *
1148  *----------------------------------------------------------------------
1149  */
1150
1151 enum pipe_error SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
1152                          uint32 index, const float *plane)
1153 {
1154    SVGA3dCmdSetClipPlane *cmd;
1155    
1156    cmd = SVGA3D_FIFOReserve(swc,
1157                             SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
1158                             0);
1159    if(!cmd)
1160       return PIPE_ERROR_OUT_OF_MEMORY;
1161
1162    cmd->cid = swc->cid;
1163    cmd->index = index;
1164    cmd->plane[0] = plane[0];
1165    cmd->plane[1] = plane[1];
1166    cmd->plane[2] = plane[2];
1167    cmd->plane[3] = plane[3];
1168    swc->commit(swc);
1169
1170    return PIPE_OK;
1171 }
1172
1173 /*
1174  *----------------------------------------------------------------------
1175  *
1176  * SVGA3D_SetZRange --
1177  *
1178  *      Set the range of the depth buffer to use. 'min' and 'max'
1179  *      are values between 0.0 and 1.0.
1180  *
1181  * Results:
1182  *      None.
1183  *
1184  * Side effects:
1185  *      None.
1186  *
1187  *----------------------------------------------------------------------
1188  */
1189
1190 enum pipe_error
1191 SVGA3D_SetZRange(struct svga_winsys_context *swc,
1192                  float zMin,  // IN
1193                  float zMax)  // IN
1194 {
1195    SVGA3dCmdSetZRange *cmd;
1196    
1197    cmd = SVGA3D_FIFOReserve(swc,
1198                             SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
1199                             0);
1200    if(!cmd)
1201       return PIPE_ERROR_OUT_OF_MEMORY;
1202
1203    cmd->cid = swc->cid;
1204    cmd->zRange.min = zMin;
1205    cmd->zRange.max = zMax;
1206    swc->commit(swc);
1207
1208    return PIPE_OK;
1209 }
1210
1211
1212 /*
1213  *----------------------------------------------------------------------
1214  *
1215  * SVGA3D_BeginSetTextureState --
1216  *
1217  *      Begin a SETTEXTURESTATE command. This reserves space for it in
1218  *      the FIFO, and returns a pointer to the command's texture state
1219  *      array.  This function must be paired with SVGA_FIFOCommitAll().
1220  *
1221  *      This command sets rendering state which is per-texture-unit.
1222  *
1223  *      XXX: Individual texture states need documentation. However,
1224  *           they are very similar to the texture states defined by
1225  *           Direct3D. The D3D documentation is a good starting point
1226  *           for understanding SVGA3D texture states.
1227  *
1228  * Results:
1229  *      None.
1230  *
1231  * Side effects:
1232  *      None.
1233  *
1234  *----------------------------------------------------------------------
1235  */
1236
1237 enum pipe_error
1238 SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
1239                             SVGA3dTextureState **states,  // OUT
1240                             uint32 numStates)             // IN
1241 {
1242    SVGA3dCmdSetTextureState *cmd;
1243    
1244    cmd = SVGA3D_FIFOReserve(swc,
1245                             SVGA_3D_CMD_SETTEXTURESTATE, 
1246                             sizeof *cmd + sizeof **states * numStates,
1247                             numStates);
1248    if(!cmd)
1249       return PIPE_ERROR_OUT_OF_MEMORY;
1250
1251    cmd->cid = swc->cid;
1252    *states = (SVGA3dTextureState*) &cmd[1];
1253
1254    return PIPE_OK;
1255 }
1256
1257
1258 /*
1259  *----------------------------------------------------------------------
1260  *
1261  * SVGA3D_BeginSetRenderState --
1262  *
1263  *      Begin a SETRENDERSTATE command. This reserves space for it in
1264  *      the FIFO, and returns a pointer to the command's texture state
1265  *      array.  This function must be paired with SVGA_FIFOCommitAll().
1266  *
1267  *      This command sets rendering state which is global to the context.
1268  *
1269  *      XXX: Individual render states need documentation. However,
1270  *           they are very similar to the render states defined by
1271  *           Direct3D. The D3D documentation is a good starting point
1272  *           for understanding SVGA3D render states.
1273  *
1274  * Results:
1275  *      None.
1276  *
1277  * Side effects:
1278  *      None.
1279  *
1280  *----------------------------------------------------------------------
1281  */
1282
1283 enum pipe_error
1284 SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
1285                            SVGA3dRenderState **states,  // OUT
1286                            uint32 numStates)            // IN
1287 {
1288    SVGA3dCmdSetRenderState *cmd;
1289    
1290    cmd = SVGA3D_FIFOReserve(swc,
1291                             SVGA_3D_CMD_SETRENDERSTATE, 
1292                             sizeof *cmd + sizeof **states * numStates,
1293                             0);
1294    if(!cmd)
1295       return PIPE_ERROR_OUT_OF_MEMORY;
1296
1297    cmd->cid = swc->cid;
1298    *states = (SVGA3dRenderState*) &cmd[1];
1299
1300    return PIPE_OK;
1301 }
1302
1303
1304 /*
1305  *----------------------------------------------------------------------
1306  *
1307  * SVGA3D_BeginQuery--
1308  *
1309  *      Issues a SVGA_3D_CMD_BEGIN_QUERY command.
1310  *
1311  * Results:
1312  *      None.
1313  *
1314  * Side effects:
1315  *      Commits space in the FIFO memory.
1316  *
1317  *----------------------------------------------------------------------
1318  */
1319
1320 enum pipe_error
1321 SVGA3D_BeginQuery(struct svga_winsys_context *swc,
1322                   SVGA3dQueryType type) // IN
1323 {
1324    SVGA3dCmdBeginQuery *cmd;
1325
1326    cmd = SVGA3D_FIFOReserve(swc,
1327                             SVGA_3D_CMD_BEGIN_QUERY,
1328                             sizeof *cmd,
1329                             0);
1330    if(!cmd)
1331       return PIPE_ERROR_OUT_OF_MEMORY;
1332
1333    cmd->cid = swc->cid;
1334    cmd->type = type;
1335
1336    swc->commit(swc);
1337    
1338    return PIPE_OK;
1339 }
1340
1341
1342 /*
1343  *----------------------------------------------------------------------
1344  *
1345  * SVGA3D_EndQuery--
1346  *
1347  *      Issues a SVGA_3D_CMD_END_QUERY command.
1348  *
1349  * Results:
1350  *      None.
1351  *
1352  * Side effects:
1353  *      Commits space in the FIFO memory.
1354  *
1355  *----------------------------------------------------------------------
1356  */
1357
1358 enum pipe_error
1359 SVGA3D_EndQuery(struct svga_winsys_context *swc,
1360                 SVGA3dQueryType type,              // IN
1361                 struct svga_winsys_buffer *buffer) // IN/OUT
1362 {
1363    SVGA3dCmdEndQuery *cmd;
1364
1365    cmd = SVGA3D_FIFOReserve(swc,
1366                             SVGA_3D_CMD_END_QUERY, 
1367                             sizeof *cmd,
1368                             1);
1369    if(!cmd)
1370       return PIPE_ERROR_OUT_OF_MEMORY;
1371
1372    cmd->cid = swc->cid;
1373    cmd->type = type;
1374
1375    swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1376                           PIPE_BUFFER_USAGE_GPU_WRITE);
1377
1378    swc->commit(swc);
1379    
1380    return PIPE_OK;
1381 }
1382
1383
1384 /*
1385  *----------------------------------------------------------------------
1386  *
1387  * SVGA3D_WaitForQuery--
1388  *
1389  *      Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command.  This reserves space
1390  *      for it in the FIFO.  This doesn't actually wait for the query to
1391  *      finish but instead tells the host to start a wait at the driver
1392  *      level.  The caller can wait on the status variable in the
1393  *      guestPtr memory or send an insert fence instruction after this
1394  *      command and wait on the fence.
1395  *
1396  * Results:
1397  *      None.
1398  *
1399  * Side effects:
1400  *      Commits space in the FIFO memory.
1401  *
1402  *----------------------------------------------------------------------
1403  */
1404
1405 enum pipe_error
1406 SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
1407                     SVGA3dQueryType type,              // IN
1408                     struct svga_winsys_buffer *buffer) // IN/OUT
1409 {
1410    SVGA3dCmdWaitForQuery *cmd;
1411
1412    cmd = SVGA3D_FIFOReserve(swc,
1413                             SVGA_3D_CMD_WAIT_FOR_QUERY, 
1414                             sizeof *cmd,
1415                             1);
1416    if(!cmd)
1417       return PIPE_ERROR_OUT_OF_MEMORY;
1418
1419    cmd->cid = swc->cid;
1420    cmd->type = type;
1421    
1422    swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
1423                           PIPE_BUFFER_USAGE_GPU_WRITE);
1424
1425    swc->commit(swc);
1426    
1427    return PIPE_OK;
1428 }