- sync wined3d with wine HEAD

svn path=/trunk/; revision=38914
This commit is contained in:
Kamil Hornicek 2009-01-18 21:09:22 +00:00
parent c41ccd6b73
commit f1fd1b0ce1
34 changed files with 4053 additions and 3337 deletions

View file

@ -70,6 +70,7 @@ struct shader_arb_priv {
static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, const WineD3D_GL_Info *gl_info,
GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts)
{
DWORD shader_version = This->baseShader.reg_maps.shader_version;
local_constant* lconst;
DWORD i, j;
unsigned int ret;
@ -83,8 +84,8 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, con
}
}
/* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
if(target_type == GL_FRAGMENT_PROGRAM_ARB &&
WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
if (target_type == GL_FRAGMENT_PROGRAM_ARB && WINED3DSHADER_VERSION_MAJOR(shader_version) == 1)
{
float lcl_const[4];
for(i = 0; i < max_constants; i++) {
if(!dirty_consts[i]) continue;
@ -225,6 +226,28 @@ static void shader_arb_load_constants(
}
}
static void shader_arb_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
/* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
* context. On a context switch the old context will be fully dirtified */
memset(This->activeContext->vshader_const_dirty + start, 1,
sizeof(*This->activeContext->vshader_const_dirty) * count);
This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start + count + 1);
}
static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
/* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
* context. On a context switch the old context will be fully dirtified */
memset(This->activeContext->pshader_const_dirty + start, 1,
sizeof(*This->activeContext->pshader_const_dirty) * count);
This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count + 1);
}
/* Generate the variable & register declarations for the ARB_vertex_program output target */
static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info)
@ -232,7 +255,7 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
DWORD i, cur;
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
char pshader = shader_is_pshader_version(reg_maps->shader_version);
unsigned max_constantsF = min(This->baseShader.limits.constant_float,
(pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
UINT extra_constants_needed = 0;
@ -291,7 +314,7 @@ static void shader_generate_arb_declarations(IWineD3DBaseShader *iface, const sh
FIXME("No free constant to load the luminance parameters\n");
}
} else {
FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
FIXME("No free constant found to load environment bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
}
ps->numbumpenvmatconsts = cur + 1;
@ -360,9 +383,8 @@ static const char * const shift_tab[] = {
static void shader_arb_get_write_mask(const SHADER_OPCODE_ARG *arg, const DWORD param, char *write_mask)
{
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader;
char *ptr = write_mask;
char vshader = shader_is_vshader_version(This->baseShader.hex_version);
char vshader = shader_is_vshader_version(arg->reg_maps->shader_version);
if(vshader && shader_get_regtype(param) == WINED3DSPR_ADDR) {
*ptr++ = '.';
@ -488,8 +510,7 @@ static void vshader_program_add_param(const SHADER_OPCODE_ARG *arg, const DWORD
break;
case WINED3DSPR_INPUT:
if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
is_color = TRUE;
if (This->swizzle_map & (1 << reg)) is_color = TRUE;
sprintf(tmpReg, "vertex.attrib[%u]", reg);
strcat(hwLine, tmpReg);
@ -787,7 +808,6 @@ static void pshader_hw_bem(const SHADER_OPCODE_ARG *arg)
static void pshader_hw_cnd(const SHADER_OPCODE_ARG *arg)
{
IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
SHADER_BUFFER* buffer = arg->buffer;
char dst_wmask[20];
char dst_name[50];
@ -807,8 +827,8 @@ static void pshader_hw_cnd(const SHADER_OPCODE_ARG *arg)
pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[2], 2, src_name[2]);
/* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
if (shader->baseShader.hex_version <= WINED3DPS_VERSION(1, 3) &&
arg->opcode_token & WINED3DSI_COISSUE) {
if (arg->reg_maps->shader_version <= WINED3DPS_VERSION(1, 3) && arg->opcode_token & WINED3DSI_COISSUE)
{
shader_addline(buffer, "MOV%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1]);
} else {
shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", src_name[0]);
@ -877,15 +897,45 @@ static void pshader_hw_dp2add(const SHADER_OPCODE_ARG *arg)
/* Map the opcode 1-to-1 to the GL code */
static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
{
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl*)arg->shader;
CONST SHADER_OPCODE* curOpcode = arg->opcode;
SHADER_BUFFER* buffer = arg->buffer;
DWORD dst = arg->dst;
const DWORD *src = arg->src;
const char *instruction;
char arguments[256];
unsigned int i;
if (shader_is_pshader_version(shader->baseShader.hex_version))
switch (curOpcode->opcode)
{
case WINED3DSIO_ABS: instruction = "ABS"; break;
case WINED3DSIO_ADD: instruction = "ADD"; break;
case WINED3DSIO_CRS: instruction = "XPD"; break;
case WINED3DSIO_DP3: instruction = "DP3"; break;
case WINED3DSIO_DP4: instruction = "DP4"; break;
case WINED3DSIO_DST: instruction = "DST"; break;
case WINED3DSIO_EXP: instruction = "EX2"; break;
case WINED3DSIO_EXPP: instruction = "EXP"; break;
case WINED3DSIO_FRC: instruction = "FRC"; break;
case WINED3DSIO_LIT: instruction = "LIT"; break;
case WINED3DSIO_LOG: instruction = "LG2"; break;
case WINED3DSIO_LOGP: instruction = "LOG"; break;
case WINED3DSIO_LRP: instruction = "LRP"; break;
case WINED3DSIO_MAD: instruction = "MAD"; break;
case WINED3DSIO_MAX: instruction = "MAX"; break;
case WINED3DSIO_MIN: instruction = "MIN"; break;
case WINED3DSIO_MOV: instruction = "MOV"; break;
case WINED3DSIO_MUL: instruction = "MUL"; break;
case WINED3DSIO_NOP: instruction = "NOP"; break;
case WINED3DSIO_POW: instruction = "POW"; break;
case WINED3DSIO_SGE: instruction = "SGE"; break;
case WINED3DSIO_SLT: instruction = "SLT"; break;
case WINED3DSIO_SUB: instruction = "SUB"; break;
default: instruction = "";
FIXME("Unhandled opcode %s\n", curOpcode->name);
break;
}
if (shader_is_pshader_version(arg->reg_maps->shader_version))
{
/* Output token related */
char output_rname[256];
@ -938,7 +988,7 @@ static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
strcat(arguments, ", ");
strcat(arguments, operands[i]);
}
shader_addline(buffer, "%s%s %s;\n", curOpcode->glname, modifier, arguments);
shader_addline(buffer, "%s%s %s;\n", instruction, modifier, arguments);
/* A shift requires another line. */
if (shift) pshader_gen_output_modifier_line(buffer, saturate, output_wmask, shift, output_rname);
@ -955,7 +1005,7 @@ static void shader_hw_map2gl(const SHADER_OPCODE_ARG *arg)
vshader_program_add_param(arg, src[i-1], TRUE, arguments);
}
}
shader_addline(buffer, "%s%s;\n", curOpcode->glname, arguments);
shader_addline(buffer, "%s%s;\n", instruction, arguments);
}
}
@ -963,8 +1013,8 @@ static void shader_hw_mov(const SHADER_OPCODE_ARG *arg)
{
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl*)arg->shader;
if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1
&& !shader_is_pshader_version(shader->baseShader.hex_version)
if ((WINED3DSHADER_VERSION_MAJOR(arg->reg_maps->shader_version) == 1
&& !shader_is_pshader_version(arg->reg_maps->shader_version)
&& shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)
|| arg->opcode->opcode == WINED3DSIO_MOVA)
{
@ -1008,8 +1058,7 @@ static void shader_hw_mov(const SHADER_OPCODE_ARG *arg)
static void pshader_hw_texkill(const SHADER_OPCODE_ARG *arg)
{
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD hex_version = This->baseShader.hex_version;
DWORD shader_version = arg->reg_maps->shader_version;
SHADER_BUFFER* buffer = arg->buffer;
char reg_dest[40];
@ -1018,7 +1067,8 @@ static void pshader_hw_texkill(const SHADER_OPCODE_ARG *arg)
*/
pshader_get_register_name(arg->shader, arg->dst, reg_dest);
if(hex_version >= WINED3DPS_VERSION(2,0)) {
if (shader_version >= WINED3DPS_VERSION(2,0))
{
/* The arb backend doesn't claim ps 2.0 support, but try to eat what the app feeds to us */
shader_addline(buffer, "KIL %s;\n", reg_dest);
} else {
@ -1039,7 +1089,7 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
DWORD dst = arg->dst;
const DWORD *src = arg->src;
SHADER_BUFFER* buffer = arg->buffer;
DWORD hex_version = This->baseShader.hex_version;
DWORD shader_version = arg->reg_maps->shader_version;
BOOL projected = FALSE, bias = FALSE;
char reg_dest[40];
@ -1053,14 +1103,14 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
/* 1.0-1.3: Use destination register as coordinate source.
1.4+: Use provided coordinate source register. */
if (hex_version < WINED3DPS_VERSION(1,4))
if (shader_version < WINED3DPS_VERSION(1,4))
strcpy(reg_coord, reg_dest);
else
pshader_gen_input_modifier_line(arg->shader, buffer, src[0], 0, reg_coord);
/* 1.0-1.4: Use destination register number as texture code.
2.0+: Use provided sampler number as texure code. */
if (hex_version < WINED3DPS_VERSION(2,0))
if (shader_version < WINED3DPS_VERSION(2,0))
reg_sampler_code = reg_dest_code;
else
reg_sampler_code = src[1] & WINED3DSP_REGNUM_MASK;
@ -1070,7 +1120,8 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
* 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0]
* 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode
*/
if(hex_version < WINED3DPS_VERSION(1,4)) {
if (shader_version < WINED3DPS_VERSION(1,4))
{
DWORD flags = 0;
if(reg_sampler_code < MAX_TEXTURES) {
flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS];
@ -1078,7 +1129,9 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
if (flags & WINED3DTTFF_PROJECTED) {
projected = TRUE;
}
} else if(hex_version < WINED3DPS_VERSION(2,0)) {
}
else if (shader_version < WINED3DPS_VERSION(2,0))
{
DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
if (src_mod == WINED3DSPSM_DZ) {
projected = TRUE;
@ -1098,14 +1151,13 @@ static void pshader_hw_tex(const SHADER_OPCODE_ARG *arg)
static void pshader_hw_texcoord(const SHADER_OPCODE_ARG *arg)
{
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
DWORD dst = arg->dst;
SHADER_BUFFER* buffer = arg->buffer;
DWORD hex_version = This->baseShader.hex_version;
char tmp[20];
shader_arb_get_write_mask(arg, dst, tmp);
if (hex_version != WINED3DPS_VERSION(1,4)) {
if (arg->reg_maps->shader_version != WINED3DPS_VERSION(1,4))
{
DWORD reg = dst & WINED3DSP_REGNUM_MASK;
shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg);
} else {
@ -1130,8 +1182,8 @@ static void pshader_hw_texreg2ar(const SHADER_OPCODE_ARG *arg)
sprintf(dst_str, "T%u", reg1);
pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str);
shader_addline(buffer, "MOV TMP.r, %s.a;\n", src_str);
shader_addline(buffer, "MOV TMP.g, %s.r;\n", src_str);
shader_addline(buffer, "MOV TMP.x, %s.w;\n", src_str);
shader_addline(buffer, "MOV TMP.y, %s.x;\n", src_str);
flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
shader_hw_sample(arg, reg1, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE);
}
@ -1146,8 +1198,8 @@ static void pshader_hw_texreg2gb(const SHADER_OPCODE_ARG *arg)
sprintf(dst_str, "T%u", reg1);
pshader_gen_input_modifier_line(arg->shader, buffer, arg->src[0], 0, src_str);
shader_addline(buffer, "MOV TMP.r, %s.g;\n", src_str);
shader_addline(buffer, "MOV TMP.g, %s.b;\n", src_str);
shader_addline(buffer, "MOV TMP.x, %s.y;\n", src_str);
shader_addline(buffer, "MOV TMP.y, %s.z;\n", src_str);
shader_hw_sample(arg, reg1, dst_str, "TMP", FALSE, FALSE);
}
@ -1199,20 +1251,20 @@ static void pshader_hw_texbem(const SHADER_OPCODE_ARG *arg)
/* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed */
shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
shader_addline(buffer, "DP3 TMP.x, TMP2, T%u;\n", src);
shader_addline(buffer, "SWZ TMP2, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code);
shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
shader_addline(buffer, "DP3 TMP.y, TMP2, T%u;\n", src);
/* with projective textures, texbem only divides the static texture coord, not the displacement,
* so we can't let the GL handle this.
*/
if (((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]
& WINED3DTTFF_PROJECTED) {
shader_addline(buffer, "RCP TMP2.a, %s.a;\n", reg_coord);
shader_addline(buffer, "MUL TMP2.rg, %s, TMP2.a;\n", reg_coord);
shader_addline(buffer, "ADD TMP.rg, TMP, TMP2;\n");
shader_addline(buffer, "RCP TMP2.w, %s.w;\n", reg_coord);
shader_addline(buffer, "MUL TMP2.xy, %s, TMP2.w;\n", reg_coord);
shader_addline(buffer, "ADD TMP.xy, TMP, TMP2;\n");
} else {
shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord);
shader_addline(buffer, "ADD TMP.xy, TMP, %s;\n", reg_coord);
}
shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP", FALSE, FALSE);
@ -1384,15 +1436,15 @@ static void pshader_hw_texdepth(const SHADER_OPCODE_ARG *arg)
/* According to the msdn, the source register(must be r5) is unusable after
* the texdepth instruction, so we're free to modify it
*/
shader_addline(buffer, "MIN %s.g, %s.g, one.g;\n", dst_name, dst_name);
shader_addline(buffer, "MIN %s.y, %s.y, one.y;\n", dst_name, dst_name);
/* How to deal with the special case dst_name.g == 0? if r != 0, then
* the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
* result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
*/
shader_addline(buffer, "RCP %s.g, %s.g;\n", dst_name, dst_name);
shader_addline(buffer, "MUL TMP.x, %s.r, %s.g;\n", dst_name, dst_name);
shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n");
shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
shader_addline(buffer, "MUL TMP.x, %s.x, %s.y;\n", dst_name, dst_name);
shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n");
shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n");
}
@ -1474,7 +1526,7 @@ static void pshader_hw_texm3x2depth(const SHADER_OPCODE_ARG *arg)
*/
shader_addline(buffer, "RCP TMP.y, TMP.y;\n");
shader_addline(buffer, "MUL TMP.x, TMP.x, TMP.y;\n");
shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n");
shader_addline(buffer, "MIN TMP.x, TMP.x, one.x;\n");
shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n");
}
@ -1487,7 +1539,7 @@ static void shader_hw_mnxn(const SHADER_OPCODE_ARG *arg)
SHADER_OPCODE_ARG tmpArg;
IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
const SHADER_OPCODE *opcode_table = shader->baseShader.shader_ins;
DWORD shader_version = shader->baseShader.hex_version;
DWORD shader_version = arg->reg_maps->shader_version;
memset(&tmpArg, 0, sizeof(SHADER_OPCODE_ARG));
@ -1538,10 +1590,20 @@ static void vshader_hw_rsq_rcp(const SHADER_OPCODE_ARG *arg)
DWORD dst = arg->dst;
DWORD src = arg->src[0];
DWORD swizzle = (src & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
const char *instruction;
char tmpLine[256];
strcpy(tmpLine, curOpcode->glname); /* Opcode */
switch(curOpcode->opcode)
{
case WINED3DSIO_RSQ: instruction = "RSQ"; break;
case WINED3DSIO_RCP: instruction = "RCP"; break;
default: instruction = "";
FIXME("Unhandled opcode %s\n", curOpcode->name);
break;
}
strcpy(tmpLine, instruction);
vshader_program_add_param(arg, dst, FALSE, tmpLine); /* Destination */
strcat(tmpLine, ",");
vshader_program_add_param(arg, src, TRUE, tmpLine);
@ -1631,7 +1693,7 @@ static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info)
static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, enum tex_types tex_type)
{
GLuint program_id = 0;
const char *blt_fprograms[tex_type_count] =
static const char * const blt_fprograms[tex_type_count] =
{
/* tex_1d */
NULL,
@ -1777,19 +1839,12 @@ static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
}
}
static void shader_arb_cleanup(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) glDisable(GL_VERTEX_PROGRAM_ARB);
if (GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) glDisable(GL_FRAGMENT_PROGRAM_ARB);
}
static void shader_arb_destroy(IWineD3DBaseShader *iface) {
IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
char pshader = shader_is_pshader_version(baseShader->baseShader.hex_version);
if(pshader) {
if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version))
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
UINT i;
@ -1864,18 +1919,35 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
/* [0.0;1.0] clamping. Not needed, this is done implicitly */
}
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
const shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const char *fragcolor;
DWORD shader_version = reg_maps->shader_version;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
const local_constant *lconst;
GLuint retval;
const char *fragcolor;
/* Create the hw ARB shader */
shader_addline(buffer, "!!ARBfp1.0\n");
if (shader_version < WINED3DPS_VERSION(3,0)) {
switch(args->fog) {
case FOG_OFF:
break;
case FOG_LINEAR:
shader_addline(buffer, "OPTION ARB_fog_linear;\n");
break;
case FOG_EXP:
shader_addline(buffer, "OPTION ARB_fog_exp;\n");
break;
case FOG_EXP2:
shader_addline(buffer, "OPTION ARB_fog_exp2;\n");
break;
}
}
shader_addline(buffer, "TEMP TMP;\n"); /* Used in matrix ops */
shader_addline(buffer, "TEMP TMP2;\n"); /* Used in matrix ops */
shader_addline(buffer, "TEMP TA;\n"); /* Used for modifiers */
@ -1885,37 +1957,23 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
shader_addline(buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
if (shader_version < WINED3DPS_VERSION(2,0)) {
fragcolor = "R0";
} else {
shader_addline(buffer, "TEMP TMP_COLOR;\n");
fragcolor = "TMP_COLOR";
}
/* Base Declarations */
shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
/* We need two variables for fog blending */
shader_addline(buffer, "TEMP TMP_FOG;\n");
if (This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)) {
shader_addline(buffer, "TEMP TMP_COLOR;\n");
}
/* Base Shader Body */
shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function);
/* calculate fog and blend it
* NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but
* -1/(e-s) and e/(e-s) respectively.
*/
shader_addline(buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
fragcolor = "R0";
} else {
fragcolor = "TMP_COLOR";
}
if(((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
if(args->srgb_correction) {
arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB");
}
if (This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
shader_addline(buffer, "MOV result.color.a, %s.a;\n", fragcolor);
}
shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
shader_addline(buffer, "END\n");
/* TODO: change to resource.glObjectHandle or something like that */
@ -2185,8 +2243,9 @@ const shader_backend_t arb_program_shader_backend = {
shader_arb_select,
shader_arb_select_depth_blt,
shader_arb_deselect_depth_blt,
shader_arb_update_float_vertex_constants,
shader_arb_update_float_pixel_constants,
shader_arb_load_constants,
shader_arb_cleanup,
shader_arb_color_correction,
shader_arb_destroy,
shader_arb_alloc,
@ -2310,7 +2369,7 @@ static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *statebloc
* application provided constants
*/
if(device->shader_backend == &arb_program_shader_backend) {
if(use_ps(device)) return;
if (use_ps(stateblock)) return;
device = stateblock->wineD3DDevice;
device->activeContext->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
@ -2331,7 +2390,7 @@ static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateb
* application provided constants
*/
if(device->shader_backend == &arb_program_shader_backend) {
if(use_ps(device)) return;
if (use_ps(stateblock)) return;
device = stateblock->wineD3DDevice;
device->activeContext->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
@ -2351,11 +2410,12 @@ static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateb
}
static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
float mat[2][2];
if(use_ps(device)) {
if (use_ps(stateblock))
{
if(stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
/* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
@ -2385,11 +2445,12 @@ static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, W
}
static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
float param[4];
if(use_ps(device)) {
if (use_ps(stateblock))
{
if(stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
/* The pixel shader has to know the luminance offset. Do a constants update if it
@ -2481,7 +2542,7 @@ static const char *get_argreg(SHADER_BUFFER *buffer, DWORD argnum, unsigned int
if(argnum == 2) ret = "arg2";
}
if(arg & WINED3DTA_ALPHAREPLICATE) {
shader_addline(buffer, "MOV arg%u, %s.a;\n", argnum, ret);
shader_addline(buffer, "MOV arg%u, %s.w;\n", argnum, ret);
if(argnum == 0) ret = "arg0";
if(argnum == 1) ret = "arg1";
if(argnum == 2) ret = "arg2";
@ -2496,8 +2557,8 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color,
BOOL mul_final_dest = FALSE;
if(color && alpha) dstmask = "";
else if(color) dstmask = ".rgb";
else dstmask = ".a";
else if(color) dstmask = ".xyz";
else dstmask = ".w";
if(dst == tempreg) dstreg = "tempreg";
else dstreg = "ret";
@ -2508,7 +2569,7 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color,
switch(op) {
case WINED3DTOP_DISABLE:
if(stage == 1) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
if(stage == 0) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
break;
case WINED3DTOP_SELECTARG2:
@ -2553,42 +2614,42 @@ static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color,
case WINED3DTOP_BLENDCURRENTALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT);
shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDFACTORALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR);
shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDTEXTUREALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDDIFFUSEALPHA:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE);
shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
break;
case WINED3DTOP_BLENDTEXTUREALPHAPM:
arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
shader_addline(buffer, "SUB arg0.a, const.x, %s.a;\n", arg0);
shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.a, %s;\n", dstreg, dstmask, arg2, arg1);
shader_addline(buffer, "SUB arg0.w, const.x, %s.w;\n", arg0);
shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.w, %s;\n", dstreg, dstmask, arg2, arg1);
break;
/* D3DTOP_PREMODULATE ???? */
case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
shader_addline(buffer, "SUB arg0.a, const.x, %s;\n", arg1);
shader_addline(buffer, "MAD_SAT %s%s, arg0.a, %s, %s;\n", dstreg, dstmask, arg2, arg1);
shader_addline(buffer, "SUB arg0.w, const.x, %s;\n", arg1);
shader_addline(buffer, "MAD_SAT %s%s, arg0.w, %s, %s;\n", dstreg, dstmask, arg2, arg1);
break;
case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
shader_addline(buffer, "MAD_SAT %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
shader_addline(buffer, "MAD_SAT %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
break;
case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1);
shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.a;\n", dstreg, dstmask, arg2, arg1);
shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.w;\n", dstreg, dstmask, arg2, arg1);
break;
case WINED3DTOP_MODULATECOLOR_ADDALPHA:
shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.a;\n", dstreg, dstmask, arg1, arg2, arg1);
shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.w;\n", dstreg, dstmask, arg1, arg2, arg1);
break;
case WINED3DTOP_DOTPRODUCT3:
@ -2694,10 +2755,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
}
/* Shader header */
buffer.bsize = 0;
buffer.lineNo = 0;
buffer.newline = TRUE;
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
shader_buffer_init(&buffer);
shader_addline(&buffer, "!!ARBfp1.0\n");
@ -2776,20 +2834,20 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAP ||
settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) {
shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1);
shader_addline(&buffer, "DP3 ret.r, arg1, tex%u;\n", stage - 1);
shader_addline(&buffer, "DP3 ret.x, arg1, tex%u;\n", stage - 1);
shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1);
shader_addline(&buffer, "DP3 ret.g, arg1, tex%u;\n", stage - 1);
shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage - 1);
/* with projective textures, texbem only divides the static texture coord, not the displacement,
* so multiply the displacement with the dividing parameter before passing it to TXP
*/
if (settings->op[stage].projected != proj_none) {
if(settings->op[stage].projected == proj_count4) {
shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].a;\n", stage);
shader_addline(&buffer, "MUL ret.rgb, ret, fragment.texcoord[%u].a, fragment.texcoord[%u];\n", stage, stage);
shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].w;\n", stage);
shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage);
} else {
shader_addline(&buffer, "MOV ret.a, fragment.texcoord[%u].b;\n", stage);
shader_addline(&buffer, "MAD ret.rgb, ret, fragment.texcoord[%u].b, fragment.texcoord[%u];\n", stage, stage);
shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].z;\n", stage);
shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage);
}
} else {
shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage);
@ -2798,13 +2856,13 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
instr, sat, stage, stage, textype);
if(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) {
shader_addline(&buffer, "MAD_SAT ret.r, tex%u.b, luminance%u.r, luminance%u.g;\n",
shader_addline(&buffer, "MAD_SAT ret.x, tex%u.z, luminance%u.x, luminance%u.y;\n",
stage - 1, stage - 1, stage - 1);
shader_addline(&buffer, "MUL tex%u, tex%u, ret.r;\n", stage, stage);
shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n", stage, stage);
}
} else if(settings->op[stage].projected == proj_count3) {
shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage);
shader_addline(&buffer, "MOV ret.a, ret.b;\n");
shader_addline(&buffer, "MOV ret.w, ret.z;\n");
shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
instr, sat, stage, stage, textype);
} else {
@ -2814,7 +2872,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
sprintf(colorcor_dst, "tex%u", stage);
gen_color_correction(&buffer, colorcor_dst, WINED3DSP_WRITEMASK_ALL, "const.x", "const.y",
settings->op[stage].color_correction);
settings->op[stage].color_fixup);
}
/* Generate the main shader */
@ -2850,7 +2908,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
settings->op[stage].cop, settings->op[stage].carg0,
settings->op[stage].carg1, settings->op[stage].carg2);
if(stage == 0) {
shader_addline(&buffer, "MOV ret.a, fragment.color.primary.a;\n");
shader_addline(&buffer, "MOV ret.w, fragment.color.primary.w;\n");
}
} else if(op_equal) {
gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst,
@ -2869,7 +2927,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
if(settings->sRGB_write) {
shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg");
shader_addline(&buffer, "MOV result.color.a, ret.a;\n");
shader_addline(&buffer, "MOV result.color.w, ret.w;\n");
} else {
shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
}
@ -2888,15 +2946,15 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWi
FIXME("Fragment program error at position %d: %s\n", pos,
debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
}
HeapFree(GetProcessHeap(), 0, buffer.buffer);
shader_buffer_free(&buffer);
return ret;
}
static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
struct shader_arb_priv *priv = (struct shader_arb_priv *) device->fragment_priv;
BOOL use_pshader = use_ps(device);
BOOL use_vshader = use_vs(device);
BOOL use_pshader = use_ps(stateblock);
BOOL use_vshader = use_vs(stateblock);
struct ffp_frag_settings settings;
const struct arbfp_ffp_desc *desc;
unsigned int i;
@ -2909,6 +2967,8 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
}
state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context);
state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context);
} else if(use_pshader && !isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
}
return;
}
@ -2983,9 +3043,36 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock,
* fragment_prog_arbfp function being called because FOGENABLE is dirty, which calls this function here
*/
static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
enum fogsource new_source;
if(!isStateDirty(context, STATE_PIXELSHADER)) {
fragment_prog_arbfp(state, stateblock, context);
}
if(!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
if(use_vs(stateblock)
&& ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
FIXME("vertex shader with table fog used\n");
}
context->last_was_foggy_shader = TRUE;
new_source = FOGSOURCE_VS;
} else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
context->last_was_foggy_shader = FALSE;
if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
new_source = FOGSOURCE_COORD;
} else {
new_source = FOGSOURCE_FFP;
}
} else {
context->last_was_foggy_shader = FALSE;
new_source = FOGSOURCE_FFP;
}
if(new_source != context->fog_source) {
context->fog_source = new_source;
state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
}
}
static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
@ -3130,7 +3217,11 @@ static const struct StateEntryTemplate arbfp_fragmentstate_template[] = {
{ STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 },
{ STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 },
{ STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 },
{ STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{ STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 },
{ STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
{ STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
@ -3191,11 +3282,11 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
const char *tex, *texinstr;
if (yuv_fixup == YUV_FIXUP_UYVY) {
chroma = 'r';
*luminance = 'a';
chroma = 'x';
*luminance = 'w';
} else {
chroma = 'a';
*luminance = 'r';
chroma = 'w';
*luminance = 'x';
}
switch(textype) {
case GL_TEXTURE_2D: tex = "2D"; texinstr = "TXP"; break;
@ -3221,8 +3312,8 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
* So we have to get the sampling x position in non-normalized coordinates in integers
*/
if(textype != GL_TEXTURE_RECTANGLE_ARB) {
shader_addline(buffer, "MUL texcrd.rg, fragment.texcoord[0], size.x;\n");
shader_addline(buffer, "MOV texcrd.a, size.x;\n");
shader_addline(buffer, "MUL texcrd.xy, fragment.texcoord[0], size.x;\n");
shader_addline(buffer, "MOV texcrd.w, size.x;\n");
} else {
shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
}
@ -3244,9 +3335,9 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
/* Put the value into either of the chroma values */
shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
shader_addline(buffer, "MUL chroma.r, luminance.%c, temp.x;\n", chroma);
shader_addline(buffer, "MUL chroma.x, luminance.%c, temp.x;\n", chroma);
shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
shader_addline(buffer, "MUL chroma.g, luminance.%c, temp.x;\n", chroma);
shader_addline(buffer, "MUL chroma.y, luminance.%c, temp.x;\n", chroma);
/* Sample pixel 2. If we read an even pixel(SLT above returned 1), sample
* the pixel right to the current one. Otherwise, sample the left pixel.
@ -3258,9 +3349,9 @@ static BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, enum yuv_fixup yuv_fixup,
/* Put the value into the other chroma */
shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
shader_addline(buffer, "MAD chroma.g, luminance.%c, temp.x, chroma.g;\n", chroma);
shader_addline(buffer, "MAD chroma.y, luminance.%c, temp.x, chroma.y;\n", chroma);
shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
shader_addline(buffer, "MAD chroma.r, luminance.%c, temp.x, chroma.r;\n", chroma);
shader_addline(buffer, "MAD chroma.x, luminance.%c, temp.x, chroma.x;\n", chroma);
/* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of
* the current one and lerp the two U and V values
@ -3380,7 +3471,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance
}
/* Read the texture, put the result into the output register */
shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
shader_addline(buffer, "MOV chroma.r, temp.a;\n");
shader_addline(buffer, "MOV chroma.x, temp.w;\n");
/* The other chroma value is 1/6th of the texture lower, from 5/6th to 6/6th
* No need to clamp because we're just reusing the already clamped value from above
@ -3391,7 +3482,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance
shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, texcrd.y;\n");
}
shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
shader_addline(buffer, "MOV chroma.g, temp.a;\n");
shader_addline(buffer, "MOV chroma.y, temp.w;\n");
/* Sample the luminance value. It is in the top 2/3rd of the texture, so scale the y coordinate.
* Clamp the y coordinate to prevent the chroma values from bleeding into the sampled luminance
@ -3405,7 +3496,7 @@ static BOOL gen_yv12_read(SHADER_BUFFER *buffer, GLenum textype, char *luminance
shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
} else {
/* Reading from texture_rectangles is pretty streightforward, just use the unmodified
/* Reading from texture_rectangles is pretty straightforward, just use the unmodified
* texture coordinate. It is still a good idea to clamp it though, since the opengl texture
* is bigger
*/
@ -3426,10 +3517,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
struct arbfp_blit_priv *priv = (struct arbfp_blit_priv *) device->blit_priv;
/* Shader header */
buffer.bsize = 0;
buffer.lineNo = 0;
buffer.newline = TRUE;
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
shader_buffer_init(&buffer);
ENTER_GL();
GL_EXTCALL(glGenProgramsARB(1, &shader));
@ -3438,7 +3526,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
LEAVE_GL();
if(!shader) {
HeapFree(GetProcessHeap(), 0, buffer.buffer);
shader_buffer_free(&buffer);
return 0;
}
@ -3452,7 +3540,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
* contains the luminance and alpha the chroma. With UYVY it is vice versa. Thus
* take the format into account when generating the read swizzles
*
* Reading the Y value is streightforward - just sample the texture. The hardware
* Reading the Y value is straightforward - just sample the texture. The hardware
* takes care of filtering in the horizontal and vertical direction.
*
* Reading the U and V values is harder. We have to avoid filtering horizontally,
@ -3493,7 +3581,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
case YUV_FIXUP_YUY2:
if (!gen_planar_yuv_read(&buffer, yuv_fixup, textype, &luminance_component))
{
HeapFree(GetProcessHeap(), 0, buffer.buffer);
shader_buffer_free(&buffer);
return 0;
}
break;
@ -3501,14 +3589,14 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
case YUV_FIXUP_YV12:
if (!gen_yv12_read(&buffer, textype, &luminance_component))
{
HeapFree(GetProcessHeap(), 0, buffer.buffer);
shader_buffer_free(&buffer);
return 0;
}
break;
default:
FIXME("Unsupported YUV fixup %#x\n", yuv_fixup);
HeapFree(GetProcessHeap(), 0, buffer.buffer);
shader_buffer_free(&buffer);
return 0;
}
@ -3516,12 +3604,12 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
* http://www.fourcc.org/fccyvrgb.php. Note that the chroma
* ranges from -0.5 to 0.5
*/
shader_addline(&buffer, "SUB chroma.rg, chroma, coef.y;\n");
shader_addline(&buffer, "SUB chroma.xy, chroma, coef.y;\n");
shader_addline(&buffer, "MAD result.color.r, chroma.r, yuv_coef.x, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "MAD temp.r, -chroma.g, yuv_coef.y, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "MAD result.color.g, -chroma.r, yuv_coef.z, temp.r;\n");
shader_addline(&buffer, "MAD result.color.b, chroma.g, yuv_coef.w, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "MAD result.color.x, chroma.x, yuv_coef.x, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "MAD temp.x, -chroma.y, yuv_coef.y, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "MAD result.color.y, -chroma.x, yuv_coef.z, temp.x;\n");
shader_addline(&buffer, "MAD result.color.z, chroma.y, yuv_coef.w, luminance.%c;\n", luminance_component);
shader_addline(&buffer, "END\n");
ENTER_GL();
@ -3533,7 +3621,7 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum yuv_fixup yuv_fixu
FIXME("Fragment program error at position %d: %s\n", pos,
debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
}
HeapFree(GetProcessHeap(), 0, buffer.buffer);
shader_buffer_free(&buffer);
LEAVE_GL();
switch (yuv_fixup)

View file

@ -159,7 +159,96 @@ static const char *debug_rep(GLuint rep) {
}
}
static const char *debug_op(GLuint op) {
switch(op) {
case GL_MOV_ATI: return "GL_MOV_ATI";
case GL_ADD_ATI: return "GL_ADD_ATI";
case GL_MUL_ATI: return "GL_MUL_ATI";
case GL_SUB_ATI: return "GL_SUB_ATI";
case GL_DOT3_ATI: return "GL_DOT3_ATI";
case GL_DOT4_ATI: return "GL_DOT4_ATI";
case GL_MAD_ATI: return "GL_MAD_ATI";
case GL_LERP_ATI: return "GL_LERP_ATI";
case GL_CND_ATI: return "GL_CND_ATI";
case GL_CND0_ATI: return "GL_CND0_ATI";
case GL_DOT2_ADD_ATI: return "GL_DOT2_ADD_ATI";
default: return "unexpected op";
}
}
static const char *debug_mask(GLuint mask) {
switch(mask) {
case GL_NONE: return "GL_NONE";
case GL_RED_BIT_ATI: return "GL_RED_BIT_ATI";
case GL_GREEN_BIT_ATI: return "GL_GREEN_BIT_ATI";
case GL_BLUE_BIT_ATI: return "GL_BLUE_BIT_ATI";
case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI";
case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI: return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI";
case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
default: return "Unexpected writemask";
}
}
#define GLINFO_LOCATION (*gl_info)
static void wrap_op1(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
if(dstMask == GL_ALPHA) {
TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod));
} else {
TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
debug_mask(dstMask), debug_dstmod(dstMod),
debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
}
}
static void wrap_op2(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
GLuint arg1, GLuint arg1Rep, GLuint arg1Mod,
GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
if(dstMask == GL_ALPHA) {
TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
} else {
TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
debug_mask(dstMask), debug_dstmod(dstMod),
debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
}
}
static void wrap_op3(const WineD3D_GL_Info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
GLuint arg1, GLuint arg1Rep, GLuint arg1Mod,
GLuint arg2, GLuint arg2Rep, GLuint arg2Mod,
GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
if(dstMask == GL_ALPHA) {
/* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */
TRACE("glAlphaFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod,
arg1, arg1Rep, arg1Mod,
arg2, arg2Rep, arg2Mod,
arg3, arg3Rep, arg3Mod));
} else {
TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
debug_mask(dstMask), debug_dstmod(dstMod),
debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod,
arg1, arg1Rep, arg1Mod,
arg2, arg2Rep, arg2Mod,
arg3, arg3Rep, arg3Mod));
}
}
static GLuint register_for_arg(DWORD arg, const WineD3D_GL_Info *gl_info,
unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
{
@ -351,6 +440,7 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
if(op[stage].cop != WINED3DTOP_BUMPENVMAP &&
op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue;
fixup = op[stage].color_fixup;
if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
{
FIXME("Swizzles not implemented\n");
@ -364,12 +454,10 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
}
TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_RED_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, ATI_FFP_CONST_BUMPMAT(%d), GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_RED, GL_NONE)\n",
stage + 1, stage, debug_argmod(argmodextra_x), stage, stage + 1);
GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE));
wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
/* FIXME: How can I make GL_DOT2_ADD_ATI read the factors from blue and alpha? It defaults to red and green,
* and it is fairly easy to make it read GL_BLUE or BL_ALPHA, but I can't get an R * B + G * A. So we're wasting
@ -379,18 +467,14 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
* NOTE: GL_BLUE | GL_ALPHA is not possible. It doesn't throw a compilation error, but an OR operation on the
* constants doesn't make sense, considering their values.
*/
TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_BLUE, GL_NONE)\n", stage);
GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE));
TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_ALPHA, GL_NONE)\n", stage);
GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE));
TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_GREEN_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, GL_REG_5_ATI, GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_GREEN, GL_NONE)\n",
stage + 1, stage, debug_argmod(argmodextra_y), stage + 1);
GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
GL_REG_0_ATI + stage, GL_NONE, argmodextra_y,
GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE));
wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE);
wrap_op1(gl_info, GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE);
wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
GL_REG_0_ATI + stage, GL_NONE, argmodextra_y,
GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
}
/* Pass 3: Generate sampling instructions for regular textures */
@ -438,12 +522,10 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
if(op[stage].cop == WINED3DTOP_DISABLE) {
if(stage == 0) {
/* Handle complete texture disabling gracefully */
TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
}
break;
}
@ -472,10 +554,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
argmod1 = argmod2;
rep1 = rep2;
case WINED3DTOP_SELECTARG1:
TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s)\n",
debug_register(dstreg), debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
arg1, rep1, argmod1));
wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
arg1, rep1, argmod1);
break;
case WINED3DTOP_MODULATE4X:
@ -484,13 +564,9 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
dstmod |= GL_SATURATE_BIT_ATI;
case WINED3DTOP_MODULATE:
TRACE("glColorFragmentOp2ATI(GL_MUL_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg), debug_dstmod(dstmod),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
GL_EXTCALL(glColorFragmentOp2ATI(GL_MUL_ATI, dstreg, GL_NONE, dstmod,
arg1, rep1, argmod1,
arg2, rep2, argmod2));
wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
arg1, rep1, argmod1,
arg2, rep2, argmod2);
break;
case WINED3DTOP_ADDSIGNED2X:
@ -499,40 +575,27 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
argmodextra = GL_BIAS_BIT_ATI;
case WINED3DTOP_ADD:
dstmod |= GL_SATURATE_BIT_ATI;
TRACE("glColorFragmentOp2ATI(GL_ADD_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg), debug_dstmod(dstmod),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmodextra | argmod2));
GL_EXTCALL(glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
arg1, rep1, argmod1,
arg2, rep2, argmodextra | argmod2));
wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
arg1, rep1, argmod1,
arg2, rep2, argmodextra | argmod2);
break;
case WINED3DTOP_SUBTRACT:
dstmod |= GL_SATURATE_BIT_ATI;
TRACE("glColorFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg), debug_dstmod(dstmod),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
GL_EXTCALL(glColorFragmentOp2ATI(GL_SUB_ATI, dstreg, GL_NONE, dstmod,
arg1, rep1, argmod1,
arg2, rep2, argmod2));
wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
arg1, rep1, argmod1,
arg2, rep2, argmod2);
break;
case WINED3DTOP_ADDSMOOTH:
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
/* Dst = arg1 + * arg2(1 -arg 1)
* = arg2 * (1 - arg1) + arg1
*/
GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg2, rep2, argmod2,
arg1, rep1, argmodextra,
arg1, rep1, argmod1));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg2, rep2, argmod2,
arg1, rep1, argmodextra,
arg1, rep1, argmod1);
break;
case WINED3DTOP_BLENDCURRENTALPHA:
@ -543,28 +606,18 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
case WINED3DTOP_BLENDDIFFUSEALPHA:
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(extrarg),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2));
GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
extrarg, GL_ALPHA, GL_NONE,
arg1, rep1, argmod1,
arg2, rep2, argmod2));
wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
extrarg, GL_ALPHA, GL_NONE,
arg1, rep1, argmod1,
arg2, rep2, argmod2);
break;
case WINED3DTOP_BLENDTEXTUREALPHAPM:
arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
debug_register(arg0),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1));
GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
arg2, rep2, argmod2,
arg0, GL_ALPHA, GL_COMP_BIT_ATI,
arg1, rep1, argmod1));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
arg2, rep2, argmod2,
arg0, GL_ALPHA, GL_COMP_BIT_ATI,
arg1, rep1, argmod1);
break;
/* D3DTOP_PREMODULATE ???? */
@ -573,63 +626,40 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
if(!argmodextra) argmodextra = argmod1;
TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, GL_ALPHA, %s, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_rep(rep1), debug_argmod(arg1));
GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg2, rep2, argmod2,
arg1, GL_ALPHA, argmodextra,
arg1, rep1, argmod1));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg2, rep2, argmod2,
arg1, GL_ALPHA, argmodextra,
arg1, rep1, argmod1);
break;
case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
case WINED3DTOP_MODULATECOLOR_ADDALPHA:
if(!argmodextra) argmodextra = argmod1;
TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, GL_ALPHA, %s)\n",
debug_register(dstreg),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmodextra),
debug_register(arg1), debug_argmod(argmod1));
GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg2, rep2, argmod2,
arg1, rep1, argmodextra,
arg1, GL_ALPHA, argmod1));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg2, rep2, argmod2,
arg1, rep1, argmodextra,
arg1, GL_ALPHA, argmod1);
break;
case WINED3DTOP_DOTPRODUCT3:
TRACE("glColorFragmentOp2ATI(GL_DOT3_ATI, %s, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
GL_EXTCALL(glColorFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
arg2, rep2, argmod2 | GL_BIAS_BIT_ATI));
wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
break;
case WINED3DTOP_MULTIPLYADD:
TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, GL_SATURATE_BIT_ATI, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0));
GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg1, rep1, argmod1,
arg2, rep2, argmod2,
arg0, rep0, argmod0));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
arg1, rep1, argmod1,
arg2, rep2, argmod2,
arg0, rep0, argmod0);
break;
case WINED3DTOP_LERP:
TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, GL_NONE, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_rep(rep1), debug_argmod(argmod1),
debug_register(arg2), debug_rep(rep2), debug_argmod(argmod2),
debug_register(arg0), debug_rep(rep0), debug_argmod(argmod0));
GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
arg0, rep0, argmod0,
arg1, rep1, argmod1,
arg2, rep2, argmod2));
wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
arg0, rep0, argmod0,
arg1, rep1, argmod1,
arg2, rep2, argmod2);
break;
case WINED3DTOP_BUMPENVMAP:
@ -651,9 +681,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
case WINED3DTOP_DISABLE:
/* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
if(stage == 0) {
TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
}
break;
@ -661,11 +690,8 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
arg1 = arg2;
argmod1 = argmod2;
case WINED3DTOP_SELECTARG1:
TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, %s, GL_NONE, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_argmod(argmod1));
GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, dstreg, GL_NONE,
arg1, GL_NONE, argmod1));
wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
arg1, GL_NONE, argmod1);
break;
case WINED3DTOP_MODULATE4X:
@ -674,13 +700,9 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
dstmod |= GL_SATURATE_BIT_ATI;
case WINED3DTOP_MODULATE:
TRACE("glAlphaFragmentOp2ATI(GL_MUL_ATI, %s, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg), debug_dstmod(dstmod),
debug_register(arg1), debug_argmod(argmod1),
debug_register(arg2), debug_argmod(argmod2));
GL_EXTCALL(glAlphaFragmentOp2ATI(GL_MUL_ATI, dstreg, dstmod,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2));
wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2);
break;
case WINED3DTOP_ADDSIGNED2X:
@ -689,40 +711,27 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
argmodextra = GL_BIAS_BIT_ATI;
case WINED3DTOP_ADD:
dstmod |= GL_SATURATE_BIT_ATI;
TRACE("glAlphaFragmentOp2ATI(GL_ADD_ATI, %s, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg), debug_dstmod(dstmod),
debug_register(arg1), debug_argmod(argmod1),
debug_register(arg2), debug_argmod(argmodextra | argmod2));
GL_EXTCALL(glAlphaFragmentOp2ATI(GL_ADD_ATI, dstreg, dstmod,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmodextra | argmod2));
wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmodextra | argmod2);
break;
case WINED3DTOP_SUBTRACT:
dstmod |= GL_SATURATE_BIT_ATI;
TRACE("glAlphaFragmentOp2ATI(GL_SUB_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg), debug_dstmod(dstmod),
debug_register(arg1), debug_argmod(argmod1),
debug_register(arg2), debug_argmod(argmod2));
GL_EXTCALL(glAlphaFragmentOp2ATI(GL_SUB_ATI, dstreg, dstmod,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2));
wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2);
break;
case WINED3DTOP_ADDSMOOTH:
argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(arg2), debug_argmod(argmod2),
debug_register(arg1), debug_argmod(argmodextra),
debug_register(arg1), debug_argmod(argmod1));
/* Dst = arg1 + * arg2(1 -arg 1)
* = arg2 * (1 - arg1) + arg1
*/
GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI,
arg2, GL_NONE, argmod2,
arg1, GL_NONE, argmodextra,
arg1, GL_NONE, argmod1));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
arg2, GL_NONE, argmod2,
arg1, GL_NONE, argmodextra,
arg1, GL_NONE, argmod1);
break;
case WINED3DTOP_BLENDCURRENTALPHA:
@ -733,64 +742,40 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
case WINED3DTOP_BLENDDIFFUSEALPHA:
if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(extrarg),
debug_register(arg1), debug_argmod(argmod1),
debug_register(arg2), debug_argmod(argmod2));
GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_NONE,
extrarg, GL_ALPHA, GL_NONE,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2));
wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
extrarg, GL_ALPHA, GL_NONE,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2);
break;
case WINED3DTOP_BLENDTEXTUREALPHAPM:
arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(arg2), debug_argmod(argmod2),
debug_register(arg0),
debug_register(arg1), debug_argmod(argmod1));
GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_NONE,
arg2, GL_NONE, argmod2,
arg0, GL_ALPHA, GL_COMP_BIT_ATI,
arg1, GL_NONE, argmod1));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
arg2, GL_NONE, argmod2,
arg0, GL_ALPHA, GL_COMP_BIT_ATI,
arg1, GL_NONE, argmod1);
break;
/* D3DTOP_PREMODULATE ???? */
case WINED3DTOP_DOTPRODUCT3:
TRACE("glAlphaFragmentOp2ATI(GL_DOT3_ATI, %s, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI),
debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
GL_EXTCALL(glAlphaFragmentOp2ATI(GL_DOT3_ATI, dstreg, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_ALPHA, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
break;
case WINED3DTOP_MULTIPLYADD:
TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_argmod(argmod1),
debug_register(arg2), debug_argmod(argmod2),
debug_register(arg0), debug_argmod(argmod0));
GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, dstreg, GL_SATURATE_BIT_ATI,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2,
arg0, GL_NONE, argmod0));
wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2,
arg0, GL_NONE, argmod0);
break;
case WINED3DTOP_LERP:
TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, %s, GL_SATURATE_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
debug_register(dstreg),
debug_register(arg1), debug_argmod(argmod1),
debug_register(arg2), debug_argmod(argmod2),
debug_register(arg0), debug_argmod(argmod0));
GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, dstreg, GL_SATURATE_BIT_ATI,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2,
arg0, GL_NONE, argmod0));
wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
arg1, GL_NONE, argmod1,
arg2, GL_NONE, argmod2,
arg0, GL_NONE, argmod0);
break;
case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
@ -868,7 +853,7 @@ static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *statebloc
}
static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
float mat[2][2];
mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
@ -896,10 +881,41 @@ static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3
}
}
static void atifs_apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
BOOL use_vshader = use_vs(stateblock);
/* The ATIFS code does not support pixel shaders currently, but we have to provide a state handler
* to call shader_select to select a vertex shader if one is applied because the vertex shader state
* may defer calling the shader backend if the pshader state is dirty.
*
* In theory the application should not be able to mark the pixel shader dirty because it cannot
* create a shader, and thus has no way to set the state to something != NULL. However, a different
* pipeline part may link a different state to its pixelshader handler, thus a pshader state exists
* and can be dirtified. Also the pshader is always dirtified at startup, and blitting disables all
* shaders and dirtifies all shader states. If atifs can deal with this it keeps the rest of the code
* simpler.
*/
if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, use_vshader);
if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) {
device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context);
}
}
}
#undef GLINFO_LOCATION
static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
{STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_atifs }, 0 },
{STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
{STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
{STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
{STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
{STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
{STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 },
{STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 },
{STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), set_tex_op_atifs }, 0 },
@ -1020,6 +1036,7 @@ static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform }, 0 },
{STATE_PIXELSHADER, { STATE_PIXELSHADER, atifs_apply_pixelshader }, 0 },
{0 /* Terminate */, { 0, 0 }, 0 },
};

