svga: Add svga driver

This commit is contained in:
Jakob Bornecrantz 2009-11-16 19:56:18 +01:00
parent 6b480dc21d
commit 3192633d4a
95 changed files with 27235 additions and 0 deletions

View file

@ -0,0 +1,63 @@
TOP = ../../../..
include $(TOP)/configs/current
LIBNAME = svga
C_SOURCES = \
svgadump/st_shader_dump.c \
svgadump/st_shader_op.c \
svgadump/svga_dump.c \
svga_cmd.c \
svga_context.c \
svga_draw.c \
svga_draw_arrays.c \
svga_draw_elements.c \
svga_pipe_blend.c \
svga_pipe_blit.c \
svga_pipe_clear.c \
svga_pipe_constants.c \
svga_pipe_depthstencil.c \
svga_pipe_draw.c \
svga_pipe_flush.c \
svga_pipe_fs.c \
svga_pipe_misc.c \
svga_pipe_query.c \
svga_pipe_rasterizer.c \
svga_pipe_sampler.c \
svga_pipe_vertex.c \
svga_pipe_vs.c \
svga_screen.c \
svga_screen_buffer.c \
svga_screen_texture.c \
svga_screen_cache.c \
svga_state.c \
svga_state_need_swtnl.c \
svga_state_constants.c \
svga_state_framebuffer.c \
svga_state_rss.c \
svga_state_tss.c \
svga_state_vdecl.c \
svga_state_fs.c \
svga_state_vs.c \
svga_swtnl_backend.c \
svga_swtnl_draw.c \
svga_swtnl_state.c \
svga_tgsi.c \
svga_tgsi_decl_sm20.c \
svga_tgsi_decl_sm30.c \
svga_tgsi_insn.c
LIBRARY_INCLUDES = \
-I$(TOP)/src/gallium/drivers/svga/include
LIBRARY_DEFINES = \
-DHAVE_STDINT_H -DHAVE_SYS_TYPES_H
CC = gcc -fvisibility=hidden -msse -msse2
# Set the gnu99 standard to enable anonymous structs in vmware headers.
#
CFLAGS = -Wall -Werror -Wmissing-prototypes -std=gnu99 -ffast-math \
$(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) $(ASM_FLAGS)
include ../../Makefile.template

View file

@ -0,0 +1,75 @@
Import('*')
env = env.Clone()
if env['platform'] in ['linux']:
env.Append(CCFLAGS = ['-fvisibility=hidden'])
if env['gcc']:
env.Append(CPPDEFINES = [
'HAVE_STDINT_H',
'HAVE_SYS_TYPES_H',
])
if env['platform'] not in ['windows']:
# The Windows headers cause many gcc warnings
env.Append(CCFLAGS = ['-Werror'])
env.Prepend(CPPPATH = [
'include',
])
env.Append(CPPDEFINES = [
])
sources = [
'svga_cmd.c',
'svga_context.c',
'svga_draw.c',
'svga_draw_arrays.c',
'svga_draw_elements.c',
'svga_pipe_blend.c',
'svga_pipe_blit.c',
'svga_pipe_clear.c',
'svga_pipe_constants.c',
'svga_pipe_depthstencil.c',
'svga_pipe_draw.c',
'svga_pipe_flush.c',
'svga_pipe_fs.c',
'svga_pipe_misc.c',
'svga_pipe_query.c',
'svga_pipe_rasterizer.c',
'svga_pipe_sampler.c',
'svga_pipe_vertex.c',
'svga_pipe_vs.c',
'svga_screen.c',
'svga_screen_buffer.c',
'svga_screen_cache.c',
'svga_screen_texture.c',
'svga_state.c',
'svga_state_constants.c',
'svga_state_framebuffer.c',
'svga_state_need_swtnl.c',
'svga_state_rss.c',
'svga_state_tss.c',
'svga_state_vdecl.c',
'svga_state_fs.c',
'svga_state_vs.c',
'svga_swtnl_backend.c',
'svga_swtnl_draw.c',
'svga_swtnl_state.c',
'svga_tgsi.c',
'svga_tgsi_decl_sm20.c',
'svga_tgsi_decl_sm30.c',
'svga_tgsi_insn.c',
'svgadump/svga_dump.c',
'svgadump/st_shader_dump.c',
'svgadump/st_shader_op.c',
]
svga = env.ConvenienceLibrary(
target = 'svga',
source = sources,
)
Export('svga')

View file

@ -0,0 +1,3 @@
This directory contains the headers from the VMware SVGA Device Developer Kit:
https://vmware-svga.svn.sourceforge.net/svnroot/vmware-svga/trunk/lib/vmware/

View file

@ -0,0 +1,139 @@
/**********************************************************
* Copyright 2007-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.
*
**********************************************************/
/*
* svga3d_caps.h --
*
* Definitions for SVGA3D hardware capabilities. Capabilities
* are used to query for optional rendering features during
* driver initialization. The capability data is stored as very
* basic key/value dictionary within the "FIFO register" memory
* area at the beginning of BAR2.
*
* Note that these definitions are only for 3D capabilities.
* The SVGA device also has "device capabilities" and "FIFO
* capabilities", which are non-3D-specific and are stored as
* bitfields rather than key/value pairs.
*/
#ifndef _SVGA3D_CAPS_H_
#define _SVGA3D_CAPS_H_
#define SVGA_FIFO_3D_CAPS_SIZE (SVGA_FIFO_3D_CAPS_LAST - \
SVGA_FIFO_3D_CAPS + 1)
/*
* SVGA3dCapsRecordType
*
* Record types that can be found in the caps block.
* Related record types are grouped together numerically so that
* SVGA3dCaps_FindRecord() can be applied on a range of record
* types.
*/
typedef enum {
SVGA3DCAPS_RECORD_UNKNOWN = 0,
SVGA3DCAPS_RECORD_DEVCAPS_MIN = 0x100,
SVGA3DCAPS_RECORD_DEVCAPS = 0x100,
SVGA3DCAPS_RECORD_DEVCAPS_MAX = 0x1ff,
} SVGA3dCapsRecordType;
/*
* SVGA3dCapsRecordHeader
*
* Header field leading each caps block record. Contains the offset (in
* register words, NOT bytes) to the next caps block record (or the end
* of caps block records which will be a zero word) and the record type
* as defined above.
*/
typedef
struct SVGA3dCapsRecordHeader {
uint32 length;
SVGA3dCapsRecordType type;
}
SVGA3dCapsRecordHeader;
/*
* SVGA3dCapsRecord
*
* Caps block record; "data" is a placeholder for the actual data structure
* contained within the record; for example a record containing a FOOBAR
* structure would be of size "sizeof(SVGA3dCapsRecordHeader) +
* sizeof(FOOBAR)".
*/
typedef
struct SVGA3dCapsRecord {
SVGA3dCapsRecordHeader header;
uint32 data[1];
}
SVGA3dCapsRecord;
typedef uint32 SVGA3dCapPair[2];
/*
*----------------------------------------------------------------------
*
* SVGA3dCaps_FindRecord
*
* Finds the record with the highest-valued type within the given range
* in the caps block.
*
* Result: pointer to found record, or NULL if not found.
*
*----------------------------------------------------------------------
*/
static INLINE SVGA3dCapsRecord *
SVGA3dCaps_FindRecord(const uint32 *capsBlock,
SVGA3dCapsRecordType recordTypeMin,
SVGA3dCapsRecordType recordTypeMax)
{
SVGA3dCapsRecord *record, *found = NULL;
uint32 offset;
/*
* Search linearly through the caps block records for the specified type.
*/
for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) {
record = (SVGA3dCapsRecord *) (capsBlock + offset);
if ((record->header.type >= recordTypeMin) &&
(record->header.type <= recordTypeMax) &&
(!found || (record->header.type > found->header.type))) {
found = record;
}
}
return found;
}
#endif // _SVGA3D_CAPS_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,519 @@
/**********************************************************
* Copyright 2007-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.
*
**********************************************************/
/*
* svga3d_shaderdefs.h --
*
* SVGA3D byte code format and limit definitions.
*
* The format of the byte code directly corresponds to that defined
* by Microsoft DirectX SDK 9.0c (file d3d9types.h). The format can
* also be extended so that different shader formats can be supported
* for example GLSL, ARB vp/fp, NV/ATI shader formats, etc.
*
*/
#ifndef __SVGA3D_SHADER_DEFS__
#define __SVGA3D_SHADER_DEFS__
/* SVGA3D shader hardware limits. */
#define SVGA3D_INPUTREG_MAX 16
#define SVGA3D_OUTPUTREG_MAX 12
#define SVGA3D_VERTEX_SAMPLERREG_MAX 4
#define SVGA3D_PIXEL_SAMPLERREG_MAX 16
#define SVGA3D_SAMPLERREG_MAX (SVGA3D_PIXEL_SAMPLERREG_MAX+\
SVGA3D_VERTEX_SAMPLERREG_MAX)
#define SVGA3D_TEMPREG_MAX 32
#define SVGA3D_CONSTREG_MAX 256
#define SVGA3D_CONSTINTREG_MAX 16
#define SVGA3D_CONSTBOOLREG_MAX 16
#define SVGA3D_ADDRREG_MAX 1
#define SVGA3D_PREDREG_MAX 1
/* SVGA3D byte code specific limits */
#define SVGA3D_MAX_SRC_REGS 4
#define SVGA3D_MAX_NESTING_LEVEL 32
/* SVGA3D version information. */
#define SVGA3D_VS_TYPE 0xFFFE
#define SVGA3D_PS_TYPE 0xFFFF
typedef struct {
union {
struct {
uint32 minor : 8;
uint32 major : 8;
uint32 type : 16;
};
uint32 value;
};
} SVGA3dShaderVersion;
#define SVGA3D_VS_10 ((SVGA3D_VS_TYPE << 16) | 1 << 8)
#define SVGA3D_VS_11 (SVGA3D_VS_10 | 1)
#define SVGA3D_VS_20 ((SVGA3D_VS_TYPE << 16) | 2 << 8)
#define SVGA3D_VS_30 ((SVGA3D_VS_TYPE << 16) | 3 << 8)
#define SVGA3D_PS_10 ((SVGA3D_PS_TYPE << 16) | 1 << 8)
#define SVGA3D_PS_11 (SVGA3D_PS_10 | 1)
#define SVGA3D_PS_12 (SVGA3D_PS_10 | 2)
#define SVGA3D_PS_13 (SVGA3D_PS_10 | 3)
#define SVGA3D_PS_14 (SVGA3D_PS_10 | 4)
#define SVGA3D_PS_20 ((SVGA3D_PS_TYPE << 16) | 2 << 8)
#define SVGA3D_PS_30 ((SVGA3D_PS_TYPE << 16) | 3 << 8)
/* The *_ENABLED are for backwards compatibility with old drivers */
typedef enum {
SVGA3DPSVERSION_NONE = 0,
SVGA3DPSVERSION_ENABLED = 1,
SVGA3DPSVERSION_11 = 3,
SVGA3DPSVERSION_12 = 5,
SVGA3DPSVERSION_13 = 7,
SVGA3DPSVERSION_14 = 9,
SVGA3DPSVERSION_20 = 11,
SVGA3DPSVERSION_30 = 13,
SVGA3DPSVERSION_40 = 15,
SVGA3DPSVERSION_MAX
} SVGA3dPixelShaderVersion;
typedef enum {
SVGA3DVSVERSION_NONE = 0,
SVGA3DVSVERSION_ENABLED = 1,
SVGA3DVSVERSION_11 = 3,
SVGA3DVSVERSION_20 = 5,
SVGA3DVSVERSION_30 = 7,
SVGA3DVSVERSION_40 = 9,
SVGA3DVSVERSION_MAX
} SVGA3dVertexShaderVersion;
/* SVGA3D instruction op codes. */
typedef enum {
SVGA3DOP_NOP = 0,
SVGA3DOP_MOV,
SVGA3DOP_ADD,
SVGA3DOP_SUB,
SVGA3DOP_MAD,
SVGA3DOP_MUL,
SVGA3DOP_RCP,
SVGA3DOP_RSQ,
SVGA3DOP_DP3,
SVGA3DOP_DP4,
SVGA3DOP_MIN,
SVGA3DOP_MAX,
SVGA3DOP_SLT,
SVGA3DOP_SGE,
SVGA3DOP_EXP,
SVGA3DOP_LOG,
SVGA3DOP_LIT,
SVGA3DOP_DST,
SVGA3DOP_LRP,
SVGA3DOP_FRC,
SVGA3DOP_M4x4,
SVGA3DOP_M4x3,
SVGA3DOP_M3x4,
SVGA3DOP_M3x3,
SVGA3DOP_M3x2,
SVGA3DOP_CALL,
SVGA3DOP_CALLNZ,
SVGA3DOP_LOOP,
SVGA3DOP_RET,
SVGA3DOP_ENDLOOP,
SVGA3DOP_LABEL,
SVGA3DOP_DCL,
SVGA3DOP_POW,
SVGA3DOP_CRS,
SVGA3DOP_SGN,
SVGA3DOP_ABS,
SVGA3DOP_NRM,
SVGA3DOP_SINCOS,
SVGA3DOP_REP,
SVGA3DOP_ENDREP,
SVGA3DOP_IF,
SVGA3DOP_IFC,
SVGA3DOP_ELSE,
SVGA3DOP_ENDIF,
SVGA3DOP_BREAK,
SVGA3DOP_BREAKC,
SVGA3DOP_MOVA,
SVGA3DOP_DEFB,
SVGA3DOP_DEFI,
SVGA3DOP_TEXCOORD = 64,
SVGA3DOP_TEXKILL,
SVGA3DOP_TEX,
SVGA3DOP_TEXBEM,
SVGA3DOP_TEXBEML,
SVGA3DOP_TEXREG2AR,
SVGA3DOP_TEXREG2GB = 70,
SVGA3DOP_TEXM3x2PAD,
SVGA3DOP_TEXM3x2TEX,
SVGA3DOP_TEXM3x3PAD,
SVGA3DOP_TEXM3x3TEX,
SVGA3DOP_RESERVED0,
SVGA3DOP_TEXM3x3SPEC,
SVGA3DOP_TEXM3x3VSPEC,
SVGA3DOP_EXPP,
SVGA3DOP_LOGP,
SVGA3DOP_CND = 80,
SVGA3DOP_DEF,
SVGA3DOP_TEXREG2RGB,
SVGA3DOP_TEXDP3TEX,
SVGA3DOP_TEXM3x2DEPTH,
SVGA3DOP_TEXDP3,
SVGA3DOP_TEXM3x3,
SVGA3DOP_TEXDEPTH,
SVGA3DOP_CMP,
SVGA3DOP_BEM,
SVGA3DOP_DP2ADD = 90,
SVGA3DOP_DSX,
SVGA3DOP_DSY,
SVGA3DOP_TEXLDD,
SVGA3DOP_SETP,
SVGA3DOP_TEXLDL,
SVGA3DOP_BREAKP = 96,
SVGA3DOP_LAST_INST,
SVGA3DOP_PHASE = 0xFFFD,
SVGA3DOP_COMMENT = 0xFFFE,
SVGA3DOP_END = 0xFFFF,
} SVGA3dShaderOpCodeType;
/* SVGA3D operation control/comparison function types */
typedef enum {
SVGA3DOPCONT_NONE,
SVGA3DOPCONT_PROJECT, /* Projective texturing */
SVGA3DOPCONT_BIAS, /* Texturing with a LOD bias */
} SVGA3dShaderOpCodeControlFnType;
typedef enum {
SVGA3DOPCOMP_RESERVED0 = 0,
SVGA3DOPCOMP_GT,
SVGA3DOPCOMP_EQ,
SVGA3DOPCOMP_GE,
SVGA3DOPCOMP_LT,
SVGA3DOPCOMPC_NE,
SVGA3DOPCOMP_LE,
SVGA3DOPCOMP_RESERVED1
} SVGA3dShaderOpCodeCompFnType;
/* SVGA3D register types */
typedef enum {
SVGA3DREG_TEMP = 0, /* Temporary register file */
SVGA3DREG_INPUT, /* Input register file */
SVGA3DREG_CONST, /* Constant register file */
SVGA3DREG_ADDR, /* Address register for VS */
SVGA3DREG_TEXTURE = 3, /* Texture register file for PS */
SVGA3DREG_RASTOUT, /* Rasterizer register file */
SVGA3DREG_ATTROUT, /* Attribute output register file */
SVGA3DREG_TEXCRDOUT, /* Texture coordinate output register file */
SVGA3DREG_OUTPUT = 6, /* Output register file for VS 3.0+ */
SVGA3DREG_CONSTINT, /* Constant integer vector register file */
SVGA3DREG_COLOROUT, /* Color output register file */
SVGA3DREG_DEPTHOUT, /* Depth output register file */
SVGA3DREG_SAMPLER, /* Sampler state register file */
SVGA3DREG_CONST2, /* Constant register file 2048 - 4095 */
SVGA3DREG_CONST3, /* Constant register file 4096 - 6143 */
SVGA3DREG_CONST4, /* Constant register file 6144 - 8191 */
SVGA3DREG_CONSTBOOL, /* Constant boolean register file */
SVGA3DREG_LOOP, /* Loop counter register file */
SVGA3DREG_TEMPFLOAT16, /* 16-bit float temp register file */
SVGA3DREG_MISCTYPE, /* Miscellaneous (single) registers */
SVGA3DREG_LABEL, /* Label */
SVGA3DREG_PREDICATE, /* Predicate register */
} SVGA3dShaderRegType;
/* SVGA3D rasterizer output register types */
typedef enum {
SVGA3DRASTOUT_POSITION = 0,
SVGA3DRASTOUT_FOG,
SVGA3DRASTOUT_PSIZE
} SVGA3dShaderRastOutRegType;
/* SVGA3D miscellaneous register types */
typedef enum {
SVGA3DMISCREG_POSITION = 0, /* Input position x,y,z,rhw (PS) */
SVGA3DMISCREG_FACE /* Floating point primitive area (PS) */
} SVGA3DShaderMiscRegType;
/* SVGA3D sampler types */
typedef enum {
SVGA3DSAMP_UNKNOWN = 0, /* Uninitialized value */
SVGA3DSAMP_2D = 2, /* dcl_2d s# (for declaring a 2-D texture) */
SVGA3DSAMP_CUBE, /* dcl_cube s# (for declaring a cube texture) */
SVGA3DSAMP_VOLUME, /* dcl_volume s# (for declaring a volume texture) */
} SVGA3dShaderSamplerType;
/* SVGA3D sampler format classes */
typedef enum {
SVGA3DSAMPFORMAT_ARGB, /* ARGB formats */
SVGA3DSAMPFORMAT_V8U8, /* Sign and normalize (SNORM) V & U */
SVGA3DSAMPFORMAT_Q8W8V8U8, /* SNORM all */
SVGA3DSAMPFORMAT_CxV8U8, /* SNORM V & U, C=SQRT(1-U^2-V^2) */
SVGA3DSAMPFORMAT_X8L8V8U8, /* SNORM V & U */
SVGA3DSAMPFORMAT_A2W10V10U10, /* SNORM W, V & U */
SVGA3DSAMPFORMAT_DXT_PMA, /* DXT pre-multiplied alpha */
SVGA3DSAMPFORMAT_YUV, /* YUV video format */
SVGA3DSAMPFORMAT_UYVY, /* UYVY video format */
SVGA3DSAMPFORMAT_Rx, /* R16F/32F */
SVGA3DSAMPFORMAT_RxGx, /* R16FG16F, R32FG32F */
SVGA3DSAMPFORMAT_V16U16, /* SNORM all */
} SVGA3DShaderSamplerFormatClass;
/* SVGA3D write mask */
#define SVGA3DWRITEMASK_0 1 /* Component 0 (X;Red) */
#define SVGA3DWRITEMASK_1 2 /* Component 1 (Y;Green) */
#define SVGA3DWRITEMASK_2 4 /* Component 2 (Z;Blue) */
#define SVGA3DWRITEMASK_3 8 /* Component 3 (W;Alpha) */
#define SVGA3DWRITEMASK_ALL 15 /* All components */
/* SVGA3D destination modifiers */
#define SVGA3DDSTMOD_NONE 0 /* nop */
#define SVGA3DDSTMOD_SATURATE 1 /* clamp to [0, 1] */
#define SVGA3DDSTMOD_PARTIALPRECISION 2 /* Partial precision hint */
/*
* Relevant to multisampling only:
* When the pixel center is not covered, sample
* attribute or compute gradients/LOD
* using multisample "centroid" location.
* "Centroid" is some location within the covered
* region of the pixel.
*/
#define SVGA3DDSTMOD_MSAMPCENTROID 4
/* SVGA3D source swizzle */
#define SVGA3DSWIZZLE_REPLICATEX 0x00
#define SVGA3DSWIZZLE_REPLICATEY 0x55
#define SVGA3DSWIZZLE_REPLICATEZ 0xAA
#define SVGA3DSWIZZLE_REPLICATEW 0xFF
#define SVGA3DSWIZZLE_NONE 0xE4
#define SVGA3DSWIZZLE_YZXW 0xC9
#define SVGA3DSWIZZLE_ZXYW 0xD2
#define SVGA3DSWIZZLE_WXYZ 0x1B
/* SVGA3D source modifiers */
typedef enum {
SVGA3DSRCMOD_NONE = 0, /* nop */
SVGA3DSRCMOD_NEG, /* negate */
SVGA3DSRCMOD_BIAS, /* bias */
SVGA3DSRCMOD_BIASNEG, /* bias and negate */
SVGA3DSRCMOD_SIGN, /* sign */
SVGA3DSRCMOD_SIGNNEG, /* sign and negate */
SVGA3DSRCMOD_COMP, /* complement */
SVGA3DSRCMOD_X2, /* x2 */
SVGA3DSRCMOD_X2NEG, /* x2 and negate */
SVGA3DSRCMOD_DZ, /* divide through by z component */
SVGA3DSRCMOD_DW, /* divide through by w component */
SVGA3DSRCMOD_ABS, /* abs() */
SVGA3DSRCMOD_ABSNEG, /* -abs() */
SVGA3DSRCMOD_NOT, /* ! (for predicate register) */
} SVGA3dShaderSrcModType;
/* SVGA3D instruction token */
typedef struct {
union {
struct {
uint32 comment_op : 16;
uint32 comment_size : 16;
};
struct {
uint32 op : 16;
uint32 control : 3;
uint32 reserved2 : 5;
uint32 size : 4;
uint32 predicated : 1;
uint32 reserved1 : 1;
uint32 coissue : 1;
uint32 reserved0 : 1;
};
uint32 value;
};
} SVGA3dShaderInstToken;
/* SVGA3D destination parameter token */
typedef struct {
union {
struct {
uint32 num : 11;
uint32 type_upper : 2;
uint32 relAddr : 1;
uint32 reserved1 : 2;
uint32 mask : 4;
uint32 dstMod : 4;
uint32 shfScale : 4;
uint32 type_lower : 3;
uint32 reserved0 : 1;
};
uint32 value;
};
} SVGA3dShaderDestToken;
/* SVGA3D source parameter token */
typedef struct {
union {
struct {
uint32 num : 11;
uint32 type_upper : 2;
uint32 relAddr : 1;
uint32 reserved1 : 2;
uint32 swizzle : 8;
uint32 srcMod : 4;
uint32 type_lower : 3;
uint32 reserved0 : 1;
};
uint32 value;
};
} SVGA3dShaderSrcToken;
/* SVGA3DOP_DCL parameter tokens */
typedef struct {
union {
struct {
union {
struct {
uint32 usage : 5;
uint32 reserved1 : 11;
uint32 index : 4;
uint32 reserved0 : 12;
}; /* input / output declaration */
struct {
uint32 reserved3 : 27;
uint32 type : 4;
uint32 reserved2 : 1;
}; /* sampler declaration */
};
SVGA3dShaderDestToken dst;
};
uint32 values[2];
};
} SVGA3DOpDclArgs;
/* SVGA3DOP_DEF parameter tokens */
typedef struct {
union {
struct {
SVGA3dShaderDestToken dst;
union {
float constValues[4];
int constIValues[4];
Bool constBValue;
};
};
uint32 values[5];
};
} SVGA3DOpDefArgs;
/* SVGA3D shader token */
typedef union {
uint32 value;
SVGA3dShaderInstToken inst;
SVGA3dShaderDestToken dest;
SVGA3dShaderSrcToken src;
} SVGA3dShaderToken;
/* SVGA3D shader program */
typedef struct {
SVGA3dShaderVersion version;
/* SVGA3dShaderToken stream */
} SVGA3dShaderProgram;
/* SVGA3D version specific register assignments */
static const uint32 SVGA3D_INPUT_REG_POSITION_VS11 = 0;
static const uint32 SVGA3D_INPUT_REG_PSIZE_VS11 = 1;
static const uint32 SVGA3D_INPUT_REG_FOG_VS11 = 3;
static const uint32 SVGA3D_INPUT_REG_FOG_MASK_VS11 = SVGA3DWRITEMASK_3;
static const uint32 SVGA3D_INPUT_REG_COLOR_BASE_VS11 = 2;
static const uint32 SVGA3D_INPUT_REG_TEXCOORD_BASE_VS11 = 4;
static const uint32 SVGA3D_INPUT_REG_COLOR_BASE_PS11 = 0;
static const uint32 SVGA3D_INPUT_REG_TEXCOORD_BASE_PS11 = 2;
static const uint32 SVGA3D_OUTPUT_REG_DEPTH_PS11 = 0;
static const uint32 SVGA3D_OUTPUT_REG_COLOR_PS11 = 1;
static const uint32 SVGA3D_INPUT_REG_COLOR_BASE_PS20 = 0;
static const uint32 SVGA3D_INPUT_REG_COLOR_NUM_PS20 = 2;
static const uint32 SVGA3D_INPUT_REG_TEXCOORD_BASE_PS20 = 2;
static const uint32 SVGA3D_INPUT_REG_TEXCOORD_NUM_PS20 = 8;
static const uint32 SVGA3D_OUTPUT_REG_COLOR_BASE_PS20 = 1;
static const uint32 SVGA3D_OUTPUT_REG_COLOR_NUM_PS20 = 4;
static const uint32 SVGA3D_OUTPUT_REG_DEPTH_BASE_PS20 = 0;
static const uint32 SVGA3D_OUTPUT_REG_DEPTH_NUM_PS20 = 1;
/*
*----------------------------------------------------------------------
*
* SVGA3dShaderGetRegType --
*
* As the register type is split into two non sequential fields,
* this function provides an useful way of accessing the actual
* register type without having to manually concatenate the
* type_upper and type_lower fields.
*
* Results:
* Returns the register type.
*
*----------------------------------------------------------------------
*/
static INLINE SVGA3dShaderRegType
SVGA3dShaderGetRegType(uint32 token)
{
SVGA3dShaderSrcToken src;
src.value = token;
return (SVGA3dShaderRegType)(src.type_upper << 3 | src.type_lower);
}
#endif /* __SVGA3D_SHADER_DEFS__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
/**********************************************************
* Copyright 1998-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.
*
**********************************************************/
#ifndef _SVGA_TYPES_H_
#define _SVGA_TYPES_H_
#include "pipe/p_compiler.h"
typedef int64_t int64;
typedef uint64_t uint64;
typedef int32_t int32;
typedef uint32_t uint32;
typedef int16_t int16;
typedef uint16_t uint16;
typedef int8_t int8;
typedef uint8_t uint8;
typedef uint8_t Bool;
#endif /* _SVGA_TYPES_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,235 @@
/**********************************************************
* 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.h --
*
* Command construction utility for the SVGA3D protocol used by
* the VMware SVGA device, based on the svgautil library.
*/
#ifndef __SVGA3D_H__
#define __SVGA3D_H__
#include "svga_types.h"
#include "svga_reg.h"
#include "svga3d_reg.h"
#include "pipe/p_defines.h"
struct pipe_buffer;
struct pipe_surface;
struct svga_transfer;
struct svga_winsys_context;
struct svga_winsys_buffer;
struct svga_winsys_surface;
/*
* SVGA Device Interoperability
*/
void *
SVGA3D_FIFOReserve(struct svga_winsys_context *swc, uint32 cmd, uint32 cmdSize, uint32 nr_relocs);
void
SVGA_FIFOCommitAll(struct svga_winsys_context *swc);
/*
* Context Management
*/
enum pipe_error
SVGA3D_DefineContext(struct svga_winsys_context *swc);
enum pipe_error
SVGA3D_DestroyContext(struct svga_winsys_context *swc);
/*
* Surface Management
*/
enum pipe_error
SVGA3D_BeginDefineSurface(struct svga_winsys_context *swc,
struct svga_winsys_surface *sid,
SVGA3dSurfaceFlags flags,
SVGA3dSurfaceFormat format,
SVGA3dSurfaceFace **faces,
SVGA3dSize **mipSizes,
uint32 numMipSizes);
enum pipe_error
SVGA3D_DefineSurface2D(struct svga_winsys_context *swc,
struct svga_winsys_surface *sid,
uint32 width,
uint32 height,
SVGA3dSurfaceFormat format);
enum pipe_error
SVGA3D_DestroySurface(struct svga_winsys_context *swc,
struct svga_winsys_surface *sid);
/*
* Surface Operations
*/
enum pipe_error
SVGA3D_SurfaceDMA(struct svga_winsys_context *swc,
struct svga_transfer *st,
SVGA3dTransferType transfer,
const SVGA3dCopyBox *boxes,
uint32 numBoxes);
enum pipe_error
SVGA3D_BufferDMA(struct svga_winsys_context *swc,
struct svga_winsys_buffer *guest,
struct svga_winsys_surface *host,
SVGA3dTransferType transfer,
uint32 size,
uint32 offset,
SVGA3dSurfaceDMAFlags flags);
/*
* Drawing Operations
*/
enum pipe_error
SVGA3D_BeginClear(struct svga_winsys_context *swc,
SVGA3dClearFlag flags,
uint32 color, float depth, uint32 stencil,
SVGA3dRect **rects, uint32 numRects);
enum pipe_error
SVGA3D_ClearRect(struct svga_winsys_context *swc,
SVGA3dClearFlag flags, uint32 color, float depth,
uint32 stencil, uint32 x, uint32 y, uint32 w, uint32 h);
enum pipe_error
SVGA3D_BeginDrawPrimitives(struct svga_winsys_context *swc,
SVGA3dVertexDecl **decls,
uint32 numVertexDecls,
SVGA3dPrimitiveRange **ranges,
uint32 numRanges);
/*
* Blits
*/
enum pipe_error
SVGA3D_BeginSurfaceCopy(struct svga_winsys_context *swc,
struct pipe_surface *src,
struct pipe_surface *dest,
SVGA3dCopyBox **boxes, uint32 numBoxes);
enum pipe_error
SVGA3D_SurfaceStretchBlt(struct svga_winsys_context *swc,
struct pipe_surface *src,
struct pipe_surface *dest,
SVGA3dBox *boxSrc, SVGA3dBox *boxDest,
SVGA3dStretchBltMode mode);
/*
* Shared FFP/Shader Render State
*/
enum pipe_error
SVGA3D_SetRenderTarget(struct svga_winsys_context *swc,
SVGA3dRenderTargetType type,
struct pipe_surface *surface);
enum pipe_error
SVGA3D_SetZRange(struct svga_winsys_context *swc,
float zMin, float zMax);
enum pipe_error
SVGA3D_SetViewport(struct svga_winsys_context *swc,
SVGA3dRect *rect);
enum pipe_error
SVGA3D_SetScissorRect(struct svga_winsys_context *swc,
SVGA3dRect *rect);
enum pipe_error
SVGA3D_SetClipPlane(struct svga_winsys_context *swc,
uint32 index, const float *plane);
enum pipe_error
SVGA3D_BeginSetTextureState(struct svga_winsys_context *swc,
SVGA3dTextureState **states,
uint32 numStates);
enum pipe_error
SVGA3D_BeginSetRenderState(struct svga_winsys_context *swc,
SVGA3dRenderState **states,
uint32 numStates);
/*
* Shaders
*/
enum pipe_error
SVGA3D_DefineShader(struct svga_winsys_context *swc,
uint32 shid, SVGA3dShaderType type,
const uint32 *bytecode, uint32 bytecodeLen);
enum pipe_error
SVGA3D_DestroyShader(struct svga_winsys_context *swc,
uint32 shid, SVGA3dShaderType type);
enum pipe_error
SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
uint32 reg, SVGA3dShaderType type,
SVGA3dShaderConstType ctype, const void *value);
enum pipe_error
SVGA3D_SetShader(struct svga_winsys_context *swc,
SVGA3dShaderType type, uint32 shid);
/*
* Queries
*/
enum pipe_error
SVGA3D_BeginQuery(struct svga_winsys_context *swc,
SVGA3dQueryType type);
enum pipe_error
SVGA3D_EndQuery(struct svga_winsys_context *swc,
SVGA3dQueryType type,
struct svga_winsys_buffer *buffer);
enum pipe_error
SVGA3D_WaitForQuery(struct svga_winsys_context *swc,
SVGA3dQueryType type,
struct svga_winsys_buffer *buffer);
#endif /* __SVGA3D_H__ */

View file

@ -0,0 +1,269 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_screen.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_texture.h"
#include "svga_screen_buffer.h"
#include "svga_winsys.h"
#include "svga_swtnl.h"
#include "svga_draw.h"
#include "svga_debug.h"
#include "svga_state.h"
static void svga_destroy( struct pipe_context *pipe )
{
struct svga_context *svga = svga_context( pipe );
unsigned shader;
svga_cleanup_framebuffer( svga );
svga_cleanup_tss_binding( svga );
svga_hwtnl_destroy( svga->hwtnl );
svga_cleanup_vertex_state(svga);
svga->swc->destroy(svga->swc);
svga_destroy_swtnl( svga );
u_upload_destroy( svga->upload_vb );
u_upload_destroy( svga->upload_ib );
for(shader = 0; shader < PIPE_SHADER_TYPES; ++shader)
pipe_buffer_reference( &svga->curr.cb[shader], NULL );
FREE( svga );
}
static unsigned int
svga_is_texture_referenced( struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face, unsigned level)
{
struct svga_texture *tex = svga_texture(texture);
struct svga_screen *ss = svga_screen(pipe->screen);
/**
* The screen does not cache texture writes.
*/
if (!tex->handle || ss->sws->surface_is_flushed(ss->sws, tex->handle))
return PIPE_UNREFERENCED;
/**
* sws->surface_is_flushed() does not distinguish between read references
* and write references. So assume a reference is both.
*/
return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}
static unsigned int
svga_is_buffer_referenced( struct pipe_context *pipe,
struct pipe_buffer *buf)
{
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_buffer *sbuf = svga_buffer(buf);
/**
* XXX: Check this.
* The screen may cache buffer writes, but when we map, we map out
* of those cached writes, so we don't need to set a
* PIPE_REFERENCED_FOR_WRITE flag for cached buffers.
*/
if (!sbuf->handle || ss->sws->surface_is_flushed(ss->sws, sbuf->handle))
return PIPE_UNREFERENCED;
/**
* sws->surface_is_flushed() does not distinguish between read references
* and write references. So assume a reference is both,
* however, we make an exception for index- and vertex buffers, to avoid
* a flush in st_bufferobj_get_subdata, during display list replay.
*/
if (sbuf->base.usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_INDEX))
return PIPE_REFERENCED_FOR_READ;
return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
}
struct pipe_context *svga_context_create( struct pipe_screen *screen )
{
struct svga_screen *svgascreen = svga_screen(screen);
struct svga_context *svga = NULL;
enum pipe_error ret;
svga = CALLOC_STRUCT(svga_context);
if (svga == NULL)
goto error1;
svga->pipe.winsys = screen->winsys;
svga->pipe.screen = screen;
svga->pipe.destroy = svga_destroy;
svga->pipe.clear = svga_clear;
svga->pipe.is_texture_referenced = svga_is_texture_referenced;
svga->pipe.is_buffer_referenced = svga_is_buffer_referenced;
svga->swc = svgascreen->sws->context_create(svgascreen->sws);
if(!svga->swc)
goto error2;
svga_init_blend_functions(svga);
svga_init_blit_functions(svga);
svga_init_depth_stencil_functions(svga);
svga_init_draw_functions(svga);
svga_init_flush_functions(svga);
svga_init_misc_functions(svga);
svga_init_rasterizer_functions(svga);
svga_init_sampler_functions(svga);
svga_init_fs_functions(svga);
svga_init_vs_functions(svga);
svga_init_vertex_functions(svga);
svga_init_constbuffer_functions(svga);
svga_init_query_functions(svga);
/* debug */
svga->debug.no_swtnl = debug_get_bool_option("SVGA_NO_SWTNL", FALSE);
svga->debug.force_swtnl = debug_get_bool_option("SVGA_FORCE_SWTNL", FALSE);
svga->debug.use_min_mipmap = debug_get_bool_option("SVGA_USE_MIN_MIPMAP", FALSE);
svga->debug.disable_shader = debug_get_num_option("SVGA_DISABLE_SHADER", ~0);
if (!svga_init_swtnl(svga))
goto error3;
svga->upload_ib = u_upload_create( svga->pipe.screen,
32 * 1024,
16,
PIPE_BUFFER_USAGE_INDEX );
if (svga->upload_ib == NULL)
goto error4;
svga->upload_vb = u_upload_create( svga->pipe.screen,
128 * 1024,
16,
PIPE_BUFFER_USAGE_VERTEX );
if (svga->upload_vb == NULL)
goto error5;
svga->hwtnl = svga_hwtnl_create( svga,
svga->upload_ib,
svga->swc );
if (svga->hwtnl == NULL)
goto error6;
ret = svga_emit_initial_state( svga );
if (ret)
goto error7;
/* Avoid shortcircuiting state with initial value of zero.
*/
memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear));
memset(&svga->state.hw_clear.framebuffer, 0x0,
sizeof(svga->state.hw_clear.framebuffer));
memset(&svga->state.hw_draw, 0xcd, sizeof(svga->state.hw_draw));
memset(&svga->state.hw_draw.views, 0x0, sizeof(svga->state.hw_draw.views));
svga->state.hw_draw.num_views = 0;
svga->dirty = ~0;
svga->state.white_fs_id = SVGA3D_INVALID_ID;
LIST_INITHEAD(&svga->dirty_buffers);
return &svga->pipe;
error7:
svga_hwtnl_destroy( svga->hwtnl );
error6:
u_upload_destroy( svga->upload_vb );
error5:
u_upload_destroy( svga->upload_ib );
error4:
svga_destroy_swtnl(svga);
error3:
svga->swc->destroy(svga->swc);
error2:
FREE(svga);
error1:
return NULL;
}
void svga_context_flush( struct svga_context *svga,
struct pipe_fence_handle **pfence )
{
struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
/* Unmap upload manager buffers:
*/
u_upload_flush(svga->upload_vb);
u_upload_flush(svga->upload_ib);
/* Flush screen, to ensure that texture dma uploads are processed
* before submitting commands.
*/
svga_screen_flush(svgascreen, NULL);
svga_context_flush_buffers(svga);
/* Flush pending commands to hardware:
*/
svga->swc->flush(svga->swc, pfence);
if (SVGA_DEBUG & DEBUG_SYNC) {
if (pfence && *pfence)
svga->pipe.screen->fence_finish( svga->pipe.screen, *pfence, 0);
}
}
void svga_hwtnl_flush_retry( struct svga_context *svga )
{
enum pipe_error ret = PIPE_OK;
ret = svga_hwtnl_flush( svga->hwtnl );
if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
svga_context_flush( svga, NULL );
ret = svga_hwtnl_flush( svga->hwtnl );
}
assert(ret == 0);
}

View file

@ -0,0 +1,443 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_CONTEXT_H
#define SVGA_CONTEXT_H
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "util/u_double_list.h"
#include "tgsi/tgsi_scan.h"
#define SVGA_TEX_UNITS 8
struct draw_vertex_shader;
struct svga_shader_result;
struct SVGACmdMemory;
struct u_upload_mgr;
struct svga_shader
{
const struct tgsi_token *tokens;
struct tgsi_shader_info info;
struct svga_shader_result *results;
unsigned id;
boolean use_sm30;
};
struct svga_fragment_shader
{
struct svga_shader base;
};
struct svga_vertex_shader
{
struct svga_shader base;
struct draw_vertex_shader *draw_shader;
};
struct svga_cache_context;
struct svga_tracked_state;
struct svga_blend_state {
boolean need_white_fragments;
/* Should be per-render-target:
*/
struct {
uint8_t writemask;
boolean blend_enable;
uint8_t srcblend;
uint8_t dstblend;
uint8_t blendeq;
boolean separate_alpha_blend_enable;
uint8_t srcblend_alpha;
uint8_t dstblend_alpha;
uint8_t blendeq_alpha;
} rt[1];
};
struct svga_depth_stencil_state {
unsigned zfunc:8;
unsigned zenable:1;
unsigned zwriteenable:1;
unsigned alphatestenable:1;
unsigned alphafunc:8;
struct {
unsigned enabled:1;
unsigned func:8;
unsigned fail:8;
unsigned zfail:8;
unsigned pass:8;
} stencil[2];
/* SVGA3D has one ref/mask/writemask triple shared between front &
* back face stencil. We really need two:
*/
unsigned stencil_ref:8;
unsigned stencil_mask:8;
unsigned stencil_writemask:8;
float alpharef;
};
#define SVGA_UNFILLED_DISABLE 0
#define SVGA_UNFILLED_LINE 1
#define SVGA_UNFILLED_POINT 2
#define SVGA_PIPELINE_FLAG_POINTS (1<<PIPE_PRIM_POINTS)
#define SVGA_PIPELINE_FLAG_LINES (1<<PIPE_PRIM_LINES)
#define SVGA_PIPELINE_FLAG_TRIS (1<<PIPE_PRIM_TRIANGLES)
struct svga_rasterizer_state {
struct pipe_rasterizer_state templ; /* needed for draw module */
unsigned shademode:8;
unsigned cullmode:8;
unsigned scissortestenable:1;
unsigned multisampleantialias:1;
unsigned antialiasedlineenable:1;
unsigned lastpixel:1;
unsigned linepattern;
float slopescaledepthbias;
float depthbias;
float pointsize;
float pointsize_min;
float pointsize_max;
unsigned hw_unfilled:16; /* PIPE_POLYGON_MODE_x */
unsigned need_pipeline:16; /* which prims do we need help for? */
};
struct svga_sampler_state {
unsigned mipfilter;
unsigned magfilter;
unsigned minfilter;
unsigned aniso_level;
float lod_bias;
unsigned addressu;
unsigned addressv;
unsigned addressw;
unsigned bordercolor;
unsigned normalized_coords:1;
unsigned compare_mode:1;
unsigned compare_func:3;
unsigned min_lod;
unsigned view_min_lod;
unsigned view_max_lod;
};
/* Use to calculate differences between state emitted to hardware and
* current driver-calculated state.
*/
struct svga_state
{
const struct svga_blend_state *blend;
const struct svga_depth_stencil_state *depth;
const struct svga_rasterizer_state *rast;
const struct svga_sampler_state *sampler[PIPE_MAX_SAMPLERS];
struct pipe_texture *texture[PIPE_MAX_SAMPLERS]; /* or texture ID's? */
struct svga_fragment_shader *fs;
struct svga_vertex_shader *vs;
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
struct pipe_buffer *cb[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
float depthscale;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
struct pipe_viewport_state viewport;
const unsigned *edgeflags;
unsigned num_samplers;
unsigned num_textures;
unsigned num_vertex_elements;
unsigned num_vertex_buffers;
unsigned reduced_prim;
struct {
unsigned flag_1d;
unsigned flag_srgb;
} tex_flags;
boolean any_user_vertex_buffers;
unsigned zero_stride_vertex_elements;
unsigned num_zero_stride_vertex_elements;
/* ### maybe dynamically allocate this */
float zero_stride_constants[PIPE_MAX_ATTRIBS*4];
};
#define RS_MAX 97
#define TS_MAX 30
#define CB_MAX 256
struct svga_prescale {
float translate[4];
float scale[4];
boolean enabled;
};
/* Updated by calling svga_update_state( SVGA_STATE_HW_VIEWPORT )
*/
struct svga_hw_clear_state
{
struct {
unsigned x,y,w,h;
} viewport;
struct {
float zmin, zmax;
} depthrange;
struct pipe_framebuffer_state framebuffer;
struct svga_prescale prescale;
};
struct svga_hw_view_state
{
struct pipe_texture *texture;
struct svga_sampler_view *v;
unsigned min_lod;
unsigned max_lod;
int dirty;
};
/* Updated by calling svga_update_state( SVGA_STATE_HW_DRAW )
*/
struct svga_hw_draw_state
{
unsigned rs[RS_MAX];
unsigned ts[16][TS_MAX];
float cb[PIPE_SHADER_TYPES][CB_MAX][4];
unsigned shader_id[PIPE_SHADER_TYPES];
struct svga_shader_result *fs;
struct svga_shader_result *vs;
struct svga_hw_view_state views[PIPE_MAX_SAMPLERS];
unsigned num_views;
};
/* Updated by calling svga_update_state( SVGA_STATE_NEED_SWTNL )
*/
struct svga_sw_state
{
unsigned ve_format[PIPE_MAX_ATTRIBS]; /* NEW_VELEMENT */
/* which parts we need */
boolean need_swvfetch;
boolean need_pipeline;
boolean need_swtnl;
};
/* Queue some state updates (like rss) and submit them to hardware in
* a single packet.
*/
struct svga_hw_queue;
struct svga_query;
struct svga_context
{
struct pipe_context pipe;
struct svga_winsys_context *swc;
struct {
boolean no_swtnl;
boolean force_swtnl;
boolean use_min_mipmap;
/* incremented for each shader */
unsigned shader_id;
unsigned disable_shader;
} debug;
struct {
struct draw_context *draw;
struct vbuf_render *backend;
unsigned hw_prim;
boolean new_vbuf;
boolean new_vdecl;
} swtnl;
struct {
unsigned dirty[4];
unsigned texture_timestamp;
unsigned next_fs_id;
unsigned next_vs_id;
/* Internally generated shaders:
*/
unsigned white_fs_id;
/*
*/
struct svga_sw_state sw;
struct svga_hw_draw_state hw_draw;
struct svga_hw_clear_state hw_clear;
} state;
struct svga_state curr; /* state from the state tracker */
unsigned dirty; /* statechanges since last update_state() */
struct u_upload_mgr *upload_ib;
struct u_upload_mgr *upload_vb;
struct svga_hwtnl *hwtnl;
/** The occlusion query currently in progress */
struct svga_query *sq;
/** List of buffers with queued transfers */
struct list_head dirty_buffers;
};
/* A flag for each state_tracker state object:
*/
#define SVGA_NEW_BLEND 0x1
#define SVGA_NEW_DEPTH_STENCIL 0x2
#define SVGA_NEW_RAST 0x4
#define SVGA_NEW_SAMPLER 0x8
#define SVGA_NEW_TEXTURE 0x10
#define SVGA_NEW_VBUFFER 0x20
#define SVGA_NEW_VELEMENT 0x40
#define SVGA_NEW_FS 0x80
#define SVGA_NEW_VS 0x100
#define SVGA_NEW_FS_CONST_BUFFER 0x200
#define SVGA_NEW_VS_CONST_BUFFER 0x400
#define SVGA_NEW_FRAME_BUFFER 0x800
#define SVGA_NEW_STIPPLE 0x1000
#define SVGA_NEW_SCISSOR 0x2000
#define SVGA_NEW_BLEND_COLOR 0x5000
#define SVGA_NEW_CLIP 0x8000
#define SVGA_NEW_VIEWPORT 0x10000
#define SVGA_NEW_PRESCALE 0x20000
#define SVGA_NEW_REDUCED_PRIMITIVE 0x40000
#define SVGA_NEW_TEXTURE_BINDING 0x80000
#define SVGA_NEW_NEED_PIPELINE 0x100000
#define SVGA_NEW_NEED_SWVFETCH 0x200000
#define SVGA_NEW_NEED_SWTNL 0x400000
#define SVGA_NEW_FS_RESULT 0x800000
#define SVGA_NEW_VS_RESULT 0x1000000
#define SVGA_NEW_EDGEFLAGS 0x2000000
#define SVGA_NEW_ZERO_STRIDE 0x4000000
#define SVGA_NEW_TEXTURE_FLAGS 0x8000000
/***********************************************************************
* svga_clear.c:
*/
void svga_clear(struct pipe_context *pipe,
unsigned buffers,
const float *rgba,
double depth,
unsigned stencil);
/***********************************************************************
* svga_screen_texture.c:
*/
void svga_mark_surfaces_dirty(struct svga_context *svga);
void svga_init_state_functions( struct svga_context *svga );
void svga_init_flush_functions( struct svga_context *svga );
void svga_init_string_functions( struct svga_context *svga );
void svga_init_blit_functions(struct svga_context *svga);
void svga_init_blend_functions( struct svga_context *svga );
void svga_init_depth_stencil_functions( struct svga_context *svga );
void svga_init_misc_functions( struct svga_context *svga );
void svga_init_rasterizer_functions( struct svga_context *svga );
void svga_init_sampler_functions( struct svga_context *svga );
void svga_init_fs_functions( struct svga_context *svga );
void svga_init_vs_functions( struct svga_context *svga );
void svga_init_vertex_functions( struct svga_context *svga );
void svga_init_constbuffer_functions( struct svga_context *svga );
void svga_init_draw_functions( struct svga_context *svga );
void svga_init_query_functions( struct svga_context *svga );
void svga_cleanup_vertex_state( struct svga_context *svga );
void svga_cleanup_tss_binding( struct svga_context *svga );
void svga_cleanup_framebuffer( struct svga_context *svga );
void svga_context_flush( struct svga_context *svga,
struct pipe_fence_handle **pfence );
void svga_hwtnl_flush_retry( struct svga_context *svga );
/***********************************************************************
* Inline conversion functions. These are better-typed than the
* macros used previously:
*/
static INLINE struct svga_context *
svga_context( struct pipe_context *pipe )
{
return (struct svga_context *)pipe;
}
#endif

View file

@ -0,0 +1,74 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_DEBUG_H
#define SVGA_DEBUG_H
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#define DEBUG_DMA 0x1
#define DEBUG_TGSI 0x4
#define DEBUG_PIPE 0x8
#define DEBUG_STATE 0x10
#define DEBUG_SCREEN 0x20
#define DEBUG_TEX 0x40
#define DEBUG_SWTNL 0x80
#define DEBUG_CONSTS 0x100
#define DEBUG_VIEWPORT 0x200
#define DEBUG_VIEWS 0x400
#define DEBUG_PERF 0x800 /* print something when we hit any slow path operation */
#define DEBUG_FLUSH 0x1000 /* flush after every draw */
#define DEBUG_SYNC 0x2000 /* sync after every flush */
#define DEBUG_QUERY 0x4000
#ifdef DEBUG
extern int SVGA_DEBUG;
#define DBSTR(x) x
#else
#define SVGA_DEBUG 0
#define DBSTR(x) ""
#endif
static INLINE void
SVGA_DBG( unsigned flag, const char *fmt, ... )
{
#ifdef DEBUG
if (SVGA_DEBUG & flag)
{
va_list args;
va_start( args, fmt );
debug_vprintf( fmt, args );
va_end( args );
}
#else
(void)flag;
(void)fmt;
#endif
}
#endif

View file

@ -0,0 +1,370 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_compiler.h"
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "svga_draw.h"
#include "svga_draw_private.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_winsys.h"
#include "svga_cmd.h"
struct svga_hwtnl *svga_hwtnl_create( struct svga_context *svga,
struct u_upload_mgr *upload_ib,
struct svga_winsys_context *swc )
{
struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl);
if (hwtnl == NULL)
goto fail;
hwtnl->svga = svga;
hwtnl->upload_ib = upload_ib;
hwtnl->cmd.swc = swc;
return hwtnl;
fail:
return NULL;
}
void svga_hwtnl_destroy( struct svga_hwtnl *hwtnl )
{
int i, j;
for (i = 0; i < PIPE_PRIM_MAX; i++) {
for (j = 0; j < IDX_CACHE_MAX; j++) {
pipe_buffer_reference( &hwtnl->index_cache[i][j].buffer,
NULL );
}
}
for (i = 0; i < hwtnl->cmd.vdecl_count; i++)
pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i], NULL);
for (i = 0; i < hwtnl->cmd.prim_count; i++)
pipe_buffer_reference(&hwtnl->cmd.prim_ib[i], NULL);
FREE(hwtnl);
}
void svga_hwtnl_set_flatshade( struct svga_hwtnl *hwtnl,
boolean flatshade,
boolean flatshade_first )
{
hwtnl->hw_pv = PV_FIRST;
hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST;
}
void svga_hwtnl_set_unfilled( struct svga_hwtnl *hwtnl,
unsigned mode )
{
hwtnl->api_fillmode = mode;
}
void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl,
unsigned count )
{
unsigned i;
assert(hwtnl->cmd.prim_count == 0);
for (i = count; i < hwtnl->cmd.vdecl_count; i++) {
pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i],
NULL);
}
hwtnl->cmd.vdecl_count = count;
}
void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl,
unsigned i,
const SVGA3dVertexDecl *decl,
struct pipe_buffer *vb)
{
assert(hwtnl->cmd.prim_count == 0);
assert( i < hwtnl->cmd.vdecl_count );
hwtnl->cmd.vdecl[i] = *decl;
pipe_buffer_reference(&hwtnl->cmd.vdecl_vb[i],
vb);
}
enum pipe_error
svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
{
struct svga_winsys_context *swc = hwtnl->cmd.swc;
struct svga_context *svga = hwtnl->svga;
enum pipe_error ret;
if (hwtnl->cmd.prim_count) {
struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
struct svga_winsys_surface *ib_handle[QSZ];
struct svga_winsys_surface *handle;
SVGA3dVertexDecl *vdecl;
SVGA3dPrimitiveRange *prim;
unsigned i;
for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
if (handle == NULL)
return PIPE_ERROR_OUT_OF_MEMORY;
vb_handle[i] = handle;
}
for (i = 0; i < hwtnl->cmd.prim_count; i++) {
if (hwtnl->cmd.prim_ib[i]) {
handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
if (handle == NULL)
return PIPE_ERROR_OUT_OF_MEMORY;
}
else
handle = NULL;
ib_handle[i] = handle;
}
ret = SVGA3D_BeginDrawPrimitives(swc,
&vdecl,
hwtnl->cmd.vdecl_count,
&prim,
hwtnl->cmd.prim_count);
if (ret != PIPE_OK)
return ret;
memcpy( vdecl,
hwtnl->cmd.vdecl,
hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);
for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
/* Given rangeHint is considered to be relative to indexBias, and
* indexBias varies per primitive, we cannot accurately supply an
* rangeHint when emitting more than one primitive per draw command.
*/
if (hwtnl->cmd.prim_count == 1) {
vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
}
else {
vdecl[i].rangeHint.first = 0;
vdecl[i].rangeHint.last = 0;
}
swc->surface_relocation(swc,
&vdecl[i].array.surfaceId,
vb_handle[i],
PIPE_BUFFER_USAGE_GPU_READ);
}
memcpy( prim,
hwtnl->cmd.prim,
hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);
for (i = 0; i < hwtnl->cmd.prim_count; i++) {
swc->surface_relocation(swc,
&prim[i].indexArray.surfaceId,
ib_handle[i],
PIPE_BUFFER_USAGE_GPU_READ);
pipe_buffer_reference(&hwtnl->cmd.prim_ib[i], NULL);
}
SVGA_FIFOCommitAll( swc );
hwtnl->cmd.prim_count = 0;
}
return PIPE_OK;
}
/***********************************************************************
* Internal functions:
*/
enum pipe_error svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
const SVGA3dPrimitiveRange *range,
unsigned min_index,
unsigned max_index,
struct pipe_buffer *ib )
{
int ret = PIPE_OK;
#ifdef DEBUG
{
unsigned i;
for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
struct pipe_buffer *vb = hwtnl->cmd.vdecl_vb[i];
unsigned size = vb ? vb->size : 0;
unsigned offset = hwtnl->cmd.vdecl[i].array.offset;
unsigned stride = hwtnl->cmd.vdecl[i].array.stride;
unsigned index_bias = range->indexBias;
unsigned width;
assert(vb);
assert(size);
assert(offset < size);
assert(index_bias >= 0);
assert(min_index <= max_index);
assert(offset + index_bias*stride < size);
assert(offset + (index_bias + min_index)*stride < size);
switch (hwtnl->cmd.vdecl[i].identity.type) {
case SVGA3D_DECLTYPE_FLOAT1:
width = 4;
break;
case SVGA3D_DECLTYPE_FLOAT2:
width = 4*2;
break;
case SVGA3D_DECLTYPE_FLOAT3:
width = 4*3;
break;
case SVGA3D_DECLTYPE_FLOAT4:
width = 4*4;
break;
case SVGA3D_DECLTYPE_D3DCOLOR:
width = 4;
break;
case SVGA3D_DECLTYPE_UBYTE4:
width = 1*4;
break;
case SVGA3D_DECLTYPE_SHORT2:
width = 2*2;
break;
case SVGA3D_DECLTYPE_SHORT4:
width = 2*4;
break;
case SVGA3D_DECLTYPE_UBYTE4N:
width = 1*4;
break;
case SVGA3D_DECLTYPE_SHORT2N:
width = 2*2;
break;
case SVGA3D_DECLTYPE_SHORT4N:
width = 2*4;
break;
case SVGA3D_DECLTYPE_USHORT2N:
width = 2*2;
break;
case SVGA3D_DECLTYPE_USHORT4N:
width = 2*4;
break;
case SVGA3D_DECLTYPE_UDEC3:
width = 4;
break;
case SVGA3D_DECLTYPE_DEC3N:
width = 4;
break;
case SVGA3D_DECLTYPE_FLOAT16_2:
width = 2*2;
break;
case SVGA3D_DECLTYPE_FLOAT16_4:
width = 2*4;
break;
default:
assert(0);
width = 0;
break;
}
assert(!stride || width <= stride);
assert(offset + (index_bias + max_index)*stride + width <= size);
}
assert(range->indexWidth == range->indexArray.stride);
if(ib) {
unsigned size = ib->size;
unsigned offset = range->indexArray.offset;
unsigned stride = range->indexArray.stride;
unsigned count;
assert(size);
assert(offset < size);
assert(stride);
switch (range->primType) {
case SVGA3D_PRIMITIVE_POINTLIST:
count = range->primitiveCount;
break;
case SVGA3D_PRIMITIVE_LINELIST:
count = range->primitiveCount * 2;
break;
case SVGA3D_PRIMITIVE_LINESTRIP:
count = range->primitiveCount + 1;
break;
case SVGA3D_PRIMITIVE_TRIANGLELIST:
count = range->primitiveCount * 3;
break;
case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
count = range->primitiveCount + 2;
break;
case SVGA3D_PRIMITIVE_TRIANGLEFAN:
count = range->primitiveCount + 2;
break;
default:
assert(0);
count = 0;
break;
}
assert(offset + count*stride <= size);
}
}
#endif
if (hwtnl->cmd.prim_count+1 >= QSZ) {
ret = svga_hwtnl_flush( hwtnl );
if (ret != PIPE_OK)
return ret;
}
/* min/max indices are relative to bias */
hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index;
hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index;
hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range;
pipe_buffer_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib);
hwtnl->cmd.prim_count++;
return ret;
}

View file

@ -0,0 +1,83 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_DRAW_H
#define SVGA_DRAW_H
#include "pipe/p_compiler.h"
#include "svga_hw_reg.h"
struct svga_hwtnl;
struct svga_winsys_context;
struct svga_screen;
struct svga_context;
struct pipe_buffer;
struct u_upload_mgr;
struct svga_hwtnl *svga_hwtnl_create( struct svga_context *svga,
struct u_upload_mgr *upload_ib,
struct svga_winsys_context *swc );
void svga_hwtnl_destroy( struct svga_hwtnl *hwtnl );
void svga_hwtnl_set_flatshade( struct svga_hwtnl *hwtnl,
boolean flatshade,
boolean flatshade_first );
void svga_hwtnl_set_unfilled( struct svga_hwtnl *hwtnl,
unsigned mode );
void svga_hwtnl_vdecl( struct svga_hwtnl *hwtnl,
unsigned i,
const SVGA3dVertexDecl *decl,
struct pipe_buffer *vb);
void svga_hwtnl_reset_vdecl( struct svga_hwtnl *hwtnl,
unsigned count );
enum pipe_error
svga_hwtnl_draw_arrays( struct svga_hwtnl *hwtnl,
unsigned prim,
unsigned start,
unsigned count);
enum pipe_error
svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,
struct pipe_buffer *indexBuffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
unsigned prim,
unsigned start,
unsigned count,
unsigned bias );
enum pipe_error
svga_hwtnl_flush( struct svga_hwtnl *hwtnl );
#endif /* SVGA_DRAW_H_ */

View file

@ -0,0 +1,297 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "pipe/p_inlines.h"
#include "util/u_prim.h"
#include "indices/u_indices.h"
#include "svga_hw_reg.h"
#include "svga_draw.h"
#include "svga_draw_private.h"
#include "svga_context.h"
#define DBG 0
static enum pipe_error generate_indices( struct svga_hwtnl *hwtnl,
unsigned nr,
unsigned index_size,
u_generate_func generate,
struct pipe_buffer **out_buf )
{
struct pipe_screen *screen = hwtnl->svga->pipe.screen;
unsigned size = index_size * nr;
struct pipe_buffer *dst = NULL;
void *dst_map = NULL;
dst = screen->buffer_create( screen, 32,
PIPE_BUFFER_USAGE_INDEX |
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_GPU_READ,
size );
if (dst == NULL)
goto fail;
dst_map = pipe_buffer_map( screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE );
if (dst_map == NULL)
goto fail;
generate( nr,
dst_map );
pipe_buffer_unmap( screen, dst );
*out_buf = dst;
return PIPE_OK;
fail:
if (dst_map)
screen->buffer_unmap( screen, dst );
if (dst)
screen->buffer_destroy( dst );
return PIPE_ERROR_OUT_OF_MEMORY;
}
static boolean compare( unsigned cached_nr,
unsigned nr,
unsigned type )
{
if (type == U_GENERATE_REUSABLE)
return cached_nr >= nr;
else
return cached_nr == nr;
}
static enum pipe_error retrieve_or_generate_indices( struct svga_hwtnl *hwtnl,
unsigned prim,
unsigned gen_type,
unsigned gen_nr,
unsigned gen_size,
u_generate_func generate,
struct pipe_buffer **out_buf )
{
enum pipe_error ret = PIPE_OK;
int i;
for (i = 0; i < IDX_CACHE_MAX; i++) {
if (hwtnl->index_cache[prim][i].buffer != NULL &&
hwtnl->index_cache[prim][i].generate == generate)
{
if (compare(hwtnl->index_cache[prim][i].gen_nr, gen_nr, gen_type))
{
pipe_buffer_reference( out_buf,
hwtnl->index_cache[prim][i].buffer );
if (DBG)
debug_printf("%s retrieve %d/%d\n", __FUNCTION__, i, gen_nr);
return PIPE_OK;
}
else if (gen_type == U_GENERATE_REUSABLE)
{
pipe_buffer_reference( &hwtnl->index_cache[prim][i].buffer,
NULL );
if (DBG)
debug_printf("%s discard %d/%d\n", __FUNCTION__,
i, hwtnl->index_cache[prim][i].gen_nr);
break;
}
}
}
if (i == IDX_CACHE_MAX)
{
unsigned smallest = 0;
unsigned smallest_size = ~0;
for (i = 0; i < IDX_CACHE_MAX && smallest_size; i++) {
if (hwtnl->index_cache[prim][i].buffer == NULL)
{
smallest = i;
smallest_size = 0;
}
else if (hwtnl->index_cache[prim][i].gen_nr < smallest)
{
smallest = i;
smallest_size = hwtnl->index_cache[prim][i].gen_nr;
}
}
assert (smallest != IDX_CACHE_MAX);
pipe_buffer_reference( &hwtnl->index_cache[prim][smallest].buffer,
NULL );
if (DBG)
debug_printf("%s discard smallest %d/%d\n", __FUNCTION__,
smallest, smallest_size);
i = smallest;
}
ret = generate_indices( hwtnl,
gen_nr,
gen_size,
generate,
out_buf );
if (ret != PIPE_OK)
return ret;
hwtnl->index_cache[prim][i].generate = generate;
hwtnl->index_cache[prim][i].gen_nr = gen_nr;
pipe_buffer_reference( &hwtnl->index_cache[prim][i].buffer,
*out_buf );
if (DBG)
debug_printf("%s cache %d/%d\n", __FUNCTION__,
i, hwtnl->index_cache[prim][i].gen_nr);
return PIPE_OK;
}
static enum pipe_error
simple_draw_arrays( struct svga_hwtnl *hwtnl,
unsigned prim, unsigned start, unsigned count )
{
SVGA3dPrimitiveRange range;
unsigned hw_prim;
unsigned hw_count;
hw_prim = svga_translate_prim(prim, count, &hw_count);
if (hw_count == 0)
return PIPE_ERROR_BAD_INPUT;
range.primType = hw_prim;
range.primitiveCount = hw_count;
range.indexArray.surfaceId = SVGA3D_INVALID_ID;
range.indexArray.offset = 0;
range.indexArray.stride = 0;
range.indexWidth = 0;
range.indexBias = start;
/* Min/max index should be calculated prior to applying bias, so we
* end up with min_index = 0, max_index = count - 1 and everybody
* looking at those numbers knows to adjust them by
* range.indexBias.
*/
return svga_hwtnl_prim( hwtnl, &range, 0, count - 1, NULL );
}
enum pipe_error
svga_hwtnl_draw_arrays( struct svga_hwtnl *hwtnl,
unsigned prim,
unsigned start,
unsigned count)
{
unsigned gen_prim, gen_size, gen_nr, gen_type;
u_generate_func gen_func;
enum pipe_error ret = PIPE_OK;
if (hwtnl->api_fillmode != PIPE_POLYGON_MODE_FILL &&
prim >= PIPE_PRIM_TRIANGLES)
{
gen_type = u_unfilled_generator( prim,
start,
count,
hwtnl->api_fillmode,
&gen_prim,
&gen_size,
&gen_nr,
&gen_func );
}
else {
gen_type = u_index_generator( svga_hw_prims,
prim,
start,
count,
hwtnl->api_pv,
hwtnl->hw_pv,
&gen_prim,
&gen_size,
&gen_nr,
&gen_func );
}
if (gen_type == U_GENERATE_LINEAR) {
return simple_draw_arrays( hwtnl, gen_prim, start, count );
}
else {
struct pipe_buffer *gen_buf = NULL;
/* Need to draw as indexed primitive.
* Potentially need to run the gen func to build an index buffer.
*/
ret = retrieve_or_generate_indices( hwtnl,
prim,
gen_type,
gen_nr,
gen_size,
gen_func,
&gen_buf );
if (ret)
goto done;
ret = svga_hwtnl_simple_draw_range_elements( hwtnl,
gen_buf,
gen_size,
0,
count - 1,
gen_prim,
0,
gen_nr,
start );
if (ret)
goto done;
done:
if (gen_buf)
pipe_buffer_reference( &gen_buf, NULL );
return ret;
}
}

View file

@ -0,0 +1,255 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "util/u_prim.h"
#include "util/u_upload_mgr.h"
#include "indices/u_indices.h"
#include "svga_cmd.h"
#include "svga_draw.h"
#include "svga_draw_private.h"
#include "svga_screen_buffer.h"
#include "svga_winsys.h"
#include "svga_context.h"
#include "svga_hw_reg.h"
static enum pipe_error
translate_indices( struct svga_hwtnl *hwtnl,
struct pipe_buffer *src,
unsigned offset,
unsigned nr,
unsigned index_size,
u_translate_func translate,
struct pipe_buffer **out_buf )
{
struct pipe_screen *screen = hwtnl->svga->pipe.screen;
unsigned size = index_size * nr;
const void *src_map = NULL;
struct pipe_buffer *dst = NULL;
void *dst_map = NULL;
dst = screen->buffer_create( screen, 32,
PIPE_BUFFER_USAGE_INDEX |
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_GPU_READ,
size );
if (dst == NULL)
goto fail;
src_map = pipe_buffer_map( screen, src, PIPE_BUFFER_USAGE_CPU_READ );
if (src_map == NULL)
goto fail;
dst_map = pipe_buffer_map( screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE );
if (dst_map == NULL)
goto fail;
translate( (const char *)src_map + offset,
nr,
dst_map );
pipe_buffer_unmap( screen, src );
pipe_buffer_unmap( screen, dst );
*out_buf = dst;
return PIPE_OK;
fail:
if (src_map)
screen->buffer_unmap( screen, src );
if (dst_map)
screen->buffer_unmap( screen, dst );
if (dst)
screen->buffer_destroy( dst );
return PIPE_ERROR_OUT_OF_MEMORY;
}
enum pipe_error
svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
struct pipe_buffer *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
unsigned prim,
unsigned start,
unsigned count,
unsigned bias )
{
struct pipe_buffer *upload_buffer = NULL;
SVGA3dPrimitiveRange range;
unsigned hw_prim;
unsigned hw_count;
unsigned index_offset = start * index_size;
int ret = PIPE_OK;
hw_prim = svga_translate_prim(prim, count, &hw_count);
if (hw_count == 0)
goto done;
if (index_buffer &&
svga_buffer_is_user_buffer(index_buffer))
{
assert( index_buffer->size >= index_offset + count * index_size );
ret = u_upload_buffer( hwtnl->upload_ib,
index_offset,
count * index_size,
index_buffer,
&index_offset,
&upload_buffer );
if (ret)
goto done;
/* Don't need to worry about refcounting index_buffer as this is
* just a stack variable without a counted reference of its own.
* The caller holds the reference.
*/
index_buffer = upload_buffer;
}
range.primType = hw_prim;
range.primitiveCount = hw_count;
range.indexArray.offset = index_offset;
range.indexArray.stride = index_size;
range.indexWidth = index_size;
range.indexBias = bias;
ret = svga_hwtnl_prim( hwtnl, &range, min_index, max_index, index_buffer );
if (ret)
goto done;
done:
if (upload_buffer)
pipe_buffer_reference( &upload_buffer, NULL );
return ret;
}
enum pipe_error
svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl,
struct pipe_buffer *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
unsigned prim, unsigned start, unsigned count,
unsigned bias)
{
unsigned gen_prim, gen_size, gen_nr, gen_type;
u_translate_func gen_func;
enum pipe_error ret = PIPE_OK;
if (hwtnl->api_fillmode != PIPE_POLYGON_MODE_FILL &&
prim >= PIPE_PRIM_TRIANGLES)
{
gen_type = u_unfilled_translator( prim,
index_size,
count,
hwtnl->api_fillmode,
&gen_prim,
&gen_size,
&gen_nr,
&gen_func );
}
else
{
gen_type = u_index_translator( svga_hw_prims,
prim,
index_size,
count,
hwtnl->api_pv,
hwtnl->hw_pv,
&gen_prim,
&gen_size,
&gen_nr,
&gen_func );
}
if (gen_type == U_TRANSLATE_MEMCPY) {
/* No need for translation, just pass through to hardware:
*/
return svga_hwtnl_simple_draw_range_elements( hwtnl, index_buffer,
index_size,
min_index,
max_index,
gen_prim, start, count, bias );
}
else {
struct pipe_buffer *gen_buf = NULL;
/* Need to allocate a new index buffer and run the translate
* func to populate it. Could potentially cache this translated
* index buffer with the original to avoid future
* re-translations. Not much point if we're just accelerating
* GL though, as index buffers are typically used only once
* there.
*/
ret = translate_indices( hwtnl,
index_buffer,
start * index_size,
gen_nr,
gen_size,
gen_func,
&gen_buf );
if (ret)
goto done;
ret = svga_hwtnl_simple_draw_range_elements( hwtnl,
gen_buf,
gen_size,
min_index,
max_index,
gen_prim,
0,
gen_nr,
bias );
if (ret)
goto done;
done:
if (gen_buf)
pipe_buffer_reference( &gen_buf, NULL );
return ret;
}
}

View file

@ -0,0 +1,158 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_DRAW_H_
#define SVGA_DRAW_H_
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
#include "indices/u_indices.h"
#include "svga_hw_reg.h"
#include "svga3d_shaderdefs.h"
struct svga_context;
struct u_upload_mgr;
/* Should include polygon?
*/
static const unsigned svga_hw_prims =
((1 << PIPE_PRIM_POINTS) |
(1 << PIPE_PRIM_LINES) |
(1 << PIPE_PRIM_LINE_STRIP) |
(1 << PIPE_PRIM_TRIANGLES) |
(1 << PIPE_PRIM_TRIANGLE_STRIP) |
(1 << PIPE_PRIM_TRIANGLE_FAN));
static INLINE unsigned svga_translate_prim(unsigned mode,
unsigned count,
unsigned *out_count)
{
switch (mode) {
case PIPE_PRIM_POINTS:
*out_count = count;
return SVGA3D_PRIMITIVE_POINTLIST;
case PIPE_PRIM_LINES:
*out_count = count / 2;
return SVGA3D_PRIMITIVE_LINELIST;
case PIPE_PRIM_LINE_STRIP:
*out_count = count - 1;
return SVGA3D_PRIMITIVE_LINESTRIP;
case PIPE_PRIM_TRIANGLES:
*out_count = count / 3;
return SVGA3D_PRIMITIVE_TRIANGLELIST;
case PIPE_PRIM_TRIANGLE_STRIP:
*out_count = count - 2;
return SVGA3D_PRIMITIVE_TRIANGLESTRIP;
case PIPE_PRIM_TRIANGLE_FAN:
*out_count = count - 2;
return SVGA3D_PRIMITIVE_TRIANGLEFAN;
default:
assert(0);
*out_count = 0;
return 0;
}
}
struct index_cache {
u_generate_func generate;
unsigned gen_nr;
/* If non-null, this buffer is filled by calling
* generate(nr, map(buffer))
*/
struct pipe_buffer *buffer;
};
#define QSZ 32
struct draw_cmd {
struct svga_winsys_context *swc;
SVGA3dVertexDecl vdecl[SVGA3D_INPUTREG_MAX];
struct pipe_buffer *vdecl_vb[SVGA3D_INPUTREG_MAX];
unsigned vdecl_count;
SVGA3dPrimitiveRange prim[QSZ];
struct pipe_buffer *prim_ib[QSZ];
unsigned prim_count;
unsigned min_index[QSZ];
unsigned max_index[QSZ];
};
#define IDX_CACHE_MAX 8
struct svga_hwtnl {
struct svga_context *svga;
struct u_upload_mgr *upload_ib;
/* Flatshade information:
*/
unsigned api_pv;
unsigned hw_pv;
unsigned api_fillmode;
/* Cache the results of running a particular generate func on each
* primitive type.
*/
struct index_cache index_cache[PIPE_PRIM_MAX][IDX_CACHE_MAX];
/* Try to build the maximal draw command packet before emitting:
*/
struct draw_cmd cmd;
};
/***********************************************************************
* Internal functions
*/
enum pipe_error
svga_hwtnl_prim( struct svga_hwtnl *hwtnl,
const SVGA3dPrimitiveRange *range,
unsigned min_index,
unsigned max_index,
struct pipe_buffer *ib );
enum pipe_error
svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
struct pipe_buffer *indexBuffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
unsigned prim,
unsigned start,
unsigned count,
unsigned bias );
#endif

View file

@ -0,0 +1,42 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_HW_REG_H
#define SVGA_HW_REG_H
#include "pipe/p_compiler.h"
#if defined(PIPE_CC_GCC)
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H
#endif
#endif
#include "svga_types.h"
#include "svga3d_reg.h"
#endif

View file

@ -0,0 +1,246 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_hw_reg.h"
static INLINE unsigned
svga_translate_blend_factor(unsigned factor)
{
switch (factor) {
case PIPE_BLENDFACTOR_ZERO: return SVGA3D_BLENDOP_ZERO;
case PIPE_BLENDFACTOR_SRC_ALPHA: return SVGA3D_BLENDOP_SRCALPHA;
case PIPE_BLENDFACTOR_ONE: return SVGA3D_BLENDOP_ONE;
case PIPE_BLENDFACTOR_SRC_COLOR: return SVGA3D_BLENDOP_SRCCOLOR;
case PIPE_BLENDFACTOR_INV_SRC_COLOR: return SVGA3D_BLENDOP_INVSRCCOLOR;
case PIPE_BLENDFACTOR_DST_COLOR: return SVGA3D_BLENDOP_DESTCOLOR;
case PIPE_BLENDFACTOR_INV_DST_COLOR: return SVGA3D_BLENDOP_INVDESTCOLOR;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return SVGA3D_BLENDOP_INVSRCALPHA;
case PIPE_BLENDFACTOR_DST_ALPHA: return SVGA3D_BLENDOP_DESTALPHA;
case PIPE_BLENDFACTOR_INV_DST_ALPHA: return SVGA3D_BLENDOP_INVDESTALPHA;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
case PIPE_BLENDFACTOR_CONST_COLOR: return SVGA3D_BLENDOP_BLENDFACTOR;
case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
case PIPE_BLENDFACTOR_CONST_ALPHA: return SVGA3D_BLENDOP_BLENDFACTOR; /* ? */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return SVGA3D_BLENDOP_INVBLENDFACTOR; /* ? */
default:
assert(0);
return SVGA3D_BLENDOP_ZERO;
}
}
static INLINE unsigned
svga_translate_blend_func(unsigned mode)
{
switch (mode) {
case PIPE_BLEND_ADD: return SVGA3D_BLENDEQ_ADD;
case PIPE_BLEND_SUBTRACT: return SVGA3D_BLENDEQ_SUBTRACT;
case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
case PIPE_BLEND_MIN: return SVGA3D_BLENDEQ_MINIMUM;
case PIPE_BLEND_MAX: return SVGA3D_BLENDEQ_MAXIMUM;
default:
assert(0);
return SVGA3D_BLENDEQ_ADD;
}
}
static void *
svga_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *templ)
{
struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
unsigned i;
/* Fill in the per-rendertarget blend state. We currently only
* have one rendertarget.
*/
for (i = 0; i < 1; i++) {
/* No way to set this in SVGA3D, and no way to correctly implement it on
* top of D3D9 API. Instead we try to simulate with various blend modes.
*/
if (templ->logicop_enable) {
switch (templ->logicop_func) {
case PIPE_LOGICOP_XOR:
blend->need_white_fragments = TRUE;
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_SUBTRACT;
break;
case PIPE_LOGICOP_CLEAR:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_COPY:
blend->rt[i].blend_enable = FALSE;
break;
case PIPE_LOGICOP_COPY_INVERTED:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_NOOP:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_SET:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_INVERT:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_AND:
/* Approximate with minimum - works for the 0 & anything case: */
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_AND_REVERSE:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_AND_INVERTED:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_OR:
/* Approximate with maximum - works for the 1 | anything case: */
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_OR_REVERSE:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_OR_INVERTED:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_NAND:
case PIPE_LOGICOP_NOR:
case PIPE_LOGICOP_EQUIV:
/* Fill these in with plausible values */
blend->rt[i].blend_enable = FALSE;
break;
default:
assert(0);
break;
}
}
else {
blend->rt[i].blend_enable = templ->blend_enable;
if (templ->blend_enable) {
blend->rt[i].srcblend = svga_translate_blend_factor(templ->rgb_src_factor);
blend->rt[i].dstblend = svga_translate_blend_factor(templ->rgb_dst_factor);
blend->rt[i].blendeq = svga_translate_blend_func(templ->rgb_func);
blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->alpha_src_factor);
blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->alpha_dst_factor);
blend->rt[i].blendeq_alpha = svga_translate_blend_func(templ->alpha_func);
if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
blend->rt[i].blendeq_alpha != blend->rt[i].blendeq)
{
blend->rt[i].separate_alpha_blend_enable = TRUE;
}
}
}
blend->rt[i].writemask = templ->colormask;
}
return blend;
}
static void svga_bind_blend_state(struct pipe_context *pipe,
void *blend)
{
struct svga_context *svga = svga_context(pipe);
svga->curr.blend = (struct svga_blend_state*)blend;
svga->dirty |= SVGA_NEW_BLEND;
}
static void svga_delete_blend_state(struct pipe_context *pipe, void *blend)
{
FREE(blend);
}
static void svga_set_blend_color( struct pipe_context *pipe,
const struct pipe_blend_color *blend_color )
{
struct svga_context *svga = svga_context(pipe);
svga->curr.blend_color = *blend_color;
svga->dirty |= SVGA_NEW_BLEND;
}
void svga_init_blend_functions( struct svga_context *svga )
{
svga->pipe.create_blend_state = svga_create_blend_state;
svga->pipe.bind_blend_state = svga_bind_blend_state;
svga->pipe.delete_blend_state = svga_delete_blend_state;
svga->pipe.set_blend_color = svga_set_blend_color;
}

View file

@ -0,0 +1,84 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_screen_texture.h"
#include "svga_context.h"
#include "svga_cmd.h"
#define FILE_DEBUG_FLAG DEBUG_BLIT
static void svga_surface_copy(struct pipe_context *pipe,
struct pipe_surface *dest,
unsigned destx, unsigned desty,
struct pipe_surface *src,
unsigned srcx, unsigned srcy,
unsigned width, unsigned height)
{
struct svga_context *svga = svga_context(pipe);
SVGA3dCopyBox *box;
enum pipe_error ret;
svga_hwtnl_flush_retry( svga );
ret = SVGA3D_BeginSurfaceCopy(svga->swc,
src,
dest,
&box,
1);
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_BeginSurfaceCopy(svga->swc,
src,
dest,
&box,
1);
assert(ret == PIPE_OK);
}
box->x = destx;
box->y = desty;
box->z = 0;
box->w = width;
box->h = height;
box->d = 1;
box->srcx = srcx;
box->srcy = srcy;
box->srcz = 0;
SVGA_FIFOCommitAll(svga->swc);
svga_surface(dest)->dirty = TRUE;
svga_propagate_surface(pipe, dest);
}
void
svga_init_blit_functions(struct svga_context *svga)
{
svga->pipe.surface_copy = svga_surface_copy;
}

View file

@ -0,0 +1,119 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "pipe/p_defines.h"
#include "util/u_pack_color.h"
#include "svga_context.h"
#include "svga_state.h"
static enum pipe_error
try_clear(struct svga_context *svga,
unsigned buffers,
const float *rgba,
double depth,
unsigned stencil)
{
int ret = PIPE_OK;
SVGA3dRect rect = { 0, 0, 0, 0 };
boolean restore_viewport = FALSE;
SVGA3dClearFlag flags = 0;
struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
unsigned color = 0;
ret = svga_update_state(svga, SVGA_STATE_HW_CLEAR);
if (ret)
return ret;
if ((buffers & PIPE_CLEAR_COLOR) && fb->cbufs[0]) {
flags |= SVGA3D_CLEAR_COLOR;
util_pack_color(rgba, PIPE_FORMAT_A8R8G8B8_UNORM, &color);
rect.w = fb->cbufs[0]->width;
rect.h = fb->cbufs[0]->height;
}
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) {
flags |= SVGA3D_CLEAR_DEPTH;
if (svga->curr.framebuffer.zsbuf->format == PIPE_FORMAT_Z24S8_UNORM)
flags |= SVGA3D_CLEAR_STENCIL;
rect.w = MAX2(rect.w, fb->zsbuf->width);
rect.h = MAX2(rect.h, fb->zsbuf->height);
}
if (memcmp(&rect, &svga->state.hw_clear.viewport, sizeof(rect)) != 0) {
restore_viewport = TRUE;
ret = SVGA3D_SetViewport(svga->swc, &rect);
if (ret)
return ret;
}
ret = SVGA3D_ClearRect(svga->swc, flags, color, depth, stencil,
rect.x, rect.y, rect.w, rect.h);
if (ret != PIPE_OK)
return ret;
if (restore_viewport) {
memcpy(&rect, &svga->state.hw_clear.viewport, sizeof rect);
ret = SVGA3D_SetViewport(svga->swc, &rect);
}
return ret;
}
/**
* Clear the given surface to the specified value.
* No masking, no scissor (clear entire buffer).
*/
void
svga_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
double depth, unsigned stencil)
{
struct svga_context *svga = svga_context( pipe );
int ret;
ret = try_clear( svga, buffers, rgba, depth, stencil );
if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
/* Flush command buffer and retry:
*/
svga_context_flush( svga, NULL );
ret = try_clear( svga, buffers, rgba, depth, stencil );
}
/*
* Mark target surfaces as dirty
* TODO Mark only cleared surfaces.
*/
svga_mark_surfaces_dirty(svga);
assert (ret == PIPE_OK);
}

View file

@ -0,0 +1,74 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_hw_reg.h"
#include "svga_cmd.h"
/***********************************************************************
* Constant buffers
*/
struct svga_constbuf
{
unsigned type;
float (*data)[4];
unsigned count;
};
static void svga_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
const struct pipe_constant_buffer *buf)
{
struct svga_context *svga = svga_context(pipe);
assert(shader < PIPE_SHADER_TYPES);
assert(index == 0);
pipe_buffer_reference( &svga->curr.cb[shader],
buf->buffer );
if (shader == PIPE_SHADER_FRAGMENT)
svga->dirty |= SVGA_NEW_FS_CONST_BUFFER;
else
svga->dirty |= SVGA_NEW_VS_CONST_BUFFER;
}
void svga_init_constbuffer_functions( struct svga_context *svga )
{
svga->pipe.set_constant_buffer = svga_set_constant_buffer;
}

View file

@ -0,0 +1,153 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_hw_reg.h"
static INLINE unsigned
svga_translate_compare_func(unsigned func)
{
switch (func) {
case PIPE_FUNC_NEVER: return SVGA3D_CMP_NEVER;
case PIPE_FUNC_LESS: return SVGA3D_CMP_LESS;
case PIPE_FUNC_LEQUAL: return SVGA3D_CMP_LESSEQUAL;
case PIPE_FUNC_GREATER: return SVGA3D_CMP_GREATER;
case PIPE_FUNC_GEQUAL: return SVGA3D_CMP_GREATEREQUAL;
case PIPE_FUNC_NOTEQUAL: return SVGA3D_CMP_NOTEQUAL;
case PIPE_FUNC_EQUAL: return SVGA3D_CMP_EQUAL;
case PIPE_FUNC_ALWAYS: return SVGA3D_CMP_ALWAYS;
default:
assert(0);
return SVGA3D_CMP_ALWAYS;
}
}
static INLINE unsigned
svga_translate_stencil_op(unsigned op)
{
switch (op) {
case PIPE_STENCIL_OP_KEEP: return SVGA3D_STENCILOP_KEEP;
case PIPE_STENCIL_OP_ZERO: return SVGA3D_STENCILOP_ZERO;
case PIPE_STENCIL_OP_REPLACE: return SVGA3D_STENCILOP_REPLACE;
case PIPE_STENCIL_OP_INCR: return SVGA3D_STENCILOP_INCR;
case PIPE_STENCIL_OP_DECR: return SVGA3D_STENCILOP_DECR;
case PIPE_STENCIL_OP_INCR_WRAP: return SVGA3D_STENCILOP_INCRSAT; /* incorrect? */
case PIPE_STENCIL_OP_DECR_WRAP: return SVGA3D_STENCILOP_DECRSAT; /* incorrect? */
case PIPE_STENCIL_OP_INVERT: return SVGA3D_STENCILOP_INVERT;
default:
assert(0);
return SVGA3D_STENCILOP_KEEP;
}
}
static void *
svga_create_depth_stencil_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *templ)
{
struct svga_depth_stencil_state *ds = CALLOC_STRUCT( svga_depth_stencil_state );
/* Don't try to figure out CW/CCW correspondence with
* stencil[0]/[1] at this point. Presumably this can change as
* back/front face are modified.
*/
ds->stencil[0].enabled = templ->stencil[0].enabled;
if (ds->stencil[0].enabled) {
ds->stencil[0].func = svga_translate_compare_func(templ->stencil[0].func);
ds->stencil[0].fail = svga_translate_stencil_op(templ->stencil[0].fail_op);
ds->stencil[0].zfail = svga_translate_stencil_op(templ->stencil[0].zfail_op);
ds->stencil[0].pass = svga_translate_stencil_op(templ->stencil[0].zpass_op);
/* SVGA3D has one ref/mask/writemask triple shared between front &
* back face stencil. We really need two:
*/
ds->stencil_ref = templ->stencil[0].ref_value & 0xff;
ds->stencil_mask = templ->stencil[0].valuemask & 0xff;
ds->stencil_writemask = templ->stencil[0].writemask & 0xff;
}
ds->stencil[1].enabled = templ->stencil[1].enabled;
if (templ->stencil[1].enabled) {
ds->stencil[1].func = svga_translate_compare_func(templ->stencil[1].func);
ds->stencil[1].fail = svga_translate_stencil_op(templ->stencil[1].fail_op);
ds->stencil[1].zfail = svga_translate_stencil_op(templ->stencil[1].zfail_op);
ds->stencil[1].pass = svga_translate_stencil_op(templ->stencil[1].zpass_op);
ds->stencil_ref = templ->stencil[1].ref_value & 0xff;
ds->stencil_mask = templ->stencil[1].valuemask & 0xff;
ds->stencil_writemask = templ->stencil[1].writemask & 0xff;
}
ds->zenable = templ->depth.enabled;
if (ds->zenable) {
ds->zfunc = svga_translate_compare_func(templ->depth.func);
ds->zwriteenable = templ->depth.writemask;
}
ds->alphatestenable = templ->alpha.enabled;
if (ds->alphatestenable) {
ds->alphafunc = svga_translate_compare_func(templ->alpha.func);
ds->alpharef = templ->alpha.ref_value;
}
return ds;
}
static void svga_bind_depth_stencil_state(struct pipe_context *pipe,
void *depth_stencil)
{
struct svga_context *svga = svga_context(pipe);
svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil;
svga->dirty |= SVGA_NEW_DEPTH_STENCIL;
}
static void svga_delete_depth_stencil_state(struct pipe_context *pipe,
void *depth_stencil)
{
FREE(depth_stencil);
}
void svga_init_depth_stencil_functions( struct svga_context *svga )
{
svga->pipe.create_depth_stencil_alpha_state = svga_create_depth_stencil_state;
svga->pipe.bind_depth_stencil_alpha_state = svga_bind_depth_stencil_state;
svga->pipe.delete_depth_stencil_alpha_state = svga_delete_depth_stencil_state;
}

View file

@ -0,0 +1,261 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "pipe/p_inlines.h"
#include "util/u_prim.h"
#include "util/u_time.h"
#include "indices/u_indices.h"
#include "svga_hw_reg.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_winsys.h"
#include "svga_draw.h"
#include "svga_state.h"
#include "svga_swtnl.h"
#include "svga_debug.h"
static enum pipe_error
retry_draw_range_elements( struct svga_context *svga,
struct pipe_buffer *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
unsigned prim,
unsigned start,
unsigned count,
boolean do_retry )
{
enum pipe_error ret = 0;
svga_hwtnl_set_unfilled( svga->hwtnl,
svga->curr.rast->hw_unfilled );
svga_hwtnl_set_flatshade( svga->hwtnl,
svga->curr.rast->templ.flatshade,
svga->curr.rast->templ.flatshade_first );
ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
if (ret)
goto retry;
ret = svga_hwtnl_draw_range_elements( svga->hwtnl,
index_buffer, index_size,
min_index, max_index,
prim, start, count, 0 );
if (ret)
goto retry;
if (svga->curr.any_user_vertex_buffers) {
ret = svga_hwtnl_flush( svga->hwtnl );
if (ret)
goto retry;
}
return PIPE_OK;
retry:
svga_context_flush( svga, NULL );
if (do_retry)
{
return retry_draw_range_elements( svga,
index_buffer, index_size,
min_index, max_index,
prim, start, count,
FALSE );
}
return ret;
}
static enum pipe_error
retry_draw_arrays( struct svga_context *svga,
unsigned prim,
unsigned start,
unsigned count,
boolean do_retry )
{
enum pipe_error ret;
svga_hwtnl_set_unfilled( svga->hwtnl,
svga->curr.rast->hw_unfilled );
svga_hwtnl_set_flatshade( svga->hwtnl,
svga->curr.rast->templ.flatshade,
svga->curr.rast->templ.flatshade_first );
ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
if (ret)
goto retry;
ret = svga_hwtnl_draw_arrays( svga->hwtnl, prim,
start, count );
if (ret)
goto retry;
if (svga->curr.any_user_vertex_buffers) {
ret = svga_hwtnl_flush( svga->hwtnl );
if (ret)
goto retry;
}
return 0;
retry:
if (ret == PIPE_ERROR_OUT_OF_MEMORY && do_retry)
{
svga_context_flush( svga, NULL );
return retry_draw_arrays( svga,
prim,
start,
count,
FALSE );
}
return ret;
}
static boolean
svga_draw_range_elements( struct pipe_context *pipe,
struct pipe_buffer *index_buffer,
unsigned index_size,
unsigned min_index,
unsigned max_index,
unsigned prim, unsigned start, unsigned count)
{
struct svga_context *svga = svga_context( pipe );
unsigned reduced_prim = u_reduced_prim(prim);
enum pipe_error ret = 0;
if (!u_trim_pipe_prim( prim, &count ))
return TRUE;
/*
* Mark currently bound target surfaces as dirty
* doesn't really matter if it is done before drawing.
*
* TODO If we ever normaly return something other then
* true we should not mark it as dirty then.
*/
svga_mark_surfaces_dirty(svga_context(pipe));
if (svga->curr.reduced_prim != reduced_prim) {
svga->curr.reduced_prim = reduced_prim;
svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
}
svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );
#ifdef DEBUG
if (svga->curr.vs->base.id == svga->debug.disable_shader ||
svga->curr.fs->base.id == svga->debug.disable_shader)
return 0;
#endif
if (svga->state.sw.need_swtnl)
{
ret = svga_swtnl_draw_range_elements( svga,
index_buffer,
index_size,
min_index, max_index,
prim,
start, count );
}
else {
if (index_buffer) {
ret = retry_draw_range_elements( svga,
index_buffer,
index_size,
min_index,
max_index,
prim,
start,
count,
TRUE );
}
else {
ret = retry_draw_arrays( svga,
prim,
start,
count,
TRUE );
}
}
if (SVGA_DEBUG & DEBUG_FLUSH) {
static unsigned id;
debug_printf("%s %d\n", __FUNCTION__, id++);
if (id > 1300)
util_time_sleep( 2000 );
svga_hwtnl_flush_retry( svga );
svga_context_flush(svga, NULL);
}
return ret == PIPE_OK;
}
static boolean
svga_draw_elements( struct pipe_context *pipe,
struct pipe_buffer *index_buffer,
unsigned index_size,
unsigned prim, unsigned start, unsigned count)
{
return svga_draw_range_elements( pipe, index_buffer,
index_size,
0, 0xffffffff,
prim, start, count );
}
static boolean
svga_draw_arrays( struct pipe_context *pipe,
unsigned prim, unsigned start, unsigned count)
{
return svga_draw_range_elements(pipe, NULL, 0,
start, start + count - 1,
prim,
start, count);
}
void svga_init_draw_functions( struct svga_context *svga )
{
svga->pipe.draw_arrays = svga_draw_arrays;
svga->pipe.draw_elements = svga_draw_elements;
svga->pipe.draw_range_elements = svga_draw_range_elements;
}

View file

@ -0,0 +1,68 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_defines.h"
#include "svga_screen.h"
#include "svga_screen_texture.h"
#include "svga_context.h"
#include "svga_winsys.h"
#include "svga_draw.h"
#include "svga_debug.h"
#include "svga_hw_reg.h"
static void svga_flush( struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence )
{
struct svga_context *svga = svga_context(pipe);
int i;
/* Emit buffered drawing commands.
*/
svga_hwtnl_flush_retry( svga );
/* Emit back-copy from render target view to texture.
*/
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
if (svga->curr.framebuffer.cbufs[i])
svga_propagate_surface(pipe, svga->curr.framebuffer.cbufs[i]);
}
if (svga->curr.framebuffer.zsbuf)
svga_propagate_surface(pipe, svga->curr.framebuffer.zsbuf);
/* Flush command queue.
*/
svga_context_flush(svga, fence);
}
void svga_init_flush_functions( struct svga_context *svga )
{
svga->pipe.flush = svga_flush;
}

View file

@ -0,0 +1,124 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_text.h"
#include "svga_screen.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_tgsi.h"
#include "svga_hw_reg.h"
#include "svga_cmd.h"
#include "svga_draw.h"
#include "svga_debug.h"
/***********************************************************************
* Fragment shaders
*/
static void *
svga_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct svga_context *svga = svga_context(pipe);
struct svga_screen *svgascreen = svga_screen(pipe->screen);
struct svga_fragment_shader *fs;
fs = CALLOC_STRUCT(svga_fragment_shader);
if (!fs)
return NULL;
fs->base.tokens = tgsi_dup_tokens(templ->tokens);
/* Collect basic info that we'll need later:
*/
tgsi_scan_shader(fs->base.tokens, &fs->base.info);
fs->base.id = svga->debug.shader_id++;
fs->base.use_sm30 = svgascreen->use_ps30;
if (SVGA_DEBUG & DEBUG_TGSI || 0) {
debug_printf("%s id: %u, inputs: %u, outputs: %u\n",
__FUNCTION__, fs->base.id,
fs->base.info.num_inputs, fs->base.info.num_outputs);
}
return fs;
}
static void
svga_bind_fs_state(struct pipe_context *pipe, void *shader)
{
struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader;
struct svga_context *svga = svga_context(pipe);
svga->curr.fs = fs;
svga->dirty |= SVGA_NEW_FS;
}
static
void svga_delete_fs_state(struct pipe_context *pipe, void *shader)
{
struct svga_context *svga = svga_context(pipe);
struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader;
struct svga_shader_result *result, *tmp;
enum pipe_error ret;
svga_hwtnl_flush_retry( svga );
for (result = fs->base.results; result; result = tmp ) {
tmp = result->next;
ret = SVGA3D_DestroyShader(svga->swc,
result->id,
SVGA3D_SHADERTYPE_PS );
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_DestroyShader(svga->swc,
result->id,
SVGA3D_SHADERTYPE_PS );
assert(ret == PIPE_OK);
}
svga_destroy_shader_result( result );
}
FREE((void *)fs->base.tokens);
FREE(fs);
}
void svga_init_fs_functions( struct svga_context *svga )
{
svga->pipe.create_fs_state = svga_create_fs_state;
svga->pipe.bind_fs_state = svga_bind_fs_state;
svga->pipe.delete_fs_state = svga_delete_fs_state;
}

View file

@ -0,0 +1,187 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "svga_context.h"
#include "svga_screen_texture.h"
#include "svga_state.h"
#include "svga_winsys.h"
#include "svga_hw_reg.h"
static void svga_set_scissor_state( struct pipe_context *pipe,
const struct pipe_scissor_state *scissor )
{
struct svga_context *svga = svga_context(pipe);
memcpy( &svga->curr.scissor, scissor, sizeof(*scissor) );
svga->dirty |= SVGA_NEW_SCISSOR;
}
static void svga_set_polygon_stipple( struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple )
{
/* overridden by the draw module */
}
void svga_cleanup_framebuffer(struct svga_context *svga)
{
struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
int i;
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
pipe_surface_reference(&curr->cbufs[i], NULL);
pipe_surface_reference(&hw->cbufs[i], NULL);
}
pipe_surface_reference(&curr->zsbuf, NULL);
pipe_surface_reference(&hw->zsbuf, NULL);
}
#define DEPTH_BIAS_SCALE_FACTOR_D16 ((float)(1<<15))
#define DEPTH_BIAS_SCALE_FACTOR_D24S8 ((float)(1<<23))
#define DEPTH_BIAS_SCALE_FACTOR_D32 ((float)(1<<31))
static void svga_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct svga_context *svga = svga_context(pipe);
struct pipe_framebuffer_state *dst = &svga->curr.framebuffer;
boolean propagate = FALSE;
int i;
dst->width = fb->width;
dst->height = fb->height;
dst->nr_cbufs = fb->nr_cbufs;
/* check if we need to propaget any of the target surfaces */
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
if (dst->cbufs[i] && dst->cbufs[i] != fb->cbufs[i])
if (svga_surface_needs_propagation(dst->cbufs[i]))
propagate = TRUE;
}
if (propagate) {
/* make sure that drawing calls comes before propagation calls */
svga_hwtnl_flush_retry( svga );
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
if (dst->cbufs[i] && dst->cbufs[i] != fb->cbufs[i])
svga_propagate_surface(pipe, dst->cbufs[i]);
}
/* XXX: Actually the virtual hardware may support rendertargets with
* different size, depending on the host API and driver, but since we cannot
* know that make no such assumption here. */
for(i = 0; i < fb->nr_cbufs; ++i) {
if (fb->zsbuf && fb->cbufs[i]) {
assert(fb->zsbuf->width == fb->cbufs[i]->width);
assert(fb->zsbuf->height == fb->cbufs[i]->height);
}
}
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
pipe_surface_reference(&dst->cbufs[i], fb->cbufs[i]);
pipe_surface_reference(&dst->zsbuf, fb->zsbuf);
if (svga->curr.framebuffer.zsbuf)
{
switch (svga->curr.framebuffer.zsbuf->format) {
case PIPE_FORMAT_Z16_UNORM:
svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D16;
break;
case PIPE_FORMAT_S8Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D24S8;
break;
case PIPE_FORMAT_Z32_UNORM:
svga->curr.depthscale = 1.0f / DEPTH_BIAS_SCALE_FACTOR_D32;
break;
case PIPE_FORMAT_Z32_FLOAT:
svga->curr.depthscale = 1.0f / ((float)(1<<23));
break;
default:
svga->curr.depthscale = 0.0f;
break;
}
}
else {
svga->curr.depthscale = 0.0f;
}
svga->dirty |= SVGA_NEW_FRAME_BUFFER;
}
static void svga_set_clip_state( struct pipe_context *pipe,
const struct pipe_clip_state *clip )
{
struct svga_context *svga = svga_context(pipe);
svga->curr.clip = *clip; /* struct copy */
svga->dirty |= SVGA_NEW_CLIP;
}
/* Called when driver state tracker notices changes to the viewport
* matrix:
*/
static void svga_set_viewport_state( struct pipe_context *pipe,
const struct pipe_viewport_state *viewport )
{
struct svga_context *svga = svga_context(pipe);
svga->curr.viewport = *viewport; /* struct copy */
svga->dirty |= SVGA_NEW_VIEWPORT;
}
void svga_init_misc_functions( struct svga_context *svga )
{
svga->pipe.set_scissor_state = svga_set_scissor_state;
svga->pipe.set_polygon_stipple = svga_set_polygon_stipple;
svga->pipe.set_framebuffer_state = svga_set_framebuffer_state;
svga->pipe.set_clip_state = svga_set_clip_state;
svga->pipe.set_viewport_state = svga_set_viewport_state;
}

View file

@ -0,0 +1,267 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_state.h"
#include "pipe/p_context.h"
#include "util/u_memory.h"
#include "svga_cmd.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_winsys.h"
#include "svga_draw.h"
#include "svga_debug.h"
/* Fixme: want a public base class for all pipe structs, even if there
* isn't much in them.
*/
struct pipe_query {
int dummy;
};
struct svga_query {
struct pipe_query base;
SVGA3dQueryType type;
struct svga_winsys_buffer *hwbuf;
volatile SVGA3dQueryResult *queryResult;
struct pipe_fence_handle *fence;
};
/***********************************************************************
* Inline conversion functions. These are better-typed than the
* macros used previously:
*/
static INLINE struct svga_query *
svga_query( struct pipe_query *q )
{
return (struct svga_query *)q;
}
static boolean svga_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
uint64_t *result);
static struct pipe_query *svga_create_query( struct pipe_context *pipe,
unsigned query_type )
{
struct svga_screen *svgascreen = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_query *sq;
SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
sq = CALLOC_STRUCT(svga_query);
if (!sq)
goto no_sq;
sq->type = SVGA3D_QUERYTYPE_OCCLUSION;
sq->hwbuf = svga_winsys_buffer_create(svgascreen,
1,
SVGA_BUFFER_USAGE_PINNED,
sizeof *sq->queryResult);
if(!sq->hwbuf)
goto no_hwbuf;
sq->queryResult = (SVGA3dQueryResult *)sws->buffer_map(sws,
sq->hwbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
if(!sq->queryResult)
goto no_query_result;
sq->queryResult->totalSize = sizeof *sq->queryResult;
sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
/*
* We request the buffer to be pinned and assume it is always mapped.
*
* The reason is that we don't want to wait for fences when checking the
* query status.
*/
sws->buffer_unmap(sws, sq->hwbuf);
return &sq->base;
no_query_result:
sws->buffer_destroy(sws, sq->hwbuf);
no_hwbuf:
FREE(sq);
no_sq:
return NULL;
}
static void svga_destroy_query(struct pipe_context *pipe,
struct pipe_query *q)
{
struct svga_screen *svgascreen = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_query *sq = svga_query( q );
SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
sws->buffer_destroy(sws, sq->hwbuf);
sws->fence_reference(sws, &sq->fence, NULL);
FREE(sq);
}
static void svga_begin_query(struct pipe_context *pipe,
struct pipe_query *q)
{
struct svga_screen *svgascreen = svga_screen(pipe->screen);
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_context *svga = svga_context( pipe );
struct svga_query *sq = svga_query( q );
enum pipe_error ret;
SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
assert(!svga->sq);
/* Need to flush out buffered drawing commands so that they don't
* get counted in the query results.
*/
svga_hwtnl_flush_retry(svga);
if(sq->queryResult->state == SVGA3D_QUERYSTATE_PENDING) {
/* The application doesn't care for the pending query result. We cannot
* let go the existing buffer and just get a new one because its storage
* may be reused for other purposes and clobbered by the host when it
* determines the query result. So the only option here is to wait for
* the existing query's result -- not a big deal, given that no sane
* application would do this.
*/
uint64_t result;
svga_get_query_result(pipe, q, TRUE, &result);
assert(sq->queryResult->state != SVGA3D_QUERYSTATE_PENDING);
}
sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
sws->fence_reference(sws, &sq->fence, NULL);
ret = SVGA3D_BeginQuery(svga->swc, sq->type);
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_BeginQuery(svga->swc, sq->type);
assert(ret == PIPE_OK);
}
svga->sq = sq;
}
static void svga_end_query(struct pipe_context *pipe,
struct pipe_query *q)
{
struct svga_context *svga = svga_context( pipe );
struct svga_query *sq = svga_query( q );
enum pipe_error ret;
SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
assert(svga->sq == sq);
svga_hwtnl_flush_retry(svga);
/* Set to PENDING before sending EndQuery. */
sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING;
ret = SVGA3D_EndQuery( svga->swc, sq->type, sq->hwbuf);
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_EndQuery( svga->swc, sq->type, sq->hwbuf);
assert(ret == PIPE_OK);
}
/* TODO: Delay flushing. We don't really need to flush here, just ensure
* that there is one flush before svga_get_query_result attempts to get the
* result */
svga_context_flush(svga, NULL);
svga->sq = NULL;
}
static boolean svga_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
uint64_t *result)
{
struct svga_context *svga = svga_context( pipe );
struct svga_screen *svgascreen = svga_screen( pipe->screen );
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_query *sq = svga_query( q );
SVGA3dQueryState state;
SVGA_DBG(DEBUG_QUERY, "%s wait: %d\n", __FUNCTION__);
/* The query status won't be updated by the host unless
* SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause a
* synchronous wait on the host */
if(!sq->fence) {
enum pipe_error ret;
ret = SVGA3D_WaitForQuery( svga->swc, sq->type, sq->hwbuf);
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_WaitForQuery( svga->swc, sq->type, sq->hwbuf);
assert(ret == PIPE_OK);
}
svga_context_flush(svga, &sq->fence);
assert(sq->fence);
}
state = sq->queryResult->state;
if(state == SVGA3D_QUERYSTATE_PENDING) {
if(!wait)
return FALSE;
sws->fence_finish(sws, sq->fence, 0);
state = sq->queryResult->state;
}
assert(state == SVGA3D_QUERYSTATE_SUCCEEDED ||
state == SVGA3D_QUERYSTATE_FAILED);
*result = (uint64_t)sq->queryResult->result32;
SVGA_DBG(DEBUG_QUERY, "%s result %d\n", __FUNCTION__, (unsigned)*result);
return TRUE;
}
void svga_init_query_functions( struct svga_context *svga )
{
svga->pipe.create_query = svga_create_query;
svga->pipe.destroy_query = svga_destroy_query;
svga->pipe.begin_query = svga_begin_query;
svga->pipe.end_query = svga_end_query;
svga->pipe.get_query_result = svga_get_query_result;
}

View file

@ -0,0 +1,250 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "draw/draw_context.h"
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_hw_reg.h"
/* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW.
*/
static SVGA3dFace svga_translate_cullmode( unsigned mode,
unsigned front_winding )
{
switch (mode) {
case PIPE_WINDING_NONE:
return SVGA3D_FACE_NONE;
case PIPE_WINDING_CCW:
return SVGA3D_FACE_BACK;
case PIPE_WINDING_CW:
return SVGA3D_FACE_FRONT;
case PIPE_WINDING_BOTH:
return SVGA3D_FACE_FRONT_BACK;
default:
assert(0);
return SVGA3D_FACE_NONE;
}
}
static SVGA3dShadeMode svga_translate_flatshade( unsigned mode )
{
return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
}
static void *
svga_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *templ)
{
struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state );
/* need this for draw module. */
rast->templ = *templ;
/* light_twoside - XXX: need fragment shader varient */
/* poly_smooth - XXX: no fallback available */
/* poly_stipple_enable - draw module */
/* point_sprite - ? */
/* point_size_per_vertex - ? */
/* sprite_coord_mode - ??? */
/* bypass_vs_viewport_and_clip - handled by viewport setup */
/* flatshade_first - handled by index translation */
/* gl_rasterization_rules - XXX - viewport code */
/* line_width - draw module */
/* fill_cw, fill_ccw - draw module or index translation */
rast->shademode = svga_translate_flatshade( templ->flatshade );
rast->cullmode = svga_translate_cullmode( templ->cull_mode,
templ->front_winding );
rast->scissortestenable = templ->scissor;
rast->multisampleantialias = templ->multisample;
rast->antialiasedlineenable = templ->line_smooth;
rast->lastpixel = templ->line_last_pixel;
rast->pointsize = templ->point_size;
rast->pointsize_min = templ->point_size_min;
rast->pointsize_max = templ->point_size_max;
rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
/* Use swtnl + decomposition implement these:
*/
if (templ->poly_stipple_enable)
rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
if (templ->line_width != 1.0 &&
templ->line_width != 0.0)
rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
if (templ->line_stipple_enable) {
/* LinePattern not implemented on all backends.
*/
if (0) {
SVGA3dLinePattern lp;
lp.repeat = templ->line_stipple_factor + 1;
lp.pattern = templ->line_stipple_pattern;
rast->linepattern = lp.uintValue;
}
else {
rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
}
}
if (templ->point_smooth)
rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
{
boolean offset_cw = templ->offset_cw;
boolean offset_ccw = templ->offset_ccw;
boolean offset = 0;
int fill_cw = templ->fill_cw;
int fill_ccw = templ->fill_ccw;
int fill = PIPE_POLYGON_MODE_FILL;
switch (templ->cull_mode) {
case PIPE_WINDING_BOTH:
offset = 0;
fill = PIPE_POLYGON_MODE_FILL;
break;
case PIPE_WINDING_CW:
offset = offset_ccw;
fill = fill_ccw;
break;
case PIPE_WINDING_CCW:
offset = offset_cw;
fill = fill_cw;
break;
case PIPE_WINDING_NONE:
if (fill_cw != fill_ccw || offset_cw != offset_ccw)
{
/* Always need the draw module to work out different
* front/back fill modes:
*/
rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
}
else {
offset = offset_ccw;
fill = fill_ccw;
}
break;
default:
assert(0);
break;
}
/* Unfilled primitive modes aren't implemented on all virtual
* hardware. We can do some unfilled processing with index
* translation, but otherwise need the draw module:
*/
if (fill != PIPE_POLYGON_MODE_FILL &&
(templ->flatshade ||
templ->light_twoside ||
offset ||
templ->cull_mode != PIPE_WINDING_NONE))
{
fill = PIPE_POLYGON_MODE_FILL;
rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
}
/* If we are decomposing to lines, and lines need the pipeline,
* then we also need the pipeline for tris.
*/
if (fill == PIPE_POLYGON_MODE_LINE &&
(rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES))
{
fill = PIPE_POLYGON_MODE_FILL;
rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
}
/* Similarly for points:
*/
if (fill == PIPE_POLYGON_MODE_POINT &&
(rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS))
{
fill = PIPE_POLYGON_MODE_FILL;
rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
}
if (offset) {
rast->slopescaledepthbias = templ->offset_scale;
rast->depthbias = templ->offset_units;
}
rast->hw_unfilled = fill;
}
if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
/* Turn off stuff which will get done in the draw module:
*/
rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
rast->slopescaledepthbias = 0;
rast->depthbias = 0;
}
return rast;
}
static void svga_bind_rasterizer_state( struct pipe_context *pipe,
void *state )
{
struct svga_context *svga = svga_context(pipe);
struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
svga->curr.rast = raster;
draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL);
svga->dirty |= SVGA_NEW_RAST;
}
static void svga_delete_rasterizer_state(struct pipe_context *pipe,
void *raster)
{
FREE(raster);
}
void svga_init_rasterizer_functions( struct svga_context *svga )
{
svga->pipe.create_rasterizer_state = svga_create_rasterizer_state;
svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state;
svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state;
}
/***********************************************************************
* Hardware state update
*/

View file

@ -0,0 +1,243 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pack_color.h"
#include "tgsi/tgsi_parse.h"
#include "svga_context.h"
#include "svga_screen_texture.h"
#include "svga_state.h"
#include "svga_hw_reg.h"
#include "svga_debug.h"
static INLINE unsigned
translate_wrap_mode(unsigned wrap)
{
switch (wrap) {
case PIPE_TEX_WRAP_REPEAT:
return SVGA3D_TEX_ADDRESS_WRAP;
case PIPE_TEX_WRAP_CLAMP:
return SVGA3D_TEX_ADDRESS_CLAMP;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
/* Unfortunately SVGA3D_TEX_ADDRESS_EDGE not respected by
* hardware.
*/
return SVGA3D_TEX_ADDRESS_CLAMP;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return SVGA3D_TEX_ADDRESS_BORDER;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return SVGA3D_TEX_ADDRESS_MIRROR;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
return SVGA3D_TEX_ADDRESS_MIRRORONCE;
default:
assert(0);
return SVGA3D_TEX_ADDRESS_WRAP;
}
}
static INLINE unsigned translate_img_filter( unsigned filter )
{
switch (filter) {
case PIPE_TEX_FILTER_NEAREST: return SVGA3D_TEX_FILTER_NEAREST;
case PIPE_TEX_FILTER_LINEAR: return SVGA3D_TEX_FILTER_LINEAR;
case PIPE_TEX_FILTER_ANISO: return SVGA3D_TEX_FILTER_ANISOTROPIC;
default:
assert(0);
return SVGA3D_TEX_FILTER_NEAREST;
}
}
static INLINE unsigned translate_mip_filter( unsigned filter )
{
switch (filter) {
case PIPE_TEX_MIPFILTER_NONE: return SVGA3D_TEX_FILTER_NONE;
case PIPE_TEX_MIPFILTER_NEAREST: return SVGA3D_TEX_FILTER_NEAREST;
case PIPE_TEX_MIPFILTER_LINEAR: return SVGA3D_TEX_FILTER_LINEAR;
default:
assert(0);
return SVGA3D_TEX_FILTER_NONE;
}
}
static void *
svga_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
{
struct svga_context *svga = svga_context(pipe);
struct svga_sampler_state *cso = CALLOC_STRUCT( svga_sampler_state );
cso->mipfilter = translate_mip_filter(sampler->min_mip_filter);
cso->magfilter = translate_img_filter( sampler->mag_img_filter );
cso->minfilter = translate_img_filter( sampler->min_img_filter );
cso->aniso_level = MAX2( (unsigned) sampler->max_anisotropy, 1 );
cso->lod_bias = sampler->lod_bias;
cso->addressu = translate_wrap_mode(sampler->wrap_s);
cso->addressv = translate_wrap_mode(sampler->wrap_t);
cso->addressw = translate_wrap_mode(sampler->wrap_r);
cso->normalized_coords = sampler->normalized_coords;
cso->compare_mode = sampler->compare_mode;
cso->compare_func = sampler->compare_func;
{
ubyte r = float_to_ubyte(sampler->border_color[0]);
ubyte g = float_to_ubyte(sampler->border_color[1]);
ubyte b = float_to_ubyte(sampler->border_color[2]);
ubyte a = float_to_ubyte(sampler->border_color[3]);
util_pack_color_ub( r, g, b, a,
PIPE_FORMAT_B8G8R8A8_UNORM,
&cso->bordercolor );
}
/* No SVGA3D support for:
* - min/max LOD clamping
*/
cso->min_lod = 0;
cso->view_min_lod = MAX2(sampler->min_lod, 0);
cso->view_max_lod = MAX2(sampler->max_lod, 0);
/* Use min_mipmap */
if (svga->debug.use_min_mipmap) {
if (cso->view_min_lod == cso->view_max_lod) {
cso->min_lod = cso->view_min_lod;
cso->view_min_lod = 0;
cso->view_max_lod = 1000; /* Just a high number */
cso->mipfilter = SVGA3D_TEX_FILTER_NONE;
}
}
SVGA_DBG(DEBUG_VIEWS, "min %u, view(min %u, max %u) lod, mipfilter %s\n",
cso->min_lod, cso->view_min_lod, cso->view_max_lod,
cso->mipfilter == SVGA3D_TEX_FILTER_NONE ? "SVGA3D_TEX_FILTER_NONE" : "SOMETHING");
return cso;
}
static void svga_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct svga_context *svga = svga_context(pipe);
unsigned i;
assert(num <= PIPE_MAX_SAMPLERS);
/* Check for no-op */
if (num == svga->curr.num_samplers &&
!memcmp(svga->curr.sampler, sampler, num * sizeof(void *))) {
debug_printf("sampler noop\n");
return;
}
for (i = 0; i < num; i++)
svga->curr.sampler[i] = sampler[i];
for (i = num; i < svga->curr.num_samplers; i++)
svga->curr.sampler[i] = NULL;
svga->curr.num_samplers = num;
svga->dirty |= SVGA_NEW_SAMPLER;
}
static void svga_delete_sampler_state(struct pipe_context *pipe,
void *sampler)
{
FREE(sampler);
}
static void svga_set_sampler_textures(struct pipe_context *pipe,
unsigned num,
struct pipe_texture **texture)
{
struct svga_context *svga = svga_context(pipe);
unsigned flag_1d = 0;
unsigned flag_srgb = 0;
uint i;
assert(num <= PIPE_MAX_SAMPLERS);
/* Check for no-op */
if (num == svga->curr.num_textures &&
!memcmp(svga->curr.texture, texture, num * sizeof(struct pipe_texture *))) {
if (0) debug_printf("texture noop\n");
return;
}
for (i = 0; i < num; i++) {
pipe_texture_reference(&svga->curr.texture[i],
texture[i]);
if (!texture[i])
continue;
if (texture[i]->format == PIPE_FORMAT_A8R8G8B8_SRGB)
flag_srgb |= 1 << i;
if (texture[i]->target == PIPE_TEXTURE_1D)
flag_1d |= 1 << i;
}
for (i = num; i < svga->curr.num_textures; i++)
pipe_texture_reference(&svga->curr.texture[i],
NULL);
svga->curr.num_textures = num;
svga->dirty |= SVGA_NEW_TEXTURE_BINDING;
if (flag_srgb != svga->curr.tex_flags.flag_srgb ||
flag_1d != svga->curr.tex_flags.flag_1d)
{
svga->dirty |= SVGA_NEW_TEXTURE_FLAGS;
svga->curr.tex_flags.flag_1d = flag_1d;
svga->curr.tex_flags.flag_srgb = flag_srgb;
}
}
void svga_init_sampler_functions( struct svga_context *svga )
{
svga->pipe.create_sampler_state = svga_create_sampler_state;
svga->pipe.bind_sampler_states = svga_bind_sampler_states;
svga->pipe.delete_sampler_state = svga_delete_sampler_state;
svga->pipe.set_sampler_textures = svga_set_sampler_textures;
}

View file

@ -0,0 +1,115 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_winsys.h"
#include "svga_hw_reg.h"
static void svga_set_vertex_buffers(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_buffer *buffers)
{
struct svga_context *svga = svga_context(pipe);
unsigned i;
boolean any_user_buffer = FALSE;
/* Check for no change */
if (count == svga->curr.num_vertex_buffers &&
memcmp(svga->curr.vb, buffers, count * sizeof buffers[0]) == 0)
return;
/* Adjust refcounts */
for (i = 0; i < count; i++) {
pipe_buffer_reference(&svga->curr.vb[i].buffer, buffers[i].buffer);
if (svga_buffer(buffers[i].buffer)->user)
any_user_buffer = TRUE;
}
for ( ; i < svga->curr.num_vertex_buffers; i++)
pipe_buffer_reference(&svga->curr.vb[i].buffer, NULL);
/* Copy remaining data */
memcpy(svga->curr.vb, buffers, count * sizeof buffers[0]);
svga->curr.num_vertex_buffers = count;
svga->curr.any_user_vertex_buffers = any_user_buffer;
svga->dirty |= SVGA_NEW_VBUFFER;
}
static void svga_set_vertex_elements(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_element *elements)
{
struct svga_context *svga = svga_context(pipe);
unsigned i;
for (i = 0; i < count; i++)
svga->curr.ve[i] = elements[i];
svga->curr.num_vertex_elements = count;
svga->dirty |= SVGA_NEW_VELEMENT;
}
static void svga_set_edgeflags(struct pipe_context *pipe,
const unsigned *bitfield)
{
struct svga_context *svga = svga_context(pipe);
if (bitfield != NULL || svga->curr.edgeflags != NULL) {
svga->curr.edgeflags = bitfield;
svga->dirty |= SVGA_NEW_EDGEFLAGS;
}
}
void svga_cleanup_vertex_state( struct svga_context *svga )
{
unsigned i;
for (i = 0 ; i < svga->curr.num_vertex_buffers; i++)
pipe_buffer_reference(&svga->curr.vb[i].buffer, NULL);
}
void svga_init_vertex_functions( struct svga_context *svga )
{
svga->pipe.set_vertex_buffers = svga_set_vertex_buffers;
svga->pipe.set_vertex_elements = svga_set_vertex_elements;
svga->pipe.set_edgeflags = svga_set_edgeflags;
}

View file

@ -0,0 +1,189 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "draw/draw_context.h"
#include "pipe/p_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_text.h"
#include "svga_screen.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_tgsi.h"
#include "svga_hw_reg.h"
#include "svga_cmd.h"
#include "svga_debug.h"
static const struct tgsi_token *substitute_vs(
unsigned shader_id,
const struct tgsi_token *old_tokens )
{
#if 0
if (shader_id == 12) {
static struct tgsi_token tokens[300];
const char *text =
"VERT1.1\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
"DCL IN[2]\n"
"DCL OUT[0], POSITION\n"
"DCL TEMP[0..4]\n"
"IMM FLT32 { 1.0000, 1.0000, 1.0000, 1.0000 }\n"
"IMM FLT32 { 0.45, 1.0000, 1.0000, 1.0000 }\n"
"IMM FLT32 { 1.297863, 0.039245, 0.035993, 0.035976}\n"
"IMM FLT32 { -0.019398, 1.696131, -0.202151, -0.202050 }\n"
"IMM FLT32 { 0.051711, -0.348713, -0.979204, -0.978714 }\n"
"IMM FLT32 { 0.000000, 0.000003, 139.491577, 141.421356 }\n"
"DCL CONST[0..7]\n"
"DCL CONST[9..16]\n"
" MOV TEMP[2], IMM[0]\n"
" MOV TEMP[2].xyz, IN[2]\n"
" MOV TEMP[2].xyz, IN[0]\n"
" MOV TEMP[2].xyz, IN[1]\n"
" MUL TEMP[1], IMM[3], TEMP[2].yyyy\n"
" MAD TEMP[3], IMM[2], TEMP[2].xxxx, TEMP[1]\n"
" MAD TEMP[1], IMM[4], TEMP[2].zzzz, TEMP[3]\n"
" MAD TEMP[4], IMM[5], TEMP[2].wwww, TEMP[1]\n"
" MOV OUT[0], TEMP[4]\n"
" END\n";
if (!tgsi_text_translate( text,
tokens,
Elements(tokens) ))
{
assert(0);
return NULL;
}
return tokens;
}
#endif
return old_tokens;
}
/***********************************************************************
* Vertex shaders
*/
static void *
svga_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct svga_context *svga = svga_context(pipe);
struct svga_screen *svgascreen = svga_screen(pipe->screen);
struct svga_vertex_shader *vs = CALLOC_STRUCT(svga_vertex_shader);
if (!vs)
return NULL;
/* substitute a debug shader?
*/
vs->base.tokens = tgsi_dup_tokens(substitute_vs(svga->debug.shader_id,
templ->tokens));
/* Collect basic info that we'll need later:
*/
tgsi_scan_shader(vs->base.tokens, &vs->base.info);
{
/* Need to do construct a new template in case we substitued a
* debug shader.
*/
struct pipe_shader_state tmp2 = *templ;
tmp2.tokens = vs->base.tokens;
vs->draw_shader = draw_create_vertex_shader(svga->swtnl.draw, &tmp2);
}
vs->base.id = svga->debug.shader_id++;
vs->base.use_sm30 = svgascreen->use_vs30;
if (SVGA_DEBUG & DEBUG_TGSI || 0) {
debug_printf("%s id: %u, inputs: %u, outputs: %u\n",
__FUNCTION__, vs->base.id,
vs->base.info.num_inputs, vs->base.info.num_outputs);
}
return vs;
}
static void svga_bind_vs_state(struct pipe_context *pipe, void *shader)
{
struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader;
struct svga_context *svga = svga_context(pipe);
svga->curr.vs = vs;
svga->dirty |= SVGA_NEW_VS;
}
static void svga_delete_vs_state(struct pipe_context *pipe, void *shader)
{
struct svga_context *svga = svga_context(pipe);
struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader;
struct svga_shader_result *result, *tmp;
enum pipe_error ret;
svga_hwtnl_flush_retry( svga );
draw_delete_vertex_shader(svga->swtnl.draw, vs->draw_shader);
for (result = vs->base.results; result; result = tmp ) {
tmp = result->next;
ret = SVGA3D_DestroyShader(svga->swc,
result->id,
SVGA3D_SHADERTYPE_VS );
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_DestroyShader(svga->swc,
result->id,
SVGA3D_SHADERTYPE_VS );
assert(ret == PIPE_OK);
}
svga_destroy_shader_result( result );
}
FREE((void *)vs->base.tokens);
FREE(vs);
}
void svga_init_vs_functions( struct svga_context *svga )
{
svga->pipe.create_vs_state = svga_create_vs_state;
svga->pipe.bind_vs_state = svga_bind_vs_state;
svga->pipe.delete_vs_state = svga_delete_vs_state;
}

View file

@ -0,0 +1,435 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "util/u_memory.h"
#include "pipe/p_inlines.h"
#include "util/u_string.h"
#include "util/u_math.h"
#include "svga_winsys.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_texture.h"
#include "svga_screen_buffer.h"
#include "svga_cmd.h"
#include "svga_debug.h"
#include "svga_hw_reg.h"
#include "svga3d_shaderdefs.h"
#ifdef DEBUG
int SVGA_DEBUG = 0;
static const struct debug_named_value svga_debug_flags[] = {
{ "dma", DEBUG_DMA },
{ "tgsi", DEBUG_TGSI },
{ "pipe", DEBUG_PIPE },
{ "state", DEBUG_STATE },
{ "screen", DEBUG_SCREEN },
{ "tex", DEBUG_TEX },
{ "swtnl", DEBUG_SWTNL },
{ "const", DEBUG_CONSTS },
{ "viewport", DEBUG_VIEWPORT },
{ "views", DEBUG_VIEWS },
{ "perf", DEBUG_PERF },
{ "flush", DEBUG_FLUSH },
{ "sync", DEBUG_SYNC },
{NULL, 0}
};
#endif
static const char *
svga_get_vendor( struct pipe_screen *pscreen )
{
return "VMware, Inc.";
}
static const char *
svga_get_name( struct pipe_screen *pscreen )
{
#ifdef DEBUG
/* Only return internal details in the DEBUG version:
*/
return "SVGA3D; build: DEBUG; mutex: " PIPE_ATOMIC;
#else
return "SVGA3D; build: RELEASE; ";
#endif
}
static float
svga_get_paramf(struct pipe_screen *screen, int param)
{
struct svga_screen *svgascreen = svga_screen(screen);
struct svga_winsys_screen *sws = svgascreen->sws;
SVGA3dDevCapResult result;
switch (param) {
case PIPE_CAP_MAX_LINE_WIDTH:
/* fall-through */
case PIPE_CAP_MAX_LINE_WIDTH_AA:
return 7.0;
case PIPE_CAP_MAX_POINT_WIDTH:
/* fall-through */
case PIPE_CAP_MAX_POINT_WIDTH_AA:
/* Keep this to a reasonable size to avoid failures in
* conform/pntaa.c:
*/
return 80.0;
case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
return 4.0;
case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
return 16.0;
case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
return 16;
case PIPE_CAP_NPOT_TEXTURES:
return 1;
case PIPE_CAP_TWO_SIDED_STENCIL:
return 1;
case PIPE_CAP_GLSL:
return svgascreen->use_ps30 && svgascreen->use_vs30;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 1;
case PIPE_CAP_POINT_SPRITE:
return 1;
case PIPE_CAP_MAX_RENDER_TARGETS:
if(!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_RENDER_TARGETS, &result))
return 1;
if(!result.u)
return 1;
return MIN2(result.u, PIPE_MAX_COLOR_BUFS);
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return SVGA_MAX_TEXTURE_LEVELS;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return 8; /* max 128x128x128 */
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return SVGA_MAX_TEXTURE_LEVELS;
case PIPE_CAP_TEXTURE_MIRROR_REPEAT: /* req. for GL 1.4 */
return 1;
case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */
return 1;
default:
return 0;
}
}
/* This is a fairly pointless interface
*/
static int
svga_get_param(struct pipe_screen *screen, int param)
{
return (int) svga_get_paramf( screen, param );
}
static INLINE SVGA3dDevCapIndex
svga_translate_format_cap(enum pipe_format format)
{
switch(format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8;
case PIPE_FORMAT_R5G6B5_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_R5G6B5;
case PIPE_FORMAT_A1R5G5B5_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5;
case PIPE_FORMAT_A4R4G4B4_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4;
case PIPE_FORMAT_Z16_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_Z_D16;
case PIPE_FORMAT_Z24S8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8;
case PIPE_FORMAT_Z24X8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8;
case PIPE_FORMAT_A8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_ALPHA8;
case PIPE_FORMAT_L8_UNORM:
return SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8;
case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
return SVGA3D_DEVCAP_SURFACEFMT_DXT1;
case PIPE_FORMAT_DXT3_RGBA:
return SVGA3D_DEVCAP_SURFACEFMT_DXT3;
case PIPE_FORMAT_DXT5_RGBA:
return SVGA3D_DEVCAP_SURFACEFMT_DXT5;
default:
return SVGA3D_DEVCAP_MAX;
}
}
static boolean
svga_is_format_supported( struct pipe_screen *screen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned tex_usage,
unsigned geom_flags )
{
struct svga_winsys_screen *sws = svga_screen(screen)->sws;
SVGA3dDevCapIndex index;
SVGA3dDevCapResult result;
assert(tex_usage);
/* Override host capabilities */
if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
switch(format) {
/* Often unsupported/problematic. This means we end up with the same
* visuals for all virtual hardware implementations.
*/
case PIPE_FORMAT_A4R4G4B4_UNORM:
case PIPE_FORMAT_A1R5G5B5_UNORM:
return FALSE;
/* Simulate ability to render into compressed textures */
case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
case PIPE_FORMAT_DXT3_RGBA:
case PIPE_FORMAT_DXT5_RGBA:
return TRUE;
default:
break;
}
}
/* Try to query the host */
index = svga_translate_format_cap(format);
if( index < SVGA3D_DEVCAP_MAX &&
sws->get_cap(sws, index, &result) )
{
SVGA3dSurfaceFormatCaps mask;
mask.value = 0;
if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET)
mask.offscreenRenderTarget = 1;
if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL)
mask.zStencil = 1;
if (tex_usage & PIPE_TEXTURE_USAGE_SAMPLER)
mask.texture = 1;
if ((result.u & mask.value) == mask.value)
return TRUE;
else
return FALSE;
}
/* Use our translate functions directly rather than relying on a
* duplicated list of supported formats which is prone to getting
* out of sync:
*/
if(tex_usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL))
return svga_translate_format_render(format) != SVGA3D_FORMAT_INVALID;
else
return svga_translate_format(format) != SVGA3D_FORMAT_INVALID;
}
static void
svga_fence_reference(struct pipe_screen *screen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
struct svga_winsys_screen *sws = svga_screen(screen)->sws;
sws->fence_reference(sws, ptr, fence);
}
static int
svga_fence_signalled(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
unsigned flag)
{
struct svga_winsys_screen *sws = svga_screen(screen)->sws;
return sws->fence_signalled(sws, fence, flag);
}
static int
svga_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
unsigned flag)
{
struct svga_winsys_screen *sws = svga_screen(screen)->sws;
return sws->fence_finish(sws, fence, flag);
}
static void
svga_destroy_screen( struct pipe_screen *screen )
{
struct svga_screen *svgascreen = svga_screen(screen);
svga_screen_cache_cleanup(svgascreen);
pipe_mutex_destroy(svgascreen->swc_mutex);
pipe_mutex_destroy(svgascreen->tex_mutex);
svgascreen->swc->destroy(svgascreen->swc);
svgascreen->sws->destroy(svgascreen->sws);
FREE(svgascreen);
}
/**
* Create a new svga_screen object
*/
struct pipe_screen *
svga_screen_create(struct svga_winsys_screen *sws)
{
struct svga_screen *svgascreen;
struct pipe_screen *screen;
SVGA3dDevCapResult result;
#ifdef DEBUG
SVGA_DEBUG = debug_get_flags_option("SVGA_DEBUG", svga_debug_flags, 0 );
#endif
svgascreen = CALLOC_STRUCT(svga_screen);
if (!svgascreen)
goto error1;
svgascreen->debug.force_level_surface_view =
debug_get_bool_option("SVGA_FORCE_LEVEL_SURFACE_VIEW", FALSE);
svgascreen->debug.force_surface_view =
debug_get_bool_option("SVGA_FORCE_SURFACE_VIEW", FALSE);
svgascreen->debug.force_sampler_view =
debug_get_bool_option("SVGA_FORCE_SAMPLER_VIEW", FALSE);
svgascreen->debug.no_surface_view =
debug_get_bool_option("SVGA_NO_SURFACE_VIEW", FALSE);
svgascreen->debug.no_sampler_view =
debug_get_bool_option("SVGA_NO_SAMPLER_VIEW", FALSE);
screen = &svgascreen->screen;
screen->destroy = svga_destroy_screen;
screen->get_name = svga_get_name;
screen->get_vendor = svga_get_vendor;
screen->get_param = svga_get_param;
screen->get_paramf = svga_get_paramf;
screen->is_format_supported = svga_is_format_supported;
screen->fence_reference = svga_fence_reference;
screen->fence_signalled = svga_fence_signalled;
screen->fence_finish = svga_fence_finish;
svgascreen->sws = sws;
svga_screen_init_texture_functions(screen);
svga_screen_init_buffer_functions(screen);
svgascreen->use_ps30 =
sws->get_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, &result) &&
result.u >= SVGA3DPSVERSION_30 ? TRUE : FALSE;
svgascreen->use_vs30 =
sws->get_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION, &result) &&
result.u >= SVGA3DVSVERSION_30 ? TRUE : FALSE;
#if 1
/* Shader model 2.0 is unsupported at the moment. */
if(!svgascreen->use_ps30 || !svgascreen->use_vs30)
goto error2;
#else
if(debug_get_bool_option("SVGA_NO_SM30", FALSE))
svgascreen->use_vs30 = svgascreen->use_ps30 = FALSE;
#endif
svgascreen->swc = sws->context_create(sws);
if(!svgascreen->swc)
goto error2;
pipe_mutex_init(svgascreen->tex_mutex);
pipe_mutex_init(svgascreen->swc_mutex);
LIST_INITHEAD(&svgascreen->cached_buffers);
svga_screen_cache_init(svgascreen);
return screen;
error2:
FREE(svgascreen);
error1:
return NULL;
}
void svga_screen_flush( struct svga_screen *svgascreen,
struct pipe_fence_handle **pfence )
{
struct pipe_fence_handle *fence = NULL;
SVGA_DBG(DEBUG_PERF, "%s\n", __FUNCTION__);
pipe_mutex_lock(svgascreen->swc_mutex);
svgascreen->swc->flush(svgascreen->swc, &fence);
pipe_mutex_unlock(svgascreen->swc_mutex);
svga_screen_cache_flush(svgascreen, fence);
if(pfence)
*pfence = fence;
else
svgascreen->sws->fence_reference(svgascreen->sws, &fence, NULL);
}
struct svga_winsys_screen *
svga_winsys_screen(struct pipe_screen *screen)
{
return svga_screen(screen)->sws;
}
#ifdef DEBUG
struct svga_screen *
svga_screen(struct pipe_screen *screen)
{
assert(screen);
assert(screen->destroy == svga_destroy_screen);
return (struct svga_screen *)screen;
}
#endif

View file

@ -0,0 +1,95 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_SCREEN_H
#define SVGA_SCREEN_H
#include "pipe/p_screen.h"
#include "pipe/p_thread.h"
#include "util/u_double_list.h"
#include "svga_screen_cache.h"
struct svga_winsys_screen;
struct svga_winsys_context;
struct SVGACmdMemory;
#define SVGA_COMBINE_USERBUFFERS 1
/**
* Subclass of pipe_screen
*/
struct svga_screen
{
struct pipe_screen screen;
struct svga_winsys_screen *sws;
unsigned use_ps30;
unsigned use_vs30;
struct {
boolean force_level_surface_view;
boolean force_surface_view;
boolean no_surface_view;
boolean force_sampler_view;
boolean no_sampler_view;
} debug;
/* The screen needs its own context */
struct svga_winsys_context *swc;
struct SVGACmdMemory *fifo;
unsigned texture_timestamp;
pipe_mutex tex_mutex;
pipe_mutex swc_mutex; /* Protects the use of swc and dirty_buffers */
/**
* List of buffers with cached GMR. Ordered from the most recently used to
* the least recently used
*/
struct list_head cached_buffers;
struct svga_host_surface_cache cache;
};
#ifndef DEBUG
/** cast wrapper */
static INLINE struct svga_screen *
svga_screen(struct pipe_screen *pscreen)
{
return (struct svga_screen *) pscreen;
}
#else
struct svga_screen *
svga_screen(struct pipe_screen *screen);
#endif
void svga_screen_flush( struct svga_screen *svga_screen,
struct pipe_fence_handle **pfence );
#endif /* SVGA_SCREEN_H */

View file

@ -0,0 +1,820 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_thread.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_winsys.h"
#include "svga_debug.h"
/**
* Vertex and index buffers have to be treated slightly differently from
* regular guest memory regions because the SVGA device sees them as
* surfaces, and the state tracker can create/destroy without the pipe
* driver, therefore we must do the uploads from the vws.
*/
static INLINE boolean
svga_buffer_needs_hw_storage(unsigned usage)
{
return usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_INDEX);
}
static INLINE enum pipe_error
svga_buffer_create_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(!sbuf->handle) {
sbuf->key.flags = 0;
sbuf->key.format = SVGA3D_BUFFER;
if(sbuf->base.usage & PIPE_BUFFER_USAGE_VERTEX)
sbuf->key.flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
if(sbuf->base.usage & PIPE_BUFFER_USAGE_INDEX)
sbuf->key.flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
sbuf->key.size.width = sbuf->base.size;
sbuf->key.size.height = 1;
sbuf->key.size.depth = 1;
sbuf->key.numFaces = 1;
sbuf->key.numMipLevels = 1;
sbuf->handle = svga_screen_surface_create(ss, &sbuf->key);
if(!sbuf->handle)
return PIPE_ERROR_OUT_OF_MEMORY;
/* Always set the discard flag on the first time the buffer is written
* as svga_screen_surface_create might have passed a recycled host
* buffer.
*/
sbuf->hw.flags.discard = TRUE;
SVGA_DBG(DEBUG_DMA, " grab sid %p sz %d\n", sbuf->handle, sbuf->base.size);
}
return PIPE_OK;
}
static INLINE void
svga_buffer_destroy_host_surface(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(sbuf->handle) {
SVGA_DBG(DEBUG_DMA, " ungrab sid %p sz %d\n", sbuf->handle, sbuf->base.size);
svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle);
}
}
static INLINE void
svga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf)
{
struct svga_winsys_screen *sws = ss->sws;
assert(!sbuf->map.count);
assert(sbuf->hw.buf);
if(sbuf->hw.buf) {
sws->buffer_destroy(sws, sbuf->hw.buf);
sbuf->hw.buf = NULL;
assert(sbuf->head.prev && sbuf->head.next);
LIST_DEL(&sbuf->head);
#ifdef DEBUG
sbuf->head.next = sbuf->head.prev = NULL;
#endif
}
}
static INLINE enum pipe_error
svga_buffer_backup(struct svga_screen *ss, struct svga_buffer *sbuf)
{
if (sbuf->hw.buf && sbuf->hw.num_ranges) {
void *src;
if (!sbuf->swbuf)
sbuf->swbuf = align_malloc(sbuf->base.size, sbuf->base.alignment);
if (!sbuf->swbuf)
return PIPE_ERROR_OUT_OF_MEMORY;
src = ss->sws->buffer_map(ss->sws, sbuf->hw.buf,
PIPE_BUFFER_USAGE_CPU_READ);
if (!src)
return PIPE_ERROR;
memcpy(sbuf->swbuf, src, sbuf->base.size);
ss->sws->buffer_unmap(ss->sws, sbuf->hw.buf);
}
return PIPE_OK;
}
/**
* Try to make GMR space available by freeing the hardware storage of
* unmapped
*/
boolean
svga_buffer_free_cached_hw_storage(struct svga_screen *ss)
{
struct list_head *curr;
struct svga_buffer *sbuf;
enum pipe_error ret = PIPE_OK;
curr = ss->cached_buffers.prev;
/* free the least recently used buffer's hw storage which is not mapped */
do {
if(curr == &ss->cached_buffers)
return FALSE;
sbuf = LIST_ENTRY(struct svga_buffer, curr, head);
curr = curr->prev;
if (sbuf->map.count == 0)
ret = svga_buffer_backup(ss, sbuf);
} while(sbuf->map.count != 0 || ret != PIPE_OK);
svga_buffer_destroy_hw_storage(ss, sbuf);
return TRUE;
}
struct svga_winsys_buffer *
svga_winsys_buffer_create( struct svga_screen *ss,
unsigned alignment,
unsigned usage,
unsigned size )
{
struct svga_winsys_screen *sws = ss->sws;
struct svga_winsys_buffer *buf;
/* Just try */
buf = sws->buffer_create(sws, alignment, usage, size);
if(!buf) {
SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "flushing screen to find %d bytes GMR\n",
size);
/* Try flushing all pending DMAs */
svga_screen_flush(ss, NULL);
buf = sws->buffer_create(sws, alignment, usage, size);
SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "evicting buffers to find %d bytes GMR\n",
size);
/* Try evicing all buffer storage */
while(!buf && svga_buffer_free_cached_hw_storage(ss))
buf = sws->buffer_create(sws, alignment, usage, size);
}
return buf;
}
/**
* Allocate DMA'ble storage for the buffer.
*
* Called before mapping a buffer.
*/
static INLINE enum pipe_error
svga_buffer_create_hw_storage(struct svga_screen *ss,
struct svga_buffer *sbuf)
{
if(!sbuf->hw.buf) {
unsigned alignment = sbuf->base.alignment;
unsigned usage = 0;
unsigned size = sbuf->base.size;
sbuf->hw.buf = svga_winsys_buffer_create(ss, alignment, usage, size);
if(!sbuf->hw.buf)
return PIPE_ERROR_OUT_OF_MEMORY;
assert(!sbuf->needs_flush);
assert(!sbuf->head.prev && !sbuf->head.next);
LIST_ADD(&sbuf->head, &ss->cached_buffers);
}
return PIPE_OK;
}
/**
* Variant of SVGA3D_BufferDMA which leaves the copy box temporarily in blank.
*/
static enum pipe_error
svga_buffer_upload_command(struct svga_context *svga,
struct svga_buffer *sbuf)
{
struct svga_winsys_context *swc = svga->swc;
struct svga_winsys_buffer *guest = sbuf->hw.buf;
struct svga_winsys_surface *host = sbuf->handle;
SVGA3dTransferType transfer = SVGA3D_WRITE_HOST_VRAM;
SVGA3dSurfaceDMAFlags flags = sbuf->hw.flags;
SVGA3dCmdSurfaceDMA *cmd;
uint32 numBoxes = sbuf->hw.num_ranges;
SVGA3dCopyBox *boxes;
SVGA3dCmdSurfaceDMASuffix *pSuffix;
unsigned region_flags;
unsigned surface_flags;
struct pipe_buffer *dummy;
if(transfer == SVGA3D_WRITE_HOST_VRAM) {
region_flags = PIPE_BUFFER_USAGE_GPU_READ;
surface_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
}
else if(transfer == SVGA3D_READ_HOST_VRAM) {
region_flags = PIPE_BUFFER_USAGE_GPU_WRITE;
surface_flags = PIPE_BUFFER_USAGE_GPU_READ;
}
else {
assert(0);
return PIPE_ERROR_BAD_INPUT;
}
assert(numBoxes);
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_SURFACE_DMA,
sizeof *cmd + numBoxes * sizeof *boxes + 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;
sbuf->hw.boxes = (SVGA3dCopyBox *)&cmd[1];
sbuf->hw.svga = svga;
/* Increment reference count */
dummy = NULL;
pipe_buffer_reference(&dummy, &sbuf->base);
pSuffix = (SVGA3dCmdSurfaceDMASuffix *)((uint8_t*)cmd + sizeof *cmd + numBoxes * sizeof *boxes);
pSuffix->suffixSize = sizeof *pSuffix;
pSuffix->maximumOffset = sbuf->base.size;
pSuffix->flags = flags;
swc->commit(swc);
return PIPE_OK;
}
/**
* Patch up the upload DMA command reserved by svga_buffer_upload_command
* with the final ranges.
*/
static void
svga_buffer_upload_flush(struct svga_context *svga,
struct svga_buffer *sbuf)
{
struct svga_screen *ss = svga_screen(svga->pipe.screen);
SVGA3dCopyBox *boxes;
unsigned i;
assert(sbuf->handle);
assert(sbuf->hw.buf);
assert(sbuf->hw.num_ranges);
assert(sbuf->hw.svga == svga);
assert(sbuf->hw.boxes);
/*
* Patch the DMA command with the final copy box.
*/
SVGA_DBG(DEBUG_DMA, "dma to sid %p\n", sbuf->handle);
boxes = sbuf->hw.boxes;
for(i = 0; i < sbuf->hw.num_ranges; ++i) {
SVGA_DBG(DEBUG_DMA, " bytes %u - %u\n",
sbuf->hw.ranges[i].start, sbuf->hw.ranges[i].end);
boxes[i].x = sbuf->hw.ranges[i].start;
boxes[i].y = 0;
boxes[i].z = 0;
boxes[i].w = sbuf->hw.ranges[i].end - sbuf->hw.ranges[i].start;
boxes[i].h = 1;
boxes[i].d = 1;
boxes[i].srcx = sbuf->hw.ranges[i].start;
boxes[i].srcy = 0;
boxes[i].srcz = 0;
}
sbuf->hw.num_ranges = 0;
memset(&sbuf->hw.flags, 0, sizeof sbuf->hw.flags);
assert(sbuf->head.prev && sbuf->head.next);
LIST_DEL(&sbuf->head);
sbuf->needs_flush = FALSE;
/* XXX: do we care about cached_buffers any more ?*/
LIST_ADD(&sbuf->head, &ss->cached_buffers);
sbuf->hw.svga = NULL;
sbuf->hw.boxes = NULL;
/* Decrement reference count */
pipe_buffer_reference((struct pipe_buffer **)&sbuf, NULL);
}
/**
* Queue a DMA upload of a range of this buffer to the host.
*
* This function only notes the range down. It doesn't actually emit a DMA
* upload command. That only happens when a context tries to refer to this
* buffer, and the DMA upload command is added to that context's command buffer.
*
* We try to lump as many contiguous DMA transfers together as possible.
*/
static void
svga_buffer_upload_queue(struct svga_buffer *sbuf,
unsigned start,
unsigned end)
{
unsigned i;
assert(sbuf->hw.buf);
assert(end > start);
/*
* Try to grow one of the ranges.
*
* Note that it is not this function task to care about overlapping ranges,
* as the GMR was already given so it is too late to do anything. Situations
* where overlapping ranges may pose a problem should be detected via
* pipe_context::is_buffer_referenced and the context that refers to the
* buffer should be flushed.
*/
for(i = 0; i < sbuf->hw.num_ranges; ++i) {
if(start <= sbuf->hw.ranges[i].end && sbuf->hw.ranges[i].start <= end) {
sbuf->hw.ranges[i].start = MIN2(sbuf->hw.ranges[i].start, start);
sbuf->hw.ranges[i].end = MAX2(sbuf->hw.ranges[i].end, end);
return;
}
}
/*
* We cannot add a new range to an existing DMA command, so patch-up the
* pending DMA upload and start clean.
*/
if(sbuf->needs_flush)
svga_buffer_upload_flush(sbuf->hw.svga, sbuf);
assert(!sbuf->needs_flush);
assert(!sbuf->hw.svga);
assert(!sbuf->hw.boxes);
/*
* Add a new range.
*/
sbuf->hw.ranges[sbuf->hw.num_ranges].start = start;
sbuf->hw.ranges[sbuf->hw.num_ranges].end = end;
++sbuf->hw.num_ranges;
}
static void *
svga_buffer_map_range( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned offset, unsigned length,
unsigned usage )
{
struct svga_screen *ss = svga_screen(screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_buffer *sbuf = svga_buffer( buf );
void *map;
if(sbuf->swbuf) {
/* User/malloc buffer */
map = sbuf->swbuf;
}
else {
if(!sbuf->hw.buf) {
struct svga_winsys_surface *handle = sbuf->handle;
if(svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK)
return NULL;
/* Populate the hardware storage if the host surface pre-existed */
if((usage & PIPE_BUFFER_USAGE_CPU_READ) && handle) {
SVGA3dSurfaceDMAFlags flags;
enum pipe_error ret;
struct pipe_fence_handle *fence = NULL;
SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "dma from sid %p, bytes %u - %u\n",
sbuf->handle, 0, sbuf->base.size);
memset(&flags, 0, sizeof flags);
ret = SVGA3D_BufferDMA(ss->swc,
sbuf->hw.buf,
sbuf->handle,
SVGA3D_READ_HOST_VRAM,
sbuf->base.size,
0,
flags);
if(ret != PIPE_OK) {
ss->swc->flush(ss->swc, NULL);
ret = SVGA3D_BufferDMA(ss->swc,
sbuf->hw.buf,
sbuf->handle,
SVGA3D_READ_HOST_VRAM,
sbuf->base.size,
0,
flags);
assert(ret == PIPE_OK);
}
ss->swc->flush(ss->swc, &fence);
sws->fence_finish(sws, fence, 0);
sws->fence_reference(sws, &fence, NULL);
}
}
else {
if((usage & PIPE_BUFFER_USAGE_CPU_READ) && !sbuf->needs_flush) {
/* We already had the hardware storage but we would have to issue
* a download if we hadn't, so move the buffer to the begginning
* of the LRU list.
*/
assert(sbuf->head.prev && sbuf->head.next);
LIST_DEL(&sbuf->head);
LIST_ADD(&sbuf->head, &ss->cached_buffers);
}
}
map = sws->buffer_map(sws, sbuf->hw.buf, usage);
}
if(map) {
pipe_mutex_lock(ss->swc_mutex);
++sbuf->map.count;
if (usage & PIPE_BUFFER_USAGE_CPU_WRITE) {
assert(sbuf->map.count <= 1);
sbuf->map.writing = TRUE;
if (usage & PIPE_BUFFER_USAGE_FLUSH_EXPLICIT)
sbuf->map.flush_explicit = TRUE;
}
pipe_mutex_unlock(ss->swc_mutex);
}
return map;
}
static void
svga_buffer_flush_mapped_range( struct pipe_screen *screen,
struct pipe_buffer *buf,
unsigned offset, unsigned length)
{
struct svga_buffer *sbuf = svga_buffer( buf );
struct svga_screen *ss = svga_screen(screen);
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.writing);
if(sbuf->map.writing) {
assert(sbuf->map.flush_explicit);
if(sbuf->hw.buf)
svga_buffer_upload_queue(sbuf, offset, offset + length);
}
pipe_mutex_unlock(ss->swc_mutex);
}
static void
svga_buffer_unmap( struct pipe_screen *screen,
struct pipe_buffer *buf)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_winsys_screen *sws = ss->sws;
struct svga_buffer *sbuf = svga_buffer( buf );
pipe_mutex_lock(ss->swc_mutex);
assert(sbuf->map.count);
if(sbuf->map.count)
--sbuf->map.count;
if(sbuf->hw.buf)
sws->buffer_unmap(sws, sbuf->hw.buf);
if(sbuf->map.writing) {
if(!sbuf->map.flush_explicit) {
/* No mapped range was flushed -- flush the whole buffer */
SVGA_DBG(DEBUG_DMA, "flushing the whole buffer\n");
if(sbuf->hw.buf)
svga_buffer_upload_queue(sbuf, 0, sbuf->base.size);
}
sbuf->map.writing = FALSE;
sbuf->map.flush_explicit = FALSE;
}
pipe_mutex_unlock(ss->swc_mutex);
}
static void
svga_buffer_destroy( struct pipe_buffer *buf )
{
struct svga_screen *ss = svga_screen(buf->screen);
struct svga_buffer *sbuf = svga_buffer( buf );
assert(!p_atomic_read(&buf->reference.count));
assert(!sbuf->needs_flush);
if(sbuf->handle) {
SVGA_DBG(DEBUG_DMA, "release sid %p sz %d\n", sbuf->handle, sbuf->base.size);
svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle);
}
if(sbuf->hw.buf)
svga_buffer_destroy_hw_storage(ss, sbuf);
if(sbuf->swbuf && !sbuf->user)
align_free(sbuf->swbuf);
FREE(sbuf);
}
static struct pipe_buffer *
svga_buffer_create(struct pipe_screen *screen,
unsigned alignment,
unsigned usage,
unsigned size)
{
struct svga_screen *ss = svga_screen(screen);
struct svga_buffer *sbuf;
sbuf = CALLOC_STRUCT(svga_buffer);
if(!sbuf)
goto error1;
sbuf->magic = SVGA_BUFFER_MAGIC;
pipe_reference_init(&sbuf->base.reference, 1);
sbuf->base.screen = screen;
sbuf->base.alignment = alignment;
sbuf->base.usage = usage;
sbuf->base.size = size;
if(svga_buffer_needs_hw_storage(usage)) {
if(svga_buffer_create_host_surface(ss, sbuf) != PIPE_OK)
goto error2;
}
else {
if(alignment < sizeof(void*))
alignment = sizeof(void*);
usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE;
sbuf->swbuf = align_malloc(size, alignment);
if(!sbuf->swbuf)
goto error2;
}
return &sbuf->base;
error2:
FREE(sbuf);
error1:
return NULL;
}
static struct pipe_buffer *
svga_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes)
{
struct svga_buffer *sbuf;
sbuf = CALLOC_STRUCT(svga_buffer);
if(!sbuf)
goto no_sbuf;
sbuf->magic = SVGA_BUFFER_MAGIC;
sbuf->swbuf = ptr;
sbuf->user = TRUE;
pipe_reference_init(&sbuf->base.reference, 1);
sbuf->base.screen = screen;
sbuf->base.alignment = 1;
sbuf->base.usage = 0;
sbuf->base.size = bytes;
return &sbuf->base;
no_sbuf:
return NULL;
}
void
svga_screen_init_buffer_functions(struct pipe_screen *screen)
{
screen->buffer_create = svga_buffer_create;
screen->user_buffer_create = svga_user_buffer_create;
screen->buffer_map_range = svga_buffer_map_range;
screen->buffer_flush_mapped_range = svga_buffer_flush_mapped_range;
screen->buffer_unmap = svga_buffer_unmap;
screen->buffer_destroy = svga_buffer_destroy;
}
/**
* Copy the contents of the user buffer / malloc buffer to a hardware buffer.
*/
static INLINE enum pipe_error
svga_buffer_update_hw(struct svga_screen *ss, struct svga_buffer *sbuf)
{
if(!sbuf->hw.buf) {
enum pipe_error ret;
void *map;
assert(sbuf->swbuf);
if(!sbuf->swbuf)
return PIPE_ERROR;
ret = svga_buffer_create_hw_storage(ss, sbuf);
assert(ret == PIPE_OK);
if(ret != PIPE_OK)
return ret;
pipe_mutex_lock(ss->swc_mutex);
map = ss->sws->buffer_map(ss->sws, sbuf->hw.buf, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(map);
if(!map) {
pipe_mutex_unlock(ss->swc_mutex);
return PIPE_ERROR_OUT_OF_MEMORY;
}
memcpy(map, sbuf->swbuf, sbuf->base.size);
ss->sws->buffer_unmap(ss->sws, sbuf->hw.buf);
/* This user/malloc buffer is now indistinguishable from a gpu buffer */
assert(!sbuf->map.count);
if(!sbuf->map.count) {
if(sbuf->user)
sbuf->user = FALSE;
else
align_free(sbuf->swbuf);
sbuf->swbuf = NULL;
}
svga_buffer_upload_queue(sbuf, 0, sbuf->base.size);
}
pipe_mutex_unlock(ss->swc_mutex);
return PIPE_OK;
}
struct svga_winsys_surface *
svga_buffer_handle(struct svga_context *svga,
struct pipe_buffer *buf)
{
struct pipe_screen *screen = svga->pipe.screen;
struct svga_screen *ss = svga_screen(screen);
struct svga_buffer *sbuf;
enum pipe_error ret;
if(!buf)
return NULL;
sbuf = svga_buffer(buf);
assert(!sbuf->map.count);
if(!sbuf->handle) {
ret = svga_buffer_create_host_surface(ss, sbuf);
if(ret != PIPE_OK)
return NULL;
ret = svga_buffer_update_hw(ss, sbuf);
if(ret != PIPE_OK)
return NULL;
}
if(!sbuf->needs_flush && sbuf->hw.num_ranges) {
/* Queue the buffer for flushing */
ret = svga_buffer_upload_command(svga, sbuf);
if(ret != PIPE_OK)
/* XXX: Should probably have a richer return value */
return NULL;
assert(sbuf->hw.svga == svga);
sbuf->needs_flush = TRUE;
assert(sbuf->head.prev && sbuf->head.next);
LIST_DEL(&sbuf->head);
LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers);
}
return sbuf->handle;
}
struct pipe_buffer *
svga_screen_buffer_wrap_surface(struct pipe_screen *screen,
enum SVGA3dSurfaceFormat format,
struct svga_winsys_surface *srf)
{
struct pipe_buffer *buf;
struct svga_buffer *sbuf;
struct svga_winsys_screen *sws = svga_winsys_screen(screen);
buf = svga_buffer_create(screen, 0, SVGA_BUFFER_USAGE_WRAPPED, 0);
if (!buf)
return NULL;
sbuf = svga_buffer(buf);
/*
* We are not the creator of this surface and therefore we must not
* cache it for reuse. The caching code only caches SVGA3D_BUFFER surfaces
* so make sure this isn't one of those.
*/
assert(format != SVGA3D_BUFFER);
sbuf->key.format = format;
sws->surface_reference(sws, &sbuf->handle, srf);
return buf;
}
struct svga_winsys_surface *
svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer)
{
struct svga_winsys_screen *sws = svga_winsys_screen(buffer->screen);
struct svga_winsys_surface *vsurf = NULL;
sws->surface_reference(sws, &vsurf, svga_buffer(buffer)->handle);
return vsurf;
}
void
svga_context_flush_buffers(struct svga_context *svga)
{
struct list_head *curr, *next;
struct svga_buffer *sbuf;
curr = svga->dirty_buffers.next;
next = curr->next;
while(curr != &svga->dirty_buffers) {
sbuf = LIST_ENTRY(struct svga_buffer, curr, head);
assert(p_atomic_read(&sbuf->base.reference.count) != 0);
assert(sbuf->needs_flush);
svga_buffer_upload_flush(svga, sbuf);
curr = next;
next = curr->next;
}
}

View file

@ -0,0 +1,190 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_BUFFER_H
#define SVGA_BUFFER_H
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_double_list.h"
#include "svga_screen_cache.h"
#define SVGA_BUFFER_MAGIC 0x344f9005
/**
* Maximum number of discontiguous ranges
*/
#define SVGA_BUFFER_MAX_RANGES 32
struct svga_screen;
struct svga_context;
struct svga_winsys_buffer;
struct svga_winsys_surface;
struct svga_buffer_range
{
unsigned start;
unsigned end;
};
/**
* Describe a
*
* This holds the information to emit a SVGA3dCmdSurfaceDMA.
*/
struct svga_buffer_upload
{
/**
* Guest memory region.
*/
struct svga_winsys_buffer *buf;
struct svga_buffer_range ranges[SVGA_BUFFER_MAX_RANGES];
unsigned num_ranges;
SVGA3dSurfaceDMAFlags flags;
/**
* Pointer to the DMA copy box *inside* the command buffer.
*/
SVGA3dCopyBox *boxes;
/**
* Context that has the pending DMA to this buffer.
*/
struct svga_context *svga;
};
/**
* SVGA pipe buffer.
*/
struct svga_buffer
{
struct pipe_buffer base;
/**
* Marker to detect bad casts in runtime.
*/
uint32_t magic;
/**
* Regular (non DMA'able) memory.
*
* Used for user buffers or for buffers which we know before hand that can
* never be used by the virtual hardware directly, such as constant buffers.
*/
void *swbuf;
/**
* Whether swbuf was created by the user or not.
*/
boolean user;
/**
* DMA'ble memory.
*
* A piece of GMR memory. It is created when mapping the buffer, and will be
* used to upload/download vertex data from the host.
*/
struct svga_buffer_upload hw;
/**
* Creation key for the host surface handle.
*
* This structure describes all the host surface characteristics so that it
* can be looked up in cache, since creating a host surface is often a slow
* operation.
*/
struct svga_host_surface_cache_key key;
/**
* Host surface handle.
*
* This is a platform independent abstraction for host SID. We create when
* trying to bind
*/
struct svga_winsys_surface *handle;
struct {
unsigned count;
boolean writing;
boolean flush_explicit;
} map;
boolean needs_flush;
struct list_head head;
};
static INLINE struct svga_buffer *
svga_buffer(struct pipe_buffer *buffer)
{
if (buffer) {
assert(((struct svga_buffer *)buffer)->magic == SVGA_BUFFER_MAGIC);
return (struct svga_buffer *)buffer;
}
return NULL;
}
/**
* Returns TRUE for user buffers. We may
* decide to use an alternate upload path for these buffers.
*/
static INLINE boolean
svga_buffer_is_user_buffer( struct pipe_buffer *buffer )
{
return svga_buffer(buffer)->user;
}
void
svga_screen_init_buffer_functions(struct pipe_screen *screen);
struct svga_winsys_surface *
svga_buffer_handle(struct svga_context *svga,
struct pipe_buffer *buf);
void
svga_context_flush_buffers(struct svga_context *svga);
boolean
svga_buffer_free_cached_hw_storage(struct svga_screen *ss);
struct svga_winsys_buffer *
svga_winsys_buffer_create(struct svga_screen *ss,
unsigned alignment,
unsigned usage,
unsigned size);
#endif /* SVGA_BUFFER_H */

View file

@ -0,0 +1,307 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "util/u_memory.h"
#include "svga_debug.h"
#include "svga_winsys.h"
#include "svga_screen.h"
#include "svga_screen_cache.h"
#define SVGA_SURFACE_CACHE_ENABLED 1
/**
* Compute the bucket for this key.
*
* We simply compute log2(width) for now, but
*/
static INLINE unsigned
svga_screen_cache_bucket(const struct svga_host_surface_cache_key *key)
{
unsigned bucket = 0;
unsigned size = key->size.width;
while ((size >>= 1))
++bucket;
if(key->flags & SVGA3D_SURFACE_HINT_INDEXBUFFER)
bucket += 32;
assert(bucket < SVGA_HOST_SURFACE_CACHE_BUCKETS);
return bucket;
}
static INLINE struct svga_winsys_surface *
svga_screen_cache_lookup(struct svga_screen *svgascreen,
const struct svga_host_surface_cache_key *key)
{
struct svga_host_surface_cache *cache = &svgascreen->cache;
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_host_surface_cache_entry *entry;
struct svga_winsys_surface *handle = NULL;
struct list_head *curr, *next;
unsigned bucket;
unsigned tries = 0;
bucket = svga_screen_cache_bucket(key);
pipe_mutex_lock(cache->mutex);
curr = cache->bucket[bucket].next;
next = curr->next;
while(curr != &cache->bucket[bucket]) {
++tries;
entry = LIST_ENTRY(struct svga_host_surface_cache_entry, curr, bucket_head);
assert(entry->handle);
if(memcmp(&entry->key, key, sizeof *key) == 0 &&
sws->fence_signalled( sws, entry->fence, 0 ) == 0) {
assert(sws->surface_is_flushed(sws, entry->handle));
handle = entry->handle; // Reference is transfered here.
entry->handle = NULL;
LIST_DEL(&entry->bucket_head);
LIST_DEL(&entry->head);
LIST_ADD(&entry->head, &cache->empty);
break;
}
curr = next;
next = curr->next;
}
pipe_mutex_unlock(cache->mutex);
#if 0
_debug_printf("%s: cache %s after %u tries\n", __FUNCTION__, handle ? "hit" : "miss", tries);
#else
(void)tries;
#endif
return handle;
}
/*
* Transfers a handle reference.
*/
static INLINE void
svga_screen_cache_add(struct svga_screen *svgascreen,
const struct svga_host_surface_cache_key *key,
struct svga_winsys_surface **p_handle)
{
struct svga_host_surface_cache *cache = &svgascreen->cache;
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_host_surface_cache_entry *entry = NULL;
struct svga_winsys_surface *handle = *p_handle;
assert(handle);
if(!handle)
return;
*p_handle = NULL;
pipe_mutex_lock(cache->mutex);
if(!LIST_IS_EMPTY(&cache->empty)) {
/* use the first empty entry */
entry = LIST_ENTRY(struct svga_host_surface_cache_entry, cache->empty.next, head);
LIST_DEL(&entry->head);
}
else if(!LIST_IS_EMPTY(&cache->unused)) {
/* free the last used buffer and reuse its entry */
entry = LIST_ENTRY(struct svga_host_surface_cache_entry, cache->unused.prev, head);
SVGA_DBG(DEBUG_DMA, "unref sid %p\n", entry->handle);
sws->surface_reference(sws, &entry->handle, NULL);
LIST_DEL(&entry->bucket_head);
LIST_DEL(&entry->head);
}
if(entry) {
entry->handle = handle;
memcpy(&entry->key, key, sizeof entry->key);
LIST_ADD(&entry->head, &cache->validated);
}
else {
/* Couldn't cache the buffer -- this really shouldn't happen */
SVGA_DBG(DEBUG_DMA, "unref sid %p\n", handle);
sws->surface_reference(sws, &handle, NULL);
}
pipe_mutex_unlock(cache->mutex);
}
/**
* Called during the screen flush to move all buffers not in a validate list
* into the unused list.
*/
void
svga_screen_cache_flush(struct svga_screen *svgascreen,
struct pipe_fence_handle *fence)
{
struct svga_host_surface_cache *cache = &svgascreen->cache;
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_host_surface_cache_entry *entry;
struct list_head *curr, *next;
unsigned bucket;
pipe_mutex_lock(cache->mutex);
curr = cache->validated.next;
next = curr->next;
while(curr != &cache->validated) {
entry = LIST_ENTRY(struct svga_host_surface_cache_entry, curr, head);
assert(entry->handle);
if(sws->surface_is_flushed(sws, entry->handle)) {
LIST_DEL(&entry->head);
svgascreen->sws->fence_reference(svgascreen->sws, &entry->fence, fence);
LIST_ADD(&entry->head, &cache->unused);
bucket = svga_screen_cache_bucket(&entry->key);
LIST_ADD(&entry->bucket_head, &cache->bucket[bucket]);
}
curr = next;
next = curr->next;
}
pipe_mutex_unlock(cache->mutex);
}
void
svga_screen_cache_cleanup(struct svga_screen *svgascreen)
{
struct svga_host_surface_cache *cache = &svgascreen->cache;
struct svga_winsys_screen *sws = svgascreen->sws;
unsigned i;
for(i = 0; i < SVGA_HOST_SURFACE_CACHE_SIZE; ++i) {
if(cache->entries[i].handle) {
SVGA_DBG(DEBUG_DMA, "unref sid %p\n", cache->entries[i].handle);
sws->surface_reference(sws, &cache->entries[i].handle, NULL);
}
if(cache->entries[i].fence)
svgascreen->sws->fence_reference(svgascreen->sws, &cache->entries[i].fence, NULL);
}
pipe_mutex_destroy(cache->mutex);
}
enum pipe_error
svga_screen_cache_init(struct svga_screen *svgascreen)
{
struct svga_host_surface_cache *cache = &svgascreen->cache;
unsigned i;
pipe_mutex_init(cache->mutex);
for(i = 0; i < SVGA_HOST_SURFACE_CACHE_BUCKETS; ++i)
LIST_INITHEAD(&cache->bucket[i]);
LIST_INITHEAD(&cache->unused);
LIST_INITHEAD(&cache->validated);
LIST_INITHEAD(&cache->empty);
for(i = 0; i < SVGA_HOST_SURFACE_CACHE_SIZE; ++i)
LIST_ADDTAIL(&cache->entries[i].head, &cache->empty);
return PIPE_OK;
}
struct svga_winsys_surface *
svga_screen_surface_create(struct svga_screen *svgascreen,
struct svga_host_surface_cache_key *key)
{
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_winsys_surface *handle = NULL;
if (SVGA_SURFACE_CACHE_ENABLED && key->format == SVGA3D_BUFFER) {
/* round the buffer size up to the nearest power of two to increase the
* probability of cache hits */
uint32_t size = 1;
while(size < key->size.width)
size <<= 1;
key->size.width = size;
handle = svga_screen_cache_lookup(svgascreen, key);
if (handle)
SVGA_DBG(DEBUG_DMA, " reuse sid %p sz %d\n", handle, size);
}
if (!handle) {
handle = sws->surface_create(sws,
key->flags,
key->format,
key->size,
key->numFaces,
key->numMipLevels);
if (handle)
SVGA_DBG(DEBUG_DMA, "create sid %p sz %d\n", handle, key->size);
}
return handle;
}
void
svga_screen_surface_destroy(struct svga_screen *svgascreen,
const struct svga_host_surface_cache_key *key,
struct svga_winsys_surface **p_handle)
{
struct svga_winsys_screen *sws = svgascreen->sws;
if(SVGA_SURFACE_CACHE_ENABLED && key->format == SVGA3D_BUFFER) {
svga_screen_cache_add(svgascreen, key, p_handle);
}
else {
SVGA_DBG(DEBUG_DMA, "unref sid %p\n", *p_handle);
sws->surface_reference(sws, p_handle, NULL);
}
}

View file

@ -0,0 +1,135 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_SCREEN_CACHE_H_
#define SVGA_SCREEN_CACHE_H_
#include "svga_types.h"
#include "svga_reg.h"
#include "svga3d_reg.h"
#include "pipe/p_thread.h"
#include "util/u_double_list.h"
/* TODO: Reduce this once we don't allocate an index buffer per draw call */
#define SVGA_HOST_SURFACE_CACHE_SIZE 1024
#define SVGA_HOST_SURFACE_CACHE_BUCKETS 64
struct svga_winsys_surface;
struct svga_screen;
/**
* Same as svga_winsys_screen::surface_create.
*/
struct svga_host_surface_cache_key
{
SVGA3dSurfaceFlags flags;
SVGA3dSurfaceFormat format;
SVGA3dSize size;
uint32_t numFaces;
uint32_t numMipLevels;
};
struct svga_host_surface_cache_entry
{
/**
* Head for the LRU list, svga_host_surface_cache::unused, and
* svga_host_surface_cache::empty
*/
struct list_head head;
/** Head for the bucket lists. */
struct list_head bucket_head;
struct svga_host_surface_cache_key key;
struct svga_winsys_surface *handle;
struct pipe_fence_handle *fence;
};
/**
* Cache of the host surfaces.
*
* A cache entry can be in the following stages:
* 1. empty
* 2. holding a buffer in a validate list
* 3. holding a flushed buffer (not in any validate list) with an active fence
* 4. holding a flushed buffer with an expired fence
*
* An entry progresses from 1 -> 2 -> 3 -> 4. When we need an entry to put a
* buffer into we preferencial take from 1, or from the least recentely used
* buffer from 3/4.
*/
struct svga_host_surface_cache
{
pipe_mutex mutex;
/* Unused buffers are put in buckets to speed up lookups */
struct list_head bucket[SVGA_HOST_SURFACE_CACHE_BUCKETS];
/* Entries with unused buffers, ordered from most to least recently used
* (3 and 4) */
struct list_head unused;
/* Entries with buffers still in validate lists (2) */
struct list_head validated;
/** Empty entries (1) */
struct list_head empty;
/** The actual storage for the entries */
struct svga_host_surface_cache_entry entries[SVGA_HOST_SURFACE_CACHE_SIZE];
};
void
svga_screen_cache_cleanup(struct svga_screen *svgascreen);
void
svga_screen_cache_flush(struct svga_screen *svgascreen,
struct pipe_fence_handle *fence);
enum pipe_error
svga_screen_cache_init(struct svga_screen *svgascreen);
struct svga_winsys_surface *
svga_screen_surface_create(struct svga_screen *svgascreen,
struct svga_host_surface_cache_key *key);
void
svga_screen_surface_destroy(struct svga_screen *svgascreen,
const struct svga_host_surface_cache_key *key,
struct svga_winsys_surface **handle);
#endif /* SVGA_SCREEN_CACHE_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,177 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_TEXTURE_H
#define SVGA_TEXTURE_H
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
struct pipe_context;
struct pipe_screen;
struct svga_context;
struct svga_winsys_surface;
enum SVGA3dSurfaceFormat;
#define SVGA_MAX_TEXTURE_LEVELS 12 /* 2048x2048 */
/**
* A sampler's view into a texture
*
* We currently cache one sampler view on
* the texture and in there by holding a reference
* from the texture to the sampler view.
*
* Because of this we can not hold a refernce to the
* texture from the sampler view. So the user
* of the sampler views must make sure that the
* texture has a reference take for as long as
* the sampler view is refrenced.
*
* Just unreferencing the sampler_view before the
* texture is enough.
*/
struct svga_sampler_view
{
struct pipe_reference reference;
struct svga_texture *texture;
int min_lod;
int max_lod;
unsigned age;
struct svga_winsys_surface *handle;
};
struct svga_texture
{
struct pipe_texture base;
struct svga_winsys_surface *handle;
boolean defined[6][PIPE_MAX_TEXTURE_LEVELS];
struct svga_sampler_view *cached_view;
unsigned view_age[SVGA_MAX_TEXTURE_LEVELS];
unsigned age;
boolean views_modified;
};
struct svga_surface
{
struct pipe_surface base;
struct svga_winsys_surface *handle;
unsigned real_face;
unsigned real_level;
unsigned real_zslice;
boolean dirty;
};
struct svga_transfer
{
struct pipe_transfer base;
struct svga_winsys_buffer *hwbuf;
/* Height of the hardware buffer in pixel blocks */
unsigned hw_nblocksy;
/* Temporary malloc buffer when we can't allocate a hardware buffer
* big enough */
void *swbuf;
};
static INLINE struct svga_texture *
svga_texture(struct pipe_texture *texture)
{
return (struct svga_texture *)texture;
}
static INLINE struct svga_surface *
svga_surface(struct pipe_surface *surface)
{
assert(surface);
return (struct svga_surface *)surface;
}
static INLINE struct svga_transfer *
svga_transfer(struct pipe_transfer *transfer)
{
assert(transfer);
return (struct svga_transfer *)transfer;
}
extern struct svga_sampler_view *
svga_get_tex_sampler_view(struct pipe_context *pipe,
struct pipe_texture *pt,
unsigned min_lod, unsigned max_lod);
void
svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *v);
void
svga_destroy_sampler_view_priv(struct svga_sampler_view *v);
static INLINE void
svga_sampler_view_reference(struct svga_sampler_view **ptr, struct svga_sampler_view *v)
{
struct svga_sampler_view *old = *ptr;
if (pipe_reference((struct pipe_reference **)ptr, &v->reference))
svga_destroy_sampler_view_priv(old);
}
extern void
svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf);
extern boolean
svga_surface_needs_propagation(struct pipe_surface *surf);
extern void
svga_screen_init_texture_functions(struct pipe_screen *screen);
enum SVGA3dSurfaceFormat
svga_translate_format(enum pipe_format format);
enum SVGA3dSurfaceFormat
svga_translate_format_render(enum pipe_format format);
#endif /* SVGA_TEXTURE_H */

View file

@ -0,0 +1,278 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "util/u_debug.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "svga_context.h"
#include "svga_screen.h"
#include "svga_state.h"
#include "svga_draw.h"
#include "svga_cmd.h"
#include "svga_hw_reg.h"
/* This is just enough to decide whether we need to use the draw
* module (swtnl) or not.
*/
static const struct svga_tracked_state *need_swtnl_state[] =
{
&svga_update_need_swvfetch,
&svga_update_need_pipeline,
&svga_update_need_swtnl,
NULL
};
/* Atoms to update hardware state prior to emitting a clear or draw
* packet.
*/
static const struct svga_tracked_state *hw_clear_state[] =
{
&svga_hw_scissor,
&svga_hw_viewport,
&svga_hw_framebuffer,
NULL
};
/* Atoms to update hardware state prior to emitting a draw packet.
*/
static const struct svga_tracked_state *hw_draw_state[] =
{
&svga_hw_update_zero_stride,
&svga_hw_fs,
&svga_hw_vs,
&svga_hw_rss,
&svga_hw_tss,
&svga_hw_tss_binding,
&svga_hw_clip_planes,
&svga_hw_vdecl,
&svga_hw_fs_parameters,
&svga_hw_vs_parameters,
NULL
};
static const struct svga_tracked_state *swtnl_draw_state[] =
{
&svga_update_swtnl_draw,
&svga_update_swtnl_vdecl,
NULL
};
/* Flattens the graph of state dependencies. Could swap the positions
* of hw_clear_state and need_swtnl_state without breaking anything.
*/
static const struct svga_tracked_state **state_levels[] =
{
need_swtnl_state,
hw_clear_state,
hw_draw_state,
swtnl_draw_state
};
static unsigned check_state( unsigned a,
unsigned b )
{
return (a & b);
}
static void accumulate_state( unsigned *a,
unsigned b )
{
*a |= b;
}
static void xor_states( unsigned *result,
unsigned a,
unsigned b )
{
*result = a ^ b;
}
static int update_state( struct svga_context *svga,
const struct svga_tracked_state *atoms[],
unsigned *state )
{
boolean debug = TRUE;
enum pipe_error ret = 0;
unsigned i;
ret = svga_hwtnl_flush( svga->hwtnl );
if (ret != 0)
return ret;
if (debug) {
/* Debug version which enforces various sanity checks on the
* state flags which are generated and checked to help ensure
* state atoms are ordered correctly in the list.
*/
unsigned examined, prev;
examined = 0;
prev = *state;
for (i = 0; atoms[i] != NULL; i++) {
unsigned generated;
assert(atoms[i]->dirty);
assert(atoms[i]->update);
if (check_state(*state, atoms[i]->dirty)) {
if (0)
debug_printf("update: %s\n", atoms[i]->name);
ret = atoms[i]->update( svga, *state );
if (ret != 0)
return ret;
}
/* generated = (prev ^ state)
* if (examined & generated)
* fail;
*/
xor_states(&generated, prev, *state);
if (check_state(examined, generated)) {
debug_printf("state atom %s generated state already examined\n",
atoms[i]->name);
assert(0);
}
prev = *state;
accumulate_state(&examined, atoms[i]->dirty);
}
}
else {
for (i = 0; atoms[i] != NULL; i++) {
if (check_state(*state, atoms[i]->dirty)) {
ret = atoms[i]->update( svga, *state );
if (ret != 0)
return ret;
}
}
}
return 0;
}
int svga_update_state( struct svga_context *svga,
unsigned max_level )
{
struct svga_screen *screen = svga_screen(svga->pipe.screen);
int ret = 0;
int i;
/* Check for updates to bound textures. This can't be done in an
* atom as there is no flag which could provoke this test, and we
* cannot create one.
*/
if (svga->state.texture_timestamp != screen->texture_timestamp) {
svga->state.texture_timestamp = screen->texture_timestamp;
svga->dirty |= SVGA_NEW_TEXTURE;
}
for (i = 0; i <= max_level; i++) {
svga->dirty |= svga->state.dirty[i];
if (svga->dirty) {
ret = update_state( svga,
state_levels[i],
&svga->dirty );
if (ret != 0)
return ret;
svga->state.dirty[i] = 0;
}
}
for (; i < SVGA_STATE_MAX; i++)
svga->state.dirty[i] |= svga->dirty;
svga->dirty = 0;
return 0;
}
void svga_update_state_retry( struct svga_context *svga,
unsigned max_level )
{
int ret;
ret = svga_update_state( svga, max_level );
if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
svga_context_flush(svga, NULL);
ret = svga_update_state( svga, max_level );
}
assert( ret == 0 );
}
#define EMIT_RS(_rs, _count, _name, _value) \
do { \
_rs[_count].state = _name; \
_rs[_count].uintValue = _value; \
_count++; \
} while (0)
/* Setup any hardware state which will be constant through the life of
* a context.
*/
enum pipe_error svga_emit_initial_state( struct svga_context *svga )
{
SVGA3dRenderState *rs;
unsigned count = 0;
const unsigned COUNT = 2;
enum pipe_error ret;
ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
if (ret)
return ret;
/* Always use D3D style coordinate space as this is the only one
* which is implemented on all backends.
*/
EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE, SVGA3D_COORDINATE_LEFTHANDED );
EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
assert( COUNT == count );
SVGA_FIFOCommitAll( svga->swc );
return 0;
}

View file

@ -0,0 +1,95 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_STATE_H
#define SVGA_STATE_H
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
struct svga_context;
void svga_init_state( struct svga_context *svga );
void svga_destroy_state( struct svga_context *svga );
struct svga_tracked_state {
const char *name;
unsigned dirty;
int (*update)( struct svga_context *svga, unsigned dirty );
};
/* NEED_SWTNL
*/
extern struct svga_tracked_state svga_update_need_swvfetch;
extern struct svga_tracked_state svga_update_need_pipeline;
extern struct svga_tracked_state svga_update_need_swtnl;
/* HW_CLEAR
*/
extern struct svga_tracked_state svga_hw_viewport;
extern struct svga_tracked_state svga_hw_scissor;
extern struct svga_tracked_state svga_hw_framebuffer;
/* HW_DRAW
*/
extern struct svga_tracked_state svga_hw_vs;
extern struct svga_tracked_state svga_hw_fs;
extern struct svga_tracked_state svga_hw_rss;
extern struct svga_tracked_state svga_hw_tss;
extern struct svga_tracked_state svga_hw_tss_binding;
extern struct svga_tracked_state svga_hw_clip_planes;
extern struct svga_tracked_state svga_hw_vdecl;
extern struct svga_tracked_state svga_hw_fs_parameters;
extern struct svga_tracked_state svga_hw_vs_parameters;
extern struct svga_tracked_state svga_hw_update_zero_stride;
/* SWTNL_DRAW
*/
extern struct svga_tracked_state svga_update_swtnl_draw;
extern struct svga_tracked_state svga_update_swtnl_vdecl;
/* Bring the hardware fully up-to-date so that we can emit draw
* commands.
*/
#define SVGA_STATE_NEED_SWTNL 0
#define SVGA_STATE_HW_CLEAR 1
#define SVGA_STATE_HW_DRAW 2
#define SVGA_STATE_SWTNL_DRAW 3
#define SVGA_STATE_MAX 4
enum pipe_error svga_update_state( struct svga_context *svga,
unsigned level );
void svga_update_state_retry( struct svga_context *svga,
unsigned level );
enum pipe_error svga_emit_initial_state( struct svga_context *svga );
#endif

View file

@ -0,0 +1,239 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
#include "svga_tgsi.h"
#include "svga_debug.h"
#include "svga_hw_reg.h"
/***********************************************************************
* Hardware update
*/
/* Convert from PIPE_SHADER_* to SVGA3D_SHADERTYPE_*
*/
static int svga_shader_type( int unit )
{
return unit + 1;
}
static int emit_const( struct svga_context *svga,
int unit,
int i,
const float *value )
{
int ret = PIPE_OK;
if (memcmp(svga->state.hw_draw.cb[unit][i], value, 4 * sizeof(float)) != 0) {
if (SVGA_DEBUG & DEBUG_CONSTS)
debug_printf("%s %s %d: %f %f %f %f\n",
__FUNCTION__,
unit == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
i,
value[0],
value[1],
value[2],
value[3]);
ret = SVGA3D_SetShaderConst( svga->swc,
i,
svga_shader_type(unit),
SVGA3D_CONST_TYPE_FLOAT,
value );
if (ret)
return ret;
memcpy(svga->state.hw_draw.cb[unit][i], value, 4 * sizeof(float));
}
return ret;
}
static int emit_consts( struct svga_context *svga,
int offset,
int unit )
{
struct pipe_screen *screen = svga->pipe.screen;
unsigned count;
const float (*data)[4] = NULL;
unsigned i;
int ret = PIPE_OK;
if (svga->curr.cb[unit] == NULL)
goto done;
count = svga->curr.cb[unit]->size / (4 * sizeof(float));
data = (const float (*)[4])pipe_buffer_map(screen,
svga->curr.cb[unit],
PIPE_BUFFER_USAGE_CPU_READ);
if (data == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto done;
}
for (i = 0; i < count; i++) {
ret = emit_const( svga, unit, offset + i, data[i] );
if (ret)
goto done;
}
done:
if (data)
pipe_buffer_unmap(screen, svga->curr.cb[unit]);
return ret;
}
static int emit_fs_consts( struct svga_context *svga,
unsigned dirty )
{
const struct svga_shader_result *result = svga->state.hw_draw.fs;
const struct svga_fs_compile_key *key = &result->key.fkey;
int ret = 0;
ret = emit_consts( svga, 0, PIPE_SHADER_FRAGMENT );
if (ret)
return ret;
/* The internally generated fragment shader for xor blending
* doesn't have a 'result' struct. It should be fixed to avoid
* this special case, but work around it with a NULL check:
*/
if (result != NULL &&
key->num_unnormalized_coords)
{
unsigned offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
int i;
for (i = 0; i < key->num_textures; i++) {
if (key->tex[i].unnormalized) {
struct pipe_texture *tex = svga->curr.texture[i];
float data[4];
data[0] = 1.0 / (float)tex->width[0];
data[1] = 1.0 / (float)tex->height[0];
data[2] = 1.0;
data[3] = 1.0;
ret = emit_const( svga,
PIPE_SHADER_FRAGMENT,
key->tex[i].width_height_idx + offset,
data );
if (ret)
return ret;
}
}
offset += key->num_unnormalized_coords;
}
return 0;
}
struct svga_tracked_state svga_hw_fs_parameters =
{
"hw fs params",
(SVGA_NEW_FS_CONST_BUFFER |
SVGA_NEW_FS_RESULT |
SVGA_NEW_TEXTURE_BINDING),
emit_fs_consts
};
/***********************************************************************
*/
static int emit_vs_consts( struct svga_context *svga,
unsigned dirty )
{
const struct svga_shader_result *result = svga->state.hw_draw.vs;
const struct svga_vs_compile_key *key = &result->key.vkey;
int ret = 0;
unsigned offset;
/* SVGA_NEW_VS_RESULT
*/
if (result == NULL)
return 0;
/* SVGA_NEW_VS_CONST_BUFFER
*/
ret = emit_consts( svga, 0, PIPE_SHADER_VERTEX );
if (ret)
return ret;
offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
/* SVGA_NEW_VS_RESULT
*/
if (key->need_prescale) {
ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
svga->state.hw_clear.prescale.scale );
if (ret)
return ret;
ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
svga->state.hw_clear.prescale.translate );
if (ret)
return ret;
}
/* SVGA_NEW_ZERO_STRIDE
*/
if (key->zero_stride_vertex_elements) {
unsigned i, curr_zero_stride = 0;
for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) {
if (key->zero_stride_vertex_elements & (1 << i)) {
ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
svga->curr.zero_stride_constants +
4 * curr_zero_stride );
if (ret)
return ret;
++curr_zero_stride;
}
}
}
return 0;
}
struct svga_tracked_state svga_hw_vs_parameters =
{
"hw vs params",
(SVGA_NEW_VS_CONST_BUFFER |
SVGA_NEW_ZERO_STRIDE |
SVGA_NEW_VS_RESULT),
emit_vs_consts
};

View file

@ -0,0 +1,455 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
#include "svga_debug.h"
#include "svga_hw_reg.h"
/***********************************************************************
* Hardware state update
*/
static int emit_framebuffer( struct svga_context *svga,
unsigned dirty )
{
const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
unsigned i;
enum pipe_error ret;
/* XXX: Need shadow state in svga->hw to eliminate redundant
* uploads, especially of NULL buffers.
*/
for(i = 0; i < PIPE_MAX_COLOR_BUFS; ++i) {
if (curr->cbufs[i] != hw->cbufs[i]) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i, curr->cbufs[i]);
if (ret != PIPE_OK)
return ret;
pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
}
}
if (curr->zsbuf != hw->zsbuf) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, curr->zsbuf);
if (ret != PIPE_OK)
return ret;
if (curr->zsbuf &&
curr->zsbuf->format == PIPE_FORMAT_Z24S8_UNORM) {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, curr->zsbuf);
if (ret != PIPE_OK)
return ret;
}
else {
ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
if (ret != PIPE_OK)
return ret;
}
pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
}
return 0;
}
struct svga_tracked_state svga_hw_framebuffer =
{
"hw framebuffer state",
SVGA_NEW_FRAME_BUFFER,
emit_framebuffer
};
/***********************************************************************
*/
static int emit_viewport( struct svga_context *svga,
unsigned dirty )
{
const struct pipe_viewport_state *viewport = &svga->curr.viewport;
struct svga_prescale prescale;
SVGA3dRect rect;
/* Not sure if this state is relevant with POSITIONT. Probably
* not, but setting to 0,1 avoids some state pingponging.
*/
float range_min = 0.0;
float range_max = 1.0;
float flip = -1.0;
boolean degenerate = FALSE;
enum pipe_error ret;
float fb_width = svga->curr.framebuffer.width;
float fb_height = svga->curr.framebuffer.height;
memset( &prescale, 0, sizeof(prescale) );
if (svga->curr.rast->templ.bypass_vs_clip_and_viewport) {
/* Avoid POSITIONT as it has a non trivial implementation outside the D3D
* API. Always generate a vertex shader.
*/
rect.x = 0;
rect.y = 0;
rect.w = svga->curr.framebuffer.width;
rect.h = svga->curr.framebuffer.height;
prescale.scale[0] = 2.0 / (float)rect.w;
prescale.scale[1] = - 2.0 / (float)rect.h;
prescale.scale[2] = 1.0;
prescale.scale[3] = 1.0;
prescale.translate[0] = -1.0f;
prescale.translate[1] = 1.0f;
prescale.translate[2] = 0;
prescale.translate[3] = 0;
prescale.enabled = TRUE;
} else {
/* Examine gallium viewport transformation and produce a screen
* rectangle and possibly vertex shader pre-transformation to
* get the same results.
*/
float fx = viewport->scale[0] * -1.0 + viewport->translate[0];
float fy = flip * viewport->scale[1] * -1.0 + viewport->translate[1];
float fw = viewport->scale[0] * 2;
float fh = flip * viewport->scale[1] * 2;
SVGA_DBG(DEBUG_VIEWPORT,
"\ninitial %f,%f %fx%f\n",
fx,
fy,
fw,
fh);
prescale.scale[0] = 1.0;
prescale.scale[1] = 1.0;
prescale.scale[2] = 1.0;
prescale.scale[3] = 1.0;
prescale.translate[0] = 0;
prescale.translate[1] = 0;
prescale.translate[2] = 0;
prescale.translate[3] = 0;
prescale.enabled = TRUE;
if (fw < 0) {
prescale.scale[0] *= -1.0;
prescale.translate[0] += -fw;
fw = -fw;
fx = viewport->scale[0] * 1.0 + viewport->translate[0];
}
if (fh < 0) {
prescale.scale[1] *= -1.0;
prescale.translate[1] += -fh;
fh = -fh;
fy = flip * viewport->scale[1] * 1.0 + viewport->translate[1];
}
if (fx < 0) {
prescale.translate[0] += fx;
prescale.scale[0] *= fw / (fw + fx);
fw += fx;
fx = 0;
}
if (fy < 0) {
prescale.translate[1] += fy;
prescale.scale[1] *= fh / (fh + fy);
fh += fy;
fy = 0;
}
if (fx + fw > fb_width) {
prescale.scale[0] *= fw / (fb_width - fx);
prescale.translate[0] -= fx * (fw / (fb_width - fx));
prescale.translate[0] += fx;
fw = fb_width - fx;
}
if (fy + fh > fb_height) {
prescale.scale[1] *= fh / (fb_height - fy);
prescale.translate[1] -= fy * (fh / (fb_height - fy));
prescale.translate[1] += fy;
fh = fb_height - fy;
}
if (fw < 0 || fh < 0) {
fw = fh = fx = fy = 0;
degenerate = TRUE;
goto out;
}
/* D3D viewport is integer space. Convert fx,fy,etc. to
* integers.
*
* TODO: adjust pretranslate correct for any subpixel error
* introduced converting to integers.
*/
rect.x = fx;
rect.y = fy;
rect.w = fw;
rect.h = fh;
SVGA_DBG(DEBUG_VIEWPORT,
"viewport error %f,%f %fx%f\n",
fabs((float)rect.x - fx),
fabs((float)rect.y - fy),
fabs((float)rect.w - fw),
fabs((float)rect.h - fh));
SVGA_DBG(DEBUG_VIEWPORT,
"viewport %d,%d %dx%d\n",
rect.x,
rect.y,
rect.w,
rect.h);
/* Finally, to get GL rasterization rules, need to tweak the
* screen-space coordinates slightly relative to D3D which is
* what hardware implements natively.
*/
if (svga->curr.rast->templ.gl_rasterization_rules) {
float adjust_x = 0.0;
float adjust_y = 0.0;
switch (svga->curr.reduced_prim) {
case PIPE_PRIM_LINES:
adjust_x = -0.5;
adjust_y = 0;
break;
case PIPE_PRIM_POINTS:
case PIPE_PRIM_TRIANGLES:
adjust_x = -0.375;
adjust_y = -0.5;
break;
}
prescale.translate[0] += adjust_x;
prescale.translate[1] += adjust_y;
prescale.translate[2] = 0.5; /* D3D clip space */
prescale.scale[2] = 0.5; /* D3D clip space */
}
range_min = viewport->scale[2] * -1.0 + viewport->translate[2];
range_max = viewport->scale[2] * 1.0 + viewport->translate[2];
/* D3D (and by implication SVGA) doesn't like dealing with zmax
* less than zmin. Detect that case, flip the depth range and
* invert our z-scale factor to achieve the same effect.
*/
if (range_min > range_max) {
float range_tmp;
range_tmp = range_min;
range_min = range_max;
range_max = range_tmp;
prescale.scale[2] = -prescale.scale[2];
}
}
if (prescale.enabled) {
float H[2];
float J[2];
int i;
SVGA_DBG(DEBUG_VIEWPORT,
"prescale %f,%f %fx%f\n",
prescale.translate[0],
prescale.translate[1],
prescale.scale[0],
prescale.scale[1]);
H[0] = (float)rect.w / 2.0;
H[1] = -(float)rect.h / 2.0;
J[0] = (float)rect.x + (float)rect.w / 2.0;
J[1] = (float)rect.y + (float)rect.h / 2.0;
SVGA_DBG(DEBUG_VIEWPORT,
"H %f,%f\n"
"J %fx%f\n",
H[0],
H[1],
J[0],
J[1]);
/* Adjust prescale to take into account the fact that it is
* going to be applied prior to the perspective divide and
* viewport transformation.
*
* Vwin = H(Vc/Vc.w) + J
*
* We want to tweak Vwin with scale and translation from above,
* as in:
*
* Vwin' = S Vwin + T
*
* But we can only modify the values at Vc. Plugging all the
* above together, and rearranging, eventually we get:
*
* Vwin' = H(Vc'/Vc'.w) + J
* where:
* Vc' = SVc + KVc.w
* K = (T + (S-1)J) / H
*
* Overwrite prescale.translate with values for K:
*/
for (i = 0; i < 2; i++) {
prescale.translate[i] = ((prescale.translate[i] +
(prescale.scale[i] - 1.0) * J[i]) / H[i]);
}
SVGA_DBG(DEBUG_VIEWPORT,
"clipspace %f,%f %fx%f\n",
prescale.translate[0],
prescale.translate[1],
prescale.scale[0],
prescale.scale[1]);
}
out:
if (degenerate) {
rect.x = 0;
rect.y = 0;
rect.w = 1;
rect.h = 1;
prescale.enabled = FALSE;
}
if (memcmp(&rect, &svga->state.hw_clear.viewport, sizeof(rect)) != 0) {
ret = SVGA3D_SetViewport(svga->swc, &rect);
if(ret != PIPE_OK)
return ret;
memcpy(&svga->state.hw_clear.viewport, &rect, sizeof(rect));
assert(sizeof(rect) == sizeof(svga->state.hw_clear.viewport));
}
if (svga->state.hw_clear.depthrange.zmin != range_min ||
svga->state.hw_clear.depthrange.zmax != range_max)
{
ret = SVGA3D_SetZRange(svga->swc, range_min, range_max );
if(ret != PIPE_OK)
return ret;
svga->state.hw_clear.depthrange.zmin = range_min;
svga->state.hw_clear.depthrange.zmax = range_max;
}
if (memcmp(&prescale, &svga->state.hw_clear.prescale, sizeof prescale) != 0) {
svga->dirty |= SVGA_NEW_PRESCALE;
svga->state.hw_clear.prescale = prescale;
}
return 0;
}
struct svga_tracked_state svga_hw_viewport =
{
"hw viewport state",
( SVGA_NEW_FRAME_BUFFER |
SVGA_NEW_VIEWPORT |
SVGA_NEW_RAST |
SVGA_NEW_REDUCED_PRIMITIVE ),
emit_viewport
};
/***********************************************************************
* Scissor state
*/
static int emit_scissor_rect( struct svga_context *svga,
unsigned dirty )
{
const struct pipe_scissor_state *scissor = &svga->curr.scissor;
SVGA3dRect rect;
rect.x = scissor->minx;
rect.y = scissor->miny;
rect.w = scissor->maxx - scissor->minx; /* + 1 ?? */
rect.h = scissor->maxy - scissor->miny; /* + 1 ?? */
return SVGA3D_SetScissorRect(svga->swc, &rect);
}
struct svga_tracked_state svga_hw_scissor =
{
"hw scissor state",
SVGA_NEW_SCISSOR,
emit_scissor_rect
};
/***********************************************************************
* Userclip state
*/
static int emit_clip_planes( struct svga_context *svga,
unsigned dirty )
{
unsigned i;
enum pipe_error ret;
/* TODO: just emit directly from svga_set_clip_state()?
*/
for (i = 0; i < svga->curr.clip.nr; i++) {
ret = SVGA3D_SetClipPlane( svga->swc,
i,
svga->curr.clip.ucp[i] );
if(ret != PIPE_OK)
return ret;
}
return 0;
}
struct svga_tracked_state svga_hw_clip_planes =
{
"hw viewport state",
SVGA_NEW_CLIP,
emit_clip_planes
};

View file

@ -0,0 +1,282 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
#include "svga_tgsi.h"
#include "svga_hw_reg.h"
static INLINE int compare_fs_keys( const struct svga_fs_compile_key *a,
const struct svga_fs_compile_key *b )
{
unsigned keysize = svga_fs_key_size( a );
return memcmp( a, b, keysize );
}
static struct svga_shader_result *search_fs_key( struct svga_fragment_shader *fs,
const struct svga_fs_compile_key *key )
{
struct svga_shader_result *result = fs->base.results;
assert(key);
for ( ; result; result = result->next) {
if (compare_fs_keys( key, &result->key.fkey ) == 0)
return result;
}
return NULL;
}
static enum pipe_error compile_fs( struct svga_context *svga,
struct svga_fragment_shader *fs,
const struct svga_fs_compile_key *key,
struct svga_shader_result **out_result )
{
struct svga_shader_result *result;
enum pipe_error ret;
result = svga_translate_fragment_program( fs, key );
if (result == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
}
ret = SVGA3D_DefineShader(svga->swc,
svga->state.next_fs_id,
SVGA3D_SHADERTYPE_PS,
result->tokens,
result->nr_tokens * sizeof result->tokens[0]);
if (ret)
goto fail;
*out_result = result;
result->id = svga->state.next_fs_id++;
result->next = fs->base.results;
fs->base.results = result;
return PIPE_OK;
fail:
if (result)
svga_destroy_shader_result( result );
return ret;
}
/* The blend workaround for simulating logicop xor behaviour requires
* that the incoming fragment color be white. This change achieves
* that by hooking up a hard-wired fragment shader that just emits
* color 1,1,1,1
*
* This is a slightly incomplete solution as it assumes that the
* actual bound shader has no other effects beyond generating a
* fragment color. In particular shaders containing TEXKIL and/or
* depth-write will not have the correct behaviour, nor will those
* expecting to use alphatest.
*
* These are avoidable issues, but they are not much worse than the
* unavoidable ones associated with this technique, so it's not clear
* how much effort should be expended trying to resolve them - the
* ultimate result will still not be correct in most cases.
*
* Shader below was generated with:
* SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt
*/
static int emit_white_fs( struct svga_context *svga )
{
int ret;
/* ps_3_0
* def c0, 1.000000, 0.000000, 0.000000, 1.000000
* mov oC0, c0.x
* end
*/
static const unsigned white_tokens[] = {
0xffff0300,
0x05000051,
0xa00f0000,
0x3f800000,
0x00000000,
0x00000000,
0x3f800000,
0x02000001,
0x800f0800,
0xa0000000,
0x0000ffff,
};
ret = SVGA3D_DefineShader(svga->swc,
svga->state.next_fs_id,
SVGA3D_SHADERTYPE_PS,
white_tokens,
sizeof(white_tokens));
if (ret)
return ret;
svga->state.white_fs_id = svga->state.next_fs_id++;
return 0;
}
/* SVGA_NEW_TEXTURE_BINDING
* SVGA_NEW_RAST
* SVGA_NEW_NEED_SWTNL
* SVGA_NEW_SAMPLER
*/
static int make_fs_key( const struct svga_context *svga,
struct svga_fs_compile_key *key )
{
int i;
int idx = 0;
memset(key, 0, sizeof *key);
/* Only need fragment shader fixup for twoside lighting if doing
* hwtnl. Otherwise the draw module does the whole job for us.
*
* SVGA_NEW_SWTNL
*/
if (!svga->state.sw.need_swtnl) {
/* SVGA_NEW_RAST
*/
key->light_twoside = svga->curr.rast->templ.light_twoside;
key->front_cw = (svga->curr.rast->templ.front_winding ==
PIPE_WINDING_CW);
}
/* XXX: want to limit this to the textures that the shader actually
* refers to.
*
* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
*/
for (i = 0; i < svga->curr.num_textures; i++) {
if (svga->curr.texture[i]) {
assert(svga->curr.sampler[i]);
key->tex[i].texture_target = svga->curr.texture[i]->target;
if (!svga->curr.sampler[i]->normalized_coords) {
key->tex[i].width_height_idx = idx++;
key->tex[i].unnormalized = TRUE;
++key->num_unnormalized_coords;
}
}
}
key->num_textures = svga->curr.num_textures;
idx = 0;
for (i = 0; i < svga->curr.num_samplers; ++i) {
if (svga->curr.sampler[i]) {
key->tex[i].compare_mode = svga->curr.sampler[i]->compare_mode;
key->tex[i].compare_func = svga->curr.sampler[i]->compare_func;
}
}
return 0;
}
static int emit_hw_fs( struct svga_context *svga,
unsigned dirty )
{
struct svga_shader_result *result = NULL;
unsigned id = SVGA3D_INVALID_ID;
int ret = 0;
/* SVGA_NEW_BLEND
*/
if (svga->curr.blend->need_white_fragments) {
if (svga->state.white_fs_id == SVGA3D_INVALID_ID) {
ret = emit_white_fs( svga );
if (ret)
return ret;
}
id = svga->state.white_fs_id;
}
else {
struct svga_fragment_shader *fs = svga->curr.fs;
struct svga_fs_compile_key key;
/* SVGA_NEW_TEXTURE_BINDING
* SVGA_NEW_RAST
* SVGA_NEW_NEED_SWTNL
* SVGA_NEW_SAMPLER
*/
ret = make_fs_key( svga, &key );
if (ret)
return ret;
result = search_fs_key( fs, &key );
if (!result) {
ret = compile_fs( svga, fs, &key, &result );
if (ret)
return ret;
}
assert (result);
id = result->id;
}
assert(id != SVGA3D_INVALID_ID);
if (id != svga->state.hw_draw.shader_id[PIPE_SHADER_FRAGMENT]) {
ret = SVGA3D_SetShader(svga->swc,
SVGA3D_SHADERTYPE_PS,
id );
if (ret)
return ret;
svga->dirty |= SVGA_NEW_FS_RESULT;
svga->state.hw_draw.shader_id[PIPE_SHADER_FRAGMENT] = id;
svga->state.hw_draw.fs = result;
}
return 0;
}
struct svga_tracked_state svga_hw_fs =
{
"fragment shader (hwtnl)",
(SVGA_NEW_FS |
SVGA_NEW_TEXTURE_BINDING |
SVGA_NEW_NEED_SWTNL |
SVGA_NEW_RAST |
SVGA_NEW_SAMPLER |
SVGA_NEW_BLEND),
emit_hw_fs
};

View file

@ -0,0 +1,200 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_state.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_debug.h"
#include "svga_hw_reg.h"
/***********************************************************************
*/
static INLINE SVGA3dDeclType
svga_translate_vertex_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_R32_FLOAT: return SVGA3D_DECLTYPE_FLOAT1;
case PIPE_FORMAT_R32G32_FLOAT: return SVGA3D_DECLTYPE_FLOAT2;
case PIPE_FORMAT_R32G32B32_FLOAT: return SVGA3D_DECLTYPE_FLOAT3;
case PIPE_FORMAT_R32G32B32A32_FLOAT: return SVGA3D_DECLTYPE_FLOAT4;
case PIPE_FORMAT_B8G8R8A8_UNORM: return SVGA3D_DECLTYPE_D3DCOLOR;
case PIPE_FORMAT_R8G8B8A8_USCALED: return SVGA3D_DECLTYPE_UBYTE4;
case PIPE_FORMAT_R16G16_SSCALED: return SVGA3D_DECLTYPE_SHORT2;
case PIPE_FORMAT_R16G16B16A16_SSCALED: return SVGA3D_DECLTYPE_SHORT4;
case PIPE_FORMAT_R8G8B8A8_UNORM: return SVGA3D_DECLTYPE_UBYTE4N;
case PIPE_FORMAT_R16G16_SNORM: return SVGA3D_DECLTYPE_SHORT2N;
case PIPE_FORMAT_R16G16B16A16_SNORM: return SVGA3D_DECLTYPE_SHORT4N;
case PIPE_FORMAT_R16G16_UNORM: return SVGA3D_DECLTYPE_USHORT2N;
case PIPE_FORMAT_R16G16B16A16_UNORM: return SVGA3D_DECLTYPE_USHORT4N;
/* These formats don't exist yet:
*
case PIPE_FORMAT_R10G10B10_USCALED: return SVGA3D_DECLTYPE_UDEC3;
case PIPE_FORMAT_R10G10B10_SNORM: return SVGA3D_DECLTYPE_DEC3N;
case PIPE_FORMAT_R16G16_FLOAT: return SVGA3D_DECLTYPE_FLOAT16_2;
case PIPE_FORMAT_R16G16B16A16_FLOAT: return SVGA3D_DECLTYPE_FLOAT16_4;
*/
default:
/* There are many formats without hardware support. This case
* will be hit regularly, meaning we'll need swvfetch.
*/
return SVGA3D_DECLTYPE_MAX;
}
}
static int update_need_swvfetch( struct svga_context *svga,
unsigned dirty )
{
unsigned i;
boolean need_swvfetch = FALSE;
for (i = 0; i < svga->curr.num_vertex_elements; i++) {
svga->state.sw.ve_format[i] = svga_translate_vertex_format(svga->curr.ve[i].src_format);
if (svga->state.sw.ve_format[i] == SVGA3D_DECLTYPE_MAX) {
need_swvfetch = TRUE;
break;
}
}
if (need_swvfetch != svga->state.sw.need_swvfetch) {
svga->state.sw.need_swvfetch = need_swvfetch;
svga->dirty |= SVGA_NEW_NEED_SWVFETCH;
}
return 0;
}
struct svga_tracked_state svga_update_need_swvfetch =
{
"update need_swvfetch",
( SVGA_NEW_VELEMENT ),
update_need_swvfetch
};
/***********************************************************************
*/
static int update_need_pipeline( struct svga_context *svga,
unsigned dirty )
{
boolean need_pipeline = FALSE;
/* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE
*/
if (svga->curr.rast->need_pipeline & (1 << svga->curr.reduced_prim)) {
SVGA_DBG(DEBUG_SWTNL, "%s: rast need_pipeline (%d) & prim (%x)\n",
__FUNCTION__,
svga->curr.rast->need_pipeline,
(1 << svga->curr.reduced_prim) );
need_pipeline = TRUE;
}
/* SVGA_NEW_EDGEFLAGS
*/
if (svga->curr.rast->hw_unfilled != PIPE_POLYGON_MODE_FILL &&
svga->curr.reduced_prim == PIPE_PRIM_TRIANGLES &&
svga->curr.edgeflags != NULL) {
SVGA_DBG(DEBUG_SWTNL, "%s: edgeflags\n", __FUNCTION__);
need_pipeline = TRUE;
}
/* SVGA_NEW_CLIP
*/
if (!svga->curr.rast->templ.bypass_vs_clip_and_viewport &&
svga->curr.clip.nr) {
SVGA_DBG(DEBUG_SWTNL, "%s: userclip\n", __FUNCTION__);
need_pipeline = TRUE;
}
if (need_pipeline != svga->state.sw.need_pipeline) {
svga->state.sw.need_pipeline = need_pipeline;
svga->dirty |= SVGA_NEW_NEED_PIPELINE;
}
return 0;
}
struct svga_tracked_state svga_update_need_pipeline =
{
"need pipeline",
(SVGA_NEW_RAST |
SVGA_NEW_CLIP |
SVGA_NEW_REDUCED_PRIMITIVE),
update_need_pipeline
};
/***********************************************************************
*/
static int update_need_swtnl( struct svga_context *svga,
unsigned dirty )
{
boolean need_swtnl;
if (svga->debug.no_swtnl) {
svga->state.sw.need_swvfetch = 0;
svga->state.sw.need_pipeline = 0;
}
need_swtnl = (svga->state.sw.need_swvfetch ||
svga->state.sw.need_pipeline);
if (svga->debug.force_swtnl) {
need_swtnl = 1;
}
if (need_swtnl != svga->state.sw.need_swtnl) {
SVGA_DBG(DEBUG_SWTNL|DEBUG_PERF,
"%s need_swvfetch: %s, need_pipeline %s\n",
__FUNCTION__,
svga->state.sw.need_swvfetch ? "true" : "false",
svga->state.sw.need_pipeline ? "true" : "false");
svga->state.sw.need_swtnl = need_swtnl;
svga->dirty |= SVGA_NEW_NEED_SWTNL;
svga->swtnl.new_vdecl = TRUE;
}
return 0;
}
struct svga_tracked_state svga_update_need_swtnl =
{
"need swtnl",
(SVGA_NEW_NEED_PIPELINE |
SVGA_NEW_NEED_SWVFETCH),
update_need_swtnl
};

View file

@ -0,0 +1,268 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
#include "svga_hw_reg.h"
struct rs_queue {
unsigned rs_count;
SVGA3dRenderState rs[SVGA3D_RS_MAX];
};
#define EMIT_RS(svga, value, token, fail) \
do { \
if (svga->state.hw_draw.rs[SVGA3D_RS_##token] != value) { \
svga_queue_rs( &queue, SVGA3D_RS_##token, value ); \
svga->state.hw_draw.rs[SVGA3D_RS_##token] = value; \
} \
} while (0)
#define EMIT_RS_FLOAT(svga, fvalue, token, fail) \
do { \
unsigned value = fui(fvalue); \
if (svga->state.hw_draw.rs[SVGA3D_RS_##token] != value) { \
svga_queue_rs( &queue, SVGA3D_RS_##token, value ); \
svga->state.hw_draw.rs[SVGA3D_RS_##token] = value; \
} \
} while (0)
static INLINE void
svga_queue_rs( struct rs_queue *q,
unsigned rss,
unsigned value )
{
q->rs[q->rs_count].state = rss;
q->rs[q->rs_count].uintValue = value;
q->rs_count++;
}
/* Compare old and new render states and emit differences between them
* to hardware. Simplest implementation would be to emit the whole of
* the "to" state.
*/
static int emit_rss( struct svga_context *svga,
unsigned dirty )
{
struct rs_queue queue;
queue.rs_count = 0;
if (dirty & SVGA_NEW_BLEND) {
const struct svga_blend_state *curr = svga->curr.blend;
EMIT_RS( svga, curr->rt[0].writemask, COLORWRITEENABLE, fail );
EMIT_RS( svga, curr->rt[0].blend_enable, BLENDENABLE, fail );
if (curr->rt[0].blend_enable) {
EMIT_RS( svga, curr->rt[0].srcblend, SRCBLEND, fail );
EMIT_RS( svga, curr->rt[0].dstblend, DSTBLEND, fail );
EMIT_RS( svga, curr->rt[0].blendeq, BLENDEQUATION, fail );
EMIT_RS( svga, curr->rt[0].separate_alpha_blend_enable,
SEPARATEALPHABLENDENABLE, fail );
if (curr->rt[0].separate_alpha_blend_enable) {
EMIT_RS( svga, curr->rt[0].srcblend_alpha, SRCBLENDALPHA, fail );
EMIT_RS( svga, curr->rt[0].dstblend_alpha, DSTBLENDALPHA, fail );
EMIT_RS( svga, curr->rt[0].blendeq_alpha, BLENDEQUATIONALPHA, fail );
}
}
}
if (dirty & (SVGA_NEW_DEPTH_STENCIL | SVGA_NEW_RAST)) {
const struct svga_depth_stencil_state *curr = svga->curr.depth;
const struct svga_rasterizer_state *rast = svga->curr.rast;
if (!curr->stencil[0].enabled)
{
/* Stencil disabled
*/
EMIT_RS( svga, FALSE, STENCILENABLE, fail );
EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail );
}
else if (curr->stencil[0].enabled && !curr->stencil[1].enabled)
{
/* Regular stencil
*/
EMIT_RS( svga, TRUE, STENCILENABLE, fail );
EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail );
EMIT_RS( svga, curr->stencil[0].func, STENCILFUNC, fail );
EMIT_RS( svga, curr->stencil[0].fail, STENCILFAIL, fail );
EMIT_RS( svga, curr->stencil[0].zfail, STENCILZFAIL, fail );
EMIT_RS( svga, curr->stencil[0].pass, STENCILPASS, fail );
EMIT_RS( svga, curr->stencil_ref, STENCILREF, fail );
EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail );
EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail );
}
else
{
int cw, ccw;
/* Hardware frontwinding is always CW, so if ours is also CW,
* then our definition of front face agrees with hardware.
* Otherwise need to flip.
*/
if (rast->templ.front_winding == PIPE_WINDING_CW) {
cw = 0;
ccw = 1;
}
else {
cw = 1;
ccw = 0;
}
/* Twoside stencil
*/
EMIT_RS( svga, TRUE, STENCILENABLE, fail );
EMIT_RS( svga, TRUE, STENCILENABLE2SIDED, fail );
EMIT_RS( svga, curr->stencil[cw].func, STENCILFUNC, fail );
EMIT_RS( svga, curr->stencil[cw].fail, STENCILFAIL, fail );
EMIT_RS( svga, curr->stencil[cw].zfail, STENCILZFAIL, fail );
EMIT_RS( svga, curr->stencil[cw].pass, STENCILPASS, fail );
EMIT_RS( svga, curr->stencil[ccw].func, CCWSTENCILFUNC, fail );
EMIT_RS( svga, curr->stencil[ccw].fail, CCWSTENCILFAIL, fail );
EMIT_RS( svga, curr->stencil[ccw].zfail, CCWSTENCILZFAIL, fail );
EMIT_RS( svga, curr->stencil[ccw].pass, CCWSTENCILPASS, fail );
EMIT_RS( svga, curr->stencil_ref, STENCILREF, fail );
EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail );
EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail );
}
EMIT_RS( svga, curr->zenable, ZENABLE, fail );
if (curr->zenable) {
EMIT_RS( svga, curr->zfunc, ZFUNC, fail );
EMIT_RS( svga, curr->zwriteenable, ZWRITEENABLE, fail );
}
EMIT_RS( svga, curr->alphatestenable, ALPHATESTENABLE, fail );
if (curr->alphatestenable) {
EMIT_RS( svga, curr->alphafunc, ALPHAFUNC, fail );
EMIT_RS_FLOAT( svga, curr->alpharef, ALPHAREF, fail );
}
}
if (dirty & SVGA_NEW_RAST)
{
const struct svga_rasterizer_state *curr = svga->curr.rast;
/* Shademode: still need to rearrange index list to move
* flat-shading PV first vertex.
*/
EMIT_RS( svga, curr->shademode, SHADEMODE, fail );
EMIT_RS( svga, curr->cullmode, CULLMODE, fail );
EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail );
EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail );
EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail );
EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail );
EMIT_RS_FLOAT( svga, curr->pointsize, POINTSIZE, fail );
EMIT_RS_FLOAT( svga, curr->pointsize_min, POINTSIZEMIN, fail );
EMIT_RS_FLOAT( svga, curr->pointsize_max, POINTSIZEMAX, fail );
}
if (dirty & (SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE))
{
const struct svga_rasterizer_state *curr = svga->curr.rast;
float slope = 0.0;
float bias = 0.0;
/* Need to modify depth bias according to bound depthbuffer
* format. Don't do hardware depthbias while the software
* pipeline is active.
*/
if (!svga->state.sw.need_pipeline &&
svga->curr.framebuffer.zsbuf)
{
slope = curr->slopescaledepthbias;
bias = svga->curr.depthscale * curr->depthbias;
}
EMIT_RS_FLOAT( svga, slope, SLOPESCALEDEPTHBIAS, fail );
EMIT_RS_FLOAT( svga, bias, DEPTHBIAS, fail );
}
if (queue.rs_count) {
SVGA3dRenderState *rs;
if (SVGA3D_BeginSetRenderState( svga->swc,
&rs,
queue.rs_count ) != PIPE_OK)
goto fail;
memcpy( rs,
queue.rs,
queue.rs_count * sizeof queue.rs[0]);
SVGA_FIFOCommitAll( svga->swc );
}
/* Also blend color:
*/
return 0;
fail:
/* XXX: need to poison cached hardware state on failure to ensure
* dirty state gets re-emitted. Fix this by re-instating partial
* FIFOCommit command and only updating cached hw state once the
* initial allocation has succeeded.
*/
memset(svga->state.hw_draw.rs, 0xcd, sizeof(svga->state.hw_draw.rs));
return PIPE_ERROR_OUT_OF_MEMORY;
}
struct svga_tracked_state svga_hw_rss =
{
"hw rss state",
(SVGA_NEW_BLEND |
SVGA_NEW_DEPTH_STENCIL |
SVGA_NEW_RAST |
SVGA_NEW_FRAME_BUFFER |
SVGA_NEW_NEED_PIPELINE),
emit_rss
};

View file

@ -0,0 +1,279 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "svga_screen_texture.h"
#include "svga_winsys.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
#include "svga_hw_reg.h"
void svga_cleanup_tss_binding(struct svga_context *svga)
{
int i;
unsigned count = MAX2( svga->curr.num_textures,
svga->state.hw_draw.num_views );
for (i = 0; i < count; i++) {
struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
svga_sampler_view_reference(&view->v, NULL);
pipe_texture_reference( &svga->curr.texture[i], NULL );
pipe_texture_reference( &view->texture, NULL );
view->dirty = 1;
}
}
static int
update_tss_binding(struct svga_context *svga,
unsigned dirty )
{
unsigned i;
unsigned count = MAX2( svga->curr.num_textures,
svga->state.hw_draw.num_views );
unsigned min_lod;
unsigned max_lod;
struct {
struct {
unsigned unit;
struct svga_hw_view_state *view;
} bind[PIPE_MAX_SAMPLERS];
unsigned bind_count;
} queue;
queue.bind_count = 0;
for (i = 0; i < count; i++) {
const struct svga_sampler_state *s = svga->curr.sampler[i];
struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
/* get min max lod */
if (svga->curr.texture[i]) {
min_lod = MAX2(s->view_min_lod, 0);
max_lod = MIN2(s->view_max_lod, svga->curr.texture[i]->last_level);
} else {
min_lod = 0;
max_lod = 0;
}
if (view->texture != svga->curr.texture[i] ||
view->min_lod != min_lod ||
view->max_lod != max_lod) {
svga_sampler_view_reference(&view->v, NULL);
pipe_texture_reference( &view->texture, svga->curr.texture[i] );
view->dirty = TRUE;
view->min_lod = min_lod;
view->max_lod = max_lod;
if (svga->curr.texture[i])
view->v = svga_get_tex_sampler_view(&svga->pipe,
svga->curr.texture[i],
min_lod,
max_lod);
}
if (view->dirty) {
queue.bind[queue.bind_count].unit = i;
queue.bind[queue.bind_count].view = view;
queue.bind_count++;
}
else if (view->v) {
svga_validate_sampler_view(svga, view->v);
}
}
svga->state.hw_draw.num_views = svga->curr.num_textures;
if (queue.bind_count) {
SVGA3dTextureState *ts;
if (SVGA3D_BeginSetTextureState( svga->swc,
&ts,
queue.bind_count ) != PIPE_OK)
goto fail;
for (i = 0; i < queue.bind_count; i++) {
ts[i].stage = queue.bind[i].unit;
ts[i].name = SVGA3D_TS_BIND_TEXTURE;
if (queue.bind[i].view->v) {
svga->swc->surface_relocation(svga->swc,
&ts[i].value,
queue.bind[i].view->v->handle,
PIPE_BUFFER_USAGE_GPU_READ);
}
else {
ts[i].value = SVGA3D_INVALID_ID;
}
queue.bind[i].view->dirty = FALSE;
}
SVGA_FIFOCommitAll( svga->swc );
}
return 0;
fail:
return PIPE_ERROR_OUT_OF_MEMORY;
}
struct svga_tracked_state svga_hw_tss_binding = {
"texture binding emit",
SVGA_NEW_TEXTURE_BINDING |
SVGA_NEW_SAMPLER,
update_tss_binding
};
/***********************************************************************
*/
struct ts_queue {
unsigned ts_count;
SVGA3dTextureState ts[PIPE_MAX_SAMPLERS*SVGA3D_TS_MAX];
};
#define EMIT_TS(svga, unit, val, token, fail) \
do { \
if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) { \
svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val ); \
svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val; \
} \
} while (0)
#define EMIT_TS_FLOAT(svga, unit, fvalue, token, fail) \
do { \
unsigned val = fui(fvalue); \
if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) { \
svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val ); \
svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val; \
} \
} while (0)
static INLINE void
svga_queue_tss( struct ts_queue *q,
unsigned unit,
unsigned tss,
unsigned value )
{
assert(q->ts_count < sizeof(q->ts)/sizeof(q->ts[0]));
q->ts[q->ts_count].stage = unit;
q->ts[q->ts_count].name = tss;
q->ts[q->ts_count].value = value;
q->ts_count++;
}
static int
update_tss(struct svga_context *svga,
unsigned dirty )
{
unsigned i;
struct ts_queue queue;
queue.ts_count = 0;
for (i = 0; i < svga->curr.num_samplers; i++) {
if (svga->curr.sampler[i]) {
const struct svga_sampler_state *curr = svga->curr.sampler[i];
EMIT_TS(svga, i, curr->mipfilter, MIPFILTER, fail);
EMIT_TS(svga, i, curr->min_lod, TEXTURE_MIPMAP_LEVEL, fail);
EMIT_TS(svga, i, curr->magfilter, MAGFILTER, fail);
EMIT_TS(svga, i, curr->minfilter, MINFILTER, fail);
EMIT_TS(svga, i, curr->aniso_level, TEXTURE_ANISOTROPIC_LEVEL, fail);
EMIT_TS_FLOAT(svga, i, curr->lod_bias, TEXTURE_LOD_BIAS, fail);
EMIT_TS(svga, i, curr->addressu, ADDRESSU, fail);
EMIT_TS(svga, i, curr->addressw, ADDRESSW, fail);
EMIT_TS(svga, i, curr->bordercolor, BORDERCOLOR, fail);
// TEXCOORDINDEX -- hopefully not needed
if (svga->curr.tex_flags.flag_1d & (1 << i)) {
debug_printf("wrap 1d tex %d\n", i);
EMIT_TS(svga, i, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV, fail);
}
else
EMIT_TS(svga, i, curr->addressv, ADDRESSV, fail);
if (svga->curr.tex_flags.flag_srgb & (1 << i))
EMIT_TS_FLOAT(svga, i, 2.2f, GAMMA, fail);
else
EMIT_TS_FLOAT(svga, i, 1.0f, GAMMA, fail);
}
}
if (queue.ts_count) {
SVGA3dTextureState *ts;
if (SVGA3D_BeginSetTextureState( svga->swc,
&ts,
queue.ts_count ) != PIPE_OK)
goto fail;
memcpy( ts,
queue.ts,
queue.ts_count * sizeof queue.ts[0]);
SVGA_FIFOCommitAll( svga->swc );
}
return 0;
fail:
/* XXX: need to poison cached hardware state on failure to ensure
* dirty state gets re-emitted. Fix this by re-instating partial
* FIFOCommit command and only updating cached hw state once the
* initial allocation has succeeded.
*/
memset(svga->state.hw_draw.ts, 0xcd, sizeof(svga->state.hw_draw.ts));
return PIPE_ERROR_OUT_OF_MEMORY;
}
struct svga_tracked_state svga_hw_tss = {
"texture state emit",
(SVGA_NEW_SAMPLER |
SVGA_NEW_TEXTURE_FLAGS),
update_tss
};

View file

@ -0,0 +1,182 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_upload_mgr.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_draw.h"
#include "svga_tgsi.h"
#include "svga_screen.h"
#include "svga_screen_buffer.h"
#include "svga_hw_reg.h"
static int
upload_user_buffers( struct svga_context *svga )
{
enum pipe_error ret = PIPE_OK;
int i;
int nr;
if (0)
debug_printf("%s: %d\n", __FUNCTION__, svga->curr.num_vertex_buffers);
nr = svga->curr.num_vertex_buffers;
for (i = 0; i < nr; i++)
{
if (svga_buffer_is_user_buffer(svga->curr.vb[i].buffer))
{
struct pipe_buffer *upload_buffer = NULL;
unsigned offset = /*svga->curr.vb[i].buffer_offset*/ 0;
unsigned size = svga->curr.vb[i].buffer->size /*- offset*/;
unsigned upload_offset;
ret = u_upload_buffer( svga->upload_vb,
offset,
size,
svga->curr.vb[i].buffer,
&upload_offset,
&upload_buffer );
if (ret)
return ret;
if (0)
debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sz %d\n",
__FUNCTION__,
i,
svga->curr.vb[i].buffer,
upload_buffer, upload_offset, size);
/* Make sure we release the old buffer and end up with the
* correct refcount on the uploaded buffer.
*/
pipe_buffer_reference( &svga->curr.vb[i].buffer, NULL );
svga->curr.vb[i].buffer = upload_buffer;
svga->curr.vb[i].buffer_offset = upload_offset;
}
}
if (0)
debug_printf("%s: DONE\n", __FUNCTION__);
return ret;
}
/***********************************************************************
*/
static int emit_hw_vs_vdecl( struct svga_context *svga,
unsigned dirty )
{
const struct pipe_vertex_element *ve = svga->curr.ve;
SVGA3dVertexDecl decl;
unsigned i;
assert(svga->curr.num_vertex_elements >=
svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]);
svga_hwtnl_reset_vdecl( svga->hwtnl,
svga->curr.num_vertex_elements );
for (i = 0; i < svga->curr.num_vertex_elements; i++) {
const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index];
unsigned usage, index;
svga_generate_vdecl_semantics( i, &usage, &index );
/* SVGA_NEW_VELEMENT
*/
decl.identity.type = svga->state.sw.ve_format[i];
decl.identity.method = SVGA3D_DECLMETHOD_DEFAULT;
decl.identity.usage = usage;
decl.identity.usageIndex = index;
decl.array.stride = vb->stride;
decl.array.offset = (vb->buffer_offset +
ve[i].src_offset);
svga_hwtnl_vdecl( svga->hwtnl,
i,
&decl,
vb->buffer );
}
return 0;
}
static int emit_hw_vdecl( struct svga_context *svga,
unsigned dirty )
{
int ret = 0;
/* SVGA_NEW_NEED_SWTNL
*/
if (svga->state.sw.need_swtnl)
return 0; /* Do not emit during swtnl */
/* If we get to here, we know that we're going to draw. Upload
* userbuffers now and try to combine multiple userbuffers from
* multiple draw calls into a single host buffer for performance.
*/
if (svga->curr.any_user_vertex_buffers &&
SVGA_COMBINE_USERBUFFERS)
{
ret = upload_user_buffers( svga );
if (ret)
return ret;
svga->curr.any_user_vertex_buffers = FALSE;
}
return emit_hw_vs_vdecl( svga, dirty );
}
struct svga_tracked_state svga_hw_vdecl =
{
"hw vertex decl state (hwtnl version)",
( SVGA_NEW_NEED_SWTNL |
SVGA_NEW_VELEMENT |
SVGA_NEW_VBUFFER |
SVGA_NEW_RAST |
SVGA_NEW_FS |
SVGA_NEW_VS ),
emit_hw_vdecl
};

View file

@ -0,0 +1,239 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_inlines.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "translate/translate.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
#include "svga_tgsi.h"
#include "svga_hw_reg.h"
/***********************************************************************
*/
static INLINE int compare_vs_keys( const struct svga_vs_compile_key *a,
const struct svga_vs_compile_key *b )
{
unsigned keysize = svga_vs_key_size( a );
return memcmp( a, b, keysize );
}
static struct svga_shader_result *search_vs_key( struct svga_vertex_shader *vs,
const struct svga_vs_compile_key *key )
{
struct svga_shader_result *result = vs->base.results;
assert(key);
for ( ; result; result = result->next) {
if (compare_vs_keys( key, &result->key.vkey ) == 0)
return result;
}
return NULL;
}
static enum pipe_error compile_vs( struct svga_context *svga,
struct svga_vertex_shader *vs,
const struct svga_vs_compile_key *key,
struct svga_shader_result **out_result )
{
struct svga_shader_result *result;
enum pipe_error ret = PIPE_OK;
result = svga_translate_vertex_program( vs, key );
if (result == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
}
ret = SVGA3D_DefineShader(svga->swc,
svga->state.next_vs_id,
SVGA3D_SHADERTYPE_VS,
result->tokens,
result->nr_tokens * sizeof result->tokens[0]);
if (ret)
goto fail;
*out_result = result;
result->id = svga->state.next_vs_id++;
result->next = vs->base.results;
vs->base.results = result;
return PIPE_OK;
fail:
if (result)
svga_destroy_shader_result( result );
return ret;
}
/* SVGA_NEW_PRESCALE, SVGA_NEW_RAST, SVGA_NEW_ZERO_STRIDE
*/
static int make_vs_key( struct svga_context *svga,
struct svga_vs_compile_key *key )
{
memset(key, 0, sizeof *key);
key->need_prescale = svga->state.hw_clear.prescale.enabled;
key->allow_psiz = svga->curr.rast->templ.point_size_per_vertex;
key->zero_stride_vertex_elements =
svga->curr.zero_stride_vertex_elements;
key->num_zero_stride_vertex_elements =
svga->curr.num_zero_stride_vertex_elements;
return 0;
}
static int emit_hw_vs( struct svga_context *svga,
unsigned dirty )
{
struct svga_shader_result *result = NULL;
unsigned id = SVGA3D_INVALID_ID;
int ret = 0;
/* SVGA_NEW_NEED_SWTNL */
if (!svga->state.sw.need_swtnl) {
struct svga_vertex_shader *vs = svga->curr.vs;
struct svga_vs_compile_key key;
ret = make_vs_key( svga, &key );
if (ret)
return ret;
result = search_vs_key( vs, &key );
if (!result) {
ret = compile_vs( svga, vs, &key, &result );
if (ret)
return ret;
}
assert (result);
id = result->id;
}
if (id != svga->state.hw_draw.shader_id[PIPE_SHADER_VERTEX]) {
ret = SVGA3D_SetShader(svga->swc,
SVGA3D_SHADERTYPE_VS,
id );
if (ret)
return ret;
svga->dirty |= SVGA_NEW_VS_RESULT;
svga->state.hw_draw.shader_id[PIPE_SHADER_VERTEX] = id;
svga->state.hw_draw.vs = result;
}
return 0;
}
struct svga_tracked_state svga_hw_vs =
{
"vertex shader (hwtnl)",
(SVGA_NEW_VS |
SVGA_NEW_PRESCALE |
SVGA_NEW_NEED_SWTNL |
SVGA_NEW_ZERO_STRIDE),
emit_hw_vs
};
/***********************************************************************
*/
static int update_zero_stride( struct svga_context *svga,
unsigned dirty )
{
unsigned i;
svga->curr.zero_stride_vertex_elements = 0;
svga->curr.num_zero_stride_vertex_elements = 0;
for (i = 0; i < svga->curr.num_vertex_elements; i++) {
const struct pipe_vertex_element *vel = &svga->curr.ve[i];
const struct pipe_vertex_buffer *vbuffer = &svga->curr.vb[
vel->vertex_buffer_index];
if (vbuffer->stride == 0) {
unsigned const_idx =
svga->curr.num_zero_stride_vertex_elements;
struct translate *translate;
struct translate_key key;
void *mapped_buffer;
svga->curr.zero_stride_vertex_elements |= (1 << i);
++svga->curr.num_zero_stride_vertex_elements;
key.output_stride = 4 * sizeof(float);
key.nr_elements = 1;
key.element[0].input_format = vel->src_format;
key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
key.element[0].input_buffer = vel->vertex_buffer_index;
key.element[0].input_offset = vel->src_offset;
key.element[0].output_offset = const_idx * 4 * sizeof(float);
translate_key_sanitize(&key);
/* translate_generic_create is technically private but
* we don't want to code-generate, just want generic
* translation */
translate = translate_generic_create(&key);
assert(vel->src_offset == 0);
mapped_buffer = pipe_buffer_map_range(svga->pipe.screen,
vbuffer->buffer,
vel->src_offset,
pf_get_size(vel->src_format),
PIPE_BUFFER_USAGE_CPU_READ);
translate->set_buffer(translate, vel->vertex_buffer_index,
mapped_buffer,
vbuffer->stride);
translate->run(translate, 0, 1,
svga->curr.zero_stride_constants);
pipe_buffer_unmap(svga->pipe.screen,
vbuffer->buffer);
translate->release(translate);
}
}
if (svga->curr.num_zero_stride_vertex_elements)
svga->dirty |= SVGA_NEW_ZERO_STRIDE;
return 0;
}
struct svga_tracked_state svga_hw_update_zero_stride =
{
"update zero_stride",
( SVGA_NEW_VELEMENT |
SVGA_NEW_VBUFFER ),
update_zero_stride
};

View file

@ -0,0 +1,52 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_SWTNL_H
#define SVGA_SWTNL_H
#include "pipe/p_compiler.h"
struct svga_context;
struct pipe_context;
struct pipe_buffer;
struct vbuf_render;
boolean svga_init_swtnl( struct svga_context *svga );
void svga_destroy_swtnl( struct svga_context *svga );
enum pipe_error
svga_swtnl_draw_range_elements(struct svga_context *svga,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,
unsigned prim,
unsigned start,
unsigned count);
#endif

View file

@ -0,0 +1,349 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "draw/draw_vbuf.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "util/u_debug.h"
#include "pipe/p_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_simple_shaders.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_swtnl.h"
#include "svga_types.h"
#include "svga_reg.h"
#include "svga3d_reg.h"
#include "svga_draw.h"
#include "svga_swtnl_private.h"
static const struct vertex_info *
svga_vbuf_render_get_vertex_info( struct vbuf_render *render )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
svga_swtnl_update_vdecl(svga);
return &svga_render->vertex_info;
}
static boolean
svga_vbuf_render_allocate_vertices( struct vbuf_render *render,
ushort vertex_size,
ushort nr_vertices )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
struct pipe_screen *screen = svga->pipe.screen;
size_t size = (size_t)nr_vertices * (size_t)vertex_size;
boolean new_vbuf = FALSE;
boolean new_ibuf = FALSE;
if (svga_render->vertex_size != vertex_size)
svga->swtnl.new_vdecl = TRUE;
svga_render->vertex_size = (size_t)vertex_size;
if (svga->swtnl.new_vbuf)
new_ibuf = new_vbuf = TRUE;
svga->swtnl.new_vbuf = FALSE;
if (svga_render->vbuf_size < svga_render->vbuf_offset + svga_render->vbuf_used + size)
new_vbuf = TRUE;
if (new_vbuf)
pipe_buffer_reference(&svga_render->vbuf, NULL);
if (new_ibuf)
pipe_buffer_reference(&svga_render->ibuf, NULL);
if (!svga_render->vbuf) {
svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size);
svga_render->vbuf = pipe_buffer_create(screen,
0,
PIPE_BUFFER_USAGE_VERTEX,
svga_render->vbuf_size);
if(!svga_render->vbuf) {
svga_context_flush(svga, NULL);
svga_render->vbuf = pipe_buffer_create(screen,
0,
PIPE_BUFFER_USAGE_VERTEX,
svga_render->vbuf_size);
assert(svga_render->vbuf);
}
svga->swtnl.new_vdecl = TRUE;
svga_render->vbuf_offset = 0;
} else {
svga_render->vbuf_offset += svga_render->vbuf_used;
}
svga_render->vbuf_used = 0;
if (svga->swtnl.new_vdecl)
svga_render->vdecl_offset = svga_render->vbuf_offset;
return TRUE;
}
static void *
svga_vbuf_render_map_vertices( struct vbuf_render *render )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
struct pipe_screen *screen = svga->pipe.screen;
char *ptr = (char*)pipe_buffer_map(screen,
svga_render->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_FLUSH_EXPLICIT);
return ptr + svga_render->vbuf_offset;
}
static void
svga_vbuf_render_unmap_vertices( struct vbuf_render *render,
ushort min_index,
ushort max_index )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
struct pipe_screen *screen = svga->pipe.screen;
unsigned offset, length;
size_t used = svga_render->vertex_size * ((size_t)max_index + 1);
offset = svga_render->vbuf_offset + svga_render->vertex_size * min_index;
length = svga_render->vertex_size * (max_index + 1 - min_index);
pipe_buffer_flush_mapped_range(screen, svga_render->vbuf, offset, length);
pipe_buffer_unmap(screen, svga_render->vbuf);
svga_render->min_index = min_index;
svga_render->max_index = max_index;
svga_render->vbuf_used = MAX2(svga_render->vbuf_used, used);
}
static boolean
svga_vbuf_render_set_primitive( struct vbuf_render *render,
unsigned prim )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
svga_render->prim = prim;
return TRUE;
}
static void
svga_vbuf_sumbit_state( struct svga_vbuf_render *svga_render )
{
struct svga_context *svga = svga_render->svga;
SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS];
enum pipe_error ret;
int i;
/* if the vdecl or vbuf hasn't changed do nothing */
if (!svga->swtnl.new_vdecl)
return;
memcpy(vdecl, svga_render->vdecl, sizeof(vdecl));
/* flush the hw state */
ret = svga_hwtnl_flush(svga->hwtnl);
if (ret) {
svga_context_flush(svga, NULL);
ret = svga_hwtnl_flush(svga->hwtnl);
/* if we hit this path we might become synced with hw */
svga->swtnl.new_vbuf = TRUE;
assert(ret == 0);
}
svga_hwtnl_reset_vdecl(svga->hwtnl, svga_render->vdecl_count);
for (i = 0; i < svga_render->vdecl_count; i++) {
vdecl[i].array.offset += svga_render->vdecl_offset;
svga_hwtnl_vdecl( svga->hwtnl,
i,
&vdecl[i],
svga_render->vbuf );
}
/* We have already taken care of flatshading, so let the hwtnl
* module use whatever is most convenient:
*/
if (svga->state.sw.need_pipeline) {
svga_hwtnl_set_flatshade(svga->hwtnl, FALSE, FALSE);
svga_hwtnl_set_unfilled(svga->hwtnl, PIPE_POLYGON_MODE_FILL);
}
else {
svga_hwtnl_set_flatshade( svga->hwtnl,
svga->curr.rast->templ.flatshade,
svga->curr.rast->templ.flatshade_first );
svga_hwtnl_set_unfilled( svga->hwtnl,
svga->curr.rast->hw_unfilled );
}
svga->swtnl.new_vdecl = FALSE;
}
static void
svga_vbuf_render_draw_arrays( struct vbuf_render *render,
unsigned start,
uint nr )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size;
enum pipe_error ret = 0;
svga_vbuf_sumbit_state(svga_render);
/* Need to call update_state() again as the draw module may have
* altered some of our state behind our backs. Testcase:
* redbook/polys.c
*/
svga_update_state_retry( svga, SVGA_STATE_HW_DRAW );
ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr);
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr);
svga->swtnl.new_vbuf = TRUE;
assert(ret == PIPE_OK);
}
}
static void
svga_vbuf_render_draw( struct vbuf_render *render,
const ushort *indices,
uint nr_indices)
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
struct svga_context *svga = svga_render->svga;
struct pipe_screen *screen = svga->pipe.screen;
unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size;
boolean ret;
size_t size = 2 * nr_indices;
assert(( svga_render->vbuf_offset - svga_render->vdecl_offset) % svga_render->vertex_size == 0);
if (svga_render->ibuf_size < svga_render->ibuf_offset + size)
pipe_buffer_reference(&svga_render->ibuf, NULL);
if (!svga_render->ibuf) {
svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size);
svga_render->ibuf = pipe_buffer_create(screen,
0,
PIPE_BUFFER_USAGE_VERTEX,
svga_render->ibuf_size);
svga_render->ibuf_offset = 0;
}
pipe_buffer_write(screen, svga_render->ibuf,
svga_render->ibuf_offset, 2 * nr_indices, indices);
/* off to hardware */
svga_vbuf_sumbit_state(svga_render);
/* Need to call update_state() again as the draw module may have
* altered some of our state behind our backs. Testcase:
* redbook/polys.c
*/
svga_update_state_retry( svga, SVGA_STATE_HW_DRAW );
ret = svga_hwtnl_draw_range_elements(svga->hwtnl,
svga_render->ibuf,
2,
svga_render->min_index,
svga_render->max_index,
svga_render->prim,
svga_render->ibuf_offset / 2, nr_indices, bias);
if(ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = svga_hwtnl_draw_range_elements(svga->hwtnl,
svga_render->ibuf,
2,
svga_render->min_index,
svga_render->max_index,
svga_render->prim,
svga_render->ibuf_offset / 2, nr_indices, bias);
svga->swtnl.new_vbuf = TRUE;
assert(ret == PIPE_OK);
}
svga_render->ibuf_offset += size;
}
static void
svga_vbuf_render_release_vertices( struct vbuf_render *render )
{
}
static void
svga_vbuf_render_destroy( struct vbuf_render *render )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
pipe_buffer_reference(&svga_render->vbuf, NULL);
pipe_buffer_reference(&svga_render->ibuf, NULL);
FREE(svga_render);
}
/**
* Create a new primitive render.
*/
struct vbuf_render *
svga_vbuf_render_create( struct svga_context *svga )
{
struct svga_vbuf_render *svga_render = CALLOC_STRUCT(svga_vbuf_render);
svga_render->svga = svga;
svga_render->ibuf_size = 0;
svga_render->vbuf_size = 0;
svga_render->ibuf_alloc_size = 4*1024;
svga_render->vbuf_alloc_size = 64*1024;
svga_render->base.max_vertex_buffer_bytes = 64*1024/10;
svga_render->base.max_indices = 65536;
svga_render->base.get_vertex_info = svga_vbuf_render_get_vertex_info;
svga_render->base.allocate_vertices = svga_vbuf_render_allocate_vertices;
svga_render->base.map_vertices = svga_vbuf_render_map_vertices;
svga_render->base.unmap_vertices = svga_vbuf_render_unmap_vertices;
svga_render->base.set_primitive = svga_vbuf_render_set_primitive;
svga_render->base.draw = svga_vbuf_render_draw;
svga_render->base.draw_arrays = svga_vbuf_render_draw_arrays;
svga_render->base.release_vertices = svga_vbuf_render_release_vertices;
svga_render->base.destroy = svga_vbuf_render_destroy;
return &svga_render->base;
}

View file

@ -0,0 +1,170 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "pipe/p_inlines.h"
#include "pipe/p_state.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_swtnl.h"
#include "svga_state.h"
#include "svga_swtnl_private.h"
enum pipe_error
svga_swtnl_draw_range_elements(struct svga_context *svga,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,
unsigned prim, unsigned start, unsigned count)
{
struct draw_context *draw = svga->swtnl.draw;
unsigned i;
const void *map;
enum pipe_error ret;
assert(!svga->dirty);
assert(svga->state.sw.need_swtnl);
assert(draw);
ret = svga_update_state(svga, SVGA_STATE_SWTNL_DRAW);
if (ret) {
svga_context_flush(svga, NULL);
ret = svga_update_state(svga, SVGA_STATE_SWTNL_DRAW);
svga->swtnl.new_vbuf = TRUE;
assert(ret == PIPE_OK);
}
/*
* Map vertex buffers
*/
for (i = 0; i < svga->curr.num_vertex_buffers; i++) {
map = pipe_buffer_map(svga->pipe.screen,
svga->curr.vb[i].buffer,
PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_vertex_buffer(draw, i, map);
}
/* Map index buffer, if present */
if (indexBuffer) {
map = pipe_buffer_map(svga->pipe.screen, indexBuffer,
PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_element_buffer_range(draw,
indexSize,
min_index,
max_index,
map);
}
if (svga->curr.cb[PIPE_SHADER_VERTEX]) {
map = pipe_buffer_map(svga->pipe.screen,
svga->curr.cb[PIPE_SHADER_VERTEX],
PIPE_BUFFER_USAGE_CPU_READ);
assert(map);
draw_set_mapped_constant_buffer(
draw,
map,
svga->curr.cb[PIPE_SHADER_VERTEX]->size);
}
draw_arrays(svga->swtnl.draw, prim, start, count);
draw_flush(svga->swtnl.draw);
/* Ensure the draw module didn't touch this */
assert(i == svga->curr.num_vertex_buffers);
/*
* unmap vertex/index buffers
*/
for (i = 0; i < svga->curr.num_vertex_buffers; i++) {
pipe_buffer_unmap(svga->pipe.screen, svga->curr.vb[i].buffer);
draw_set_mapped_vertex_buffer(draw, i, NULL);
}
if (indexBuffer) {
pipe_buffer_unmap(svga->pipe.screen, indexBuffer);
draw_set_mapped_element_buffer(draw, 0, NULL);
}
if (svga->curr.cb[PIPE_SHADER_VERTEX]) {
pipe_buffer_unmap(svga->pipe.screen,
svga->curr.cb[PIPE_SHADER_VERTEX]);
}
return ret;
}
boolean svga_init_swtnl( struct svga_context *svga )
{
svga->swtnl.backend = svga_vbuf_render_create(svga);
if(!svga->swtnl.backend)
goto fail;
/*
* Create drawing context and plug our rendering stage into it.
*/
svga->swtnl.draw = draw_create();
if (svga->swtnl.draw == NULL)
goto fail;
draw_set_rasterize_stage(svga->swtnl.draw,
draw_vbuf_stage( svga->swtnl.draw, svga->swtnl.backend ));
draw_set_render(svga->swtnl.draw, svga->swtnl.backend);
draw_install_aaline_stage(svga->swtnl.draw, &svga->pipe);
draw_install_aapoint_stage(svga->swtnl.draw, &svga->pipe);
draw_install_pstipple_stage(svga->swtnl.draw, &svga->pipe);
draw_set_driver_clipping(svga->swtnl.draw, debug_get_bool_option("SVGA_SWTNL_FSE", FALSE));
return TRUE;
fail:
if (svga->swtnl.backend)
svga->swtnl.backend->destroy( svga->swtnl.backend );
if (svga->swtnl.draw)
draw_destroy( svga->swtnl.draw );
return FALSE;
}
void svga_destroy_swtnl( struct svga_context *svga )
{
draw_destroy( svga->swtnl.draw );
}

View file

@ -0,0 +1,93 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_SWTNL_PRIVATE_H
#define SVGA_SWTNL_PRIVATE_H
#include "svga_swtnl.h"
#include "draw/draw_vertex.h"
#include "svga_types.h"
#include "svga3d_reg.h"
/**
* Primitive renderer for svga.
*/
struct svga_vbuf_render {
struct vbuf_render base;
struct svga_context *svga;
struct vertex_info vertex_info;
unsigned vertex_size;
unsigned prim;
struct pipe_buffer *vbuf;
struct pipe_buffer *ibuf;
/* current size of buffer */
size_t vbuf_size;
size_t ibuf_size;
/* size of that the buffer should be */
size_t vbuf_alloc_size;
size_t ibuf_alloc_size;
/* current write place */
size_t vbuf_offset;
size_t ibuf_offset;
/* currently used */
size_t vbuf_used;
SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS];
unsigned vdecl_offset;
unsigned vdecl_count;
ushort min_index;
ushort max_index;
};
/**
* Basically a cast wrapper.
*/
static INLINE struct svga_vbuf_render *
svga_vbuf_render( struct vbuf_render *render )
{
assert(render);
return (struct svga_vbuf_render *)render;
}
struct vbuf_render *
svga_vbuf_render_create( struct svga_context *svga );
int
svga_swtnl_update_vdecl( struct svga_context *svga );
#endif

View file

@ -0,0 +1,242 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "pipe/p_inlines.h"
#include "pipe/p_state.h"
#include "util/u_memory.h"
#include "svga_context.h"
#include "svga_swtnl.h"
#include "svga_state.h"
#include "svga_swtnl_private.h"
#define SVGA_POINT_ADJ_X -0.375
#define SVGA_POINT_ADJ_Y -0.5
#define SVGA_LINE_ADJ_X -0.5
#define SVGA_LINE_ADJ_Y -0.5
#define SVGA_TRIANGLE_ADJ_X -0.375
#define SVGA_TRIANGLE_ADJ_Y -0.5
static void set_draw_viewport( struct svga_context *svga )
{
struct pipe_viewport_state vp = svga->curr.viewport;
float adjx = 0;
float adjy = 0;
switch (svga->curr.reduced_prim) {
case PIPE_PRIM_POINTS:
adjx = SVGA_POINT_ADJ_X;
adjy = SVGA_POINT_ADJ_Y;
break;
case PIPE_PRIM_LINES:
/* XXX: This is to compensate for the fact that wide lines are
* going to be drawn with triangles, but we're not catching all
* cases where that will happen.
*/
if (svga->curr.rast->templ.line_width > 1.0)
{
adjx = SVGA_LINE_ADJ_X + 0.175;
adjy = SVGA_LINE_ADJ_Y - 0.175;
}
else {
adjx = SVGA_LINE_ADJ_X;
adjy = SVGA_LINE_ADJ_Y;
}
break;
case PIPE_PRIM_TRIANGLES:
adjx += SVGA_TRIANGLE_ADJ_X;
adjy += SVGA_TRIANGLE_ADJ_Y;
break;
}
vp.translate[0] += adjx;
vp.translate[1] += adjy;
draw_set_viewport_state(svga->swtnl.draw, &vp);
}
static int update_swtnl_draw( struct svga_context *svga,
unsigned dirty )
{
draw_flush( svga->swtnl.draw );
if (dirty & SVGA_NEW_VS)
draw_bind_vertex_shader(svga->swtnl.draw,
svga->curr.vs->draw_shader);
if (dirty & SVGA_NEW_VBUFFER)
draw_set_vertex_buffers(svga->swtnl.draw,
svga->curr.num_vertex_buffers,
svga->curr.vb);
if (dirty & SVGA_NEW_VELEMENT)
draw_set_vertex_elements(svga->swtnl.draw,
svga->curr.num_vertex_elements,
svga->curr.ve );
if (dirty & SVGA_NEW_CLIP)
draw_set_clip_state(svga->swtnl.draw,
&svga->curr.clip);
if (dirty & (SVGA_NEW_VIEWPORT |
SVGA_NEW_REDUCED_PRIMITIVE |
SVGA_NEW_RAST))
set_draw_viewport( svga );
if (dirty & SVGA_NEW_RAST)
draw_set_rasterizer_state(svga->swtnl.draw,
&svga->curr.rast->templ);
if (dirty & SVGA_NEW_FRAME_BUFFER)
draw_set_mrd(svga->swtnl.draw,
svga->curr.depthscale);
if (dirty & SVGA_NEW_EDGEFLAGS)
draw_set_edgeflags( svga->swtnl.draw,
svga->curr.edgeflags );
return 0;
}
struct svga_tracked_state svga_update_swtnl_draw =
{
"update draw module state",
(SVGA_NEW_VS |
SVGA_NEW_VBUFFER |
SVGA_NEW_VELEMENT |
SVGA_NEW_CLIP |
SVGA_NEW_VIEWPORT |
SVGA_NEW_RAST |
SVGA_NEW_FRAME_BUFFER |
SVGA_NEW_REDUCED_PRIMITIVE |
SVGA_NEW_EDGEFLAGS),
update_swtnl_draw
};
int svga_swtnl_update_vdecl( struct svga_context *svga )
{
struct svga_vbuf_render *svga_render = svga_vbuf_render(svga->swtnl.backend);
struct draw_context *draw = svga->swtnl.draw;
struct vertex_info *vinfo = &svga_render->vertex_info;
SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS];
const enum interp_mode colorInterp =
svga->curr.rast->templ.flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
const struct svga_fragment_shader *fs = svga->curr.fs;
int offset = 0;
int nr_decls = 0;
int src, i;
memset(vinfo, 0, sizeof(*vinfo));
memset(vdecl, 0, sizeof(vdecl));
/* always add position */
src = draw_find_vs_output(draw, TGSI_SEMANTIC_POSITION, 0);
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src);
vinfo->attrib[0].emit = EMIT_4F;
vdecl[0].array.offset = offset;
vdecl[0].identity.type = SVGA3D_DECLTYPE_FLOAT4;
vdecl[0].identity.usage = SVGA3D_DECLUSAGE_POSITIONT;
vdecl[0].identity.usageIndex = 0;
offset += 16;
nr_decls++;
for (i = 0; i < fs->base.info.num_inputs; i++) {
unsigned name = fs->base.info.input_semantic_name[i];
unsigned index = fs->base.info.input_semantic_index[i];
src = draw_find_vs_output(draw, name, index);
vdecl[nr_decls].array.offset = offset;
vdecl[nr_decls].identity.usageIndex = fs->base.info.input_semantic_index[i];
switch (name) {
case TGSI_SEMANTIC_COLOR:
draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_COLOR;
vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4;
offset += 16;
nr_decls++;
break;
case TGSI_SEMANTIC_GENERIC:
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD;
vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4;
vdecl[nr_decls].identity.usageIndex += 1;
offset += 16;
nr_decls++;
break;
case TGSI_SEMANTIC_FOG:
draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD;
vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT1;
assert(vdecl[nr_decls].identity.usageIndex == 0);
offset += 4;
nr_decls++;
break;
case TGSI_SEMANTIC_POSITION:
/* generated internally, not a vertex shader output */
break;
default:
assert(0);
}
}
draw_compute_vertex_size(vinfo);
svga_render->vdecl_count = nr_decls;
for (i = 0; i < svga_render->vdecl_count; i++)
vdecl[i].array.stride = offset;
if (memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)) == 0)
return 0;
memcpy(svga_render->vdecl, vdecl, sizeof(vdecl));
svga->swtnl.new_vdecl = TRUE;
return 0;
}
static int update_swtnl_vdecl( struct svga_context *svga,
unsigned dirty )
{
return svga_swtnl_update_vdecl( svga );
}
struct svga_tracked_state svga_update_swtnl_vdecl =
{
"update draw module vdecl",
(SVGA_NEW_VS |
SVGA_NEW_FS),
update_swtnl_vdecl
};

View file

@ -0,0 +1,266 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_defines.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
#include "util/u_memory.h"
#include "svgadump/st_shader_dump.h"
#include "svga_context.h"
#include "svga_tgsi.h"
#include "svga_tgsi_emit.h"
#include "svga_debug.h"
#include "svga_hw_reg.h"
#include "svga3d_shaderdefs.h"
/* Sinkhole used only in error conditions.
*/
static char err_buf[128];
#if 0
static void svga_destroy_shader_emitter( struct svga_shader_emitter *emit )
{
if (emit->buf != err_buf)
FREE(emit->buf);
}
#endif
static boolean svga_shader_expand( struct svga_shader_emitter *emit )
{
char *new_buf;
unsigned newsize = emit->size * 2;
if(emit->buf != err_buf)
new_buf = REALLOC(emit->buf, emit->size, newsize);
else
new_buf = NULL;
if (new_buf == NULL) {
emit->ptr = err_buf;
emit->buf = err_buf;
emit->size = sizeof(err_buf);
return FALSE;
}
emit->size = newsize;
emit->ptr = new_buf + (emit->ptr - emit->buf);
emit->buf = new_buf;
return TRUE;
}
static INLINE boolean reserve( struct svga_shader_emitter *emit,
unsigned nr_dwords )
{
if (emit->ptr - emit->buf + nr_dwords * sizeof(unsigned) >= emit->size) {
if (!svga_shader_expand( emit ))
return FALSE;
}
return TRUE;
}
boolean svga_shader_emit_dword( struct svga_shader_emitter *emit,
unsigned dword )
{
if (!reserve(emit, 1))
return FALSE;
*(unsigned *)emit->ptr = dword;
emit->ptr += sizeof dword;
return TRUE;
}
boolean svga_shader_emit_dwords( struct svga_shader_emitter *emit,
const unsigned *dwords,
unsigned nr )
{
if (!reserve(emit, nr))
return FALSE;
memcpy( emit->ptr, dwords, nr * sizeof *dwords );
emit->ptr += nr * sizeof *dwords;
return TRUE;
}
boolean svga_shader_emit_opcode( struct svga_shader_emitter *emit,
unsigned opcode )
{
SVGA3dShaderInstToken *here;
if (!reserve(emit, 1))
return FALSE;
here = (SVGA3dShaderInstToken *)emit->ptr;
here->value = opcode;
if (emit->insn_offset) {
SVGA3dShaderInstToken *prev = (SVGA3dShaderInstToken *)(emit->buf +
emit->insn_offset);
prev->size = (here - prev) - 1;
}
emit->insn_offset = emit->ptr - emit->buf;
emit->ptr += sizeof(unsigned);
return TRUE;
}
#define SVGA3D_PS_2X (SVGA3D_PS_20 | 1)
#define SVGA3D_VS_2X (SVGA3D_VS_20 | 1)
static boolean svga_shader_emit_header( struct svga_shader_emitter *emit )
{
SVGA3dShaderVersion header;
memset( &header, 0, sizeof header );
switch (emit->unit) {
case PIPE_SHADER_FRAGMENT:
header.value = emit->use_sm30 ? SVGA3D_PS_30 : SVGA3D_PS_2X;
break;
case PIPE_SHADER_VERTEX:
header.value = emit->use_sm30 ? SVGA3D_VS_30 : SVGA3D_VS_2X;
break;
}
return svga_shader_emit_dword( emit, header.value );
}
/* Parse TGSI shader and translate to SVGA/DX9 serialized
* representation.
*
* In this function SVGA shader is emitted to an in-memory buffer that
* can be dynamically grown. Once we've finished and know how large
* it is, it will be copied to a hardware buffer for upload.
*/
static struct svga_shader_result *
svga_tgsi_translate( const struct svga_shader *shader,
union svga_compile_key key,
unsigned unit )
{
struct svga_shader_result *result = NULL;
struct svga_shader_emitter emit;
int ret = 0;
memset(&emit, 0, sizeof(emit));
emit.use_sm30 = shader->use_sm30;
emit.size = 1024;
emit.buf = MALLOC(emit.size);
if (emit.buf == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
}
emit.ptr = emit.buf;
emit.unit = unit;
emit.key = key;
tgsi_scan_shader( shader->tokens, &emit.info);
emit.imm_start = emit.info.file_max[TGSI_FILE_CONSTANT] + 1;
if (unit == PIPE_SHADER_FRAGMENT)
emit.imm_start += key.fkey.num_unnormalized_coords;
if (unit == PIPE_SHADER_VERTEX) {
emit.imm_start += key.vkey.need_prescale ? 2 : 0;
emit.imm_start += key.vkey.num_zero_stride_vertex_elements;
}
emit.nr_hw_const = (emit.imm_start + emit.info.file_max[TGSI_FILE_IMMEDIATE] + 1);
emit.nr_hw_temp = emit.info.file_max[TGSI_FILE_TEMPORARY] + 1;
emit.in_main_func = TRUE;
if (!svga_shader_emit_header( &emit ))
goto fail;
if (!svga_shader_emit_instructions( &emit, shader->tokens ))
goto fail;
result = CALLOC_STRUCT(svga_shader_result);
if (result == NULL)
goto fail;
result->shader = shader;
result->tokens = (const unsigned *)emit.buf;
result->nr_tokens = (emit.ptr - emit.buf) / sizeof(unsigned);
memcpy(&result->key, &key, sizeof key);
return result;
fail:
FREE(result);
FREE(emit.buf);
return NULL;
}
struct svga_shader_result *
svga_translate_fragment_program( const struct svga_fragment_shader *fs,
const struct svga_fs_compile_key *fkey )
{
union svga_compile_key key;
memcpy(&key.fkey, fkey, sizeof *fkey);
return svga_tgsi_translate( &fs->base,
key,
PIPE_SHADER_FRAGMENT );
}
struct svga_shader_result *
svga_translate_vertex_program( const struct svga_vertex_shader *vs,
const struct svga_vs_compile_key *vkey )
{
union svga_compile_key key;
memcpy(&key.vkey, vkey, sizeof *vkey);
return svga_tgsi_translate( &vs->base,
key,
PIPE_SHADER_VERTEX );
}
void svga_destroy_shader_result( struct svga_shader_result *result )
{
FREE((unsigned *)result->tokens);
FREE(result);
}

View file

@ -0,0 +1,139 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_TGSI_H
#define SVGA_TGSI_H
#include "pipe/p_state.h"
#include "svga_hw_reg.h"
struct svga_fragment_shader;
struct svga_vertex_shader;
struct svga_shader;
struct tgsi_shader_info;
struct tgsi_token;
struct svga_vs_compile_key
{
ubyte need_prescale:1;
ubyte allow_psiz:1;
unsigned zero_stride_vertex_elements;
ubyte num_zero_stride_vertex_elements:6;
};
struct svga_fs_compile_key
{
boolean light_twoside:1;
boolean front_cw:1;
ubyte num_textures;
ubyte num_unnormalized_coords;
struct {
ubyte compare_mode : 1;
ubyte compare_func : 3;
ubyte unnormalized : 1;
ubyte width_height_idx : 7;
ubyte texture_target;
} tex[PIPE_MAX_SAMPLERS];
};
union svga_compile_key {
struct svga_vs_compile_key vkey;
struct svga_fs_compile_key fkey;
};
struct svga_shader_result
{
const struct svga_shader *shader;
/* Parameters used to generate this compilation result:
*/
union svga_compile_key key;
/* Compiled shader tokens:
*/
const unsigned *tokens;
unsigned nr_tokens;
/* SVGA Shader ID:
*/
unsigned id;
/* Next compilation result:
*/
struct svga_shader_result *next;
};
/* TGSI doesn't provide use with VS input semantics (they're actually
* pretty meaningless), so we just generate some plausible ones here.
* This is called both from within the TGSI translator and when
* building vdecls to ensure they match up.
*
* The real use of this information is matching vertex elements to
* fragment shader inputs in the case where vertex shader is disabled.
*/
static INLINE void svga_generate_vdecl_semantics( unsigned idx,
unsigned *usage,
unsigned *usage_index )
{
if (idx == 0) {
*usage = SVGA3D_DECLUSAGE_POSITION;
*usage_index = 0;
}
else {
*usage = SVGA3D_DECLUSAGE_TEXCOORD;
*usage_index = idx - 1;
}
}
static INLINE unsigned svga_vs_key_size( const struct svga_vs_compile_key *key )
{
return sizeof *key;
}
static INLINE unsigned svga_fs_key_size( const struct svga_fs_compile_key *key )
{
return (const char *)&key->tex[key->num_textures].texture_target -
(const char *)key;
}
struct svga_shader_result *
svga_translate_fragment_program( const struct svga_fragment_shader *fs,
const struct svga_fs_compile_key *fkey );
struct svga_shader_result *
svga_translate_vertex_program( const struct svga_vertex_shader *fs,
const struct svga_vs_compile_key *vkey );
void svga_destroy_shader_result( struct svga_shader_result *result );
#endif

View file

@ -0,0 +1,280 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_memory.h"
#include "svga_tgsi_emit.h"
#include "svga_context.h"
static boolean ps20_input( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
struct src_register reg;
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
switch (semantic.SemanticName) {
case TGSI_SEMANTIC_POSITION:
/* Special case:
*/
reg = src_register( SVGA3DREG_MISCTYPE,
SVGA3DMISCREG_POSITION );
break;
case TGSI_SEMANTIC_COLOR:
reg = src_register( SVGA3DREG_INPUT,
semantic.SemanticIndex );
break;
case TGSI_SEMANTIC_FOG:
assert(semantic.SemanticIndex == 0);
reg = src_register( SVGA3DREG_TEXTURE, 0 );
break;
case TGSI_SEMANTIC_GENERIC:
reg = src_register( SVGA3DREG_TEXTURE,
semantic.SemanticIndex + 1 );
break;
default:
assert(0);
return TRUE;
}
emit->input_map[idx] = reg;
dcl.dst = dst( reg );
dcl.usage = 0;
dcl.index = 0;
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
static boolean ps20_output( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3dShaderDestToken reg;
switch (semantic.SemanticName) {
case TGSI_SEMANTIC_COLOR:
if (semantic.SemanticIndex < PIPE_MAX_COLOR_BUFS) {
unsigned cbuf = semantic.SemanticIndex;
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_col[cbuf] = emit->output_map[idx];
emit->true_col[cbuf] = dst_register( SVGA3DREG_COLOROUT,
semantic.SemanticIndex );
}
else {
assert(0);
reg = dst_register( SVGA3DREG_COLOROUT, 0 );
}
break;
case TGSI_SEMANTIC_POSITION:
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_pos = emit->output_map[idx];
emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT,
semantic.SemanticIndex );
break;
default:
assert(0);
reg = dst_register( SVGA3DREG_COLOROUT, 0 );
break;
}
return TRUE;
}
static boolean vs20_input( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx );
dcl.dst = dst_register( SVGA3DREG_INPUT, idx );
assert(dcl.dst.reserved0);
/* Mesa doesn't provide use with VS input semantics (they're
* actually pretty meaningless), so we just generate some plausible
* ones here. This has to match what we declare in the vdecl code
* in svga_pipe_vertex.c.
*/
if (idx == 0) {
dcl.usage = SVGA3D_DECLUSAGE_POSITION;
dcl.index = 0;
}
else {
dcl.usage = SVGA3D_DECLUSAGE_TEXCOORD;
dcl.index = idx - 1;
}
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
static boolean vs20_output( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
/* Don't emit dcl instruction for vs20 inputs
*/
/* Just build the register map table:
*/
switch (semantic.SemanticName) {
case TGSI_SEMANTIC_POSITION:
assert(semantic.SemanticIndex == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_pos = emit->output_map[idx];
emit->true_pos = dst_register( SVGA3DREG_RASTOUT,
SVGA3DRASTOUT_POSITION);
break;
case TGSI_SEMANTIC_PSIZE:
assert(semantic.SemanticIndex == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_psiz = emit->output_map[idx];
emit->true_psiz = dst_register( SVGA3DREG_RASTOUT,
SVGA3DRASTOUT_PSIZE );
break;
case TGSI_SEMANTIC_FOG:
assert(semantic.SemanticIndex == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT, 0 );
break;
case TGSI_SEMANTIC_COLOR:
/* oD0 */
emit->output_map[idx] = dst_register( SVGA3DREG_ATTROUT,
semantic.SemanticIndex );
break;
case TGSI_SEMANTIC_GENERIC:
emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT,
semantic.SemanticIndex + 1 );
break;
default:
assert(0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, 0 );
return FALSE;
}
return TRUE;
}
static boolean ps20_sampler( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx );
dcl.type = svga_tgsi_sampler_type( emit, idx );
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
boolean svga_translate_decl_sm20( struct svga_shader_emitter *emit,
const struct tgsi_full_declaration *decl )
{
unsigned first = decl->DeclarationRange.First;
unsigned last = decl->DeclarationRange.Last;
unsigned semantic = 0;
unsigned semantic_idx = 0;
unsigned idx;
if (decl->Declaration.Semantic) {
semantic = decl->Semantic.SemanticName;
semantic_idx = decl->Semantic.SemanticIndex;
}
for( idx = first; idx <= last; idx++ ) {
boolean ok;
switch (decl->Declaration.File) {
case TGSI_FILE_SAMPLER:
assert (emit->unit == PIPE_SHADER_FRAGMENT);
ok = ps20_sampler( emit, decl->Semantic, idx );
break;
case TGSI_FILE_INPUT:
if (emit->unit == PIPE_SHADER_VERTEX)
ok = vs20_input( emit, decl->Semantic, idx );
else
ok = ps20_input( emit, decl->Semantic, idx );
break;
case TGSI_FILE_OUTPUT:
if (emit->unit == PIPE_SHADER_VERTEX)
ok = vs20_output( emit, decl->Semantic, idx );
else
ok = ps20_output( emit, decl->Semantic, idx );
break;
default:
/* don't need to declare other vars */
ok = TRUE;
}
if (!ok)
return FALSE;
}
return TRUE;
}

View file

@ -0,0 +1,385 @@
/**********************************************************
* 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.
*
**********************************************************/
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_memory.h"
#include "svga_tgsi_emit.h"
#include "svga_context.h"
static boolean translate_vs_ps_semantic( struct tgsi_declaration_semantic semantic,
unsigned *usage,
unsigned *idx )
{
switch (semantic.SemanticName) {
case TGSI_SEMANTIC_POSITION:
*idx = semantic.SemanticIndex;
*usage = SVGA3D_DECLUSAGE_POSITION;
break;
case TGSI_SEMANTIC_COLOR:
*idx = semantic.SemanticIndex;
*usage = SVGA3D_DECLUSAGE_COLOR;
break;
case TGSI_SEMANTIC_BCOLOR:
*idx = semantic.SemanticIndex + 2; /* sharing with COLOR */
*usage = SVGA3D_DECLUSAGE_COLOR;
break;
case TGSI_SEMANTIC_FOG:
*idx = 0;
assert(semantic.SemanticIndex == 0);
*usage = SVGA3D_DECLUSAGE_TEXCOORD;
break;
case TGSI_SEMANTIC_PSIZE:
*idx = semantic.SemanticIndex;
*usage = SVGA3D_DECLUSAGE_PSIZE;
break;
case TGSI_SEMANTIC_GENERIC:
*idx = semantic.SemanticIndex + 1; /* texcoord[0] is reserved for fog */
*usage = SVGA3D_DECLUSAGE_TEXCOORD;
break;
case TGSI_SEMANTIC_NORMAL:
*idx = semantic.SemanticIndex;
*usage = SVGA3D_DECLUSAGE_NORMAL;
break;
default:
assert(0);
*usage = SVGA3D_DECLUSAGE_TEXCOORD;
*idx = 0;
return FALSE;
}
return TRUE;
}
static boolean emit_decl( struct svga_shader_emitter *emit,
SVGA3dShaderDestToken reg,
unsigned usage,
unsigned index )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
dcl.dst = reg;
dcl.usage = usage;
dcl.index = index;
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
static boolean emit_vface_decl( struct svga_shader_emitter *emit )
{
if (!emit->emitted_vface) {
SVGA3dShaderDestToken reg =
dst_register( SVGA3DREG_MISCTYPE,
SVGA3DMISCREG_FACE );
if (!emit_decl( emit, reg, 0, 0 ))
return FALSE;
emit->emitted_vface = TRUE;
}
return TRUE;
}
static boolean ps30_input( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
unsigned usage, index;
SVGA3dShaderDestToken reg;
if (semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
emit->input_map[idx] = src_register( SVGA3DREG_MISCTYPE,
SVGA3DMISCREG_POSITION );
emit->input_map[idx].base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X,
TGSI_SWIZZLE_Y,
TGSI_SWIZZLE_Y,
TGSI_SWIZZLE_Y );
reg = writemask( dst(emit->input_map[idx]),
TGSI_WRITEMASK_XY );
return emit_decl( emit, reg, 0, 0 );
}
else if (emit->key.fkey.light_twoside &&
(semantic.SemanticName == TGSI_SEMANTIC_COLOR)) {
if (!translate_vs_ps_semantic( semantic, &usage, &index ))
return FALSE;
emit->internal_color_idx[emit->internal_color_count] = idx;
emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count );
emit->ps30_input_count++;
emit->internal_color_count++;
reg = dst( emit->input_map[idx] );
if (!emit_decl( emit, reg, usage, index ))
return FALSE;
semantic.SemanticName = TGSI_SEMANTIC_BCOLOR;
if (!translate_vs_ps_semantic( semantic, &usage, &index ))
return FALSE;
reg = dst_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
if (!emit_decl( emit, reg, usage, index ))
return FALSE;
if (!emit_vface_decl( emit ))
return FALSE;
return TRUE;
}
else if (semantic.SemanticName == TGSI_SEMANTIC_FACE) {
if (!emit_vface_decl( emit ))
return FALSE;
emit->emit_frontface = TRUE;
emit->internal_frontface_idx = idx;
return TRUE;
}
else {
if (!translate_vs_ps_semantic( semantic, &usage, &index ))
return FALSE;
emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
reg = dst( emit->input_map[idx] );
return emit_decl( emit, reg, usage, index );
}
}
/* PS output registers are the same as 2.0
*/
static boolean ps30_output( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3dShaderDestToken reg;
switch (semantic.SemanticName) {
case TGSI_SEMANTIC_COLOR:
emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT,
semantic.SemanticIndex );
break;
case TGSI_SEMANTIC_POSITION:
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_pos = emit->output_map[idx];
emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT,
semantic.SemanticIndex );
break;
default:
assert(0);
reg = dst_register( SVGA3DREG_COLOROUT, 0 );
break;
}
return TRUE;
}
/* We still make up the input semantics the same as in 2.0
*/
static boolean vs30_input( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
unsigned usage, index;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
if (emit->key.vkey.zero_stride_vertex_elements & (1 << idx)) {
unsigned i;
unsigned offset = 0;
unsigned start_idx = emit->info.file_max[TGSI_FILE_CONSTANT] + 1;
/* adjust for prescale constants */
start_idx += emit->key.vkey.need_prescale ? 2 : 0;
/* compute the offset from the start of zero stride constants */
for (i = 0; i < PIPE_MAX_ATTRIBS && i < idx; ++i) {
if (emit->key.vkey.zero_stride_vertex_elements & (1<<i))
++offset;
}
emit->input_map[idx] = src_register( SVGA3DREG_CONST,
start_idx + offset );
} else {
emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx );
dcl.dst = dst_register( SVGA3DREG_INPUT, idx );
assert(dcl.dst.reserved0);
svga_generate_vdecl_semantics( idx, &usage, &index );
dcl.usage = usage;
dcl.index = index;
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
return TRUE;
}
/* VS3.0 outputs have proper declarations and semantic info for
* matching against PS inputs.
*/
static boolean vs30_output( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
unsigned usage, index;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
if (!translate_vs_ps_semantic( semantic, &usage, &index ))
return FALSE;
dcl.dst = dst_register( SVGA3DREG_OUTPUT, idx );
dcl.usage = usage;
dcl.index = index;
dcl.values[0] |= 1<<31;
if (semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
assert(idx == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_pos = emit->output_map[idx];
emit->true_pos = dcl.dst;
}
else if (semantic.SemanticName == TGSI_SEMANTIC_PSIZE) {
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_psiz = emit->output_map[idx];
/* This has the effect of not declaring psiz (below) and not
* emitting the final MOV to true_psiz in the postamble.
*/
if (!emit->key.vkey.allow_psiz)
return TRUE;
emit->true_psiz = dcl.dst;
}
else {
emit->output_map[idx] = dcl.dst;
}
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
static boolean ps30_sampler( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx );
dcl.type = svga_tgsi_sampler_type( emit, idx );
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
boolean svga_translate_decl_sm30( struct svga_shader_emitter *emit,
const struct tgsi_full_declaration *decl )
{
unsigned first = decl->DeclarationRange.First;
unsigned last = decl->DeclarationRange.Last;
unsigned semantic = 0;
unsigned semantic_idx = 0;
unsigned idx;
if (decl->Declaration.Semantic) {
semantic = decl->Semantic.SemanticName;
semantic_idx = decl->Semantic.SemanticIndex;
}
for( idx = first; idx <= last; idx++ ) {
boolean ok;
switch (decl->Declaration.File) {
case TGSI_FILE_SAMPLER:
assert (emit->unit == PIPE_SHADER_FRAGMENT);
ok = ps30_sampler( emit, decl->Semantic, idx );
break;
case TGSI_FILE_INPUT:
if (emit->unit == PIPE_SHADER_VERTEX)
ok = vs30_input( emit, decl->Semantic, idx );
else
ok = ps30_input( emit, decl->Semantic, idx );
break;
case TGSI_FILE_OUTPUT:
if (emit->unit == PIPE_SHADER_VERTEX)
ok = vs30_output( emit, decl->Semantic, idx );
else
ok = ps30_output( emit, decl->Semantic, idx );
break;
default:
/* don't need to declare other vars */
ok = TRUE;
}
if (!ok)
return FALSE;
}
return TRUE;
}

View file

@ -0,0 +1,345 @@
/**********************************************************
* 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.
*
**********************************************************/
#ifndef SVGA_TGSI_EMIT_H
#define SVGA_TGSI_EMIT_H
#include "tgsi/tgsi_scan.h"
#include "svga_hw_reg.h"
#include "svga_tgsi.h"
#include "svga3d_shaderdefs.h"
struct src_register
{
SVGA3dShaderSrcToken base;
SVGA3dShaderSrcToken indirect;
};
struct svga_arl_consts {
int number;
int idx;
int swizzle;
int arl_num;
};
/* Internal functions:
*/
struct svga_shader_emitter
{
boolean use_sm30;
unsigned size;
char *buf;
char *ptr;
union svga_compile_key key;
struct tgsi_shader_info info;
int unit;
int imm_start;
int nr_hw_const;
int nr_hw_temp;
int insn_offset;
int internal_temp_count;
int internal_imm_count;
int internal_color_idx[2]; /* diffuse, specular */
int internal_color_count;
boolean emitted_vface;
boolean emit_frontface;
int internal_frontface_idx;
int ps30_input_count;
boolean in_main_func;
boolean created_zero_immediate;
int zero_immediate_idx;
boolean created_loop_const;
int loop_const_idx;
boolean created_sincos_consts;
int sincos_consts_idx;
unsigned label[32];
unsigned nr_labels;
struct src_register input_map[PIPE_MAX_ATTRIBS];
SVGA3dShaderDestToken output_map[PIPE_MAX_ATTRIBS];
struct src_register imm_0055;
SVGA3dShaderDestToken temp_pos;
SVGA3dShaderDestToken true_pos;
SVGA3dShaderDestToken temp_col[PIPE_MAX_COLOR_BUFS];
SVGA3dShaderDestToken true_col[PIPE_MAX_COLOR_BUFS];
SVGA3dShaderDestToken temp_psiz;
SVGA3dShaderDestToken true_psiz;
struct svga_arl_consts arl_consts[12];
int num_arl_consts;
int current_arl;
};
boolean svga_shader_emit_dword( struct svga_shader_emitter *emit,
unsigned dword );
boolean svga_shader_emit_dwords( struct svga_shader_emitter *emit,
const unsigned *dwords,
unsigned nr );
boolean svga_shader_emit_opcode( struct svga_shader_emitter *emit,
unsigned opcode );
boolean svga_shader_emit_instructions( struct svga_shader_emitter *emit,
const struct tgsi_token *tokens );
boolean svga_translate_decl_sm20( struct svga_shader_emitter *emit,
const struct tgsi_full_declaration *decl );
boolean svga_translate_decl_sm30( struct svga_shader_emitter *emit,
const struct tgsi_full_declaration *decl );
static INLINE boolean emit_dst( struct svga_shader_emitter *emit,
SVGA3dShaderDestToken dest )
{
assert(dest.reserved0);
return svga_shader_emit_dword( emit, dest.value );
}
static INLINE boolean emit_src( struct svga_shader_emitter *emit,
const struct src_register src )
{
if (src.base.relAddr) {
assert(src.base.reserved0);
assert(src.indirect.reserved0);
return (svga_shader_emit_dword( emit, src.base.value ) &&
svga_shader_emit_dword( emit, src.indirect.value ));
}
else {
assert(src.base.reserved0);
return svga_shader_emit_dword( emit, src.base.value );
}
}
static INLINE boolean emit_instruction( struct svga_shader_emitter *emit,
SVGA3dShaderInstToken opcode )
{
return svga_shader_emit_opcode( emit, opcode.value );
}
static INLINE boolean emit_op1( struct svga_shader_emitter *emit,
SVGA3dShaderInstToken inst,
SVGA3dShaderDestToken dest,
struct src_register src0 )
{
return (emit_instruction( emit, inst ) &&
emit_dst( emit, dest ) &&
emit_src( emit, src0 ));
}
static INLINE boolean emit_op2( struct svga_shader_emitter *emit,
SVGA3dShaderInstToken inst,
SVGA3dShaderDestToken dest,
struct src_register src0,
struct src_register src1 )
{
return (emit_instruction( emit, inst ) &&
emit_dst( emit, dest ) &&
emit_src( emit, src0 ) &&
emit_src( emit, src1 ));
}
static INLINE boolean emit_op3( struct svga_shader_emitter *emit,
SVGA3dShaderInstToken inst,
SVGA3dShaderDestToken dest,
struct src_register src0,
struct src_register src1,
struct src_register src2 )
{
return (emit_instruction( emit, inst ) &&
emit_dst( emit, dest ) &&
emit_src( emit, src0 ) &&
emit_src( emit, src1 ) &&
emit_src( emit, src2 ));
}
#define TRANSLATE_SWIZZLE(x,y,z,w) ((x) | ((y) << 2) | ((z) << 4) | ((w) << 6))
#define SWIZZLE_XYZW \
TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_W)
#define SWIZZLE_XXXX \
TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_X,TGSI_SWIZZLE_X,TGSI_SWIZZLE_X)
#define SWIZZLE_YYYY \
TRANSLATE_SWIZZLE(TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y)
#define SWIZZLE_ZZZZ \
TRANSLATE_SWIZZLE(TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z)
#define SWIZZLE_WWWW \
TRANSLATE_SWIZZLE(TGSI_SWIZZLE_W,TGSI_SWIZZLE_W,TGSI_SWIZZLE_W,TGSI_SWIZZLE_W)
static INLINE SVGA3dShaderInstToken
inst_token( unsigned opcode )
{
SVGA3dShaderInstToken inst;
inst.value = 0;
inst.op = opcode;
return inst;
}
static INLINE SVGA3dShaderDestToken
dst_register( unsigned file,
int number )
{
SVGA3dShaderDestToken dest;
dest.value = 0;
dest.num = number;
dest.type_upper = file >> 3;
dest.relAddr = 0;
dest.reserved1 = 0;
dest.mask = 0xf;
dest.dstMod = 0;
dest.shfScale = 0;
dest.type_lower = file & 0x7;
dest.reserved0 = 1; /* is_reg */
return dest;
}
static INLINE SVGA3dShaderDestToken
writemask( SVGA3dShaderDestToken dest,
unsigned mask )
{
dest.mask &= mask;
return dest;
}
static INLINE SVGA3dShaderSrcToken
src_token( unsigned file, int number )
{
SVGA3dShaderSrcToken src;
src.value = 0;
src.num = number;
src.type_upper = file >> 3;
src.relAddr = 0;
src.reserved1 = 0;
src.swizzle = SWIZZLE_XYZW;
src.srcMod = 0;
src.type_lower = file & 0x7;
src.reserved0 = 1; /* is_reg */
return src;
}
static INLINE struct src_register
absolute( struct src_register src )
{
src.base.srcMod = SVGA3DSRCMOD_ABS;
return src;
}
static INLINE struct src_register
negate( struct src_register src )
{
switch (src.base.srcMod) {
case SVGA3DSRCMOD_ABS:
src.base.srcMod = SVGA3DSRCMOD_ABSNEG;
break;
case SVGA3DSRCMOD_ABSNEG:
src.base.srcMod = SVGA3DSRCMOD_ABS;
break;
case SVGA3DSRCMOD_NEG:
src.base.srcMod = SVGA3DSRCMOD_NONE;
break;
case SVGA3DSRCMOD_NONE:
src.base.srcMod = SVGA3DSRCMOD_NEG;
break;
}
return src;
}
static INLINE struct src_register
src_register( unsigned file, int number )
{
struct src_register src;
src.base = src_token( file, number );
src.indirect.value = 0;
return src;
}
static INLINE SVGA3dShaderDestToken dst( struct src_register src )
{
return dst_register( SVGA3dShaderGetRegType( src.base.value ),
src.base.num );
}
static INLINE struct src_register src( SVGA3dShaderDestToken dst )
{
return src_register( SVGA3dShaderGetRegType( dst.value ),
dst.num );
}
static INLINE ubyte svga_tgsi_sampler_type( struct svga_shader_emitter *emit,
int idx )
{
switch (emit->key.fkey.tex[idx].texture_target) {
case PIPE_TEXTURE_1D:
return SVGA3DSAMP_2D;
case PIPE_TEXTURE_2D:
return SVGA3DSAMP_2D;
case PIPE_TEXTURE_3D:
return SVGA3DSAMP_VOLUME;
case PIPE_TEXTURE_CUBE:
return SVGA3DSAMP_CUBE;
}
return SVGA3DSAMP_UNKNOWN;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,299 @@
/**********************************************************
* 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.
*
**********************************************************/
/**
* @file
* VMware SVGA specific winsys interface.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*
* Documentation taken from the VMware SVGA DDK.
*/
#ifndef SVGA_WINSYS_H_
#define SVGA_WINSYS_H_
#include "svga_types.h"
#include "svga_reg.h"
#include "svga3d_reg.h"
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
struct svga_winsys_screen;
struct svga_winsys_buffer;
struct pipe_screen;
struct pipe_context;
struct pipe_fence_handle;
struct pipe_texture;
struct svga_region;
#define SVGA_BUFFER_USAGE_PINNED (PIPE_BUFFER_USAGE_CUSTOM << 0)
#define SVGA_BUFFER_USAGE_WRAPPED (PIPE_BUFFER_USAGE_CUSTOM << 1)
/** Opaque surface handle */
struct svga_winsys_surface;
/** Opaque buffer handle */
struct svga_winsys_handle;
/**
* SVGA per-context winsys interface.
*/
struct svga_winsys_context
{
void
(*destroy)(struct svga_winsys_context *swc);
void *
(*reserve)(struct svga_winsys_context *swc,
uint32_t nr_bytes, uint32_t nr_relocs );
/**
* Emit a relocation for a host surface.
*
* @param flags PIPE_BUFFER_USAGE_GPU_READ/WRITE
*
* NOTE: Order of this call does matter. It should be the same order
* as relocations appear in the command buffer.
*/
void
(*surface_relocation)(struct svga_winsys_context *swc,
uint32 *sid,
struct svga_winsys_surface *surface,
unsigned flags);
/**
* Emit a relocation for a guest memory region.
*
* @param flags PIPE_BUFFER_USAGE_GPU_READ/WRITE
*
* NOTE: Order of this call does matter. It should be the same order
* as relocations appear in the command buffer.
*/
void
(*region_relocation)(struct svga_winsys_context *swc,
struct SVGAGuestPtr *ptr,
struct svga_winsys_buffer *buffer,
uint32 offset,
unsigned flags);
void
(*commit)(struct svga_winsys_context *swc);
enum pipe_error
(*flush)(struct svga_winsys_context *swc,
struct pipe_fence_handle **pfence);
/**
* Context ID used to fill in the commands
*
* Context IDs are arbitrary small non-negative integers,
* global to the entire SVGA device.
*/
uint32 cid;
};
/**
* SVGA per-screen winsys interface.
*/
struct svga_winsys_screen
{
void
(*destroy)(struct svga_winsys_screen *sws);
boolean
(*get_cap)(struct svga_winsys_screen *sws,
SVGA3dDevCapIndex index,
SVGA3dDevCapResult *result);
/**
* Create a new context.
*
* 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.
*/
struct svga_winsys_context *
(*context_create)(struct svga_winsys_screen *sws);
/**
* This creates a "surface" object in the SVGA3D device,
* and returns the surface ID (sid). Surfaces are generic
* containers for host VRAM objects like textures, vertex
* buffers, and depth/stencil buffers.
*
* Surfaces are hierarchial:
*
* - 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.
*/
struct svga_winsys_surface *
(*surface_create)(struct svga_winsys_screen *sws,
SVGA3dSurfaceFlags flags,
SVGA3dSurfaceFormat format,
SVGA3dSize size,
uint32 numFaces,
uint32 numMipLevels);
/**
* Whether this surface is sitting in a validate list
*/
boolean
(*surface_is_flushed)(struct svga_winsys_screen *sws,
struct svga_winsys_surface *surface);
/**
* Reference a SVGA3D surface object. This allows sharing of a
* surface between different objects.
*/
void
(*surface_reference)(struct svga_winsys_screen *sws,
struct svga_winsys_surface **pdst,
struct svga_winsys_surface *src);
/**
* Buffer management. Buffer attributes are mostly fixed over its lifetime.
*
* Remember that gallium gets to choose the interface it needs, and the
* window systems must then implement that interface (rather than the
* other way around...).
*
* usage is a bitmask of PIPE_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This
* usage argument is only an optimization hint, not a guarantee, therefore
* proper behavior must be observed in all circumstances.
*
* alignment indicates the client's alignment requirements, eg for
* SSE instructions.
*/
struct svga_winsys_buffer *
(*buffer_create)( struct svga_winsys_screen *sws,
unsigned alignment,
unsigned usage,
unsigned size );
/**
* Map the entire data store of a buffer object into the client's address.
* flags is a bitmask of:
* - PIPE_BUFFER_USAGE_CPU_READ/WRITE
* - PIPE_BUFFER_USAGE_DONTBLOCK
* - PIPE_BUFFER_USAGE_UNSYNCHRONIZED
*/
void *
(*buffer_map)( struct svga_winsys_screen *sws,
struct svga_winsys_buffer *buf,
unsigned usage );
void
(*buffer_unmap)( struct svga_winsys_screen *sws,
struct svga_winsys_buffer *buf );
void
(*buffer_destroy)( struct svga_winsys_screen *sws,
struct svga_winsys_buffer *buf );
/**
* Reference a fence object.
*/
void
(*fence_reference)( struct svga_winsys_screen *sws,
struct pipe_fence_handle **pdst,
struct pipe_fence_handle *src );
/**
* Checks whether the fence has been signalled.
* \param flags driver-specific meaning
* \return zero on success.
*/
int (*fence_signalled)( struct svga_winsys_screen *sws,
struct pipe_fence_handle *fence,
unsigned flag );
/**
* Wait for the fence to finish.
* \param flags driver-specific meaning
* \return zero on success.
*/
int (*fence_finish)( struct svga_winsys_screen *sws,
struct pipe_fence_handle *fence,
unsigned flag );
};
struct pipe_context *
svga_context_create(struct pipe_screen *screen);
struct pipe_screen *
svga_screen_create(struct svga_winsys_screen *sws);
struct svga_winsys_screen *
svga_winsys_screen(struct pipe_screen *screen);
struct pipe_buffer *
svga_screen_buffer_wrap_surface(struct pipe_screen *screen,
enum SVGA3dSurfaceFormat format,
struct svga_winsys_surface *srf);
struct svga_winsys_surface *
svga_screen_texture_get_winsys_surface(struct pipe_texture *texture);
struct svga_winsys_surface *
svga_screen_buffer_get_winsys_surface(struct pipe_buffer *buffer);
boolean
svga_screen_buffer_from_texture(struct pipe_texture *texture,
struct pipe_buffer **buffer,
unsigned *stride);
#endif /* SVGA_WINSYS_H_ */

View file

@ -0,0 +1,214 @@
/**********************************************************
* Copyright 2007-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.
*
**********************************************************/
/**
* @file
* SVGA Shader Token Definitions
*
* @author Michal Krol <michal@vmware.com>
*/
#ifndef ST_SHADER_SVGA_H
#define ST_SHADER_SVGA_H
#include "pipe/p_compiler.h"
struct sh_op
{
unsigned opcode:16;
unsigned control:8;
unsigned length:4;
unsigned predicated:1;
unsigned unused:1;
unsigned coissue:1;
unsigned is_reg:1;
};
struct sh_reg
{
unsigned number:11;
unsigned type_hi:2;
unsigned relative:1;
unsigned unused:14;
unsigned type_lo:3;
unsigned is_reg:1;
};
static INLINE unsigned
sh_reg_type( struct sh_reg reg )
{
return reg.type_lo | (reg.type_hi << 3);
}
struct sh_cdata
{
float xyzw[4];
};
struct sh_def
{
struct sh_op op;
struct sh_reg reg;
struct sh_cdata cdata;
};
struct sh_defb
{
struct sh_op op;
struct sh_reg reg;
uint data;
};
struct sh_idata
{
int xyzw[4];
};
struct sh_defi
{
struct sh_op op;
struct sh_reg reg;
struct sh_idata idata;
};
#define PS_TEXTURETYPE_UNKNOWN SVGA3DSAMP_UNKNOWN
#define PS_TEXTURETYPE_2D SVGA3DSAMP_2D
#define PS_TEXTURETYPE_CUBE SVGA3DSAMP_CUBE
#define PS_TEXTURETYPE_VOLUME SVGA3DSAMP_VOLUME
struct ps_sampleinfo
{
unsigned unused:27;
unsigned texture_type:4;
unsigned is_reg:1;
};
struct vs_semantic
{
unsigned usage:5;
unsigned unused1:11;
unsigned usage_index:4;
unsigned unused2:12;
};
struct sh_dstreg
{
unsigned number:11;
unsigned type_hi:2;
unsigned relative:1;
unsigned unused:2;
unsigned write_mask:4;
unsigned modifier:4;
unsigned shift_scale:4;
unsigned type_lo:3;
unsigned is_reg:1;
};
static INLINE unsigned
sh_dstreg_type( struct sh_dstreg reg )
{
return reg.type_lo | (reg.type_hi << 3);
}
struct sh_dcl
{
struct sh_op op;
union {
struct {
struct ps_sampleinfo sampleinfo;
} ps;
struct {
struct vs_semantic semantic;
} vs;
} u;
struct sh_dstreg reg;
};
struct sh_srcreg
{
unsigned number:11;
unsigned type_hi:2;
unsigned relative:1;
unsigned unused:2;
unsigned swizzle_x:2;
unsigned swizzle_y:2;
unsigned swizzle_z:2;
unsigned swizzle_w:2;
unsigned modifier:4;
unsigned type_lo:3;
unsigned is_reg:1;
};
static INLINE unsigned
sh_srcreg_type( struct sh_srcreg reg )
{
return reg.type_lo | (reg.type_hi << 3);
}
struct sh_dstop
{
struct sh_op op;
struct sh_dstreg dst;
};
struct sh_srcop
{
struct sh_op op;
struct sh_srcreg src;
};
struct sh_src2op
{
struct sh_op op;
struct sh_srcreg src0;
struct sh_srcreg src1;
};
struct sh_unaryop
{
struct sh_op op;
struct sh_dstreg dst;
struct sh_srcreg src;
};
struct sh_binaryop
{
struct sh_op op;
struct sh_dstreg dst;
struct sh_srcreg src0;
struct sh_srcreg src1;
};
struct sh_trinaryop
{
struct sh_op op;
struct sh_dstreg dst;
struct sh_srcreg src0;
struct sh_srcreg src1;
struct sh_srcreg src2;
};
#endif /* ST_SHADER_SVGA_H */

View file

@ -0,0 +1,649 @@
/**********************************************************
* 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.
*
**********************************************************/
/**
* @file
* SVGA Shader Dump Facilities
*
* @author Michal Krol <michal@vmware.com>
*/
#include "st_shader.h"
#include "st_shader_dump.h"
#include "st_shader_op.h"
#include "util/u_debug.h"
#include "../svga_hw_reg.h"
#include "svga3d_shaderdefs.h"
struct dump_info
{
SVGA3dShaderVersion version;
boolean is_ps;
};
static void dump_op( struct sh_op op, const char *mnemonic )
{
assert( op.predicated == 0 );
assert( op.is_reg == 0 );
if (op.coissue)
debug_printf( "+" );
debug_printf( "%s", mnemonic );
switch (op.control) {
case 0:
break;
case SVGA3DOPCONT_PROJECT:
debug_printf( "p" );
break;
case SVGA3DOPCONT_BIAS:
debug_printf( "b" );
break;
default:
assert( 0 );
}
}
static void dump_comp_op( struct sh_op op, const char *mnemonic )
{
assert( op.is_reg == 0 );
if (op.coissue)
debug_printf( "+" );
debug_printf( "%s", mnemonic );
switch (op.control) {
case SVGA3DOPCOMP_RESERVED0:
break;
case SVGA3DOPCOMP_GT:
debug_printf("_gt");
break;
case SVGA3DOPCOMP_EQ:
debug_printf("_eq");
break;
case SVGA3DOPCOMP_GE:
debug_printf("_ge");
break;
case SVGA3DOPCOMP_LT:
debug_printf("_lt");
break;
case SVGA3DOPCOMPC_NE:
debug_printf("_ne");
break;
case SVGA3DOPCOMP_LE:
debug_printf("_le");
break;
case SVGA3DOPCOMP_RESERVED1:
default:
assert( 0 );
}
}
static void dump_reg( struct sh_reg reg, struct sh_srcreg *indreg, const struct dump_info *di )
{
assert( sh_reg_type( reg ) == SVGA3DREG_CONST || reg.relative == 0 );
assert( reg.is_reg == 1 );
switch (sh_reg_type( reg )) {
case SVGA3DREG_TEMP:
debug_printf( "r%u", reg.number );
break;
case SVGA3DREG_INPUT:
debug_printf( "v%u", reg.number );
break;
case SVGA3DREG_CONST:
if (reg.relative) {
if (sh_srcreg_type( *indreg ) == SVGA3DREG_LOOP)
debug_printf( "c[aL+%u]", reg.number );
else
debug_printf( "c[a%u.x+%u]", indreg->number, reg.number );
}
else
debug_printf( "c%u", reg.number );
break;
case SVGA3DREG_ADDR: /* VS */
/* SVGA3DREG_TEXTURE */ /* PS */
if (di->is_ps)
debug_printf( "t%u", reg.number );
else
debug_printf( "a%u", reg.number );
break;
case SVGA3DREG_RASTOUT:
switch (reg.number) {
case 0 /*POSITION*/:
debug_printf( "oPos" );
break;
case 1 /*FOG*/:
debug_printf( "oFog" );
break;
case 2 /*POINT_SIZE*/:
debug_printf( "oPts" );
break;
default:
assert( 0 );
debug_printf( "???" );
}
break;
case SVGA3DREG_ATTROUT:
assert( reg.number < 2 );
debug_printf( "oD%u", reg.number );
break;
case SVGA3DREG_TEXCRDOUT:
/* SVGA3DREG_OUTPUT */
debug_printf( "oT%u", reg.number );
break;
case SVGA3DREG_COLOROUT:
debug_printf( "oC%u", reg.number );
break;
case SVGA3DREG_DEPTHOUT:
debug_printf( "oD%u", reg.number );
break;
case SVGA3DREG_SAMPLER:
debug_printf( "s%u", reg.number );
break;
case SVGA3DREG_CONSTBOOL:
assert( !reg.relative );
debug_printf( "b%u", reg.number );
break;
case SVGA3DREG_CONSTINT:
assert( !reg.relative );
debug_printf( "i%u", reg.number );
break;
case SVGA3DREG_LOOP:
assert( reg.number == 0 );
debug_printf( "aL" );
break;
case SVGA3DREG_MISCTYPE:
switch (reg.number) {
case SVGA3DMISCREG_POSITION:
debug_printf( "vPos" );
break;
case SVGA3DMISCREG_FACE:
debug_printf( "vFace" );
break;
default:
assert(0);
break;
}
break;
case SVGA3DREG_LABEL:
debug_printf( "l%u", reg.number );
break;
case SVGA3DREG_PREDICATE:
debug_printf( "p%u", reg.number );
break;
default:
assert( 0 );
debug_printf( "???" );
}
}
static void dump_cdata( struct sh_cdata cdata )
{
debug_printf( "%f, %f, %f, %f", cdata.xyzw[0], cdata.xyzw[1], cdata.xyzw[2], cdata.xyzw[3] );
}
static void dump_idata( struct sh_idata idata )
{
debug_printf( "%d, %d, %d, %d", idata.xyzw[0], idata.xyzw[1], idata.xyzw[2], idata.xyzw[3] );
}
static void dump_bdata( boolean bdata )
{
debug_printf( bdata ? "TRUE" : "FALSE" );
}
static void dump_sampleinfo( struct ps_sampleinfo sampleinfo )
{
switch (sampleinfo.texture_type) {
case SVGA3DSAMP_2D:
debug_printf( "_2d" );
break;
case SVGA3DSAMP_CUBE:
debug_printf( "_cube" );
break;
case SVGA3DSAMP_VOLUME:
debug_printf( "_volume" );
break;
default:
assert( 0 );
}
}
static void dump_usageinfo( struct vs_semantic semantic )
{
switch (semantic.usage) {
case SVGA3D_DECLUSAGE_POSITION:
debug_printf("_position" );
break;
case SVGA3D_DECLUSAGE_BLENDWEIGHT:
debug_printf("_blendweight" );
break;
case SVGA3D_DECLUSAGE_BLENDINDICES:
debug_printf("_blendindices" );
break;
case SVGA3D_DECLUSAGE_NORMAL:
debug_printf("_normal" );
break;
case SVGA3D_DECLUSAGE_PSIZE:
debug_printf("_psize" );
break;
case SVGA3D_DECLUSAGE_TEXCOORD:
debug_printf("_texcoord");
break;
case SVGA3D_DECLUSAGE_TANGENT:
debug_printf("_tangent" );
break;
case SVGA3D_DECLUSAGE_BINORMAL:
debug_printf("_binormal" );
break;
case SVGA3D_DECLUSAGE_TESSFACTOR:
debug_printf("_tessfactor" );
break;
case SVGA3D_DECLUSAGE_POSITIONT:
debug_printf("_positiont" );
break;
case SVGA3D_DECLUSAGE_COLOR:
debug_printf("_color" );
break;
case SVGA3D_DECLUSAGE_FOG:
debug_printf("_fog" );
break;
case SVGA3D_DECLUSAGE_DEPTH:
debug_printf("_depth" );
break;
case SVGA3D_DECLUSAGE_SAMPLE:
debug_printf("_sample");
break;
default:
assert( 0 );
return;
}
if (semantic.usage_index != 0) {
debug_printf("%d", semantic.usage_index );
}
}
static void dump_dstreg( struct sh_dstreg dstreg, const struct dump_info *di )
{
union {
struct sh_reg reg;
struct sh_dstreg dstreg;
} u;
assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier );
if (dstreg.modifier & SVGA3DDSTMOD_SATURATE)
debug_printf( "_sat" );
if (dstreg.modifier & SVGA3DDSTMOD_PARTIALPRECISION)
debug_printf( "_pp" );
switch (dstreg.shift_scale) {
case 0:
break;
case 1:
debug_printf( "_x2" );
break;
case 2:
debug_printf( "_x4" );
break;
case 3:
debug_printf( "_x8" );
break;
case 13:
debug_printf( "_d8" );
break;
case 14:
debug_printf( "_d4" );
break;
case 15:
debug_printf( "_d2" );
break;
default:
assert( 0 );
}
debug_printf( " " );
u.dstreg = dstreg;
dump_reg( u.reg, NULL, di );
if (dstreg.write_mask != SVGA3DWRITEMASK_ALL) {
debug_printf( "." );
if (dstreg.write_mask & SVGA3DWRITEMASK_0)
debug_printf( "x" );
if (dstreg.write_mask & SVGA3DWRITEMASK_1)
debug_printf( "y" );
if (dstreg.write_mask & SVGA3DWRITEMASK_2)
debug_printf( "z" );
if (dstreg.write_mask & SVGA3DWRITEMASK_3)
debug_printf( "w" );
}
}
static void dump_srcreg( struct sh_srcreg srcreg, struct sh_srcreg *indreg, const struct dump_info *di )
{
union {
struct sh_reg reg;
struct sh_srcreg srcreg;
} u;
switch (srcreg.modifier) {
case SVGA3DSRCMOD_NEG:
case SVGA3DSRCMOD_BIASNEG:
case SVGA3DSRCMOD_SIGNNEG:
case SVGA3DSRCMOD_X2NEG:
debug_printf( "-" );
break;
case SVGA3DSRCMOD_ABS:
debug_printf( "|" );
break;
case SVGA3DSRCMOD_ABSNEG:
debug_printf( "-|" );
break;
case SVGA3DSRCMOD_COMP:
debug_printf( "1-" );
break;
case SVGA3DSRCMOD_NOT:
debug_printf( "!" );
}
u.srcreg = srcreg;
dump_reg( u.reg, indreg, di );
switch (srcreg.modifier) {
case SVGA3DSRCMOD_NONE:
case SVGA3DSRCMOD_NEG:
case SVGA3DSRCMOD_COMP:
case SVGA3DSRCMOD_NOT:
break;
case SVGA3DSRCMOD_ABS:
case SVGA3DSRCMOD_ABSNEG:
debug_printf( "|" );
break;
case SVGA3DSRCMOD_BIAS:
case SVGA3DSRCMOD_BIASNEG:
debug_printf( "_bias" );
break;
case SVGA3DSRCMOD_SIGN:
case SVGA3DSRCMOD_SIGNNEG:
debug_printf( "_bx2" );
break;
case SVGA3DSRCMOD_X2:
case SVGA3DSRCMOD_X2NEG:
debug_printf( "_x2" );
break;
case SVGA3DSRCMOD_DZ:
debug_printf( "_dz" );
break;
case SVGA3DSRCMOD_DW:
debug_printf( "_dw" );
break;
default:
assert( 0 );
}
if (srcreg.swizzle_x != 0 || srcreg.swizzle_y != 1 || srcreg.swizzle_z != 2 || srcreg.swizzle_w != 3) {
debug_printf( "." );
if (srcreg.swizzle_x == srcreg.swizzle_y && srcreg.swizzle_y == srcreg.swizzle_z && srcreg.swizzle_z == srcreg.swizzle_w) {
debug_printf( "%c", "xyzw"[srcreg.swizzle_x] );
}
else {
debug_printf( "%c", "xyzw"[srcreg.swizzle_x] );
debug_printf( "%c", "xyzw"[srcreg.swizzle_y] );
debug_printf( "%c", "xyzw"[srcreg.swizzle_z] );
debug_printf( "%c", "xyzw"[srcreg.swizzle_w] );
}
}
}
void
sh_svga_dump(
const unsigned *assem,
unsigned dwords,
unsigned do_binary )
{
const unsigned *start = assem;
boolean finished = FALSE;
struct dump_info di;
unsigned i;
if (do_binary) {
for (i = 0; i < dwords; i++)
debug_printf(" 0x%08x,\n", assem[i]);
debug_printf("\n\n");
}
di.version.value = *assem++;
di.is_ps = (di.version.type == SVGA3D_PS_TYPE);
debug_printf(
"%s_%u_%u\n",
di.is_ps ? "ps" : "vs",
di.version.major,
di.version.minor );
while (!finished) {
struct sh_op op = *(struct sh_op *) assem;
if (assem - start >= dwords) {
debug_printf("... ran off end of buffer\n");
assert(0);
return;
}
switch (op.opcode) {
case SVGA3DOP_DCL:
{
struct sh_dcl dcl = *(struct sh_dcl *) assem;
debug_printf( "dcl" );
if (sh_dstreg_type( dcl.reg ) == SVGA3DREG_SAMPLER)
dump_sampleinfo( dcl.u.ps.sampleinfo );
else if (di.is_ps) {
if (di.version.major == 3 &&
sh_dstreg_type( dcl.reg ) != SVGA3DREG_MISCTYPE)
dump_usageinfo( dcl.u.vs.semantic );
}
else
dump_usageinfo( dcl.u.vs.semantic );
dump_dstreg( dcl.reg, &di );
debug_printf( "\n" );
assem += sizeof( struct sh_dcl ) / sizeof( unsigned );
}
break;
case SVGA3DOP_DEFB:
{
struct sh_defb defb = *(struct sh_defb *) assem;
debug_printf( "defb " );
dump_reg( defb.reg, NULL, &di );
debug_printf( ", " );
dump_bdata( defb.data );
debug_printf( "\n" );
assem += sizeof( struct sh_defb ) / sizeof( unsigned );
}
break;
case SVGA3DOP_DEFI:
{
struct sh_defi defi = *(struct sh_defi *) assem;
debug_printf( "defi " );
dump_reg( defi.reg, NULL, &di );
debug_printf( ", " );
dump_idata( defi.idata );
debug_printf( "\n" );
assem += sizeof( struct sh_defi ) / sizeof( unsigned );
}
break;
case SVGA3DOP_TEXCOORD:
assert( di.is_ps );
dump_op( op, "texcoord" );
if (0) {
struct sh_dstop dstop = *(struct sh_dstop *) assem;
dump_dstreg( dstop.dst, &di );
assem += sizeof( struct sh_dstop ) / sizeof( unsigned );
}
else {
struct sh_unaryop unaryop = *(struct sh_unaryop *) assem;
dump_dstreg( unaryop.dst, &di );
debug_printf( ", " );
dump_srcreg( unaryop.src, NULL, &di );
assem += sizeof( struct sh_unaryop ) / sizeof( unsigned );
}
debug_printf( "\n" );
break;
case SVGA3DOP_TEX:
assert( di.is_ps );
if (0) {
dump_op( op, "tex" );
if (0) {
struct sh_dstop dstop = *(struct sh_dstop *) assem;
dump_dstreg( dstop.dst, &di );
assem += sizeof( struct sh_dstop ) / sizeof( unsigned );
}
else {
struct sh_unaryop unaryop = *(struct sh_unaryop *) assem;
dump_dstreg( unaryop.dst, &di );
debug_printf( ", " );
dump_srcreg( unaryop.src, NULL, &di );
assem += sizeof( struct sh_unaryop ) / sizeof( unsigned );
}
}
else {
struct sh_binaryop binaryop = *(struct sh_binaryop *) assem;
dump_op( op, "texld" );
dump_dstreg( binaryop.dst, &di );
debug_printf( ", " );
dump_srcreg( binaryop.src0, NULL, &di );
debug_printf( ", " );
dump_srcreg( binaryop.src1, NULL, &di );
assem += sizeof( struct sh_binaryop ) / sizeof( unsigned );
}
debug_printf( "\n" );
break;
case SVGA3DOP_DEF:
{
struct sh_def def = *(struct sh_def *) assem;
debug_printf( "def " );
dump_reg( def.reg, NULL, &di );
debug_printf( ", " );
dump_cdata( def.cdata );
debug_printf( "\n" );
assem += sizeof( struct sh_def ) / sizeof( unsigned );
}
break;
case SVGA3DOP_PHASE:
debug_printf( "phase\n" );
assem += sizeof( struct sh_op ) / sizeof( unsigned );
break;
case SVGA3DOP_COMMENT:
assert( 0 );
break;
case SVGA3DOP_RET:
debug_printf( "ret\n" );
assem += sizeof( struct sh_op ) / sizeof( unsigned );
break;
case SVGA3DOP_END:
debug_printf( "end\n" );
finished = TRUE;
break;
default:
{
const struct sh_opcode_info *info = sh_svga_opcode_info( op.opcode );
uint i;
uint num_src = info->num_src + op.predicated;
boolean not_first_arg = FALSE;
assert( info->num_dst <= 1 );
if (op.opcode == SVGA3DOP_SINCOS && di.version.major < 3)
num_src += 2;
dump_comp_op( op, info->mnemonic );
assem += sizeof( struct sh_op ) / sizeof( unsigned );
if (info->num_dst > 0) {
struct sh_dstreg dstreg = *(struct sh_dstreg *) assem;
dump_dstreg( dstreg, &di );
assem += sizeof( struct sh_dstreg ) / sizeof( unsigned );
not_first_arg = TRUE;
}
for (i = 0; i < num_src; i++) {
struct sh_srcreg srcreg;
struct sh_srcreg indreg;
srcreg = *(struct sh_srcreg *) assem;
assem += sizeof( struct sh_srcreg ) / sizeof( unsigned );
if (srcreg.relative && !di.is_ps && di.version.major >= 2) {
indreg = *(struct sh_srcreg *) assem;
assem += sizeof( struct sh_srcreg ) / sizeof( unsigned );
}
if (not_first_arg)
debug_printf( ", " );
else
debug_printf( " " );
dump_srcreg( srcreg, &indreg, &di );
not_first_arg = TRUE;
}
debug_printf( "\n" );
}
}
}
}

View file

@ -0,0 +1,42 @@
/**********************************************************
* 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.
*
**********************************************************/
/**
* @file
* SVGA Shader Dump Facilities
*
* @author Michal Krol <michal@vmware.com>
*/
#ifndef ST_SHADER_SVGA_DUMP_H
#define ST_SHADER_SVGA_DUMP_H
void
sh_svga_dump(
const unsigned *assem,
unsigned dwords,
unsigned do_binary );
#endif /* ST_SHADER_SVGA_DUMP_H */

View file

@ -0,0 +1,168 @@
/**********************************************************
* 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.
*
**********************************************************/
/**
* @file
* SVGA Shader Token Opcode Info
*
* @author Michal Krol <michal@vmware.com>
*/
#include "util/u_debug.h"
#include "st_shader_op.h"
#include "../svga_hw_reg.h"
#include "svga3d_shaderdefs.h"
#define SVGA3DOP_INVALID SVGA3DOP_END
#define TGSI_OPCODE_INVALID TGSI_OPCODE_LAST
static struct sh_opcode_info opcode_info[] =
{
{ "nop", 0, 0, SVGA3DOP_NOP },
{ "mov", 1, 1, SVGA3DOP_MOV, },
{ "add", 1, 2, SVGA3DOP_ADD, },
{ "sub", 1, 2, SVGA3DOP_SUB, },
{ "mad", 1, 3, SVGA3DOP_MAD, },
{ "mul", 1, 2, SVGA3DOP_MUL, },
{ "rcp", 1, 1, SVGA3DOP_RCP, },
{ "rsq", 1, 1, SVGA3DOP_RSQ, },
{ "dp3", 1, 2, SVGA3DOP_DP3, },
{ "dp4", 1, 2, SVGA3DOP_DP4, },
{ "min", 1, 2, SVGA3DOP_MIN, },
{ "max", 1, 2, SVGA3DOP_MAX, },
{ "slt", 1, 2, SVGA3DOP_SLT, },
{ "sge", 1, 2, SVGA3DOP_SGE, },
{ "exp", 1, 1, SVGA3DOP_EXP, },
{ "log", 1, 1, SVGA3DOP_LOG, },
{ "lit", 1, 1, SVGA3DOP_LIT, },
{ "dst", 1, 2, SVGA3DOP_DST, },
{ "lrp", 1, 3, SVGA3DOP_LRP, },
{ "frc", 1, 1, SVGA3DOP_FRC, },
{ "m4x4", 1, 2, SVGA3DOP_M4x4, },
{ "m4x3", 1, 2, SVGA3DOP_M4x3, },
{ "m3x4", 1, 2, SVGA3DOP_M3x4, },
{ "m3x3", 1, 2, SVGA3DOP_M3x3, },
{ "m3x2", 1, 2, SVGA3DOP_M3x2, },
{ "call", 0, 1, SVGA3DOP_CALL, },
{ "callnz", 0, 2, SVGA3DOP_CALLNZ, },
{ "loop", 0, 2, SVGA3DOP_LOOP, },
{ "ret", 0, 0, SVGA3DOP_RET, },
{ "endloop", 0, 0, SVGA3DOP_ENDLOOP, },
{ "label", 0, 1, SVGA3DOP_LABEL, },
{ "dcl", 0, 0, SVGA3DOP_DCL, },
{ "pow", 1, 2, SVGA3DOP_POW, },
{ "crs", 1, 2, SVGA3DOP_CRS, },
{ "sgn", 1, 3, SVGA3DOP_SGN, },
{ "abs", 1, 1, SVGA3DOP_ABS, },
{ "nrm", 1, 1, SVGA3DOP_NRM, }, /* 3-componenet normalization */
{ "sincos", 1, 1, SVGA3DOP_SINCOS, },
{ "rep", 0, 1, SVGA3DOP_REP, },
{ "endrep", 0, 0, SVGA3DOP_ENDREP, },
{ "if", 0, 1, SVGA3DOP_IF, },
{ "ifc", 0, 2, SVGA3DOP_IFC, },
{ "else", 0, 0, SVGA3DOP_ELSE, },
{ "endif", 0, 0, SVGA3DOP_ENDIF, },
{ "break", 0, 0, SVGA3DOP_BREAK, },
{ "breakc", 0, 0, SVGA3DOP_BREAKC, },
{ "mova", 1, 1, SVGA3DOP_MOVA, },
{ "defb", 0, 0, SVGA3DOP_DEFB, },
{ "defi", 0, 0, SVGA3DOP_DEFI, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "???", 0, 0, SVGA3DOP_INVALID, },
{ "texcoord", 0, 0, SVGA3DOP_TEXCOORD, },
{ "texkill", 1, 0, SVGA3DOP_TEXKILL, },
{ "tex", 0, 0, SVGA3DOP_TEX, },
{ "texbem", 1, 1, SVGA3DOP_TEXBEM, },
{ "texbeml", 1, 1, SVGA3DOP_TEXBEML, },
{ "texreg2ar", 1, 1, SVGA3DOP_TEXREG2AR, },
{ "texreg2gb", 1, 1, SVGA3DOP_TEXREG2GB, },
{ "texm3x2pad", 1, 1, SVGA3DOP_TEXM3x2PAD, },
{ "texm3x2tex", 1, 1, SVGA3DOP_TEXM3x2TEX, },
{ "texm3x3pad", 1, 1, SVGA3DOP_TEXM3x3PAD, },
{ "texm3x3tex", 1, 1, SVGA3DOP_TEXM3x3TEX, },
{ "reserved0", 0, 0, SVGA3DOP_RESERVED0, },
{ "texm3x3spec", 1, 2, SVGA3DOP_TEXM3x3SPEC, },
{ "texm3x3vspec", 1, 1, SVGA3DOP_TEXM3x3VSPEC,},
{ "expp", 1, 1, SVGA3DOP_EXPP, },
{ "logp", 1, 1, SVGA3DOP_LOGP, },
{ "cnd", 1, 3, SVGA3DOP_CND, },
{ "def", 0, 0, SVGA3DOP_DEF, },
{ "texreg2rgb", 1, 1, SVGA3DOP_TEXREG2RGB, },
{ "texdp3tex", 1, 1, SVGA3DOP_TEXDP3TEX, },
{ "texm3x2depth", 1, 1, SVGA3DOP_TEXM3x2DEPTH,},
{ "texdp3", 1, 1, SVGA3DOP_TEXDP3, },
{ "texm3x3", 1, 1, SVGA3DOP_TEXM3x3, },
{ "texdepth", 1, 0, SVGA3DOP_TEXDEPTH, },
{ "cmp", 1, 3, SVGA3DOP_CMP, },
{ "bem", 1, 2, SVGA3DOP_BEM, },
{ "dp2add", 1, 3, SVGA3DOP_DP2ADD, },
{ "dsx", 1, 1, SVGA3DOP_INVALID, },
{ "dsy", 1, 1, SVGA3DOP_INVALID, },
{ "texldd", 1, 1, SVGA3DOP_INVALID, },
{ "setp", 1, 2, SVGA3DOP_SETP, },
{ "texldl", 1, 1, SVGA3DOP_INVALID, },
{ "breakp", 1, 1, SVGA3DOP_INVALID, },
};
const struct sh_opcode_info *sh_svga_opcode_info( uint op )
{
struct sh_opcode_info *info;
if (op >= sizeof( opcode_info ) / sizeof( opcode_info[0] )) {
/* The opcode is either PHASE, COMMENT, END or out of range.
*/
assert( 0 );
return NULL;
}
info = &opcode_info[op];
if (info->svga_opcode == SVGA3DOP_INVALID) {
/* No valid information. Please provide number of dst/src registers.
*/
assert( 0 );
return NULL;
}
/* Sanity check.
*/
assert( op == info->svga_opcode );
return info;
}

View file

@ -0,0 +1,46 @@
/**********************************************************
* 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.
*
**********************************************************/
/**
* @file
* SVGA Shader Token Opcode Info
*
* @author Michal Krol <michal@vmware.com>
*/
#ifndef ST_SHADER_SVGA_OP_H
#define ST_SHADER_SVGA_OP_H
struct sh_opcode_info
{
const char *mnemonic;
unsigned num_dst:8;
unsigned num_src:8;
unsigned svga_opcode:16;
};
const struct sh_opcode_info *sh_svga_opcode_info( unsigned op );
#endif /* ST_SHADER_SVGA_OP_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,34 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#ifndef SVGA_DUMP_H_
#define SVGA_DUMP_H_
#include "pipe/p_compiler.h"
void
svga_dump_commands(const void *commands, uint32_t size);
#endif /* SVGA_DUMP_H_ */

View file

@ -0,0 +1,329 @@
#!/usr/bin/env python
'''
Generates dumper for the SVGA 3D command stream using pygccxml.
Jose Fonseca <jfonseca@vmware.com>
'''
copyright = '''
/**********************************************************
* Copyright 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.
*
**********************************************************/
'''
import os
import sys
from pygccxml import parser
from pygccxml import declarations
from pygccxml.declarations import algorithm
from pygccxml.declarations import decl_visitor
from pygccxml.declarations import type_traits
from pygccxml.declarations import type_visitor
enums = True
class decl_dumper_t(decl_visitor.decl_visitor_t):
def __init__(self, instance = '', decl = None):
decl_visitor.decl_visitor_t.__init__(self)
self._instance = instance
self.decl = decl
def clone(self):
return decl_dumper_t(self._instance, self.decl)
def visit_class(self):
class_ = self.decl
assert self.decl.class_type in ('struct', 'union')
for variable in class_.variables():
if variable.name != '':
#print 'variable = %r' % variable.name
dump_type(self._instance + '.' + variable.name, variable.type)
def visit_enumeration(self):
if enums:
print ' switch(%s) {' % ("(*cmd)" + self._instance,)
for name, value in self.decl.values:
print ' case %s:' % (name,)
print ' debug_printf("\\t\\t%s = %s\\n");' % (self._instance, name)
print ' break;'
print ' default:'
print ' debug_printf("\\t\\t%s = %%i\\n", %s);' % (self._instance, "(*cmd)" + self._instance)
print ' break;'
print ' }'
else:
print ' debug_printf("\\t\\t%s = %%i\\n", %s);' % (self._instance, "(*cmd)" + self._instance)
def dump_decl(instance, decl):
dumper = decl_dumper_t(instance, decl)
algorithm.apply_visitor(dumper, decl)
class type_dumper_t(type_visitor.type_visitor_t):
def __init__(self, instance, type_):
type_visitor.type_visitor_t.__init__(self)
self.instance = instance
self.type = type_
def clone(self):
return type_dumper_t(self.instance, self.type)
def visit_char(self):
self.print_instance('%i')
def visit_unsigned_char(self):
self.print_instance('%u')
def visit_signed_char(self):
self.print_instance('%i')
def visit_wchar(self):
self.print_instance('%i')
def visit_short_int(self):
self.print_instance('%i')
def visit_short_unsigned_int(self):
self.print_instance('%u')
def visit_bool(self):
self.print_instance('%i')
def visit_int(self):
self.print_instance('%i')
def visit_unsigned_int(self):
self.print_instance('%u')
def visit_long_int(self):
self.print_instance('%li')
def visit_long_unsigned_int(self):
self.print_instance('%lu')
def visit_long_long_int(self):
self.print_instance('%lli')
def visit_long_long_unsigned_int(self):
self.print_instance('%llu')
def visit_float(self):
self.print_instance('%f')
def visit_double(self):
self.print_instance('%f')
def visit_array(self):
for i in range(type_traits.array_size(self.type)):
dump_type(self.instance + '[%i]' % i, type_traits.base_type(self.type))
def visit_pointer(self):
self.print_instance('%p')
def visit_declarated(self):
#print 'decl = %r' % self.type.decl_string
decl = type_traits.remove_declarated(self.type)
dump_decl(self.instance, decl)
def print_instance(self, format):
print ' debug_printf("\\t\\t%s = %s\\n", %s);' % (self.instance, format, "(*cmd)" + self.instance)
def dump_type(instance, type_):
type_ = type_traits.remove_alias(type_)
visitor = type_dumper_t(instance, type_)
algorithm.apply_visitor(visitor, type_)
def dump_struct(decls, class_):
print 'static void'
print 'dump_%s(const %s *cmd)' % (class_.name, class_.name)
print '{'
dump_decl('', class_)
print '}'
print ''
cmds = [
('SVGA_3D_CMD_SURFACE_DEFINE', 'SVGA3dCmdDefineSurface', (), 'SVGA3dSize'),
('SVGA_3D_CMD_SURFACE_DESTROY', 'SVGA3dCmdDestroySurface', (), None),
('SVGA_3D_CMD_SURFACE_COPY', 'SVGA3dCmdSurfaceCopy', (), 'SVGA3dCopyBox'),
('SVGA_3D_CMD_SURFACE_STRETCHBLT', 'SVGA3dCmdSurfaceStretchBlt', (), None),
('SVGA_3D_CMD_SURFACE_DMA', 'SVGA3dCmdSurfaceDMA', (), 'SVGA3dCopyBox'),
('SVGA_3D_CMD_CONTEXT_DEFINE', 'SVGA3dCmdDefineContext', (), None),
('SVGA_3D_CMD_CONTEXT_DESTROY', 'SVGA3dCmdDestroyContext', (), None),
('SVGA_3D_CMD_SETTRANSFORM', 'SVGA3dCmdSetTransform', (), None),
('SVGA_3D_CMD_SETZRANGE', 'SVGA3dCmdSetZRange', (), None),
('SVGA_3D_CMD_SETRENDERSTATE', 'SVGA3dCmdSetRenderState', (), 'SVGA3dRenderState'),
('SVGA_3D_CMD_SETRENDERTARGET', 'SVGA3dCmdSetRenderTarget', (), None),
('SVGA_3D_CMD_SETTEXTURESTATE', 'SVGA3dCmdSetTextureState', (), 'SVGA3dTextureState'),
('SVGA_3D_CMD_SETMATERIAL', 'SVGA3dCmdSetMaterial', (), None),
('SVGA_3D_CMD_SETLIGHTDATA', 'SVGA3dCmdSetLightData', (), None),
('SVGA_3D_CMD_SETLIGHTENABLED', 'SVGA3dCmdSetLightEnabled', (), None),
('SVGA_3D_CMD_SETVIEWPORT', 'SVGA3dCmdSetViewport', (), None),
('SVGA_3D_CMD_SETCLIPPLANE', 'SVGA3dCmdSetClipPlane', (), None),
('SVGA_3D_CMD_CLEAR', 'SVGA3dCmdClear', (), 'SVGA3dRect'),
('SVGA_3D_CMD_PRESENT', 'SVGA3dCmdPresent', (), 'SVGA3dCopyRect'),
('SVGA_3D_CMD_SHADER_DEFINE', 'SVGA3dCmdDefineShader', (), None),
('SVGA_3D_CMD_SHADER_DESTROY', 'SVGA3dCmdDestroyShader', (), None),
('SVGA_3D_CMD_SET_SHADER', 'SVGA3dCmdSetShader', (), None),
('SVGA_3D_CMD_SET_SHADER_CONST', 'SVGA3dCmdSetShaderConst', (), None),
('SVGA_3D_CMD_DRAW_PRIMITIVES', 'SVGA3dCmdDrawPrimitives', (('SVGA3dVertexDecl', 'numVertexDecls'), ('SVGA3dPrimitiveRange', 'numRanges')), 'SVGA3dVertexDivisor'),
('SVGA_3D_CMD_SETSCISSORRECT', 'SVGA3dCmdSetScissorRect', (), None),
('SVGA_3D_CMD_BEGIN_QUERY', 'SVGA3dCmdBeginQuery', (), None),
('SVGA_3D_CMD_END_QUERY', 'SVGA3dCmdEndQuery', (), None),
('SVGA_3D_CMD_WAIT_FOR_QUERY', 'SVGA3dCmdWaitForQuery', (), None),
#('SVGA_3D_CMD_PRESENT_READBACK', None, (), None),
]
def dump_cmds():
print r'''
void
svga_dump_commands(const void *commands, uint32_t size)
{
const uint8_t *next = commands;
const uint8_t *last = next + size;
assert(size % sizeof(uint32_t) == 0);
while(next < last) {
const uint32_t cmd_id = *(const uint32_t *)next;
if(SVGA_3D_CMD_BASE <= cmd_id && cmd_id < SVGA_3D_CMD_MAX) {
const SVGA3dCmdHeader *header = (const SVGA3dCmdHeader *)next;
const uint8_t *body = (const uint8_t *)&header[1];
next = (const uint8_t *)body + header->size;
if(next > last)
break;
'''
print ' switch(cmd_id) {'
indexes = 'ijklmn'
for id, header, body, footer in cmds:
print ' case %s:' % id
print ' debug_printf("\\t%s\\n");' % id
print ' {'
print ' const %s *cmd = (const %s *)body;' % (header, header)
if len(body):
print ' unsigned ' + ', '.join(indexes[:len(body)]) + ';'
print ' dump_%s(cmd);' % header
print ' body = (const uint8_t *)&cmd[1];'
for i in range(len(body)):
struct, count = body[i]
idx = indexes[i]
print ' for(%s = 0; %s < cmd->%s; ++%s) {' % (idx, idx, count, idx)
print ' dump_%s((const %s *)body);' % (struct, struct)
print ' body += sizeof(%s);' % struct
print ' }'
if footer is not None:
print ' while(body + sizeof(%s) <= next) {' % footer
print ' dump_%s((const %s *)body);' % (footer, footer)
print ' body += sizeof(%s);' % footer
print ' }'
if id == 'SVGA_3D_CMD_SHADER_DEFINE':
print ' sh_svga_dump((const uint32_t *)body, (unsigned)(next - body)/sizeof(uint32_t));'
print ' body = next;'
print ' }'
print ' break;'
print ' default:'
print ' debug_printf("\\t0x%08x\\n", cmd_id);'
print ' break;'
print ' }'
print r'''
while(body + sizeof(uint32_t) <= next) {
debug_printf("\t\t0x%08x\n", *(const uint32_t *)body);
body += sizeof(uint32_t);
}
while(body + sizeof(uint32_t) <= next)
debug_printf("\t\t0x%02x\n", *body++);
}
else if(cmd_id == SVGA_CMD_FENCE) {
debug_printf("\tSVGA_CMD_FENCE\n");
debug_printf("\t\t0x%08x\n", ((const uint32_t *)next)[1]);
next += 2*sizeof(uint32_t);
}
else {
debug_printf("\t0x%08x\n", cmd_id);
next += sizeof(uint32_t);
}
}
}
'''
def main():
print copyright.strip()
print
print '/**'
print ' * @file'
print ' * Dump SVGA commands.'
print ' *'
print ' * Generated automatically from svga3d_reg.h by svga_dump.py.'
print ' */'
print
print '#include "svga_types.h"'
print '#include "shader_dump/st_shader_dump.h"'
print '#include "svga3d_reg.h"'
print
print '#include "pipe/p_debug.h"'
print '#include "svga_dump.h"'
print
config = parser.config_t(
include_paths = ['include'],
compiler = 'gcc',
)
headers = [
'include/svga_types.h',
'include/svga3d_reg.h',
]
decls = parser.parse(headers, config, parser.COMPILATION_MODE.ALL_AT_ONCE)
global_ns = declarations.get_global_namespace(decls)
names = set()
for id, header, body, footer in cmds:
names.add(header)
for struct, count in body:
names.add(struct)
if footer is not None:
names.add(footer)
for class_ in global_ns.classes(lambda decl: decl.name in names):
dump_struct(decls, class_)
dump_cmds()
if __name__ == '__main__':
main()

View file

@ -0,0 +1,12 @@
# src/gallium/winsys/drm/vmware/Makefile
TOP = ../../../../..
include $(TOP)/configs/current
SUBDIRS = core $(GALLIUM_STATE_TRACKERS_DIRS)
default install clean:
@for dir in $(SUBDIRS) ; do \
if [ -d $$dir ] ; then \
(cd $$dir && $(MAKE) $@) || exit 1; \
fi \
done

View file

@ -0,0 +1,11 @@
Import('*')
SConscript(['core/SConscript',])
if 'mesa' in env['statetrackers']:
SConscript(['dri/SConscript'])
if 'xorg' in env['statetrackers']:
SConscript(['xorg/SConscript'])

View file

@ -0,0 +1,47 @@
TOP = ../../../../../..
include $(TOP)/configs/current
LIBNAME = svgadrm
C_SOURCES = \
vmw_buffer.c \
vmw_context.c \
vmw_fence.c \
vmw_screen.c \
vmw_screen_dri.c \
vmw_screen_ioctl.c \
vmw_screen_pools.c \
vmw_screen_svga.c \
vmw_surface.c
LIBRARY_INCLUDES = \
-I$(TOP)/src/gallium/drivers/svga \
-I$(TOP)/src/gallium/drivers/svga/include \
-I$(GALLIUM)/src/mesa/drivers/dri/common \
-I$(GALLIUM)/include \
-I$(GALLIUM)/include/GL/internal \
-I$(GALLIUM)/src/mesa \
-I$(GALLIUM)/src/mesa/main \
-I$(GALLIUM)/src/mesa/glapi \
-I$(GALLIUM)/src/egl/main \
-I$(GALLIUM)/src/egl/drivers/dri \
$(shell pkg-config libdrm --cflags-only-I)
LIBRARY_DEFINES = \
-DHAVE_STDINT_H -D_FILE_OFFSET_BITS=64 \
$(shell pkg-config libdrm --cflags-only-other)
CC = gcc -fvisibility=hidden -msse -msse2
# Set the gnu99 standard to enable anonymous structs in vmware headers.
#
CFLAGS = -Wall -Werror -Wmissing-prototypes -std=gnu99 -ffast-math \
$(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) $(ASM_FLAGS)
include ../../../../Makefile.template
symlinks:
include depend

View file

@ -0,0 +1,39 @@
Import('*')
env = env.Clone()
if env['gcc']:
env.Append(CCFLAGS = ['-fvisibility=hidden', '-Werror'])
env.Append(CPPDEFINES = [
'HAVE_STDINT_H',
'HAVE_SYS_TYPES_H',
'-D_FILE_OFFSET_BITS=64',
])
env.Prepend(CPPPATH = [
'include',
'#/src/gallium/drivers/svga',
'#/src/gallium/drivers/svga/include',
])
env.Append(CPPDEFINES = [
])
sources = [
'vmw_buffer.c',
'vmw_context.c',
'vmw_fence.c',
'vmw_screen.c',
'vmw_screen_dri.c',
'vmw_screen_ioctl.c',
'vmw_screen_pools.c',
'vmw_screen_svga.c',
'vmw_surface.c',
]
svgadrm = env.ConvenienceLibrary(
target = 'svgadrm',
source = sources,
)
Export('svgadrm')

View file

@ -0,0 +1,274 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
/**
* @file
* SVGA buffer manager for Guest Memory Regions (GMRs).
*
* GMRs are used for pixel and vertex data upload/download to/from the virtual
* SVGA hardware. There is a limited number of GMRs available, and
* creating/destroying them is also a slow operation so we must suballocate
* them.
*
* This file implements a pipebuffer library's buffer manager, so that we can
* use pipepbuffer's suballocation, fencing, and debugging facilities with GMRs.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#include "svga_cmd.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "pipebuffer/pb_buffer.h"
#include "pipebuffer/pb_bufmgr.h"
#include "svga_winsys.h"
#include "vmw_screen.h"
#include "vmw_buffer.h"
struct vmw_gmr_bufmgr;
struct vmw_gmr_buffer
{
struct pb_buffer base;
struct vmw_gmr_bufmgr *mgr;
struct vmw_region *region;
void *map;
#ifdef DEBUG
struct pipe_fence_handle *last_fence;
#endif
};
extern const struct pb_vtbl vmw_gmr_buffer_vtbl;
static INLINE struct vmw_gmr_buffer *
vmw_gmr_buffer(struct pb_buffer *buf)
{
assert(buf);
assert(buf->vtbl == &vmw_gmr_buffer_vtbl);
return (struct vmw_gmr_buffer *)buf;
}
struct vmw_gmr_bufmgr
{
struct pb_manager base;
struct vmw_winsys_screen *vws;
};
static INLINE struct vmw_gmr_bufmgr *
vmw_gmr_bufmgr(struct pb_manager *mgr)
{
assert(mgr);
return (struct vmw_gmr_bufmgr *)mgr;
}
static void
vmw_gmr_buffer_destroy(struct pb_buffer *_buf)
{
struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf);
#ifdef DEBUG
if(buf->last_fence) {
struct svga_winsys_screen *sws = &buf->mgr->vws->base;
assert(sws->fence_signalled(sws, buf->last_fence, 0) == 0);
}
#endif
vmw_ioctl_region_unmap(buf->region);
vmw_ioctl_region_destroy(buf->region);
FREE(buf);
}
static void *
vmw_gmr_buffer_map(struct pb_buffer *_buf,
unsigned flags)
{
struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf);
return buf->map;
}
static void
vmw_gmr_buffer_unmap(struct pb_buffer *_buf)
{
/* Do nothing */
(void)_buf;
}
static void
vmw_gmr_buffer_get_base_buffer(struct pb_buffer *buf,
struct pb_buffer **base_buf,
unsigned *offset)
{
*base_buf = buf;
*offset = 0;
}
static enum pipe_error
vmw_gmr_buffer_validate( struct pb_buffer *_buf,
struct pb_validate *vl,
unsigned flags )
{
/* Always pinned */
return PIPE_OK;
}
static void
vmw_gmr_buffer_fence( struct pb_buffer *_buf,
struct pipe_fence_handle *fence )
{
/* We don't need to do anything, as the pipebuffer library
* will take care of delaying the destruction of fenced buffers */
#ifdef DEBUG
struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf);
if(fence)
buf->last_fence = fence;
#endif
}
const struct pb_vtbl vmw_gmr_buffer_vtbl = {
vmw_gmr_buffer_destroy,
vmw_gmr_buffer_map,
vmw_gmr_buffer_unmap,
vmw_gmr_buffer_validate,
vmw_gmr_buffer_fence,
vmw_gmr_buffer_get_base_buffer
};
static struct pb_buffer *
vmw_gmr_bufmgr_create_buffer(struct pb_manager *_mgr,
pb_size size,
const struct pb_desc *desc)
{
struct vmw_gmr_bufmgr *mgr = vmw_gmr_bufmgr(_mgr);
struct vmw_winsys_screen *vws = mgr->vws;
struct vmw_gmr_buffer *buf;
buf = CALLOC_STRUCT(vmw_gmr_buffer);
if(!buf)
goto error1;
pipe_reference_init(&buf->base.base.reference, 1);
buf->base.base.alignment = desc->alignment;
buf->base.base.usage = desc->usage;
buf->base.base.size = size;
buf->base.vtbl = &vmw_gmr_buffer_vtbl;
buf->mgr = mgr;
buf->region = vmw_ioctl_region_create(vws, size);
if(!buf->region)
goto error2;
buf->map = vmw_ioctl_region_map(buf->region);
if(!buf->map)
goto error3;
return &buf->base;
error3:
vmw_ioctl_region_destroy(buf->region);
error2:
FREE(buf);
error1:
return NULL;
}
static void
vmw_gmr_bufmgr_flush(struct pb_manager *mgr)
{
/* No-op */
}
static void
vmw_gmr_bufmgr_destroy(struct pb_manager *_mgr)
{
struct vmw_gmr_bufmgr *mgr = vmw_gmr_bufmgr(_mgr);
FREE(mgr);
}
struct pb_manager *
vmw_gmr_bufmgr_create(struct vmw_winsys_screen *vws)
{
struct vmw_gmr_bufmgr *mgr;
mgr = CALLOC_STRUCT(vmw_gmr_bufmgr);
if(!mgr)
return NULL;
mgr->base.destroy = vmw_gmr_bufmgr_destroy;
mgr->base.create_buffer = vmw_gmr_bufmgr_create_buffer;
mgr->base.flush = vmw_gmr_bufmgr_flush;
mgr->vws = vws;
return &mgr->base;
}
boolean
vmw_gmr_bufmgr_region_ptr(struct pb_buffer *buf,
struct SVGAGuestPtr *ptr)
{
struct pb_buffer *base_buf;
unsigned offset = 0;
struct vmw_gmr_buffer *gmr_buf;
pb_get_base_buffer( buf, &base_buf, &offset );
gmr_buf = vmw_gmr_buffer(base_buf);
if(!gmr_buf)
return FALSE;
*ptr = vmw_ioctl_region_ptr(gmr_buf->region);
ptr->offset += offset;
return TRUE;
}

View file

@ -0,0 +1,65 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#ifndef VMW_BUFFER_H_
#define VMW_BUFFER_H_
#include "pipe/p_compiler.h"
struct SVGAGuestPtr;
struct pb_buffer;
struct pb_manager;
struct svga_winsys_buffer;
struct svga_winsys_surface;
struct vmw_winsys_screen;
static INLINE struct pb_buffer *
vmw_pb_buffer(struct svga_winsys_buffer *buffer)
{
assert(buffer);
return (struct pb_buffer *)buffer;
}
static INLINE struct svga_winsys_buffer *
vmw_svga_winsys_buffer(struct pb_buffer *buffer)
{
assert(buffer);
return (struct svga_winsys_buffer *)buffer;
}
struct pb_manager *
vmw_gmr_bufmgr_create(struct vmw_winsys_screen *vws);
boolean
vmw_gmr_bufmgr_region_ptr(struct pb_buffer *buf,
struct SVGAGuestPtr *ptr);
#endif /* VMW_BUFFER_H_ */

View file

@ -0,0 +1,297 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_debug_stack.h"
#include "pipebuffer/pb_buffer.h"
#include "pipebuffer/pb_validate.h"
#include "svga_winsys.h"
#include "vmw_context.h"
#include "vmw_screen.h"
#include "vmw_buffer.h"
#include "vmw_surface.h"
#include "vmw_fence.h"
#define VMW_COMMAND_SIZE (64*1024)
#define VMW_SURFACE_RELOCS (1024)
#define VMW_MUST_FLUSH_STACK 8
struct vmw_svga_winsys_context
{
struct svga_winsys_context base;
struct vmw_winsys_screen *vws;
#ifdef DEBUG
boolean must_flush;
struct debug_stack_frame must_flush_stack[VMW_MUST_FLUSH_STACK];
#endif
struct {
uint8_t buffer[VMW_COMMAND_SIZE];
uint32_t size;
uint32_t used;
uint32_t reserved;
} command;
struct {
struct vmw_svga_winsys_surface *handles[VMW_SURFACE_RELOCS];
uint32_t size;
uint32_t used;
uint32_t staged;
uint32_t reserved;
} surface;
struct pb_validate *validate;
uint32_t last_fence;
};
static INLINE struct vmw_svga_winsys_context *
vmw_svga_winsys_context(struct svga_winsys_context *swc)
{
assert(swc);
return (struct vmw_svga_winsys_context *)swc;
}
static enum pipe_error
vmw_swc_flush(struct svga_winsys_context *swc,
struct pipe_fence_handle **pfence)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
struct pipe_fence_handle *fence = NULL;
unsigned i;
enum pipe_error ret;
ret = pb_validate_validate(vswc->validate);
assert(ret == PIPE_OK);
if(ret == PIPE_OK) {
if (vswc->command.used)
vmw_ioctl_command(vswc->vws,
vswc->command.buffer,
vswc->command.used,
&vswc->last_fence);
fence = vmw_pipe_fence(vswc->last_fence);
pb_validate_fence(vswc->validate, fence);
}
vswc->command.used = 0;
vswc->command.reserved = 0;
for(i = 0; i < vswc->surface.used + vswc->surface.staged; ++i) {
struct vmw_svga_winsys_surface *vsurf =
vswc->surface.handles[i];
p_atomic_dec(&vsurf->validated);
vmw_svga_winsys_surface_reference(&vswc->surface.handles[i], NULL);
}
vswc->surface.used = 0;
vswc->surface.reserved = 0;
#ifdef DEBUG
vswc->must_flush = FALSE;
#endif
if(pfence)
*pfence = fence;
return ret;
}
static void *
vmw_swc_reserve(struct svga_winsys_context *swc,
uint32_t nr_bytes, uint32_t nr_relocs )
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
#ifdef DEBUG
/* Check if somebody forgot to check the previous failure */
if(vswc->must_flush) {
debug_printf("Forgot to flush:\n");
debug_backtrace_dump(vswc->must_flush_stack, VMW_MUST_FLUSH_STACK);
assert(!vswc->must_flush);
}
#endif
assert(nr_bytes <= vswc->command.size);
if(nr_bytes > vswc->command.size)
return NULL;
if(vswc->command.used + nr_bytes > vswc->command.size ||
vswc->surface.used + nr_relocs > vswc->surface.size) {
#ifdef DEBUG
vswc->must_flush = TRUE;
debug_backtrace_capture(vswc->must_flush_stack, 1,
VMW_MUST_FLUSH_STACK);
#endif
return NULL;
}
assert(vswc->command.used + nr_bytes <= vswc->command.size);
assert(vswc->surface.used + nr_relocs <= vswc->surface.size);
vswc->command.reserved = nr_bytes;
vswc->surface.reserved = nr_relocs;
vswc->surface.staged = 0;
return vswc->command.buffer + vswc->command.used;
}
static void
vmw_swc_surface_relocation(struct svga_winsys_context *swc,
uint32 *where,
struct svga_winsys_surface *surface,
unsigned flags)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
struct vmw_svga_winsys_surface *vsurf;
if(!surface) {
*where = SVGA3D_INVALID_ID;
return;
}
assert(vswc->surface.staged < vswc->surface.reserved);
vsurf = vmw_svga_winsys_surface(surface);
*where = vsurf->sid;
vmw_svga_winsys_surface_reference(&vswc->surface.handles[vswc->surface.used + vswc->surface.staged], vsurf);
p_atomic_inc(&vsurf->validated);
++vswc->surface.staged;
}
static void
vmw_swc_region_relocation(struct svga_winsys_context *swc,
struct SVGAGuestPtr *where,
struct svga_winsys_buffer *buffer,
uint32 offset,
unsigned flags)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
struct SVGAGuestPtr ptr;
struct pb_buffer *buf = vmw_pb_buffer(buffer);
enum pipe_error ret;
if(!vmw_gmr_bufmgr_region_ptr(buf, &ptr))
assert(0);
ptr.offset += offset;
*where = ptr;
ret = pb_validate_add_buffer(vswc->validate, buf, flags);
/* TODO: Update pipebuffer to reserve buffers and not fail here */
assert(ret == PIPE_OK);
}
static void
vmw_swc_commit(struct svga_winsys_context *swc)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
assert(vswc->command.reserved);
assert(vswc->command.used + vswc->command.reserved <= vswc->command.size);
vswc->command.used += vswc->command.reserved;
vswc->command.reserved = 0;
assert(vswc->surface.staged <= vswc->surface.reserved);
assert(vswc->surface.used + vswc->surface.staged <= vswc->surface.size);
vswc->surface.used += vswc->surface.staged;
vswc->surface.staged = 0;
vswc->surface.reserved = 0;
}
static void
vmw_swc_destroy(struct svga_winsys_context *swc)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
unsigned i;
for(i = 0; i < vswc->surface.used; ++i) {
p_atomic_dec(&vswc->surface.handles[i]->validated);
vmw_svga_winsys_surface_reference(&vswc->surface.handles[i], NULL);
}
pb_validate_destroy(vswc->validate);
vmw_ioctl_context_destroy(vswc->vws, swc->cid);
FREE(vswc);
}
struct svga_winsys_context *
vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
struct vmw_svga_winsys_context *vswc;
vswc = CALLOC_STRUCT(vmw_svga_winsys_context);
if(!vswc)
return NULL;
vswc->base.destroy = vmw_swc_destroy;
vswc->base.reserve = vmw_swc_reserve;
vswc->base.surface_relocation = vmw_swc_surface_relocation;
vswc->base.region_relocation = vmw_swc_region_relocation;
vswc->base.commit = vmw_swc_commit;
vswc->base.flush = vmw_swc_flush;
vswc->base.cid = vmw_ioctl_context_create(vws);
vswc->vws = vws;
vswc->command.size = VMW_COMMAND_SIZE;
vswc->surface.size = VMW_SURFACE_RELOCS;
vswc->validate = pb_validate_create();
if(!vswc->validate) {
FREE(vswc);
return NULL;
}
return &vswc->base;
}
struct pipe_context *
vmw_svga_context_create(struct pipe_screen *screen)
{
return svga_context_create(screen);
}

View file

@ -0,0 +1,59 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
/**
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#ifndef VMW_CONTEXT_H_
#define VMW_CONTEXT_H_
#include "pipe/p_compiler.h"
struct svga_winsys_screen;
struct svga_winsys_context;
struct pipe_context;
struct pipe_screen;
#define VMW_DEBUG 0
#if VMW_DEBUG
#define vmw_printf debug_printf
#define VMW_FUNC debug_printf("%s\n", __FUNCTION__)
#else
#define VMW_FUNC
#define vmw_printf(...)
#endif
struct svga_winsys_context *
vmw_svga_winsys_context_create(struct svga_winsys_screen *sws);
struct pipe_context *
vmw_svga_context_create(struct pipe_screen *screen);
#endif /* VMW_CONTEXT_H_ */

View file

@ -0,0 +1,108 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#include "util/u_memory.h"
#include "pipebuffer/pb_buffer_fenced.h"
#include "vmw_screen.h"
#include "vmw_fence.h"
struct vmw_fence_ops
{
struct pb_fence_ops base;
struct vmw_winsys_screen *vws;
};
static INLINE struct vmw_fence_ops *
vmw_fence_ops(struct pb_fence_ops *ops)
{
assert(ops);
return (struct vmw_fence_ops *)ops;
}
static void
vmw_fence_ops_fence_reference(struct pb_fence_ops *ops,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
*ptr = fence;
}
static int
vmw_fence_ops_fence_signalled(struct pb_fence_ops *ops,
struct pipe_fence_handle *fence,
unsigned flag)
{
struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
(void)flag;
return vmw_ioctl_fence_signalled(vws, vmw_fence(fence));
}
static int
vmw_fence_ops_fence_finish(struct pb_fence_ops *ops,
struct pipe_fence_handle *fence,
unsigned flag)
{
struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
(void)flag;
return vmw_ioctl_fence_finish(vws, vmw_fence(fence));
}
static void
vmw_fence_ops_destroy(struct pb_fence_ops *ops)
{
FREE(ops);
}
struct pb_fence_ops *
vmw_fence_ops_create(struct vmw_winsys_screen *vws)
{
struct vmw_fence_ops *ops;
ops = CALLOC_STRUCT(vmw_fence_ops);
if(!ops)
return NULL;
ops->base.destroy = &vmw_fence_ops_destroy;
ops->base.fence_reference = &vmw_fence_ops_fence_reference;
ops->base.fence_signalled = &vmw_fence_ops_fence_signalled;
ops->base.fence_finish = &vmw_fence_ops_fence_finish;
ops->vws = vws;
return &ops->base;
}

View file

@ -0,0 +1,59 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#ifndef VMW_FENCE_H_
#define VMW_FENCE_H_
#include "pipe/p_compiler.h"
struct pipe_fence_handle;
struct pb_fence_ops;
struct vmw_winsys_screen;
/** Cast from a pipe_fence_handle pointer into a SVGA fence */
static INLINE uint32_t
vmw_fence( struct pipe_fence_handle *fence )
{
return (uint32_t)(uintptr_t)fence;
}
/** Cast from a SVGA fence number to pipe_fence_handle pointer */
static INLINE struct pipe_fence_handle *
vmw_pipe_fence( uint32_t fence )
{
return (struct pipe_fence_handle *)(uintptr_t)fence;
}
struct pb_fence_ops *
vmw_fence_ops_create(struct vmw_winsys_screen *vws);
#endif /* VMW_FENCE_H_ */

View file

@ -0,0 +1,74 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#include "vmw_screen.h"
#include "vmw_context.h"
#include "util/u_memory.h"
#include "pipe/p_compiler.h"
/* Called from vmw_drm_create_screen(), creates and initializes the
* vmw_winsys_screen structure, which is the main entity in this
* module.
*/
struct vmw_winsys_screen *
vmw_winsys_create( int fd )
{
struct vmw_winsys_screen *vws = CALLOC_STRUCT(vmw_winsys_screen);
if (!vws)
goto out_no_vws;
vws->ioctl.drm_fd = fd;
if (!vmw_ioctl_init(vws))
goto out_no_ioctl;
if(!vmw_pools_init(vws))
goto out_no_pools;
if (!vmw_winsys_screen_init_svga(vws))
goto out_no_svga;
return vws;
out_no_svga:
vmw_pools_cleanup(vws);
out_no_pools:
vmw_ioctl_cleanup(vws);
out_no_ioctl:
FREE(vws);
out_no_vws:
return NULL;
}
void
vmw_winsys_destroy(struct vmw_winsys_screen *vws)
{
vmw_pools_cleanup(vws);
vmw_ioctl_cleanup(vws);
FREE(vws);
}

View file

@ -0,0 +1,134 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
/**
* @file
* Common definitions for the VMware SVGA winsys.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#ifndef VMW_SCREEN_H_
#define VMW_SCREEN_H_
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "svga_winsys.h"
struct pb_manager;
struct vmw_region;
struct vmw_winsys_screen
{
struct svga_winsys_screen base;
struct {
volatile uint32_t *fifo_map;
uint64_t last_fence;
int drm_fd;
} ioctl;
struct {
struct pb_manager *gmr;
struct pb_manager *gmr_mm;
struct pb_manager *gmr_fenced;
} pools;
};
static INLINE struct vmw_winsys_screen *
vmw_winsys_screen(struct svga_winsys_screen *base)
{
return (struct vmw_winsys_screen *)base;
}
/* */
uint32
vmw_ioctl_context_create(struct vmw_winsys_screen *vws);
void
vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws,
uint32 cid);
uint32
vmw_ioctl_surface_create(struct vmw_winsys_screen *vws,
SVGA3dSurfaceFlags flags,
SVGA3dSurfaceFormat format,
SVGA3dSize size,
uint32 numFaces,
uint32 numMipLevels);
void
vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws,
uint32 sid);
void
vmw_ioctl_command(struct vmw_winsys_screen *vws,
void *commands,
uint32_t size,
uint32_t *fence);
struct vmw_region *
vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size);
void
vmw_ioctl_region_destroy(struct vmw_region *region);
struct SVGAGuestPtr
vmw_ioctl_region_ptr(struct vmw_region *region);
void *
vmw_ioctl_region_map(struct vmw_region *region);
void
vmw_ioctl_region_unmap(struct vmw_region *region);
int
vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws,
uint32_t fence);
int
vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
uint32_t fence);
/* Initialize parts of vmw_winsys_screen at startup:
*/
boolean vmw_ioctl_init(struct vmw_winsys_screen *vws);
boolean vmw_pools_init(struct vmw_winsys_screen *vws);
boolean vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws);
void vmw_ioctl_cleanup(struct vmw_winsys_screen *vws);
void vmw_pools_cleanup(struct vmw_winsys_screen *vws);
struct vmw_winsys_screen *vmw_winsys_create(int fd);
void vmw_winsys_destroy(struct vmw_winsys_screen *sws);
#endif /* VMW_SCREEN_H_ */

View file

@ -0,0 +1,371 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#include "pipe/p_compiler.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "vmw_screen.h"
#include "trace/tr_drm.h"
#include "vmw_screen.h"
#include "vmw_surface.h"
#include "vmw_fence.h"
#include "vmw_context.h"
#include <state_tracker/dri1_api.h>
#include <state_tracker/drm_api.h>
#include <vmwgfx_drm.h>
#include <xf86drm.h>
#include <stdio.h>
static struct dri1_api dri1_api_hooks;
static struct dri1_api_version ddx_required = { 0, 1, 0 };
static struct dri1_api_version ddx_compat = { 0, 0, 0 };
static struct dri1_api_version dri_required = { 4, 0, 0 };
static struct dri1_api_version dri_compat = { 4, 0, 0 };
static struct dri1_api_version drm_required = { 0, 1, 0 };
static struct dri1_api_version drm_compat = { 0, 0, 0 };
static boolean
vmw_dri1_check_version(const struct dri1_api_version *cur,
const struct dri1_api_version *required,
const struct dri1_api_version *compat,
const char component[])
{
if (cur->major > required->major && cur->major <= compat->major)
return TRUE;
if (cur->major == required->major && cur->minor >= required->minor)
return TRUE;
fprintf(stderr, "%s version failure.\n", component);
fprintf(stderr, "%s version is %d.%d.%d and this driver can only work\n"
"with versions %d.%d.x through %d.x.x.\n",
component,
cur->major,
cur->minor,
cur->patch_level, required->major, required->minor, compat->major);
return FALSE;
}
/* This is actually the entrypoint to the entire driver, called by the
* libGL (or EGL, or ...) code via the drm_api_hooks table at the
* bottom of the file.
*/
static struct pipe_screen *
vmw_drm_create_screen(struct drm_api *drm_api,
int fd,
struct drm_create_screen_arg *arg)
{
struct vmw_winsys_screen *vws;
struct pipe_screen *screen;
struct dri1_create_screen_arg *dri1;
if (arg != NULL) {
switch (arg->mode) {
case DRM_CREATE_NORMAL:
break;
case DRM_CREATE_DRI1:
dri1 = (struct dri1_create_screen_arg *)arg;
if (!vmw_dri1_check_version(&dri1->ddx_version, &ddx_required,
&ddx_compat, "ddx - driver api"))
return NULL;
if (!vmw_dri1_check_version(&dri1->dri_version, &dri_required,
&dri_compat, "dri info"))
return NULL;
if (!vmw_dri1_check_version(&dri1->drm_version, &drm_required,
&drm_compat, "vmwgfx drm driver"))
return NULL;
dri1->api = &dri1_api_hooks;
break;
default:
return NULL;
}
}
vws = vmw_winsys_create( fd );
if (!vws)
goto out_no_vws;
screen = svga_screen_create( &vws->base );
if (!screen)
goto out_no_screen;
return screen;
/* Failure cases:
*/
out_no_screen:
vmw_winsys_destroy( vws );
out_no_vws:
return NULL;
}
static INLINE boolean
vmw_dri1_intersect_src_bbox(struct drm_clip_rect *dst,
int dst_x,
int dst_y,
const struct drm_clip_rect *src,
const struct drm_clip_rect *bbox)
{
int xy1;
int xy2;
xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
(int)bbox->x1 + dst_x;
xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
(int)bbox->x2 + dst_x;
if (xy1 >= xy2 || xy1 < 0)
return FALSE;
dst->x1 = xy1;
dst->x2 = xy2;
xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
(int)bbox->y1 + dst_y;
xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
(int)bbox->y2 + dst_y;
if (xy1 >= xy2 || xy1 < 0)
return FALSE;
dst->y1 = xy1;
dst->y2 = xy2;
return TRUE;
}
/**
* No fancy get-surface-from-sarea stuff here.
* Just use the present blit.
*/
static void
vmw_dri1_present_locked(struct pipe_context *locked_pipe,
struct pipe_surface *surf,
const struct drm_clip_rect *rect,
unsigned int num_clip,
int x_draw, int y_draw,
const struct drm_clip_rect *bbox,
struct pipe_fence_handle **p_fence)
{
struct svga_winsys_surface *srf =
svga_screen_texture_get_winsys_surface(surf->texture);
struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf);
struct vmw_winsys_screen *vws =
vmw_winsys_screen(svga_winsys_screen(locked_pipe->screen));
struct drm_clip_rect clip;
int i;
struct
{
SVGA3dCmdHeader header;
SVGA3dCmdPresent body;
SVGA3dCopyRect rect;
} cmd;
boolean visible = FALSE;
uint32_t fence_seq = 0;
VMW_FUNC;
cmd.header.id = SVGA_3D_CMD_PRESENT;
cmd.header.size = sizeof cmd.body + sizeof cmd.rect;
cmd.body.sid = vsrf->sid;
for (i = 0; i < num_clip; ++i) {
if (!vmw_dri1_intersect_src_bbox(&clip, x_draw, y_draw, rect++, bbox))
continue;
cmd.rect.x = clip.x1;
cmd.rect.y = clip.y1;
cmd.rect.w = clip.x2 - clip.x1;
cmd.rect.h = clip.y2 - clip.y1;
cmd.rect.srcx = (int)clip.x1 - x_draw;
cmd.rect.srcy = (int)clip.y1 - y_draw;
vmw_printf("%s: Clip %d x %d y %d w %d h %d srcx %d srcy %d\n",
__FUNCTION__,
i,
cmd.rect.x,
cmd.rect.y,
cmd.rect.w, cmd.rect.h, cmd.rect.srcx, cmd.rect.srcy);
vmw_ioctl_command(vws, &cmd, sizeof cmd.header + cmd.header.size,
&fence_seq);
visible = TRUE;
}
*p_fence = (visible) ? vmw_pipe_fence(fence_seq) : NULL;
vmw_svga_winsys_surface_reference(&vsrf, NULL);
}
/**
* FIXME: We'd probably want to cache these buffers in the
* screen, based on handle.
*/
static struct pipe_buffer *
vmw_drm_buffer_from_handle(struct drm_api *drm_api,
struct pipe_screen *screen,
const char *name,
unsigned handle)
{
struct vmw_svga_winsys_surface *vsrf;
struct svga_winsys_surface *ssrf;
struct vmw_winsys_screen *vws =
vmw_winsys_screen(svga_winsys_screen(screen));
struct pipe_buffer *buf;
union drm_vmw_surface_reference_arg arg;
struct drm_vmw_surface_arg *req = &arg.req;
struct drm_vmw_surface_create_req *rep = &arg.rep;
int ret;
int i;
/**
* The vmware device specific handle is the hardware SID.
* FIXME: We probably want to move this to the ioctl implementations.
*/
memset(&arg, 0, sizeof(arg));
req->sid = handle;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE,
&arg, sizeof(arg));
if (ret) {
fprintf(stderr, "Failed referencing shared surface. SID %d.\n"
"Error %d (%s).\n",
handle, ret, strerror(-ret));
return NULL;
}
if (rep->mip_levels[0] != 1) {
fprintf(stderr, "Incorrect number of mipmap levels on shared surface."
" SID %d, levels %d\n",
handle, rep->mip_levels[0]);
goto out_mip;
}
for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
if (rep->mip_levels[i] != 0) {
fprintf(stderr, "Incorrect number of faces levels on shared surface."
" SID %d, face %d present.\n",
handle, i);
goto out_mip;
}
}
vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface);
if (!vsrf)
goto out_mip;
pipe_reference_init(&vsrf->refcnt, 1);
p_atomic_set(&vsrf->validated, 0);
vsrf->sid = handle;
ssrf = svga_winsys_surface(vsrf);
buf = svga_screen_buffer_wrap_surface(screen, rep->format, ssrf);
if (!buf)
vmw_svga_winsys_surface_reference(&vsrf, NULL);
return buf;
out_mip:
vmw_ioctl_surface_destroy(vws, handle);
return NULL;
}
static struct pipe_texture *
vmw_drm_texture_from_handle(struct drm_api *drm_api,
struct pipe_screen *screen,
struct pipe_texture *templat,
const char *name,
unsigned stride,
unsigned handle)
{
struct pipe_buffer *buffer;
buffer = vmw_drm_buffer_from_handle(drm_api, screen, name, handle);
if (!buffer)
return NULL;
return screen->texture_blanket(screen, templat, &stride, buffer);
}
static boolean
vmw_drm_handle_from_buffer(struct drm_api *drm_api,
struct pipe_screen *screen,
struct pipe_buffer *buffer,
unsigned *handle)
{
struct svga_winsys_surface *surface =
svga_screen_buffer_get_winsys_surface(buffer);
struct vmw_svga_winsys_surface *vsrf;
if (!surface)
return FALSE;
vsrf = vmw_svga_winsys_surface(surface);
*handle = vsrf->sid;
vmw_svga_winsys_surface_reference(&vsrf, NULL);
return TRUE;
}
static boolean
vmw_drm_handle_from_texture(struct drm_api *drm_api,
struct pipe_screen *screen,
struct pipe_texture *texture,
unsigned *stride,
unsigned *handle)
{
struct pipe_buffer *buffer;
if (!svga_screen_buffer_from_texture(texture, &buffer, stride))
return FALSE;
return vmw_drm_handle_from_buffer(drm_api, screen, buffer, handle);
}
static struct pipe_context*
vmw_drm_create_context(struct drm_api *drm_api,
struct pipe_screen *screen)
{
return vmw_svga_context_create(screen);
}
static struct dri1_api dri1_api_hooks = {
.front_srf_locked = NULL,
.present_locked = vmw_dri1_present_locked
};
static struct drm_api vmw_drm_api_hooks = {
.create_screen = vmw_drm_create_screen,
.create_context = vmw_drm_create_context,
.texture_from_shared_handle = vmw_drm_texture_from_handle,
.shared_handle_from_texture = vmw_drm_handle_from_texture,
.local_handle_from_texture = vmw_drm_handle_from_texture,
};
struct drm_api* drm_api_create()
{
return trace_drm_create(&vmw_drm_api_hooks);
}

View file

@ -0,0 +1,503 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
/**
* @file
*
* Wrappers for DRM ioctl functionlaity used by the rest of the vmw
* drm winsys.
*
* Based on svgaicd_escape.c
*/
#include "svga_cmd.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "svgadump/svga_dump.h"
#include "vmw_screen.h"
#include "vmw_context.h"
#include "xf86drm.h"
#include "vmwgfx_drm.h"
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>
struct vmw_region
{
SVGAGuestPtr ptr;
uint32_t handle;
uint64_t map_handle;
void *data;
uint32_t map_count;
int drm_fd;
uint32_t size;
};
static void
vmw_check_last_cmd(struct vmw_winsys_screen *vws)
{
static uint32_t buffer[16384];
struct drm_vmw_fifo_debug_arg arg;
int ret;
return;
memset(&arg, 0, sizeof(arg));
arg.debug_buffer = (unsigned long)buffer;
arg.debug_buffer_size = 65536;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FIFO_DEBUG,
&arg, sizeof(arg));
if (ret) {
debug_printf("%s Ioctl error: \"%s\".\n", __FUNCTION__, strerror(-ret));
return;
}
if (arg.did_not_fit) {
debug_printf("%s Command did not fit completely.\n", __FUNCTION__);
}
svga_dump_commands(buffer, arg.used_size);
}
static void
vmw_ioctl_fifo_unmap(struct vmw_winsys_screen *vws, void *mapping)
{
VMW_FUNC;
(void)munmap(mapping, getpagesize());
}
static void *
vmw_ioctl_fifo_map(struct vmw_winsys_screen *vws,
uint32_t fifo_offset )
{
void *map;
VMW_FUNC;
map = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED,
vws->ioctl.drm_fd, fifo_offset);
if (map == MAP_FAILED) {
debug_printf("Map failed %s\n", strerror(errno));
return NULL;
}
vmw_printf("Fifo (min) is 0x%08x\n", ((uint32_t *) map)[SVGA_FIFO_MIN]);
return map;
}
uint32
vmw_ioctl_context_create(struct vmw_winsys_screen *vws)
{
struct drm_vmw_context_arg c_arg;
int ret;
VMW_FUNC;
ret = drmCommandRead(vws->ioctl.drm_fd, DRM_VMW_CREATE_CONTEXT,
&c_arg, sizeof(c_arg));
if (ret)
return -1;
vmw_check_last_cmd(vws);
vmw_printf("Context id is %d\n", c_arg.cid);
return c_arg.cid;
}
void
vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, uint32 cid)
{
struct drm_vmw_context_arg c_arg;
VMW_FUNC;
memset(&c_arg, 0, sizeof(c_arg));
c_arg.cid = cid;
(void)drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_UNREF_CONTEXT,
&c_arg, sizeof(c_arg));
vmw_check_last_cmd(vws);
}
uint32
vmw_ioctl_surface_create(struct vmw_winsys_screen *vws,
SVGA3dSurfaceFlags flags,
SVGA3dSurfaceFormat format,
SVGA3dSize size,
uint32_t numFaces, uint32_t numMipLevels)
{
union drm_vmw_surface_create_arg s_arg;
struct drm_vmw_surface_create_req *req = &s_arg.req;
struct drm_vmw_surface_arg *rep = &s_arg.rep;
struct drm_vmw_size sizes[DRM_VMW_MAX_SURFACE_FACES*
DRM_VMW_MAX_MIP_LEVELS];
struct drm_vmw_size *cur_size;
uint32_t iFace;
uint32_t iMipLevel;
int ret;
vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format);
memset(&s_arg, 0, sizeof(s_arg));
req->flags = (uint32_t) flags;
req->format = (uint32_t) format;
req->shareable = 1;
assert(numFaces * numMipLevels < DRM_VMW_MAX_SURFACE_FACES*
DRM_VMW_MAX_MIP_LEVELS);
cur_size = sizes;
for (iFace = 0; iFace < numFaces; ++iFace) {
SVGA3dSize mipSize = size;
req->mip_levels[iFace] = numMipLevels;
for (iMipLevel = 0; iMipLevel < numMipLevels; ++iMipLevel) {
cur_size->width = mipSize.width;
cur_size->height = mipSize.height;
cur_size->depth = mipSize.depth;
mipSize.width = MAX2(mipSize.width >> 1, 1);
mipSize.height = MAX2(mipSize.height >> 1, 1);
mipSize.depth = MAX2(mipSize.depth >> 1, 1);
cur_size++;
}
}
for (iFace = numFaces; iFace < SVGA3D_MAX_SURFACE_FACES; ++iFace) {
req->mip_levels[iFace] = 0;
}
req->size_addr = (unsigned long)&sizes;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_CREATE_SURFACE,
&s_arg, sizeof(s_arg));
if (ret)
return -1;
vmw_printf("Surface id is %d\n", rep->sid);
vmw_check_last_cmd(vws);
return rep->sid;
}
void
vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, uint32 sid)
{
struct drm_vmw_surface_arg s_arg;
VMW_FUNC;
memset(&s_arg, 0, sizeof(s_arg));
s_arg.sid = sid;
(void)drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_UNREF_SURFACE,
&s_arg, sizeof(s_arg));
vmw_check_last_cmd(vws);
}
void
vmw_ioctl_command(struct vmw_winsys_screen *vws, void *commands, uint32_t size,
uint32_t * pfence)
{
struct drm_vmw_execbuf_arg arg;
struct drm_vmw_fence_rep rep;
int ret;
#ifdef DEBUG
{
static boolean firsttime = TRUE;
static boolean debug = FALSE;
static boolean skip = FALSE;
if (firsttime) {
debug = debug_get_bool_option("SVGA_DUMP_CMD", FALSE);
skip = debug_get_bool_option("SVGA_SKIP_CMD", FALSE);
}
if (debug) {
VMW_FUNC;
svga_dump_commands(commands, size);
}
firsttime = FALSE;
if (skip) {
size = 0;
}
}
#endif
memset(&arg, 0, sizeof(arg));
memset(&rep, 0, sizeof(rep));
rep.error = -EFAULT;
arg.fence_rep = (unsigned long)&rep;
arg.commands = (unsigned long)commands;
arg.command_size = size;
do {
ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
} while(ret == -ERESTART);
if (ret) {
debug_printf("%s error %s.\n", __FUNCTION__, strerror(-ret));
}
if (rep.error) {
/*
* Kernel has synced and put the last fence sequence in the FIFO
* register.
*/
if (rep.error == -EFAULT)
rep.fence_seq = vws->ioctl.fifo_map[SVGA_FIFO_FENCE];
debug_printf("%s Fence error %s.\n", __FUNCTION__,
strerror(-rep.error));
}
vws->ioctl.last_fence = rep.fence_seq;
if (pfence)
*pfence = rep.fence_seq;
vmw_check_last_cmd(vws);
}
struct vmw_region *
vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size)
{
struct vmw_region *region;
union drm_vmw_alloc_dmabuf_arg arg;
struct drm_vmw_alloc_dmabuf_req *req = &arg.req;
struct drm_vmw_dmabuf_rep *rep = &arg.rep;
int ret;
vmw_printf("%s: size = %u\n", __FUNCTION__, size);
region = CALLOC_STRUCT(vmw_region);
if (!region)
goto out_err1;
memset(&arg, 0, sizeof(arg));
req->size = size;
do {
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_ALLOC_DMABUF, &arg,
sizeof(arg));
} while (ret == -ERESTART);
if (ret) {
debug_printf("IOCTL failed %d: %s\n", ret, strerror(-ret));
goto out_err1;
}
region->ptr.gmrId = rep->cur_gmr_id;
region->ptr.offset = rep->cur_gmr_offset;
region->data = NULL;
region->handle = rep->handle;
region->map_handle = rep->map_handle;
region->map_count = 0;
region->size = size;
region->drm_fd = vws->ioctl.drm_fd;
vmw_printf(" gmrId = %u, offset = %u\n",
region->ptr.gmrId, region->ptr.offset);
return region;
out_err1:
return NULL;
}
void
vmw_ioctl_region_destroy(struct vmw_region *region)
{
struct drm_vmw_unref_dmabuf_arg arg;
vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__,
region->ptr.gmrId, region->ptr.offset);
if (region->data) {
munmap(region->data, region->size);
region->data = NULL;
}
memset(&arg, 0, sizeof(arg));
arg.handle = region->handle;
drmCommandWrite(region->drm_fd, DRM_VMW_UNREF_DMABUF, &arg, sizeof(arg));
FREE(region);
}
SVGAGuestPtr
vmw_ioctl_region_ptr(struct vmw_region *region)
{
return region->ptr;
}
void *
vmw_ioctl_region_map(struct vmw_region *region)
{
void *map;
vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__,
region->ptr.gmrId, region->ptr.offset);
if (region->data == NULL) {
map = mmap(NULL, region->size, PROT_READ | PROT_WRITE, MAP_SHARED,
region->drm_fd, region->map_handle);
if (map == MAP_FAILED) {
debug_printf("%s: Map failed.\n", __FUNCTION__);
return NULL;
}
region->data = map;
}
++region->map_count;
return region->data;
}
void
vmw_ioctl_region_unmap(struct vmw_region *region)
{
vmw_printf("%s: gmrId = %u, offset = %u\n", __FUNCTION__,
region->ptr.gmrId, region->ptr.offset);
--region->map_count;
}
int
vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
uint32_t fence)
{
uint32_t expected;
uint32_t current;
assert(fence);
if(!fence)
return 0;
expected = fence;
current = vws->ioctl.fifo_map[SVGA_FIFO_FENCE];
if ((int32)(current - expected) >= 0)
return 0; /* fence passed */
else
return -1;
}
static void
vmw_ioctl_sync(struct vmw_winsys_screen *vws,
uint32_t fence)
{
uint32_t cur_fence;
struct drm_vmw_fence_wait_arg arg;
int ret;
vmw_printf("%s: fence = %lu\n", __FUNCTION__,
(unsigned long)fence);
cur_fence = vws->ioctl.fifo_map[SVGA_FIFO_FENCE];
vmw_printf("%s: Fence id read is 0x%08x\n", __FUNCTION__,
(unsigned int)cur_fence);
if ((cur_fence - fence) < (1 << 24))
return;
memset(&arg, 0, sizeof(arg));
arg.sequence = fence;
do {
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FENCE_WAIT, &arg,
sizeof(arg));
} while (ret == -ERESTART);
}
int
vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws,
uint32_t fence)
{
assert(fence);
if(fence) {
if(vmw_ioctl_fence_signalled(vws, fence) != 0) {
vmw_ioctl_sync(vws, fence);
}
}
return 0;
}
boolean
vmw_ioctl_init(struct vmw_winsys_screen *vws)
{
struct drm_vmw_getparam_arg gp_arg;
int ret;
VMW_FUNC;
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_FIFO_OFFSET;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
&gp_arg, sizeof(gp_arg));
if (ret) {
debug_printf("GET_PARAM on %d returned %d: %s\n",
vws->ioctl.drm_fd, ret, strerror(-ret));
goto out_err1;
}
vmw_printf("Offset to map is 0x%08llx\n",
(unsigned long long)gp_arg.value);
vws->ioctl.fifo_map = vmw_ioctl_fifo_map(vws, gp_arg.value);
if (vws->ioctl.fifo_map == NULL)
goto out_err1;
vmw_printf("%s OK\n", __FUNCTION__);
return TRUE;
out_err1:
debug_printf("%s Failed\n", __FUNCTION__);
return FALSE;
}
void
vmw_ioctl_cleanup(struct vmw_winsys_screen *vws)
{
VMW_FUNC;
vmw_ioctl_fifo_unmap(vws, (void *)vws->ioctl.fifo_map);
}

View file

@ -0,0 +1,79 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#include "vmw_screen.h"
#include "vmw_buffer.h"
#include "vmw_fence.h"
#include "pipebuffer/pb_buffer.h"
#include "pipebuffer/pb_bufmgr.h"
void
vmw_pools_cleanup(struct vmw_winsys_screen *vws)
{
if(vws->pools.gmr_fenced)
vws->pools.gmr_fenced->destroy(vws->pools.gmr_fenced);
/* gmr_mm pool is already destroyed above */
if(vws->pools.gmr)
vws->pools.gmr->destroy(vws->pools.gmr);
}
boolean
vmw_pools_init(struct vmw_winsys_screen *vws)
{
vws->pools.gmr = vmw_gmr_bufmgr_create(vws);
if(!vws->pools.gmr)
goto error;
vws->pools.gmr_mm = mm_bufmgr_create(vws->pools.gmr,
16*1024*1024,
12 /* 4096 alignment */);
if(!vws->pools.gmr_mm)
goto error;
vws->pools.gmr_fenced = fenced_bufmgr_create(
vws->pools.gmr_mm,
vmw_fence_ops_create(vws));
#ifdef DEBUG
vws->pools.gmr_fenced = pb_debug_manager_create(vws->pools.gmr_fenced,
4096,
4096);
#endif
if(!vws->pools.gmr_fenced)
goto error;
return TRUE;
error:
vmw_pools_cleanup(vws);
return FALSE;
}

View file

@ -0,0 +1,295 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
/**
* @file
* This file implements the SVGA interface into this winsys, defined
* in drivers/svga/svga_winsys.h.
*
* @author Keith Whitwell
* @author Jose Fonseca
*/
#include "svga_cmd.h"
#include "svga3d_caps.h"
#include "pipe/p_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipebuffer/pb_buffer.h"
#include "pipebuffer/pb_bufmgr.h"
#include "svga_winsys.h"
#include "vmw_context.h"
#include "vmw_screen.h"
#include "vmw_surface.h"
#include "vmw_buffer.h"
#include "vmw_fence.h"
static struct svga_winsys_buffer *
vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws,
unsigned alignment,
unsigned usage,
unsigned size)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
struct pb_desc desc;
struct pb_manager *provider;
struct pb_buffer *buffer;
memset(&desc, 0, sizeof desc);
desc.alignment = alignment;
desc.usage = usage;
provider = vws->pools.gmr_fenced;
assert(provider);
buffer = provider->create_buffer(provider, size, &desc);
if(!buffer)
return NULL;
return vmw_svga_winsys_buffer(buffer);
}
static void *
vmw_svga_winsys_buffer_map(struct svga_winsys_screen *sws,
struct svga_winsys_buffer *buf,
unsigned flags)
{
(void)sws;
return pb_map(vmw_pb_buffer(buf), flags);
}
static void
vmw_svga_winsys_buffer_unmap(struct svga_winsys_screen *sws,
struct svga_winsys_buffer *buf)
{
(void)sws;
pb_unmap(vmw_pb_buffer(buf));
}
static void
vmw_svga_winsys_buffer_destroy(struct svga_winsys_screen *sws,
struct svga_winsys_buffer *buf)
{
struct pb_buffer *pbuf = vmw_pb_buffer(buf);
(void)sws;
pb_reference(&pbuf, NULL);
}
static void
vmw_svga_winsys_fence_reference(struct svga_winsys_screen *sws,
struct pipe_fence_handle **pdst,
struct pipe_fence_handle *src)
{
(void)sws;
*pdst = src;
}
static int
vmw_svga_winsys_fence_signalled(struct svga_winsys_screen *sws,
struct pipe_fence_handle *fence,
unsigned flag)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
(void)flag;
return vmw_ioctl_fence_signalled(vws, vmw_fence(fence));
}
static int
vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws,
struct pipe_fence_handle *fence,
unsigned flag)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
(void)flag;
return vmw_ioctl_fence_finish(vws, vmw_fence(fence));
}
static struct svga_winsys_surface *
vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
SVGA3dSurfaceFlags flags,
SVGA3dSurfaceFormat format,
SVGA3dSize size,
uint32 numFaces,
uint32 numMipLevels)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
struct vmw_svga_winsys_surface *surface;
surface = CALLOC_STRUCT(vmw_svga_winsys_surface);
if(!surface)
goto no_surface;
pipe_reference_init(&surface->refcnt, 1);
p_atomic_set(&surface->validated, 0);
surface->screen = vws;
surface->sid = vmw_ioctl_surface_create(vws,
flags, format, size,
numFaces, numMipLevels);
if(surface->sid == SVGA3D_INVALID_ID)
goto no_sid;
return svga_winsys_surface(surface);
no_sid:
FREE(surface);
no_surface:
return NULL;
}
static boolean
vmw_svga_winsys_surface_is_flushed(struct svga_winsys_screen *sws,
struct svga_winsys_surface *surface)
{
struct vmw_svga_winsys_surface *vsurf = vmw_svga_winsys_surface(surface);
return (p_atomic_read(&vsurf->validated) == 0);
}
static void
vmw_svga_winsys_surface_ref(struct svga_winsys_screen *sws,
struct svga_winsys_surface **pDst,
struct svga_winsys_surface *src)
{
struct vmw_svga_winsys_surface *d_vsurf = vmw_svga_winsys_surface(*pDst);
struct vmw_svga_winsys_surface *s_vsurf = vmw_svga_winsys_surface(src);
vmw_svga_winsys_surface_reference(&d_vsurf, s_vsurf);
*pDst = svga_winsys_surface(d_vsurf);
}
static void
vmw_svga_winsys_destroy(struct svga_winsys_screen *sws)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
vmw_winsys_destroy(vws);
}
static boolean
vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws,
SVGA3dDevCapIndex index,
SVGA3dDevCapResult *result)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
const uint32 *capsBlock;
const SVGA3dCapsRecord *capsRecord = NULL;
uint32 offset;
const SVGA3dCapPair *capArray;
int numCaps, first, last;
if(!vws->ioctl.fifo_map)
return FALSE;
if(vws->ioctl.fifo_map[SVGA_FIFO_3D_HWVERSION] < SVGA3D_HWVERSION_WS6_B1)
return FALSE;
/*
* Search linearly through the caps block records for the specified type.
*/
capsBlock = (const uint32 *)&vws->ioctl.fifo_map[SVGA_FIFO_3D_CAPS];
for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) {
const SVGA3dCapsRecord *record;
assert(offset < SVGA_FIFO_3D_CAPS_SIZE);
record = (const SVGA3dCapsRecord *) (capsBlock + offset);
if ((record->header.type >= SVGA3DCAPS_RECORD_DEVCAPS_MIN) &&
(record->header.type <= SVGA3DCAPS_RECORD_DEVCAPS_MAX) &&
(!capsRecord || (record->header.type > capsRecord->header.type))) {
capsRecord = record;
}
}
if(!capsRecord)
return FALSE;
/*
* Calculate the number of caps from the size of the record.
*/
capArray = (const SVGA3dCapPair *) capsRecord->data;
numCaps = (int) ((capsRecord->header.length * sizeof(uint32) -
sizeof capsRecord->header) / (2 * sizeof(uint32)));
/*
* Binary-search for the cap with the specified index.
*/
for (first = 0, last = numCaps - 1; first <= last; ) {
int mid = (first + last) / 2;
if ((SVGA3dDevCapIndex) capArray[mid][0] == index) {
/*
* Found it.
*/
result->u = capArray[mid][1];
return TRUE;
}
/*
* Divide and conquer.
*/
if ((SVGA3dDevCapIndex) capArray[mid][0] > index) {
last = mid - 1;
} else {
first = mid + 1;
}
}
return FALSE;
}
boolean
vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws)
{
vws->base.destroy = vmw_svga_winsys_destroy;
vws->base.get_cap = vmw_svga_winsys_get_cap;
vws->base.context_create = vmw_svga_winsys_context_create;
vws->base.surface_create = vmw_svga_winsys_surface_create;
vws->base.surface_is_flushed = vmw_svga_winsys_surface_is_flushed;
vws->base.surface_reference = vmw_svga_winsys_surface_ref;
vws->base.buffer_create = vmw_svga_winsys_buffer_create;
vws->base.buffer_map = vmw_svga_winsys_buffer_map;
vws->base.buffer_unmap = vmw_svga_winsys_buffer_unmap;
vws->base.buffer_destroy = vmw_svga_winsys_buffer_destroy;
vws->base.fence_reference = vmw_svga_winsys_fence_reference;
vws->base.fence_signalled = vmw_svga_winsys_fence_signalled;
vws->base.fence_finish = vmw_svga_winsys_fence_finish;
return TRUE;
}

View file

@ -0,0 +1,59 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
#include "svga_cmd.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "vmw_surface.h"
#include "vmw_screen.h"
void
vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst,
struct vmw_svga_winsys_surface *src)
{
struct pipe_reference *src_ref;
struct pipe_reference *dst_ref;
struct vmw_svga_winsys_surface *dst = *pdst;
if(*pdst == src || pdst == NULL)
return;
src_ref = src ? &src->refcnt : NULL;
dst_ref = dst ? &dst->refcnt : NULL;
if (pipe_reference(&dst_ref, src_ref)) {
vmw_ioctl_surface_destroy(dst->screen, dst->sid);
#ifdef DEBUG
/* to detect dangling pointers */
assert(p_atomic_read(&dst->validated) == 0);
dst->sid = SVGA3D_INVALID_ID;
#endif
FREE(dst);
}
*pdst = src;
}

View file

@ -0,0 +1,79 @@
/**********************************************************
* Copyright 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.
*
**********************************************************/
/**
* @file
* Surfaces for VMware SVGA winsys.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#ifndef VMW_SURFACE_H_
#define VMW_SURFACE_H_
#include "pipe/p_compiler.h"
#include "pipe/p_atomic.h"
#include "pipe/p_refcnt.h"
#define VMW_MAX_PRESENTS 3
struct vmw_svga_winsys_surface
{
struct pipe_atomic validated;
struct pipe_reference refcnt;
struct vmw_winsys_screen *screen;
uint32_t sid;
/* FIXME: make this thread safe */
unsigned next_present_no;
uint32_t present_fences[VMW_MAX_PRESENTS];
};
static INLINE struct svga_winsys_surface *
svga_winsys_surface(struct vmw_svga_winsys_surface *surf)
{
assert(!surf || surf->sid != SVGA3D_INVALID_ID);
return (struct svga_winsys_surface *)surf;
}
static INLINE struct vmw_svga_winsys_surface *
vmw_svga_winsys_surface(struct svga_winsys_surface *surf)
{
return (struct vmw_svga_winsys_surface *)surf;
}
void
vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst,
struct vmw_svga_winsys_surface *src);
#endif /* VMW_SURFACE_H_ */

View file

@ -0,0 +1,18 @@
TOP = ../../../../../..
include $(TOP)/configs/current
LIBNAME = vmwgfx_dri.so
PIPE_DRIVERS = \
$(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
$(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \
$(TOP)/src/gallium/drivers/trace/libtrace.a \
$(TOP)/src/gallium/drivers/svga/libsvga.a
C_SOURCES = \
$(COMMON_GALLIUM_SOURCES)
include ../../Makefile.template
symlinks:

View file

@ -0,0 +1,63 @@
import os
import os.path
Import('*')
if env['platform'] == 'linux':
if env['dri']:
env = env.Clone()
sources = [
'#/src/mesa/drivers/dri/common/utils.c',
'#/src/mesa/drivers/dri/common/vblank.c',
'#/src/mesa/drivers/dri/common/dri_util.c',
'#/src/mesa/drivers/dri/common/xmlconfig.c',
]
env.ParseConfig('pkg-config --cflags --libs libdrm')
env.Prepend(CPPPATH = [
'#/src/mesa/state_tracker',
'#/src/mesa/drivers/dri/common',
'#/src/mesa/main',
'#/src/mesa/glapi',
'#/src/mesa',
'#/include',
'#/src/gallium/drivers/svga',
'#/src/gallium/drivers/svga/include',
])
env.Append(CPPDEFINES = [
'HAVE_STDINT_H',
'HAVE_SYS_TYPES_H',
])
env.Append(CFLAGS = [
'-Werror',
'-std=gnu99',
'-D_FILE_OFFSET_BITS=64',
])
env.Prepend(LIBPATH = [
])
env.Prepend(LIBS = [
trace,
st_dri,
svgadrm,
svga,
mesa,
auxiliaries,
])
# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions
env.LoadableModule(
target ='vmwgfx_dri.so',
source = sources,
LIBS = env['LIBS'],
SHLIBPREFIX = '',
)

View file

@ -0,0 +1,18 @@
TOP = ../../../../../..
include $(TOP)/configs/current
LIBNAME = EGL_svga.so
PIPE_DRIVERS = \
$(TOP)/src/gallium/state_trackers/egl/libegldrm.a \
$(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \
$(TOP)/src/gallium/drivers/trace/libtrace.a \
$(TOP)/src/gallium/drivers/svga/libsvga.a
C_SOURCES = \
$(COMMON_GALLIUM_SOURCES)
include ../../Makefile.template
symlinks:

View file

@ -0,0 +1,54 @@
TARGET = vmwgfx_drv.so
CFILES = $(wildcard ./*.c)
OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
TOP = ../../../../../..
include $(TOP)/configs/current
INCLUDES = \
$(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \
-I../gem \
-I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/drivers \
-I$(TOP)/src/gallium/auxiliary \
-I$(TOP)/src/gallium
LIBS = \
$(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \
$(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \
$(TOP)/src/gallium/drivers/trace/libtrace.a \
$(TOP)/src/gallium/drivers/svga/libsvga.a \
$(GALLIUM_AUXILIARIES)
DRIVER_DEFINES = \
-DHAVE_CONFIG_H
#############################################
all default: $(TARGET)
$(TARGET): $(OBJECTS) Makefile $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a $(LIBS)
$(TOP)/bin/mklib -noprefix -o $@ \
$(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel
clean:
rm -rf $(OBJECTS) $(TARGET)
install:
$(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
$(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR)
##############################################
.c.o:
$(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@
##############################################
.PHONY = all clean install

View file

@ -0,0 +1,55 @@
import os.path
Import('*')
if env['platform'] == 'linux':
env = env.Clone()
env.ParseConfig('pkg-config --cflags --libs libdrm xorg-server')
env.Prepend(CPPPATH = [
'#/include',
'#/src/gallium',
'#/src/mesa',
'#/src/gallium/drivers/svga',
'#/src/gallium/drivers/svga/include',
])
env.Append(CPPDEFINES = [
])
if env['gcc']:
env.Append(CPPDEFINES = [
'HAVE_STDINT_H',
'HAVE_SYS_TYPES_H',
])
env.Append(CFLAGS = ['-Werror'])
env.Append(CFLAGS = [
'-std=gnu99',
'-D_FILE_OFFSET_BITS=64',
])
env.Prepend(LIBPATH = [
])
env.Prepend(LIBS = [
trace,
st_xorg,
svgadrm,
svga,
auxiliaries,
])
sources = [
'vmw_xorg.c',
]
# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions
env.LoadableModule(
target ='vmwgfx_drv.so',
source = sources,
LIBS = env['LIBS'],
SHLIBPREFIX = '',
)

View file

@ -0,0 +1,150 @@
/**********************************************************
* 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.
*
**********************************************************/
/**
* @file
* Glue file for Xorg State Tracker.
*
* @author Alan Hourihane <alanh@tungstengraphics.com>
* @author Jakob Bornecrantz <wallbraker@gmail.com>
*/
#include "state_trackers/xorg/xorg_winsys.h"
static void vmw_xorg_identify(int flags);
static Bool vmw_xorg_pci_probe(DriverPtr driver,
int entity_num,
struct pci_device *device,
intptr_t match_data);
static const struct pci_id_match vmw_xorg_device_match[] = {
{0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
};
static SymTabRec vmw_xorg_chipsets[] = {
{PCI_MATCH_ANY, "VMware SVGA Device"},
{-1, NULL}
};
static PciChipsets vmw_xorg_pci_devices[] = {
{PCI_MATCH_ANY, PCI_MATCH_ANY, NULL},
{-1, -1, NULL}
};
static XF86ModuleVersionInfo vmw_xorg_version = {
"vmwgfx",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
0, 1, 0, /* major, minor, patch */
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0, 0, 0, 0}
};
/*
* Xorg driver exported structures
*/
_X_EXPORT DriverRec vmwgfx = {
1,
"vmwgfx",
vmw_xorg_identify,
NULL,
xorg_tracker_available_options,
NULL,
0,
NULL,
vmw_xorg_device_match,
vmw_xorg_pci_probe
};
static MODULESETUPPROTO(vmw_xorg_setup);
_X_EXPORT XF86ModuleData vmwgfxModuleData = {
&vmw_xorg_version,
vmw_xorg_setup,
NULL
};
/*
* Xorg driver functions
*/
static pointer
vmw_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = 0;
/* This module should be loaded only once, but check to be sure.
*/
if (!setupDone) {
setupDone = 1;
xf86AddDriver(&vmwgfx, module, HaveDriverFuncs);
/*
* The return value must be non-NULL on success even though there
* is no TearDownProc.
*/
return (pointer) 1;
} else {
if (errmaj)
*errmaj = LDR_ONCEONLY;
return NULL;
}
}
static void
vmw_xorg_identify(int flags)
{
xf86PrintChipsets("vmwgfx", "Driver for VMware SVGA device",
vmw_xorg_chipsets);
}
static Bool
vmw_xorg_pci_probe(DriverPtr driver,
int entity_num, struct pci_device *device, intptr_t match_data)
{
ScrnInfoPtr scrn = NULL;
EntityInfoPtr entity;
scrn = xf86ConfigPciEntity(scrn, 0, entity_num, vmw_xorg_pci_devices,
NULL, NULL, NULL, NULL, NULL);
if (scrn != NULL) {
scrn->driverVersion = 1;
scrn->driverName = "vmwgfx";
scrn->name = "vmwgfx";
scrn->Probe = NULL;
entity = xf86GetEntityInfo(entity_num);
/* Use all the functions from the xorg tracker */
xorg_tracker_set_functions(scrn);
}
return scrn != NULL;
}