/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
/**
* svga_cmd.c --
*
* Command construction utility for the SVGA3D protocol used by
* the VMware SVGA device, based on the svgautil library.
*/
#include "svga_winsys.h"
#include "svga_resource_buffer.h"
#include "svga_resource_texture.h"
#include "svga_surface.h"
#include "svga_cmd.h"
/*
*----------------------------------------------------------------------
*
* surface_to_surfaceid --
*
* Utility function for surface ids.
* Can handle null surface. Does a surface_reallocation so you need
* to have allocated the fifo space before converting.
*
* Results:
* id is filled out.
*
* Side effects:
* One surface relocation is performed for texture handle.
*
*----------------------------------------------------------------------
*/
static INLINE
void surface_to_surfaceid(struct svga_winsys_context *swc, // IN
struct pipe_surface *surface, // IN
SVGA3dSurfaceImageId *id, // OUT
unsigned flags) // IN
{
if(surface) {
struct svga_surface *s = svga_surface(surface);
swc->surface_relocation(swc, &id->sid, s->handle, flags);
id->face = s->real_face; /* faces have the same order */
id->mipmap = s->real_level;
}
else {
swc->surface_relocation(swc, &id->sid, NULL, flags);
id->face = 0;
id->mipmap = 0;
}
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_FIFOReserve --
*
* Reserve space for an SVGA3D FIFO command.
*
* The 2D SVGA commands have been around for a while, so they
* have a rather asymmetric structure. The SVGA3D protocol is
* more uniform: each command begins with a header containing the
* command number and the full size.
*
* This is a convenience wrapper around SVGA_FIFOReserve. We
* reserve space for the whole command, and write the header.
*
* This function must be paired with SVGA_FIFOCommitAll().
*
* Results:
* Returns a pointer to the space reserved for command-specific
* data. It must be 'cmdSize' bytes long.
*
* Side effects:
* Begins a FIFO reservation.
*
*----------------------------------------------------------------------
*/
void *
SVGA3D_FIFOReserve(struct svga_winsys_context *swc,
uint32 cmd, // IN
uint32 cmdSize, // IN
uint32 nr_relocs) // IN
{
SVGA3dCmdHeader *header;
header = swc->reserve(swc, sizeof *header + cmdSize, nr_relocs);
if(!header)
return NULL;
header->id = cmd;
header->size = cmdSize;
return &header[1];
}
void
SVGA_FIFOCommitAll(struct svga_winsys_context *swc)
{
swc->commit(swc);
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_DefineContext --
*
* Create a new context, to be referred to with the provided ID.
*
* Context objects encapsulate all render state, and shader
* objects are per-context.
*
* Surfaces are not per-context. The same surface can be shared
* between multiple contexts, and surface operations can occur
* without a context.
*
* If the provided context ID already existed, it is redefined.
*
* Context IDs are arbitrary small non-negative integers,
* global to the entire SVGA device.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_DefineContext(struct svga_winsys_context *swc) // IN
{
SVGA3dCmdDefineContext *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_CONTEXT_DEFINE, sizeof *cmd, 0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_DestroyContext --
*
* Delete a context created with SVGA3D_DefineContext.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_DestroyContext(struct svga_winsys_context *swc) // IN
{
SVGA3dCmdDestroyContext *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_CONTEXT_DESTROY, sizeof *cmd, 0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginDefineSurface --
*
* Begin a SURFACE_DEFINE command. This reserves space for it in
* the FIFO, and returns pointers to the command's faces and
* mipsizes arrays.
*
* This function must be paired with SVGA_FIFOCommitAll().
* The faces and mipSizes arrays are initialized to zero.
*
* This creates a "surface" object in the SVGA3D device,
* with the provided surface ID (sid). Surfaces are generic
* containers for host VRAM objects like textures, vertex
* buffers, and depth/stencil buffers.
*
* Surfaces are hierarchical:
*
* - Surface may have multiple faces (for cube maps)
*
* - Each face has a list of mipmap levels
*
* - Each mipmap image may have multiple volume
* slices, if the image is three dimensional.
*
* - Each slice is a 2D array of 'blocks'
*
* - Each block may be one or more pixels.
* (Usually 1, more for DXT or YUV formats.)
*
* Surfaces are generic host VRAM objects. The SVGA3D device
* may optimize surfaces according to the format they were
* created with, but this format does not limit the ways in
* which the surface may be used. For example, a depth surface
* can be used as a texture, or a floating point image may
* be used as a vertex buffer. Some surface usages may be
* lower performance, due to software emulation, but any
* usage should work with any surface.
*
* If 'sid' is already defined, the old surface is deleted
* and this new surface replaces it.
*
* Surface IDs are arbitrary small non-negative integers,
* global to the entire SVGA device.
*
* Results:
* Returns pointers to arrays allocated in the FIFO for 'faces'
* and 'mipSizes'.
*
* Side effects:
* Begins a FIFO reservation.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginDefineSurface(struct svga_winsys_context *swc,
struct svga_winsys_surface *sid, // IN
SVGA3dSurfaceFlags flags, // IN
SVGA3dSurfaceFormat format, // IN
SVGA3dSurfaceFace **faces, // OUT
SVGA3dSize **mipSizes, // OUT
uint32 numMipSizes) // IN
{
SVGA3dCmdDefineSurface *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_DEFINE, sizeof *cmd +
sizeof **mipSizes * numMipSizes, 1);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->surface_relocation(swc, &cmd->sid, sid, SVGA_RELOC_WRITE);
cmd->surfaceFlags = flags;
cmd->format = format;
*faces = &cmd->face[0];
*mipSizes = (SVGA3dSize*) &cmd[1];
memset(*faces, 0, sizeof **faces * SVGA3D_MAX_SURFACE_FACES);
memset(*mipSizes, 0, sizeof **mipSizes * numMipSizes);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_DefineSurface2D --
*
* This is a simplified version of SVGA3D_BeginDefineSurface(),
* which does not support cube maps, mipmaps, or volume textures.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_DefineSurface2D(struct svga_winsys_context *swc, // IN
struct svga_winsys_surface *sid, // IN
uint32 width, // IN
uint32 height, // IN
SVGA3dSurfaceFormat format) // IN
{
SVGA3dSize *mipSizes;
SVGA3dSurfaceFace *faces;
enum pipe_error ret;
ret = SVGA3D_BeginDefineSurface(swc,
sid, 0, format, &faces, &mipSizes, 1);
if(ret != PIPE_OK)
return ret;
faces[0].numMipLevels = 1;
mipSizes[0].width = width;
mipSizes[0].height = height;
mipSizes[0].depth = 1;
swc->commit(swc);;
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_DestroySurface --
*
* Release the host VRAM encapsulated by a particular surface ID.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_DestroySurface(struct svga_winsys_context *swc,
struct svga_winsys_surface *sid) // IN
{
SVGA3dCmdDestroySurface *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_DESTROY, sizeof *cmd, 1);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->surface_relocation(swc, &cmd->sid, sid, SVGA_RELOC_READ);
swc->commit(swc);;
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SurfaceDMA--
*
* Emit a SURFACE_DMA command.
*
* When the SVGA3D device asynchronously processes this FIFO
* command, a DMA operation is performed between host VRAM and
* a generic SVGAGuestPtr. The guest pointer may refer to guest
* VRAM (provided by the SVGA PCI device) or to guest system
* memory that has been set up as a Guest Memory Region (GMR)
* by the SVGA device.
*
* The guest's DMA buffer must remain valid (not freed, paged out,
* or overwritten) until the host has finished processing this
* command. The guest can determine that the host has finished
* by using the SVGA device's FIFO Fence mechanism.
*
* The guest's image buffer can be an arbitrary size and shape.
* Guest image data is interpreted according to the SVGA3D surface
* format specified when the surface was defined.
*
* The caller may optionally define the guest image's pitch.
* guestImage->pitch can either be zero (assume image is tightly
* packed) or it must be the number of bytes between vertically
* adjacent image blocks.
*
* The provided copybox list specifies which regions of the source
* image are to be copied, and where they appear on the destination.
*
* NOTE: srcx/srcy are always on the guest image and x/y are
* always on the host image, regardless of the actual transfer
* direction!
*
* For efficiency, the SVGA3D device is free to copy more data
* than specified. For example, it may round copy boxes outwards
* such that they lie on particular alignment boundaries.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
struct svga_transfer *st, // IN
SVGA3dTransferType transfer, // IN
const SVGA3dCopyBox *boxes, // IN
uint32 numBoxes, // IN
SVGA3dSurfaceDMAFlags flags) // IN
{
struct svga_texture *texture = svga_texture(st->base.resource);
SVGA3dCmdSurfaceDMA *cmd;
SVGA3dCmdSurfaceDMASuffix *pSuffix;
uint32 boxesSize = sizeof *boxes * numBoxes;
unsigned region_flags;
unsigned surface_flags;
if(transfer == SVGA3D_WRITE_HOST_VRAM) {
region_flags = SVGA_RELOC_READ;
surface_flags = SVGA_RELOC_WRITE;
}
else if(transfer == SVGA3D_READ_HOST_VRAM) {
region_flags = SVGA_RELOC_WRITE;
surface_flags = SVGA_RELOC_READ;
}
else {
assert(0);
return PIPE_ERROR_BAD_INPUT;
}
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_DMA,
sizeof *cmd + boxesSize + sizeof *pSuffix,
2);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->region_relocation(swc, &cmd->guest.ptr, st->hwbuf, 0, region_flags);
cmd->guest.pitch = st->base.stride;
swc->surface_relocation(swc, &cmd->host.sid, texture->handle, surface_flags);
cmd->host.face = st->face; /* PIPE_TEX_FACE_* and SVGA3D_CUBEFACE_* match */
cmd->host.mipmap = st->base.level;
cmd->transfer = transfer;
memcpy(&cmd[1], boxes, boxesSize);
pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + boxesSize);
pSuffix->suffixSize = sizeof *pSuffix;
pSuffix->maximumOffset = st->hw_nblocksy*st->base.stride;
pSuffix->flags = flags;
swc->commit(swc);
return PIPE_OK;
}
enum pipe_error
SVGA3D_BufferDMA(struct svga_winsys_context *swc,
struct svga_winsys_buffer *guest,
struct svga_winsys_surface *host,
SVGA3dTransferType transfer, // IN
uint32 size, // IN
uint32 guest_offset, // IN
uint32 host_offset, // IN
SVGA3dSurfaceDMAFlags flags) // IN
{
SVGA3dCmdSurfaceDMA *cmd;
SVGA3dCopyBox *box;
SVGA3dCmdSurfaceDMASuffix *pSuffix;
unsigned region_flags;
unsigned surface_flags;
if(transfer == SVGA3D_WRITE_HOST_VRAM) {
region_flags = SVGA_RELOC_READ;
surface_flags = SVGA_RELOC_WRITE;
}
else if(transfer == SVGA3D_READ_HOST_VRAM) {
region_flags = SVGA_RELOC_WRITE;
surface_flags = SVGA_RELOC_READ;
}
else {
assert(0);
return PIPE_ERROR_BAD_INPUT;
}
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_DMA,
sizeof *cmd + sizeof *box + sizeof *pSuffix,
2);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->region_relocation(swc, &cmd->guest.ptr, guest, 0, region_flags);
cmd->guest.pitch = 0;
swc->surface_relocation(swc, &cmd->host.sid, host, surface_flags);
cmd->host.face = 0;
cmd->host.mipmap = 0;
cmd->transfer = transfer;
box = (SVGA3dCopyBox *)&cmd[1];
box->x = host_offset;
box->y = 0;
box->z = 0;
box->w = size;
box->h = 1;
box->d = 1;
box->srcx = guest_offset;
box->srcy = 0;
box->srcz = 0;
pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + sizeof *box);
pSuffix->suffixSize = sizeof *pSuffix;
pSuffix->maximumOffset = guest_offset + size;
pSuffix->flags = flags;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetRenderTarget --
*
* Bind a surface object to a particular render target attachment
* point on the current context. Render target attachment points
* exist for color buffers, a depth buffer, and a stencil buffer.
*
* The SVGA3D device is quite lenient about the types of surfaces
* that may be used as render targets. The color buffers must
* all be the same size, but the depth and stencil buffers do not
* have to be the same size as the color buffer. All attachments
* are optional.
*
* Some combinations of render target formats may require software
* emulation, depending on the capabilities of the host graphics
* API and graphics hardware.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetRenderTarget(struct svga_winsys_context *swc,
SVGA3dRenderTargetType type, // IN
struct pipe_surface *surface) // IN
{
SVGA3dCmdSetRenderTarget *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETRENDERTARGET, sizeof *cmd, 1);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->type = type;
surface_to_surfaceid(swc, surface, &cmd->target, SVGA_RELOC_WRITE);
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_DefineShader --
*
* Upload the bytecode for a new shader. The bytecode is "SVGA3D
* format", which is theoretically a binary-compatible superset
* of Microsoft's DirectX shader bytecode. In practice, the
* SVGA3D bytecode doesn't yet have any extensions to DirectX's
* bytecode format.
*
* The SVGA3D device supports shader models 1.1 through 2.0.
*
* The caller chooses a shader ID (small positive integer) by
* which this shader will be identified in future commands. This
* ID is in a namespace which is per-context and per-shader-type.
*
* 'bytecodeLen' is specified in bytes. It must be a multiple of 4.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_DefineShader(struct svga_winsys_context *swc,
uint32 shid, // IN
SVGA3dShaderType type, // IN
const uint32 *bytecode, // IN
uint32 bytecodeLen) // IN
{
SVGA3dCmdDefineShader *cmd;
assert(bytecodeLen % 4 == 0);
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SHADER_DEFINE, sizeof *cmd + bytecodeLen,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->shid = shid;
cmd->type = type;
memcpy(&cmd[1], bytecode, bytecodeLen);
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_DestroyShader --
*
* Delete a shader that was created by SVGA3D_DefineShader. If
* the shader was the current vertex or pixel shader for its
* context, rendering results are undefined until a new shader is
* bound.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_DestroyShader(struct svga_winsys_context *swc,
uint32 shid, // IN
SVGA3dShaderType type) // IN
{
SVGA3dCmdDestroyShader *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SHADER_DESTROY, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->shid = shid;
cmd->type = type;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetShaderConst --
*
* Set the value of a shader constant.
*
* Shader constants are analogous to uniform variables in GLSL,
* except that they belong to the render context rather than to
* an individual shader.
*
* Constants may have one of three types: A 4-vector of floats,
* a 4-vector of integers, or a single boolean flag.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
uint32 reg, // IN
SVGA3dShaderType type, // IN
SVGA3dShaderConstType ctype, // IN
const void *value) // IN
{
SVGA3dCmdSetShaderConst *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SET_SHADER_CONST, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->reg = reg;
cmd->type = type;
cmd->ctype = ctype;
switch (ctype) {
case SVGA3D_CONST_TYPE_FLOAT:
case SVGA3D_CONST_TYPE_INT:
memcpy(&cmd->values, value, sizeof cmd->values);
break;
case SVGA3D_CONST_TYPE_BOOL:
memset(&cmd->values, 0, sizeof cmd->values);
cmd->values[0] = *(uint32*)value;
break;
default:
assert(0);
break;
}
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetShaderConsts --
*
* Set the value of successive shader constants.
*
* Shader constants are analogous to uniform variables in GLSL,
* except that they belong to the render context rather than to
* an individual shader.
*
* Constants may have one of three types: A 4-vector of floats,
* a 4-vector of integers, or a single boolean flag.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetShaderConsts(struct svga_winsys_context *swc,
uint32 reg, // IN
uint32 numRegs, // IN
SVGA3dShaderType type, // IN
SVGA3dShaderConstType ctype, // IN
const void *values) // IN
{
SVGA3dCmdSetShaderConst *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SET_SHADER_CONST,
sizeof *cmd + (numRegs - 1) * sizeof cmd->values,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->reg = reg;
cmd->type = type;
cmd->ctype = ctype;
memcpy(&cmd->values, values, numRegs * sizeof cmd->values);
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetShader --
*
* Switch active shaders. This binds a new vertex or pixel shader
* to the specified context.
*
* A shader ID of SVGA3D_INVALID_ID unbinds any shader, switching
* back to the fixed function vertex or pixel pipeline.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetShader(struct svga_winsys_context *swc,
SVGA3dShaderType type, // IN
uint32 shid) // IN
{
SVGA3dCmdSetShader *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SET_SHADER, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->type = type;
cmd->shid = shid;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginClear --
*
* Begin a CLEAR command. This reserves space for it in the FIFO,
* and returns a pointer to the command's rectangle array. This
* function must be paired with SVGA_FIFOCommitAll().
*
* Clear is a rendering operation which fills a list of
* rectangles with constant values on all render target types
* indicated by 'flags'.
*
* Clear is not affected by clipping, depth test, or other
* render state which affects the fragment pipeline.
*
* Results:
* None.
*
* Side effects:
* May write to attached render target surfaces.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginClear(struct svga_winsys_context *swc,
SVGA3dClearFlag flags, // IN
uint32 color, // IN
float depth, // IN
uint32 stencil, // IN
SVGA3dRect **rects, // OUT
uint32 numRects) // IN
{
SVGA3dCmdClear *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_CLEAR,
sizeof *cmd + sizeof **rects * numRects,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->clearFlag = flags;
cmd->color = color;
cmd->depth = depth;
cmd->stencil = stencil;
*rects = (SVGA3dRect*) &cmd[1];
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_ClearRect --
*
* This is a simplified version of SVGA3D_BeginClear().
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_ClearRect(struct svga_winsys_context *swc,
SVGA3dClearFlag flags, // IN
uint32 color, // IN
float depth, // IN
uint32 stencil, // IN
uint32 x, // IN
uint32 y, // IN
uint32 w, // IN
uint32 h) // IN
{
SVGA3dRect *rect;
enum pipe_error ret;
ret = SVGA3D_BeginClear(swc, flags, color, depth, stencil, &rect, 1);
if(ret != PIPE_OK)
return PIPE_ERROR_OUT_OF_MEMORY;
memset(rect, 0, sizeof *rect);
rect->x = x;
rect->y = y;
rect->w = w;
rect->h = h;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginDrawPrimitives --
*
* Begin a DRAW_PRIMITIVES command. This reserves space for it in
* the FIFO, and returns a pointer to the command's arrays.
* This function must be paired with SVGA_FIFOCommitAll().
*
* Drawing commands consist of two variable-length arrays:
* SVGA3dVertexDecl elements declare a set of vertex buffers to
* use while rendering, and SVGA3dPrimitiveRange elements specify
* groups of primitives each with an optional index buffer.
*
* The decls and ranges arrays are initialized to zero.
*
* Results:
* None.
*
* Side effects:
* May write to attached render target surfaces.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
SVGA3dVertexDecl **decls, // OUT
uint32 numVertexDecls, // IN
SVGA3dPrimitiveRange **ranges, // OUT
uint32 numRanges) // IN
{
SVGA3dCmdDrawPrimitives *cmd;
SVGA3dVertexDecl *declArray;
SVGA3dPrimitiveRange *rangeArray;
uint32 declSize = sizeof **decls * numVertexDecls;
uint32 rangeSize = sizeof **ranges * numRanges;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_DRAW_PRIMITIVES,
sizeof *cmd + declSize + rangeSize,
numVertexDecls + numRanges);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->numVertexDecls = numVertexDecls;
cmd->numRanges = numRanges;
declArray = (SVGA3dVertexDecl*) &cmd[1];
rangeArray = (SVGA3dPrimitiveRange*) &declArray[numVertexDecls];
memset(declArray, 0, declSize);
memset(rangeArray, 0, rangeSize);
*decls = declArray;
*ranges = rangeArray;
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginSurfaceCopy --
*
* Begin a SURFACE_COPY command. This reserves space for it in
* the FIFO, and returns a pointer to the command's arrays. This
* function must be paired with SVGA_FIFOCommitAll().
*
* The box array is initialized with zeroes.
*
* Results:
* None.
*
* Side effects:
* Asynchronously copies a list of boxes from surface to surface.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
struct pipe_surface *src, // IN
struct pipe_surface *dest, // IN
SVGA3dCopyBox **boxes, // OUT
uint32 numBoxes) // IN
{
SVGA3dCmdSurfaceCopy *cmd;
uint32 boxesSize = sizeof **boxes * numBoxes;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_COPY, sizeof *cmd + boxesSize,
2);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
*boxes = (SVGA3dCopyBox*) &cmd[1];
memset(*boxes, 0, boxesSize);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SurfaceStretchBlt --
*
* Issue a SURFACE_STRETCHBLT command: an asynchronous
* surface-to-surface blit, with scaling.
*
* Results:
* None.
*
* Side effects:
* Asynchronously copies one box from surface to surface.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
struct pipe_surface *src, // IN
struct pipe_surface *dest, // IN
SVGA3dBox *boxSrc, // IN
SVGA3dBox *boxDest, // IN
SVGA3dStretchBltMode mode) // IN
{
SVGA3dCmdSurfaceStretchBlt *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_STRETCHBLT, sizeof *cmd,
2);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
surface_to_surfaceid(swc, src, &cmd->src, SVGA_RELOC_READ);
surface_to_surfaceid(swc, dest, &cmd->dest, SVGA_RELOC_WRITE);
cmd->boxSrc = *boxSrc;
cmd->boxDest = *boxDest;
cmd->mode = mode;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetViewport --
*
* Set the current context's viewport rectangle. The viewport
* is clipped to the dimensions of the current render target,
* then all rendering is clipped to the viewport.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetViewport(struct svga_winsys_context *swc,
SVGA3dRect *rect) // IN
{
SVGA3dCmdSetViewport *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETVIEWPORT, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->rect = *rect;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetScissorRect --
*
* Set the current context's scissor rectangle. If scissor
* is enabled then all rendering is clipped to the scissor.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
SVGA3dRect *rect) // IN
{
SVGA3dCmdSetScissorRect *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETSCISSORRECT, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->rect = *rect;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetClipPlane --
*
* Set one of the current context's clip planes. If the clip
* plane is enabled then all 3d rendering is clipped to against
* the plane.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
uint32 index, const float *plane)
{
SVGA3dCmdSetClipPlane *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETCLIPPLANE, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->index = index;
cmd->plane[0] = plane[0];
cmd->plane[1] = plane[1];
cmd->plane[2] = plane[2];
cmd->plane[3] = plane[3];
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_SetZRange --
*
* Set the range of the depth buffer to use. 'min' and 'max'
* are values between 0.0 and 1.0.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_SetZRange(struct svga_winsys_context *swc,
float zMin, // IN
float zMax) // IN
{
SVGA3dCmdSetZRange *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETZRANGE, sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->zRange.min = zMin;
cmd->zRange.max = zMax;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginSetTextureState --
*
* Begin a SETTEXTURESTATE command. This reserves space for it in
* the FIFO, and returns a pointer to the command's texture state
* array. This function must be paired with SVGA_FIFOCommitAll().
*
* This command sets rendering state which is per-texture-unit.
*
* XXX: Individual texture states need documentation. However,
* they are very similar to the texture states defined by
* Direct3D. The D3D documentation is a good starting point
* for understanding SVGA3D texture states.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
SVGA3dTextureState **states, // OUT
uint32 numStates) // IN
{
SVGA3dCmdSetTextureState *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETTEXTURESTATE,
sizeof *cmd + sizeof **states * numStates,
numStates);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
*states = (SVGA3dTextureState*) &cmd[1];
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginSetRenderState --
*
* Begin a SETRENDERSTATE command. This reserves space for it in
* the FIFO, and returns a pointer to the command's texture state
* array. This function must be paired with SVGA_FIFOCommitAll().
*
* This command sets rendering state which is global to the context.
*
* XXX: Individual render states need documentation. However,
* they are very similar to the render states defined by
* Direct3D. The D3D documentation is a good starting point
* for understanding SVGA3D render states.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
SVGA3dRenderState **states, // OUT
uint32 numStates) // IN
{
SVGA3dCmdSetRenderState *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SETRENDERSTATE,
sizeof *cmd + sizeof **states * numStates,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
*states = (SVGA3dRenderState*) &cmd[1];
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_BeginQuery--
*
* Issues a SVGA_3D_CMD_BEGIN_QUERY command.
*
* Results:
* None.
*
* Side effects:
* Commits space in the FIFO memory.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_BeginQuery(struct svga_winsys_context *swc,
SVGA3dQueryType type) // IN
{
SVGA3dCmdBeginQuery *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_BEGIN_QUERY,
sizeof *cmd,
0);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->type = type;
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_EndQuery--
*
* Issues a SVGA_3D_CMD_END_QUERY command.
*
* Results:
* None.
*
* Side effects:
* Commits space in the FIFO memory.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_EndQuery(struct svga_winsys_context *swc,
SVGA3dQueryType type, // IN
struct svga_winsys_buffer *buffer) // IN/OUT
{
SVGA3dCmdEndQuery *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_END_QUERY,
sizeof *cmd,
1);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->type = type;
swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
SVGA_RELOC_WRITE);
swc->commit(swc);
return PIPE_OK;
}
/*
*----------------------------------------------------------------------
*
* SVGA3D_WaitForQuery--
*
* Issues a SVGA_3D_CMD_WAIT_FOR_QUERY command. This reserves space
* for it in the FIFO. This doesn't actually wait for the query to
* finish but instead tells the host to start a wait at the driver
* level. The caller can wait on the status variable in the
* guestPtr memory or send an insert fence instruction after this
* command and wait on the fence.
*
* Results:
* None.
*
* Side effects:
* Commits space in the FIFO memory.
*
*----------------------------------------------------------------------
*/
enum pipe_error
SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
SVGA3dQueryType type, // IN
struct svga_winsys_buffer *buffer) // IN/OUT
{
SVGA3dCmdWaitForQuery *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_WAIT_FOR_QUERY,
sizeof *cmd,
1);
if(!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->cid = swc->cid;
cmd->type = type;
swc->region_relocation(swc, &cmd->guestResult, buffer, 0,
SVGA_RELOC_WRITE);
swc->commit(swc);
return PIPE_OK;
}