View file

@ -40,6 +40,20 @@ static inline BOOL shader_is_version_token(DWORD token) {
shader_is_vshader_version(token);
}
void shader_buffer_init(struct SHADER_BUFFER *buffer)
{
buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
buffer->buffer[0] = '\0';
buffer->bsize = 0;
buffer->lineNo = 0;
buffer->newline = TRUE;
}
void shader_buffer_free(struct SHADER_BUFFER *buffer)
{
HeapFree(GetProcessHeap(), 0, buffer->buffer);
}
int shader_addline(
SHADER_BUFFER* buffer,
const char *format, ...) {
@ -76,6 +90,15 @@ int shader_addline(
return 0;
}
void shader_init(struct IWineD3DBaseShaderClass *shader,
IWineD3DDevice *device, const SHADER_OPCODE *instruction_table)
{
shader->ref = 1;
shader->device = device;
shader->shader_ins = instruction_table;
list_init(&shader->linked_programs);
}
const SHADER_OPCODE *shader_get_opcode(const SHADER_OPCODE *opcode_table, DWORD shader_version, DWORD code)
{
DWORD i = 0;
@ -117,17 +140,12 @@ static int shader_get_param(const DWORD *pToken, DWORD shader_version, DWORD *pa
}
/* Return the number of parameters to skip for an opcode */
static inline int shader_skip_opcode(
IWineD3DBaseShaderImpl* This,
const SHADER_OPCODE* curOpcode,
DWORD opcode_token) {
static inline int shader_skip_opcode(const SHADER_OPCODE *curOpcode, DWORD opcode_token, DWORD shader_version)
{
/* Shaders >= 2.0 may contain address tokens, but fortunately they
* have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
return (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)?
((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT):
curOpcode->num_params;
return (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : curOpcode->num_params;
}
/* Read the parameters of an unrecognized opcode from the input stream
@ -192,28 +210,21 @@ static void shader_delete_constant_list(struct list* clist) {
/* Note that this does not count the loop register
* as an address register. */
HRESULT shader_get_registers_used(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
semantic* semantics_in,
semantic* semantics_out,
CONST DWORD* pToken,
IWineD3DStateBlockImpl *stateBlock) {
HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_maps *reg_maps,
struct semantic *semantics_in, struct semantic *semantics_out, const DWORD *byte_code)
{
IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
DWORD shader_version = This->baseShader.hex_version;
DWORD shader_version;
unsigned int cur_loop_depth = 0, max_loop_depth = 0;
const DWORD* pToken = byte_code;
char pshader;
/* There are some minor differences between pixel and vertex shaders */
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
memset(reg_maps->bumpmat, 0, sizeof(reg_maps->bumpmat));
memset(reg_maps->luminanceparams, 0, sizeof(reg_maps->luminanceparams));
if (pToken == NULL)
return WINED3D_OK;
/* get_registers_used is called on every compile on some 1.x shaders, which can result
* in stacking up a collection of local constants. Delete the old constants if existing
*/
@ -221,17 +232,22 @@ HRESULT shader_get_registers_used(
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
/* The version token is supposed to be the first token */
if (!shader_is_version_token(*pToken))
{
FIXME("First token is not a version token, invalid shader.\n");
return WINED3DERR_INVALIDCALL;
}
reg_maps->shader_version = shader_version = *pToken++;
pshader = shader_is_pshader_version(shader_version);
while (WINED3DVS_END() != *pToken) {
CONST SHADER_OPCODE* curOpcode;
DWORD opcode_token;
/* Skip version */
if (shader_is_version_token(*pToken)) {
++pToken;
continue;
/* Skip comments */
} else if (shader_is_comment(*pToken)) {
if (shader_is_comment(*pToken))
{
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken;
pToken += comment_len;
@ -287,7 +303,8 @@ HRESULT shader_get_registers_used(
memcpy(lconst->value, pToken + 1, 4 * sizeof(DWORD));
/* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && pshader) {
if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1 && pshader)
{
float *value = (float *) lconst->value;
if(value[0] < -1.0) value[0] = -1.0;
else if(value[0] > 1.0) value[0] = 1.0;
@ -328,6 +345,8 @@ HRESULT shader_get_registers_used(
max_loop_depth = cur_loop_depth;
pToken += curOpcode->num_params;
/* Rep and Loop always use an integer constant for the control parameters */
This->baseShader.uses_int_consts = TRUE;
} else if (WINED3DSIO_ENDLOOP == curOpcode->opcode ||
WINED3DSIO_ENDREP == curOpcode->opcode) {
cur_loop_depth--;
@ -344,50 +363,25 @@ HRESULT shader_get_registers_used(
int i, limit;
/* Declare 1.X samplers implicitly, based on the destination reg. number */
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 &&
pshader /* Filter different instructions with the same enum values in VS */ &&
(WINED3DSIO_TEX == curOpcode->opcode ||
WINED3DSIO_TEXBEM == curOpcode->opcode ||
WINED3DSIO_TEXBEML == curOpcode->opcode ||
WINED3DSIO_TEXDP3TEX == curOpcode->opcode ||
WINED3DSIO_TEXM3x2TEX == curOpcode->opcode ||
WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode ||
WINED3DSIO_TEXM3x3TEX == curOpcode->opcode ||
WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode ||
WINED3DSIO_TEXREG2AR == curOpcode->opcode ||
WINED3DSIO_TEXREG2GB == curOpcode->opcode ||
WINED3DSIO_TEXREG2RGB == curOpcode->opcode)) {
if (WINED3DSHADER_VERSION_MAJOR(shader_version) == 1
&& pshader /* Filter different instructions with the same enum values in VS */
&& (WINED3DSIO_TEX == curOpcode->opcode
|| WINED3DSIO_TEXBEM == curOpcode->opcode
|| WINED3DSIO_TEXBEML == curOpcode->opcode
|| WINED3DSIO_TEXDP3TEX == curOpcode->opcode
|| WINED3DSIO_TEXM3x2TEX == curOpcode->opcode
|| WINED3DSIO_TEXM3x3SPEC == curOpcode->opcode
|| WINED3DSIO_TEXM3x3TEX == curOpcode->opcode
|| WINED3DSIO_TEXM3x3VSPEC == curOpcode->opcode
|| WINED3DSIO_TEXREG2AR == curOpcode->opcode
|| WINED3DSIO_TEXREG2GB == curOpcode->opcode
|| WINED3DSIO_TEXREG2RGB == curOpcode->opcode))
{
/* Fake sampler usage, only set reserved bit and ttype */
DWORD sampler_code = *pToken & WINED3DSP_REGNUM_MASK;
if(!stateBlock->textures[sampler_code]) {
ERR("No texture bound to sampler %d\n", sampler_code);
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
} else {
int texType = IWineD3DBaseTexture_GetTextureDimensions(stateBlock->textures[sampler_code]);
switch(texType) {
/* We have to select between texture rectangles and 2D textures later because 2.0 and
* 3.0 shaders only have WINED3DSTT_2D as well
*/
case GL_TEXTURE_RECTANGLE_ARB:
case GL_TEXTURE_2D:
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
break;
case GL_TEXTURE_3D:
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_VOLUME;
break;
case GL_TEXTURE_CUBE_MAP_ARB:
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_CUBE;
break;
default:
ERR("Unexpected gl texture type found: %d\n", texType);
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
}
}
TRACE("Setting fake 2D sampler for 1.x pixelshader\n");
reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D;
/* texbem is only valid with < 1.4 pixel shaders */
if(WINED3DSIO_TEXBEM == curOpcode->opcode ||
@ -473,20 +467,30 @@ HRESULT shader_get_registers_used(
reg_maps->usesrelconstF = TRUE;
}
}
else if(WINED3DSPR_CONSTINT == regtype) {
This->baseShader.uses_int_consts = TRUE;
}
else if(WINED3DSPR_CONSTBOOL == regtype) {
This->baseShader.uses_bool_consts = TRUE;
}
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
* in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
* isn't used in them, but future register types might cause issues
*/
else if(WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */ &&
!pshader && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) < 3) {
else if (WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */
&& !pshader && WINED3DSHADER_VERSION_MAJOR(shader_version) < 3)
{
reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
}
}
}
}
++pToken;
reg_maps->loop_depth = max_loop_depth;
This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
return WINED3D_OK;
}
@ -593,7 +597,7 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
{
static const char * const rastout_reg_names[] = { "oPos", "oFog", "oPts" };
static const char * const misctype_reg_names[] = { "vPos", "vFace"};
char swizzle_reg_chars[4];
const char *swizzle_reg_chars = "xyzw";
DWORD reg = param & WINED3DSP_REGNUM_MASK;
DWORD regtype = shader_get_regtype(param);
@ -602,14 +606,6 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
/* There are some minor differences between pixel and vertex shaders */
char pshader = shader_is_pshader_version(shader_version);
/* For one, we'd prefer color components to be shown for pshaders.
* FIXME: use the swizzle function for this */
swizzle_reg_chars[0] = pshader? 'r': 'x';
swizzle_reg_chars[1] = pshader? 'g': 'y';
swizzle_reg_chars[2] = pshader? 'b': 'z';
swizzle_reg_chars[3] = pshader? 'a': 'w';
if (input) {
if ( (modifier == WINED3DSPSM_NEG) ||
(modifier == WINED3DSPSM_BIASNEG) ||
@ -714,10 +710,10 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
} else {
/** operand input */
DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
DWORD swizzle_r = swizzle & 0x03;
DWORD swizzle_g = (swizzle >> 2) & 0x03;
DWORD swizzle_b = (swizzle >> 4) & 0x03;
DWORD swizzle_a = (swizzle >> 6) & 0x03;
DWORD swizzle_x = swizzle & 0x03;
DWORD swizzle_y = (swizzle >> 2) & 0x03;
DWORD swizzle_z = (swizzle >> 4) & 0x03;
DWORD swizzle_w = (swizzle >> 6) & 0x03;
if (0 != modifier) {
switch (modifier) {
@ -745,25 +741,24 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
* RRGGBBAA
*/
if ((WINED3DVS_NOSWIZZLE >> WINED3DVS_SWIZZLE_SHIFT) != swizzle) {
if (swizzle_r == swizzle_g &&
swizzle_r == swizzle_b &&
swizzle_r == swizzle_a) {
TRACE(".%c", swizzle_reg_chars[swizzle_r]);
if (swizzle_x == swizzle_y &&
swizzle_x == swizzle_z &&
swizzle_x == swizzle_w) {
TRACE(".%c", swizzle_reg_chars[swizzle_x]);
} else {
TRACE(".%c%c%c%c",
swizzle_reg_chars[swizzle_r],
swizzle_reg_chars[swizzle_g],
swizzle_reg_chars[swizzle_b],
swizzle_reg_chars[swizzle_a]);
swizzle_reg_chars[swizzle_x],
swizzle_reg_chars[swizzle_y],
swizzle_reg_chars[swizzle_z],
swizzle_reg_chars[swizzle_w]);
}
}
}
}
static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg)
IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg, DWORD shader_version)
{
DWORD hex_version = shader->baseShader.hex_version;
IWineD3DBaseTextureImpl *texture;
struct color_fixup_desc fixup;
BOOL recorded = FALSE;
@ -773,7 +768,7 @@ static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
switch(arg->opcode->opcode)
{
case WINED3DSIO_TEX:
if (hex_version < WINED3DPS_VERSION(2,0)) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
if (WINED3DSHADER_VERSION_MAJOR(shader_version) < 2) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
break;
@ -821,10 +816,8 @@ static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
device->shader_backend->shader_color_correction(arg, fixup);
}
/** Shared code in order to generate the bulk of the shader string.
Use the shader_header_fct & shader_footer_fct to add strings
that are specific to pixel or vertex functions
NOTE: A description of how to parse tokens can be found on msdn */
/* Shared code in order to generate the bulk of the shader string.
* NOTE: A description of how to parse tokens can be found on msdn */
void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
const shader_reg_maps* reg_maps, CONST DWORD* pFunction)
{
@ -832,10 +825,10 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */
const SHADER_OPCODE *opcode_table = This->baseShader.shader_ins;
const SHADER_HANDLER *handler_table = device->shader_backend->shader_instruction_handler_table;
DWORD shader_version = This->baseShader.hex_version;
DWORD shader_version = reg_maps->shader_version;
const DWORD *pToken = pFunction;
const SHADER_OPCODE *curOpcode = NULL;
SHADER_HANDLER hw_fct = NULL;
const SHADER_OPCODE *curOpcode;
SHADER_HANDLER hw_fct;
DWORD i;
SHADER_OPCODE_ARG hw_arg;
@ -845,99 +838,92 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
hw_arg.reg_maps = reg_maps;
This->baseShader.parse_state.current_row = 0;
/* Second pass, process opcodes */
if (NULL != pToken) {
while (WINED3DPS_END() != *pToken) {
/* Skip version token */
if (shader_is_version_token(*pToken)) {
++pToken;
continue;
}
/* Skip comment tokens */
if (shader_is_comment(*pToken)) {
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken;
TRACE("#%s\n", (const char*)pToken);
pToken += comment_len;
continue;
}
/* Read opcode */
hw_arg.opcode_token = *pToken++;
curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token);
/* Select handler */
if (curOpcode == NULL)
hw_fct = NULL;
else
hw_fct = handler_table[curOpcode->handler_idx];
/* Unknown opcode and its parameters */
if (NULL == curOpcode) {
FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token);
pToken += shader_skip_unrecognized(pToken, shader_version);
/* Nothing to do */
} else if (WINED3DSIO_DCL == curOpcode->opcode ||
WINED3DSIO_NOP == curOpcode->opcode ||
WINED3DSIO_DEF == curOpcode->opcode ||
WINED3DSIO_DEFI == curOpcode->opcode ||
WINED3DSIO_DEFB == curOpcode->opcode ||
WINED3DSIO_PHASE == curOpcode->opcode ||
WINED3DSIO_RET == curOpcode->opcode) {
pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
/* If a generator function is set for current shader target, use it */
} else if (hw_fct != NULL) {
hw_arg.opcode = curOpcode;
/* Destination token */
if (curOpcode->dst_token) {
DWORD param, addr_token = 0;
pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
hw_arg.dst = param;
hw_arg.dst_addr = addr_token;
}
/* Predication token */
if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
hw_arg.predicate = *pToken++;
/* Other source tokens */
for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); i++) {
DWORD param, addr_token = 0;
pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
hw_arg.src[i] = param;
hw_arg.src_addr[i] = addr_token;
}
/* Call appropriate function for output target */
hw_fct(&hw_arg);
/* Add color correction if needed */
shader_color_correction(This, device, &hw_arg);
/* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
/* FIXME: This should be internal to the shader backend.
* Also, right now this is the only reason "shader_mode" exists. */
if (This->baseShader.shader_mode == SHADER_GLSL)
shader_glsl_add_instruction_modifiers(&hw_arg);
/* Unhandled opcode */
} else {
FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
}
while (WINED3DPS_END() != *pToken)
{
/* Skip version token */
if (shader_is_version_token(*pToken))
{
++pToken;
continue;
}
/* TODO: What about result.depth? */
/* Skip comment tokens */
if (shader_is_comment(*pToken))
{
pToken += (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken;
continue;
}
/* Read opcode */
hw_arg.opcode_token = *pToken++;
curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token);
/* Unknown opcode and its parameters */
if (!curOpcode)
{
FIXME("Unrecognized opcode: token=0x%08x\n", hw_arg.opcode_token);
pToken += shader_skip_unrecognized(pToken, shader_version);
continue;
}
/* Nothing to do */
if (WINED3DSIO_DCL == curOpcode->opcode
|| WINED3DSIO_NOP == curOpcode->opcode
|| WINED3DSIO_DEF == curOpcode->opcode
|| WINED3DSIO_DEFI == curOpcode->opcode
|| WINED3DSIO_DEFB == curOpcode->opcode
|| WINED3DSIO_PHASE == curOpcode->opcode
|| WINED3DSIO_RET == curOpcode->opcode)
{
pToken += shader_skip_opcode(curOpcode, hw_arg.opcode_token, shader_version);
continue;
}
/* Select handler */
hw_fct = handler_table[curOpcode->handler_idx];
/* Unhandled opcode */
if (!hw_fct)
{
FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
pToken += shader_skip_opcode(curOpcode, hw_arg.opcode_token, shader_version);
continue;
}
hw_arg.opcode = curOpcode;
/* Destination token */
if (curOpcode->dst_token)
{
DWORD param, addr_token = 0;
pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
hw_arg.dst = param;
hw_arg.dst_addr = addr_token;
}
/* Predication token */
if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) hw_arg.predicate = *pToken++;
/* Other source tokens */
for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); ++i)
{
DWORD param, addr_token = 0;
pToken += shader_get_param(pToken, shader_version, &param, &addr_token);
hw_arg.src[i] = param;
hw_arg.src_addr[i] = addr_token;
}
/* Call appropriate function for output target */
hw_fct(&hw_arg);
/* Add color correction if needed */
shader_color_correction(This, device, &hw_arg, shader_version);
/* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
/* FIXME: This should be internal to the shader backend.
* Also, right now this is the only reason "shader_mode" exists. */
if (This->baseShader.shader_mode == SHADER_GLSL) shader_glsl_add_instruction_modifiers(&hw_arg);
}
}
@ -966,60 +952,45 @@ static void shader_dump_ins_modifiers(const DWORD output)
FIXME("_unrecognized_modifier(%#x)", mmask >> WINED3DSP_DSTMOD_SHIFT);
}
/* First pass: trace shader, initialize length and version */
void shader_trace_init(
IWineD3DBaseShader *iface,
const DWORD* pFunction) {
IWineD3DBaseShaderImpl *This =(IWineD3DBaseShaderImpl *)iface;
void shader_trace_init(const DWORD *pFunction, const SHADER_OPCODE *opcode_table)
{
const DWORD* pToken = pFunction;
const SHADER_OPCODE* curOpcode = NULL;
DWORD shader_version;
DWORD opcode_token;
unsigned int len = 0;
DWORD i;
TRACE("(%p) : Parsing program\n", This);
TRACE("Parsing %p\n", pFunction);
if (!pFunction)
/* The version token is supposed to be the first token */
if (!shader_is_version_token(*pToken))
{
WARN("Got a NULL pFunction, returning.\n");
This->baseShader.functionLength = 1; /* no Function defined use fixed function vertex processing */
FIXME("First token is not a version token, invalid shader.\n");
return;
}
shader_version = *pToken++;
TRACE("%s_%u_%u\n", shader_is_pshader_version(shader_version) ? "ps": "vs",
WINED3DSHADER_VERSION_MAJOR(shader_version), WINED3DSHADER_VERSION_MINOR(shader_version));
while (WINED3DVS_END() != *pToken)
{
if (shader_is_version_token(*pToken)) /* version */
{
This->baseShader.hex_version = *pToken;
TRACE("%s_%u_%u\n", shader_is_pshader_version(This->baseShader.hex_version)? "ps": "vs",
WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version),
WINED3DSHADER_VERSION_MINOR(This->baseShader.hex_version));
++pToken;
++len;
continue;
}
if (shader_is_comment(*pToken)) /* comment */
{
DWORD comment_len = (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT;
++pToken;
TRACE("//%s\n", (const char*)pToken);
pToken += comment_len;
len += comment_len + 1;
continue;
}
opcode_token = *pToken++;
curOpcode = shader_get_opcode(This->baseShader.shader_ins, This->baseShader.hex_version, opcode_token);
len++;
curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
if (!curOpcode)
{
int tokens_read;
FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
tokens_read = shader_skip_unrecognized(pToken, This->baseShader.hex_version);
tokens_read = shader_skip_unrecognized(pToken, shader_version);
pToken += tokens_read;
len += tokens_read;
}
else
{
@ -1028,12 +999,11 @@ void shader_trace_init(
DWORD usage = *pToken;
DWORD param = *(pToken + 1);
shader_dump_decl_usage(usage, param, This->baseShader.hex_version);
shader_dump_decl_usage(usage, param, shader_version);
shader_dump_ins_modifiers(param);
TRACE(" ");
shader_dump_param(param, 0, 0, This->baseShader.hex_version);
shader_dump_param(param, 0, 0, shader_version);
pToken += 2;
len += 2;
}
else if (curOpcode->opcode == WINED3DSIO_DEF)
{
@ -1045,7 +1015,6 @@ void shader_trace_init(
*(const float *)(pToken + 3),
*(const float *)(pToken + 4));
pToken += 5;
len += 5;
}
else if (curOpcode->opcode == WINED3DSIO_DEFI)
{
@ -1055,14 +1024,12 @@ void shader_trace_init(
*(pToken + 3),
*(pToken + 4));
pToken += 5;
len += 5;
}
else if (curOpcode->opcode == WINED3DSIO_DEFB)
{
TRACE("defb b%u = %s", *pToken & WINED3DSP_REGNUM_MASK,
*(pToken + 1)? "true": "false");
pToken += 2;
len += 2;
}
else
{
@ -1074,7 +1041,7 @@ void shader_trace_init(
if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
{
TRACE("(");
shader_dump_param(*(pToken + 2), 0, 1, This->baseShader.hex_version);
shader_dump_param(*(pToken + 2), 0, 1, shader_version);
TRACE(") ");
}
if (opcode_token & WINED3DSI_COISSUE)
@ -1102,7 +1069,7 @@ void shader_trace_init(
}
}
else if (curOpcode->opcode == WINED3DSIO_TEX
&& This->baseShader.hex_version >= WINED3DPS_VERSION(2,0)
&& shader_version >= WINED3DPS_VERSION(2,0)
&& (opcode_token & WINED3DSI_TEXLD_PROJECT))
{
TRACE("p");
@ -1111,51 +1078,60 @@ void shader_trace_init(
/* Destination token */
if (curOpcode->dst_token)
{
tokens_read = shader_get_param(pToken, This->baseShader.hex_version, &param, &addr_token);
tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
pToken += tokens_read;
len += tokens_read;
shader_dump_ins_modifiers(param);
TRACE(" ");
shader_dump_param(param, addr_token, 0, This->baseShader.hex_version);
shader_dump_param(param, addr_token, 0, shader_version);
}
/* Predication token - already printed out, just skip it */
if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED)
{
pToken++;
len++;
}
/* Other source tokens */
for (i = curOpcode->dst_token; i < curOpcode->num_params; ++i)
{
tokens_read = shader_get_param(pToken, This->baseShader.hex_version, &param, &addr_token);
tokens_read = shader_get_param(pToken, shader_version, &param, &addr_token);
pToken += tokens_read;
len += tokens_read;
TRACE((i == 0)? " " : ", ");
shader_dump_param(param, addr_token, 1, This->baseShader.hex_version);
shader_dump_param(param, addr_token, 1, shader_version);
}
}
TRACE("\n");
}
}
This->baseShader.functionLength = (len + 1) * sizeof(DWORD);
}
void shader_cleanup(IWineD3DBaseShader *iface)
{
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_destroy(iface);
HeapFree(GetProcessHeap(), 0, This->baseShader.function);
shader_delete_constant_list(&This->baseShader.constantsF);
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
list_remove(&This->baseShader.shader_list_entry);
}
static const SHADER_HANDLER shader_none_instruction_handler_table[WINED3DSIH_TABLE_SIZE] = {0};
static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {}
static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {}
static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
static void shader_none_cleanup(IWineD3DDevice *iface) {}
static void shader_none_color_correction(const struct SHADER_OPCODE_ARG *arg, struct color_fixup_desc fixup) {}
static void shader_none_destroy(IWineD3DBaseShader *iface) {}
static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
static void shader_none_free(IWineD3DDevice *iface) {}
static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) {
FIXME("NONE shader backend asked to generate a pixel shader\n");
return 0;
}
@ -1196,8 +1172,9 @@ const shader_backend_t none_shader_backend = {
shader_none_select,
shader_none_select_depth_blt,
shader_none_deselect_depth_blt,
shader_none_update_float_vertex_constants,
shader_none_update_float_pixel_constants,
shader_none_load_constants,
shader_none_cleanup,
shader_none_color_correction,
shader_none_destroy,
shader_none_alloc,
@ -1208,46 +1185,3 @@ const shader_backend_t none_shader_backend = {
shader_none_get_caps,
shader_none_color_fixup_supported,
};
/* *******************************************
IWineD3DPixelShader IUnknown parts follow
******************************************* */
HRESULT WINAPI IWineD3DBaseShaderImpl_QueryInterface(IWineD3DBaseShader *iface, REFIID riid, LPVOID *ppobj)
{
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IWineD3DBase)
|| IsEqualGUID(riid, &IID_IWineD3DBaseShader)
|| IsEqualGUID(riid, &IID_IWineD3DPixelShader)) {
IUnknown_AddRef(iface);
*ppobj = This;
return S_OK;
}
*ppobj = NULL;
return E_NOINTERFACE;
}
ULONG WINAPI IWineD3DBaseShaderImpl_AddRef(IWineD3DBaseShader *iface) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
TRACE("(%p) : AddRef increasing from %d\n", This, This->baseShader.ref);
return InterlockedIncrement(&This->baseShader.ref);
}
ULONG WINAPI IWineD3DBaseShaderImpl_Release(IWineD3DBaseShader *iface) {
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface;
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
ULONG ref;
TRACE("(%p) : Releasing from %d\n", This, This->baseShader.ref);
ref = InterlockedDecrement(&This->baseShader.ref);
if (ref == 0) {
deviceImpl->shader_backend->shader_destroy(iface);
HeapFree(GetProcessHeap(), 0, This->baseShader.function);
shader_delete_constant_list(&This->baseShader.constantsF);
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
list_remove(&This->baseShader.shader_list_entry);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}

View file

@ -27,6 +27,16 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
#define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
void basetexture_init(struct IWineD3DBaseTextureClass *texture, UINT levels, DWORD usage)
{
texture->levels = levels;
texture->filterType = (usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE;
texture->LOD = 0;
texture->dirty = TRUE;
texture->is_srgb = FALSE;
texture->srgb_mode_change_count = 0;
}
void basetexture_cleanup(IWineD3DBaseTexture *iface)
{
IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
@ -249,7 +259,6 @@ HRESULT basetexture_bind(IWineD3DBaseTexture *iface)
glTexParameteri(textureDimensions, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
}
} else { /* this only happened if we've run out of openGL textures */
WARN("This texture doesn't have an openGL texture assigned to it\n");
hr = WINED3DERR_INVALIDCALL;

View file

@ -839,12 +839,6 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar
checkGLcall("glClear");
glColor3f(1.0, 1.0, 1.0);
checkGLcall("glColor3f");
glEnable(GL_LIGHTING);
checkGLcall("glEnable");
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
@ -1053,7 +1047,7 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
/* TODO: Use a display list */
/* Disable shaders */
This->shader_backend->shader_cleanup((IWineD3DDevice *) This);
This->shader_backend->shader_select((IWineD3DDevice *)This, FALSE, FALSE);
Context_MarkStateDirty(context, STATE_VSHADER, StateTable);
Context_MarkStateDirty(context, STATE_PIXELSHADER, StateTable);
@ -1066,42 +1060,40 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
/* Disable all textures. The caller can then bind a texture it wants to blit
* from
*
* The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
* function texture unit. No need to care for higher samplers
*/
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
/* The blitting code uses (for now) the fixed function pipeline, so make sure to reset all fixed
* function texture unit. No need to care for higher samplers
*/
for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
sampler = This->rev_tex_unit_map[i];
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
checkGLcall("glActiveTextureARB");
if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
}
glDisable(GL_TEXTURE_3D);
checkGLcall("glDisable GL_TEXTURE_3D");
if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
glDisable(GL_TEXTURE_RECTANGLE_ARB);
checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
}
glDisable(GL_TEXTURE_2D);
checkGLcall("glDisable GL_TEXTURE_2D");
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
if (sampler != -1) {
if (sampler < MAX_TEXTURES) {
Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
}
Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
}
}
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
for(i = GL_LIMITS(textures) - 1; i > 0 ; i--) {
sampler = This->rev_tex_unit_map[i];
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
checkGLcall("glActiveTextureARB");
if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB");
}
glDisable(GL_TEXTURE_3D);
checkGLcall("glDisable GL_TEXTURE_3D");
if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
glDisable(GL_TEXTURE_RECTANGLE_ARB);
checkGLcall("glDisable GL_TEXTURE_RECTANGLE_ARB");
}
glDisable(GL_TEXTURE_2D);
checkGLcall("glDisable GL_TEXTURE_2D");
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);");
if (sampler != -1) {
if (sampler < MAX_TEXTURES) {
Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable);
}
Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable);
}
}
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
checkGLcall("glActiveTextureARB");
sampler = This->rev_tex_unit_map[0];
@ -1150,7 +1142,7 @@ static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *contex
glDisable(GL_DEPTH_TEST);
checkGLcall("glDisable GL_DEPTH_TEST");
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ZENABLE), StateTable);
glDisable(GL_FOG);
glDisableWINE(GL_FOG);
checkGLcall("glDisable GL_FOG");
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE), StateTable);
glDisable(GL_BLEND);
@ -1623,3 +1615,7 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
FIXME("Unexpected context usage requested\n");
}
}
WineD3DContext *getActiveContext(void) {
return last_device->activeContext;
}

