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