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