View file

@ -136,9 +136,8 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) {
}
}
} else if (srgb_was_toggled) {
/* Loop is repeated in the else block with the extra AddDirtyRect line to avoid the alternative of
* checking srgb_was_toggled in every iteration, even when the texture is just dirty
*/
/* Loop is repeated in the else block with the extra surface_add_dirty_rect() line to avoid the
* alternative of checking srgb_was_toggled in every iteration, even when the texture is just dirty */
if (This->baseTexture.srgb_mode_change_count < 20)
++This->baseTexture.srgb_mode_change_count;
else
@ -146,7 +145,7 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) {
for (i = 0; i < This->baseTexture.levels; i++) {
for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) {
IWineD3DSurface_AddDirtyRect(This->surfaces[j][i], NULL);
surface_add_dirty_rect(This->surfaces[j][i], NULL);
surface_force_reload(This->surfaces[j][i]);
IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode);
}
@ -298,7 +297,7 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_GetLevelDesc(IWineD3DCubeTexture *
TRACE("(%p) level (%d)\n", This, Level);
return IWineD3DSurface_GetDesc(This->surfaces[0][Level], pDesc);
}
FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
}
@ -360,7 +359,8 @@ static HRESULT WINAPI IWineD3DCubeTextureImpl_AddDirtyRect(IWineD3DCubeTexture
This->baseTexture.dirty = TRUE;
TRACE("(%p) : dirtyfication of faceType(%d) Level (0)\n", This, FaceType);
if (FaceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z) {
hr = IWineD3DSurface_AddDirtyRect(This->surfaces[FaceType][0], pDirtyRect);
surface_add_dirty_rect(This->surfaces[FaceType][0], pDirtyRect);
hr = WINED3D_OK;
} else {
WARN("(%p) overflow FaceType(%d)\n", This, FaceType);
}

File diff suppressed because it is too large Load diff

View file

@ -82,6 +82,7 @@ static const struct {
{"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
{"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
{"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
{"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
{"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
{"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
{"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
@ -109,9 +110,11 @@ static const struct {
{"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
{"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
{"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
{"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
{"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
{"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
{"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
{"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
{"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
{"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
@ -187,7 +190,6 @@ glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
glAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
/**
* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
@ -519,8 +521,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
ENTER_GL();
gl_string = (const char *) glGetString(GL_RENDERER);
if (NULL == gl_string)
gl_string = "None";
if (!gl_string) gl_string = "None";
strcpy(gl_info->gl_renderer, gl_string);
gl_string = (const char *) glGetString(GL_VENDOR);
@ -715,7 +716,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
gl_info->max_texture_stages = 1;
gl_info->max_fragment_samplers = 1;
gl_info->max_vertex_samplers = 0;
gl_info->max_combined_samplers = 0;
gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
gl_info->max_sampler_stages = 1;
gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
gl_info->ps_arb_max_temps = 0;
@ -743,7 +744,7 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
gl_info->max_texture_size = gl_max;
TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
gl_info->max_pointsizemin = gl_floatv[0];
gl_info->max_pointsize = gl_floatv[1];
TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
@ -1303,7 +1304,8 @@ static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
}
break;
case VENDOR_INTEL:
if (strstr(gl_info->gl_renderer, "GMA 950")) {
if (strstr(gl_info->gl_renderer, "GMA 950") ||
strstr(gl_info->gl_renderer, "945GM")) {
/* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
gl_info->gl_card = CARD_INTEL_I945GM;
vidmem = 64;
@ -2361,6 +2363,10 @@ static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINE
case WINED3DFMT_G16R16F:
case WINED3DFMT_G32R32F:
if(GL_SUPPORT(ARB_TEXTURE_RG)) {
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
}
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
@ -3146,11 +3152,11 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
}
/* FIXME Add:
WINED3DPRASTERCAPS_COLORPERSPECTIVE
WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
WINED3DPRASTERCAPS_ANTIALIASEDGES
WINED3DPRASTERCAPS_ZBUFFERLESSHSR
WINED3DPRASTERCAPS_WBUFFER */
WINED3DPRASTERCAPS_COLORPERSPECTIVE
WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
WINED3DPRASTERCAPS_ANTIALIASEDGES
WINED3DPRASTERCAPS_ZBUFFERLESSHSR
WINED3DPRASTERCAPS_WBUFFER */
pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
WINED3DPCMPCAPS_EQUAL |
@ -3616,16 +3622,17 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
/* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
and fields being inserted in the middle, a new structure is used in place */
static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
IUnknown *parent) {
static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
{
IWineD3DDeviceImpl *object = NULL;
IWineD3DImpl *This = (IWineD3DImpl *)iface;
WINED3DDISPLAYMODE mode;
const struct fragment_pipeline *frag_pipeline = NULL;
int i;
struct fragment_caps ffp_caps;
HRESULT hr;
/* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
* number and create a device without a 3D adapter for 2D only operation.
@ -3649,6 +3656,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
IWineD3D_AddRef(object->wineD3D);
object->parent = parent;
object->device_parent = device_parent;
list_init(&object->resources);
list_init(&object->shaders);
@ -3684,19 +3692,18 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
hr = compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
ffp_vertexstate_template, frag_pipeline, misc_state_template);
object->blitter = select_blit_implementation(Adapter, DeviceType);
if (FAILED(hr)) {
IWineD3D_Release(object->wineD3D);
HeapFree(GetProcessHeap(), 0, object);
/* Prefer the vtable with functions optimized for single dirtifyable objects if the shader
* model can deal with that. It is essentially the same, just with adjusted
* Set*ShaderConstantF implementations
*/
if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) {
object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl;
return hr;
}
object->blitter = select_blit_implementation(Adapter, DeviceType);
/* set the state of the device to valid */
object->state = WINED3D_OK;
@ -4155,35 +4162,11 @@ static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
}
texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glAttribFunc)glTexCoord1fv;
texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glAttribFunc)glTexCoord2fv;
texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glTexCoord3fv;
texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glTexCoord4fv;
texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glAttribFunc)glTexCoord2sv;
texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glTexCoord4sv;
texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
if (GL_SUPPORT(NV_HALF_FLOAT))
{
texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glAttribFunc)GL_EXTCALL(glTexCoord2hvNV);
texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glAttribFunc)GL_EXTCALL(glTexCoord4hvNV);
} else {
texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
}
}
#define PUSH1(att) attribs[nAttribs++] = (att);
BOOL InitAdapters(void) {
static HMODULE mod_gl, mod_win32gl;
static HMODULE mod_gl;
BOOL ret;
int ps_selected_mode, vs_selected_mode;
@ -4202,16 +4185,10 @@ BOOL InitAdapters(void) {
ERR("Can't load opengl32.dll!\n");
goto nogl_adapter;
}
mod_win32gl = mod_gl;
#else
#define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
/* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
mod_gl = GetModuleHandleA("gdi32.dll");
mod_win32gl = LoadLibraryA("opengl32.dll");
if(!mod_win32gl) {
ERR("Can't load opengl32.dll!\n");
goto nogl_adapter;
}
#endif
}
@ -4232,8 +4209,16 @@ BOOL InitAdapters(void) {
/* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
* otherwise because we have to use winex11.drv's override
*/
glFinish = (void*)GetProcAddress(mod_win32gl, "glFinish");
glFlush = (void*)GetProcAddress(mod_win32gl, "glFlush");
#ifdef USE_WIN32_OPENGL
glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
#else
glFinish = (void*)pwglGetProcAddress("wglFinish");
glFlush = (void*)pwglGetProcAddress("wglFlush");
#endif
glEnableWINE = glEnable;
glDisableWINE = glDisable;
/* For now only one default adapter */
{
@ -4376,6 +4361,7 @@ BOOL InitAdapters(void) {
}
fixup_extensions(&Adapters[0].gl_info);
add_gl_compat_wrappers(&Adapters[0].gl_info);
WineD3D_ReleaseFakeGLContext();

View file

@ -152,12 +152,13 @@ void primitiveDeclarationConvertToStridedData(
const DWORD *streams = vertexDeclaration->streams;
/* Check for transformed vertices, disable vertex shader if present */
strided->u.s.position_transformed = vertexDeclaration->position_transformed;
strided->position_transformed = vertexDeclaration->position_transformed;
if(vertexDeclaration->position_transformed) {
useVertexShaderFunction = FALSE;
}
/* Translate the declaration into strided data */
strided->swizzle_map = 0;
for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
GLint streamVBO = 0;
BOOL stride_used;
@ -201,8 +202,8 @@ void primitiveDeclarationConvertToStridedData(
element->Usage == WINED3DDECLUSAGE_POSITIONT)) {
static BOOL warned = FALSE;
if(!warned) {
/* This may be bad with the fixed function pipeline */
FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
/* This may be bad with the fixed function pipeline */
FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
warned = TRUE;
}
}
@ -234,6 +235,11 @@ void primitiveDeclarationConvertToStridedData(
strided->u.input[idx].dwStride = stride;
strided->u.input[idx].VBO = streamVBO;
strided->u.input[idx].streamNo = element->Stream;
if (!GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) && element->Type == WINED3DDECLTYPE_D3DCOLOR)
{
strided->swizzle_map |= 1 << idx;
}
strided->use_map |= 1 << idx;
}
}
}
@ -253,32 +259,35 @@ void primitiveDeclarationConvertToStridedData(
}
}
static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum glPrimitiveType,
const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
static void drawStridedFast(IWineD3DDevice *iface, GLenum primitive_type,
UINT min_vertex_idx, UINT max_vertex_idx, UINT count, short idx_size,
const void *idx_data, UINT start_idx)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
if (idxSize != 0 /* This crashes sometimes!*/) {
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
idxData = idxData == (void *)-1 ? NULL : idxData;
#if 1
glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idxData+(idxSize * startIdx));
checkGLcall("glDrawElements");
#else /* using drawRangeElements may be faster */
if (idx_size)
{
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, primitive_type, count, min_vertex_idx);
glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices,
idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idxData+(idxSize * startIdx));
#if 1
glDrawElements(primitive_type, count,
idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idx_data + (idx_size * start_idx));
checkGLcall("glDrawElements");
#else
glDrawRangeElements(primitive_type, min_vertex_idx, max_vertex_idx, count,
idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
(const char *)idx_data + (idx_size * start_idx));
checkGLcall("glDrawRangeElements");
#endif
}
else
{
TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, primitive_type, start_idx, count);
} else {
TRACE("(%p) : glDrawArrays(%#x, %d, %d)\n", This, glPrimitiveType, startVertex, numberOfVertices);
glDrawArrays(glPrimitiveType, startVertex, numberOfVertices);
glDrawArrays(primitive_type, start_idx, count);
checkGLcall("glDrawArrays");
}
return;
}
/*
@ -287,7 +296,7 @@ static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum
*/
static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd, UINT NumVertexes,
GLenum glPrimType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex)
GLenum glPrimType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx)
{
unsigned int textureNo = 0;
const WORD *pIdxBufS = NULL;
@ -295,8 +304,8 @@ static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStrid
ULONG vx_index;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
const UINT *streamOffset = This->stateBlock->streamOffset;
long SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
BOOL pixelShader = use_ps(This);
long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex;
BOOL pixelShader = use_ps(This->stateBlock);
BOOL specular_fog = FALSE;
UINT texture_stages = GL_LIMITS(texture_stages);
const BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
@ -440,21 +449,15 @@ static void drawStridedSlow(IWineD3DDevice *iface, const WineDirect3DVertexStrid
{
int coord_idx;
const void *ptr;
int texture_idx;
if (!(tmp_tex_mask & 1)) continue;
coord_idx = This->stateBlock->textureState[texture][WINED3DTSS_TEXCOORDINDEX];
ptr = texCoords[coord_idx] + (SkipnStrides * sd->u.s.texCoords[coord_idx].dwStride);
if (GL_SUPPORT(ARB_MULTITEXTURE))
{
int texture_idx = This->texUnitMap[texture];
multi_texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](GL_TEXTURE0_ARB + texture_idx, ptr);
}
else
{
texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](ptr);
}
texture_idx = This->texUnitMap[texture];
multi_texcoord_funcs[sd->u.s.texCoords[coord_idx].dwType](GL_TEXTURE0_ARB + texture_idx, ptr);
}
/* Diffuse -------------------------------- */
@ -603,10 +606,10 @@ static inline void send_attribute(IWineD3DDeviceImpl *This, const DWORD type, co
}
static void drawStridedSlowVs(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd, UINT numberOfVertices,
GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex)
GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
long SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
long SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex;
const WORD *pIdxBufS = NULL;
const DWORD *pIdxBufL = NULL;
ULONG vx_index;
@ -664,7 +667,7 @@ static void drawStridedSlowVs(IWineD3DDevice *iface, const WineDirect3DVertexStr
static inline void drawStridedInstanced(IWineD3DDevice *iface, const WineDirect3DVertexStridedData *sd,
UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, short idxSize, ULONG minIndex,
ULONG startIdx, ULONG startVertex)
ULONG startIdx)
{
UINT numInstances = 0, i;
int numInstancedAttribs = 0, j;
@ -684,7 +687,6 @@ static inline void drawStridedInstanced(IWineD3DDevice *iface, const WineDirect3
}
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
idxData = idxData == (void *)-1 ? NULL : idxData;
/* First, figure out how many instances we have to draw */
for(i = 0; i < MAX_STREAMS; i++) {
@ -817,16 +819,9 @@ static inline void remove_vbos(IWineD3DDeviceImpl *This, WineDirect3DVertexStrid
}
/* Routine common to the draw primitive and draw indexed primitive routines */
void drawPrimitive(IWineD3DDevice *iface,
int PrimitiveType,
long NumPrimitives,
/* for Indexed: */
long StartVertexIndex,
UINT numberOfVertices,
long StartIdx,
short idxSize,
const void *idxData,
int minIndex) {
void drawPrimitive(IWineD3DDevice *iface, int PrimitiveType, long NumPrimitives,
UINT numberOfVertices, long StartIdx, short idxSize, const void *idxData, int minIndex)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSurfaceImpl *target;
@ -869,9 +864,11 @@ void drawPrimitive(IWineD3DDevice *iface,
if (numberOfVertices == 0 )
numberOfVertices = calculatedNumberOfindices;
if(!use_vs(This)) {
if(!This->strided_streams.u.s.position_transformed && This->activeContext->num_untracked_materials &&
This->stateBlock->renderState[WINED3DRS_LIGHTING]) {
if (!use_vs(This->stateBlock))
{
if (!This->strided_streams.position_transformed && This->activeContext->num_untracked_materials
&& This->stateBlock->renderState[WINED3DRS_LIGHTING])
{
static BOOL warned;
if (!warned) {
FIXME("Using software emulation because not all material properties could be tracked\n");
@ -904,7 +901,8 @@ void drawPrimitive(IWineD3DDevice *iface,
if (This->useDrawStridedSlow || emulation) {
/* Immediate mode drawing */
if(use_vs(This)) {
if (use_vs(This->stateBlock))
{
static BOOL warned;
if (!warned) {
FIXME("Using immediate mode with vertex shaders for half float emulation\n");
@ -912,19 +910,19 @@ void drawPrimitive(IWineD3DDevice *iface,
} else {
TRACE("Using immediate mode with vertex shaders for half float emulation\n");
}
drawStridedSlowVs(iface, strided, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
drawStridedSlowVs(iface, strided, calculatedNumberOfindices,
glPrimType, idxData, idxSize, minIndex, StartIdx);
} else {
drawStridedSlow(iface, strided, calculatedNumberOfindices,
glPrimType, idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
glPrimType, idxData, idxSize, minIndex, StartIdx);
}
} else if(This->instancedDraw) {
/* Instancing emulation with mixing immediate mode and arrays */
drawStridedInstanced(iface, &This->strided_streams, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
idxData, idxSize, minIndex, StartIdx);
} else {
drawStridedFast(iface, calculatedNumberOfindices, glPrimType,
idxData, idxSize, minIndex, StartIdx, StartVertexIndex);
drawStridedFast(iface, glPrimType, minIndex, minIndex + numberOfVertices - 1,
calculatedNumberOfindices, idxSize, idxData, StartIdx);
}
}
@ -1035,9 +1033,8 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
vtxStride * info->StartVertexOffsetWidth;
/* Not entirely sure about what happens with transformed vertices */
if(strided.u.s.position_transformed) {
FIXME("Transformed position in rectpatch generation\n");
}
if (strided.position_transformed) FIXME("Transformed position in rectpatch generation\n");
if(vtxStride % sizeof(GLfloat)) {
/* glMap2f reads vertex sizes in GLfloats, the d3d stride is in bytes.
* I don't see how the stride could not be a multiple of 4, but make sure
@ -1092,11 +1089,11 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_FILLMODE));
if(patch->has_normals) {
const GLfloat black[4] = {0, 0, 0, 0};
const GLfloat red[4] = {1, 0, 0, 0};
const GLfloat green[4] = {0, 1, 0, 0};
const GLfloat blue[4] = {0, 0, 1, 0};
const GLfloat white[4] = {1, 1, 1, 1};
static const GLfloat black[] = {0, 0, 0, 0};
static const GLfloat red[] = {1, 0, 0, 0};
static const GLfloat green[] = {0, 1, 0, 0};
static const GLfloat blue[] = {0, 0, 1, 0};
static const GLfloat white[] = {1, 1, 1, 1};
glEnable(GL_LIGHTING);
checkGLcall("glEnable(GL_LIGHTING)");
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black);
@ -1263,9 +1260,9 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This,
if(patch->has_normals) {
/* Now do the same with reverse light directions */
const GLfloat x[4] = {-1, 0, 0, 0};
const GLfloat y[4] = { 0, -1, 0, 0};
const GLfloat z[4] = { 0, 0, -1, 0};
static const GLfloat x[] = {-1, 0, 0, 0};
static const GLfloat y[] = { 0, -1, 0, 0};
static const GLfloat z[] = { 0, 0, -1, 0};
glLightfv(GL_LIGHT0, GL_POSITION, x);
glLightfv(GL_LIGHT1, GL_POSITION, y);
glLightfv(GL_LIGHT2, GL_POSITION, z);

View file

@ -0,0 +1,535 @@
/*
* Compatibility functions for older GL implementations
*
* Copyright 2008 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <stdio.h>
#ifdef HAVE_FLOAT_H
# include <float.h>
#endif
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(gl_compat);
/* Start GL_ARB_multitexture emulation */
static void WINE_GLAPI wine_glMultiTexCoord1fARB(GLenum target, GLfloat s) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord1f(s);
}
static void WINE_GLAPI wine_glMultiTexCoord1fvARB(GLenum target, const GLfloat *v) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord1fv(v);
}
static void WINE_GLAPI wine_glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord2f(s, t);
}
static void WINE_GLAPI wine_glMultiTexCoord2fvARB(GLenum target, const GLfloat *v) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord2fv(v);
}
static void WINE_GLAPI wine_glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord3f(s, t, r);
}
static void WINE_GLAPI wine_glMultiTexCoord3fvARB(GLenum target, const GLfloat *v) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord3fv(v);
}
static void WINE_GLAPI wine_glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord4f(s, t, r, q);
}
static void WINE_GLAPI wine_glMultiTexCoord4fvARB(GLenum target, const GLfloat *v) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord4fv(v);
}
static void WINE_GLAPI wine_glMultiTexCoord2svARB(GLenum target, const GLshort *v) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord2sv(v);
}
static void WINE_GLAPI wine_glMultiTexCoord4svARB(GLenum target, const GLshort *v) {
if(target != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
glTexCoord4sv(v);
}
static void WINE_GLAPI wine_glActiveTextureARB(GLenum texture) {
if(texture != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
}
static void WINE_GLAPI wine_glClientActiveTextureARB(GLenum texture) {
if(texture != GL_TEXTURE0) {
ERR("Texture unit > 0 used, but GL_ARB_multitexture is not supported\n");
return;
}
}
static void (WINE_GLAPI *old_multitex_glGetIntegerv) (GLenum pname, GLint* params) = NULL;
static void WINE_GLAPI wine_glGetIntegerv(GLenum pname, GLint* params) {
switch(pname) {
case GL_ACTIVE_TEXTURE: *params = 0; break;
case GL_MAX_TEXTURE_UNITS_ARB: *params = 1; break;
default: old_multitex_glGetIntegerv(pname, params);
}
}
static void (WINE_GLAPI *old_multitex_glGetFloatv) (GLenum pname, GLfloat* params) = NULL;
static void WINE_GLAPI wine_glGetFloatv(GLenum pname, GLfloat* params) {
if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
else old_multitex_glGetFloatv(pname, params);
}
static void (WINE_GLAPI *old_multitex_glGetDoublev) (GLenum pname, GLdouble* params) = NULL;
static void WINE_GLAPI wine_glGetDoublev(GLenum pname, GLdouble* params) {
if(pname == GL_ACTIVE_TEXTURE) *params = 0.0;
else old_multitex_glGetDoublev(pname, params);
}
/* Start GL_EXT_fogcoord emulation */
static void (WINE_GLAPI *old_fogcoord_glEnable) (GLenum cap) = NULL;
static void WINE_GLAPI wine_glEnable(GLenum cap) {
if(cap == GL_FOG) {
WineD3DContext *ctx = getActiveContext();
ctx->fog_enabled = 1;
if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
}
old_fogcoord_glEnable(cap);
}
static void (WINE_GLAPI *old_fogcoord_glDisable) (GLenum cap) = NULL;
static void WINE_GLAPI wine_glDisable(GLenum cap) {
if(cap == GL_FOG) {
WineD3DContext *ctx = getActiveContext();
ctx->fog_enabled = 0;
if(ctx->gl_fog_source != GL_FRAGMENT_DEPTH_EXT) return;
}
old_fogcoord_glDisable(cap);
}
static void (WINE_GLAPI *old_fogcoord_glFogi) (GLenum pname, GLint param) = NULL;
static void WINE_GLAPI wine_glFogi(GLenum pname, GLint param) {
if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
WineD3DContext *ctx = getActiveContext();
ctx->gl_fog_source = param;
if(param == GL_FRAGMENT_DEPTH_EXT) {
if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
} else {
WARN("Fog coords activated, but not supported. Using slow emulation\n");
old_fogcoord_glDisable(GL_FOG);
}
} else {
if(pname == GL_FOG_START) {
getActiveContext()->fogstart = param;
} else if(pname == GL_FOG_END) {
getActiveContext()->fogend = param;
}
old_fogcoord_glFogi(pname, param);
}
}
static void (WINE_GLAPI *old_fogcoord_glFogiv) (GLenum pname, const GLint *param) = NULL;
static void WINE_GLAPI wine_glFogiv(GLenum pname, const GLint *param) {
if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
WineD3DContext *ctx = getActiveContext();
ctx->gl_fog_source = *param;
if(*param == GL_FRAGMENT_DEPTH_EXT) {
if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
} else {
WARN("Fog coords activated, but not supported. Using slow emulation\n");
old_fogcoord_glDisable(GL_FOG);
}
} else {
if(pname == GL_FOG_START) {
getActiveContext()->fogstart = *param;
} else if(pname == GL_FOG_END) {
getActiveContext()->fogend = *param;
}
old_fogcoord_glFogiv(pname, param);
}
}
static void (WINE_GLAPI *old_fogcoord_glFogf) (GLenum pname, GLfloat param) = NULL;
static void WINE_GLAPI wine_glFogf(GLenum pname, GLfloat param) {
if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
WineD3DContext *ctx = getActiveContext();
ctx->gl_fog_source = (GLint) param;
if(param == GL_FRAGMENT_DEPTH_EXT) {
if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
} else {
WARN("Fog coords activated, but not supported. Using slow emulation\n");
old_fogcoord_glDisable(GL_FOG);
}
} else {
if(pname == GL_FOG_START) {
getActiveContext()->fogstart = param;
} else if(pname == GL_FOG_END) {
getActiveContext()->fogend = param;
}
old_fogcoord_glFogf(pname, param);
}
}
static void (WINE_GLAPI *old_fogcoord_glFogfv) (GLenum pname, const GLfloat *param) = NULL;
static void WINE_GLAPI wine_glFogfv(GLenum pname, const GLfloat *param) {
if(pname == GL_FOG_COORDINATE_SOURCE_EXT) {
WineD3DContext *ctx = getActiveContext();
ctx->gl_fog_source = (GLint) *param;
if(*param == GL_FRAGMENT_DEPTH_EXT) {
if(ctx->fog_enabled) old_fogcoord_glEnable(GL_FOG);
} else {
WARN("Fog coords activated, but not supported. Using slow emulation\n");
old_fogcoord_glDisable(GL_FOG);
}
} else {
if(pname == GL_FOG_COLOR) {
WineD3DContext *ctx = getActiveContext();
ctx->fogcolor[0] = param[0];
ctx->fogcolor[1] = param[1];
ctx->fogcolor[2] = param[2];
ctx->fogcolor[3] = param[3];
} else if(pname == GL_FOG_START) {
getActiveContext()->fogstart = *param;
} else if(pname == GL_FOG_END) {
getActiveContext()->fogend = *param;
}
old_fogcoord_glFogfv(pname, param);
}
}
static void (WINE_GLAPI *old_fogcoord_glVertex4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w) = NULL;
static void (WINE_GLAPI *old_fogcoord_glVertex4fv) (const GLfloat *pos) = NULL;
static void (WINE_GLAPI *old_fogcoord_glVertex3f) (GLfloat x, GLfloat y, GLfloat z) = NULL;
static void (WINE_GLAPI *old_fogcoord_glVertex3fv) (const GLfloat *pos) = NULL;
static void (WINE_GLAPI *old_fogcoord_glColor4f) (GLfloat r, GLfloat g, GLfloat b, GLfloat a) = NULL;
static void (WINE_GLAPI *old_fogcoord_glColor4fv) (const GLfloat *color) = NULL;
static void (WINE_GLAPI *old_fogcoord_glColor3f) (GLfloat r, GLfloat g, GLfloat b) = NULL;
static void (WINE_GLAPI *old_fogcoord_glColor3fv) (const GLfloat *color) = NULL;
static void (WINE_GLAPI *old_fogcoord_glColor4ub) (GLubyte r, GLubyte g, GLubyte b, GLubyte a) = NULL;
static void (WINE_GLAPI *old_fogcoord_glFogCoordfEXT) (GLfloat f) = NULL;
static void (WINE_GLAPI *old_fogcoord_glFogCoorddEXT) (GLdouble f) = NULL;
static void (WINE_GLAPI *old_fogcoord_glFogCoordfvEXT) (const GLfloat *f) = NULL;
static void (WINE_GLAPI *old_fogcoord_glFogCoorddvEXT) (const GLdouble *f) = NULL;
static void WINE_GLAPI wine_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
WineD3DContext *ctx = getActiveContext();
if(ctx->gl_fog_source == GL_FOG_COORDINATE_EXT && ctx->fog_enabled) {
GLfloat c[4] = {ctx->color[0], ctx->color[1], ctx->color[2], ctx->color[3]};
GLfloat i;
i = (ctx->fogend - ctx->fog_coord_value) / (ctx->fogend - ctx->fogstart);
c[0] = i * c[0] + (1.0 - i) * ctx->fogcolor[0];
c[1] = i * c[1] + (1.0 - i) * ctx->fogcolor[1];
c[2] = i * c[2] + (1.0 - i) * ctx->fogcolor[2];
old_fogcoord_glColor4f(c[0], c[1], c[2], c[3]);
old_fogcoord_glVertex4f(x, y, z, w);
} else {
old_fogcoord_glVertex4f(x, y, z, w);
}
}
static void WINE_GLAPI wine_glVertex4fv(const GLfloat *pos) {
wine_glVertex4f(pos[0], pos[1], pos[2], pos[3]);
}
static void WINE_GLAPI wine_glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
wine_glVertex4f(x, y, z, 1.0);
}
static void WINE_GLAPI wine_glVertex3fv(const GLfloat *pos) {
wine_glVertex4f(pos[0], pos[1], pos[2], 1.0);
}
static void wine_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
WineD3DContext *ctx = getActiveContext();
ctx->color[0] = r;
ctx->color[1] = g;
ctx->color[2] = b;
ctx->color[3] = a;
old_fogcoord_glColor4f(r, g, b, a);
}
static void wine_glColor4fv(const GLfloat *c) {
wine_glColor4f(c[0], c[1], c[2], c[3]);
}
static void wine_glColor3f(GLfloat r, GLfloat g, GLfloat b) {
wine_glColor4f(r, g, b, 1.0);
}
static void wine_glColor3fv(const GLfloat *c) {
wine_glColor4f(c[0], c[1], c[2], 1.0);
}
static void wine_glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
wine_glColor4f(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
}
/* In D3D the fog coord is a UBYTE, so there's no problem with using the single
* precision function
*/
static void wine_glFogCoordfEXT(GLfloat f) {
WineD3DContext *ctx = getActiveContext();
ctx->fog_coord_value = f;
}
static void wine_glFogCoorddEXT(GLdouble f) {
wine_glFogCoordfEXT(f);
}
static void wine_glFogCoordfvEXT(const GLfloat *f) {
wine_glFogCoordfEXT(*f);
}
static void wine_glFogCoorddvEXT(const GLdouble *f) {
wine_glFogCoordfEXT(*f);
}
/* End GL_EXT_fog_coord emulation */
#define GLINFO_LOCATION (*gl_info)
void add_gl_compat_wrappers(WineD3D_GL_Info *gl_info) {
if(!GL_SUPPORT(ARB_MULTITEXTURE)) {
TRACE("Applying GL_ARB_multitexture emulation hooks\n");
gl_info->glActiveTextureARB = wine_glActiveTextureARB;
gl_info->glClientActiveTextureARB = wine_glClientActiveTextureARB;
gl_info->glMultiTexCoord1fARB = wine_glMultiTexCoord1fARB;
gl_info->glMultiTexCoord1fvARB = wine_glMultiTexCoord1fvARB;
gl_info->glMultiTexCoord2fARB = wine_glMultiTexCoord2fARB;
gl_info->glMultiTexCoord2fvARB = wine_glMultiTexCoord2fvARB;
gl_info->glMultiTexCoord3fARB = wine_glMultiTexCoord3fARB;
gl_info->glMultiTexCoord3fvARB = wine_glMultiTexCoord3fvARB;
gl_info->glMultiTexCoord4fARB = wine_glMultiTexCoord4fARB;
gl_info->glMultiTexCoord4fvARB = wine_glMultiTexCoord4fvARB;
gl_info->glMultiTexCoord2svARB = wine_glMultiTexCoord2svARB;
gl_info->glMultiTexCoord4svARB = wine_glMultiTexCoord4svARB;
if(old_multitex_glGetIntegerv) {
FIXME("GL_ARB_multitexture glGetIntegerv hook already applied\n");
} else {
old_multitex_glGetIntegerv = glGetIntegerv;
glGetIntegerv = wine_glGetIntegerv;
}
if(old_multitex_glGetFloatv) {
FIXME("GL_ARB_multitexture glGetGloatv hook already applied\n");
} else {
old_multitex_glGetFloatv = glGetFloatv;
glGetFloatv = wine_glGetFloatv;
}
if(old_multitex_glGetDoublev) {
FIXME("GL_ARB_multitexture glGetDoublev hook already applied\n");
} else {
old_multitex_glGetDoublev = glGetDoublev;
glGetDoublev = wine_glGetDoublev;
}
gl_info->supported[ARB_MULTITEXTURE] = TRUE;
}
if(!GL_SUPPORT(EXT_FOG_COORD)) {
/* This emulation isn't perfect. There are a number of potential problems, but they should
* not matter in practise:
*
* Fog vs fragment shader: If we are using GL_ARB_fragment_program with the fog option, the
* glDisable(GL_FOG) here won't matter. However, if we have GL_ARB_fragment_program, it is pretty
* unlikely that we don't have GL_EXT_fog_coord. Besides, we probably have GL_ARB_vertex_program
* too, which would allow fog coord emulation in a fixed function vertex pipeline replacement.
*
* Fog vs texture: We apply the fog in the vertex color. An app could set up texturing settings which
* ignore the vertex color, thus effectively disabing our fog. However, in D3D this type of fog is
* a per-vertex fog too, so the apps shouldn't do that.
*
* Fog vs lighting: The app could in theory use D3DFOG_NONE table and D3DFOG_NONE vertex fog with
* untransformed vertices. That enables lighting and fog coords at the same time, and the lighting
* calculations could affect the already blended in fog color. There's nothing we can do against that,
* but most apps using fog color do their own lighting too and often even use RHW vertices. So live
* with it.
*/
TRACE("Applying GL_ARB_fog_coord emulation hooks\n");
/* This probably means that the implementation doesn't advertise the extension, but implicitly supports
* it via the GL core version, or someone messed around in the extension table in directx.c. Add version-
* dependent loading for this extension if we ever hit this situation
*/
if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
FIXME("GL implementation supports GL_ARB_fragment_program but not GL_EXT_fog_coord\n");
FIXME("The fog coord emulation will most likely fail\n");
} else if(GL_SUPPORT(ARB_FRAGMENT_SHADER)) {
FIXME("GL implementation supports GL_ARB_fragment_shader but not GL_EXT_fog_coord\n");
FIXME("The fog coord emulation will most likely fail\n");
}
if(old_fogcoord_glFogi) {
FIXME("GL_EXT_fogcoord glFogi hook already applied\n");
} else {
old_fogcoord_glFogi = glFogi;
glFogi = wine_glFogi;
}
if(old_fogcoord_glFogiv) {
FIXME("GL_EXT_fogcoord glFogiv hook already applied\n");
} else {
old_fogcoord_glFogiv = glFogiv;
glFogiv = wine_glFogiv;
}
if(old_fogcoord_glFogf) {
FIXME("GL_EXT_fogcoord glFogf hook already applied\n");
} else {
old_fogcoord_glFogf = glFogf;
glFogf = wine_glFogf;
}
if(old_fogcoord_glFogfv) {
FIXME("GL_EXT_fogcoord glFogfv hook already applied\n");
} else {
old_fogcoord_glFogfv = glFogfv;
glFogfv = wine_glFogfv;
}
if(old_fogcoord_glEnable) {
FIXME("GL_EXT_fogcoord glEnable hook already applied\n");
} else {
old_fogcoord_glEnable = glEnableWINE;
glEnableWINE = wine_glEnable;
}
if(old_fogcoord_glDisable) {
FIXME("GL_EXT_fogcoord glDisable hook already applied\n");
} else {
old_fogcoord_glDisable = glDisableWINE;
glDisableWINE = wine_glDisable;
}
if(old_fogcoord_glVertex4f) {
FIXME("GL_EXT_fogcoord glVertex4f hook already applied\n");
} else {
old_fogcoord_glVertex4f = glVertex4f;
glVertex4f = wine_glVertex4f;
}
if(old_fogcoord_glVertex4fv) {
FIXME("GL_EXT_fogcoord glVertex4fv hook already applied\n");
} else {
old_fogcoord_glVertex4fv = glVertex4fv;
glVertex4fv = wine_glVertex4fv;
}
if(old_fogcoord_glVertex3f) {
FIXME("GL_EXT_fogcoord glVertex3f hook already applied\n");
} else {
old_fogcoord_glVertex3f = glVertex3f;
glVertex3f = wine_glVertex3f;
}
if(old_fogcoord_glVertex3fv) {
FIXME("GL_EXT_fogcoord glVertex3fv hook already applied\n");
} else {
old_fogcoord_glVertex3fv = glVertex3fv;
glVertex3fv = wine_glVertex3fv;
}
if(old_fogcoord_glColor4f) {
FIXME("GL_EXT_fogcoord glColor4f hook already applied\n");
} else {
old_fogcoord_glColor4f = glColor4f;
glColor4f = wine_glColor4f;
}
if(old_fogcoord_glColor4fv) {
FIXME("GL_EXT_fogcoord glColor4fv hook already applied\n");
} else {
old_fogcoord_glColor4fv = glColor4fv;
glColor4fv = wine_glColor4fv;
}
if(old_fogcoord_glColor3f) {
FIXME("GL_EXT_fogcoord glColor3f hook already applied\n");
} else {
old_fogcoord_glColor3f = glColor3f;
glColor3f = wine_glColor3f;
}
if(old_fogcoord_glColor3fv) {
FIXME("GL_EXT_fogcoord glColor3fv hook already applied\n");
} else {
old_fogcoord_glColor3fv = glColor3fv;
glColor3fv = wine_glColor3fv;
}
if(old_fogcoord_glColor4ub) {
FIXME("GL_EXT_fogcoord glColor4ub hook already applied\n");
} else {
old_fogcoord_glColor4ub = glColor4ub;
glColor4ub = wine_glColor4ub;
}
if(old_fogcoord_glFogCoordfEXT) {
FIXME("GL_EXT_fogcoord glFogCoordfEXT hook already applied\n");
} else {
old_fogcoord_glFogCoordfEXT = gl_info->glFogCoordfEXT;
gl_info->glFogCoordfEXT = wine_glFogCoordfEXT;
}
if(old_fogcoord_glFogCoordfvEXT) {
FIXME("GL_EXT_fogcoord glFogCoordfvEXT hook already applied\n");
} else {
old_fogcoord_glFogCoordfvEXT = gl_info->glFogCoordfvEXT;
gl_info->glFogCoordfvEXT = wine_glFogCoordfvEXT;
}
if(old_fogcoord_glFogCoorddEXT) {
FIXME("GL_EXT_fogcoord glFogCoorddEXT hook already applied\n");
} else {
old_fogcoord_glFogCoorddEXT = gl_info->glFogCoorddEXT;
gl_info->glFogCoorddEXT = wine_glFogCoorddEXT;
}
if(old_fogcoord_glFogCoorddvEXT) {
FIXME("GL_EXT_fogcoord glFogCoorddvEXT hook already applied\n");
} else {
old_fogcoord_glFogCoorddvEXT = gl_info->glFogCoorddvEXT;
gl_info->glFogCoorddvEXT = wine_glFogCoorddvEXT;
}
gl_info->supported[EXT_FOG_COORD] = TRUE;
}
}
#undef GLINFO_LOCATION

File diff suppressed because it is too large Load diff

View file

@ -108,7 +108,7 @@ static DWORD WINAPI IWineD3DIndexBufferImpl_GetPriority(IWineD3DIndexBuffer *ifa
}
static void WINAPI IWineD3DIndexBufferImpl_PreLoad(IWineD3DIndexBuffer *iface) {
FIXME("iface %p stub!\n", iface);
TRACE("iface %p.\n", iface);
}
static void WINAPI IWineD3DIndexBufferImpl_UnLoad(IWineD3DIndexBuffer *iface) {

View file

@ -41,7 +41,7 @@ static void nvts_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateb
}
if(stateblock->textures[stage]) {
switch(stateblock->textureDimensions[stage]) {
switch(IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[stage])) {
case GL_TEXTURE_2D:
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
@ -451,32 +451,24 @@ void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEX
static void nvrc_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
TRACE("Setting color op for stage %d\n", stage);
if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
/* Using a pixel shader? Don't care for anything here, the shader applying does it */
return;
}
/* Using a pixel shader? Don't care for anything here, the shader applying does it */
if (use_ps(stateblock)) return;
if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
if (mapped_stage != -1) {
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
FIXME("Attempt to enable unsupported stage!\n");
return;
}
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
checkGLcall("glActiveTextureARB");
} else if (stage > 0) {
WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
FIXME("Attempt to enable unsupported stage!\n");
return;
}
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
checkGLcall("glActiveTextureARB");
}
if(stateblock->lowest_disabled_stage > 0) {
@ -564,7 +556,7 @@ static void nvts_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
}
static void nvts_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
float mat[2][2];
@ -800,6 +792,13 @@ static const struct StateEntryTemplate nvrc_fragmentstate_template[] = {
{ STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
{ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
{ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), nvrc_texfactor }, 0 },
{ STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
{ STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
{ STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
{ STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
{ STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
{ STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{ STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
{ STATE_SAMPLER(0), { STATE_SAMPLER(0), nvts_texdim }, NV_TEXTURE_SHADER2 },
{ STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
{ STATE_SAMPLER(1), { STATE_SAMPLER(1), nvts_texdim }, NV_TEXTURE_SHADER2 },

View file

@ -1,4 +1,4 @@
/* DirectDraw - IDirectPalette base interface
/* DirectDraw - IDirectPalette base interface
*
* Copyright 1997-2000 Marcus Meissner
* Copyright 2000-2001 TransGaming Technologies Inc.

View file

@ -37,15 +37,46 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
#define GLNAME_REQUIRE_GLSL ((const char *)1)
static HRESULT WINAPI IWineD3DPixelShaderImpl_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, LPVOID *ppobj) {
return IWineD3DBaseShaderImpl_QueryInterface((IWineD3DBaseShader *) iface, riid, ppobj);
TRACE("iface %p, riid %s, ppobj %p\n", iface, debugstr_guid(riid), ppobj);
if (IsEqualGUID(riid, &IID_IWineD3DPixelShader)
|| IsEqualGUID(riid, &IID_IWineD3DBaseShader)
|| IsEqualGUID(riid, &IID_IWineD3DBase)
|| IsEqualGUID(riid, &IID_IUnknown))
{
IUnknown_AddRef(iface);
*ppobj = iface;
return S_OK;
}
WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
*ppobj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface) {
return IWineD3DBaseShaderImpl_AddRef((IWineD3DBaseShader *) iface);
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
ULONG refcount = InterlockedIncrement(&This->baseShader.ref);
TRACE("%p increasing refcount to %u\n", This, refcount);
return refcount;
}
static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
return IWineD3DBaseShaderImpl_Release((IWineD3DBaseShader *) iface);
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
ULONG refcount = InterlockedDecrement(&This->baseShader.ref);
TRACE("%p decreasing refcount to %u\n", This, refcount);
if (!refcount)
{
shader_cleanup((IWineD3DBaseShader *)iface);
HeapFree(GetProcessHeap(), 0, This);
}
return refcount;
}
/* *******************************************
@ -84,111 +115,105 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_GetFunction(IWineD3DPixelShader*
* return D3DERR_MOREDATA. That's not actually true. */
return WINED3DERR_INVALIDCALL;
}
if (NULL == This->baseShader.function) { /* no function defined */
TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
(*(DWORD **) pData) = NULL;
} else {
if (This->baseShader.functionLength == 0) {
}
TRACE("(%p) : GetFunction copying to %p\n", This, pData);
memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
}
TRACE("(%p) : GetFunction copying to %p\n", This, pData);
memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
return WINED3D_OK;
}
CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
/* Arithmetic */
{WINED3DSIO_NOP, "nop", "NOP", 0, 0, WINED3DSIH_NOP, 0, 0 },
{WINED3DSIO_MOV, "mov", "MOV", 1, 2, WINED3DSIH_MOV, 0, 0 },
{WINED3DSIO_ADD, "add", "ADD", 1, 3, WINED3DSIH_ADD, 0, 0 },
{WINED3DSIO_SUB, "sub", "SUB", 1, 3, WINED3DSIH_SUB, 0, 0 },
{WINED3DSIO_MAD, "mad", "MAD", 1, 4, WINED3DSIH_MAD, 0, 0 },
{WINED3DSIO_MUL, "mul", "MUL", 1, 3, WINED3DSIH_MUL, 0, 0 },
{WINED3DSIO_RCP, "rcp", "RCP", 1, 2, WINED3DSIH_RCP, 0, 0 },
{WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, WINED3DSIH_RSQ, 0, 0 },
{WINED3DSIO_DP3, "dp3", "DP3", 1, 3, WINED3DSIH_DP3, 0, 0 },
{WINED3DSIO_DP4, "dp4", "DP4", 1, 3, WINED3DSIH_DP4, 0, 0 },
{WINED3DSIO_MIN, "min", "MIN", 1, 3, WINED3DSIH_MIN, 0, 0 },
{WINED3DSIO_MAX, "max", "MAX", 1, 3, WINED3DSIH_MAX, 0, 0 },
{WINED3DSIO_SLT, "slt", "SLT", 1, 3, WINED3DSIH_SLT, 0, 0 },
{WINED3DSIO_SGE, "sge", "SGE", 1, 3, WINED3DSIH_SGE, 0, 0 },
{WINED3DSIO_ABS, "abs", "ABS", 1, 2, WINED3DSIH_ABS, 0, 0 },
{WINED3DSIO_EXP, "exp", "EX2", 1, 2, WINED3DSIH_EXP, 0, 0 },
{WINED3DSIO_LOG, "log", "LG2", 1, 2, WINED3DSIH_LOG, 0, 0 },
{WINED3DSIO_EXPP, "expp", "EXP", 1, 2, WINED3DSIH_EXPP, 0, 0 },
{WINED3DSIO_LOGP, "logp", "LOG", 1, 2, WINED3DSIH_LOGP, 0, 0 },
{WINED3DSIO_DST, "dst", "DST", 1, 3, WINED3DSIH_DST, 0, 0 },
{WINED3DSIO_LRP, "lrp", "LRP", 1, 4, WINED3DSIH_LRP, 0, 0 },
{WINED3DSIO_FRC, "frc", "FRC", 1, 2, WINED3DSIH_FRC, 0, 0 },
{WINED3DSIO_CND, "cnd", NULL, 1, 4, WINED3DSIH_CND, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_CMP, "cmp", NULL, 1, 4, WINED3DSIH_CMP, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(3,0)},
{WINED3DSIO_POW, "pow", "POW", 1, 3, WINED3DSIH_POW, 0, 0 },
{WINED3DSIO_CRS, "crs", "XPD", 1, 3, WINED3DSIH_CRS, 0, 0 },
{WINED3DSIO_NRM, "nrm", NULL, 1, 2, WINED3DSIH_NRM, 0, 0 },
{WINED3DSIO_SINCOS, "sincos", NULL, 1, 4, WINED3DSIH_SINCOS, WINED3DPS_VERSION(2,0), WINED3DPS_VERSION(2,1)},
{WINED3DSIO_SINCOS, "sincos", "SCS", 1, 2, WINED3DSIH_SINCOS, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_DP2ADD, "dp2add", NULL, 1, 4, WINED3DSIH_DP2ADD, WINED3DPS_VERSION(2,0), -1 },
{WINED3DSIO_NOP, "nop", 0, 0, WINED3DSIH_NOP, 0, 0 },
{WINED3DSIO_MOV, "mov", 1, 2, WINED3DSIH_MOV, 0, 0 },
{WINED3DSIO_ADD, "add", 1, 3, WINED3DSIH_ADD, 0, 0 },
{WINED3DSIO_SUB, "sub", 1, 3, WINED3DSIH_SUB, 0, 0 },
{WINED3DSIO_MAD, "mad", 1, 4, WINED3DSIH_MAD, 0, 0 },
{WINED3DSIO_MUL, "mul", 1, 3, WINED3DSIH_MUL, 0, 0 },
{WINED3DSIO_RCP, "rcp", 1, 2, WINED3DSIH_RCP, 0, 0 },
{WINED3DSIO_RSQ, "rsq", 1, 2, WINED3DSIH_RSQ, 0, 0 },
{WINED3DSIO_DP3, "dp3", 1, 3, WINED3DSIH_DP3, 0, 0 },
{WINED3DSIO_DP4, "dp4", 1, 3, WINED3DSIH_DP4, 0, 0 },
{WINED3DSIO_MIN, "min", 1, 3, WINED3DSIH_MIN, 0, 0 },
{WINED3DSIO_MAX, "max", 1, 3, WINED3DSIH_MAX, 0, 0 },
{WINED3DSIO_SLT, "slt", 1, 3, WINED3DSIH_SLT, 0, 0 },
{WINED3DSIO_SGE, "sge", 1, 3, WINED3DSIH_SGE, 0, 0 },
{WINED3DSIO_ABS, "abs", 1, 2, WINED3DSIH_ABS, 0, 0 },
{WINED3DSIO_EXP, "exp", 1, 2, WINED3DSIH_EXP, 0, 0 },
{WINED3DSIO_LOG, "log", 1, 2, WINED3DSIH_LOG, 0, 0 },
{WINED3DSIO_EXPP, "expp", 1, 2, WINED3DSIH_EXPP, 0, 0 },
{WINED3DSIO_LOGP, "logp", 1, 2, WINED3DSIH_LOGP, 0, 0 },
{WINED3DSIO_DST, "dst", 1, 3, WINED3DSIH_DST, 0, 0 },
{WINED3DSIO_LRP, "lrp", 1, 4, WINED3DSIH_LRP, 0, 0 },
{WINED3DSIO_FRC, "frc", 1, 2, WINED3DSIH_FRC, 0, 0 },
{WINED3DSIO_CND, "cnd", 1, 4, WINED3DSIH_CND, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_CMP, "cmp", 1, 4, WINED3DSIH_CMP, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(3,0)},
{WINED3DSIO_POW, "pow", 1, 3, WINED3DSIH_POW, 0, 0 },
{WINED3DSIO_CRS, "crs", 1, 3, WINED3DSIH_CRS, 0, 0 },
{WINED3DSIO_NRM, "nrm", 1, 2, WINED3DSIH_NRM, 0, 0 },
{WINED3DSIO_SINCOS, "sincos", 1, 4, WINED3DSIH_SINCOS, WINED3DPS_VERSION(2,0), WINED3DPS_VERSION(2,1)},
{WINED3DSIO_SINCOS, "sincos", 1, 2, WINED3DSIH_SINCOS, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_DP2ADD, "dp2add", 1, 4, WINED3DSIH_DP2ADD, WINED3DPS_VERSION(2,0), -1 },
/* Matrix */
{WINED3DSIO_M4x4, "m4x4", "undefined", 1, 3, WINED3DSIH_M4x4, 0, 0 },
{WINED3DSIO_M4x3, "m4x3", "undefined", 1, 3, WINED3DSIH_M4x3, 0, 0 },
{WINED3DSIO_M3x4, "m3x4", "undefined", 1, 3, WINED3DSIH_M3x4, 0, 0 },
{WINED3DSIO_M3x3, "m3x3", "undefined", 1, 3, WINED3DSIH_M3x3, 0, 0 },
{WINED3DSIO_M3x2, "m3x2", "undefined", 1, 3, WINED3DSIH_M3x2, 0, 0 },
{WINED3DSIO_M4x4, "m4x4", 1, 3, WINED3DSIH_M4x4, 0, 0 },
{WINED3DSIO_M4x3, "m4x3", 1, 3, WINED3DSIH_M4x3, 0, 0 },
{WINED3DSIO_M3x4, "m3x4", 1, 3, WINED3DSIH_M3x4, 0, 0 },
{WINED3DSIO_M3x3, "m3x3", 1, 3, WINED3DSIH_M3x3, 0, 0 },
{WINED3DSIO_M3x2, "m3x2", 1, 3, WINED3DSIH_M3x2, 0, 0 },
/* Register declarations */
{WINED3DSIO_DCL, "dcl", NULL, 0, 2, WINED3DSIH_DCL, 0, 0 },
{WINED3DSIO_DCL, "dcl", 0, 2, WINED3DSIH_DCL, 0, 0 },
/* Flow control - requires GLSL or software shaders */
{WINED3DSIO_REP , "rep", NULL, 0, 1, WINED3DSIH_REP, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ENDREP, "endrep", NULL, 0, 0, WINED3DSIH_ENDREP, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_IF, "if", NULL, 0, 1, WINED3DSIH_IF, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_IFC, "ifc", NULL, 0, 2, WINED3DSIH_IFC, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ELSE, "else", NULL, 0, 0, WINED3DSIH_ELSE, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ENDIF, "endif", NULL, 0, 0, WINED3DSIH_ENDIF, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_BREAK, "break", NULL, 0, 0, WINED3DSIH_BREAK, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKC, "breakc", NULL, 0, 2, WINED3DSIH_BREAKC, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, WINED3DSIH_BREAKP, 0, 0 },
{WINED3DSIO_CALL, "call", NULL, 0, 1, WINED3DSIH_CALL, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_CALLNZ, "callnz", NULL, 0, 2, WINED3DSIH_CALLNZ, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_LOOP, "loop", NULL, 0, 2, WINED3DSIH_LOOP, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_RET, "ret", NULL, 0, 0, WINED3DSIH_RET, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ENDLOOP, "endloop", NULL, 0, 0, WINED3DSIH_ENDLOOP, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_LABEL, "label", NULL, 0, 1, WINED3DSIH_LABEL, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_REP , "rep", 0, 1, WINED3DSIH_REP, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ENDREP, "endrep", 0, 0, WINED3DSIH_ENDREP, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_IF, "if", 0, 1, WINED3DSIH_IF, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_IFC, "ifc", 0, 2, WINED3DSIH_IFC, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ELSE, "else", 0, 0, WINED3DSIH_ELSE, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ENDIF, "endif", 0, 0, WINED3DSIH_ENDIF, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_BREAK, "break", 0, 0, WINED3DSIH_BREAK, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKC, "breakc", 0, 2, WINED3DSIH_BREAKC, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKP, "breakp", 0, 1, WINED3DSIH_BREAKP, 0, 0 },
{WINED3DSIO_CALL, "call", 0, 1, WINED3DSIH_CALL, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_CALLNZ, "callnz", 0, 2, WINED3DSIH_CALLNZ, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_LOOP, "loop", 0, 2, WINED3DSIH_LOOP, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_RET, "ret", 0, 0, WINED3DSIH_RET, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_ENDLOOP, "endloop", 0, 0, WINED3DSIH_ENDLOOP, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_LABEL, "label", 0, 1, WINED3DSIH_LABEL, WINED3DPS_VERSION(2,1), -1 },
/* Constant definitions */
{WINED3DSIO_DEF, "def", "undefined", 1, 5, WINED3DSIH_DEF, 0, 0 },
{WINED3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 1, 2, WINED3DSIH_DEFB, 0, 0 },
{WINED3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, WINED3DSIH_DEFI, 0, 0 },
{WINED3DSIO_DEF, "def", 1, 5, WINED3DSIH_DEF, 0, 0 },
{WINED3DSIO_DEFB, "defb", 1, 2, WINED3DSIH_DEFB, 0, 0 },
{WINED3DSIO_DEFI, "defi", 1, 5, WINED3DSIH_DEFI, 0, 0 },
/* Texture */
{WINED3DSIO_TEXCOORD, "texcoord", "undefined", 1, 1, WINED3DSIH_TEXCOORD, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXCOORD, "texcrd", "undefined", 1, 2, WINED3DSIH_TEXCOORD, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_TEXKILL, "texkill", "KIL", 1, 1, WINED3DSIH_TEXKILL, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(3,0)},
{WINED3DSIO_TEX, "tex", "undefined", 1, 1, WINED3DSIH_TEX, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEX, "texld", "undefined", 1, 2, WINED3DSIH_TEX, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_TEX, "texld", "undefined", 1, 3, WINED3DSIH_TEX, WINED3DPS_VERSION(2,0), -1 },
{WINED3DSIO_TEXBEM, "texbem", "undefined", 1, 2, WINED3DSIH_TEXBEM, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 1, 2, WINED3DSIH_TEXBEML, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2AR, "texreg2ar", "undefined", 1, 2, WINED3DSIH_TEXREG2AR, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2GB, "texreg2gb", "undefined", 1, 2, WINED3DSIH_TEXREG2GB, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2RGB, "texreg2rgb", "undefined", 1, 2, WINED3DSIH_TEXREG2RGB, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x2PAD, "texm3x2pad", "undefined", 1, 2, WINED3DSIH_TEXM3x2PAD, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x2TEX, "texm3x2tex", "undefined", 1, 2, WINED3DSIH_TEXM3x2TEX, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3PAD, "texm3x3pad", "undefined", 1, 2, WINED3DSIH_TEXM3x3PAD, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3DIFF, "texm3x3diff", GLNAME_REQUIRE_GLSL, 1, 2, WINED3DSIH_TEXM3x3DIFF, WINED3DPS_VERSION(0,0), WINED3DPS_VERSION(0,0)},
{WINED3DSIO_TEXM3x3SPEC, "texm3x3spec", "undefined", 1, 3, WINED3DSIH_TEXM3x3SPEC, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3VSPEC, "texm3x3vspec", "undefined", 1, 2, WINED3DSIH_TEXM3x3VSPEC, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3TEX, "texm3x3tex", "undefined", 1, 2, WINED3DSIH_TEXM3x3TEX, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXDP3TEX, "texdp3tex", NULL, 1, 2, WINED3DSIH_TEXDP3TEX, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, WINED3DSIH_TEXM3x2DEPTH, WINED3DPS_VERSION(1,3), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXDP3, "texdp3", NULL, 1, 2, WINED3DSIH_TEXDP3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3, "texm3x3", NULL, 1, 2, WINED3DSIH_TEXM3x3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXDEPTH, "texdepth", NULL, 1, 1, WINED3DSIH_TEXDEPTH, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_BEM, "bem", "undefined", 1, 3, WINED3DSIH_BEM, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_DSX, "dsx", NULL, 1, 2, WINED3DSIH_DSX, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_DSY, "dsy", NULL, 1, 2, WINED3DSIH_DSY, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 1, 5, WINED3DSIH_TEXLDD, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 1, 3, WINED3DSIH_SETP, 0, 0 },
{WINED3DSIO_TEXLDL, "texldl", NULL, 1, 3, WINED3DSIH_TEXLDL, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, 0, WINED3DSIH_PHASE, 0, 0 },
{0, NULL, NULL, 0, 0, 0, 0, 0 }
{WINED3DSIO_TEXCOORD, "texcoord", 1, 1, WINED3DSIH_TEXCOORD, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXCOORD, "texcrd", 1, 2, WINED3DSIH_TEXCOORD, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_TEXKILL, "texkill", 1, 1, WINED3DSIH_TEXKILL, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(3,0)},
{WINED3DSIO_TEX, "tex", 1, 1, WINED3DSIH_TEX, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEX, "texld", 1, 2, WINED3DSIH_TEX, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_TEX, "texld", 1, 3, WINED3DSIH_TEX, WINED3DPS_VERSION(2,0), -1 },
{WINED3DSIO_TEXBEM, "texbem", 1, 2, WINED3DSIH_TEXBEM, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXBEML, "texbeml", 1, 2, WINED3DSIH_TEXBEML, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2AR, "texreg2ar", 1, 2, WINED3DSIH_TEXREG2AR, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2GB, "texreg2gb", 1, 2, WINED3DSIH_TEXREG2GB, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2RGB, "texreg2rgb", 1, 2, WINED3DSIH_TEXREG2RGB, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x2PAD, "texm3x2pad", 1, 2, WINED3DSIH_TEXM3x2PAD, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x2TEX, "texm3x2tex", 1, 2, WINED3DSIH_TEXM3x2TEX, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3PAD, "texm3x3pad", 1, 2, WINED3DSIH_TEXM3x3PAD, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3DIFF, "texm3x3diff", 1, 2, WINED3DSIH_TEXM3x3DIFF, WINED3DPS_VERSION(0,0), WINED3DPS_VERSION(0,0)},
{WINED3DSIO_TEXM3x3SPEC, "texm3x3spec", 1, 3, WINED3DSIH_TEXM3x3SPEC, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3VSPEC, "texm3x3vspec", 1, 2, WINED3DSIH_TEXM3x3VSPEC, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3TEX, "texm3x3tex", 1, 2, WINED3DSIH_TEXM3x3TEX, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXDP3TEX, "texdp3tex", 1, 2, WINED3DSIH_TEXDP3TEX, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x2DEPTH, "texm3x2depth", 1, 2, WINED3DSIH_TEXM3x2DEPTH, WINED3DPS_VERSION(1,3), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXDP3, "texdp3", 1, 2, WINED3DSIH_TEXDP3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXM3x3, "texm3x3", 1, 2, WINED3DSIH_TEXM3x3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXDEPTH, "texdepth", 1, 1, WINED3DSIH_TEXDEPTH, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_BEM, "bem", 1, 3, WINED3DSIH_BEM, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_DSX, "dsx", 1, 2, WINED3DSIH_DSX, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_DSY, "dsy", 1, 2, WINED3DSIH_DSY, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_TEXLDD, "texldd", 1, 5, WINED3DSIH_TEXLDD, WINED3DPS_VERSION(2,1), -1 },
{WINED3DSIO_SETP, "setp", 1, 3, WINED3DSIH_SETP, 0, 0 },
{WINED3DSIO_TEXLDL, "texldl", 1, 3, WINED3DSIH_TEXLDL, WINED3DPS_VERSION(3,0), -1 },
{WINED3DSIO_PHASE, "phase", 0, 0, WINED3DSIH_PHASE, 0, 0 },
{0, NULL, 0, 0, 0, 0, 0 }
};
static void pshader_set_limits(
@ -198,7 +223,8 @@ static void pshader_set_limits(
This->baseShader.limits.address = 0;
This->baseShader.limits.packed_output = 0;
switch (This->baseShader.hex_version) {
switch (This->baseShader.reg_maps.shader_version)
{
case WINED3DPS_VERSION(1,0):
case WINED3DPS_VERSION(1,1):
case WINED3DPS_VERSION(1,2):
@ -265,154 +291,159 @@ static void pshader_set_limits(
This->baseShader.limits.sampler = 16;
This->baseShader.limits.packed_input = 0;
This->baseShader.limits.label = 0;
FIXME("Unrecognized pixel shader version %#x\n",
This->baseShader.hex_version);
FIXME("Unrecognized pixel shader version %#x\n",
This->baseShader.reg_maps.shader_version);
}
}
/** Generate a pixel shader string using either GL_FRAGMENT_PROGRAM_ARB
or GLSL and send it to the card */
static inline GLuint IWineD3DPixelShaderImpl_GenerateShader(
IWineD3DPixelShaderImpl *This) {
SHADER_BUFFER buffer;
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
buffer.bsize = 0;
buffer.lineNo = 0;
buffer.newline = TRUE;
return ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_pshader((IWineD3DPixelShader *) This, &buffer);
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
unsigned int i, highest_reg_used = 0, num_regs_used = 0;
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
HRESULT hr;
TRACE("(%p) : pFunction %p\n", iface, pFunction);
/* First pass: trace shader */
shader_trace_init((IWineD3DBaseShader*) This, pFunction);
pshader_set_limits(This);
if (TRACE_ON(d3d_shader)) shader_trace_init(pFunction, This->baseShader.shader_ins);
/* Initialize immediate constant lists */
list_init(&This->baseShader.constantsF);
list_init(&This->baseShader.constantsB);
list_init(&This->baseShader.constantsI);
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) > 1) {
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
HRESULT hr;
unsigned int i, j, highest_reg_used = 0, num_regs_used = 0;
/* Second pass: figure out which registers are used, what the semantics are, etc.. */
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader *)This, reg_maps, This->semantics_in, NULL, pFunction);
if (FAILED(hr)) return hr;
/* Second pass: figure out which registers are used, what the semantics are, etc.. */
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, reg_maps,
This->semantics_in, NULL, pFunction, NULL);
if (FAILED(hr)) return hr;
/* FIXME: validate reg_maps against OpenGL */
pshader_set_limits(This);
for(i = 0; i < MAX_REG_INPUT; i++) {
if(This->input_reg_used[i]) {
num_regs_used++;
highest_reg_used = i;
}
}
/* Don't do any register mapping magic if it is not needed, or if we can't
* achieve anything anyway
*/
if(highest_reg_used < (GL_LIMITS(glsl_varyings) / 4) ||
num_regs_used > (GL_LIMITS(glsl_varyings) / 4) ) {
if(num_regs_used > (GL_LIMITS(glsl_varyings) / 4)) {
/* This happens with relative addressing. The input mapper function
* warns about this if the higher registers are declared too, so
* don't write a FIXME here
*/
WARN("More varying registers used than supported\n");
}
for(i = 0; i < MAX_REG_INPUT; i++) {
This->input_reg_map[i] = i;
}
This->declared_in_count = highest_reg_used + 1;
} else {
j = 0;
for(i = 0; i < MAX_REG_INPUT; i++) {
if(This->input_reg_used[i]) {
This->input_reg_map[i] = j;
j++;
} else {
This->input_reg_map[i] = -1;
}
}
This->declared_in_count = j;
for (i = 0; i < MAX_REG_INPUT; ++i)
{
if (This->input_reg_used[i])
{
++num_regs_used;
highest_reg_used = i;
}
}
/* Don't do any register mapping magic if it is not needed, or if we can't
* achieve anything anyway */
if (highest_reg_used < (GL_LIMITS(glsl_varyings) / 4)
|| num_regs_used > (GL_LIMITS(glsl_varyings) / 4))
{
if (num_regs_used > (GL_LIMITS(glsl_varyings) / 4))
{
/* This happens with relative addressing. The input mapper function
* warns about this if the higher registers are declared too, so
* don't write a FIXME here */
WARN("More varying registers used than supported\n");
}
for (i = 0; i < MAX_REG_INPUT; ++i)
{
This->input_reg_map[i] = i;
}
This->declared_in_count = highest_reg_used + 1;
}
else
{
This->declared_in_count = 0;
for (i = 0; i < MAX_REG_INPUT; ++i)
{
if (This->input_reg_used[i]) This->input_reg_map[i] = This->declared_in_count++;
else This->input_reg_map[i] = -1;
}
}
This->baseShader.load_local_constsF = FALSE;
This->baseShader.shader_mode = deviceImpl->ps_selected_mode;
TRACE("(%p) : Copying the function\n", This);
if (NULL != pFunction) {
void *function;
function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
if (!function) return E_OUTOFMEMORY;
memcpy(function, pFunction, This->baseShader.functionLength);
This->baseShader.function = function;
} else {
This->baseShader.function = NULL;
}
This->baseShader.function = HeapAlloc(GetProcessHeap(), 0, This->baseShader.functionLength);
if (!This->baseShader.function) return E_OUTOFMEMORY;
memcpy(This->baseShader.function, pFunction, This->baseShader.functionLength);
return WINED3D_OK;
}
static void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD3DBaseTexture * const *textures)
{
DWORD shader_version = reg_maps->shader_version;
DWORD *samplers = reg_maps->samplers;
unsigned int i;
if (WINED3DSHADER_VERSION_MAJOR(shader_version) != 1) return;
for (i = 0; i < max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS); ++i)
{
/* We don't sample from this sampler */
if (!samplers[i]) continue;
if (!textures[i])
{
ERR("No texture bound to sampler %u, using 2D\n", i);
samplers[i] = (0x1 << 31) | WINED3DSTT_2D;
continue;
}
switch (IWineD3DBaseTexture_GetTextureDimensions(textures[i]))
{
case GL_TEXTURE_RECTANGLE_ARB:
case GL_TEXTURE_2D:
/* We have to select between texture rectangles and 2D textures later because 2.0 and
* 3.0 shaders only have WINED3DSTT_2D as well */
samplers[i] = (1 << 31) | WINED3DSTT_2D;
break;
case GL_TEXTURE_3D:
samplers[i] = (1 << 31) | WINED3DSTT_VOLUME;
break;
case GL_TEXTURE_CUBE_MAP_ARB:
samplers[i] = (1 << 31) | WINED3DSTT_CUBE;
break;
default:
FIXME("Unrecognized texture type %#x, using 2D\n",
IWineD3DBaseTexture_GetTextureDimensions(textures[i]));
samplers[i] = (0x1 << 31) | WINED3DSTT_2D;
}
}
}
static GLuint pixelshader_compile(IWineD3DPixelShaderImpl *This, const struct ps_compile_args *args)
{
CONST DWORD *function = This->baseShader.function;
HRESULT hr;
GLuint retval;
SHADER_BUFFER buffer;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
TRACE("(%p) : function %p\n", This, function);
hr = IWineD3DPixelShader_UpdateSamplers((IWineD3DPixelShader *) This);
if(FAILED(hr)) {
ERR("Failed to update sampler information\n");
return 0;
}
pixelshader_update_samplers(&This->baseShader.reg_maps,
((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->textures);
/* Reset fields tracking stateblock values being hardcoded in the shader */
This->baseShader.num_sampled_samplers = 0;
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
retval = IWineD3DPixelShaderImpl_GenerateShader(This);
shader_buffer_init(&buffer);
retval = device->shader_backend->shader_generate_pshader((IWineD3DPixelShader *)This, &buffer, args);
shader_buffer_free(&buffer);
This->baseShader.is_compiled = TRUE;
return retval;
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_UpdateSamplers(IWineD3DPixelShader *iface) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) {
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
HRESULT hr;
/* Second pass: figure out which registers are used, what the semantics are, etc.. */
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*)This, reg_maps,
This->semantics_in, NULL, This->baseShader.function, deviceImpl->stateBlock);
return hr;
/* FIXME: validate reg_maps against OpenGL */
} else {
return WINED3D_OK;
}
}
const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
{
/*** IUnknown methods ***/
@ -424,7 +455,6 @@ const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
/*** IWineD3DBaseShader methods ***/
IWineD3DPixelShaderImpl_SetFunction,
/*** IWineD3DPixelShader methods ***/
IWineD3DPixelShaderImpl_UpdateSamplers,
IWineD3DPixelShaderImpl_GetDevice,
IWineD3DPixelShaderImpl_GetFunction
};
@ -433,9 +463,9 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp
UINT i, sampler;
IWineD3DBaseTextureImpl *tex;
memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set */
args->srgb_correction = stateblock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0;
memset(args->color_fixup, 0, sizeof(args->color_fixup));
for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) {
sampler = shader->baseShader.sampled_samplers[i];
tex = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
@ -445,16 +475,45 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp
}
args->color_fixup[sampler] = tex->baseTexture.shader_color_fixup;
}
if(shader->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) {
if(((IWineD3DDeviceImpl *) shader->baseShader.device)->strided_streams.u.s.position_transformed) {
if (shader->baseShader.reg_maps.shader_version >= WINED3DPS_VERSION(3,0))
{
if (((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.position_transformed)
{
args->vp_mode = pretransformed;
} else if(use_vs((IWineD3DDeviceImpl *) shader->baseShader.device)) {
}
else if (use_vs(stateblock))
{
args->vp_mode = vertexshader;
} else {
args->vp_mode = fixedfunction;
}
args->fog = FOG_OFF;
} else {
args->vp_mode = vertexshader;
if(stateblock->renderState[WINED3DRS_FOGENABLE]) {
switch(stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
case WINED3DFOG_NONE:
if (((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.position_transformed
|| use_vs(stateblock))
{
args->fog = FOG_LINEAR;
break;
}
switch(stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
case WINED3DFOG_NONE: /* Drop through */
case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
case WINED3DFOG_EXP: args->fog = FOG_EXP; break;
case WINED3DFOG_EXP2: args->fog = FOG_EXP2; break;
}
break;
case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
case WINED3DFOG_EXP: args->fog = FOG_EXP; break;
case WINED3DFOG_EXP2: args->fog = FOG_EXP2; break;
}
} else {
args->fog = FOG_OFF;
}
}
}

View file

@ -63,8 +63,18 @@ static ULONG WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
ENTER_GL();
/* Queries are specific to the GL context that created them. Not
* deleting the query will obviously leak it, but that's still better
* than potentially deleting a different query with the same id in this
* context, and (still) leaking the actual query. */
if(This->type == WINED3DQUERYTYPE_EVENT) {
if(GL_SUPPORT(APPLE_FENCE)) {
if (((WineQueryEventData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
|| This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
{
FIXME("Query was created in a different context, skipping deletion\n");
}
else if(GL_SUPPORT(APPLE_FENCE))
{
GL_EXTCALL(glDeleteFencesAPPLE(1, &((WineQueryEventData *)(This->extendedData))->fenceId));
checkGLcall("glDeleteFencesAPPLE");
} else if(GL_SUPPORT(NV_FENCE)) {
@ -72,8 +82,16 @@ static ULONG WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
checkGLcall("glDeleteFencesNV");
}
} else if(This->type == WINED3DQUERYTYPE_OCCLUSION && GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
GL_EXTCALL(glDeleteQueriesARB(1, &((WineQueryOcclusionData *)(This->extendedData))->queryId));
checkGLcall("glDeleteQueriesARB");
if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
|| This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
{
FIXME("Query was created in a different context, skipping deletion\n");
}
else
{
GL_EXTCALL(glDeleteQueriesARB(1, &((WineQueryOcclusionData *)(This->extendedData))->queryId));
checkGLcall("glDeleteQueriesARB");
}
}
LEAVE_GL();
@ -268,48 +286,68 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa
static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId;
DWORD* data = pData;
GLuint available;
GLuint samples;
HRESULT res;
TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
if(This->state == QUERY_CREATED) {
if (This->state == QUERY_CREATED)
{
/* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
TRACE("Query wasn't yet started, returning S_OK\n");
res = S_OK;
if(data) *data = 0;
} else if(This->state == QUERY_BUILDING) {
return S_OK;
}
if (This->state == QUERY_BUILDING)
{
/* Msdn says this returns an error, but our tests show that S_FALSE is returned */
TRACE("Query is building, returning S_FALSE\n");
res = S_FALSE;
} else if (GL_SUPPORT(ARB_OCCLUSION_QUERY) &&
((WineQueryOcclusionData *)This->extendedData)->ctx == This->wineD3DDevice->activeContext &&
This->wineD3DDevice->activeContext->tid == GetCurrentThreadId()) {
GLuint available;
GLuint samples;
GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId;
return S_FALSE;
}
ENTER_GL();
GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n");
TRACE("(%p) : available %d.\n", This, available);
if (available) {
if(data) {
GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples));
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n");
TRACE("(%p) : Returning %d samples.\n", This, samples);
*data = samples;
}
res = S_OK;
} else {
res = S_FALSE;
}
LEAVE_GL();
} else {
WARN("(%p) : Occlusion queries not supported, or wrong context. Returning 1.\n", This);
if (!GL_SUPPORT(ARB_OCCLUSION_QUERY))
{
WARN("(%p) : Occlusion queries not supported. Returning 1.\n", This);
*data = 1;
return S_OK;
}
if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
|| This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
{
FIXME("%p Wrong context, returning 1.\n", This);
*data = 1;
return S_OK;
}
ENTER_GL();
GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n");
TRACE("(%p) : available %d.\n", This, available);
if (available)
{
if (data)
{
GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples));
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n");
TRACE("(%p) : Returning %d samples.\n", This, samples);
*data = samples;
}
res = S_OK;
}
else
{
res = S_FALSE;
}
LEAVE_GL();
return res;
}
@ -324,7 +362,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
return S_OK;
} if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
/* See comment in IWineD3DQuery::Issue, event query codeblock */
WARN("Query context not active, reporting GPU idle\n");
FIXME("Query context not active, reporting GPU idle\n");
*data = TRUE;
} else if(GL_SUPPORT(APPLE_FENCE)) {
ENTER_GL();
@ -460,7 +498,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D
WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx;
if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
WARN("Not the owning context, can't start query\n");
FIXME("Not the owning context, can't start query\n");
} else {
ENTER_GL();
/* This is allowed according to msdn and our tests. Reset the query and restart */

View file

@ -27,6 +27,50 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
HRESULT resource_init(struct IWineD3DResourceClass *resource, WINED3DRESOURCETYPE resource_type,
IWineD3DDeviceImpl *device, UINT size, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent)
{
resource->wineD3DDevice = device;
resource->parent = parent;
resource->resourceType = resource_type;
resource->ref = 1;
resource->pool = pool;
resource->format = format;
resource->usage = usage;
resource->size = size;
resource->priority = 0;
list_init(&resource->privateData);
if (size)
{
resource->heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + RESOURCE_ALIGNMENT);
if (!resource->heapMemory)
{
ERR("Out of memory!\n");
return WINED3DERR_OUTOFVIDEOMEMORY;
}
}
else
{
resource->heapMemory = NULL;
}
resource->allocatedMemory = (BYTE *)(((ULONG_PTR)resource->heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
/* Check that we have enough video ram left */
if (pool == WINED3DPOOL_DEFAULT)
{
if (size > IWineD3DDevice_GetAvailableTextureMem((IWineD3DDevice *)device))
{
ERR("Out of adapter memory\n");
HeapFree(GetProcessHeap(), 0, resource->heapMemory);
return WINED3DERR_OUTOFVIDEOMEMORY;
}
WineD3DAdapterChangeGLRam(device, size);
}
return WINED3D_OK;
}
void resource_cleanup(IWineD3DResource *iface)
{
IWineD3DResourceImpl *This = (IWineD3DResourceImpl *)iface;

File diff suppressed because it is too large Load diff

View file

@ -38,28 +38,36 @@ HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) {
IWineD3DStateBlockImpl *This = object;
#define WINED3D_MEMCHECK(_object) if (NULL == _object) { FIXME("Out of memory!\n"); return E_OUTOFMEMORY; }
/* Allocate space for floating point constants */
object->pixelShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
WINED3D_MEMCHECK(object->pixelShaderConstantF);
if (!object->pixelShaderConstantF) goto fail;
object->changed.pixelShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(pshader_constantsF));
WINED3D_MEMCHECK(object->changed.pixelShaderConstantsF);
if (!object->changed.pixelShaderConstantsF) goto fail;
object->vertexShaderConstantF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4);
WINED3D_MEMCHECK(object->vertexShaderConstantF);
if (!object->vertexShaderConstantF) goto fail;
object->changed.vertexShaderConstantsF = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOL) * GL_LIMITS(vshader_constantsF));
WINED3D_MEMCHECK(object->changed.vertexShaderConstantsF);
if (!object->changed.vertexShaderConstantsF) goto fail;
object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(vshader_constantsF));
WINED3D_MEMCHECK(object->contained_vs_consts_f);
if (!object->contained_vs_consts_f) goto fail;
object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(pshader_constantsF));
WINED3D_MEMCHECK(object->contained_ps_consts_f);
list_init(&object->set_vconstantsF);
list_init(&object->set_pconstantsF);
#undef WINED3D_MEMCHECK
if (!object->contained_ps_consts_f) goto fail;
return WINED3D_OK;
fail:
ERR("Failed to allocate memory\n");
HeapFree(GetProcessHeap(), 0, object->pixelShaderConstantF);
HeapFree(GetProcessHeap(), 0, object->changed.pixelShaderConstantsF);
HeapFree(GetProcessHeap(), 0, object->vertexShaderConstantF);
HeapFree(GetProcessHeap(), 0, object->changed.vertexShaderConstantsF);
HeapFree(GetProcessHeap(), 0, object->contained_vs_consts_f);
HeapFree(GetProcessHeap(), 0, object->contained_ps_consts_f);
return E_OUTOFMEMORY;
}
/** Copy all members of one stateblock to another */
@ -71,7 +79,6 @@ static void stateblock_savedstates_copy(IWineD3DStateBlock* iface, SAVEDSTATES *
/* Single values */
dest->indices = source->indices;
dest->material = source->material;
dest->fvf = source->fvf;
dest->viewport = source->viewport;
dest->vertexDecl = source->vertexDecl;
dest->pixelShader = source->pixelShader;
@ -79,14 +86,14 @@ static void stateblock_savedstates_copy(IWineD3DStateBlock* iface, SAVEDSTATES *
dest->scissorRect = dest->scissorRect;
/* Fixed size arrays */
memcpy(dest->streamSource, source->streamSource, bsize * MAX_STREAMS);
memcpy(dest->streamFreq, source->streamFreq, bsize * MAX_STREAMS);
memcpy(dest->textures, source->textures, bsize * MAX_COMBINED_SAMPLERS);
memcpy(dest->transform, source->transform, bsize * (HIGHEST_TRANSFORMSTATE + 1));
memcpy(dest->renderState, source->renderState, bsize * (WINEHIGHEST_RENDER_STATE + 1));
memcpy(dest->textureState, source->textureState, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
memcpy(dest->samplerState, source->samplerState, bsize * MAX_COMBINED_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1));
memcpy(dest->clipplane, source->clipplane, bsize * MAX_CLIPPLANES);
dest->streamSource = source->streamSource;
dest->streamFreq = source->streamFreq;
dest->textures = source->textures;
memcpy(dest->transform, source->transform, sizeof(source->transform));
memcpy(dest->renderState, source->renderState, sizeof(source->renderState));
memcpy(dest->textureState, source->textureState, sizeof(source->textureState));
memcpy(dest->samplerState, source->samplerState, sizeof(source->samplerState));
dest->clipplane = source->clipplane;
dest->pixelShaderConstantsB = source->pixelShaderConstantsB;
dest->pixelShaderConstantsI = source->pixelShaderConstantsI;
dest->vertexShaderConstantsB = source->vertexShaderConstantsB;
@ -97,6 +104,13 @@ static void stateblock_savedstates_copy(IWineD3DStateBlock* iface, SAVEDSTATES *
memcpy(dest->vertexShaderConstantsF, source->vertexShaderConstantsF, bsize * GL_LIMITS(vshader_constantsF));
}
static inline void stateblock_set_bits(DWORD *map, UINT map_size)
{
DWORD mask = (1 << (map_size & 0x1f)) - 1;
memset(map, 0xff, (map_size >> 5) * sizeof(*map));
if (mask) map[map_size >> 5] = mask;
}
/** Set all members of a stateblock savedstate to the given value */
void stateblock_savedstates_set(
IWineD3DStateBlock* iface,
@ -109,7 +123,6 @@ void stateblock_savedstates_set(
/* Single values */
states->indices = value;
states->material = value;
states->fvf = value;
states->viewport = value;
states->vertexDecl = value;
states->pixelShader = value;
@ -117,18 +130,37 @@ void stateblock_savedstates_set(
states->scissorRect = value;
/* Fixed size arrays */
memset(states->streamSource, value, bsize * MAX_STREAMS);
memset(states->streamFreq, value, bsize * MAX_STREAMS);
memset(states->textures, value, bsize * MAX_COMBINED_SAMPLERS);
memset(states->transform, value, bsize * (HIGHEST_TRANSFORMSTATE + 1));
memset(states->renderState, value, bsize * (WINEHIGHEST_RENDER_STATE + 1));
memset(states->textureState, value, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
memset(states->samplerState, value, bsize * MAX_COMBINED_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1));
memset(states->clipplane, value, bsize * MAX_CLIPPLANES);
states->pixelShaderConstantsB = value ? 0xffff : 0;
states->pixelShaderConstantsI = value ? 0xffff : 0;
states->vertexShaderConstantsB = value ? 0xffff : 0;
states->vertexShaderConstantsI = value ? 0xffff : 0;
if (value)
{
int i;
states->streamSource = 0xffff;
states->streamFreq = 0xffff;
states->textures = 0xfffff;
stateblock_set_bits(states->transform, HIGHEST_TRANSFORMSTATE + 1);
stateblock_set_bits(states->renderState, WINEHIGHEST_RENDER_STATE + 1);
for (i = 0; i < MAX_TEXTURES; ++i) states->textureState[i] = 0x3ffff;
for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) states->samplerState[i] = 0x3fff;
states->clipplane = 0xffffffff;
states->pixelShaderConstantsB = 0xffff;
states->pixelShaderConstantsI = 0xffff;
states->vertexShaderConstantsB = 0xffff;
states->vertexShaderConstantsI = 0xffff;
}
else
{
states->streamSource = 0;
states->streamFreq = 0;
states->textures = 0;
memset(states->transform, 0, sizeof(states->transform));
memset(states->renderState, 0, sizeof(states->renderState));
memset(states->textureState, 0, sizeof(states->textureState));
memset(states->samplerState, 0, sizeof(states->samplerState));
states->clipplane = 0;
states->pixelShaderConstantsB = 0;
states->pixelShaderConstantsI = 0;
states->vertexShaderConstantsB = 0;
states->vertexShaderConstantsI = 0;
}
/* Dynamically sized arrays */
memset(states->pixelShaderConstantsF, value, bsize * GL_LIMITS(pshader_constantsF));
@ -156,7 +188,6 @@ void stateblock_copy(
stateblock_savedstates_copy(source, &Dest->changed, &This->changed);
/* Single items */
Dest->fvf = This->fvf;
Dest->vertexDecl = This->vertexDecl;
Dest->vertexShader = This->vertexShader;
Dest->streamIsUP = This->streamIsUP;
@ -203,7 +234,6 @@ void stateblock_copy(
memcpy(Dest->clipplane, This->clipplane, sizeof(double) * MAX_CLIPPLANES * 4);
memcpy(Dest->renderState, This->renderState, sizeof(DWORD) * (WINEHIGHEST_RENDER_STATE + 1));
memcpy(Dest->textures, This->textures, sizeof(IWineD3DBaseTexture*) * MAX_COMBINED_SAMPLERS);
memcpy(Dest->textureDimensions, This->textureDimensions, sizeof(int) * MAX_COMBINED_SAMPLERS);
memcpy(Dest->textureState, This->textureState, sizeof(DWORD) * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1));
memcpy(Dest->samplerState, This->samplerState, sizeof(DWORD) * MAX_COMBINED_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1));
@ -245,7 +275,6 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
if (!refCount) {
constants_entry *constant, *constant2;
int counter;
/* type 0 represents the primary stateblock, so free all the resources */
@ -287,15 +316,6 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
HeapFree(GetProcessHeap(), 0, This->contained_vs_consts_f);
HeapFree(GetProcessHeap(), 0, This->contained_ps_consts_f);
LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_vconstantsF, constants_entry, entry) {
HeapFree(GetProcessHeap(), 0, constant);
}
LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_pconstantsF, constants_entry, entry) {
HeapFree(GetProcessHeap(), 0, constant);
}
HeapFree(GetProcessHeap(), 0, This);
}
return refCount;
@ -378,6 +398,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface;
IWineD3DStateBlockImpl *targetStateBlock = This->wineD3DDevice->stateBlock;
unsigned int i, j;
DWORD map;
TRACE("(%p) : Updating state block %p ------------------v\n", targetStateBlock, This);
@ -396,11 +417,11 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
/* Vertex Shader Float Constants */
for (j = 0; j < This->num_contained_vs_consts_f; ++j) {
i = This->contained_vs_consts_f[j];
TRACE("Setting %p from %p %d to { %f, %f, %f, %f }\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantF[i * 4],
targetStateBlock->vertexShaderConstantF[i * 4 + 1],
targetStateBlock->vertexShaderConstantF[i * 4 + 2],
targetStateBlock->vertexShaderConstantF[i * 4 + 3]);
TRACE("Setting %p from %p %u to {%f, %f, %f, %f}\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantF[i * 4],
targetStateBlock->vertexShaderConstantF[i * 4 + 1],
targetStateBlock->vertexShaderConstantF[i * 4 + 2],
targetStateBlock->vertexShaderConstantF[i * 4 + 3]);
This->vertexShaderConstantF[i * 4] = targetStateBlock->vertexShaderConstantF[i * 4];
This->vertexShaderConstantF[i * 4 + 1] = targetStateBlock->vertexShaderConstantF[i * 4 + 1];
@ -411,11 +432,11 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
/* Vertex Shader Integer Constants */
for (j = 0; j < This->num_contained_vs_consts_i; ++j) {
i = This->contained_vs_consts_i[j];
TRACE("Setting %p from %p %d to { %d, %d, %d, %d }\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantI[i * 4],
targetStateBlock->vertexShaderConstantI[i * 4 + 1],
targetStateBlock->vertexShaderConstantI[i * 4 + 2],
targetStateBlock->vertexShaderConstantI[i * 4 + 3]);
TRACE("Setting %p from %p %u to {%d, %d, %d, %d}\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantI[i * 4],
targetStateBlock->vertexShaderConstantI[i * 4 + 1],
targetStateBlock->vertexShaderConstantI[i * 4 + 2],
targetStateBlock->vertexShaderConstantI[i * 4 + 3]);
This->vertexShaderConstantI[i * 4] = targetStateBlock->vertexShaderConstantI[i * 4];
This->vertexShaderConstantI[i * 4 + 1] = targetStateBlock->vertexShaderConstantI[i * 4 + 1];
@ -426,8 +447,8 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
/* Vertex Shader Boolean Constants */
for (j = 0; j < This->num_contained_vs_consts_b; ++j) {
i = This->contained_vs_consts_b[j];
TRACE("Setting %p from %p %d to %s\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantB[i]? "TRUE":"FALSE");
TRACE("Setting %p from %p %u to %s\n", This, targetStateBlock, i,
targetStateBlock->vertexShaderConstantB[i] ? "TRUE" : "FALSE");
This->vertexShaderConstantB[i] = targetStateBlock->vertexShaderConstantB[i];
}
@ -435,11 +456,11 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
/* Pixel Shader Float Constants */
for (j = 0; j < This->num_contained_ps_consts_f; ++j) {
i = This->contained_ps_consts_f[j];
TRACE("Setting %p from %p %d to { %f, %f, %f, %f }\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantF[i * 4],
targetStateBlock->pixelShaderConstantF[i * 4 + 1],
targetStateBlock->pixelShaderConstantF[i * 4 + 2],
targetStateBlock->pixelShaderConstantF[i * 4 + 3]);
TRACE("Setting %p from %p %u to {%f, %f, %f, %f}\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantF[i * 4],
targetStateBlock->pixelShaderConstantF[i * 4 + 1],
targetStateBlock->pixelShaderConstantF[i * 4 + 2],
targetStateBlock->pixelShaderConstantF[i * 4 + 3]);
This->pixelShaderConstantF[i * 4] = targetStateBlock->pixelShaderConstantF[i * 4];
This->pixelShaderConstantF[i * 4 + 1] = targetStateBlock->pixelShaderConstantF[i * 4 + 1];
@ -450,11 +471,11 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
/* Pixel Shader Integer Constants */
for (j = 0; j < This->num_contained_ps_consts_i; ++j) {
i = This->contained_ps_consts_i[j];
TRACE("Setting %p from %p %d to { %d, %d, %d, %d }\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantI[i * 4],
targetStateBlock->pixelShaderConstantI[i * 4 + 1],
targetStateBlock->pixelShaderConstantI[i * 4 + 2],
targetStateBlock->pixelShaderConstantI[i * 4 + 3]);
TRACE("Setting %p from %p %u to {%d, %d, %d, %d}\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantI[i * 4],
targetStateBlock->pixelShaderConstantI[i * 4 + 1],
targetStateBlock->pixelShaderConstantI[i * 4 + 2],
targetStateBlock->pixelShaderConstantI[i * 4 + 3]);
This->pixelShaderConstantI[i * 4] = targetStateBlock->pixelShaderConstantI[i * 4];
This->pixelShaderConstantI[i * 4 + 1] = targetStateBlock->pixelShaderConstantI[i * 4 + 1];
@ -465,23 +486,23 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
/* Pixel Shader Boolean Constants */
for (j = 0; j < This->num_contained_ps_consts_b; ++j) {
i = This->contained_ps_consts_b[j];
TRACE("Setting %p from %p %d to %s\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantB[i]? "TRUE":"FALSE");
TRACE("Setting %p from %p %u to %s\n", This, targetStateBlock, i,
targetStateBlock->pixelShaderConstantB[i] ? "TRUE" : "FALSE");
This->pixelShaderConstantB[i] = targetStateBlock->pixelShaderConstantB[i];
}
/* Others + Render & Texture */
for (i = 0; i < This->num_contained_transform_states; i++) {
TRACE("Updating transform %d\n", i);
TRACE("Updating transform %u\n", i);
This->transforms[This->contained_transform_states[i]] =
targetStateBlock->transforms[This->contained_transform_states[i]];
}
if (This->changed.indices && ((This->pIndexData != targetStateBlock->pIndexData)
|| (This->baseVertexIndex != targetStateBlock->baseVertexIndex))) {
TRACE("Updating pindexData to %p, baseVertexIndex to %d\n",
targetStateBlock->pIndexData, targetStateBlock->baseVertexIndex);
TRACE("Updating pIndexData to %p, baseVertexIndex to %d\n",
targetStateBlock->pIndexData, targetStateBlock->baseVertexIndex);
if(targetStateBlock->pIndexData) IWineD3DIndexBuffer_AddRef(targetStateBlock->pIndexData);
if(This->pIndexData) IWineD3DIndexBuffer_Release(This->pIndexData);
This->pIndexData = targetStateBlock->pIndexData;
@ -494,10 +515,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
This->vertexDecl = targetStateBlock->vertexDecl;
}
if(This->changed.fvf && This->fvf != targetStateBlock->fvf){
This->fvf = targetStateBlock->fvf;
}
if (This->changed.material && memcmp(&targetStateBlock->material,
&This->material,
sizeof(WINED3DMATERIAL)) != 0) {
@ -520,43 +537,54 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
targetStateBlock->scissorRect = This->scissorRect;
}
for (i = 0; i < MAX_STREAMS; i++) {
if (This->changed.streamSource[i] &&
((This->streamStride[i] != targetStateBlock->streamStride[i]) ||
(This->streamSource[i] != targetStateBlock->streamSource[i]))) {
TRACE("Updating stream source %d to %p, stride to %d\n", i, targetStateBlock->streamSource[i],
targetStateBlock->streamStride[i]);
map = This->changed.streamSource;
for (i = 0; map; map >>= 1, ++i)
{
if (!(map & 1)) continue;
if (This->streamStride[i] != targetStateBlock->streamStride[i]
|| This->streamSource[i] != targetStateBlock->streamSource[i])
{
TRACE("Updating stream source %u to %p, stride to %u\n",
i, targetStateBlock->streamSource[i], targetStateBlock->streamStride[i]);
This->streamStride[i] = targetStateBlock->streamStride[i];
if(targetStateBlock->streamSource[i]) IWineD3DVertexBuffer_AddRef(targetStateBlock->streamSource[i]);
if(This->streamSource[i]) IWineD3DVertexBuffer_Release(This->streamSource[i]);
This->streamSource[i] = targetStateBlock->streamSource[i];
}
}
if (This->changed.streamFreq[i] &&
(This->streamFreq[i] != targetStateBlock->streamFreq[i]
|| This->streamFlags[i] != targetStateBlock->streamFlags[i])){
TRACE("Updating stream frequency %d to %d flags to %d\n", i , targetStateBlock->streamFreq[i] ,
targetStateBlock->streamFlags[i]);
This->streamFreq[i] = targetStateBlock->streamFreq[i];
This->streamFlags[i] = targetStateBlock->streamFlags[i];
map = This->changed.streamFreq;
for (i = 0; map; map >>= 1, ++i)
{
if (!(map & 1)) continue;
if (This->streamFreq[i] != targetStateBlock->streamFreq[i]
|| This->streamFlags[i] != targetStateBlock->streamFlags[i])
{
TRACE("Updating stream frequency %u to %u flags to %#x\n",
i, targetStateBlock->streamFreq[i], targetStateBlock->streamFlags[i]);
This->streamFreq[i] = targetStateBlock->streamFreq[i];
This->streamFlags[i] = targetStateBlock->streamFlags[i];
}
}
for (i = 0; i < GL_LIMITS(clipplanes); i++) {
if (This->changed.clipplane[i] && memcmp(&targetStateBlock->clipplane[i],
&This->clipplane[i],
sizeof(This->clipplane)) != 0) {
map = This->changed.clipplane;
for (i = 0; map; map >>= 1, ++i)
{
if (!(map & 1)) continue;
TRACE("Updating clipplane %d\n", i);
memcpy(&This->clipplane[i], &targetStateBlock->clipplane[i],
sizeof(This->clipplane));
if (memcmp(targetStateBlock->clipplane[i], This->clipplane[i], sizeof(*This->clipplane)))
{
TRACE("Updating clipplane %u\n", i);
memcpy(This->clipplane[i], targetStateBlock->clipplane[i], sizeof(*This->clipplane));
}
}
/* Render */
for (i = 0; i < This->num_contained_render_states; i++) {
TRACE("Updating renderState %d to %d\n",
This->contained_render_states[i], targetStateBlock->renderState[This->contained_render_states[i]]);
TRACE("Updating renderState %u to %u\n", This->contained_render_states[i],
targetStateBlock->renderState[This->contained_render_states[i]]);
This->renderState[This->contained_render_states[i]] = targetStateBlock->renderState[This->contained_render_states[i]];
}
@ -565,26 +593,27 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
DWORD stage = This->contained_tss_states[j].stage;
DWORD state = This->contained_tss_states[j].state;
TRACE("Updating texturestagestate %d,%d to %d (was %d)\n", stage,state,
targetStateBlock->textureState[stage][state], This->textureState[stage][state]);
This->textureState[stage][state] = targetStateBlock->textureState[stage][state];
TRACE("Updating texturestage state %u, %u to %u (was %u)\n", stage, state,
targetStateBlock->textureState[stage][state], This->textureState[stage][state]);
This->textureState[stage][state] = targetStateBlock->textureState[stage][state];
}
/* Samplers */
/* TODO: move over to using memcpy */
for (j = 0; j < MAX_COMBINED_SAMPLERS; j++) {
if (This->changed.textures[j]) {
TRACE("Updating texture %d to %p (was %p)\n", j, targetStateBlock->textures[j], This->textures[j]);
This->textures[j] = targetStateBlock->textures[j];
}
map = This->changed.textures;
for (i = 0; map; map >>= 1, ++i)
{
if (!(map & 1)) continue;
TRACE("Updating texture %u to %p (was %p)\n", i, targetStateBlock->textures[i], This->textures[i]);
This->textures[i] = targetStateBlock->textures[i];
}
for (j = 0; j < This->num_contained_sampler_states; j++) {
DWORD stage = This->contained_sampler_states[j].stage;
DWORD state = This->contained_sampler_states[j].state;
TRACE("Updating sampler state %d,%d to %d (was %d)\n",
stage, state, targetStateBlock->samplerState[stage][state],
This->samplerState[stage][state]);
TRACE("Updating sampler state %u, %u to %u (was %u)\n", stage, state,
targetStateBlock->samplerState[stage][state], This->samplerState[stage][state]);
This->samplerState[stage][state] = targetStateBlock->samplerState[stage][state];
}
if(This->changed.pixelShader && This->pixelShader != targetStateBlock->pixelShader) {
@ -615,7 +644,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface)
memcpy(This->pixelShaderConstantF, targetStateBlock->pixelShaderConstantF, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4);
memcpy(This->renderState, targetStateBlock->renderState, sizeof(This->renderState));
memcpy(This->textures, targetStateBlock->textures, sizeof(This->textures));
memcpy(This->textureDimensions, targetStateBlock->textureDimensions, sizeof(This->textureDimensions));
memcpy(This->textureState, targetStateBlock->textureState, sizeof(This->textureState));
memcpy(This->samplerState, targetStateBlock->samplerState, sizeof(This->samplerState));
This->scissorRect = targetStateBlock->scissorRect;
@ -728,6 +756,7 @@ should really perform a delta so that only the changes get updated*/
UINT i;
UINT j;
DWORD map;
TRACE("(%p) : Applying state block %p ------------------v\n", This, pDevice);
@ -780,7 +809,7 @@ should really perform a delta so that only the changes get updated*/
DWORD stage = This->contained_tss_states[i].stage;
DWORD state = This->contained_tss_states[i].state;
((IWineD3DDeviceImpl *)pDevice)->stateBlock->textureState[stage][state] = This->textureState[stage][state];
((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.textureState[stage][state] = TRUE;
((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.textureState[stage] |= 1 << state;
/* TODO: Record a display list to apply all gl states. For now apply by brute force */
IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)pDevice, STATE_TEXTURESTAGE(stage, state));
}
@ -789,7 +818,7 @@ should really perform a delta so that only the changes get updated*/
DWORD stage = This->contained_sampler_states[i].stage;
DWORD state = This->contained_sampler_states[i].state;
((IWineD3DDeviceImpl *)pDevice)->stateBlock->samplerState[stage][state] = This->samplerState[stage][state];
((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.samplerState[stage][state] = TRUE;
((IWineD3DDeviceImpl *)pDevice)->stateBlock->changed.samplerState[stage] |= 1 << state;
IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *)pDevice, STATE_SAMPLER(stage));
}
@ -803,10 +832,6 @@ should really perform a delta so that only the changes get updated*/
IWineD3DDevice_SetBaseVertexIndex(pDevice, This->baseVertexIndex);
}
if (This->changed.fvf) {
IWineD3DDevice_SetFVF(pDevice, This->fvf);
}
if (This->changed.vertexDecl) {
IWineD3DDevice_SetVertexDeclaration(pDevice, This->vertexDecl);
}
@ -824,35 +849,41 @@ should really perform a delta so that only the changes get updated*/
}
/* TODO: Proper implementation using SetStreamSource offset (set to 0 for the moment)\n") */
for (i=0; i<MAX_STREAMS; i++) {
if (This->changed.streamSource[i])
IWineD3DDevice_SetStreamSource(pDevice, i, This->streamSource[i], 0, This->streamStride[i]);
if (This->changed.streamFreq[i])
IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[i]);
}
for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){
if (This->changed.textures[j]) {
if (j < MAX_FRAGMENT_SAMPLERS) {
IWineD3DDevice_SetTexture(pDevice, j, This->textures[j]);
} else {
IWineD3DDevice_SetTexture(pDevice, WINED3DVERTEXTEXTURESAMPLER0 + j - MAX_FRAGMENT_SAMPLERS, This->textures[j]);
}
}
map = This->changed.streamSource;
for (i = 0; map; map >>= 1, ++i)
{
if (map & 1) IWineD3DDevice_SetStreamSource(pDevice, i, This->streamSource[i], 0, This->streamStride[i]);
}
for (i = 0; i < GL_LIMITS(clipplanes); i++) {
if (This->changed.clipplane[i]) {
float clip[4];
clip[0] = This->clipplane[i][0];
clip[1] = This->clipplane[i][1];
clip[2] = This->clipplane[i][2];
clip[3] = This->clipplane[i][3];
IWineD3DDevice_SetClipPlane(pDevice, i, clip);
}
map = This->changed.streamFreq;
for (i = 0; map; map >>= 1, ++i)
{
if (map & 1) IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[i]);
}
map = This->changed.textures;
for (i = 0; map; map >>= 1, ++i)
{
if (!(map & 1)) continue;
if (i < MAX_FRAGMENT_SAMPLERS) IWineD3DDevice_SetTexture(pDevice, i, This->textures[i]);
else IWineD3DDevice_SetTexture(pDevice, WINED3DVERTEXTEXTURESAMPLER0 + i - MAX_FRAGMENT_SAMPLERS,
This->textures[i]);
}
map = This->changed.clipplane;
for (i = 0; map; map >>= 1, ++i)
{
float clip[4];
if (!(map & 1)) continue;
clip[0] = This->clipplane[i][0];
clip[1] = This->clipplane[i][1];
clip[2] = This->clipplane[i][2];
clip[3] = This->clipplane[i][3];
IWineD3DDevice_SetClipPlane(pDevice, i, clip);
}
} else if(This->blockType == WINED3DSBT_VERTEXSTATE) {
IWineD3DDevice_SetVertexShader(pDevice, This->vertexShader);
for (i = 0; i < GL_LIMITS(vshader_constantsF); i++) {
@ -968,7 +999,8 @@ should really perform a delta so that only the changes get updated*/
IWineD3DDevice_SetRenderState(pDevice, i, This->renderState[i]);
}
for(j = 0; j < MAX_TEXTURES; j++) {
for(i = 1; i <= WINED3D_HIGHEST_TEXTURE_STATE; i++) {
for (i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
{
IWineD3DDevice_SetTextureStageState(pDevice, j, i, This->textureState[j][i]);
}
}
@ -979,7 +1011,6 @@ should really perform a delta so that only the changes get updated*/
}
IWineD3DDevice_SetIndices(pDevice, This->pIndexData);
IWineD3DDevice_SetBaseVertexIndex(pDevice, This->baseVertexIndex);
IWineD3DDevice_SetFVF(pDevice, This->fvf);
IWineD3DDevice_SetVertexDeclaration(pDevice, This->vertexDecl);
IWineD3DDevice_SetMaterial(pDevice, &This->material);
IWineD3DDevice_SetViewport(pDevice, &This->viewport);
@ -994,7 +1025,8 @@ should really perform a delta so that only the changes get updated*/
UINT sampler = j < MAX_FRAGMENT_SAMPLERS ? j : WINED3DVERTEXTEXTURESAMPLER0 + j - MAX_FRAGMENT_SAMPLERS;
IWineD3DDevice_SetTexture(pDevice, sampler, This->textures[j]);
for(i = 1; i < WINED3D_HIGHEST_SAMPLER_STATE; i++) {
for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE; ++i)
{
IWineD3DDevice_SetSamplerState(pDevice, sampler, i, This->samplerState[j][i]);
}
}
@ -1125,7 +1157,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
IWineD3DDevice_SetRenderState(device, WINED3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
tmpfloat.f = 1.0f;
IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE, tmpfloat.d);
tmpfloat.f = 1.0f;
tmpfloat.f = ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion < 9 ? 0.0f : 1.0f;
IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE_MIN, tmpfloat.d);
IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSPRITEENABLE, FALSE);
IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSCALEENABLE, FALSE);
@ -1141,7 +1173,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
tmpfloat.f = 1.0f;
IWineD3DDevice_SetRenderState(device, WINED3DRS_PATCHSEGMENTS, tmpfloat.d);
IWineD3DDevice_SetRenderState(device, WINED3DRS_DEBUGMONITORTOKEN, 0xbaadcafe);
tmpfloat.f = 64.0f;
tmpfloat.f = GL_LIMITS(pointsize);
IWineD3DDevice_SetRenderState(device, WINED3DRS_POINTSIZE_MAX, tmpfloat.d);
IWineD3DDevice_SetRenderState(device, WINED3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
IWineD3DDevice_SetRenderState(device, WINED3DRS_COLORWRITEENABLE, 0x0000000F);
@ -1211,7 +1243,6 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
This->textureState[i][WINED3DTSS_BUMPENVLSCALE ] = 0;
This->textureState[i][WINED3DTSS_BUMPENVLOFFSET ] = 0;
This->textureState[i][WINED3DTSS_TEXTURETRANSFORMFLAGS ] = WINED3DTTFF_DISABLE;
This->textureState[i][WINED3DTSS_ADDRESSW ] = WINED3DTADDRESS_WRAP;
This->textureState[i][WINED3DTSS_COLORARG0 ] = WINED3DTA_CURRENT;
This->textureState[i][WINED3DTSS_ALPHAARG0 ] = WINED3DTA_CURRENT;
This->textureState[i][WINED3DTSS_RESULTARG ] = WINED3DTA_CURRENT;
@ -1238,7 +1269,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
for(i = 0; i < GL_LIMITS(textures); i++) {
/* Note: This avoids calling SetTexture, so pretend it has been called */
This->changed.textures[i] = TRUE;
This->changed.textures |= 1 << i;
This->textures[i] = NULL;
}
@ -1249,6 +1280,8 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
/* check the return values, because the GetBackBuffer call isn't valid for ddraw */
hr = IWineD3DDevice_GetSwapChain(device, 0, &swapchain);
if( hr == WINED3D_OK && swapchain != NULL) {
WINED3DVIEWPORT vp;
hr = IWineD3DSwapChain_GetBackBuffer(swapchain, 0, WINED3DBACKBUFFER_TYPE_MONO, &backbuffer);
if( hr == WINED3D_OK && backbuffer != NULL) {
IWineD3DSurface_GetDesc(backbuffer, &desc);
@ -1263,6 +1296,16 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat
ERR("This should never happen, expect rendering issues!\n");
}
}
/* Set the default viewport */
vp.X = 0;
vp.Y = 0;
vp.Width = ((IWineD3DSwapChainImpl *)swapchain)->presentParms.BackBufferWidth;
vp.Height = ((IWineD3DSwapChainImpl *)swapchain)->presentParms.BackBufferHeight;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
IWineD3DDevice_SetViewport(device, &vp);
IWineD3DSwapChain_Release(swapchain);
}

View file

@ -99,15 +99,11 @@ static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This) {
*
* TODO: Track the current active texture per GL context instead of using glGet
*/
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GLint active_texture;
ENTER_GL();
glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
LEAVE_GL();
active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB];
} else {
active_sampler = 0;
}
GLint active_texture;
ENTER_GL();
glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
LEAVE_GL();
active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB];
if (active_sampler != -1) {
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler));
@ -480,6 +476,43 @@ GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchai
return GL_BACK;
}
/* Slightly inefficient way to handle multiple dirty rects but it works :) */
void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DBaseTexture *baseTexture = NULL;
if (!(This->Flags & SFLAG_INSYSMEM) && (This->Flags & SFLAG_INTEXTURE))
IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
if (dirty_rect)
{
This->dirtyRect.left = min(This->dirtyRect.left, dirty_rect->left);
This->dirtyRect.top = min(This->dirtyRect.top, dirty_rect->top);
This->dirtyRect.right = max(This->dirtyRect.right, dirty_rect->right);
This->dirtyRect.bottom = max(This->dirtyRect.bottom, dirty_rect->bottom);
}
else
{
This->dirtyRect.left = 0;
This->dirtyRect.top = 0;
This->dirtyRect.right = This->currentDesc.Width;
This->dirtyRect.bottom = This->currentDesc.Height;
}
TRACE("(%p) : Dirty: yes, Rect:(%d, %d, %d, %d)\n", This, This->dirtyRect.left,
This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
/* if the container is a basetexture then mark it dirty. */
if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)))
{
TRACE("Passing to container\n");
IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
IWineD3DBaseTexture_Release(baseTexture);
}
}
static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
@ -695,6 +728,9 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v
BOOL bpp;
RECT local_rect;
BOOL srcIsUpsideDown;
GLint rowLen = 0;
GLint skipPix = 0;
GLint skipRow = 0;
if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
static BOOL warned = FALSE;
@ -790,14 +826,42 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v
if(This->Flags & SFLAG_PBO) {
GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
checkGLcall("glBindBufferARB");
if(mem != NULL) {
ERR("mem not null for pbo -- unexpected\n");
mem = NULL;
}
}
glReadPixels(local_rect.left, local_rect.top,
/* Save old pixel store pack state */
glGetIntegerv(GL_PACK_ROW_LENGTH, &rowLen);
checkGLcall("glIntegerv");
glGetIntegerv(GL_PACK_SKIP_PIXELS, &skipPix);
checkGLcall("glIntegerv");
glGetIntegerv(GL_PACK_SKIP_ROWS, &skipRow);
checkGLcall("glIntegerv");
/* Setup pixel store pack state -- to glReadPixels into the correct place */
glPixelStorei(GL_PACK_ROW_LENGTH, This->currentDesc.Width);
checkGLcall("glPixelStorei");
glPixelStorei(GL_PACK_SKIP_PIXELS, local_rect.left);
checkGLcall("glPixelStorei");
glPixelStorei(GL_PACK_SKIP_ROWS, local_rect.top);
checkGLcall("glPixelStorei");
glReadPixels(local_rect.left, (!srcIsUpsideDown) ? (This->currentDesc.Height - local_rect.bottom) : local_rect.top ,
local_rect.right - local_rect.left,
local_rect.bottom - local_rect.top,
fmt, type, mem);
checkGLcall("glReadPixels");
/* Reset previous pixel store pack state */
glPixelStorei(GL_PACK_ROW_LENGTH, rowLen);
checkGLcall("glPixelStorei");
glPixelStorei(GL_PACK_SKIP_PIXELS, skipPix);
checkGLcall("glPixelStorei");
glPixelStorei(GL_PACK_SKIP_ROWS, skipRow);
checkGLcall("glPixelStorei");
if(This->Flags & SFLAG_PBO) {
GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
checkGLcall("glBindBufferARB");
@ -832,7 +896,7 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v
}
top = mem + pitch * local_rect.top;
bottom = mem + pitch * ( local_rect.bottom - local_rect.top - 1);
bottom = mem + pitch * (local_rect.bottom - 1);
for(i = 0; i < (local_rect.bottom - local_rect.top) / 2; i++) {
memcpy(row, top + off, len);
memcpy(top + off, bottom + off, len);
@ -936,6 +1000,7 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This)
TRACE("Locking offscreen render target\n");
ENTER_GL();
glReadBuffer(device->offscreenBuffer);
checkGLcall("glReadBuffer");
LEAVE_GL();
}
@ -1165,7 +1230,7 @@ lock_end:
* Dirtify on lock
* as seen in msdn docs
*/
IWineD3DSurface_AddDirtyRect(iface, pRect);
surface_add_dirty_rect(iface, pRect);
/** Dirtify Container if needed */
if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture))) {
@ -1293,7 +1358,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
if (!(This->Flags & SFLAG_LOCKED)) {
WARN("trying to Unlock an unlocked surf@%p\n", This);
return WINED3DERR_INVALIDCALL;
return WINEDDERR_NOTLOCKED;
}
if (This->Flags & SFLAG_PBO) {
@ -1500,11 +1565,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC
TRACE("(%p)->(%p)\n",This,hDC);
if (!(This->Flags & SFLAG_DCINUSE))
return WINED3DERR_INVALIDCALL;
return WINEDDERR_NODC;
if (This->hDC !=hDC) {
WARN("Application tries to release an invalid DC(%p), surface dc is %p\n", hDC, This->hDC);
return WINED3DERR_INVALIDCALL;
return WINEDDERR_NODC;
}
if((This->Flags & SFLAG_PBO) && This->resource.allocatedMemory) {
@ -1700,6 +1765,14 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_
*target_bpp = 2;
break;
case WINED3DFMT_G16R16:
*convert = CONVERT_G16R16;
*format = GL_RGB;
*internal = GL_RGB16_EXT;
*type = GL_UNSIGNED_SHORT;
*target_bpp = 6;
break;
default:
break;
}
@ -1795,7 +1868,7 @@ static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UI
Dest = (WORD *) (dst + y * outpitch);
for (x = 0; x < width; x++ ) {
WORD color = *Source++;
*Dest = color;
*Dest = color;
if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
(color > This->SrcBltCKey.dwColorSpaceHighValue)) {
*Dest |= (1 << 15);
@ -2027,6 +2100,27 @@ static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UI
break;
}
case CONVERT_G16R16:
{
unsigned int x, y;
const WORD *Source;
WORD *Dest;
for(y = 0; y < height; y++) {
Source = (const WORD *)(src + y * pitch);
Dest = (WORD *) (dst + y * outpitch);
for (x = 0; x < width; x++ ) {
WORD green = (*Source++);
WORD red = (*Source++);
Dest[0] = green;
Dest[1] = red;
Dest[2] = 0xffff;
Dest += 3;
}
}
break;
}
default:
ERR("Unsupported conversation type %d\n", convert);
}
@ -2446,40 +2540,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, c
return WINED3D_OK;
}
/**
* Slightly inefficient way to handle multiple dirty rects but it works :)
*/
static HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DBaseTexture *baseTexture = NULL;
if (!(This->Flags & SFLAG_INSYSMEM) && (This->Flags & SFLAG_INTEXTURE))
IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
if (NULL != pDirtyRect) {
This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
} else {
This->dirtyRect.left = 0;
This->dirtyRect.top = 0;
This->dirtyRect.right = This->currentDesc.Width;
This->dirtyRect.bottom = This->currentDesc.Height;
}
TRACE("(%p) : Dirty: yes, Rect:(%d,%d,%d,%d)\n", This, This->dirtyRect.left,
This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
/* if the container is a basetexture then mark it dirty. */
if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
TRACE("Passing to container\n");
IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
IWineD3DBaseTexture_Release(baseTexture);
}
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
HRESULT hr;
@ -3809,7 +3869,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
3: WARN and return WINED3DERR_NOTAVAILABLE;
4: Create the surface, but allow it to be used only for DirectDraw Blts. Some apps(e.g. Swat 3) create textures with a Height of 16 and a Width > 3000 and blt 16x16 letter areas from them to the render target.
*/
WARN("(%p) Creating an oversized surface\n", This);
WARN("(%p) Creating an oversized surface: %ux%u (texture is %ux%u)\n",
This, This->pow2Width, This->pow2Height, This->currentDesc.Width, This->currentDesc.Height);
This->Flags |= SFLAG_OVERSIZE;
/* This will be initialized on the first blt */
@ -4678,7 +4739,6 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
IWineD3DBaseSurfaceImpl_SetClipper,
IWineD3DBaseSurfaceImpl_GetClipper,
/* Internal use: */
IWineD3DSurfaceImpl_AddDirtyRect,
IWineD3DSurfaceImpl_LoadTexture,
IWineD3DSurfaceImpl_BindTexture,
IWineD3DSurfaceImpl_SaveSnapshot,

View file

@ -29,6 +29,7 @@
#include "config.h"
#include "wine/port.h"
#include "wined3d_private.h"
#include "float.h"
#include <assert.h>
@ -45,7 +46,7 @@ static inline unsigned short float_32_to_16(const float *in)
/* Deal with special numbers */
if(*in == 0.0) return 0x0000;
if(isnan(*in)) return 0x7C01;
if(!finite(*in)) return (*in < 0.0 ? 0xFC00 : 0x7c00);
if(!_finite(*in)) return (*in < 0.0 ? 0xFC00 : 0x7c00);
if(tmp < pow(2, 10)) {
do
@ -166,11 +167,7 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFI
ERR("Called without a valid ppContainer.\n");
}
/** From MSDN:
* If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
* or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
* GetContainer will return the Direct3D device used to create the surface.
*/
/* Standalone surfaces return the device as container. */
if (This->container) {
container = This->container;
} else {
@ -702,6 +699,46 @@ static void convert_r32f_r16f(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD
}
}
static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst,
DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
{
static const unsigned char convert_5to8[] =
{
0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
};
static const unsigned char convert_6to8[] =
{
0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
};
unsigned int x, y;
TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
for (y = 0; y < h; ++y)
{
const WORD *src_line = (const WORD *)(src + y * pitch_in);
DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
for (x = 0; x < w; ++x)
{
WORD pixel = src_line[x];
dst_line[x] = 0xff000000
| convert_5to8[(pixel & 0xf800) >> 11] << 16
| convert_6to8[(pixel & 0x07e0) >> 5] << 8
| convert_5to8[(pixel & 0x001f)];
}
}
}
struct d3dfmt_convertor_desc {
WINED3DFORMAT from, to;
void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h);
@ -710,6 +747,7 @@ struct d3dfmt_convertor_desc {
static const struct d3dfmt_convertor_desc convertors[] =
{
{WINED3DFMT_R32F, WINED3DFMT_R16F, convert_r32f_r16f},
{WINED3DFMT_R5G6B5, WINED3DFMT_X8R8G8B8, convert_r5g6b5_x8r8g8b8},
};
static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to)

View file

@ -168,7 +168,7 @@ IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface)
if (!(This->Flags & SFLAG_LOCKED))
{
WARN("trying to Unlock an unlocked surf@%p\n", This);
return WINED3DERR_INVALIDCALL;
return WINEDDERR_NOTLOCKED;
}
/* Can be useful for debugging */
@ -341,7 +341,7 @@ const char* filename)
for (y = 0; y < This->pow2Height; y++) {
const unsigned char *src = This->resource.allocatedMemory + (y * 1 * IWineD3DSurface_GetPitch(iface));
for (x = 0; x < This->pow2Width; x++) {
for (x = 0; x < This->pow2Width; x++) {
unsigned int color;
unsigned int comp;
int i;
@ -442,11 +442,11 @@ static HRESULT WINAPI IWineGDISurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC
TRACE("(%p)->(%p)\n",This,hDC);
if (!(This->Flags & SFLAG_DCINUSE))
return WINED3DERR_INVALIDCALL;
return WINEDDERR_NODC;
if (This->hDC !=hDC) {
WARN("Application tries to release an invalid DC(%p), surface dc is %p\n", hDC, This->hDC);
return WINED3DERR_INVALIDCALL;
return WINEDDERR_NODC;
}
/* we locked first, so unlock now */
@ -540,14 +540,6 @@ static void WINAPI IWineGDISurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescr
*glDescription = NULL;
}
static HRESULT WINAPI IWineGDISurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
/* GDI surface data can only be in one location, the system memory dib section. So they are
* always clean by definition.
*/
TRACE("No dirtification in GDI surfaces\n");
return WINED3D_OK;
}
static HRESULT WINAPI IWineGDISurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
@ -673,7 +665,6 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl =
IWineD3DBaseSurfaceImpl_SetClipper,
IWineD3DBaseSurfaceImpl_GetClipper,
/* Internal use: */
IWineGDISurfaceImpl_AddDirtyRect,
IWineGDISurfaceImpl_LoadTexture,
IWineD3DBaseSurfaceImpl_BindTexture,
IWineGDISurfaceImpl_SaveSnapshot,

View file

@ -137,7 +137,7 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) {
FIXME("Texture (%p) has been reloaded at least 20 times due to WINED3DSAMP_SRGBTEXTURE changes on it\'s sampler\n", This);
for (i = 0; i < This->baseTexture.levels; i++) {
IWineD3DSurface_AddDirtyRect(This->surfaces[i], NULL);
surface_add_dirty_rect(This->surfaces[i], NULL);
surface_force_reload(This->surfaces[i]);
IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode);
}
@ -303,7 +303,7 @@ static HRESULT WINAPI IWineD3DTextureImpl_GetLevelDesc(IWineD3DTexture *iface, U
TRACE("(%p) Level (%d)\n", This, Level);
return IWineD3DSurface_GetDesc(This->surfaces[Level], pDesc);
}
FIXME("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
WARN("(%p) level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
}
@ -360,7 +360,9 @@ static HRESULT WINAPI IWineD3DTextureImpl_AddDirtyRect(IWineD3DTexture *iface, C
IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
This->baseTexture.dirty = TRUE;
TRACE("(%p) : dirtyfication of surface Level (0)\n", This);
return IWineD3DSurface_AddDirtyRect(This->surfaces[0], pDirtyRect);
surface_add_dirty_rect(This->surfaces[0], pDirtyRect);
return WINED3D_OK;
}
const IWineD3DTextureVtbl IWineD3DTexture_Vtbl =

View file

@ -167,7 +167,7 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = {
/* IEEE formats */
{WINED3DFMT_R32F ,GL_RGB32F_ARB ,GL_RGB32F_ARB , 0, GL_RED ,GL_FLOAT
,WINED3DFMT_FLAG_RENDERTARGET },
{WINED3DFMT_G32R32F ,0 ,0 , 0, 0 ,0
{WINED3DFMT_G32R32F ,GL_RG32F ,GL_RG32F , 0, GL_RG ,GL_FLOAT
,WINED3DFMT_FLAG_RENDERTARGET },
{WINED3DFMT_A32B32G32R32F ,GL_RGBA32F_ARB ,GL_RGBA32F_ARB , 0, GL_RGBA ,GL_FLOAT
,WINED3DFMT_FLAG_RENDERTARGET },
@ -177,7 +177,7 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = {
/* Float */
{WINED3DFMT_R16F ,GL_RGB16F_ARB ,GL_RGB16F_ARB , 0, GL_RED ,GL_HALF_FLOAT_ARB
,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET },
{WINED3DFMT_G16R16F ,0 ,0 , 0, 0 ,0
{WINED3DFMT_G16R16F ,GL_RG16F ,GL_RG16F , 0, GL_RG ,GL_HALF_FLOAT_ARB
,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET },
{WINED3DFMT_A16B16G16R16F ,GL_RGBA16F_ARB ,GL_RGBA16F_ARB , 0, GL_RGBA ,GL_HALF_FLOAT_ARB
,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET },
@ -366,10 +366,22 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
dst = getFmtIdx(WINED3DFMT_R16F);
gl_info->gl_formats[dst].color_fixup = create_color_fixup_desc(
0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
/* When ARB_texture_rg is supported we only require 16-bit for R16F instead of 64-bit RGBA16F */
if(GL_SUPPORT(ARB_TEXTURE_RG))
{
gl_info->gl_formats[dst].glInternal = GL_R16F;
gl_info->gl_formats[dst].glGammaInternal = GL_R16F;
}
dst = getFmtIdx(WINED3DFMT_R32F);
gl_info->gl_formats[dst].color_fixup = create_color_fixup_desc(
0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
/* When ARB_texture_rg is supported we only require 32-bit for R32F instead of 128-bit RGBA32F */
if(GL_SUPPORT(ARB_TEXTURE_RG))
{
gl_info->gl_formats[dst].glInternal = GL_R32F;
gl_info->gl_formats[dst].glGammaInternal = GL_R32F;
}
dst = getFmtIdx(WINED3DFMT_G16R16);
gl_info->gl_formats[dst].color_fixup = create_color_fixup_desc(
@ -470,33 +482,42 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
}
/* NOTE: Make sure these are in the correct numerical order. (see /include/wined3d_types.h) */
static WINED3DGLTYPE const glTypeLookupTemplate[WINED3DDECLTYPE_UNUSED] = {
{WINED3DDECLTYPE_FLOAT1, 1, GL_FLOAT , GL_FALSE ,sizeof(float)},
{WINED3DDECLTYPE_FLOAT2, 2, GL_FLOAT , GL_FALSE ,sizeof(float)},
{WINED3DDECLTYPE_FLOAT3, 3, GL_FLOAT , GL_FALSE ,sizeof(float)},
{WINED3DDECLTYPE_FLOAT4, 4, GL_FLOAT , GL_FALSE ,sizeof(float)},
{WINED3DDECLTYPE_D3DCOLOR, 4, GL_UNSIGNED_BYTE , GL_TRUE ,sizeof(BYTE)},
{WINED3DDECLTYPE_UBYTE4, 4, GL_UNSIGNED_BYTE , GL_FALSE ,sizeof(BYTE)},
{WINED3DDECLTYPE_SHORT2, 2, GL_SHORT , GL_FALSE ,sizeof(short int)},
{WINED3DDECLTYPE_SHORT4, 4, GL_SHORT , GL_FALSE ,sizeof(short int)},
{WINED3DDECLTYPE_UBYTE4N, 4, GL_UNSIGNED_BYTE , GL_TRUE ,sizeof(BYTE)},
{WINED3DDECLTYPE_SHORT2N, 2, GL_SHORT , GL_TRUE ,sizeof(short int)},
{WINED3DDECLTYPE_SHORT4N, 4, GL_SHORT , GL_TRUE ,sizeof(short int)},
{WINED3DDECLTYPE_USHORT2N, 2, GL_UNSIGNED_SHORT , GL_TRUE ,sizeof(short int)},
{WINED3DDECLTYPE_USHORT4N, 4, GL_UNSIGNED_SHORT , GL_TRUE ,sizeof(short int)},
{WINED3DDECLTYPE_UDEC3, 3, GL_UNSIGNED_SHORT , GL_FALSE ,sizeof(short int)},
{WINED3DDECLTYPE_DEC3N, 3, GL_SHORT , GL_TRUE ,sizeof(short int)},
{WINED3DDECLTYPE_FLOAT16_2, 2, GL_HALF_FLOAT_NV , GL_FALSE ,sizeof(GLhalfNV)},
{WINED3DDECLTYPE_FLOAT16_4, 4, GL_HALF_FLOAT_NV , GL_FALSE ,sizeof(GLhalfNV)}};
static WINED3DGLTYPE const glTypeLookupTemplate[WINED3DDECLTYPE_UNUSED] =
{
{WINED3DDECLTYPE_FLOAT1, 1, GL_FLOAT, 1, GL_FALSE, sizeof(float)},
{WINED3DDECLTYPE_FLOAT2, 2, GL_FLOAT, 2, GL_FALSE, sizeof(float)},
{WINED3DDECLTYPE_FLOAT3, 3, GL_FLOAT, 3, GL_FALSE, sizeof(float)},
{WINED3DDECLTYPE_FLOAT4, 4, GL_FLOAT, 4, GL_FALSE, sizeof(float)},
{WINED3DDECLTYPE_D3DCOLOR, 4, GL_UNSIGNED_BYTE, 4, GL_TRUE, sizeof(BYTE)},
{WINED3DDECLTYPE_UBYTE4, 4, GL_UNSIGNED_BYTE, 4, GL_FALSE, sizeof(BYTE)},
{WINED3DDECLTYPE_SHORT2, 2, GL_SHORT, 2, GL_FALSE, sizeof(short int)},
{WINED3DDECLTYPE_SHORT4, 4, GL_SHORT, 4, GL_FALSE, sizeof(short int)},
{WINED3DDECLTYPE_UBYTE4N, 4, GL_UNSIGNED_BYTE, 4, GL_TRUE, sizeof(BYTE)},
{WINED3DDECLTYPE_SHORT2N, 2, GL_SHORT, 2, GL_TRUE, sizeof(short int)},
{WINED3DDECLTYPE_SHORT4N, 4, GL_SHORT, 4, GL_TRUE, sizeof(short int)},
{WINED3DDECLTYPE_USHORT2N, 2, GL_UNSIGNED_SHORT, 2, GL_TRUE, sizeof(short int)},
{WINED3DDECLTYPE_USHORT4N, 4, GL_UNSIGNED_SHORT, 4, GL_TRUE, sizeof(short int)},
{WINED3DDECLTYPE_UDEC3, 3, GL_UNSIGNED_SHORT, 3, GL_FALSE, sizeof(short int)},
{WINED3DDECLTYPE_DEC3N, 3, GL_SHORT, 3, GL_TRUE, sizeof(short int)},
{WINED3DDECLTYPE_FLOAT16_2, 2, GL_FLOAT, 2, GL_FALSE, sizeof(GLhalfNV)},
{WINED3DDECLTYPE_FLOAT16_4, 4, GL_FLOAT, 4, GL_FALSE, sizeof(GLhalfNV)}
};
void init_type_lookup(WineD3D_GL_Info *gl_info) {
memcpy(gl_info->glTypeLookup, glTypeLookupTemplate, sizeof(glTypeLookupTemplate));
if(!GL_SUPPORT(NV_HALF_FLOAT)) {
if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
{
gl_info->glTypeLookup[WINED3DDECLTYPE_D3DCOLOR].format = GL_BGRA;
}
if (GL_SUPPORT(NV_HALF_FLOAT))
{
/* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
* It is the job of the vertex buffer code to make sure that the vbos have the right format
*/
gl_info->glTypeLookup[WINED3DDECLTYPE_FLOAT16_2].glType = GL_FLOAT;
gl_info->glTypeLookup[WINED3DDECLTYPE_FLOAT16_4].glType = GL_FLOAT;
gl_info->glTypeLookup[WINED3DDECLTYPE_FLOAT16_2].glType = GL_HALF_FLOAT_NV;
gl_info->glTypeLookup[WINED3DDECLTYPE_FLOAT16_4].glType = GL_HALF_FLOAT_NV;
}
}
@ -742,7 +763,7 @@ const char* debug_d3ddeclusage(BYTE usage) {
const char* debug_d3dresourcetype(WINED3DRESOURCETYPE res) {
switch (res) {
#define RES_TO_STR(res) case res: return #res;
#define RES_TO_STR(res) case res: return #res
RES_TO_STR(WINED3DRTYPE_SURFACE);
RES_TO_STR(WINED3DRTYPE_VOLUME);
RES_TO_STR(WINED3DRTYPE_TEXTURE);
@ -759,7 +780,7 @@ const char* debug_d3dresourcetype(WINED3DRESOURCETYPE res) {
const char* debug_d3dprimitivetype(WINED3DPRIMITIVETYPE PrimitiveType) {
switch (PrimitiveType) {
#define PRIM_TO_STR(prim) case prim: return #prim;
#define PRIM_TO_STR(prim) case prim: return #prim
PRIM_TO_STR(WINED3DPT_POINTLIST);
PRIM_TO_STR(WINED3DPT_LINELIST);
PRIM_TO_STR(WINED3DPT_LINESTRIP);
@ -1008,15 +1029,11 @@ const char* debug_d3dtexturestate(DWORD state) {
D3DSTATE_TO_STR(WINED3DTSS_BUMPENVLSCALE );
D3DSTATE_TO_STR(WINED3DTSS_BUMPENVLOFFSET );
D3DSTATE_TO_STR(WINED3DTSS_TEXTURETRANSFORMFLAGS );
D3DSTATE_TO_STR(WINED3DTSS_ADDRESSW );
D3DSTATE_TO_STR(WINED3DTSS_COLORARG0 );
D3DSTATE_TO_STR(WINED3DTSS_ALPHAARG0 );
D3DSTATE_TO_STR(WINED3DTSS_RESULTARG );
D3DSTATE_TO_STR(WINED3DTSS_CONSTANT );
#undef D3DSTATE_TO_STR
case 12:
/* Note WINED3DTSS are not consecutive, so skip these */
return "unused";
default:
FIXME("Unrecognized %u texture state!\n", state);
return "unrecognized";
@ -1086,7 +1103,7 @@ const char* debug_d3dtstype(WINED3DTRANSFORMSTATETYPE tstype) {
const char* debug_d3dpool(WINED3DPOOL Pool) {
switch (Pool) {
#define POOL_TO_STR(p) case p: return #p;
#define POOL_TO_STR(p) case p: return #p
POOL_TO_STR(WINED3DPOOL_DEFAULT);
POOL_TO_STR(WINED3DPOOL_MANAGED);
POOL_TO_STR(WINED3DPOOL_SYSTEMMEM);
@ -1500,6 +1517,7 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
case WINED3DFVF_XYZB3: size += 6 * sizeof(float); break;
case WINED3DFVF_XYZB4: size += 7 * sizeof(float); break;
case WINED3DFVF_XYZB5: size += 8 * sizeof(float); break;
case WINED3DFVF_XYZW: size += 4 * sizeof(float); break;
default: ERR("Unexpected position mask\n");
}
for (i = 0; i < numTextures; i++) {
@ -1711,6 +1729,16 @@ void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *val
HeapFree(GetProcessHeap(), 0, table);
}
void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context)
{
unsigned int i = 0;
for (i = 0; i < table->entry_count; ++i)
{
callback(table->entries[i].value, context);
}
}
static inline struct hash_table_entry_t *hash_table_get_by_idx(const struct hash_table_t *table, const void *key,
unsigned int idx)
{
@ -1917,7 +1945,7 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
settings->op[i].aop = WINED3DTOP_DISABLE;
settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
settings->op[i].color_correction = COLOR_FIXUP_IDENTITY;
settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
settings->op[i].dst = resultreg;
settings->op[i].tex_type = tex_1d;
settings->op[i].projected = proj_none;
@ -1927,11 +1955,11 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
texture = (IWineD3DBaseTextureImpl *) stateblock->textures[i];
if(texture) {
settings->op[i].color_correction = texture->baseTexture.shader_color_fixup;
settings->op[i].color_fixup = texture->baseTexture.shader_color_fixup;
if(ignore_textype) {
settings->op[i].tex_type = tex_1d;
} else {
switch(stateblock->textureDimensions[i]) {
switch (IWineD3DBaseTexture_GetTextureDimensions((IWineD3DBaseTexture *)texture)) {
case GL_TEXTURE_1D:
settings->op[i].tex_type = tex_1d;
break;
@ -1950,21 +1978,21 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
}
}
} else {
settings->op[i].color_correction = COLOR_FIXUP_IDENTITY;
settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
settings->op[i].tex_type = tex_1d;
}
cop = stateblock->textureState[i][WINED3DTSS_COLOROP];
aop = stateblock->textureState[i][WINED3DTSS_ALPHAOP];
carg1 = (args[cop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_COLORARG1] : 0xffffffff;
carg2 = (args[cop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_COLORARG2] : 0xffffffff;
carg0 = (args[cop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_COLORARG0] : 0xffffffff;
carg1 = (args[cop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_COLORARG1] : ARG_UNUSED;
carg2 = (args[cop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_COLORARG2] : ARG_UNUSED;
carg0 = (args[cop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_COLORARG0] : ARG_UNUSED;
if(is_invalid_op(stateblock->wineD3DDevice, i, cop,
carg1, carg2, carg0)) {
carg0 = 0xffffffff;
carg2 = 0xffffffff;
carg0 = ARG_UNUSED;
carg2 = ARG_UNUSED;
carg1 = WINED3DTA_CURRENT;
cop = WINED3DTOP_SELECTARG1;
}
@ -1978,45 +2006,54 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
aarg2 = carg2;
aarg0 = carg0;
} else {
aarg1 = (args[aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : 0xffffffff;
aarg2 = (args[aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : 0xffffffff;
aarg0 = (args[aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : 0xffffffff;
aarg1 = (args[aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : ARG_UNUSED;
aarg2 = (args[aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : ARG_UNUSED;
aarg0 = (args[aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : ARG_UNUSED;
}
if(i == 0 && stateblock->textures[0] &&
stateblock->renderState[WINED3DRS_COLORKEYENABLE] &&
(stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
if (i == 0 && stateblock->textures[0] && stateblock->renderState[WINED3DRS_COLORKEYENABLE])
{
UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
{
IWineD3DSurfaceImpl *surf;
surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
if(aop == WINED3DTOP_DISABLE) {
aarg1 = WINED3DTA_TEXTURE;
aop = WINED3DTOP_SELECTARG1;
}
else if(aop == WINED3DTOP_SELECTARG1 && aarg1 != WINED3DTA_TEXTURE) {
if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
aarg2 = WINED3DTA_TEXTURE;
aop = WINED3DTOP_MODULATE;
if (surf->CKeyFlags & WINEDDSD_CKSRCBLT
&& getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000)
{
if (aop == WINED3DTOP_DISABLE)
{
aarg1 = WINED3DTA_TEXTURE;
aop = WINED3DTOP_SELECTARG1;
}
else aarg1 = WINED3DTA_TEXTURE;
}
else if(aop == WINED3DTOP_SELECTARG2 && aarg2 != WINED3DTA_TEXTURE) {
if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
aarg1 = WINED3DTA_TEXTURE;
aop = WINED3DTOP_MODULATE;
else if (aop == WINED3DTOP_SELECTARG1 && aarg1 != WINED3DTA_TEXTURE)
{
if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
{
aarg2 = WINED3DTA_TEXTURE;
aop = WINED3DTOP_MODULATE;
}
else aarg1 = WINED3DTA_TEXTURE;
}
else if (aop == WINED3DTOP_SELECTARG2 && aarg2 != WINED3DTA_TEXTURE)
{
if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
{
aarg1 = WINED3DTA_TEXTURE;
aop = WINED3DTOP_MODULATE;
}
else aarg2 = WINED3DTA_TEXTURE;
}
else aarg2 = WINED3DTA_TEXTURE;
}
}
}
if(is_invalid_op(stateblock->wineD3DDevice, i, aop,
aarg1, aarg2, aarg0)) {
aarg0 = 0xffffffff;
aarg2 = 0xffffffff;
aarg0 = ARG_UNUSED;
aarg2 = ARG_UNUSED;
aarg1 = WINED3DTA_CURRENT;
aop = WINED3DTOP_SELECTARG1;
}
@ -2115,7 +2152,7 @@ void add_ffp_frag_shader(struct hash_table_t *shaders, struct ffp_frag_desc *des
#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
if(stateblock->textures[stage]) {
switch(stateblock->textureDimensions[stage]) {
switch (IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[stage])) {
case GL_TEXTURE_2D:
glDisable(GL_TEXTURE_3D);
checkGLcall("glDisable(GL_TEXTURE_3D)");
@ -2236,3 +2273,29 @@ BOOL ffp_frag_program_key_compare(const void *keya, const void *keyb)
return memcmp(ka, kb, sizeof(*ka)) == 0;
}
UINT wined3d_log2i(UINT32 x)
{
static const BYTE l[] =
{
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
};
UINT32 i;
return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
}

View file

@ -327,8 +327,9 @@ static inline BOOL IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
* done, or if the DIFFUSE is replaced with a D3DCOLOR BLENDWEIGHT we can happily dismiss the change. Some conversion types
* depend on the semantic as well, for example a FLOAT4 texcoord needs no conversion while a FLOAT4 positiont needs one
*/
if(use_vs(device)) {
TRACE("vhsader\n");
if (use_vs(device->stateBlock))
{
TRACE("vshader\n");
/* If the current vertex declaration is marked for no half float conversion don't bother to
* analyse the strided streams in depth, just set them up for no conversion. Return decl changed
* if we used conversion before
@ -363,10 +364,11 @@ static inline BOOL IWineD3DVertexBufferImpl_FindDecl(IWineD3DVertexBufferImpl *T
* FLOAT16s if not supported. Also, we can't iterate over the array, so use macros to generate code for all
* the attributes that our current fixed function pipeline implementation cares for.
*/
BOOL support_d3dcolor = GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA);
ret = check_attribute(This, &device->strided_streams.u.s.position, TRUE, TRUE, FALSE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.normal, TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.diffuse, TRUE, FALSE, TRUE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.specular, TRUE, FALSE, TRUE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.diffuse, !support_d3dcolor, FALSE, TRUE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.specular, !support_d3dcolor, FALSE, TRUE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.texCoords[0], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.texCoords[1], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret;
ret = check_attribute(This, &device->strided_streams.u.s.texCoords[2], TRUE, FALSE, FALSE, &stride_this_run, &float16_used) || ret;

View file

@ -207,7 +207,7 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte
const WINED3DVERTEXELEMENT *elements, UINT element_count) {
IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
HRESULT hr = WINED3D_OK;
int i, j;
int i;
char isPreLoaded[MAX_STREAMS];
TRACE("(%p) : d3d version %d\n", This, ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion);
@ -263,39 +263,13 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte
isPreLoaded[This->pDeclarationWine[i].Stream] = 1;
}
/* Create a sorted array containing the attribute declarations that are of type
* D3DCOLOR. D3DCOLOR requires swizzling of the r and b component, and if the
* declaration of one attribute changes the vertex shader needs recompilation.
* Having a sorted array of the attributes allows efficient comparison of the
* declaration against a shader
*/
if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_D3DCOLOR) {
for(j = 0; j < This->num_swizzled_attribs; j++) {
if(This->swizzled_attribs[j].usage > This->pDeclarationWine[i].Usage ||
(This->swizzled_attribs[j].usage == This->pDeclarationWine[i].Usage &&
This->swizzled_attribs[j].idx > This->pDeclarationWine[i].UsageIndex)) {
memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j],
sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1)));
break;
}
}
This->swizzled_attribs[j].usage = This->pDeclarationWine[i].Usage;
This->swizzled_attribs[j].idx = This->pDeclarationWine[i].UsageIndex;
This->num_swizzled_attribs++;
} else if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2 ||
This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4) {
if(!GL_SUPPORT(NV_HALF_FLOAT)) {
This->half_float_conv_needed = TRUE;
}
if (This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2
|| This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4)
{
if (!GL_SUPPORT(NV_HALF_FLOAT)) This->half_float_conv_needed = TRUE;
}
}
TRACE("Swizzled attributes found:\n");
for(i = 0; i < This->num_swizzled_attribs; i++) {
TRACE("%u: %s%d\n", i,
debug_d3ddeclusage(This->swizzled_attribs[i].usage), This->swizzled_attribs[i].idx);
}
TRACE("Returning\n");
return hr;
}

View file

@ -43,71 +43,71 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
/* This table is not order or position dependent. */
/* Arithmetic */
{WINED3DSIO_NOP, "nop", "NOP", 0, 0, WINED3DSIH_NOP, 0, 0 },
{WINED3DSIO_MOV, "mov", "MOV", 1, 2, WINED3DSIH_MOV, 0, 0 },
{WINED3DSIO_MOVA, "mova", NULL, 1, 2, WINED3DSIH_MOVA, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ADD, "add", "ADD", 1, 3, WINED3DSIH_ADD, 0, 0 },
{WINED3DSIO_SUB, "sub", "SUB", 1, 3, WINED3DSIH_SUB, 0, 0 },
{WINED3DSIO_MAD, "mad", "MAD", 1, 4, WINED3DSIH_MAD, 0, 0 },
{WINED3DSIO_MUL, "mul", "MUL", 1, 3, WINED3DSIH_MUL, 0, 0 },
{WINED3DSIO_RCP, "rcp", "RCP", 1, 2, WINED3DSIH_RCP, 0, 0 },
{WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, WINED3DSIH_RSQ, 0, 0 },
{WINED3DSIO_DP3, "dp3", "DP3", 1, 3, WINED3DSIH_DP3, 0, 0 },
{WINED3DSIO_DP4, "dp4", "DP4", 1, 3, WINED3DSIH_DP4, 0, 0 },
{WINED3DSIO_MIN, "min", "MIN", 1, 3, WINED3DSIH_MIN, 0, 0 },
{WINED3DSIO_MAX, "max", "MAX", 1, 3, WINED3DSIH_MAX, 0, 0 },
{WINED3DSIO_SLT, "slt", "SLT", 1, 3, WINED3DSIH_SLT, 0, 0 },
{WINED3DSIO_SGE, "sge", "SGE", 1, 3, WINED3DSIH_SGE, 0, 0 },
{WINED3DSIO_ABS, "abs", "ABS", 1, 2, WINED3DSIH_ABS, 0, 0 },
{WINED3DSIO_EXP, "exp", "EX2", 1, 2, WINED3DSIH_EXP, 0, 0 },
{WINED3DSIO_LOG, "log", "LG2", 1, 2, WINED3DSIH_LOG, 0, 0 },
{WINED3DSIO_EXPP, "expp", "EXP", 1, 2, WINED3DSIH_EXPP, 0, 0 },
{WINED3DSIO_LOGP, "logp", "LOG", 1, 2, WINED3DSIH_LOGP, 0, 0 },
{WINED3DSIO_LIT, "lit", "LIT", 1, 2, WINED3DSIH_LIT, 0, 0 },
{WINED3DSIO_DST, "dst", "DST", 1, 3, WINED3DSIH_DST, 0, 0 },
{WINED3DSIO_LRP, "lrp", "LRP", 1, 4, WINED3DSIH_LRP, 0, 0 },
{WINED3DSIO_FRC, "frc", "FRC", 1, 2, WINED3DSIH_FRC, 0, 0 },
{WINED3DSIO_POW, "pow", "POW", 1, 3, WINED3DSIH_POW, 0, 0 },
{WINED3DSIO_CRS, "crs", "XPD", 1, 3, WINED3DSIH_CRS, 0, 0 },
/* TODO: sng can possibly be performed a s
{WINED3DSIO_NOP, "nop", 0, 0, WINED3DSIH_NOP, 0, 0 },
{WINED3DSIO_MOV, "mov", 1, 2, WINED3DSIH_MOV, 0, 0 },
{WINED3DSIO_MOVA, "mova", 1, 2, WINED3DSIH_MOVA, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ADD, "add", 1, 3, WINED3DSIH_ADD, 0, 0 },
{WINED3DSIO_SUB, "sub", 1, 3, WINED3DSIH_SUB, 0, 0 },
{WINED3DSIO_MAD, "mad", 1, 4, WINED3DSIH_MAD, 0, 0 },
{WINED3DSIO_MUL, "mul", 1, 3, WINED3DSIH_MUL, 0, 0 },
{WINED3DSIO_RCP, "rcp", 1, 2, WINED3DSIH_RCP, 0, 0 },
{WINED3DSIO_RSQ, "rsq", 1, 2, WINED3DSIH_RSQ, 0, 0 },
{WINED3DSIO_DP3, "dp3", 1, 3, WINED3DSIH_DP3, 0, 0 },
{WINED3DSIO_DP4, "dp4", 1, 3, WINED3DSIH_DP4, 0, 0 },
{WINED3DSIO_MIN, "min", 1, 3, WINED3DSIH_MIN, 0, 0 },
{WINED3DSIO_MAX, "max", 1, 3, WINED3DSIH_MAX, 0, 0 },
{WINED3DSIO_SLT, "slt", 1, 3, WINED3DSIH_SLT, 0, 0 },
{WINED3DSIO_SGE, "sge", 1, 3, WINED3DSIH_SGE, 0, 0 },
{WINED3DSIO_ABS, "abs", 1, 2, WINED3DSIH_ABS, 0, 0 },
{WINED3DSIO_EXP, "exp", 1, 2, WINED3DSIH_EXP, 0, 0 },
{WINED3DSIO_LOG, "log", 1, 2, WINED3DSIH_LOG, 0, 0 },
{WINED3DSIO_EXPP, "expp", 1, 2, WINED3DSIH_EXPP, 0, 0 },
{WINED3DSIO_LOGP, "logp", 1, 2, WINED3DSIH_LOGP, 0, 0 },
{WINED3DSIO_LIT, "lit", 1, 2, WINED3DSIH_LIT, 0, 0 },
{WINED3DSIO_DST, "dst", 1, 3, WINED3DSIH_DST, 0, 0 },
{WINED3DSIO_LRP, "lrp", 1, 4, WINED3DSIH_LRP, 0, 0 },
{WINED3DSIO_FRC, "frc", 1, 2, WINED3DSIH_FRC, 0, 0 },
{WINED3DSIO_POW, "pow", 1, 3, WINED3DSIH_POW, 0, 0 },
{WINED3DSIO_CRS, "crs", 1, 3, WINED3DSIH_CRS, 0, 0 },
/* TODO: sng can possibly be performed as
RCP tmp, vec
MUL out, tmp, vec*/
{WINED3DSIO_SGN, "sgn", NULL, 1, 2, WINED3DSIH_SGN, 0, 0 },
{WINED3DSIO_NRM, "nrm", NULL, 1, 2, WINED3DSIH_NRM, 0, 0 },
{WINED3DSIO_SINCOS, "sincos", NULL, 1, 4, WINED3DSIH_SINCOS, WINED3DVS_VERSION(2,0), WINED3DVS_VERSION(2,1)},
{WINED3DSIO_SINCOS, "sincos", "SCS", 1, 2, WINED3DSIH_SINCOS, WINED3DVS_VERSION(3,0), -1 },
{WINED3DSIO_SGN, "sgn", 1, 2, WINED3DSIH_SGN, 0, 0 },
{WINED3DSIO_NRM, "nrm", 1, 2, WINED3DSIH_NRM, 0, 0 },
{WINED3DSIO_SINCOS, "sincos", 1, 4, WINED3DSIH_SINCOS, WINED3DVS_VERSION(2,0), WINED3DVS_VERSION(2,1)},
{WINED3DSIO_SINCOS, "sincos", 1, 2, WINED3DSIH_SINCOS, WINED3DVS_VERSION(3,0), -1 },
/* Matrix */
{WINED3DSIO_M4x4, "m4x4", "undefined", 1, 3, WINED3DSIH_M4x4, 0, 0 },
{WINED3DSIO_M4x3, "m4x3", "undefined", 1, 3, WINED3DSIH_M4x3, 0, 0 },
{WINED3DSIO_M3x4, "m3x4", "undefined", 1, 3, WINED3DSIH_M3x4, 0, 0 },
{WINED3DSIO_M3x3, "m3x3", "undefined", 1, 3, WINED3DSIH_M3x3, 0, 0 },
{WINED3DSIO_M3x2, "m3x2", "undefined", 1, 3, WINED3DSIH_M3x2, 0, 0 },
{WINED3DSIO_M4x4, "m4x4", 1, 3, WINED3DSIH_M4x4, 0, 0 },
{WINED3DSIO_M4x3, "m4x3", 1, 3, WINED3DSIH_M4x3, 0, 0 },
{WINED3DSIO_M3x4, "m3x4", 1, 3, WINED3DSIH_M3x4, 0, 0 },
{WINED3DSIO_M3x3, "m3x3", 1, 3, WINED3DSIH_M3x3, 0, 0 },
{WINED3DSIO_M3x2, "m3x2", 1, 3, WINED3DSIH_M3x2, 0, 0 },
/* Declare registers */
{WINED3DSIO_DCL, "dcl", NULL, 0, 2, WINED3DSIH_DCL, 0, 0 },
{WINED3DSIO_DCL, "dcl", 0, 2, WINED3DSIH_DCL, 0, 0 },
/* Constant definitions */
{WINED3DSIO_DEF, "def", NULL, 1, 5, WINED3DSIH_DEF, 0, 0 },
{WINED3DSIO_DEFB, "defb", GLNAME_REQUIRE_GLSL, 1, 2, WINED3DSIH_DEFB, 0, 0 },
{WINED3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, WINED3DSIH_DEFI, 0, 0 },
{WINED3DSIO_DEF, "def", 1, 5, WINED3DSIH_DEF, 0, 0 },
{WINED3DSIO_DEFB, "defb", 1, 2, WINED3DSIH_DEFB, 0, 0 },
{WINED3DSIO_DEFI, "defi", 1, 5, WINED3DSIH_DEFI, 0, 0 },
/* Flow control - requires GLSL or software shaders */
{WINED3DSIO_REP , "rep", NULL, 0, 1, WINED3DSIH_REP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ENDREP, "endrep", NULL, 0, 0, WINED3DSIH_ENDREP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_IF, "if", NULL, 0, 1, WINED3DSIH_IF, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_IFC, "ifc", NULL, 0, 2, WINED3DSIH_IFC, WINED3DVS_VERSION(2,1), -1 },
{WINED3DSIO_ELSE, "else", NULL, 0, 0, WINED3DSIH_ELSE, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ENDIF, "endif", NULL, 0, 0, WINED3DSIH_ENDIF, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_BREAK, "break", NULL, 0, 0, WINED3DSIH_BREAK, WINED3DVS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKC, "breakc", NULL, 0, 2, WINED3DSIH_BREAKC, WINED3DVS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, WINED3DSIH_BREAKP, 0, 0 },
{WINED3DSIO_CALL, "call", NULL, 0, 1, WINED3DSIH_CALL, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_CALLNZ, "callnz", NULL, 0, 2, WINED3DSIH_CALLNZ, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_LOOP, "loop", NULL, 0, 2, WINED3DSIH_LOOP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_RET, "ret", NULL, 0, 0, WINED3DSIH_RET, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ENDLOOP, "endloop", NULL, 0, 0, WINED3DSIH_ENDLOOP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_LABEL, "label", NULL, 0, 1, WINED3DSIH_LABEL, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_REP , "rep", 0, 1, WINED3DSIH_REP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ENDREP, "endrep", 0, 0, WINED3DSIH_ENDREP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_IF, "if", 0, 1, WINED3DSIH_IF, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_IFC, "ifc", 0, 2, WINED3DSIH_IFC, WINED3DVS_VERSION(2,1), -1 },
{WINED3DSIO_ELSE, "else", 0, 0, WINED3DSIH_ELSE, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ENDIF, "endif", 0, 0, WINED3DSIH_ENDIF, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_BREAK, "break", 0, 0, WINED3DSIH_BREAK, WINED3DVS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKC, "breakc", 0, 2, WINED3DSIH_BREAKC, WINED3DVS_VERSION(2,1), -1 },
{WINED3DSIO_BREAKP, "breakp", 0, 1, WINED3DSIH_BREAKP, 0, 0 },
{WINED3DSIO_CALL, "call", 0, 1, WINED3DSIH_CALL, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_CALLNZ, "callnz", 0, 2, WINED3DSIH_CALLNZ, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_LOOP, "loop", 0, 2, WINED3DSIH_LOOP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_RET, "ret", 0, 0, WINED3DSIH_RET, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_ENDLOOP, "endloop", 0, 0, WINED3DSIH_ENDLOOP, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_LABEL, "label", 0, 1, WINED3DSIH_LABEL, WINED3DVS_VERSION(2,0), -1 },
{WINED3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 1, 3, WINED3DSIH_SETP, 0, 0 },
{WINED3DSIO_TEXLDL, "texldl", NULL, 1, 3, WINED3DSIH_TEXLDL, WINED3DVS_VERSION(3,0), -1 },
{0, NULL, NULL, 0, 0, 0, 0, 0 }
{WINED3DSIO_SETP, "setp", 1, 3, WINED3DSIH_SETP, 0, 0 },
{WINED3DSIO_TEXLDL, "texldl", 1, 3, WINED3DSIH_TEXLDL, WINED3DVS_VERSION(3,0), -1 },
{0, NULL, 0, 0, 0, 0, 0 }
};
static void vshader_set_limits(
@ -120,7 +120,8 @@ static void vshader_set_limits(
/* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
This->baseShader.limits.constant_float = GL_LIMITS(vshader_constantsF);
switch (This->baseShader.hex_version) {
switch (This->baseShader.reg_maps.shader_version)
{
case WINED3DVS_VERSION(1,0):
case WINED3DVS_VERSION(1,1):
This->baseShader.limits.temporary = 12;
@ -161,7 +162,7 @@ static void vshader_set_limits(
This->baseShader.limits.sampler = 0;
This->baseShader.limits.label = 16;
FIXME("Unrecognized vertex shader version %#x\n",
This->baseShader.hex_version);
This->baseShader.reg_maps.shader_version);
}
}
@ -217,150 +218,65 @@ BOOL vshader_get_input(
return FALSE;
}
BOOL vshader_input_is_color(
IWineD3DVertexShader* iface,
unsigned int regnum) {
IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
DWORD usage_token = This->semantics_in[regnum].usage;
DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
int i;
for(i = 0; i < This->num_swizzled_attribs; i++) {
if(This->swizzled_attribs[i].usage == usage &&
This->swizzled_attribs[i].idx == usage_idx) {
return TRUE;
}
}
return FALSE;
}
static inline void find_swizzled_attribs(IWineD3DVertexDeclaration *declaration, IWineD3DVertexShaderImpl *This) {
UINT num = 0, i, j;
UINT numoldswizzles = This->num_swizzled_attribs;
IWineD3DVertexDeclarationImpl *decl = (IWineD3DVertexDeclarationImpl *) declaration;
DWORD usage_token, usage, usage_idx;
BOOL found;
attrib_declaration oldswizzles[sizeof(This->swizzled_attribs) / sizeof(This->swizzled_attribs[0])];
/* Back up the old swizzles to keep attributes that are undefined in the current declaration */
memcpy(oldswizzles, This->swizzled_attribs, sizeof(oldswizzles));
memset(This->swizzled_attribs, 0, sizeof(This->swizzled_attribs[0]) * MAX_ATTRIBS);
for(i = 0; i < decl->num_swizzled_attribs; i++) {
for(j = 0; j < MAX_ATTRIBS; j++) {
if(!This->baseShader.reg_maps.attributes[j]) continue;
usage_token = This->semantics_in[j].usage;
usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
if(decl->swizzled_attribs[i].usage == usage &&
decl->swizzled_attribs[i].idx == usage_idx) {
This->swizzled_attribs[num].usage = usage;
This->swizzled_attribs[num].idx = usage_idx;
num++;
}
}
}
/* Add previously converted attributes back in if they are not defined in the current declaration */
for(i = 0; i < numoldswizzles; i++) {
found = FALSE;
for(j = 0; j < decl->declarationWNumElements; j++) {
if(oldswizzles[i].usage == decl->pDeclarationWine[j].Usage &&
oldswizzles[i].idx == decl->pDeclarationWine[j].UsageIndex) {
found = TRUE;
}
}
if(found) {
/* This previously converted attribute is declared in the current declaration. Either it is
* already in the new array, or it should not be there. Skip it
*/
continue;
}
/* We have a previously swizzled attribute that is not defined by the current vertex declaration.
* Insert it into the new conversion array to keep it in the old defined state. Otherwise we end up
* recompiling if the old decl is used again because undefined attributes are reset to no swizzling.
* In the reverse way(attribute was not swizzled and is not declared in new declaration) the attrib
* stays unswizzled as well because it isn't found in the oldswizzles array
*/
for(j = 0; j < num; j++) {
if(oldswizzles[i].usage > This->swizzled_attribs[j].usage || (
oldswizzles[i].usage == This->swizzled_attribs[j].usage &&
oldswizzles[i].idx > This->swizzled_attribs[j].idx)) {
memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j],
sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1)));
break;
}
}
This->swizzled_attribs[j].usage = oldswizzles[i].usage;
This->swizzled_attribs[j].idx = oldswizzles[i].idx;
num++;
}
TRACE("New swizzled attributes array\n");
for(i = 0; i < num; i++) {
TRACE("%d: %s(%d), %d\n", i, debug_d3ddeclusage(This->swizzled_attribs[i].usage),
This->swizzled_attribs[i].usage, This->swizzled_attribs[i].idx);
}
This->num_swizzled_attribs = num;
}
/** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
or GLSL and send it to the card */
static void IWineD3DVertexShaderImpl_GenerateShader(IWineD3DVertexShader *iface,
const struct shader_reg_maps* reg_maps, const DWORD *pFunction)
{
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
IWineD3DVertexDeclaration *decl = ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->vertexDecl;
SHADER_BUFFER buffer;
find_swizzled_attribs(decl, This);
#if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
This->fixupVertexBufferSize = PGMSIZE;
This->fixupVertexBuffer[0] = 0;
}
buffer.buffer = This->device->fixupVertexBuffer;
#else
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
#endif
buffer.bsize = 0;
buffer.lineNo = 0;
buffer.newline = TRUE;
This->swizzle_map = ((IWineD3DDeviceImpl *)This->baseShader.device)->strided_streams.swizzle_map;
shader_buffer_init(&buffer);
((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_vshader(iface, &buffer);
#if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif
shader_buffer_free(&buffer);
}
/* *******************************************
IWineD3DVertexShader IUnknown parts follow
******************************************* */
static HRESULT WINAPI IWineD3DVertexShaderImpl_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, LPVOID *ppobj) {
return IWineD3DBaseShaderImpl_QueryInterface((IWineD3DBaseShader *) iface, riid, ppobj);
TRACE("iface %p, riid %s, ppobj %p\n", iface, debugstr_guid(riid), ppobj);
if (IsEqualGUID(riid, &IID_IWineD3DVertexShader)
|| IsEqualGUID(riid, &IID_IWineD3DBaseShader)
|| IsEqualGUID(riid, &IID_IWineD3DBase)
|| IsEqualGUID(riid, &IID_IUnknown))
{
IUnknown_AddRef(iface);
*ppobj = iface;
return S_OK;
}
WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
*ppobj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface) {
return IWineD3DBaseShaderImpl_AddRef((IWineD3DBaseShader *) iface);
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
ULONG refcount = InterlockedIncrement(&This->baseShader.ref);
TRACE("%p increasing refcount to %u\n", This, refcount);
return refcount;
}
static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) {
return IWineD3DBaseShaderImpl_Release((IWineD3DBaseShader *) iface);
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
ULONG refcount = InterlockedDecrement(&This->baseShader.ref);
TRACE("%p decreasing refcount to %u\n", This, refcount);
if (!refcount)
{
shader_cleanup((IWineD3DBaseShader *)iface);
HeapFree(GetProcessHeap(), 0, This);
}
return refcount;
}
/* *******************************************
@ -398,16 +314,10 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_GetFunction(IWineD3DVertexShader*
* return D3DERR_MOREDATA. That's not actually true. */
return WINED3DERR_INVALIDCALL;
}
if (NULL == This->baseShader.function) { /* no function defined */
TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
(*(DWORD **) pData) = NULL;
} else {
if(This->baseShader.functionLength == 0){
}
TRACE("(%p) : GetFunction copying to %p\n", This, pData);
memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
}
TRACE("(%p) : GetFunction copying to %p\n", This, pData);
memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
return WINED3D_OK;
}
@ -425,8 +335,7 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
TRACE("(%p) : pFunction %p\n", iface, pFunction);
/* First pass: trace shader */
shader_trace_init((IWineD3DBaseShader*) This, pFunction);
vshader_set_limits(This);
if (TRACE_ON(d3d_shader)) shader_trace_init(pFunction, This->baseShader.shader_ins);
/* Initialize immediate constant lists */
list_init(&This->baseShader.constantsF);
@ -438,9 +347,11 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
This->max_rel_offset = 0;
memset(reg_maps, 0, sizeof(shader_reg_maps));
hr = shader_get_registers_used((IWineD3DBaseShader*) This, reg_maps,
This->semantics_in, This->semantics_out, pFunction, NULL);
This->semantics_in, This->semantics_out, pFunction);
if (hr != WINED3D_OK) return hr;
vshader_set_limits(This);
This->baseShader.shader_mode = deviceImpl->vs_selected_mode;
if(deviceImpl->vs_selected_mode == SHADER_ARB &&
@ -462,16 +373,9 @@ static HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader
This->baseShader.load_local_constsF = This->baseShader.reg_maps.usesrelconstF && !list_empty(&This->baseShader.constantsF);
/* copy the function ... because it will certainly be released by application */
if (NULL != pFunction) {
void *function;
function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->baseShader.functionLength);
if (!function) return E_OUTOFMEMORY;
memcpy(function, pFunction, This->baseShader.functionLength);
This->baseShader.function = function;
} else {
This->baseShader.function = NULL;
}
This->baseShader.function = HeapAlloc(GetProcessHeap(), 0, This->baseShader.functionLength);
if (!This->baseShader.function) return E_OUTOFMEMORY;
memcpy(This->baseShader.function, pFunction, This->baseShader.functionLength);
return WINED3D_OK;
}
@ -514,56 +418,8 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex
return WINED3D_OK;
}
static inline BOOL swizzled_attribs_differ(IWineD3DVertexShaderImpl *This, IWineD3DVertexDeclarationImpl *vdecl) {
UINT i, j, k;
BOOL found;
DWORD usage_token;
DWORD usage;
DWORD usage_idx;
for(i = 0; i < vdecl->declarationWNumElements; i++) {
/* Ignore tesselated streams and the termination entry(position0, stream 255, unused) */
if(vdecl->pDeclarationWine[i].Stream >= MAX_STREAMS ||
vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_UNUSED) continue;
for(j = 0; j < MAX_ATTRIBS; j++) {
if(!This->baseShader.reg_maps.attributes[j]) continue;
usage_token = This->semantics_in[j].usage;
usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
if(vdecl->pDeclarationWine[i].Usage != usage ||
vdecl->pDeclarationWine[i].UsageIndex != usage_idx) {
continue;
}
found = FALSE;
for(k = 0; k < This->num_swizzled_attribs; k++) {
if(This->swizzled_attribs[k].usage == usage &&
This->swizzled_attribs[k].idx == usage_idx) {
found = TRUE;
}
}
if(!found && vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_D3DCOLOR) {
TRACE("Attribute %s%d is D3DCOLOR now but wasn't before\n",
debug_d3ddeclusage(usage), usage_idx);
return TRUE;
}
if( found && vdecl->pDeclarationWine[i].Type != WINED3DDECLTYPE_D3DCOLOR) {
TRACE("Attribute %s%d was D3DCOLOR before but is not any more\n",
debug_d3ddeclusage(usage), usage_idx);
return TRUE;
}
}
}
return FALSE;
}
HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
IWineD3DVertexDeclarationImpl *vdecl;
CONST DWORD *function = This->baseShader.function;
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
@ -571,20 +427,10 @@ HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
/* We're already compiled. */
if (This->baseShader.is_compiled) {
vdecl = (IWineD3DVertexDeclarationImpl *) deviceImpl->stateBlock->vertexDecl;
if(This->num_swizzled_attribs != vdecl->num_swizzled_attribs ||
memcmp(This->swizzled_attribs, vdecl->swizzled_attribs, sizeof(vdecl->swizzled_attribs[0]) * This->num_swizzled_attribs) != 0) {
/* The swizzled attributes differ between shader and declaration. This doesn't necessarily mean
* we have to recompile, but we have to take a deeper look at see if the attribs that differ
* are declared in the decl and used in the shader
*/
if(swizzled_attribs_differ(This, vdecl)) {
WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This);
goto recompile;
}
WARN("Swizzled attribute validation required an expensive comparison\n");
if ((This->swizzle_map & deviceImpl->strided_streams.use_map) != deviceImpl->strided_streams.swizzle_map)
{
WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This);
goto recompile;
}
return WINED3D_OK;
@ -599,12 +445,6 @@ HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
deviceImpl->shader_backend->shader_destroy((IWineD3DBaseShader *) iface);
}
/* We don't need to compile */
if (!function) {
This->baseShader.is_compiled = TRUE;
return WINED3D_OK;
}
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
IWineD3DVertexShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);

View file

@ -64,6 +64,31 @@ static void volume_bind_and_dirtify(IWineD3DVolume *iface) {
}
}
void volume_add_dirty_box(IWineD3DVolume *iface, const WINED3DBOX *dirty_box)
{
IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
This->dirty = TRUE;
if (dirty_box)
{
This->lockedBox.Left = min(This->lockedBox.Left, dirty_box->Left);
This->lockedBox.Top = min(This->lockedBox.Top, dirty_box->Top);
This->lockedBox.Front = min(This->lockedBox.Front, dirty_box->Front);
This->lockedBox.Right = max(This->lockedBox.Right, dirty_box->Right);
This->lockedBox.Bottom = max(This->lockedBox.Bottom, dirty_box->Bottom);
This->lockedBox.Back = max(This->lockedBox.Back, dirty_box->Back);
}
else
{
This->lockedBox.Left = 0;
This->lockedBox.Top = 0;
This->lockedBox.Front = 0;
This->lockedBox.Right = This->currentDesc.Width;
This->lockedBox.Bottom = This->currentDesc.Height;
This->lockedBox.Back = This->currentDesc.Depth;
}
}
/* *******************************************
IWineD3DVolume IUnknown parts follow
******************************************* */
@ -225,7 +250,7 @@ static HRESULT WINAPI IWineD3DVolumeImpl_LockBox(IWineD3DVolume *iface, WINED3DL
* Dirtify on lock
* as seen in msdn docs
*/
IWineD3DVolume_AddDirtyBox(iface, &This->lockedBox);
volume_add_dirty_box(iface, &This->lockedBox);
/** Dirtify Container if needed */
if (NULL != This->container) {
@ -261,39 +286,6 @@ static HRESULT WINAPI IWineD3DVolumeImpl_UnlockBox(IWineD3DVolume *iface) {
/* Internal use functions follow : */
static HRESULT WINAPI IWineD3DVolumeImpl_CleanDirtyBox(IWineD3DVolume *iface) {
IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
This->dirty = FALSE;
This->lockedBox.Left = This->currentDesc.Width;
This->lockedBox.Top = This->currentDesc.Height;
This->lockedBox.Front = This->currentDesc.Depth;
This->lockedBox.Right = 0;
This->lockedBox.Bottom = 0;
This->lockedBox.Back = 0;
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DVolumeImpl_AddDirtyBox(IWineD3DVolume *iface, CONST WINED3DBOX* pDirtyBox) {
IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
This->dirty = TRUE;
if (NULL != pDirtyBox) {
This->lockedBox.Left = min(This->lockedBox.Left, pDirtyBox->Left);
This->lockedBox.Top = min(This->lockedBox.Top, pDirtyBox->Top);
This->lockedBox.Front = min(This->lockedBox.Front, pDirtyBox->Front);
This->lockedBox.Right = max(This->lockedBox.Right, pDirtyBox->Right);
This->lockedBox.Bottom = max(This->lockedBox.Bottom, pDirtyBox->Bottom);
This->lockedBox.Back = max(This->lockedBox.Back, pDirtyBox->Back);
} else {
This->lockedBox.Left = 0;
This->lockedBox.Top = 0;
This->lockedBox.Front = 0;
This->lockedBox.Right = This->currentDesc.Width;
This->lockedBox.Bottom = This->currentDesc.Height;
This->lockedBox.Back = This->currentDesc.Depth;
}
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DVolumeImpl_SetContainer(IWineD3DVolume *iface, IWineD3DBase* container) {
IWineD3DVolumeImpl *This = (IWineD3DVolumeImpl *)iface;
@ -374,8 +366,6 @@ const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl =
IWineD3DVolumeImpl_LockBox,
IWineD3DVolumeImpl_UnlockBox,
/* Internal interface */
IWineD3DVolumeImpl_AddDirtyBox,
IWineD3DVolumeImpl_CleanDirtyBox,
IWineD3DVolumeImpl_LoadTexture,
IWineD3DVolumeImpl_SetContainer
};

View file

@ -119,7 +119,7 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac
FIXME("Volumetexture (%p) has been reloaded at least 20 times due to WINED3DSAMP_SRGBTEXTURE changes on it\'s sampler\n", This);
for (i = 0; i < This->baseTexture.levels; i++) {
IWineD3DVolume_AddDirtyBox(This->volumes[i], NULL);
volume_add_dirty_box(This->volumes[i], NULL);
IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode);
}
} else {
@ -244,7 +244,7 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetLevelDesc(IWineD3DVolumeTextu
TRACE("(%p) Level (%d)\n", This, Level);
return IWineD3DVolume_GetDesc(This->volumes[Level], pDesc);
} else {
FIXME("(%p) Level (%d)\n", This, Level);
WARN("(%p) Level (%d)\n", This, Level);
}
return WINED3D_OK;
}
@ -255,7 +255,7 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_GetVolumeLevel(IWineD3DVolumeTex
IWineD3DVolume_AddRef(*ppVolumeLevel);
TRACE("(%p) -> level(%d) returning volume@%p\n", This, Level, *ppVolumeLevel);
} else {
FIXME("(%p) Level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
WARN("(%p) Level(%d) overflow Levels(%d)\n", This, Level, This->baseTexture.levels);
return WINED3DERR_INVALIDCALL;
}
return WINED3D_OK;
@ -295,7 +295,9 @@ static HRESULT WINAPI IWineD3DVolumeTextureImpl_AddDirtyBox(IWineD3DVolumeTextur
IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface;
This->baseTexture.dirty = TRUE;
TRACE("(%p) : dirtyfication of volume Level (0)\n", This);
return IWineD3DVolume_AddDirtyBox(This->volumes[0], pDirtyBox);
volume_add_dirty_box(This->volumes[0], pDirtyBox);
return WINED3D_OK;
}
const IWineD3DVolumeTextureVtbl IWineD3DVolumeTexture_Vtbl =

View file

@ -26,6 +26,7 @@
<file>device.c</file>
<file>directx.c</file>
<file>drawprim.c</file>
<file>gl_compat.c</file>
<file>glsl_shader.c</file>
<file>indexbuffer.c</file>
<file>nvidia_texture_shader.c</file>
@ -52,4 +53,4 @@
<file>version.rc</file>
<dependency>wineheaders</dependency>
</module>
</module>

View file

@ -866,6 +866,7 @@ void (WINE_GLAPI *glDepthFunc) (GLenum func);
void (WINE_GLAPI *glDepthMask) (GLboolean flag);
void (WINE_GLAPI *glDepthRange) (GLclampd nearParam, GLclampd farParam);
void (WINE_GLAPI *glDisable) (GLenum cap);
void (WINE_GLAPI *glDisableWINE) (GLenum cap);
void (WINE_GLAPI *glDisableClientState) (GLenum array);
void (WINE_GLAPI *glDrawArrays) (GLenum mode, GLint first, GLsizei count);
void (WINE_GLAPI *glDrawBuffer) (GLenum mode);
@ -875,6 +876,7 @@ void (WINE_GLAPI *glEdgeFlag) (GLboolean flag);
void (WINE_GLAPI *glEdgeFlagPointer) (GLsizei stride, const GLvoid* pointer);
void (WINE_GLAPI *glEdgeFlagv) (const GLboolean* flag);
void (WINE_GLAPI *glEnable) (GLenum cap);
void (WINE_GLAPI *glEnableWINE) (GLenum cap);
void (WINE_GLAPI *glEnableClientState) (GLenum array);
void (WINE_GLAPI *glEnd) ();
void (WINE_GLAPI *glEndList) ();
@ -2037,6 +2039,39 @@ typedef void (WINE_GLAPI * PGLFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint le
#define GL_RGBA16F_ARB 0x881A
#define GL_RGB16F_ARB 0x881B
#endif
/* GL_ARB_texture_rg */
#ifndef GL_ARB_texture_rg
#define GL_RG 0x8227
#define GL_RG_INTEGER 0x8228
#define GL_R8 0x8229
#define GL_R16 0x822A
#define GL_RG8 0x822B
#define GL_RG16 0x822C
#define GL_R16F 0x822D
#define GL_R32F 0x822E
#define GL_RG16F 0x822F
#define GL_RG32F 0x8230
#define GL_R8I 0x8231
#define GL_R8UI 0x8232
#define GL_R16I 0x8233
#define GL_R16UI 0x8234
#define GL_R32I 0x8235
#define GL_R32UI 0x8236
#define GL_RG8I 0x8237
#define GL_RG8UI 0x8238
#define GL_RG16I 0x8239
#define GL_RG16UI 0x823A
#define GL_RG32I 0x823B
#define GL_RG32UI 0x823C
#endif
/* GL_EXT_texture_swizzle */
#ifndef GL_EXT_texture_swizzle
#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
#endif
/* GL_ARB_half_float_pixel */
#ifndef GL_ARB_half_float_pixel
#define GL_ARB_half_float_pixel
@ -2288,10 +2323,10 @@ typedef void (WINE_GLAPI * PGLFNBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, G
#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
#endif /* GL_EXT_fog_coord */
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDFEXTPROC) (GLfloat intesity);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDFVEXTPROC) (GLfloat intesity);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDDEXTPROC) (GLfloat intesity);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDDVEXTPROC) (GLfloat intesity);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDFEXTPROC) (GLfloat coord);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDDEXTPROC) (GLdouble coord);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
typedef void (WINE_GLAPI * PGLFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *data);
/* GL_ARB_shader_objects (GLSL) */
#ifndef GL_ARB_shader_objects
@ -3317,6 +3352,7 @@ typedef enum _GL_SupportedExt {
ARB_TEXTURE_MIRRORED_REPEAT,
ARB_TEXTURE_NON_POWER_OF_TWO,
ARB_TEXTURE_RECTANGLE,
ARB_TEXTURE_RG,
ARB_VERTEX_PROGRAM,
ARB_VERTEX_BLEND,
ARB_VERTEX_BUFFER_OBJECT,
@ -3347,7 +3383,9 @@ typedef enum _GL_SupportedExt {
EXT_TEXTURE_ENV_COMBINE,
EXT_TEXTURE_ENV_DOT3,
EXT_TEXTURE_SRGB,
EXT_TEXTURE_SWIZZLE,
EXT_GPU_PROGRAM_PARAMETERS,
EXT_VERTEX_ARRAY_BGRA,
/* NVIDIA */
NV_HALF_FLOAT,
NV_FOG_DISTANCE,
@ -3471,7 +3509,7 @@ typedef enum _GL_SupportedExt {
USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, glFogCoordfEXT, EXT_FOG_COORD, NULL )\
USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC, glFogCoordfvEXT, EXT_FOG_COORD, NULL )\
USE_GL_FUNC(PGLFNGLFOGCOORDDEXTPROC, glFogCoorddEXT, EXT_FOG_COORD, NULL )\
USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoordvEXT, EXT_FOG_COORD, NULL )\
USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoorddvEXT, EXT_FOG_COORD, NULL )\
USE_GL_FUNC(PGLFNGLFOGCOORDPOINTEREXTPROC, glFogCoordPointerEXT, EXT_FOG_COORD, NULL )\
/* GL_EXT_framebuffer_object */ \
USE_GL_FUNC(PGLFNGLISRENDERBUFFEREXTPROC, glIsRenderbufferEXT, EXT_FRAMEBUFFER_OBJECT, NULL )\
@ -3579,8 +3617,8 @@ typedef enum _GL_SupportedExt {
USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX2FVARBPROC, glUniformMatrix2fvARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX3FVARBPROC, glUniformMatrix3fvARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLUNIFORMMATRIX4FVARBPROC, glUniformMatrix4fvARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMFVARBPROC, glGetUniform4fvARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMIVARBPROC, glGetUniform4ivARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMFVARBPROC, glGetUniformfvARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLGETUNIFORMIVARBPROC, glGetUniformivARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLGETINFOLOGARBPROC, glGetInfoLogARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB, ARB_SHADER_OBJECTS, NULL )\
USE_GL_FUNC(WINED3D_PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB, ARB_SHADER_OBJECTS, NULL )\
@ -3678,8 +3716,8 @@ typedef enum _GL_SupportedExt {
USE_GL_FUNC(PGLXFNGETVIDEOSYNCSGIPROC, glXGetVideoSyncSGI, SGI_VIDEO_SYNC, NULL )\
USE_GL_FUNC(PGLXFNWAITVIDEOSYNCSGIPROC, glXWaitVideoSyncSGI, SGI_VIDEO_SYNC, NULL )\
/* GL_APPLE_flush_render */ \
USE_GL_FUNC(PGLFNFLUSHRENDERAPPLEPROC, glFlushRenderApple, APPLE_FLUSH_RENDER, NULL )\
USE_GL_FUNC(PGLFNFINISHRENDERAPPLEPROC, glFinishRenderApple, APPLE_FLUSH_RENDER, NULL )\
USE_GL_FUNC(PGLFNFLUSHRENDERAPPLEPROC, glFlushRenderAPPLE, APPLE_FLUSH_RENDER, NULL )\
USE_GL_FUNC(PGLFNFINISHRENDERAPPLEPROC, glFinishRenderAPPLE, APPLE_FLUSH_RENDER, NULL )\
/* GL_EXT_gpu_program_parameters */ \
USE_GL_FUNC(PGLFNPROGRAMENVPARAMETERS4FVEXTPROC, glProgramEnvParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL )\
USE_GL_FUNC(PGLFNPROGRAMLOCALPARAMETERS4FVEXTPROC, glProgramLocalParameters4fvEXT, EXT_GPU_PROGRAM_PARAMETERS,NULL )\
@ -3817,6 +3855,7 @@ typedef struct _WINED3DGLTYPE {
int d3dType;
GLint size;
GLenum glType;
GLint format;
GLboolean normalized;
int typesize;
} WINED3DGLTYPE;

View file

@ -29,8 +29,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
int num_lock = 0;
void (*wine_tsx11_lock_ptr)(void) = NULL;
void (*wine_tsx11_unlock_ptr)(void) = NULL;
void (*CDECL wine_tsx11_lock_ptr)(void) = NULL;
void (*CDECL wine_tsx11_unlock_ptr)(void) = NULL;
/* When updating default value here, make sure to update winecfg as well,
@ -88,7 +88,7 @@ static inline DWORD get_config_key_dword(HKEY defkey, HKEY appkey, const char* n
return ERROR_FILE_NOT_FOUND;
}
static void wined3d_do_nothing(void)
static void CDECL wined3d_do_nothing(void)
{
}

View file

@ -155,6 +155,7 @@ struct hash_table_t {
struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function);
void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb);
void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context);
void *hash_table_get(const struct hash_table_t *table, const void *key);
void hash_table_put(struct hash_table_t *table, void *key, void *value);
void hash_table_remove(struct hash_table_t *table, void *key);
@ -214,6 +215,7 @@ void init_type_lookup(WineD3D_GL_Info *gl_info);
#define WINED3D_ATR_TYPE(type) GLINFO_LOCATION.glTypeLookup[type].d3dType
#define WINED3D_ATR_SIZE(type) GLINFO_LOCATION.glTypeLookup[type].size
#define WINED3D_ATR_GLTYPE(type) GLINFO_LOCATION.glTypeLookup[type].glType
#define WINED3D_ATR_FORMAT(type) GLINFO_LOCATION.glTypeLookup[type].format
#define WINED3D_ATR_NORMALIZED(type) GLINFO_LOCATION.glTypeLookup[type].normalized
#define WINED3D_ATR_TYPESIZE(type) GLINFO_LOCATION.glTypeLookup[type].typesize
@ -429,19 +431,50 @@ enum tex_types
tex_type_count = 5,
};
enum vertexprocessing_mode {
fixedfunction,
vertexshader,
pretransformed
};
struct stb_const_desc {
char texunit;
UINT const_num;
};
enum fogmode {
FOG_OFF,
FOG_LINEAR,
FOG_EXP,
FOG_EXP2
};
/* Stateblock dependent parameters which have to be hardcoded
* into the shader code
*/
struct ps_compile_args {
struct color_fixup_desc color_fixup[MAX_FRAGMENT_SAMPLERS];
BOOL srgb_correction;
enum vertexprocessing_mode vp_mode;
enum fogmode fog;
/* Projected textures(ps 1.0-1.3) */
/* Texture types(2D, Cube, 3D) in ps 1.x */
};
typedef struct {
const SHADER_HANDLER *shader_instruction_handler_table;
void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS);
void (*shader_select_depth_blt)(IWineD3DDevice *iface, enum tex_types tex_type);
void (*shader_deselect_depth_blt)(IWineD3DDevice *iface);
void (*shader_update_float_vertex_constants)(IWineD3DDevice *iface, UINT start, UINT count);
void (*shader_update_float_pixel_constants)(IWineD3DDevice *iface, UINT start, UINT count);
void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS);
void (*shader_cleanup)(IWineD3DDevice *iface);
void (*shader_color_correction)(const struct SHADER_OPCODE_ARG *arg, struct color_fixup_desc fixup);
void (*shader_destroy)(IWineD3DBaseShader *iface);
HRESULT (*shader_alloc_private)(IWineD3DDevice *iface);
void (*shader_free_private)(IWineD3DDevice *iface);
BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface);
GLuint (*shader_generate_pshader)(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer);
GLuint (*shader_generate_pshader)(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args);
void (*shader_generate_vshader)(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer);
void (*shader_get_caps)(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *caps);
BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);
@ -453,8 +486,8 @@ extern const shader_backend_t none_shader_backend;
/* X11 locking */
extern void (*wine_tsx11_lock_ptr)(void);
extern void (*wine_tsx11_unlock_ptr)(void);
extern void (* CDECL wine_tsx11_lock_ptr)(void);
extern void (* CDECL wine_tsx11_unlock_ptr)(void);
/* As GLX relies on X, this is needed */
extern int num_lock;
@ -501,9 +534,7 @@ extern int num_lock;
#define MAX_STREAMS 16 /* Maximum possible streams - used for fixed size arrays
See MaxStreams in MSDN under GetDeviceCaps */
/* Maximum number of constants provided to the shaders */
#define HIGHEST_TRANSFORMSTATE 512
/* Highest value in WINED3DTRANSFORMSTATETYPE */
#define HIGHEST_TRANSFORMSTATE WINED3DTS_WORLDMATRIX(255) /* Highest value in WINED3DTRANSFORMSTATETYPE */
/* Checking of API calls */
/* --------------------- */
@ -613,16 +644,8 @@ extern LONG primCounter;
*/
/* Routine common to the draw primitive and draw indexed primitive routines */
void drawPrimitive(IWineD3DDevice *iface,
int PrimitiveType,
long NumPrimitives,
/* for Indexed: */
long StartVertexIndex,
UINT numberOfVertices,
long StartIdx,
short idxBytes,
const void *idxData,
int minIndex);
void drawPrimitive(IWineD3DDevice *iface, int PrimitiveType, long NumPrimitives,
UINT numberOfVertices, long start_idx, short idxBytes, const void *idxData, int minIndex);
void primitiveDeclarationConvertToStridedData(
IWineD3DDevice *iface,
@ -639,7 +662,6 @@ extern glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
extern glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
extern glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
extern glAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
#define eps 1e-8
@ -653,7 +675,7 @@ typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock,
#define STATE_RENDER(a) (a)
#define STATE_IS_RENDER(a) ((a) >= STATE_RENDER(1) && (a) <= STATE_RENDER(WINEHIGHEST_RENDER_STATE))
#define STATE_TEXTURESTAGE(stage, num) (STATE_RENDER(WINEHIGHEST_RENDER_STATE) + (stage) * WINED3D_HIGHEST_TEXTURE_STATE + (num))
#define STATE_TEXTURESTAGE(stage, num) (STATE_RENDER(WINEHIGHEST_RENDER_STATE) + 1 + (stage) * (WINED3D_HIGHEST_TEXTURE_STATE + 1) + (num))
#define STATE_IS_TEXTURESTAGE(a) ((a) >= STATE_TEXTURESTAGE(0, 1) && (a) <= STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE))
/* + 1 because samplers start with 0 */
@ -740,7 +762,7 @@ extern const struct fragment_pipeline nvts_fragment_pipeline;
extern const struct fragment_pipeline nvrc_fragment_pipeline;
/* "Base" state table */
void compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc);
@ -756,6 +778,12 @@ struct blit_shader {
extern const struct blit_shader ffp_blit;
extern const struct blit_shader arbfp_blit;
enum fogsource {
FOGSOURCE_FFP,
FOGSOURCE_VS,
FOGSOURCE_COORD,
};
/* The new context manager that should deal with onscreen and offscreen rendering */
struct WineD3DContext {
/* State dirtification
@ -772,21 +800,27 @@ struct WineD3DContext {
DWORD tid; /* Thread ID which owns this context at the moment */
/* Stores some information about the context state for optimization */
BOOL draw_buffer_dirty;
BOOL last_was_rhw; /* true iff last draw_primitive was in xyzrhw mode */
BOOL last_was_pshader;
BOOL last_was_vshader;
BOOL last_was_foggy_shader;
BOOL namedArraysLoaded, numberedArraysLoaded;
WORD draw_buffer_dirty : 1;
WORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */
WORD last_was_pshader : 1;
WORD last_was_vshader : 1;
WORD last_was_foggy_shader : 1;
WORD namedArraysLoaded : 1;
WORD numberedArraysLoaded : 1;
WORD last_was_blit : 1;
WORD last_was_ckey : 1;
WORD fog_coord : 1;
WORD isPBuffer : 1;
WORD fog_enabled : 1;
WORD num_untracked_materials : 2; /* Max value 2 */
WORD padding : 2;
BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */
BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */
DWORD numbered_array_mask;
BOOL lastWasPow2Texture[MAX_TEXTURES];
GLenum tracking_parm; /* Which source is tracking current colour */
unsigned char num_untracked_materials;
GLenum untracked_materials[2];
BOOL last_was_blit, last_was_ckey;
UINT blit_w, blit_h;
char texShaderBumpMap;
BOOL fog_coord;
enum fogsource fog_source;
char *vshader_const_dirty, *pshader_const_dirty;
@ -795,7 +829,6 @@ struct WineD3DContext {
HWND win_handle;
HDC hdc;
HPBUFFERARB pbuffer;
BOOL isPBuffer;
GLint aux_buffers;
/* FBOs */
@ -803,6 +836,11 @@ struct WineD3DContext {
struct fbo_entry *current_fbo;
GLuint src_fbo;
GLuint dst_fbo;
/* Extension emulation */
GLint gl_fog_source;
GLfloat fog_coord_value;
GLfloat color[4], fogstart, fogend, fogcolor[4];
};
typedef enum ContextUsage {
@ -813,6 +851,7 @@ typedef enum ContextUsage {
} ContextUsage;
void ActivateContext(IWineD3DDeviceImpl *device, IWineD3DSurface *target, ContextUsage usage);
WineD3DContext *getActiveContext(void);
WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms);
void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context);
void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type);
@ -891,6 +930,7 @@ struct WineD3DAdapter
extern BOOL InitAdapters(void);
extern BOOL initPixelFormats(WineD3D_GL_Info *gl_info);
extern long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram);
extern void add_gl_compat_wrappers(WineD3D_GL_Info *gl_info);
/*****************************************************************************
* High order patch management
@ -924,7 +964,7 @@ enum dst_arg
/*****************************************************************************
* Fixed function pipeline replacements
*/
#define ARG_UNUSED 0x3f
#define ARG_UNUSED 0xff
struct texture_stage_op
{
unsigned cop : 8;
@ -937,7 +977,7 @@ struct texture_stage_op
unsigned aarg2 : 8;
unsigned aarg0 : 8;
struct color_fixup_desc color_correction;
struct color_fixup_desc color_fixup;
unsigned tex_type : 3;
unsigned dst : 1;
unsigned projected : 2;
@ -946,12 +986,7 @@ struct texture_stage_op
struct ffp_frag_settings {
struct texture_stage_op op[MAX_TEXTURES];
enum {
FOG_OFF,
FOG_LINEAR,
FOG_EXP,
FOG_EXP2
} fog;
enum fogmode fog;
/* Use an int instead of a char to get dword alignment */
unsigned int sRGB_write;
};
@ -1004,6 +1039,7 @@ struct IWineD3DDeviceImpl
/* WineD3D Information */
IUnknown *parent;
IWineD3DDeviceParent *device_parent;
IWineD3D *wineD3D;
struct WineD3DAdapter *adapter;
@ -1030,19 +1066,30 @@ struct IWineD3DDeviceImpl
unsigned int max_ffp_textures, max_ffp_texture_stages;
/* To store */
BOOL view_ident; /* true iff view matrix is identity */
BOOL untransformed;
BOOL vertexBlendUsed; /* To avoid needless setting of the blend matrices */
WORD view_ident : 1; /* true iff view matrix is identity */
WORD untransformed : 1;
WORD vertexBlendUsed : 1; /* To avoid needless setting of the blend matrices */
WORD isRecordingState : 1;
WORD isInDraw : 1;
WORD render_offscreen : 1;
WORD bCursorVisible : 1;
WORD haveHardwareCursor : 1;
WORD d3d_initialized : 1;
WORD inScene : 1; /* A flag to check for proper BeginScene / EndScene call pairs */
WORD softwareVertexProcessing : 1; /* process vertex shaders using software or hardware */
WORD useDrawStridedSlow : 1;
WORD instancedDraw : 1;
WORD padding : 3;
BYTE fixed_function_usage_map; /* MAX_TEXTURES, 8 */
#define DDRAW_PITCH_ALIGNMENT 8
#define D3D8_PITCH_ALIGNMENT 4
unsigned char surface_alignment; /* Line Alignment of surfaces */
/* State block related */
BOOL isRecordingState;
IWineD3DStateBlockImpl *stateBlock;
IWineD3DStateBlockImpl *updateStateBlock;
BOOL isInDraw;
/* Internal use fields */
WINED3DDEVICE_CREATION_PARAMETERS createParms;
@ -1072,7 +1119,6 @@ struct IWineD3DDeviceImpl
UINT paletteConversionShader;
/* For rendering to a texture using glCopyTexImage */
BOOL render_offscreen;
GLenum *draw_buffers;
GLuint depth_blt_texture;
GLuint depth_blt_rb;
@ -1080,14 +1126,12 @@ struct IWineD3DDeviceImpl
UINT depth_blt_rb_h;
/* Cursor management */
BOOL bCursorVisible;
UINT xHotSpot;
UINT yHotSpot;
UINT xScreenSpace;
UINT yScreenSpace;
UINT cursorWidth, cursorHeight;
GLuint cursorTexture;
BOOL haveHardwareCursor;
HCURSOR hardwareCursor;
/* The Wine logo surface */
@ -1096,18 +1140,8 @@ struct IWineD3DDeviceImpl
/* Textures for when no other textures are mapped */
UINT dummyTextureName[MAX_TEXTURES];
/* Debug stream management */
BOOL debug;
/* Device state management */
HRESULT state;
BOOL d3d_initialized;
/* A flag to check for proper BeginScene / EndScene call pairs */
BOOL inScene;
/* process vertex shaders using software or hardware */
BOOL softwareVertexProcessing;
/* DirectDraw stuff */
DWORD ddraw_width, ddraw_height;
@ -1119,13 +1153,10 @@ struct IWineD3DDeviceImpl
/* With register combiners we can skip junk texture stages */
DWORD texUnitMap[MAX_COMBINED_SAMPLERS];
DWORD rev_tex_unit_map[MAX_COMBINED_SAMPLERS];
BOOL fixed_function_usage_map[MAX_TEXTURES];
/* Stream source management */
WineDirect3DVertexStridedData strided_streams;
const WineDirect3DVertexStridedData *up_strided;
BOOL useDrawStridedSlow;
BOOL instancedDraw;
/* Context management */
WineD3DContext **contexts; /* Dynamic array containing pointers to context structures */
@ -1142,7 +1173,7 @@ struct IWineD3DDeviceImpl
struct WineD3DRectPatch *currentPatch;
};
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl, IWineD3DDevice_DirtyConst_Vtbl;
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count,
CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,
@ -1210,6 +1241,8 @@ HRESULT resource_get_parent(IWineD3DResource *iface, IUnknown **parent);
DWORD resource_get_priority(IWineD3DResource *iface);
HRESULT resource_get_private_data(IWineD3DResource *iface, REFGUID guid,
void *data, DWORD *data_size);
HRESULT resource_init(struct IWineD3DResourceClass *resource, WINED3DRESOURCETYPE resource_type,
IWineD3DDeviceImpl *device, UINT size, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent);
WINED3DRESOURCETYPE resource_get_type(IWineD3DResource *iface);
DWORD resource_set_priority(IWineD3DResource *iface, DWORD new_priority);
HRESULT resource_set_private_data(IWineD3DResource *iface, REFGUID guid,
@ -1349,6 +1382,7 @@ WINED3DTEXTUREFILTERTYPE basetexture_get_autogen_filter_type(IWineD3DBaseTexture
BOOL basetexture_get_dirty(IWineD3DBaseTexture *iface);
DWORD basetexture_get_level_count(IWineD3DBaseTexture *iface);
DWORD basetexture_get_lod(IWineD3DBaseTexture *iface);
void basetexture_init(struct IWineD3DBaseTextureClass *texture, UINT levels, DWORD usage);
HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE filter_type);
BOOL basetexture_set_dirty(IWineD3DBaseTexture *iface, BOOL dirty);
DWORD basetexture_set_lod(IWineD3DBaseTexture *iface, DWORD new_lod);
@ -1424,6 +1458,8 @@ typedef struct IWineD3DVolumeImpl
extern const IWineD3DVolumeVtbl IWineD3DVolume_Vtbl;
void volume_add_dirty_box(IWineD3DVolume *iface, const WINED3DBOX *dirty_box);
/*****************************************************************************
* IWineD3DVolumeTexture implementation structure (extends IWineD3DBaseTextureImpl)
*/
@ -1681,6 +1717,7 @@ typedef enum {
CONVERT_Q8W8V8U8,
CONVERT_V16U16,
CONVERT_A4L4,
CONVERT_G16R16,
} CONVERT_TYPES;
HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode);
@ -1690,11 +1727,6 @@ BOOL palette9_changed(IWineD3DSurfaceImpl *This);
/*****************************************************************************
* IWineD3DVertexDeclaration implementation structure
*/
typedef struct attrib_declaration {
DWORD usage;
DWORD idx;
} attrib_declaration;
#define MAX_ATTRIBS 16
typedef struct IWineD3DVertexDeclarationImpl {
@ -1713,10 +1745,6 @@ typedef struct IWineD3DVertexDeclarationImpl {
UINT num_streams;
BOOL position_transformed;
BOOL half_float_conv_needed;
/* Ordered array of declaration types that need swizzling in a vshader */
attrib_declaration swizzled_attribs[MAX_ATTRIBS];
UINT num_swizzled_attribs;
} IWineD3DVertexDeclarationImpl;
extern const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl;
@ -1729,36 +1757,30 @@ extern const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl;
/* Note: Very long winded but gl Lists are not flexible enough */
/* to resolve everything we need, so doing it manually for now */
typedef struct SAVEDSTATES {
BOOL indices;
BOOL material;
BOOL fvf;
BOOL streamSource[MAX_STREAMS];
BOOL streamFreq[MAX_STREAMS];
BOOL textures[MAX_COMBINED_SAMPLERS];
BOOL transform[HIGHEST_TRANSFORMSTATE + 1];
BOOL viewport;
BOOL renderState[WINEHIGHEST_RENDER_STATE + 1];
BOOL textureState[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
BOOL samplerState[MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1];
BOOL clipplane[MAX_CLIPPLANES];
BOOL vertexDecl;
BOOL pixelShader;
WORD pixelShaderConstantsB;
WORD pixelShaderConstantsI;
BOOL *pixelShaderConstantsF;
BOOL vertexShader;
WORD vertexShaderConstantsB;
WORD vertexShaderConstantsI;
BOOL *vertexShaderConstantsF;
BOOL scissorRect;
DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1];
WORD streamSource; /* MAX_STREAMS, 16 */
WORD streamFreq; /* MAX_STREAMS, 16 */
DWORD renderState[(WINEHIGHEST_RENDER_STATE >> 5) + 1];
DWORD textureState[MAX_TEXTURES]; /* WINED3D_HIGHEST_TEXTURE_STATE + 1, 18 */
WORD samplerState[MAX_COMBINED_SAMPLERS]; /* WINED3D_HIGHEST_SAMPLER_STATE + 1, 14 */
DWORD textures; /* MAX_COMBINED_SAMPLERS, 20 */
DWORD clipplane; /* WINED3DMAXUSERCLIPPLANES, 32 */
WORD pixelShaderConstantsB; /* MAX_CONST_B, 16 */
WORD pixelShaderConstantsI; /* MAX_CONST_I, 16 */
BOOL *pixelShaderConstantsF;
WORD vertexShaderConstantsB; /* MAX_CONST_B, 16 */
WORD vertexShaderConstantsI; /* MAX_CONST_I, 16 */
BOOL *vertexShaderConstantsF;
BYTE indices : 1;
BYTE material : 1;
BYTE viewport : 1;
BYTE vertexDecl : 1;
BYTE pixelShader : 1;
BYTE vertexShader : 1;
BYTE scissorRect : 1;
BYTE padding : 1;
} SAVEDSTATES;
typedef struct {
struct list entry;
DWORD count;
DWORD idx[13];
} constants_entry;
struct StageState {
DWORD stage;
DWORD state;
@ -1777,11 +1799,7 @@ struct IWineD3DStateBlockImpl
/* Array indicating whether things have been set or changed */
SAVEDSTATES changed;
struct list set_vconstantsF;
struct list set_pconstantsF;
/* Drawing - Vertex Shader or FVF related */
DWORD fvf;
/* Vertex Shader Declaration */
IWineD3DVertexDeclaration *vertexDecl;
@ -1837,7 +1855,6 @@ struct IWineD3DStateBlockImpl
/* Texture */
IWineD3DBaseTexture *textures[MAX_COMBINED_SAMPLERS];
int textureDimensions[MAX_COMBINED_SAMPLERS];
/* Texture State Stage */
DWORD textureState[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
@ -1865,7 +1882,7 @@ struct IWineD3DStateBlockImpl
unsigned int num_contained_ps_consts_b;
DWORD *contained_ps_consts_f;
unsigned int num_contained_ps_consts_f;
struct StageState contained_tss_states[MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE)];
struct StageState contained_tss_states[MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)];
unsigned int num_contained_tss_states;
struct StageState contained_sampler_states[MAX_COMBINED_SAMPLERS * WINED3D_HIGHEST_SAMPLER_STATE];
unsigned int num_contained_sampler_states;
@ -2019,7 +2036,12 @@ void texture_activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock
void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
void surface_add_dirty_rect(IWineD3DSurface *iface, const RECT *dirty_rect);
void surface_force_reload(IWineD3DSurface *iface);
GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchain);
void surface_load_ds_location(IWineD3DSurface *iface, DWORD location);
@ -2034,6 +2056,7 @@ BOOL getDepthStencilBits(WINED3DFORMAT fmt, short *depthSize, short *stencilSize
/* Math utils */
void multiply_matrix(WINED3DMATRIX *dest, const WINED3DMATRIX *src1, const WINED3DMATRIX *src2);
unsigned int count_bits(unsigned int mask);
UINT wined3d_log2i(UINT32 x);
/*****************************************************************************
* To enable calling of inherited functions, requires prototypes
@ -2069,7 +2092,7 @@ typedef struct local_constant {
} local_constant;
typedef struct shader_reg_maps {
DWORD shader_version;
char texcoord[MAX_REG_TEXCRD]; /* pixel < 3.0 */
char temporary[MAX_REG_TEMP]; /* pixel, vertex */
char address[MAX_REG_ADDR]; /* vertex */
@ -2110,7 +2133,6 @@ typedef enum COMPARISON_TYPE {
typedef struct SHADER_OPCODE {
unsigned int opcode;
const char* name;
const char* glname;
char dst_token;
CONST UINT num_params;
enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
@ -2172,10 +2194,6 @@ extern BOOL vshader_get_input(
BYTE usage_req, BYTE usage_idx_req,
unsigned int* regnum);
extern BOOL vshader_input_is_color(
IWineD3DVertexShader* iface,
unsigned int regnum);
extern HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object);
/* GLSL helper functions */
@ -2187,7 +2205,6 @@ extern void shader_glsl_add_instruction_modifiers(const SHADER_OPCODE_ARG *arg);
typedef struct IWineD3DBaseShaderClass
{
LONG ref;
DWORD hex_version;
SHADER_LIMITS limits;
SHADER_PARSE_STATE parse_state;
CONST SHADER_OPCODE *shader_ins;
@ -2196,6 +2213,7 @@ typedef struct IWineD3DBaseShaderClass
BOOL is_compiled;
UINT cur_loop_depth, cur_loop_regno;
BOOL load_local_constsF;
BOOL uses_bool_consts, uses_int_consts;
/* Type of shader backend */
int shader_mode;
@ -2228,25 +2246,18 @@ typedef struct IWineD3DBaseShaderImpl {
IWineD3DBaseShaderClass baseShader;
} IWineD3DBaseShaderImpl;
HRESULT WINAPI IWineD3DBaseShaderImpl_QueryInterface(IWineD3DBaseShader *iface, REFIID riid, LPVOID *ppobj);
ULONG WINAPI IWineD3DBaseShaderImpl_AddRef(IWineD3DBaseShader *iface);
ULONG WINAPI IWineD3DBaseShaderImpl_Release(IWineD3DBaseShader *iface);
extern HRESULT shader_get_registers_used(
IWineD3DBaseShader *iface,
shader_reg_maps* reg_maps,
semantic* semantics_in,
semantic* semantics_out,
CONST DWORD* pToken,
IWineD3DStateBlockImpl *stateBlock);
void shader_buffer_init(struct SHADER_BUFFER *buffer);
void shader_buffer_free(struct SHADER_BUFFER *buffer);
void shader_cleanup(IWineD3DBaseShader *iface);
HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_maps *reg_maps,
struct semantic *semantics_in, struct semantic *semantics_out, const DWORD *byte_code);
void shader_init(struct IWineD3DBaseShaderClass *shader,
IWineD3DDevice *device, const SHADER_OPCODE *instruction_table);
void shader_trace_init(const DWORD *byte_code, const SHADER_OPCODE *opcode_table);
extern void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER *buffer,
const shader_reg_maps *reg_maps, const DWORD *pFunction);
extern void shader_trace_init(
IWineD3DBaseShader *iface,
const DWORD* pFunction);
static inline int shader_get_regtype(const DWORD param) {
return (((param & WINED3DSP_REGTYPE_MASK) >> WINED3DSP_REGTYPE_SHIFT) |
((param & WINED3DSP_REGTYPE_MASK2) >> WINED3DSP_REGTYPE_SHIFT2));
@ -2336,9 +2347,7 @@ typedef struct IWineD3DVertexShaderImpl {
semantic semantics_in [MAX_ATTRIBS];
semantic semantics_out [MAX_REG_OUTPUT];
/* Ordered array of attributes that are swizzled */
attrib_declaration swizzled_attribs [MAX_ATTRIBS];
UINT num_swizzled_attribs;
WORD swizzle_map; /* MAX_ATTRIBS, 16 */
UINT min_rel_offset, max_rel_offset;
UINT rel_offset;
@ -2352,29 +2361,6 @@ HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface);
/*****************************************************************************
* IDirect3DPixelShader implementation structure
*/
enum vertexprocessing_mode {
fixedfunction,
vertexshader,
pretransformed
};
struct stb_const_desc {
char texunit;
UINT const_num;
};
/* Stateblock dependent parameters which have to be hardcoded
* into the shader code
*/
struct ps_compile_args {
struct color_fixup_desc color_fixup[MAX_FRAGMENT_SAMPLERS];
BOOL srgb_correction;
enum vertexprocessing_mode vp_mode;
/* Projected textures(ps 1.0-1.3) */
/* Texture types(2D, Cube, 3D) in ps 1.x */
};
struct ps_compiled_shader {
struct ps_compile_args args;
GLuint prgId;
@ -2473,17 +2459,17 @@ typedef struct {
const StaticPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt,
const WineD3D_GL_Info *gl_info, const struct GlPixelFormatDesc **glDesc);
static inline BOOL use_vs(IWineD3DDeviceImpl *device) {
return (device->vs_selected_mode != SHADER_NONE
&& device->stateBlock->vertexShader
&& ((IWineD3DVertexShaderImpl *)device->stateBlock->vertexShader)->baseShader.function
&& !device->strided_streams.u.s.position_transformed);
static inline BOOL use_vs(IWineD3DStateBlockImpl *stateblock)
{
return (stateblock->vertexShader
&& !stateblock->wineD3DDevice->strided_streams.position_transformed
&& stateblock->wineD3DDevice->vs_selected_mode != SHADER_NONE);
}
static inline BOOL use_ps(IWineD3DDeviceImpl *device) {
return (device->ps_selected_mode != SHADER_NONE
&& device->stateBlock->pixelShader
&& ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->baseShader.function);
static inline BOOL use_ps(IWineD3DStateBlockImpl *stateblock)
{
return (stateblock->pixelShader
&& stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE);
}
void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED3DRECT *src_rect,

View file

@ -74,6 +74,7 @@ cpp_quote("#define WINED3DERR_INVALIDCALL MAKE_WINED3DHRESU
cpp_quote("#define WINED3DERR_DRIVERINVALIDCALL MAKE_WINED3DHRESULT(2157)")
cpp_quote("#define WINED3DERR_WASSTILLDRAWING MAKE_WINED3DHRESULT(540)")
cpp_quote("#define WINEDDERR_NOTAOVERLAYSURFACE MAKE_WINED3DHRESULT(580)")
cpp_quote("#define WINEDDERR_NOTLOCKED MAKE_WINED3DHRESULT(584)")
cpp_quote("#define WINEDDERR_NODC MAKE_WINED3DHRESULT(586)")
cpp_quote("#define WINEDDERR_DCALREADYCREATED MAKE_WINED3DHRESULT(620)")
cpp_quote("#define WINEDDERR_NOTFLIPPABLE MAKE_WINED3DHRESULT(582)")
@ -554,35 +555,24 @@ typedef enum _WINED3DMULTISAMPLE_TYPE
typedef enum _WINED3DTEXTURESTAGESTATETYPE
{
WINED3DTSS_COLOROP = 1,
WINED3DTSS_COLORARG1 = 2,
WINED3DTSS_COLORARG2 = 3,
WINED3DTSS_ALPHAOP = 4,
WINED3DTSS_ALPHAARG1 = 5,
WINED3DTSS_ALPHAARG2 = 6,
WINED3DTSS_BUMPENVMAT00 = 7,
WINED3DTSS_BUMPENVMAT01 = 8,
WINED3DTSS_BUMPENVMAT10 = 9,
WINED3DTSS_BUMPENVMAT11 = 10,
WINED3DTSS_TEXCOORDINDEX = 11,
WINED3DTSS_ADDRESS = 12,
WINED3DTSS_ADDRESSU = 13,
WINED3DTSS_ADDRESSV = 14,
WINED3DTSS_BORDERCOLOR = 15,
WINED3DTSS_MAGFILTER = 16,
WINED3DTSS_MINFILTER = 17,
WINED3DTSS_MIPFILTER = 18,
WINED3DTSS_MIPMAPLODBIAS = 19,
WINED3DTSS_MAXMIPLEVEL = 20,
WINED3DTSS_MAXANISOTROPY = 21,
WINED3DTSS_BUMPENVLSCALE = 22,
WINED3DTSS_BUMPENVLOFFSET = 23,
WINED3DTSS_TEXTURETRANSFORMFLAGS = 24,
WINED3DTSS_ADDRESSW = 25,
WINED3DTSS_COLORARG0 = 26,
WINED3DTSS_ALPHAARG0 = 27,
WINED3DTSS_RESULTARG = 28,
WINED3DTSS_CONSTANT = 32,
WINED3DTSS_COLOROP = 0,
WINED3DTSS_COLORARG1 = 1,
WINED3DTSS_COLORARG2 = 2,
WINED3DTSS_ALPHAOP = 3,
WINED3DTSS_ALPHAARG1 = 4,
WINED3DTSS_ALPHAARG2 = 5,
WINED3DTSS_BUMPENVMAT00 = 6,
WINED3DTSS_BUMPENVMAT01 = 7,
WINED3DTSS_BUMPENVMAT10 = 8,
WINED3DTSS_BUMPENVMAT11 = 9,
WINED3DTSS_TEXCOORDINDEX = 10,
WINED3DTSS_BUMPENVLSCALE = 11,
WINED3DTSS_BUMPENVLOFFSET = 12,
WINED3DTSS_TEXTURETRANSFORMFLAGS = 13,
WINED3DTSS_COLORARG0 = 14,
WINED3DTSS_ALPHAARG0 = 15,
WINED3DTSS_RESULTARG = 16,
WINED3DTSS_CONSTANT = 17,
WINED3DTSS_FORCE_DWORD = 0x7fffffff
} WINED3DTEXTURESTAGESTATETYPE;
const UINT WINED3D_HIGHEST_TEXTURE_STATE = WINED3DTSS_CONSTANT;
@ -889,7 +879,7 @@ const UINT WINED3DCLIPPLANE5 = (1 << 5);
/* FVF (Flexible Vertex Format) codes */
const UINT WINED3DFVF_RESERVED0 = 0x0001;
const UINT WINED3DFVF_POSITION_MASK = 0x000e;
const UINT WINED3DFVF_POSITION_MASK = 0x400e;
const UINT WINED3DFVF_XYZ = 0x0002;
const UINT WINED3DFVF_XYZRHW = 0x0004;
const UINT WINED3DFVF_XYZB1 = 0x0006;
@ -1890,10 +1880,13 @@ typedef struct WineDirect3DVertexStridedData
WineDirect3DStridedData sample;
/* Add fields here */
BOOL position_transformed;
} s;
WineDirect3DStridedData input[16]; /* Indexed by constants in D3DVSDE_REGISTER */
} u;
BOOL position_transformed;
WORD swizzle_map; /* MAX_ATTRIBS, 16 */
WORD use_map; /* MAX_ATTRIBS, 16 */
} WineDirect3DVertexStridedData;
typedef struct _WINED3DVSHADERCAPS2_0
@ -2116,22 +2109,65 @@ interface IWineD3DVolume;
interface IWineD3DSwapChain;
interface IWineD3DDevice;
typedef HRESULT (*D3DCB_CREATESURFACEFN)(IUnknown *pDevice, IUnknown *pSuperior, UINT Width,
UINT Height, WINED3DFORMAT Format, DWORD Usage, WINED3DPOOL Pool, UINT Level, WINED3DCUBEMAP_FACES Face,
IWineD3DSurface **ppSurface, HANDLE *pSharedHandle);
typedef HRESULT (*D3DCB_CREATERENDERTARGETFN)(IUnknown *pDevice, IUnknown *pSuperior, UINT Width,
UINT Height, WINED3DFORMAT Format, WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
BOOL Lockable, IWineD3DSurface **ppSurface, HANDLE *pSharedHandle);
typedef HRESULT (*D3DCB_CREATEDEPTHSTENCILSURFACEFN)(IUnknown *pDevice, IUnknown *pSuperior, UINT Width,
UINT Height, WINED3DFORMAT Format, WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
BOOL Discard, IWineD3DSurface **ppSurface, HANDLE *pSharedHandle);
[
object,
local,
uuid(aeb62dfc-bdcb-4f02-9519-1eeea00c15cd)
]
interface IWineD3DDeviceParent : IUnknown
{
HRESULT CreateSurface(
[in] IUnknown *superior,
[in] UINT width,
[in] UINT height,
[in] WINED3DFORMAT format,
[in] DWORD usage,
[in] WINED3DPOOL pool,
[in] UINT level,
[in] WINED3DCUBEMAP_FACES face,
[out] IWineD3DSurface **surface
);
HRESULT CreateRenderTarget(
[in] IUnknown *superior,
[in] UINT width,
[in] UINT height,
[in] WINED3DFORMAT format,
[in] WINED3DMULTISAMPLE_TYPE multisample_type,
[in] DWORD multisample_quality,
[in] BOOL lockable,
[out] IWineD3DSurface **surface
);
HRESULT CreateDepthStencilSurface(
[in] IUnknown *superior,
[in] UINT width,
[in] UINT height,
[in] WINED3DFORMAT format,
[in] WINED3DMULTISAMPLE_TYPE multisample_type,
[in] DWORD multisample_quality,
[in] BOOL discard,
[out] IWineD3DSurface **surface
);
HRESULT CreateVolume(
[in] IUnknown *superior,
[in] UINT width,
[in] UINT height,
[in] UINT depth,
[in] WINED3DFORMAT format,
[in] WINED3DPOOL pool,
[in] DWORD usage,
[out] IWineD3DVolume **volume
);
HRESULT CreateSwapChain(
[in, out] WINED3DPRESENT_PARAMETERS *present_parameters,
[out] IWineD3DSwapChain **swapchain
);
}
typedef ULONG (*D3DCB_DESTROYSURFACEFN)(IWineD3DSurface *pSurface);
typedef HRESULT (*D3DCB_CREATEVOLUMEFN)(IUnknown *pDevice, IUnknown *pSuperior, UINT Width,
UINT Height, UINT Depth, WINED3DFORMAT Format, WINED3DPOOL Pool, DWORD Usage,
IWineD3DVolume **ppVolume, HANDLE *pSharedHandle);
typedef ULONG (*D3DCB_DESTROYVOLUMEFN)(IWineD3DVolume *pVolume);
typedef HRESULT (*D3DCB_CREATESWAPCHAIN)(IUnknown *pDevice, WINED3DPRESENT_PARAMETERS *pPresentationParameters,
IWineD3DSwapChain **pSwapChain);
typedef ULONG (*D3DCB_DESTROYSWAPCHAINFN)(IWineD3DSwapChain *pSwapChain);
typedef HRESULT (*D3DCB_ENUMRESOURCES)(IWineD3DResource *resource, void *pData);
@ -2228,8 +2264,9 @@ interface IWineD3D : IWineD3DBase
[in] WINED3DDEVTYPE device_type,
[in] HWND focus_window,
[in] DWORD behaviour_flags,
[out] IWineD3DDevice **device,
[in] IUnknown *parent
[in] IUnknown *parent,
[in] IWineD3DDeviceParent *device_parent,
[out] IWineD3DDevice **device
);
}
@ -2460,9 +2497,6 @@ interface IWineD3DSurface : IWineD3DResource
HRESULT GetClipper(
[out] IWineD3DClipper **clipper
);
HRESULT AddDirtyRect(
[in] const RECT *dirty_rect
);
HRESULT LoadTexture(
[in] BOOL srgb_mode
);
@ -2519,11 +2553,6 @@ interface IWineD3DVolume : IWineD3DResource
);
HRESULT UnlockBox(
);
HRESULT AddDirtyBox(
[in] const WINED3DBOX *dirty_box
);
HRESULT CleanDirtyBox(
);
HRESULT LoadTexture(
[in] int gl_level,
[in] BOOL srgb_mode
@ -2825,8 +2854,6 @@ interface IWineD3DVertexShader : IWineD3DBaseShader
]
interface IWineD3DPixelShader : IWineD3DBaseShader
{
HRESULT UpdateSamplers(
);
HRESULT GetDevice(
[out] IWineD3DDevice **device
);
@ -2892,8 +2919,7 @@ interface IWineD3DDevice : IWineD3DBase
[in] WINED3DPOOL pool,
[out] IWineD3DTexture **texture,
[in] HANDLE *shared_handle,
[in] IUnknown *parent,
[in] D3DCB_CREATESURFACEFN create_surface_callback
[in] IUnknown *parent
);
HRESULT CreateVolumeTexture(
[in] UINT width,
@ -2905,8 +2931,7 @@ interface IWineD3DDevice : IWineD3DBase
[in] WINED3DPOOL pool,
[out] IWineD3DVolumeTexture **texture,
[in] HANDLE *shared_handle,
[in] IUnknown *parent,
[in] D3DCB_CREATEVOLUMEFN create_volume_callback
[in] IUnknown *parent
);
HRESULT CreateVolume(
[in] UINT width,
@ -2927,8 +2952,7 @@ interface IWineD3DDevice : IWineD3DBase
[in] WINED3DPOOL pool,
[out] IWineD3DCubeTexture **texture,
[in] HANDLE *shared_handle,
[in] IUnknown *parent,
[in] D3DCB_CREATESURFACEFN create_surface_callback
[in] IUnknown *parent
);
HRESULT CreateQuery(
[in] WINED3DQUERYTYPE type,
@ -2939,8 +2963,6 @@ interface IWineD3DDevice : IWineD3DBase
[in] WINED3DPRESENT_PARAMETERS *present_parameters,
[out] IWineD3DSwapChain **swapchain,
[in] IUnknown *parent,
[in] D3DCB_CREATERENDERTARGETFN create_render_target_callback,
[in] D3DCB_CREATEDEPTHSTENCILSURFACEFN create_depth_stencil_callback,
[in] WINED3DSURFTYPE surface_type
);
HRESULT CreateVertexDeclaration(
@ -2972,12 +2994,10 @@ interface IWineD3DDevice : IWineD3DBase
[in] IUnknown *parent
);
HRESULT Init3D(
[in] WINED3DPRESENT_PARAMETERS *present_parameters,
[in] D3DCB_CREATESWAPCHAIN create_swapchain_callback
[in] WINED3DPRESENT_PARAMETERS *present_parameters
);
HRESULT InitGDI(
[in] WINED3DPRESENT_PARAMETERS *present_parameters,
[in] D3DCB_CREATESWAPCHAIN create_swapchain_callback
[in] WINED3DPRESENT_PARAMETERS *present_parameters
);
HRESULT Uninit3D(
[in] D3DCB_DESTROYSURFACEFN destroy_surface_callback,
@ -3072,12 +3092,6 @@ interface IWineD3DDevice : IWineD3DBase
HRESULT GetDepthStencilSurface(
[out] IWineD3DSurface **depth_stencil
);
HRESULT SetFVF(
[in] DWORD fvf
);
HRESULT GetFVF(
[out] DWORD *fvf
);
void SetGammaRamp(
[in] UINT swapchain_idx,
[in] DWORD flags,