From: Kamil Hornicek Date: Sun, 18 Jan 2009 21:09:22 +0000 (+0000) Subject: - sync wined3d with wine HEAD X-Git-Tag: ReactOS-0.3.8~237 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=f1fd1b0ce1c6f8884f6029b3c3024f63108a96be - sync wined3d with wine HEAD svn path=/trunk/; revision=38914 --- diff --git a/reactos/dll/directx/wine/wined3d/arb_program_shader.c b/reactos/dll/directx/wine/wined3d/arb_program_shader.c index 9d5125042f3..7ff3cd4467b 100644 --- a/reactos/dll/directx/wine/wined3d/arb_program_shader.c +++ b/reactos/dll/directx/wine/wined3d/arb_program_shader.c @@ -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"); - /* 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)) { + 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); + /* 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) diff --git a/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c index 90ca192881b..c01ec1aee21 100644 --- a/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c +++ b/reactos/dll/directx/wine/wined3d/ati_fragment_shader.c @@ -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 }, }; diff --git a/reactos/dll/directx/wine/wined3d/baseshader.c b/reactos/dll/directx/wine/wined3d/baseshader.c index c0b149f8288..a270b0c49cb 100644 --- a/reactos/dll/directx/wine/wined3d/baseshader.c +++ b/reactos/dll/directx/wine/wined3d/baseshader.c @@ -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); + while (WINED3DPS_END() != *pToken) + { + /* Skip version token */ + if (shader_is_version_token(*pToken)) + { + ++pToken; + continue; + } - /* If a generator function is set for current shader target, use it */ - } else if (hw_fct != NULL) { + /* Skip comment tokens */ + if (shader_is_comment(*pToken)) + { + pToken += (*pToken & WINED3DSI_COMMENTSIZE_MASK) >> WINED3DSI_COMMENTSIZE_SHIFT; + ++pToken; + continue; + } - hw_arg.opcode = curOpcode; + /* Read opcode */ + hw_arg.opcode_token = *pToken++; + curOpcode = shader_get_opcode(opcode_table, shader_version, hw_arg.opcode_token); - /* Destination token */ - if (curOpcode->dst_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; + } - DWORD param, addr_token = 0; - pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token); - hw_arg.dst = param; - hw_arg.dst_addr = addr_token; - } + /* 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; + } - /* Predication token */ - if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) - hw_arg.predicate = *pToken++; + /* Select handler */ + hw_fct = handler_table[curOpcode->handler_idx]; - /* Other source tokens */ - for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); i++) { + /* 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; + } - DWORD param, addr_token = 0; - pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token); - hw_arg.src[i] = param; - hw_arg.src_addr[i] = addr_token; - } + hw_arg.opcode = curOpcode; - /* Call appropriate function for output target */ - hw_fct(&hw_arg); + /* Destination token */ + if (curOpcode->dst_token) + { + DWORD param, addr_token = 0; + pToken += shader_get_param(pToken, shader_version, ¶m, &addr_token); + hw_arg.dst = param; + hw_arg.dst_addr = addr_token; + } - /* Add color correction if needed */ - shader_color_correction(This, device, &hw_arg); + /* Predication token */ + if (hw_arg.opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) hw_arg.predicate = *pToken++; - /* 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); + /* 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, ¶m, &addr_token); + hw_arg.src[i] = param; + hw_arg.src_addr[i] = addr_token; + } - /* Unhandled opcode */ - } else { + /* Call appropriate function for output target */ + hw_fct(&hw_arg); - FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name); - pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token); - } - } - /* TODO: What about result.depth? */ + /* 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, ¶m, &addr_token); + tokens_read = shader_get_param(pToken, shader_version, ¶m, &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, ¶m, &addr_token); + tokens_read = shader_get_param(pToken, shader_version, ¶m, &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; -} diff --git a/reactos/dll/directx/wine/wined3d/basetexture.c b/reactos/dll/directx/wine/wined3d/basetexture.c index 158650e2142..f6189b6a1df 100644 --- a/reactos/dll/directx/wine/wined3d/basetexture.c +++ b/reactos/dll/directx/wine/wined3d/basetexture.c @@ -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; diff --git a/reactos/dll/directx/wine/wined3d/context.c b/reactos/dll/directx/wine/wined3d/context.c index 05afe5d4d26..da3053a70dc 100644 --- a/reactos/dll/directx/wine/wined3d/context.c +++ b/reactos/dll/directx/wine/wined3d/context.c @@ -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"); + 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"); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);"); + 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"); - if (sampler != -1) { - if (sampler < MAX_TEXTURES) { - Context_MarkStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP), StateTable); - } - Context_MarkStateDirty(context, STATE_SAMPLER(sampler), StateTable); + 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"); } + 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; +} diff --git a/reactos/dll/directx/wine/wined3d/cubetexture.c b/reactos/dll/directx/wine/wined3d/cubetexture.c index 90b122128aa..c7de212b778 100644 --- a/reactos/dll/directx/wine/wined3d/cubetexture.c +++ b/reactos/dll/directx/wine/wined3d/cubetexture.c @@ -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); } diff --git a/reactos/dll/directx/wine/wined3d/device.c b/reactos/dll/directx/wine/wined3d/device.c index 836ad3bee4c..d4a57c9eec3 100644 --- a/reactos/dll/directx/wine/wined3d/device.c +++ b/reactos/dll/directx/wine/wined3d/device.c @@ -54,76 +54,6 @@ const WINED3DLIGHT WINED3D_default_light = { /* static function declarations */ static void IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource); -/* helper macros */ -#define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;} - -#define D3DCREATEOBJECTINSTANCE(object, type) { \ - object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \ - D3DMEMCHECK(object, pp##type); \ - object->lpVtbl = &IWineD3D##type##_Vtbl; \ - object->wineD3DDevice = This; \ - object->parent = parent; \ - object->ref = 1; \ - *pp##type = (IWineD3D##type *) object; \ -} - -#define D3DCREATESHADEROBJECTINSTANCE(object, type) { \ - object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \ - D3DMEMCHECK(object, pp##type); \ - object->lpVtbl = &IWineD3D##type##_Vtbl; \ - object->parent = parent; \ - object->baseShader.ref = 1; \ - object->baseShader.device = (IWineD3DDevice*) This; \ - list_init(&object->baseShader.linked_programs); \ - *pp##type = (IWineD3D##type *) object; \ -} - -#define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \ - object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \ - D3DMEMCHECK(object, pp##type); \ - object->lpVtbl = &IWineD3D##type##_Vtbl; \ - object->resource.wineD3DDevice = This; \ - object->resource.parent = parent; \ - object->resource.resourceType = d3dtype; \ - object->resource.ref = 1; \ - object->resource.pool = Pool; \ - object->resource.format = Format; \ - object->resource.usage = Usage; \ - object->resource.size = _size; \ - object->resource.priority = 0; \ - list_init(&object->resource.privateData); \ - /* Check that we have enough video ram left */ \ - if (Pool == WINED3DPOOL_DEFAULT) { \ - if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \ - WARN("Out of 'bogus' video memory\n"); \ - HeapFree(GetProcessHeap(), 0, object); \ - *pp##type = NULL; \ - return WINED3DERR_OUTOFVIDEOMEMORY; \ - } \ - WineD3DAdapterChangeGLRam(This, _size); \ - } \ - object->resource.heapMemory = (0 == _size ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size + RESOURCE_ALIGNMENT)); \ - if (object->resource.heapMemory == NULL && _size != 0) { \ - FIXME("Out of memory!\n"); \ - HeapFree(GetProcessHeap(), 0, object); \ - *pp##type = NULL; \ - return WINED3DERR_OUTOFVIDEOMEMORY; \ - } \ - object->resource.allocatedMemory = (BYTE *)(((ULONG_PTR) object->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1)); \ - *pp##type = (IWineD3D##type *) object; \ - IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\ - TRACE("(%p) : Created resource %p\n", This, object); \ -} - -#define D3DINITIALIZEBASETEXTURE(_basetexture) { \ - _basetexture.levels = Levels; \ - _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \ - _basetexture.LOD = 0; \ - _basetexture.dirty = TRUE; \ - _basetexture.is_srgb = FALSE; \ - _basetexture.srgb_mode_change_count = 0; \ -} - /********************************************************** * Global variable / Constants follow **********************************************************/ @@ -164,6 +94,13 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) { TRACE("(%p) : Releasing from %d\n", This, refCount + 1); if (!refCount) { + UINT i; + + for (i = 0; i < sizeof(This->multistate_funcs)/sizeof(This->multistate_funcs[0]); ++i) { + HeapFree(GetProcessHeap(), 0, This->multistate_funcs[i]); + This->multistate_funcs[i] = NULL; + } + /* TODO: Clean up all the surfaces and textures! */ /* NOTE: You must release the parent if the object was created via a callback ** ***************************/ @@ -203,6 +140,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac IWineD3DVertexBufferImpl *object; WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */ int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion; + HRESULT hr; BOOL conv; if(Size == 0) { @@ -218,7 +156,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac return WINED3DERR_INVALIDCALL; } - D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size) + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppVertexBuffer = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DVertexBuffer_Vtbl; + hr = resource_init(&object->resource, WINED3DRTYPE_VERTEXBUFFER, This, Size, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppVertexBuffer = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); TRACE("(%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object); *ppVertexBuffer = (IWineD3DVertexBuffer *)object; @@ -310,10 +268,32 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface HANDLE *sharedHandle, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DIndexBufferImpl *object; + HRESULT hr; + TRACE("(%p) Creating index buffer\n", This); /* Allocate the storage for the device */ - D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length) + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppIndexBuffer = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DIndexBuffer_Vtbl; + hr = resource_init(&object->resource, WINED3DRTYPE_INDEXBUFFER, This, Length, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppIndexBuffer = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) { CreateIndexBufferVBO(This, object); @@ -333,24 +313,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, int i, j; HRESULT temp_result; - D3DCREATEOBJECTINSTANCE(object, StateBlock) - object->blockType = Type; + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if(!object) + { + ERR("Out of memory\n"); + *ppStateBlock = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DStateBlock_Vtbl; + object->wineD3DDevice = This; + object->parent = parent; + object->ref = 1; + object->blockType = Type; + + *ppStateBlock = (IWineD3DStateBlock *)object; for(i = 0; i < LIGHTMAP_SIZE; i++) { list_init(&object->lightMap[i]); } + temp_result = allocate_shader_constants(object); + if (FAILED(temp_result)) + { + HeapFree(GetProcessHeap(), 0, object); + return temp_result; + } + /* Special case - Used during initialization to produce a placeholder stateblock so other functions called can update a state block */ - if (Type == WINED3DSBT_INIT) { + if (Type == WINED3DSBT_INIT || Type == WINED3DSBT_RECORDED) + { /* Don't bother increasing the reference count otherwise a device will never be freed due to circular dependencies */ return WINED3D_OK; } - - temp_result = allocate_shader_constants(object); - if (WINED3D_OK != temp_result) - return temp_result; /* Otherwise, might as well set the whole state block to the appropriate values */ if (This->stateBlock != NULL) @@ -413,7 +410,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, } object->num_contained_ps_consts_b = MAX_CONST_B; for(i = 0; i < MAX_TEXTURES; i++) { - for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) { + for (j = 0; j <= WINED3D_HIGHEST_TEXTURE_STATE; ++j) + { object->contained_tss_states[object->num_contained_tss_states].stage = i; object->contained_tss_states[object->num_contained_tss_states].state = j; object->num_contained_tss_states++; @@ -467,23 +465,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, object->num_contained_ps_consts_i = MAX_CONST_I; for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) { - object->changed.renderState[SavedPixelStates_R[i]] = TRUE; - object->contained_render_states[i] = SavedPixelStates_R[i]; + DWORD rs = SavedPixelStates_R[i]; + object->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f); + object->contained_render_states[i] = rs; } object->num_contained_render_states = NUM_SAVEDPIXELSTATES_R; for (j = 0; j < MAX_TEXTURES; j++) { for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) { - object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE; + DWORD state = SavedPixelStates_T[i]; + object->changed.textureState[j] |= 1 << state; object->contained_tss_states[object->num_contained_tss_states].stage = j; - object->contained_tss_states[object->num_contained_tss_states].state = SavedPixelStates_T[i]; + object->contained_tss_states[object->num_contained_tss_states].state = state; object->num_contained_tss_states++; } } for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++) { for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) { - object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE; + DWORD state = SavedPixelStates_S[i]; + object->changed.samplerState[j] |= 1 << state; object->contained_sampler_states[object->num_contained_sampler_states].stage = j; - object->contained_sampler_states[object->num_contained_sampler_states].state = SavedPixelStates_S[i]; + object->contained_sampler_states[object->num_contained_sampler_states].state = state; object->num_contained_sampler_states++; } } @@ -524,23 +525,26 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, } object->num_contained_vs_consts_i = MAX_CONST_I; for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) { - object->changed.renderState[SavedVertexStates_R[i]] = TRUE; - object->contained_render_states[i] = SavedVertexStates_R[i]; + DWORD rs = SavedVertexStates_R[i]; + object->changed.renderState[rs >> 5] |= 1 << (rs & 0x1f); + object->contained_render_states[i] = rs; } object->num_contained_render_states = NUM_SAVEDVERTEXSTATES_R; for (j = 0; j < MAX_TEXTURES; j++) { for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) { - object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE; + DWORD state = SavedVertexStates_T[i]; + object->changed.textureState[j] |= 1 << state; object->contained_tss_states[object->num_contained_tss_states].stage = j; - object->contained_tss_states[object->num_contained_tss_states].state = SavedVertexStates_T[i]; + object->contained_tss_states[object->num_contained_tss_states].state = state; object->num_contained_tss_states++; } } for (j = 0 ; j < MAX_COMBINED_SAMPLERS; j++){ for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) { - object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE; + DWORD state = SavedVertexStates_S[i]; + object->changed.samplerState[j] |= 1 << state; object->contained_sampler_states[object->num_contained_sampler_states].stage = j; - object->contained_sampler_states[object->num_contained_sampler_states].state = SavedVertexStates_S[i]; + object->contained_sampler_states[object->num_contained_sampler_states].state = state; object->num_contained_sampler_states++; } } @@ -572,17 +576,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, return WINED3D_OK; } -/* ************************************ -MSDN: -[in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware. - -Discard - [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. - -If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface. - -******************************** */ - static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */ @@ -590,29 +583,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U const struct GlPixelFormatDesc *glDesc; const StaticPixelFormatDesc *tableEntry = getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); UINT mul_4w, mul_4h; - TRACE("(%p) Create surface\n",This); - - /** FIXME: Check ranges on the inputs are valid - * MSDN - * MultisampleQuality - * [in] Quality level. The valid range is between zero and one less than the level - * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. - * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality - * values of paired render targets, depth stencil surfaces, and the MultiSample type - * must all match. - *******************************/ - + HRESULT hr; - /** - * TODO: Discard MSDN - * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. - * - * If this flag is set, the contents of the depth stencil buffer will be - * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface - * with a different depth surface. - * - *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG. - ***************************/ + TRACE("(%p) Create surface\n",This); if(MultisampleQuality > 0) { FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality); @@ -648,7 +621,54 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U if(glDesc->heightscale != 0.0) Size *= glDesc->heightscale; /** Create and initialise the surface resource **/ - D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size) + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppSurface = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + /* Look at the implementation and set the correct Vtable */ + switch(Impl) + { + case SURFACE_OPENGL: + /* Check if a 3D adapter is available when creating gl surfaces */ + if (!This->adapter) + { + ERR("OpenGL surfaces are not available without opengl\n"); + HeapFree(GetProcessHeap(), 0, object); + return WINED3DERR_NOTAVAILABLE; + } + object->lpVtbl = &IWineD3DSurface_Vtbl; + break; + + case SURFACE_GDI: + object->lpVtbl = &IWineGDISurface_Vtbl; + break; + + default: + /* To be sure to catch this */ + ERR("Unknown requested surface implementation %d!\n", Impl); + HeapFree(GetProcessHeap(), 0, object); + return WINED3DERR_INVALIDCALL; + } + + hr = resource_init(&object->resource, WINED3DRTYPE_SURFACE, This, Size, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppSurface = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); + + *ppSurface = (IWineD3DSurface *)object; + /* "Standalone" surface */ IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL); @@ -711,46 +731,30 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U } /* mark the texture as dirty so that it gets loaded first time around*/ - IWineD3DSurface_AddDirtyRect(*ppSurface, NULL); + surface_add_dirty_rect(*ppSurface, NULL); TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size); - /* Look at the implementation and set the correct Vtable */ - switch(Impl) { - case SURFACE_OPENGL: - /* Check if a 3D adapter is available when creating gl surfaces */ - if(!This->adapter) { - ERR("OpenGL surfaces are not available without opengl\n"); - HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory); - HeapFree(GetProcessHeap(), 0, object); - return WINED3DERR_NOTAVAILABLE; - } - break; - - case SURFACE_GDI: - object->lpVtbl = &IWineGDISurface_Vtbl; - break; - - default: - /* To be sure to catch this */ - ERR("Unknown requested surface implementation %d!\n", Impl); - IWineD3DSurface_Release((IWineD3DSurface *) object); - return WINED3DERR_INVALIDCALL; - } - list_init(&object->renderbuffers); /* Call the private setup routine */ - return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object ); + hr = IWineD3DSurface_PrivateSetup((IWineD3DSurface *)object); + if (FAILED(hr)) + { + ERR("Private setup failed, returning %#x\n", hr); + IWineD3DSurface_Release(*ppSurface); + *ppSurface = NULL; + return hr; + } + return hr; } -static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels, - DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, - IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent, - D3DCB_CREATESURFACEFN D3DCB_CreateSurface) { - +static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, + UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, + IWineD3DTexture **ppTexture, HANDLE *pSharedHandle, IUnknown *parent) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DTextureImpl *object; unsigned int i; @@ -773,41 +777,89 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U return WINED3DERR_INVALIDCALL; } - D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0); - D3DINITIALIZEBASETEXTURE(object->baseTexture); - object->width = Width; - object->height = Height; - - if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) { - object->baseTexture.minMipLookup = minMipLookup; - object->baseTexture.magLookup = magLookup; - } else { - object->baseTexture.minMipLookup = minMipLookup_noFilter; - object->baseTexture.magLookup = magLookup_noFilter; - } - - /** Non-power2 support **/ - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { + /* Non-power2 support */ + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) + { pow2Width = Width; pow2Height = Height; - } else { + } + else + { /* Find the nearest pow2 match */ pow2Width = pow2Height = 1; while (pow2Width < Width) pow2Width <<= 1; while (pow2Height < Height) pow2Height <<= 1; - if(pow2Width != Width || pow2Height != Height) { - if(Levels > 1) { + if (pow2Width != Width || pow2Height != Height) + { + if (Levels > 1) + { WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support\n"); - HeapFree(GetProcessHeap(), 0, object); - *ppTexture = NULL; return WINED3DERR_INVALIDCALL; - } else { - Levels = 1; } + Levels = 1; } } + /* Calculate levels for mip mapping */ + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + + if (Levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + + Levels = 1; + } + else if (!Levels) + { + Levels = wined3d_log2i(max(Width, Height)) + 1; + TRACE("Calculated levels = %d\n", Levels); + } + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppTexture = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DTexture_Vtbl; + hr = resource_init(&object->resource, WINED3DRTYPE_TEXTURE, This, 0, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppTexture = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); + + *ppTexture = (IWineD3DTexture *)object; + + basetexture_init(&object->baseTexture, Levels, Usage); + object->width = Width; + object->height = Height; + + if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING) { + object->baseTexture.minMipLookup = minMipLookup; + object->baseTexture.magLookup = magLookup; + } else { + object->baseTexture.minMipLookup = minMipLookup_noFilter; + object->baseTexture.magLookup = magLookup_noFilter; + } + /** FIXME: add support for real non-power-two if it's provided by the video card **/ /* Precalculated scaling for 'faked' non power of two texture coords. Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE @@ -843,37 +895,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U } TRACE(" xf(%f) yf(%f)\n", object->baseTexture.pow2Matrix[0], object->baseTexture.pow2Matrix[5]); - /* Calculate levels for mip mapping */ - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { - if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - if(Levels > 1) { - WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - object->baseTexture.levels = 1; - } else if (Levels == 0) { - TRACE("calculating levels %d\n", object->baseTexture.levels); - object->baseTexture.levels++; - tmpW = Width; - tmpH = Height; - while (tmpW > 1 || tmpH > 1) { - tmpW = max(1, tmpW >> 1); - tmpH = max(1, tmpH >> 1); - object->baseTexture.levels++; - } - TRACE("Calculated levels = %d\n", object->baseTexture.levels); - } - /* Generate all the surfaces */ tmpW = Width; tmpH = Height; for (i = 0; i < object->baseTexture.levels; i++) { /* use the callback to create the texture surface */ - hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i],NULL); + hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpH, Format, + Usage, Pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &object->surfaces[i]); if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) { FIXME("Failed to create surface %p\n", object); /* clean up */ @@ -898,13 +927,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U } static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface, - UINT Width, UINT Height, UINT Depth, - UINT Levels, DWORD Usage, - WINED3DFORMAT Format, WINED3DPOOL Pool, - IWineD3DVolumeTexture **ppVolumeTexture, - HANDLE *pSharedHandle, IUnknown *parent, - D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) { - + UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, + IWineD3DVolumeTexture **ppVolumeTexture, HANDLE *pSharedHandle, IUnknown *parent) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVolumeTextureImpl *object; unsigned int i; @@ -912,6 +937,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa UINT tmpH; UINT tmpD; const struct GlPixelFormatDesc *glDesc; + HRESULT hr; getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); @@ -926,8 +952,52 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa return WINED3DERR_INVALIDCALL; } - D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0); - D3DINITIALIZEBASETEXTURE(object->baseTexture); + /* Calculate levels for mip mapping */ + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + + if (Levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + + Levels = 1; + } + else if (!Levels) + { + Levels = wined3d_log2i(max(max(Width, Height), Depth)) + 1; + TRACE("Calculated levels = %d\n", Levels); + } + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppVolumeTexture = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DVolumeTexture_Vtbl; + hr = resource_init(&object->resource, WINED3DRTYPE_VOLUMETEXTURE, This, 0, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppVolumeTexture = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); + + basetexture_init(&object->baseTexture, Levels, Usage); TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool)); @@ -946,31 +1016,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa object->baseTexture.magLookup = magLookup_noFilter; } - /* Calculate levels for mip mapping */ - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { - if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - if(Levels > 1) { - WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); - return WINED3DERR_INVALIDCALL; - } - object->baseTexture.levels = 1; - } else if (Levels == 0) { - object->baseTexture.levels++; - tmpW = Width; - tmpH = Height; - tmpD = Depth; - while (tmpW > 1 || tmpH > 1 || tmpD > 1) { - tmpW = max(1, tmpW >> 1); - tmpH = max(1, tmpH >> 1); - tmpD = max(1, tmpD >> 1); - object->baseTexture.levels++; - } - TRACE("Calculated levels = %d\n", object->baseTexture.levels); - } - /* Generate all the surfaces */ tmpW = Width; tmpH = Height; @@ -980,9 +1025,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa { HRESULT hr; /* Create the volume */ - hr = D3DCB_CreateVolume(This->parent, parent, tmpW, tmpH, tmpD, Format, Pool, Usage, - &object->volumes[i], pSharedHandle); - + hr = IWineD3DDeviceParent_CreateVolume(This->device_parent, parent, + tmpW, tmpH, tmpD, Format, Pool, Usage, &object->volumes[i]); if(FAILED(hr)) { ERR("Creating a volume for the volume texture failed(%08x)\n", hr); IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object); @@ -1015,13 +1059,37 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/ const StaticPixelFormatDesc *formatDesc = getFormatDescEntry(Format, NULL, NULL); + HRESULT hr; if(!GL_SUPPORT(EXT_TEXTURE3D)) { WARN("(%p) : Volume cannot be created - no volume texture support\n", This); return WINED3DERR_INVALIDCALL; } - D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth)) + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppVolume = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DVolume_Vtbl; + hr = resource_init(&object->resource, WINED3DRTYPE_VOLUME, This, + Width * Height * Depth * formatDesc->bpp, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppVolume = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); + + *ppVolume = (IWineD3DVolume *)object; TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool)); @@ -1037,16 +1105,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, memset(&object->lockedBox, 0, sizeof(WINED3DBOX)); object->dirty = TRUE; - return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL); -} + volume_add_dirty_box((IWineD3DVolume *)object, NULL); -static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength, - UINT Levels, DWORD Usage, - WINED3DFORMAT Format, WINED3DPOOL Pool, - IWineD3DCubeTexture **ppCubeTexture, - HANDLE *pSharedHandle, IUnknown *parent, - D3DCB_CREATESURFACEFN D3DCB_CreateSurface) { + return WINED3D_OK; +} +static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, + UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, + IWineD3DCubeTexture **ppCubeTexture, HANDLE *pSharedHandle, IUnknown *parent) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/ unsigned int i, j; @@ -1068,8 +1135,52 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface return WINED3DERR_INVALIDCALL; } - D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0); - D3DINITIALIZEBASETEXTURE(object->baseTexture); + /* Calculate levels for mip mapping */ + if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) + { + if (!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + + if (Levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; + } + + Levels = 1; + } + else if (!Levels) + { + Levels = wined3d_log2i(EdgeLength) + 1; + TRACE("Calculated levels = %d\n", Levels); + } + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppCubeTexture = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DCubeTexture_Vtbl; + hr = resource_init(&object->resource, WINED3DRTYPE_CUBETEXTURE, This, 0, Usage, Format, Pool, parent); + if (FAILED(hr)) + { + WARN("Failed to initialize resource, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, object); + *ppCubeTexture = NULL; + return hr; + } + + TRACE("(%p) : Created resource %p\n", This, object); + + IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object); + + basetexture_init(&object->baseTexture, Levels, Usage); TRACE("(%p) Create Cube Texture\n", This); @@ -1099,33 +1210,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface object->baseTexture.magLookup = magLookup_noFilter; } - /* Calculate levels for mip mapping */ - if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) { - if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) { - WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n"); - HeapFree(GetProcessHeap(), 0, object); - *ppCubeTexture = NULL; - - return WINED3DERR_INVALIDCALL; - } - if(Levels > 1) { - WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n"); - HeapFree(GetProcessHeap(), 0, object); - *ppCubeTexture = NULL; - - return WINED3DERR_INVALIDCALL; - } - object->baseTexture.levels = 1; - } else if (Levels == 0) { - object->baseTexture.levels++; - tmpW = EdgeLength; - while (tmpW > 1) { - tmpW = max(1, tmpW >> 1); - object->baseTexture.levels++; - } - TRACE("Calculated levels = %d\n", object->baseTexture.levels); - } - /* Generate all the surfaces */ tmpW = EdgeLength; for (i = 0; i < object->baseTexture.levels; i++) { @@ -1141,24 +1225,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB }; - hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool, - i /* Level */, j, &object->surfaces[j][i],pSharedHandle); - - if(hr!= WINED3D_OK) { - /* clean up */ - unsigned int k; - unsigned int l; - for (l = 0; l < j; l++) { - IWineD3DSurface_Release(object->surfaces[l][i]); - } - for (k = 0; k < i; k++) { - for (l = 0; l < 6; l++) { - IWineD3DSurface_Release(object->surfaces[l][k]); - } - } - + hr = IWineD3DDeviceParent_CreateSurface(This->device_parent, parent, tmpW, tmpW, + Format, Usage, Pool, i /* Level */, j, &object->surfaces[j][i]); + if (FAILED(hr)) + { FIXME("(%p) Failed to create surface\n",object); - HeapFree(GetProcessHeap(),0,object); + IWineD3DCubeTexture_Release((IWineD3DCubeTexture *)object); *ppCubeTexture = NULL; return hr; } @@ -1225,10 +1297,23 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE return hr; } - D3DCREATEOBJECTINSTANCE(object, Query) - object->lpVtbl = vtable; - object->type = Type; - object->state = QUERY_CREATED; + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if(!object) + { + ERR("Out of memory\n"); + *ppQuery = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = vtable; + object->type = Type; + object->state = QUERY_CREATED; + object->wineD3DDevice = This; + object->parent = parent; + object->ref = 1; + + *ppQuery = (IWineD3DQuery *)object; + /* allocated the 'extended' data based on the type of query requested */ switch(Type){ case WINED3DQUERYTYPE_OCCLUSION: @@ -1392,10 +1477,9 @@ static void IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) } /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */ -static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, - WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain, - IUnknown* parent, D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget, - D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil, WINED3DSURFTYPE surface_type) +static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface, + WINED3DPRESENT_PARAMETERS *pPresentationParameters, IWineD3DSwapChain **ppSwapChain, + IUnknown *parent, WINED3DSURFTYPE surface_type) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; @@ -1422,7 +1506,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n"); } - D3DCREATEOBJECTINSTANCE(object, SwapChain) + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if(!object) + { + ERR("Out of memory\n"); + *ppSwapChain = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + switch(surface_type) { case SURFACE_GDI: object->lpVtbl = &IWineGDISwapChain_Vtbl; @@ -1432,8 +1523,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, break; case SURFACE_UNKNOWN: FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain\n"); + HeapFree(GetProcessHeap(), 0, object); return WINED3DERR_INVALIDCALL; } + object->wineD3DDevice = This; + object->parent = parent; + object->ref = 1; + + *ppSwapChain = (IWineD3DSwapChain *)object; /********************* * Lookup the window Handle and the relating X window handle @@ -1465,11 +1562,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, object->orig_fmt = Mode.Format; formatDesc = getFormatDescEntry(Mode.Format, NULL, NULL); - /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero, - * then the corresponding dimension of the client area of the hDeviceWindow - * (or the focus window, if hDeviceWindow is NULL) is taken. - **********************/ - if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) || (pPresentationParameters->BackBufferHeight == 0) || @@ -1497,16 +1589,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, object->presentParms = *pPresentationParameters; TRACE("calling rendertarget CB\n"); - hr = D3DCB_CreateRenderTarget(This->parent, - parent, - object->presentParms.BackBufferWidth, - object->presentParms.BackBufferHeight, - object->presentParms.BackBufferFormat, - object->presentParms.MultiSampleType, - object->presentParms.MultiSampleQuality, - TRUE /* Lockable */, - &object->frontBuffer, - NULL /* pShared (always null)*/); + hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent, + object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight, + object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType, + object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->frontBuffer); if (SUCCEEDED(hr)) { IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object); if(surface_type == SURFACE_OPENGL) { @@ -1585,16 +1671,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, for(i = 0; i < object->presentParms.BackBufferCount; i++) { TRACE("calling rendertarget CB\n"); - hr = D3DCB_CreateRenderTarget(This->parent, - parent, - object->presentParms.BackBufferWidth, - object->presentParms.BackBufferHeight, - object->presentParms.BackBufferFormat, - object->presentParms.MultiSampleType, - object->presentParms.MultiSampleQuality, - TRUE /* Lockable */, - &object->backBuffer[i], - NULL /* pShared (always null)*/); + hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent, + object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight, + object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType, + object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->backBuffer[i]); if(SUCCEEDED(hr)) { IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object); } else { @@ -1624,16 +1704,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice* iface, if (pPresentationParameters->EnableAutoDepthStencil && surface_type == SURFACE_OPENGL) { TRACE("Creating depth stencil buffer\n"); if (This->auto_depth_stencil_buffer == NULL ) { - hr = D3DCB_CreateDepthStencil(This->parent, - parent, - object->presentParms.BackBufferWidth, - object->presentParms.BackBufferHeight, - object->presentParms.AutoDepthStencilFormat, - object->presentParms.MultiSampleType, - object->presentParms.MultiSampleQuality, - FALSE /* FIXME: Discard */, - &This->auto_depth_stencil_buffer, - NULL /* pShared (always null)*/ ); + hr = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent, parent, + object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight, + object->presentParms.AutoDepthStencilFormat, object->presentParms.MultiSampleType, + object->presentParms.MultiSampleQuality, FALSE /* FIXME: Discard */, + &This->auto_depth_stencil_buffer); if (SUCCEEDED(hr)) { IWineD3DSurface_SetContainer(This->auto_depth_stencil_buffer, 0); } else { @@ -1730,7 +1805,20 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration); - D3DCREATEOBJECTINSTANCE(object, VertexDeclaration) + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if(!object) + { + ERR("Out of memory\n"); + *ppVertexDeclaration = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DVertexDeclaration_Vtbl; + object->wineD3DDevice = This; + object->parent = parent; + object->ref = 1; + + *ppVertexDeclaration = (IWineD3DVertexDeclaration *)object; hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count); if(FAILED(hr)) { @@ -1783,6 +1871,10 @@ static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl *This, /* For the elements[idx].Type = WINED3DDECLTYPE_FLOAT4; elements[idx].Usage = WINED3DDECLUSAGE_POSITIONT; } + else if ((fvf & WINED3DFVF_XYZW) == WINED3DFVF_XYZW) { + elements[idx].Type = WINED3DDECLTYPE_FLOAT4; + elements[idx].Usage = WINED3DDECLUSAGE_POSITION; + } else { elements[idx].Type = WINED3DDECLTYPE_FLOAT3; elements[idx].Usage = WINED3DDECLUSAGE_POSITION; @@ -1896,25 +1988,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *ifac IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */ HRESULT hr = WINED3D_OK; - D3DCREATESHADEROBJECTINSTANCE(object, VertexShader) - object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins; - TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader); + if (!pFunction) return WINED3DERR_INVALIDCALL; + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppVertexShader = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DVertexShader_Vtbl; + object->parent = parent; + shader_init(&object->baseShader, iface, IWineD3DVertexShaderImpl_shader_ins); + list_add_head(&This->shaders, &object->baseShader.shader_list_entry); + *ppVertexShader = (IWineD3DVertexShader *)object; + + TRACE("(%p) : Created vertex shader %p\n", This, *ppVertexShader); if (vertex_declaration) { IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration); } hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction); - - if (WINED3D_OK != hr) { - FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface); + if (FAILED(hr)) + { + WARN("(%p) : Failed to set function, returning %#x\n", iface, hr); IWineD3DVertexShader_Release(*ppVertexShader); - return WINED3DERR_INVALIDCALL; + *ppVertexShader = NULL; + return hr; } - list_add_head(&This->shaders, &object->baseShader.shader_list_entry); - return WINED3D_OK; + return hr; } static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) { @@ -1922,14 +2028,31 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */ HRESULT hr = WINED3D_OK; - D3DCREATESHADEROBJECTINSTANCE(object, PixelShader) - object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins; + if (!pFunction) return WINED3DERR_INVALIDCALL; + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if (!object) + { + ERR("Out of memory\n"); + *ppPixelShader = NULL; + return WINED3DERR_OUTOFVIDEOMEMORY; + } + + object->lpVtbl = &IWineD3DPixelShader_Vtbl; + object->parent = parent; + shader_init(&object->baseShader, iface, IWineD3DPixelShaderImpl_shader_ins); + list_add_head(&This->shaders, &object->baseShader.shader_list_entry); + *ppPixelShader = (IWineD3DPixelShader *)object; + + TRACE("(%p) : Created pixel shader %p\n", This, *ppPixelShader); + hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction); - if (WINED3D_OK == hr) { - TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader); - list_add_head(&This->shaders, &object->baseShader.shader_list_entry); - } else { - WARN("(%p) : Failed to create pixel shader\n", This); + if (FAILED(hr)) + { + WARN("(%p) : Failed to set function, returning %#x\n", iface, hr); + IWineD3DPixelShader_Release(*ppPixelShader); + *ppPixelShader = NULL; + return hr; } return hr; @@ -1956,7 +2079,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DW object->parent = Parent; object->wineD3DDevice = This; object->palNumEntries = IWineD3DPaletteImpl_Size(Flags); - object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion)); if(!object->hpal) { @@ -2050,12 +2172,8 @@ static void create_dummy_textures(IWineD3DDeviceImpl *This) { GLubyte white = 255; /* Make appropriate texture active */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); - checkGLcall("glActiveTextureARB"); - } else if (i > 0) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); - } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); + checkGLcall("glActiveTextureARB"); /* Generate an opengl texture name */ glGenTextures(1, &This->dummyTextureName[i]); @@ -2064,7 +2182,6 @@ static void create_dummy_textures(IWineD3DDeviceImpl *This) { /* Generate a dummy 2d texture (not using 1d because they cause many * DRI drivers fall back to sw) */ - This->stateBlock->textureDimensions[i] = GL_TEXTURE_2D; glBindTexture(GL_TEXTURE_2D, This->dummyTextureName[i]); checkGLcall("glBindTexture"); @@ -2080,14 +2197,17 @@ static void create_dummy_textures(IWineD3DDeviceImpl *This) { LEAVE_GL(); } -static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) { +static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, + WINED3DPRESENT_PARAMETERS *pPresentationParameters) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DSwapChainImpl *swapchain = NULL; HRESULT hr; DWORD state; unsigned int i; - TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateSwapChain); + TRACE("(%p)->(%p)\n", This, pPresentationParameters); + if(This->d3d_initialized) return WINED3DERR_INVALIDCALL; if(!This->adapter->opengl) return WINED3DERR_INVALIDCALL; @@ -2107,11 +2227,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR This->updateStateBlock = This->stateBlock; IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock); - hr = allocate_shader_constants(This->updateStateBlock); - if (WINED3D_OK != hr) { - goto err_out; - } - This->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers)); This->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers)); @@ -2147,8 +2262,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR /* Setup the implicit swapchain */ TRACE("Creating implicit swapchain\n"); - hr=D3DCB_CreateSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain); - if (FAILED(hr) || !swapchain) { + hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent, + pPresentationParameters, (IWineD3DSwapChain **)&swapchain); + if (FAILED(hr)) + { WARN("Failed to create implicit swapchain\n"); goto err_out; } @@ -2205,17 +2322,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR ENTER_GL(); - { /* Set a default viewport */ - WINED3DVIEWPORT vp; - vp.X = 0; - vp.Y = 0; - vp.Width = pPresentationParameters->BackBufferWidth; - vp.Height = pPresentationParameters->BackBufferHeight; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp); - } - /* Initialize the current view state */ This->view_ident = 1; This->contexts[0]->last_was_rhw = 0; @@ -2286,15 +2392,19 @@ err_out: return hr; } -static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATESWAPCHAIN D3DCB_CreateSwapChain) { +static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, + WINED3DPRESENT_PARAMETERS *pPresentationParameters) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DSwapChainImpl *swapchain = NULL; HRESULT hr; /* Setup the implicit swapchain */ TRACE("Creating implicit swapchain\n"); - hr=D3DCB_CreateSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain); - if (FAILED(hr) || !swapchain) { + hr = IWineD3DDeviceParent_CreateSwapChain(This->device_parent, + pPresentationParameters, (IWineD3DSwapChain **)&swapchain); + if (FAILED(hr)) + { WARN("Failed to create implicit swapchain\n"); goto err_out; } @@ -2560,36 +2670,6 @@ static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *ifa return (This->adapter->TextureRam - This->adapter->UsedTextureRam); } - - -/***** - * Get / Set FVF - *****/ -static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - - /* Update the current state block */ - This->updateStateBlock->changed.fvf = TRUE; - - if(This->updateStateBlock->fvf == fvf) { - TRACE("Application is setting the old fvf over, nothing to do\n"); - return WINED3D_OK; - } - - This->updateStateBlock->fvf = fvf; - TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL); - return WINED3D_OK; -} - - -static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf); - *pfvf = This->stateBlock->fvf; - return WINED3D_OK; -} - /***** * Get / Set Stream Source *****/ @@ -2608,7 +2688,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, oldSrc = This->updateStateBlock->streamSource[StreamNumber]; TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride); - This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE; + This->updateStateBlock->changed.streamSource |= 1 << StreamNumber; if(oldSrc == pStreamData && This->updateStateBlock->streamStride[StreamNumber] == Stride && @@ -2631,10 +2711,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, return WINED3D_OK; } - /* Need to do a getParent and pass the references up */ - /* MSDN says ..... When an application no longer holds a reference to this interface, the interface will automatically be freed. - which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source - so for now, just count internally */ if (pStreamData != NULL) { IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData; InterlockedIncrement(&vbImpl->bindCount); @@ -2696,7 +2772,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *ifa TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider); This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA ); - This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE; + This->updateStateBlock->changed.streamFreq |= 1 << StreamNumber; This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF; if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq || @@ -2730,7 +2806,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, W /* Handle recording of state blocks */ if (This->isRecordingState) { TRACE("Recording... not performing anything\n"); - This->updateStateBlock->changed.transform[d3dts] = TRUE; + This->updateStateBlock->changed.transform[d3dts >> 5] |= 1 << (d3dts & 0x1f); This->updateStateBlock->transforms[d3dts] = *lpmatrix; return WINED3D_OK; } @@ -2787,7 +2863,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State)); - if (State < HIGHEST_TRANSFORMSTATE) + if (State <= HIGHEST_TRANSFORMSTATE) { mat = &This->updateStateBlock->transforms[State]; } else { @@ -2933,9 +3009,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I if (rho < 0.0001) rho = 0.0001f; object->exponent = -0.3/log(cos(rho/2)); } - if (object->exponent > 128.0) { - object->exponent = 128.0; - } + if (object->exponent > 128.0) { + object->exponent = 128.0; + } object->cutoff = pLight->Phi*90/M_PI; /* FIXME: Range */ @@ -3049,7 +3125,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D * * TODO: Test how this affects rendering */ - FIXME("Too many concurrently active lights\n"); + WARN("Too many concurrently active lights\n"); return WINED3D_OK; } @@ -3099,7 +3175,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWO return WINED3DERR_INVALIDCALL; } - This->updateStateBlock->changed.clipplane[Index] = TRUE; + This->updateStateBlock->changed.clipplane |= 1 << Index; if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] && This->updateStateBlock->clipplane[Index][1] == pPlane[1] && @@ -3323,7 +3399,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, W TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value); - This->updateStateBlock->changed.renderState[State] = TRUE; + This->updateStateBlock->changed.renderState[State >> 5] |= 1 << (State & 0x1f); This->updateStateBlock->renderState[State] = Value; /* Handle recording of state blocks */ @@ -3386,7 +3462,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, oldValue = This->stateBlock->samplerState[Sampler][Type]; This->updateStateBlock->samplerState[Sampler][Type] = Value; - This->updateStateBlock->changed.samplerState[Sampler][Type] = Value; + This->updateStateBlock->changed.samplerState[Sampler] |= 1 << Type; /* Handle recording of state blocks */ if (This->isRecordingState) { @@ -3548,7 +3624,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB( This->updateStateBlock->changed.vertexShaderConstantsB |= (1 << i); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); return WINED3D_OK; } @@ -3596,7 +3672,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI( This->updateStateBlock->changed.vertexShaderConstantsI |= (1 << i); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); return WINED3D_OK; } @@ -3607,64 +3683,24 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI( int *dstData, UINT count) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - int cnt = min(count, MAX_CONST_I - start); - - TRACE("(iface %p, dstData %p, start %d, count %d)\n", - iface, dstData, start, count); - - if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0) - return WINED3DERR_INVALIDCALL; - - memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4); - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF( - IWineD3DDevice *iface, - UINT start, - CONST float *srcData, - UINT count) { - - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - UINT i; - - TRACE("(iface %p, srcData %p, start %d, count %d)\n", - iface, srcData, start, count); - - /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */ - if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF)) - return WINED3DERR_INVALIDCALL; - - memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4); - if(TRACE_ON(d3d)) { - for (i = 0; i < count; i++) - TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, - srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); - } + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + int cnt = min(count, MAX_CONST_I - start); - for (i = start; i < count + start; ++i) { - if (!This->updateStateBlock->changed.vertexShaderConstantsF[i]) { - constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry); - if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) { - ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry)); - list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry); - } - ptr->idx[ptr->count++] = i; - This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE; - } - } + TRACE("(iface %p, dstData %p, start %d, count %d)\n", + iface, dstData, start, count); - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0) + return WINED3DERR_INVALIDCALL; + memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4); return WINED3D_OK; } -static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst( -IWineD3DDevice *iface, -UINT start, -CONST float *srcData, -UINT count) { +static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF( + IWineD3DDevice *iface, + UINT start, + CONST float *srcData, + UINT count) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; UINT i; @@ -3680,17 +3716,17 @@ UINT count) { if(TRACE_ON(d3d)) { for (i = 0; i < count; i++) TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, - srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); + srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); } - /* 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); + if (!This->isRecordingState) + { + This->shader_backend->shader_update_float_vertex_constants(iface, start, count); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + memset(This->updateStateBlock->changed.vertexShaderConstantsF + start, 1, + sizeof(*This->updateStateBlock->changed.vertexShaderConstantsF) * count); return WINED3D_OK; } @@ -3716,7 +3752,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF( static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) { DWORD i; - for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) { + for(i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i) + { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i)); } } @@ -3739,6 +3776,7 @@ static void device_map_stage(IWineD3DDeviceImpl *This, int stage, int unit) { static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) { int i; + This->fixed_function_usage_map = 0; for (i = 0; i < MAX_TEXTURES; ++i) { WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP]; WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP]; @@ -3751,10 +3789,6 @@ static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) { if (color_op == WINED3DTOP_DISABLE) { /* Not used, and disable higher stages */ - while (i < MAX_TEXTURES) { - This->fixed_function_usage_map[i] = FALSE; - ++i; - } break; } @@ -3764,26 +3798,27 @@ static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) { || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2) || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1) || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) { - This->fixed_function_usage_map[i] = TRUE; - } else { - This->fixed_function_usage_map[i] = FALSE; + This->fixed_function_usage_map |= (1 << i); } if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) { - This->fixed_function_usage_map[i+1] = TRUE; + This->fixed_function_usage_map |= (1 << (i + 1)); } } } static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) { int i, tex; + WORD ffu_map; device_update_fixed_function_usage_map(This); + ffu_map = This->fixed_function_usage_map; if (This->max_ffp_textures == This->max_ffp_texture_stages || - This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) { - for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) { - if (!This->fixed_function_usage_map[i]) continue; + This->stateBlock->lowest_disabled_stage <= This->max_ffp_textures) { + for (i = 0; ffu_map; ffu_map >>= 1, ++i) + { + if (!(ffu_map & 1)) continue; if (This->texUnitMap[i] != i) { device_map_stage(This, i, i); @@ -3796,8 +3831,9 @@ static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) { /* Now work out the mapping */ tex = 0; - for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) { - if (!This->fixed_function_usage_map[i]) continue; + for (i = 0; ffu_map; ffu_map >>= 1, ++i) + { + if (!(ffu_map & 1)) continue; if (This->texUnitMap[i] != tex) { device_map_stage(This, i, tex); @@ -3840,7 +3876,7 @@ static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, const DWORD *pshad if (!pshader_sampler_tokens) { /* No pixel shader, check fixed function */ - return current_mapping >= MAX_TEXTURES || !This->fixed_function_usage_map[current_mapping]; + return current_mapping >= MAX_TEXTURES || !(This->fixed_function_usage_map & (1 << current_mapping)); } /* Pixel shader, check the shader's sampler map */ @@ -3861,8 +3897,8 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) { if (ps) { IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader; - /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */ - IWineD3DPixelShader_UpdateSamplers((IWineD3DPixelShader *)pshader); + /* Note that we only care if a sampler is sampled or not, not the sampler's specific type. + * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */ pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers; } @@ -3890,8 +3926,8 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) { } void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) { - BOOL vs = use_vs(This); - BOOL ps = use_ps(This); + BOOL vs = use_vs(This->stateBlock); + BOOL ps = use_ps(This->stateBlock); /* * Rules are: * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but @@ -3981,7 +4017,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB( This->updateStateBlock->changed.pixelShaderConstantsB |= (1 << i); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); + if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); return WINED3D_OK; } @@ -4029,7 +4065,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI( This->updateStateBlock->changed.pixelShaderConstantsI |= (1 << i); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); + if (!This->isRecordingState) IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); return WINED3D_OK; } @@ -4076,54 +4112,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF( srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); } - for (i = start; i < count + start; ++i) { - if (!This->updateStateBlock->changed.pixelShaderConstantsF[i]) { - constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry); - if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) { - ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry)); - list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry); - } - ptr->idx[ptr->count++] = i; - This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE; - } - } - - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); - - return WINED3D_OK; -} - -static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst( - IWineD3DDevice *iface, - UINT start, - CONST float *srcData, - UINT count) { - - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - UINT i; - - TRACE("(iface %p, srcData %p, start %d, count %d)\n", - iface, srcData, start, count); - - /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */ - if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF)) - return WINED3DERR_INVALIDCALL; - - memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4); - if(TRACE_ON(d3d)) { - for (i = 0; i < count; i++) - TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, - srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); + if (!This->isRecordingState) + { + This->shader_backend->shader_update_float_pixel_constants(iface, start, count); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); } - /* 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); - - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); + memset(This->updateStateBlock->changed.pixelShaderConstantsF + start, 1, + sizeof(*This->updateStateBlock->changed.pixelShaderConstantsF) * count); return WINED3D_OK; } @@ -4584,7 +4580,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if return WINED3D_OK; } - This->updateStateBlock->changed.textureState[Stage][Type] = TRUE; + This->updateStateBlock->changed.textureState[Stage] |= 1 << Type; This->updateStateBlock->textureState[Stage][Type] = Value; if (This->isRecordingState) { @@ -4673,20 +4669,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD oldTexture = This->updateStateBlock->textures[Stage]; - if(pTexture != NULL) { - /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; - */ - if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) { - WARN("(%p) Attempt to set scratch texture rejected\n", pTexture); - return WINED3DERR_INVALIDCALL; - } - This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture); + /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */ + if (pTexture && ((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) + { + WARN("(%p) Attempt to set scratch texture rejected\n", pTexture); + return WINED3DERR_INVALIDCALL; } TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages)); TRACE("(%p) : oldtexture(%p)\n", This,oldTexture); - This->updateStateBlock->changed.textures[Stage] = TRUE; + This->updateStateBlock->changed.textures |= 1 << Stage; TRACE("(%p) : setting new texture to %p\n", This, pTexture); This->updateStateBlock->textures[Stage] = pTexture; @@ -4708,8 +4701,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD if (NULL != This->updateStateBlock->textures[Stage]) { IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage]; ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount); + UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions(pTexture); IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]); + + if (!oldTexture || dimensions != IWineD3DBaseTexture_GetTextureDimensions(oldTexture)) + { + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER); + } + if(oldTexture == NULL && Stage < MAX_TEXTURES) { /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound, * so the COLOROP and ALPHAOP have to be dirtified. @@ -4841,42 +4841,22 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, U static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DStateBlockImpl *object; - HRESULT temp_result; - int i; + IWineD3DStateBlock *stateblock; + HRESULT hr; TRACE("(%p)\n", This); - - if (This->isRecordingState) { - return WINED3DERR_INVALIDCALL; - } - - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl)); - if (NULL == object ) { - FIXME("(%p)Error allocating memory for stateblock\n", This); - return E_OUTOFMEMORY; - } - TRACE("(%p) created object %p\n", This, object); - object->wineD3DDevice= This; - /** FIXME: object->parent = parent; **/ - object->parent = NULL; - object->blockType = WINED3DSBT_RECORDED; - object->ref = 1; - object->lpVtbl = &IWineD3DStateBlock_Vtbl; - for(i = 0; i < LIGHTMAP_SIZE; i++) { - list_init(&object->lightMap[i]); - } + if (This->isRecordingState) return WINED3DERR_INVALIDCALL; - temp_result = allocate_shader_constants(object); - if (WINED3D_OK != temp_result) - return temp_result; + hr = IWineD3DDeviceImpl_CreateStateBlock(iface, WINED3DSBT_RECORDED, &stateblock, NULL); + if (FAILED(hr)) return hr; IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock); - This->updateStateBlock = object; + This->updateStateBlock = (IWineD3DStateBlockImpl *)stateblock; This->isRecordingState = TRUE; - TRACE("(%p) recording stateblock %p\n",This , object); + TRACE("(%p) recording stateblock %p\n", This, stateblock); + return WINED3D_OK; } @@ -4886,21 +4866,30 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IW IWineD3DStateBlockImpl *object = This->updateStateBlock; if (!This->isRecordingState) { - FIXME("(%p) not recording! returning error\n", This); + WARN("(%p) not recording! returning error\n", This); *ppStateBlock = NULL; return WINED3DERR_INVALIDCALL; } - for(i = 1; i <= WINEHIGHEST_RENDER_STATE; i++) { - if(object->changed.renderState[i]) { - object->contained_render_states[object->num_contained_render_states] = i; - object->num_contained_render_states++; + for (i = 0; i <= WINEHIGHEST_RENDER_STATE >> 5; ++i) + { + DWORD map = object->changed.renderState[i]; + for (j = 0; map; map >>= 1, ++j) + { + if (!(map & 1)) continue; + + object->contained_render_states[object->num_contained_render_states++] = (i << 5) | j; } } - for(i = 1; i <= HIGHEST_TRANSFORMSTATE; i++) { - if(object->changed.transform[i]) { - object->contained_transform_states[object->num_contained_transform_states] = i; - object->num_contained_transform_states++; + + for (i = 0; i <= HIGHEST_TRANSFORMSTATE >> 5; ++i) + { + DWORD map = object->changed.transform[i]; + for (j = 0; map; map >>= 1, ++j) + { + if (!(map & 1)) continue; + + object->contained_transform_states[object->num_contained_transform_states++] = (i << 5) | j; } } for(i = 0; i < GL_LIMITS(vshader_constantsF); i++) { @@ -4923,6 +4912,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IW object->num_contained_vs_consts_b++; } } + for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) + { + if (object->changed.pixelShaderConstantsF[i]) + { + object->contained_ps_consts_f[object->num_contained_ps_consts_f] = i; + ++object->num_contained_ps_consts_f; + } + } for(i = 0; i < MAX_CONST_I; i++) { if (object->changed.pixelShaderConstantsI & (1 << i)) { @@ -4938,21 +4935,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IW } } for(i = 0; i < MAX_TEXTURES; i++) { - for(j = 1; j <= WINED3D_HIGHEST_TEXTURE_STATE; j++) { - if(object->changed.textureState[i][j]) { - object->contained_tss_states[object->num_contained_tss_states].stage = i; - object->contained_tss_states[object->num_contained_tss_states].state = j; - object->num_contained_tss_states++; - } + DWORD map = object->changed.textureState[i]; + + for(j = 0; map; map >>= 1, ++j) + { + if (!(map & 1)) continue; + + object->contained_tss_states[object->num_contained_tss_states].stage = i; + object->contained_tss_states[object->num_contained_tss_states].state = j; + ++object->num_contained_tss_states; } } for(i = 0; i < MAX_COMBINED_SAMPLERS; i++){ - for (j = 1; j < WINED3D_HIGHEST_SAMPLER_STATE; j++) { - if(object->changed.samplerState[i][j]) { - object->contained_sampler_states[object->num_contained_sampler_states].stage = i; - object->contained_sampler_states[object->num_contained_sampler_states].state = j; - object->num_contained_sampler_states++; - } + DWORD map = object->changed.samplerState[i]; + + for (j = 0; map; map >>= 1, ++j) + { + if (!(map & 1)) continue; + + object->contained_sampler_states[object->num_contained_sampler_states].stage = i; + object->contained_sampler_states[object->num_contained_sampler_states].state = j; + ++object->num_contained_sampler_states; } } @@ -5255,7 +5258,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WI IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); } /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */ - drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */, + drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0/* NumVertices */, StartVertex /* start_idx */, 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */); return WINED3D_OK; } @@ -5277,7 +5280,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice * * without an index buffer set. (The first time at least...) * D3D8 simply dies, but I doubt it can do much harm to return * D3DERR_INVALIDCALL there as well. */ - ERR("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This); + WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This); return WINED3DERR_INVALIDCALL; } @@ -5308,7 +5311,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice * IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); } - drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex, + drawPrimitive(iface, PrimitiveType, primCount, NumVertices, startIndex, idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex); return WINED3D_OK; @@ -5341,8 +5344,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, /* TODO: Only mark dirty if drawing from a different UP address */ IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC); - drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */, - 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */); + drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* NumVertices */, + 0 /* start_idx */, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */); /* MSDN specifies stream zero settings must be set to NULL */ This->stateBlock->streamStride[0] = 0; @@ -5395,7 +5398,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice * IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); - drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex); + drawPrimitive(iface, PrimitiveType, PrimitiveCount, NumVertices, 0 /* start_idx */, idxStride, pIndexData, MinVertexIndex); /* MSDN specifies stream zero settings and index buffer must be set to NULL */ This->stateBlock->streamSource[0] = NULL; @@ -5426,7 +5429,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice *if IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER); This->stateBlock->baseVertexIndex = 0; This->up_strided = DrawPrimStrideData; - drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0); + drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0); This->up_strided = NULL; return WINED3D_OK; } @@ -5448,7 +5451,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDev This->stateBlock->streamIsUP = TRUE; This->stateBlock->baseVertexIndex = 0; This->up_strided = DrawPrimStrideData; - drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* startvertexidx */, 0 /* numindices */, 0 /* startidx */, idxSize, pIndexData, 0 /* minindex */); + drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* numindices */, 0 /* start_idx */, idxSize, pIndexData, 0 /* minindex */); This->up_strided = NULL; return WINED3D_OK; } @@ -5912,12 +5915,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - ENTER_GL(); - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); - checkGLcall("glActiveTextureARB"); - LEAVE_GL(); - } + ENTER_GL(); + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); + checkGLcall("glActiveTextureARB"); + LEAVE_GL(); /* Make sure the surface is loaded and up to date */ IWineD3DSurface_PreLoad(pDestinationSurface); @@ -6787,10 +6788,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i } /* Make sure that a proper texture unit is selected */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); - checkGLcall("glActiveTextureARB"); - } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); + checkGLcall("glActiveTextureARB"); sampler = This->rev_tex_unit_map[0]; if (sampler != -1) { IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(sampler)); @@ -7214,16 +7213,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth || pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight)) { - WINED3DVIEWPORT vp; UINT i; - vp.X = 0; - vp.Y = 0; - vp.Width = pPresentationParameters->BackBufferWidth; - vp.Height = pPresentationParameters->BackBufferHeight; - vp.MinZ = 0; - vp.MaxZ = 1; - if(!pPresentationParameters->Windowed) { DisplayModeChanged = TRUE; } @@ -7237,10 +7228,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE if(This->auto_depth_stencil_buffer) { updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters); } - - - /* Now set the new viewport */ - IWineD3DDevice_SetViewport(iface, &vp); } if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) || @@ -7281,6 +7268,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE This->exStyle = exStyle; } + TRACE("Resetting stateblock\n"); + IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock); + IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock); + + /* Note: No parent needed for initial internal stateblock */ + hr = IWineD3DDevice_CreateStateBlock(iface, WINED3DSBT_INIT, (IWineD3DStateBlock **)&This->stateBlock, NULL); + if (FAILED(hr)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr); + else TRACE("Created stateblock %p\n", This->stateBlock); + This->updateStateBlock = This->stateBlock; + IWineD3DStateBlock_AddRef((IWineD3DStateBlock *)This->updateStateBlock); + hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock); if(FAILED(hr)) { ERR("Resetting the stateblock failed with error 0x%08x\n", hr); @@ -7441,7 +7439,6 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW /* TODO: nothing really? */ break; case WINED3DRTYPE_VERTEXBUFFER: - /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */ { int streamNumber; TRACE("Cleaning up stream pointers\n"); @@ -7467,7 +7464,6 @@ static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IW } break; case WINED3DRTYPE_INDEXBUFFER: - /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/ if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */ if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) { This->updateStateBlock->pIndexData = NULL; @@ -7571,8 +7567,6 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_GetCurrentTexturePalette, IWineD3DDeviceImpl_SetDepthStencilSurface, IWineD3DDeviceImpl_GetDepthStencilSurface, - IWineD3DDeviceImpl_SetFVF, - IWineD3DDeviceImpl_GetFVF, IWineD3DDeviceImpl_SetGammaRamp, IWineD3DDeviceImpl_GetGammaRamp, IWineD3DDeviceImpl_SetIndices, @@ -7660,151 +7654,6 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_EnumResources }; -const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl = -{ - /*** IUnknown methods ***/ - IWineD3DDeviceImpl_QueryInterface, - IWineD3DDeviceImpl_AddRef, - IWineD3DDeviceImpl_Release, - /*** IWineD3DDevice methods ***/ - IWineD3DDeviceImpl_GetParent, - /*** Creation methods**/ - IWineD3DDeviceImpl_CreateVertexBuffer, - IWineD3DDeviceImpl_CreateIndexBuffer, - IWineD3DDeviceImpl_CreateStateBlock, - IWineD3DDeviceImpl_CreateSurface, - IWineD3DDeviceImpl_CreateTexture, - IWineD3DDeviceImpl_CreateVolumeTexture, - IWineD3DDeviceImpl_CreateVolume, - IWineD3DDeviceImpl_CreateCubeTexture, - IWineD3DDeviceImpl_CreateQuery, - IWineD3DDeviceImpl_CreateSwapChain, - IWineD3DDeviceImpl_CreateVertexDeclaration, - IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF, - IWineD3DDeviceImpl_CreateVertexShader, - IWineD3DDeviceImpl_CreatePixelShader, - IWineD3DDeviceImpl_CreatePalette, - /*** Odd functions **/ - IWineD3DDeviceImpl_Init3D, - IWineD3DDeviceImpl_InitGDI, - IWineD3DDeviceImpl_Uninit3D, - IWineD3DDeviceImpl_UninitGDI, - IWineD3DDeviceImpl_SetMultithreaded, - IWineD3DDeviceImpl_EvictManagedResources, - IWineD3DDeviceImpl_GetAvailableTextureMem, - IWineD3DDeviceImpl_GetBackBuffer, - IWineD3DDeviceImpl_GetCreationParameters, - IWineD3DDeviceImpl_GetDeviceCaps, - IWineD3DDeviceImpl_GetDirect3D, - IWineD3DDeviceImpl_GetDisplayMode, - IWineD3DDeviceImpl_SetDisplayMode, - IWineD3DDeviceImpl_GetNumberOfSwapChains, - IWineD3DDeviceImpl_GetRasterStatus, - IWineD3DDeviceImpl_GetSwapChain, - IWineD3DDeviceImpl_Reset, - IWineD3DDeviceImpl_SetDialogBoxMode, - IWineD3DDeviceImpl_SetCursorProperties, - IWineD3DDeviceImpl_SetCursorPosition, - IWineD3DDeviceImpl_ShowCursor, - IWineD3DDeviceImpl_TestCooperativeLevel, - /*** Getters and setters **/ - IWineD3DDeviceImpl_SetClipPlane, - IWineD3DDeviceImpl_GetClipPlane, - IWineD3DDeviceImpl_SetClipStatus, - IWineD3DDeviceImpl_GetClipStatus, - IWineD3DDeviceImpl_SetCurrentTexturePalette, - IWineD3DDeviceImpl_GetCurrentTexturePalette, - IWineD3DDeviceImpl_SetDepthStencilSurface, - IWineD3DDeviceImpl_GetDepthStencilSurface, - IWineD3DDeviceImpl_SetFVF, - IWineD3DDeviceImpl_GetFVF, - IWineD3DDeviceImpl_SetGammaRamp, - IWineD3DDeviceImpl_GetGammaRamp, - IWineD3DDeviceImpl_SetIndices, - IWineD3DDeviceImpl_GetIndices, - IWineD3DDeviceImpl_SetBaseVertexIndex, - IWineD3DDeviceImpl_GetBaseVertexIndex, - IWineD3DDeviceImpl_SetLight, - IWineD3DDeviceImpl_GetLight, - IWineD3DDeviceImpl_SetLightEnable, - IWineD3DDeviceImpl_GetLightEnable, - IWineD3DDeviceImpl_SetMaterial, - IWineD3DDeviceImpl_GetMaterial, - IWineD3DDeviceImpl_SetNPatchMode, - IWineD3DDeviceImpl_GetNPatchMode, - IWineD3DDeviceImpl_SetPaletteEntries, - IWineD3DDeviceImpl_GetPaletteEntries, - IWineD3DDeviceImpl_SetPixelShader, - IWineD3DDeviceImpl_GetPixelShader, - IWineD3DDeviceImpl_SetPixelShaderConstantB, - IWineD3DDeviceImpl_GetPixelShaderConstantB, - IWineD3DDeviceImpl_SetPixelShaderConstantI, - IWineD3DDeviceImpl_GetPixelShaderConstantI, - IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst, - IWineD3DDeviceImpl_GetPixelShaderConstantF, - IWineD3DDeviceImpl_SetRenderState, - IWineD3DDeviceImpl_GetRenderState, - IWineD3DDeviceImpl_SetRenderTarget, - IWineD3DDeviceImpl_GetRenderTarget, - IWineD3DDeviceImpl_SetFrontBackBuffers, - IWineD3DDeviceImpl_SetSamplerState, - IWineD3DDeviceImpl_GetSamplerState, - IWineD3DDeviceImpl_SetScissorRect, - IWineD3DDeviceImpl_GetScissorRect, - IWineD3DDeviceImpl_SetSoftwareVertexProcessing, - IWineD3DDeviceImpl_GetSoftwareVertexProcessing, - IWineD3DDeviceImpl_SetStreamSource, - IWineD3DDeviceImpl_GetStreamSource, - IWineD3DDeviceImpl_SetStreamSourceFreq, - IWineD3DDeviceImpl_GetStreamSourceFreq, - IWineD3DDeviceImpl_SetTexture, - IWineD3DDeviceImpl_GetTexture, - IWineD3DDeviceImpl_SetTextureStageState, - IWineD3DDeviceImpl_GetTextureStageState, - IWineD3DDeviceImpl_SetTransform, - IWineD3DDeviceImpl_GetTransform, - IWineD3DDeviceImpl_SetVertexDeclaration, - IWineD3DDeviceImpl_GetVertexDeclaration, - IWineD3DDeviceImpl_SetVertexShader, - IWineD3DDeviceImpl_GetVertexShader, - IWineD3DDeviceImpl_SetVertexShaderConstantB, - IWineD3DDeviceImpl_GetVertexShaderConstantB, - IWineD3DDeviceImpl_SetVertexShaderConstantI, - IWineD3DDeviceImpl_GetVertexShaderConstantI, - IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst, - IWineD3DDeviceImpl_GetVertexShaderConstantF, - IWineD3DDeviceImpl_SetViewport, - IWineD3DDeviceImpl_GetViewport, - IWineD3DDeviceImpl_MultiplyTransform, - IWineD3DDeviceImpl_ValidateDevice, - IWineD3DDeviceImpl_ProcessVertices, - /*** State block ***/ - IWineD3DDeviceImpl_BeginStateBlock, - IWineD3DDeviceImpl_EndStateBlock, - /*** Scene management ***/ - IWineD3DDeviceImpl_BeginScene, - IWineD3DDeviceImpl_EndScene, - IWineD3DDeviceImpl_Present, - IWineD3DDeviceImpl_Clear, - /*** Drawing ***/ - IWineD3DDeviceImpl_DrawPrimitive, - IWineD3DDeviceImpl_DrawIndexedPrimitive, - IWineD3DDeviceImpl_DrawPrimitiveUP, - IWineD3DDeviceImpl_DrawIndexedPrimitiveUP, - IWineD3DDeviceImpl_DrawPrimitiveStrided, - IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided, - IWineD3DDeviceImpl_DrawRectPatch, - IWineD3DDeviceImpl_DrawTriPatch, - IWineD3DDeviceImpl_DeletePatch, - IWineD3DDeviceImpl_ColorFill, - IWineD3DDeviceImpl_UpdateTexture, - IWineD3DDeviceImpl_UpdateSurface, - IWineD3DDeviceImpl_GetFrontBufferData, - /*** object tracking ***/ - IWineD3DDeviceImpl_ResourceReleased, - IWineD3DDeviceImpl_EnumResources -}; - const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = { WINED3DRS_ALPHABLENDENABLE , WINED3DRS_ALPHAFUNC , @@ -7844,7 +7693,6 @@ const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = { }; const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = { - WINED3DTSS_ADDRESSW , WINED3DTSS_ALPHAARG0 , WINED3DTSS_ALPHAARG1 , WINED3DTSS_ALPHAARG2 , diff --git a/reactos/dll/directx/wine/wined3d/directx.c b/reactos/dll/directx/wine/wined3d/directx.c index 253860fce4e..a78f4e5c74b 100644 --- a/reactos/dll/directx/wine/wined3d/directx.c +++ b/reactos/dll/directx/wine/wined3d/directx.c @@ -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(); diff --git a/reactos/dll/directx/wine/wined3d/drawprim.c b/reactos/dll/directx/wine/wined3d/drawprim.c index 7603103fb43..b78078fd85a 100644 --- a/reactos/dll/directx/wine/wined3d/drawprim.c +++ b/reactos/dll/directx/wine/wined3d/drawprim.c @@ -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 (idx_size) + { + TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, primitive_type, count, min_vertex_idx); + #if 1 - glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, - (const char *)idxData+(idxSize * startIdx)); + glDrawElements(primitive_type, count, + idx_size == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, + (const char *)idx_data + (idx_size * start_idx)); checkGLcall("glDrawElements"); -#else /* using drawRangeElements may be faster */ - - glDrawRangeElements(glPrimitiveType, minIndex, minIndex + numberOfVertices - 1, numberOfVertices, - idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, - (const char *)idxData+(idxSize * startIdx)); +#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); diff --git a/reactos/dll/directx/wine/wined3d/gl_compat.c b/reactos/dll/directx/wine/wined3d/gl_compat.c new file mode 100644 index 00000000000..1fc48cc9204 --- /dev/null +++ b/reactos/dll/directx/wine/wined3d/gl_compat.c @@ -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 +#ifdef HAVE_FLOAT_H +# include +#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 diff --git a/reactos/dll/directx/wine/wined3d/glsl_shader.c b/reactos/dll/directx/wine/wined3d/glsl_shader.c index 4c1d2239a61..8dfb416e206 100644 --- a/reactos/dll/directx/wine/wined3d/glsl_shader.c +++ b/reactos/dll/directx/wine/wined3d/glsl_shader.c @@ -29,6 +29,7 @@ */ #include "config.h" +#include #include #include "wined3d_private.h" @@ -54,11 +55,35 @@ typedef struct { DWORD coord_mask; } glsl_sample_function_t; +enum heap_node_op +{ + HEAP_NODE_TRAVERSE_LEFT, + HEAP_NODE_TRAVERSE_RIGHT, + HEAP_NODE_POP, +}; + +struct constant_entry +{ + unsigned int idx; + unsigned int version; +}; + +struct constant_heap +{ + struct constant_entry *entries; + unsigned int *positions; + unsigned int size; +}; + /* GLSL shader private data */ struct shader_glsl_priv { struct hash_table_t *glsl_program_lookup; - const struct glsl_shader_prog_link *glsl_program; + struct glsl_shader_prog_link *glsl_program; + struct constant_heap vconst_heap; + struct constant_heap pconst_heap; + unsigned char *stack; GLhandleARB depth_blt_program[tex_type_count]; + UINT next_constant_version; }; /* Struct to maintain data about a linked GLSL program */ @@ -79,6 +104,7 @@ struct glsl_shader_prog_link { GLhandleARB vshader; IWineD3DPixelShader *pshader; struct ps_compile_args ps_args; + UINT constant_version; }; typedef struct { @@ -96,19 +122,23 @@ static void print_glsl_info_log(const WineD3D_GL_Info *gl_info, GLhandleARB obj) unsigned int i; BOOL is_spam; - const char *spam[] = { + static const char * const spam[] = + { "Vertex shader was successfully compiled to run on hardware.\n", /* fglrx */ "Fragment shader was successfully compiled to run on hardware.\n", /* fglrx */ "Fragment shader(s) linked, vertex shader(s) linked. \n ", /* fglrx, with \n */ "Fragment shader(s) linked, vertex shader(s) linked.", /* fglrx, no \n */ "Vertex shader(s) linked, no fragment shader(s) defined. \n ", /* fglrx, with \n */ "Vertex shader(s) linked, no fragment shader(s) defined.", /* fglrx, no \n */ - "Fragment shader was successfully compiled to run on hardware.\nWARNING: 0:1: extension 'GL_ARB_draw_buffers' is not supported", + "Fragment shader was successfully compiled to run on hardware.\n" + "WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported", "Fragment shader(s) linked, no vertex shader(s) defined.", /* fglrx, no \n */ "Fragment shader(s) linked, no vertex shader(s) defined. \n ", /* fglrx, with \n */ "WARNING: 0:2: extension 'GL_ARB_draw_buffers' is not supported\n" /* MacOS ati */ }; + if (!TRACE_ON(d3d_shader) && !FIXME_ON(d3d_shader)) return; + GL_EXTCALL(glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength)); @@ -188,106 +218,166 @@ static void shader_glsl_load_vsamplers(const WineD3D_GL_Info *gl_info, IWineD3DS } } -/** - * Loads floating point constants (aka uniforms) into the currently set GLSL program. - * When constant_list == NULL, it will load all the constants. - */ -static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info, - unsigned int max_constants, const float *constants, const GLhandleARB *constant_locations, - const struct list *constant_list) +static inline void walk_constant_heap(const WineD3D_GL_Info *gl_info, const float *constants, + const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) { - const constants_entry *constant; - const local_constant *lconst; - GLhandleARB tmp_loc; - DWORD i, j, k; - const DWORD *idx; - - if (TRACE_ON(d3d_shader)) { - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - tmp_loc = constant_locations[i]; - if (tmp_loc != -1) { - TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i, - constants[i * 4 + 0], constants[i * 4 + 1], - constants[i * 4 + 2], constants[i * 4 + 3]); + int stack_idx = 0; + unsigned int heap_idx = 1; + unsigned int idx; + + if (heap->entries[heap_idx].version <= version) return; + + idx = heap->entries[heap_idx].idx; + if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4])); + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + + while (stack_idx >= 0) + { + /* Note that we fall through to the next case statement. */ + switch(stack[stack_idx]) + { + case HEAP_NODE_TRAVERSE_LEFT: + { + unsigned int left_idx = heap_idx << 1; + if (left_idx < heap->size && heap->entries[left_idx].version > version) + { + heap_idx = left_idx; + idx = heap->entries[heap_idx].idx; + if (constant_locations[idx] != -1) + GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4])); + + stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; } } + + case HEAP_NODE_TRAVERSE_RIGHT: + { + unsigned int right_idx = (heap_idx << 1) + 1; + if (right_idx < heap->size && heap->entries[right_idx].version > version) + { + heap_idx = right_idx; + idx = heap->entries[heap_idx].idx; + if (constant_locations[idx] != -1) + GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4])); + + stack[stack_idx++] = HEAP_NODE_POP; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; + } + } + + case HEAP_NODE_POP: + { + heap_idx >>= 1; + --stack_idx; + break; + } } } + checkGLcall("walk_constant_heap()"); +} - /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ - if(WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1 && - shader_is_pshader_version(This->baseShader.hex_version)) { - float lcl_const[4]; - - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - tmp_loc = constant_locations[i]; - if (tmp_loc != -1) { - /* We found this uniform name in the program - go ahead and send the data */ - k = i * 4; - if(constants[k + 0] < -1.0) lcl_const[0] = -1.0; - else if(constants[k + 0] > 1.0) lcl_const[0] = 1.0; - else lcl_const[0] = constants[k + 0]; - if(constants[k + 1] < -1.0) lcl_const[1] = -1.0; - else if(constants[k + 1] > 1.0) lcl_const[1] = 1.0; - else lcl_const[1] = constants[k + 1]; - if(constants[k + 2] < -1.0) lcl_const[2] = -1.0; - else if(constants[k + 2] > 1.0) lcl_const[2] = 1.0; - else lcl_const[2] = constants[k + 2]; - if(constants[k + 3] < -1.0) lcl_const[3] = -1.0; - else if(constants[k + 3] > 1.0) lcl_const[3] = 1.0; - else lcl_const[3] = constants[k + 3]; - - GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, lcl_const)); +static inline void apply_clamped_constant(const WineD3D_GL_Info *gl_info, GLint location, const GLfloat *data) +{ + GLfloat clamped_constant[4]; + + if (location == -1) return; + + clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0 ? 1.0 : data[0]; + clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0 ? 1.0 : data[1]; + clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0 ? 1.0 : data[2]; + clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0 ? 1.0 : data[3]; + + GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant)); +} + +static inline void walk_constant_heap_clamped(const WineD3D_GL_Info *gl_info, const float *constants, + const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version) +{ + int stack_idx = 0; + unsigned int heap_idx = 1; + unsigned int idx; + + if (heap->entries[heap_idx].version <= version) return; + + idx = heap->entries[heap_idx].idx; + apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]); + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + + while (stack_idx >= 0) + { + /* Note that we fall through to the next case statement. */ + switch(stack[stack_idx]) + { + case HEAP_NODE_TRAVERSE_LEFT: + { + unsigned int left_idx = heap_idx << 1; + if (left_idx < heap->size && heap->entries[left_idx].version > version) + { + heap_idx = left_idx; + idx = heap->entries[heap_idx].idx; + apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]); + + stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; } } - } - } else { - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - tmp_loc = constant_locations[i]; - if (tmp_loc != -1) { - /* We found this uniform name in the program - go ahead and send the data */ - GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, constants + (i * 4))); + + case HEAP_NODE_TRAVERSE_RIGHT: + { + unsigned int right_idx = (heap_idx << 1) + 1; + if (right_idx < heap->size && heap->entries[right_idx].version > version) + { + heap_idx = right_idx; + idx = heap->entries[heap_idx].idx; + apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]); + + stack[stack_idx++] = HEAP_NODE_POP; + stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT; + break; } } + + case HEAP_NODE_POP: + { + heap_idx >>= 1; + --stack_idx; + break; + } } } - checkGLcall("glUniform4fvARB()"); + checkGLcall("walk_constant_heap_clamped()"); +} - if(!This->baseShader.load_local_constsF) { +/* Loads floating point constants (aka uniforms) into the currently set GLSL program. */ +static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info, + const float *constants, const GLhandleARB *constant_locations, const struct constant_heap *heap, + unsigned char *stack, UINT version) +{ + const local_constant *lconst; + + /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */ + if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.reg_maps.shader_version) == 1 + && shader_is_pshader_version(This->baseShader.reg_maps.shader_version)) + walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version); + else + walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version); + + if (!This->baseShader.load_local_constsF) + { TRACE("No need to load local float constants for this shader\n"); return; } - /* Load immediate constants */ - if (TRACE_ON(d3d_shader)) { - LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { - tmp_loc = constant_locations[lconst->idx]; - if (tmp_loc != -1) { - const GLfloat *values = (const GLfloat *)lconst->value; - TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx, - values[0], values[1], values[2], values[3]); - } - } - } /* Immediate constants are clamped to [-1;1] at shader creation time if needed */ - LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { - tmp_loc = constant_locations[lconst->idx]; - if (tmp_loc != -1) { - /* We found this uniform name in the program - go ahead and send the data */ - GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, (const GLfloat *)lconst->value)); - } + LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) + { + GLhandleARB location = constant_locations[lconst->idx]; + /* We found this uniform name in the program - go ahead and send the data */ + if (location != -1) GL_EXTCALL(glUniform4fvARB(location, 1, (const GLfloat *)lconst->value)); } checkGLcall("glUniform4fvARB()"); } @@ -335,7 +425,7 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine GLhandleARB tmp_loc; unsigned int i; char tmp_name[8]; - char is_pshader = shader_is_pshader_version(This->baseShader.hex_version); + char is_pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version); const char* prefix = is_pshader? "PB":"VB"; struct list* ptr; @@ -379,7 +469,11 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine } } - +static void reset_program_constant_version(void *value, void *context) +{ + struct glsl_shader_prog_link *entry = (struct glsl_shader_prog_link *)value; + entry->constant_version = 0; +} /** * Loads the app-supplied constants into the currently set GLSL program. @@ -390,14 +484,13 @@ static void shader_glsl_load_constants( char useVertexShader) { IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device; - const struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv; IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock; const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; - const GLhandleARB *constant_locations; - const struct list *constant_list; GLhandleARB programId; - const struct glsl_shader_prog_link *prog = priv->glsl_program; + struct glsl_shader_prog_link *prog = priv->glsl_program; + UINT constant_version; int i; if (!prog) { @@ -405,24 +498,26 @@ static void shader_glsl_load_constants( return; } programId = prog->programId; + constant_version = prog->constant_version; if (useVertexShader) { IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader; - constant_locations = prog->vuniformF_locations; - constant_list = &stateBlock->set_vconstantsF; - /* Load DirectX 9 float constants/uniforms for vertex shader */ - shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF), - stateBlock->vertexShaderConstantF, constant_locations, constant_list); + shader_glsl_load_constantsF(vshader, gl_info, stateBlock->vertexShaderConstantF, + prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version); /* Load DirectX 9 integer constants/uniforms for vertex shader */ - shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations, - stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI); + if(vshader->baseShader.uses_int_consts) { + shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations, + stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI); + } /* Load DirectX 9 boolean constants/uniforms for vertex shader */ - shader_glsl_load_constantsB(vshader, gl_info, programId, - stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB); + if(vshader->baseShader.uses_bool_consts) { + shader_glsl_load_constantsB(vshader, gl_info, programId, + stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB); + } /* Upload the position fixup params */ GL_EXTCALL(glUniform4fvARB(prog->posFixup_location, 1, &deviceImpl->posFixup[0])); @@ -433,20 +528,21 @@ static void shader_glsl_load_constants( IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader; - constant_locations = prog->puniformF_locations; - constant_list = &stateBlock->set_pconstantsF; - /* Load DirectX 9 float constants/uniforms for pixel shader */ - shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF), - stateBlock->pixelShaderConstantF, constant_locations, constant_list); + shader_glsl_load_constantsF(pshader, gl_info, stateBlock->pixelShaderConstantF, + prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version); /* Load DirectX 9 integer constants/uniforms for pixel shader */ - shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations, - stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI); + if(pshader->baseShader.uses_int_consts) { + shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations, + stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI); + } /* Load DirectX 9 boolean constants/uniforms for pixel shader */ - shader_glsl_load_constantsB(pshader, gl_info, programId, - stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB); + if(pshader->baseShader.uses_bool_consts) { + shader_glsl_load_constantsB(pshader, gl_info, programId, + stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB); + } /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from. * It can't be 0 for a valid texbem instruction. @@ -486,19 +582,87 @@ static void shader_glsl_load_constants( GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params)); } } + + if (priv->next_constant_version == UINT_MAX) + { + TRACE("Max constant version reached, resetting to 0.\n"); + hash_table_for_each_entry(priv->glsl_program_lookup, reset_program_constant_version, NULL); + priv->next_constant_version = 1; + } + else + { + prog->constant_version = priv->next_constant_version++; + } +} + +static inline void update_heap_entry(struct constant_heap *heap, unsigned int idx, + unsigned int heap_idx, DWORD new_version) +{ + struct constant_entry *entries = heap->entries; + unsigned int *positions = heap->positions; + unsigned int parent_idx; + + while (heap_idx > 1) + { + parent_idx = heap_idx >> 1; + + if (new_version <= entries[parent_idx].version) break; + + entries[heap_idx] = entries[parent_idx]; + positions[entries[parent_idx].idx] = heap_idx; + heap_idx = parent_idx; + } + + entries[heap_idx].version = new_version; + entries[heap_idx].idx = idx; + positions[idx] = heap_idx; +} + +static void shader_glsl_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv; + struct constant_heap *heap = &priv->vconst_heap; + UINT i; + + for (i = start; i < count + start; ++i) + { + if (!This->stateBlock->changed.vertexShaderConstantsF[i]) + update_heap_entry(heap, i, heap->size++, priv->next_constant_version); + else + update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version); + } +} + +static void shader_glsl_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv; + struct constant_heap *heap = &priv->pconst_heap; + UINT i; + + for (i = start; i < count + start; ++i) + { + if (!This->stateBlock->changed.pixelShaderConstantsF[i]) + update_heap_entry(heap, i, heap->size++, priv->next_constant_version); + else + update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version); + } } /** Generate the variable & register declarations for the GLSL output target */ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps, - SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info) + SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_info, + const struct ps_compile_args *ps_args) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; + DWORD shader_version = reg_maps->shader_version; unsigned int i, extra_constants_needed = 0; const local_constant *lconst; /* There are some minor differences between pixel and vertex shaders */ - char pshader = shader_is_pshader_version(This->baseShader.hex_version); + char pshader = shader_is_pshader_version(shader_version); char prefix = pshader ? 'P' : 'V'; /* Prototype the subroutines */ @@ -532,7 +696,8 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s * out. The nvidia driver only does that if the parameter is inout instead of out, hence the * inout. */ - if(This->baseShader.hex_version >= WINED3DVS_VERSION(3, 0)) { + if (shader_version >= WINED3DVS_VERSION(3, 0)) + { shader_addline(buffer, "void order_ps_input(in vec4[%u]);\n", MAX_REG_OUTPUT); } else { shader_addline(buffer, "void order_ps_input();\n"); @@ -562,7 +727,7 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s ps_impl->numbumpenvmatconsts++; } - if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { + if(ps_args->srgb_correction) { shader_addline(buffer, "const vec4 srgb_mul_low = vec4(%f, %f, %f, %f);\n", srgb_mul_low, srgb_mul_low, srgb_mul_low, srgb_mul_low); shader_addline(buffer, "const vec4 srgb_comparison = vec4(%f, %f, %f, %f);\n", @@ -633,8 +798,10 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s /* Declare input register varyings. Only pixel shader, vertex shaders have that declared in the * helper function shader that is linked in at link time */ - if(pshader && This->baseShader.hex_version >= WINED3DPS_VERSION(3, 0)) { - if(use_vs(device)) { + if (pshader && shader_version >= WINED3DPS_VERSION(3, 0)) + { + if (use_vs(device->stateBlock)) + { shader_addline(buffer, "varying vec4 IN[%u];\n", GL_LIMITS(glsl_varyings) / 4); } else { /* TODO: Write a replacement shader for the fixed function vertex pipeline, so this isn't needed. @@ -803,8 +970,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; const WineD3D_GL_Info* gl_info = &deviceImpl->adapter->gl_info; - - char pshader = shader_is_pshader_version(This->baseShader.hex_version); + DWORD shader_version = This->baseShader.reg_maps.shader_version; + char pshader = shader_is_pshader_version(shader_version); char tmpStr[150]; *is_color = FALSE; @@ -816,7 +983,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to case WINED3DSPR_INPUT: if (pshader) { /* Pixel shaders >= 3.0 */ - if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3) { + if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3) + { DWORD in_count = GL_LIMITS(glsl_varyings) / 4; if (param & WINED3DSHADER_ADDRMODE_RELATIVE) { @@ -862,8 +1030,7 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to strcpy(tmpStr, "gl_SecondaryColor"); } } else { - if (vshader_input_is_color((IWineD3DVertexShader*) This, reg)) - *is_color = TRUE; + if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << reg)) *is_color = TRUE; sprintf(tmpStr, "attrib%u", reg); } break; @@ -876,7 +1043,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to /* Relative addressing on shaders 2.0+ have a relative address token, * prior to that, it was hard-coded as "A0.x" because there's only 1 register */ - if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2) { + if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2) + { glsl_src_param_t rel_param; shader_glsl_add_src_param(arg, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param); if(reg) { @@ -955,10 +1123,8 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to break; case WINED3DSPR_TEXCRDOUT: /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */ - if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3) - sprintf(tmpStr, "OUT[%u]", reg); - else - sprintf(tmpStr, "gl_TexCoord[%u]", reg); + if (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 3) sprintf(tmpStr, "OUT[%u]", reg); + else sprintf(tmpStr, "gl_TexCoord[%u]", reg); break; case WINED3DSPR_MISCTYPE: if (reg == 0) { @@ -1307,7 +1473,6 @@ static void shader_glsl_arith(const SHADER_OPCODE_ARG *arg) /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */ static void shader_glsl_mov(const SHADER_OPCODE_ARG *arg) { - IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; SHADER_BUFFER* buffer = arg->buffer; glsl_src_param_t src0_param; DWORD write_mask; @@ -1317,9 +1482,10 @@ static void shader_glsl_mov(const SHADER_OPCODE_ARG *arg) /* In vs_1_1 WINED3DSIO_MOV can write to the address register. In later * shader versions WINED3DSIO_MOVA is used for this. */ - if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1 && - !shader_is_pshader_version(shader->baseShader.hex_version) && - shader_get_regtype(arg->dst) == WINED3DSPR_ADDR)) { + 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)) + { /* This is a simple floor() */ unsigned int mask_size = shader_glsl_get_write_mask_size(write_mask); if (mask_size > 1) { @@ -1487,12 +1653,12 @@ static void shader_glsl_map2gl(const SHADER_OPCODE_ARG *arg) */ static void shader_glsl_expp(const SHADER_OPCODE_ARG *arg) { - IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader; glsl_src_param_t src_param; shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param); - if (shader->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { + if (arg->reg_maps->shader_version < WINED3DPS_VERSION(2,0)) + { char dst_mask[6]; shader_addline(arg->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str); @@ -1683,14 +1849,14 @@ static void shader_glsl_cmp(const SHADER_OPCODE_ARG *arg) * the compare is done per component of src0. */ static void shader_glsl_cnd(const SHADER_OPCODE_ARG *arg) { - IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; glsl_src_param_t src0_param; glsl_src_param_t src1_param; glsl_src_param_t src2_param; DWORD write_mask, cmp_channel = 0; unsigned int i, j; - if (shader->baseShader.hex_version < WINED3DPS_VERSION(1, 4)) { + if (arg->reg_maps->shader_version < WINED3DPS_VERSION(1, 4)) + { write_mask = shader_glsl_append_dst(arg->buffer, arg); shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param); shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param); @@ -1749,7 +1915,7 @@ static void shader_glsl_mnxn(const SHADER_OPCODE_ARG *arg) { 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; int i; int nComponents = 0; SHADER_OPCODE_ARG tmpArg; @@ -2085,7 +2251,7 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; - DWORD hex_version = This->baseShader.hex_version; + DWORD shader_version = arg->reg_maps->shader_version; char dst_swizzle[6]; glsl_sample_function_t sample_function; DWORD sampler_type; @@ -2098,14 +2264,12 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg) /* 1.0-1.4: Use destination register as sampler source. * 2.0+: Use provided sampler source. */ - if (hex_version < WINED3DPS_VERSION(2,0)) { - sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; - } else { - sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; - } + if (shader_version < WINED3DPS_VERSION(2,0)) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK; - if (hex_version < WINED3DPS_VERSION(1,4)) { + if (shader_version < WINED3DPS_VERSION(1,4)) + { DWORD flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS]; /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */ @@ -2121,7 +2285,9 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg) } else { projected = FALSE; } - } 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) { @@ -2151,15 +2317,13 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg) shader_glsl_get_sample_function(sampler_type, projected, texrect, &sample_function); mask |= sample_function.coord_mask; - if (hex_version < WINED3DPS_VERSION(2,0)) { - shader_glsl_get_write_mask(arg->dst, dst_swizzle); - } else { - shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle); - } + if (shader_version < WINED3DPS_VERSION(2,0)) shader_glsl_get_write_mask(arg->dst, dst_swizzle); + else shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle); /* 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)) + { char coord_mask[6]; shader_glsl_get_write_mask(mask, coord_mask); shader_addline(arg->buffer, "%s(Psampler%u, T%u%s)%s);\n", @@ -2205,7 +2369,8 @@ static void shader_glsl_texldl(const SHADER_OPCODE_ARG *arg) shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &lod_param); - if (shader_is_pshader_version(This->baseShader.hex_version)) { + if (shader_is_pshader_version(arg->reg_maps->shader_version)) + { /* The GLSL spec claims the Lod sampling functions are only supported in vertex shaders. * However, they seem to work just fine in fragment shaders as well. */ WARN("Using %sLod in fragment shader.\n", sample_function.name); @@ -2220,17 +2385,15 @@ static void shader_glsl_texldl(const SHADER_OPCODE_ARG *arg) static void pshader_glsl_texcoord(const SHADER_OPCODE_ARG *arg) { /* FIXME: Make this work for more than just 2D textures */ - - IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; SHADER_BUFFER* buffer = arg->buffer; - DWORD hex_version = This->baseShader.hex_version; DWORD write_mask; char dst_mask[6]; write_mask = shader_glsl_append_dst(arg->buffer, arg); shader_glsl_get_write_mask(write_mask, dst_mask); - if (hex_version != WINED3DPS_VERSION(1,4)) { + if (arg->reg_maps->shader_version != WINED3DPS_VERSION(1,4)) + { DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK; shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n", reg, dst_mask); } else { @@ -2654,13 +2817,12 @@ static void pshader_glsl_texreg2rgb(const SHADER_OPCODE_ARG *arg) * If any of the first 3 components are < 0, discard this pixel */ static void pshader_glsl_texkill(const SHADER_OPCODE_ARG *arg) { - IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; - DWORD hex_version = This->baseShader.hex_version; glsl_dst_param_t dst_param; /* The argument is a destination parameter, and no writemasks are allowed */ shader_glsl_add_dst_param(arg, arg->dst, 0, &dst_param); - if((hex_version >= WINED3DPS_VERSION(2,0))) { + if ((arg->reg_maps->shader_version >= WINED3DPS_VERSION(2,0))) + { /* 2.0 shaders compare all 4 components in texkill */ shader_addline(arg->buffer, "if (any(lessThan(%s.xyzw, vec4(0.0)))) discard;\n", dst_param.reg_name); } else { @@ -2948,8 +3110,8 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) vertexshader; IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) pixelshader; IWineD3DDeviceImpl *device; - DWORD vs_major = WINED3DSHADER_VERSION_MAJOR(vs->baseShader.hex_version); - DWORD ps_major = ps ? WINED3DSHADER_VERSION_MAJOR(ps->baseShader.hex_version) : 0; + DWORD vs_major = WINED3DSHADER_VERSION_MAJOR(vs->baseShader.reg_maps.shader_version); + DWORD ps_major = ps ? WINED3DSHADER_VERSION_MAJOR(ps->baseShader.reg_maps.shader_version) : 0; unsigned int i; SHADER_BUFFER buffer; DWORD usage_token; @@ -2958,10 +3120,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs char reg_mask[6]; const struct semantic *semantics_out, *semantics_in; - buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); - buffer.bsize = 0; - buffer.lineNo = 0; - buffer.newline = TRUE; + shader_buffer_init(&buffer); shader_addline(&buffer, "#version 120\n"); @@ -3093,7 +3252,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs GL_EXTCALL(glCompileShaderARB(ret)); checkGLcall("glCompileShaderARB(ret)"); - HeapFree(GetProcessHeap(), 0, buffer.buffer); + shader_buffer_free(&buffer); return ret; } @@ -3164,6 +3323,7 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use entry->vshader = vshader_id; entry->pshader = pshader; entry->ps_args = compile_args; + entry->constant_version = 0; /* Add the hash table entry */ add_glsl_program_entry(priv, entry); @@ -3264,8 +3424,10 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use entry->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(programId, "ycorrection")); checkGLcall("Find glsl program uniform locations"); - if (pshader && WINED3DSHADER_VERSION_MAJOR(((IWineD3DPixelShaderImpl *)pshader)->baseShader.hex_version) >= 3 - && ((IWineD3DPixelShaderImpl *)pshader)->declared_in_count > GL_LIMITS(glsl_varyings) / 4) { + if (pshader + && WINED3DSHADER_VERSION_MAJOR(((IWineD3DPixelShaderImpl *)pshader)->baseShader.reg_maps.shader_version) >= 3 + && ((IWineD3DPixelShaderImpl *)pshader)->declared_in_count > GL_LIMITS(glsl_varyings) / 4) + { TRACE("Shader %d needs vertex color clamping disabled\n", programId); entry->vertex_color_clamp = GL_FALSE; } else { @@ -3309,7 +3471,8 @@ static GLhandleARB create_glsl_blt_shader(const WineD3D_GL_Info *gl_info, enum t { GLhandleARB program_id; GLhandleARB vshader_id, pshader_id; - const char *blt_vshader[] = { + static const char *blt_vshader[] = + { "#version 120\n" "void main(void)\n" "{\n" @@ -3319,7 +3482,8 @@ static GLhandleARB create_glsl_blt_shader(const WineD3D_GL_Info *gl_info, enum t "}\n" }; - const char *blt_pshaders[tex_type_count] = { + static const char *blt_pshaders[tex_type_count] = + { /* tex_1d */ NULL, /* tex_2d */ @@ -3436,12 +3600,6 @@ static void shader_glsl_deselect_depth_blt(IWineD3DDevice *iface) { checkGLcall("glUseProgramObjectARB"); } -static void shader_glsl_cleanup(IWineD3DDevice *iface) { - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - GL_EXTCALL(glUseProgramObjectARB(0)); -} - static void shader_glsl_destroy(IWineD3DBaseShader *iface) { const struct list *linked_programs; IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; @@ -3454,7 +3612,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { /* Note: Do not use QueryInterface here to find out which shader type this is because this code * can be called from IWineD3DBaseShader::Release */ - char pshader = shader_is_pshader_version(This->baseShader.hex_version); + char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version); if(pshader) { ps = (IWineD3DPixelShaderImpl *) This; @@ -3529,10 +3687,64 @@ static BOOL glsl_program_key_compare(const void *keya, const void *keyb) (memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) == 0); } +static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count) +{ + SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) + constant_count * sizeof(*heap->positions); + void *mem = HeapAlloc(GetProcessHeap(), 0, size); + + if (!mem) + { + ERR("Failed to allocate memory\n"); + return FALSE; + } + + heap->entries = mem; + heap->entries[1].version = 0; + heap->positions = (unsigned int *)(heap->entries + constant_count + 1); + heap->size = 1; + + return TRUE; +} + +static void constant_heap_free(struct constant_heap *heap) +{ + HeapFree(GetProcessHeap(), 0, heap->entries); +} + static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + const WineD3D_GL_Info *gl_info = &This->adapter->gl_info; struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv)); + SIZE_T stack_size = wined3d_log2i(max(GL_LIMITS(vshader_constantsF), GL_LIMITS(pshader_constantsF))) + 1; + + priv->stack = HeapAlloc(GetProcessHeap(), 0, stack_size * sizeof(*priv->stack)); + if (!priv->stack) + { + ERR("Failed to allocate memory.\n"); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; + } + + if (!constant_heap_init(&priv->vconst_heap, GL_LIMITS(vshader_constantsF))) + { + ERR("Failed to initialize vertex shader constant heap\n"); + HeapFree(GetProcessHeap(), 0, priv->stack); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; + } + + if (!constant_heap_init(&priv->pconst_heap, GL_LIMITS(pshader_constantsF))) + { + ERR("Failed to initialize pixel shader constant heap\n"); + constant_heap_free(&priv->vconst_heap); + HeapFree(GetProcessHeap(), 0, priv->stack); + HeapFree(GetProcessHeap(), 0, priv); + return E_OUTOFMEMORY; + } + priv->glsl_program_lookup = hash_table_create(glsl_program_key_hash, glsl_program_key_compare); + priv->next_constant_version = 1; + This->shader_priv = priv; return WINED3D_OK; } @@ -3552,6 +3764,8 @@ static void shader_glsl_free(IWineD3DDevice *iface) { } hash_table_destroy(priv->glsl_program_lookup, NULL, NULL); + constant_heap_free(&priv->pconst_heap); + constant_heap_free(&priv->vconst_heap); HeapFree(GetProcessHeap(), 0, This->shader_priv); This->shader_priv = NULL; @@ -3562,7 +3776,7 @@ static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) { return FALSE; } -static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) { +static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps; CONST DWORD *function = This->baseShader.function; @@ -3585,23 +3799,19 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU } /* Base Declarations */ - shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION); + shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, args); /* Pack 3.0 inputs */ - if (This->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) { - - if(((IWineD3DDeviceImpl *) This->baseShader.device)->strided_streams.u.s.position_transformed) { - pshader_glsl_input_pack(buffer, This->semantics_in, iface, pretransformed); - } else if(!use_vs((IWineD3DDeviceImpl *) This->baseShader.device)) { - pshader_glsl_input_pack(buffer, This->semantics_in, iface, fixedfunction); - } + if (reg_maps->shader_version >= WINED3DPS_VERSION(3,0) && args->vp_mode != vertexshader) { + pshader_glsl_input_pack(buffer, This->semantics_in, iface, args->vp_mode); } /* Base Shader Body */ shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function); /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */ - if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { + if (reg_maps->shader_version < WINED3DPS_VERSION(2,0)) + { /* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */ if(GL_SUPPORT(ARB_DRAW_BUFFERS)) shader_addline(buffer, "gl_FragData[0] = R0;\n"); @@ -3614,7 +3824,7 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU } else { fragcolor = "gl_FragColor"; } - if(((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { + if(args->srgb_correction) { shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n", fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high, srgb_sub_high, srgb_sub_high, srgb_sub_high); @@ -3630,9 +3840,22 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU * NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but * -1/(e-s) and e/(e-s) respectively. */ - if(This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) { - shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n"); - shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor); + if(reg_maps->shader_version < WINED3DPS_VERSION(3,0)) { + switch(args->fog) { + case FOG_OFF: break; + case FOG_LINEAR: + shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n"); + shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n"); + shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n"); + shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor); + break; + case FOG_EXP: + FIXME("Implement EXP fog in glsl\n"); + break; + case FOG_EXP2: + FIXME("Implement EXP2 fog in glsl\n"); + break; + } } shader_addline(buffer, "}\n"); @@ -3658,17 +3881,14 @@ static void shader_glsl_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUF shader_addline(buffer, "#version 120\n"); /* Base Declarations */ - shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION); + shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL); /* Base Shader Body */ shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function); /* Unpack 3.0 outputs */ - if (This->baseShader.hex_version >= WINED3DVS_VERSION(3,0)) { - shader_addline(buffer, "order_ps_input(OUT);\n"); - } else { - shader_addline(buffer, "order_ps_input();\n"); - } + if (reg_maps->shader_version >= WINED3DVS_VERSION(3,0)) shader_addline(buffer, "order_ps_input(OUT);\n"); + else shader_addline(buffer, "order_ps_input();\n"); /* If this shader doesn't use fog copy the z coord to the fog coord so that we can use table fog */ if (!reg_maps->fog) @@ -3863,8 +4083,9 @@ const shader_backend_t glsl_shader_backend = { shader_glsl_select, shader_glsl_select_depth_blt, shader_glsl_deselect_depth_blt, + shader_glsl_update_float_vertex_constants, + shader_glsl_update_float_pixel_constants, shader_glsl_load_constants, - shader_glsl_cleanup, shader_glsl_color_correction, shader_glsl_destroy, shader_glsl_alloc, diff --git a/reactos/dll/directx/wine/wined3d/indexbuffer.c b/reactos/dll/directx/wine/wined3d/indexbuffer.c index 0737892d1df..2325f70ee53 100644 --- a/reactos/dll/directx/wine/wined3d/indexbuffer.c +++ b/reactos/dll/directx/wine/wined3d/indexbuffer.c @@ -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) { diff --git a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c index 77f53655211..fc727d670a9 100644 --- a/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c +++ b/reactos/dll/directx/wine/wined3d/nvidia_texture_shader.c @@ -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 }, diff --git a/reactos/dll/directx/wine/wined3d/palette.c b/reactos/dll/directx/wine/wined3d/palette.c index 8f6e37a9013..338e66e0906 100644 --- a/reactos/dll/directx/wine/wined3d/palette.c +++ b/reactos/dll/directx/wine/wined3d/palette.c @@ -1,4 +1,4 @@ -/* DirectDraw - IDirectPalette base interface +/* DirectDraw - IDirectPalette base interface * * Copyright 1997-2000 Marcus Meissner * Copyright 2000-2001 TransGaming Technologies Inc. diff --git a/reactos/dll/directx/wine/wined3d/pixelshader.c b/reactos/dll/directx/wine/wined3d/pixelshader.c index 0557d86f1bb..9f96c59c0fa 100644 --- a/reactos/dll/directx/wine/wined3d/pixelshader.c +++ b/reactos/dll/directx/wine/wined3d/pixelshader.c @@ -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, NULL); - if (FAILED(hr)) return hr; - /* FIXME: validate reg_maps against OpenGL */ - - for(i = 0; i < MAX_REG_INPUT; i++) { - if(This->input_reg_used[i]) { - num_regs_used++; - highest_reg_used = i; - } + /* 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; + + 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"); - } + /* 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) + { + 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; + } } } diff --git a/reactos/dll/directx/wine/wined3d/query.c b/reactos/dll/directx/wine/wined3d/query.c index 7826325a374..05e114c1b5a 100644 --- a/reactos/dll/directx/wine/wined3d/query.c +++ b/reactos/dll/directx/wine/wined3d/query.c @@ -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 */ diff --git a/reactos/dll/directx/wine/wined3d/resource.c b/reactos/dll/directx/wine/wined3d/resource.c index efcac7b2a7f..1231b34a988 100644 --- a/reactos/dll/directx/wine/wined3d/resource.c +++ b/reactos/dll/directx/wine/wined3d/resource.c @@ -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; diff --git a/reactos/dll/directx/wine/wined3d/state.c b/reactos/dll/directx/wine/wined3d/state.c index 0da9842a98a..67fc1c7648f 100644 --- a/reactos/dll/directx/wine/wined3d/state.c +++ b/reactos/dll/directx/wine/wined3d/state.c @@ -1,4 +1,3 @@ - /* * Direct3D state management * @@ -96,7 +95,7 @@ static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL || stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) && - stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE; + stateblock->wineD3DDevice->strided_streams.position_transformed) ? TRUE : FALSE; if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) { glEnable(GL_LIGHTING); @@ -470,27 +469,29 @@ static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D float ref; BOOL enable_ckey = FALSE; - IWineD3DSurfaceImpl *surf; - /* Find out if the texture on the first stage has a ckey set * The alpha state func reads the texture settings, even though alpha and texture are not grouped * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha * in case it finds some texture+colorkeyenable combination which needs extra care. */ - if(stateblock->textures[0] && ( - stateblock->textureDimensions[0] == GL_TEXTURE_2D || - stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { - surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0]; - - if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) { - const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL); - /* The surface conversion does not do color keying conversion for surfaces that have an alpha - * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the - * surface has alpha bits - */ - if(fmt->alphaMask == 0x00000000) { - enable_ckey = TRUE; + if (stateblock->textures[0]) + { + UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]); + + if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) + { + IWineD3DSurfaceImpl *surf; + + surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0]; + + if (surf->CKeyFlags & WINEDDSD_CKSRCBLT) + { + const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL); + /* The surface conversion does not do color keying conversion for surfaces that have an alpha + * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the + * surface has alpha bits */ + if (fmt->alphaMask == 0x00000000) enable_ckey = TRUE; } } } @@ -531,7 +532,8 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine DWORD enable = 0xFFFFFFFF; DWORD disable = 0x00000000; - if (use_vs(stateblock->wineD3DDevice)) { + if (use_vs(stateblock)) + { /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't, * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some * conditions I got sick of tracking down. The shader state handler disables all clip planes because @@ -702,7 +704,7 @@ state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCon checkGLcall("glFinalCombinerInputNV()"); } } else { - const GLfloat black[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; /* for the case of enabled lighting: */ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]); @@ -751,14 +753,10 @@ static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, Win /* And now the default texture color as well */ for (i = 0; i < GL_LIMITS(texture_stages); i++) { /* Note the WINED3DRS value applies to all textures, but GL has one - * per texture, so apply it now ready to be used! - */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); - checkGLcall("glActiveTextureARB"); - } else if (i>0) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); - } + * per texture, so apply it now ready to be used! + */ + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); + checkGLcall("glActiveTextureARB"); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]); checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); @@ -898,40 +896,98 @@ static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, checkGLcall("glStencilMask"); } -static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE]; - BOOL is_ps3 = use_ps(stateblock->wineD3DDevice) - && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0); - float fogstart, fogend; +static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return; + /* Table fog on: Never use fog coords, and use per-fragment fog */ + if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) { + glHint(GL_FOG_HINT, GL_NICEST); + if(context->fog_coord) { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); + context->fog_coord = FALSE; + } + return; + } + + /* Otherwise use per-vertex fog in any case */ + glHint(GL_FOG_HINT, GL_FASTEST); + + if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) { + /* No fog at all, or transformed vertices: Use fog coord */ + if(!context->fog_coord) { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)"); + context->fog_coord = TRUE; + } + } else { + /* Otherwise, use the fragment depth */ + if(context->fog_coord) { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); + context->fog_coord = FALSE; + } + } +} + +void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + float fogstart, fogend; union { DWORD d; float f; } tmpvalue; - if (!fogenable) { + switch(context->fog_source) { + case FOGSOURCE_VS: + fogstart = 1.0; + fogend = 0.0; + break; + + case FOGSOURCE_COORD: + fogstart = 255.0; + fogend = 0.0; + break; + + case FOGSOURCE_FFP: + tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART]; + fogstart = tmpvalue.f; + tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND]; + fogend = tmpvalue.f; + /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/ + if(fogstart == fogend) { + fogstart = -1.0 / 0.0; + fogend = 0.0; + } + break; + + default: + /* This should not happen.context->fog_source is set in wined3d, not the app. + * Still this is needed to make the compiler happy + */ + ERR("Unexpected fog coordinate source\n"); + fogstart = 0.0; + fogend = 0.0; + } + + glFogf(GL_FOG_START, fogstart); + checkGLcall("glFogf(GL_FOG_START, fogstart)"); + TRACE("Fog Start == %f\n", fogstart); + + glFogf(GL_FOG_END, fogend); + checkGLcall("glFogf(GL_FOG_END, fogend)"); + TRACE("Fog End == %f\n", fogend); +} + +void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + enum fogsource new_source; + + if (!stateblock->renderState[WINED3DRS_FOGENABLE]) { /* No fog? Disable it, and we're done :-) */ - glDisable(GL_FOG); + glDisableWINE(GL_FOG); checkGLcall("glDisable GL_FOG"); - if( use_ps(stateblock->wineD3DDevice) - && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) { - /* disable fog in the pixel shader - * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but - * -1/(e-s) and e/(e-s) respectively. - */ - glFogf(GL_FOG_START, 0.0f); - checkGLcall("glFogf(GL_FOG_START, fogstart)"); - glFogf(GL_FOG_END, 1.0f); - checkGLcall("glFogf(GL_FOG_END, fogend)"); - } return; } - tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART]; - fogstart = tmpvalue.f; - tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND]; - fogend = tmpvalue.f; - /* Fog Rules: * * With fixed function vertex processing, Direct3D knows 2 different fog input sources. @@ -968,177 +1024,86 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo * without shaders). */ - if( is_ps3 ) { - if( !use_vs(stateblock->wineD3DDevice) - && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) { - FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n"); - } - } - - if (use_vs(stateblock->wineD3DDevice) - && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) { + if (use_vs(stateblock) && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) { if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) { - if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n"); - /* Disable fog */ - fogenable = FALSE; + FIXME("vertex shader with table fog used\n"); } else { /* Set fog computation in the rasterizer to pass through the value (just blend it) */ glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); - fogstart = 1.0; - fogend = 0.0; - } - - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; } context->last_was_foggy_shader = TRUE; - } - else if( use_ps(stateblock->wineD3DDevice) ) { - /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but - * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader. - */ - WINED3DFOGMODE mode; - context->last_was_foggy_shader = FALSE; - - /* If both fogmodes are set use the table fog mode */ - if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) - mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE]; - else - mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE]; - - switch (mode) { - case WINED3DFOG_EXP: - case WINED3DFOG_EXP2: - if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n"); - /* Disable fog */ - fogenable = FALSE; - break; - - case WINED3DFOG_LINEAR: - fogstart = -1.0f/(fogend-fogstart); - fogend *= -fogstart; - break; - - case WINED3DFOG_NONE: - if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n"); - /* Disable fog */ - fogenable = FALSE; - break; - default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]); - } - - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } + new_source = FOGSOURCE_VS; } /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, * the system will apply only pixel(=table) fog effects." */ else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { - glHint(GL_FOG_HINT, GL_FASTEST); - checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)"); context->last_was_foggy_shader = FALSE; switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) { /* If processed vertices are used, fall through to the NONE case */ - case WINED3DFOG_EXP: { + case WINED3DFOG_EXP: if(!context->last_was_rhw) { glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)"); - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } + new_source = FOGSOURCE_FFP; break; } - } - case WINED3DFOG_EXP2: { + /* drop through */ + + case WINED3DFOG_EXP2: if(!context->last_was_rhw) { glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)"); - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } + new_source = FOGSOURCE_FFP; break; } - } - case WINED3DFOG_LINEAR: { + /* drop through */ + + case WINED3DFOG_LINEAR: if(!context->last_was_rhw) { glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } + new_source = FOGSOURCE_FFP; break; } - } - case WINED3DFOG_NONE: { + /* drop through */ + + case WINED3DFOG_NONE: /* Both are none? According to msdn the alpha channel of the specular * color contains a fog factor. Set it in drawStridedSlow. * Same happens with Vertexfog on transformed vertices */ - if(GL_SUPPORT(EXT_FOG_COORD)) { - if(context->fog_coord == FALSE) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)"); - context->fog_coord = TRUE; - } - glFogi(GL_FOG_MODE, GL_LINEAR); - checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); - fogstart = 0xff; - fogend = 0x0; - } else { - /* Disable GL fog, handle this in software in drawStridedSlow */ - fogenable = FALSE; - } + new_source = FOGSOURCE_COORD; + glFogi(GL_FOG_MODE, GL_LINEAR); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); break; - } - default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]); + + default: + FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]); + new_source = FOGSOURCE_FFP; /* Make the compiler happy */ } } else { glHint(GL_FOG_HINT, GL_NICEST); checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)"); context->last_was_foggy_shader = FALSE; + new_source = FOGSOURCE_FFP; switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) { case WINED3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)"); - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } break; case WINED3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)"); - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } break; case WINED3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); - if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) { - glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); - checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); - context->fog_coord = FALSE; - } break; case WINED3DFOG_NONE: /* Won't happen */ @@ -1147,43 +1112,11 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo } } - if(fogenable) { - glEnable(GL_FOG); - checkGLcall("glEnable GL_FOG"); - - if(fogstart != fogend) - { - glFogfv(GL_FOG_START, &fogstart); - checkGLcall("glFogf(GL_FOG_START, fogstart)"); - TRACE("Fog Start == %f\n", fogstart); - - glFogfv(GL_FOG_END, &fogend); - checkGLcall("glFogf(GL_FOG_END, fogend)"); - TRACE("Fog End == %f\n", fogend); - } - else - { - glFogf(GL_FOG_START, -1.0 / 0.0); - checkGLcall("glFogf(GL_FOG_START, fogstart)"); - TRACE("Fog Start == %f\n", fogstart); - - glFogf(GL_FOG_END, 0.0); - checkGLcall("glFogf(GL_FOG_END, fogend)"); - TRACE("Fog End == %f\n", fogend); - } - } else { - glDisable(GL_FOG); - checkGLcall("glDisable GL_FOG"); - if( use_ps(stateblock->wineD3DDevice) ) { - /* disable fog in the pixel shader - * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but - * -1/(e-s) and e/(e-s) respectively. - */ - glFogf(GL_FOG_START, 0.0f); - checkGLcall("glFogf(GL_FOG_START, fogstart)"); - glFogf(GL_FOG_END, 1.0f); - checkGLcall("glFogf(GL_FOG_END, fogend)"); - } + glEnableWINE(GL_FOG); + checkGLcall("glEnable GL_FOG"); + if(new_source != context->fog_source) { + context->fog_source = new_source; + state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context); } } @@ -1203,14 +1136,14 @@ static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine } } -static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { float col[4]; D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col); glFogfv(GL_FOG_COLOR, &col[0]); checkGLcall("glFog GL_FOG_COLOR"); } -static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { +void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { union { DWORD d; float f; @@ -1323,7 +1256,7 @@ static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular); checkGLcall("glMaterialfv"); } else { - const GLfloat black[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]); checkGLcall("glMaterialfv"); } @@ -1934,10 +1867,6 @@ static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTE op = WINED3DTOP_SELECTARG1; } - /* From MSDN (WINED3DTSS_ALPHAARG1) : - The default argument is WINED3DTA_TEXTURE. If no texture is set for this stage, - then the default argument is WINED3DTA_DIFFUSE. - FIXME? If texture added/removed, may need to reset back as well? */ if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) { get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1); } else { @@ -2908,32 +2837,24 @@ static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTE static void tex_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(stage >= stateblock->lowest_disabled_stage) { @@ -2972,26 +2893,20 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D } void tex_alphaop(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); DWORD op, arg1, arg2, arg0; TRACE("Setting alpha op for stage %d\n", stage); /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */ 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) { - /* We can't do anything here */ - 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"); } op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP]; @@ -2999,50 +2914,64 @@ void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2]; arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0]; - if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && - stateblock->textures[0] && - (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { - IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; + if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0]) + { + 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; - /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly. - * On the other hand applications can still use texture combiners apparently. This code takes care that apps - * cannot remove the texture's alpha channel entirely. - * - * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work - * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to - * draw things like translucent text and perform other blending effects. - * - * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the - * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha. - * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha - * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by - * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated - * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending, - * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha; - * otherwise, selecting diffuse alpha is ignored in favour of texture alpha. - - * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing - */ - if(op == WINED3DTOP_DISABLE) { - arg1 = WINED3DTA_TEXTURE; - op = WINED3DTOP_SELECTARG1; - } - else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) { - if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { - arg2 = WINED3DTA_TEXTURE; - op = WINED3DTOP_MODULATE; - } - else arg1 = WINED3DTA_TEXTURE; - } - else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) { - if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; + + if (surf->CKeyFlags & WINEDDSD_CKSRCBLT + && getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) + { + /* Color keying needs to pass alpha values from the texture through to have the alpha test work + * properly. On the other hand applications can still use texture combiners apparently. This code + * takes care that apps cannot remove the texture's alpha channel entirely. + * + * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires + * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures + * and alpha component of diffuse color to draw things like translucent text and perform other + * blending effects. + * + * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To + * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be + * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to + * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the + * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of + * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels + * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha + * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be + * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture + * alpha. + * + * What to do with multitexturing? So far no app has been found that uses color keying with + * multitexturing */ + if (op == WINED3DTOP_DISABLE) + { arg1 = WINED3DTA_TEXTURE; - op = WINED3DTOP_MODULATE; + op = WINED3DTOP_SELECTARG1; + } + else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) + { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) + { + arg2 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg1 = WINED3DTA_TEXTURE; + } + else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) + { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) + { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg2 = WINED3DTA_TEXTURE; } - else arg2 = WINED3DTA_TEXTURE; } } } @@ -3063,31 +2992,25 @@ void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext } static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit]; BOOL generated; int coordIdx; /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */ - if(use_vs(stateblock->wineD3DDevice) || - isStateDirty(context, STATE_VDECL)) { + if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL)) + { TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n"); return; } if (mapped_stage == -1) return; - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - if(mapped_stage >= GL_LIMITS(textures)) { - return; - } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); - checkGLcall("glActiveTextureARB"); - } else if (mapped_stage > 0) { - /* We can't do anything here */ - WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + if(mapped_stage >= GL_LIMITS(textures)) { return; } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU; coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1); @@ -3101,7 +3024,8 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W stateblock->wineD3DDevice->frag_pipe->ffp_proj_control); /* The sampler applying function calls us if this changes */ - if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) { + if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit]) + { if(generated) { FIXME("Non-power2 texture being used with generated texture coords\n"); } @@ -3125,13 +3049,6 @@ static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3D unsigned int mapped_stage = 0; unsigned int textureNo = 0; - /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */ - /* Abort if we don't support the extension. */ - if (!GL_SUPPORT(ARB_MULTITEXTURE)) { - FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); - return; - } - for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) { int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX]; @@ -3153,7 +3070,7 @@ static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3D /* The coords to supply depend completely on the fvf / vertex shader */ glTexCoordPointer( - WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType), + WINED3D_ATR_FORMAT(sd->u.s.texCoords[coordIdx].dwType), WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]); @@ -3173,35 +3090,27 @@ static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3D } static void tex_coordindex(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]; - const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 }; - const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 }; - const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 }; - const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 }; + static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 }; + static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 }; + static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 }; + static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 }; if (mapped_stage == -1) { TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage); return; } - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - if(mapped_stage >= GL_LIMITS(fragment_samplers)) { - return; - } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); - checkGLcall("glActiveTextureARB"); - } else if (stage > 0) { - /* We can't do anything here */ - WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + if(mapped_stage >= GL_LIMITS(fragment_samplers)) { return; } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive * - * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include - * one flag, you can still specify an index value, which the system uses to - * determine the texture wrapping mode. + * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode. * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 ); * means use the vertex position (camera-space) as the input texture coordinates * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render @@ -3356,11 +3265,11 @@ static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine return; } - device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device)); + device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock)); } static void tex_bumpenvlscale(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); if(stateblock->pixelShader && stage != 0 && ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) { @@ -3388,20 +3297,26 @@ static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, W * misc pipeline */ if(sampler < MAX_TEXTURES) { - if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D || - stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) { + UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture); + + if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) + { if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 || ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) { texIsPow2 = TRUE; } - } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) { + } + else if (texture_dimensions == GL_TEXTURE_CUBE_MAP_ARB) + { if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) { texIsPow2 = TRUE; } } - if(texIsPow2 || context->lastWasPow2Texture[sampler]) { - context->lastWasPow2Texture[sampler] = texIsPow2; + if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler))) + { + if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler; + else context->lastWasPow2Texture &= ~(1 << sampler); transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); } } @@ -3425,17 +3340,11 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont return; } - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - if (mapped_stage >= GL_LIMITS(combined_samplers)) { - return; - } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); - checkGLcall("glActiveTextureARB"); - } else if (sampler > 0) { - /* We can't do anything here */ - WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); + if (mapped_stage >= GL_LIMITS(combined_samplers)) { return; } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); if(stateblock->textures[sampler]) { IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]); @@ -3450,7 +3359,8 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)"); } - if(!use_ps(stateblock->wineD3DDevice) && sampler < stateblock->lowest_disabled_stage) { + if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage) + { if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) { /* If color keying is enabled update the alpha test, it depends on the existence * of a color key in stage 0 @@ -3473,26 +3383,10 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont } } -static void apply_pshader_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; - - if (use_ps(device)) { - if(!context->last_was_pshader) { - state_fog(state, stateblock, context); - } - context->last_was_pshader = TRUE; - } else { - if(context->last_was_pshader) { - state_fog(state, stateblock, context); - } - context->last_was_pshader = FALSE; - } -} - void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; - BOOL use_pshader = use_ps(device); - BOOL use_vshader = use_vs(device); + BOOL use_pshader = use_ps(stateblock); + BOOL use_vshader = use_vs(stateblock); int i; if (use_pshader) { @@ -3533,7 +3427,7 @@ void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC } static void shader_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); if(stateblock->pixelShader && 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 @@ -3945,7 +3839,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, stateblock->wineD3DDevice->instancedDraw = FALSE; for (i = 0; i < MAX_ATTRIBS; i++) { - if (!strided->u.input[i].VBO && !strided->u.input[i].lpData) + if (!(strided->use_map & (1 << i))) { if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i); continue; @@ -3979,7 +3873,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]); shift_index = shift_index % strided->u.input[i].dwStride; GL_EXTCALL(glVertexAttribPointerARB(i, - WINED3D_ATR_SIZE(strided->u.input[i].dwType), + WINED3D_ATR_FORMAT(strided->u.input[i].dwType), WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), vb->conv_stride, @@ -3990,7 +3884,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, } else { GL_EXTCALL(glVertexAttribPointerARB(i, - WINED3D_ATR_SIZE(strided->u.input[i].dwType), + WINED3D_ATR_FORMAT(strided->u.input[i].dwType), WINED3D_ATR_GLTYPE(strided->u.input[i].dwType), WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType), strided->u.input[i].dwStride, @@ -4111,16 +4005,16 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) { if (GL_SUPPORT(ARB_VERTEX_BLEND)) { - TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType), + TRACE("Blend %d %p %d\n", WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType), sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]); glEnableClientState(GL_WEIGHT_ARRAY_ARB); checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)"); - GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1)); + GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) + 1)); VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n", - WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) , + WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) , sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo])); @@ -4131,7 +4025,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3 } GL_EXTCALL(glWeightPointerARB)( - WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType), + WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType), WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType), sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]); @@ -4183,7 +4077,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3 curVBO = sd->u.s.position.VBO; } - /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord + /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord handling for rhw mode should not impact screen position whereas in GL it does. This may result in very slightly distorted textures in rhw mode. There's always the other option of fixing the view matrix to @@ -4192,12 +4086,12 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3 This only applies to user pointer sources, in VBOs the vertices are fixed up */ if(sd->u.s.position.VBO == 0) { - glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */, + glVertexPointer(3 /* min(WINED3D_ATR_FORMAT(sd->u.s.position.dwType),3) */, WINED3D_ATR_GLTYPE(sd->u.s.position.dwType), sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]); } else { glVertexPointer( - WINED3D_ATR_SIZE(sd->u.s.position.dwType), + WINED3D_ATR_FORMAT(sd->u.s.position.dwType), WINED3D_ATR_GLTYPE(sd->u.s.position.dwType), sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]); } @@ -4251,7 +4145,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3 curVBO = sd->u.s.diffuse.VBO; } - glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType), + glColorPointer(WINED3D_ATR_FORMAT(sd->u.s.diffuse.dwType), WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType), sd->u.s.diffuse.dwStride, sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]); @@ -4277,7 +4171,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3 checkGLcall("glBindBufferARB"); curVBO = sd->u.s.specular.VBO; } - GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType), + GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_FORMAT(sd->u.s.specular.dwType), WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType), sd->u.s.specular.dwStride, sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]); @@ -4344,13 +4238,7 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo BOOL load_numbered = FALSE; BOOL load_named = FALSE; - if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader && - ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) { - useVertexShaderFunction = TRUE; - } else { - useVertexShaderFunction = FALSE; - } - + useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE; if(device->up_strided) { /* Note: this is a ddraw fixed-function code path */ @@ -4372,9 +4260,7 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo useVertexShaderFunction, dataLocations, &fixup); } - if (dataLocations->u.s.position_transformed) { - useVertexShaderFunction = FALSE; - } + if (dataLocations->position_transformed) useVertexShaderFunction = FALSE; if(useVertexShaderFunction) { if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) { @@ -4384,7 +4270,7 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo load_numbered = TRUE; device->useDrawStridedSlow = FALSE; } - } else if (fixup || + } else if (fixup || GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA) || (dataLocations->u.s.pSize.lpData == NULL && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL)) { @@ -4437,20 +4323,16 @@ static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo } static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - BOOL useVertexShaderFunction = FALSE, updateFog = FALSE; - BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader - && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function; + BOOL updateFog = FALSE; + BOOL useVertexShaderFunction = use_vs(stateblock); + BOOL usePixelShaderFunction = use_ps(stateblock); BOOL transformed; /* Some stuff is in the device until we have per context tracking */ IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; BOOL wasrhw = context->last_was_rhw; - /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software - - * here simply check whether a shader was set, or the user disabled shaders - */ - if (use_vs(device)) { - useVertexShaderFunction = TRUE; - + if (useVertexShaderFunction) + { if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) { updateFog = TRUE; } @@ -4458,9 +4340,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W updateFog = TRUE; } - transformed = device->strided_streams.u.s.position_transformed; - if (transformed) useVertexShaderFunction = FALSE; - + transformed = device->strided_streams.position_transformed; if(transformed != context->last_was_rhw && !useVertexShaderFunction) { updateFog = TRUE; } @@ -4577,7 +4457,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W context->last_was_vshader = useVertexShaderFunction; if(updateFog) { - state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context); + device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context); } if(!useVertexShaderFunction) { int i; @@ -5293,13 +5173,9 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = { { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 }, /* Fog */ - { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, - { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, - { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, - { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 }, - { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 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_vertexpart}, 0 }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 }, { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE }, { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 }, { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 }, @@ -5328,8 +5204,6 @@ const struct StateEntryTemplate ffp_vertexstate_template[] = { { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS }, { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 }, - /* pixel shaders need a different fog input */ - { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pshader_fog }, 0 }, /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported, * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states. * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix @@ -5446,6 +5320,13 @@ static const struct StateEntryTemplate ffp_fragmentstate_template[] = { { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 }, { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 }, { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_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), sampler_texdim }, 0 }, { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, @@ -5547,7 +5428,7 @@ static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context); } -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) { @@ -5579,6 +5460,7 @@ void compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_mul memset(set, 0, sizeof(set)); for(i = 0; cur[i].state; i++) { + APPLYSTATEFUNC *funcs_array; /* Only use the first matching state with the available extension from one template. * e.g. @@ -5611,17 +5493,24 @@ void compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_mul dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(), 0, sizeof(**dev_multistate_funcs) * 2); + if (!dev_multistate_funcs[cur[i].state]) { + goto out_of_mem; + } + dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0]; dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1]; break; case 2: StateTable[cur[i].state].apply = multistate_apply_3; - HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]); - dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(), - 0, - sizeof(**dev_multistate_funcs) * 3); - dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0]; - dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1]; + funcs_array = HeapReAlloc(GetProcessHeap(), + 0, + dev_multistate_funcs[cur[i].state], + sizeof(**dev_multistate_funcs) * 3); + if (!funcs_array) { + goto out_of_mem; + } + + dev_multistate_funcs[cur[i].state] = funcs_array; dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2]; break; default: @@ -5637,5 +5526,16 @@ void compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_mul StateTable[cur[i].state].representative = cur[i].content.representative; } } + + return WINED3D_OK; + +out_of_mem: + for (i = 0; i <= STATE_HIGHEST; ++i) { + HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]); + } + + memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs)); + + return E_OUTOFMEMORY; } #undef GLINFO_LOCATION diff --git a/reactos/dll/directx/wine/wined3d/stateblock.c b/reactos/dll/directx/wine/wined3d/stateblock.c index 3faa5a0411f..e1f1dd8eab3 100644 --- a/reactos/dll/directx/wine/wined3d/stateblock.c +++ b/reactos/dll/directx/wine/wined3d/stateblock.c @@ -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); - object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(vshader_constantsF)); - WINED3D_MEMCHECK(object->contained_vs_consts_f); - object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(pshader_constantsF)); - WINED3D_MEMCHECK(object->contained_ps_consts_f); + if (!object->changed.vertexShaderConstantsF) goto fail; - list_init(&object->set_vconstantsF); - list_init(&object->set_pconstantsF); + object->contained_vs_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(vshader_constantsF)); + if (!object->contained_vs_consts_f) goto fail; -#undef WINED3D_MEMCHECK + object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(pshader_constantsF)); + 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; ichanged.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]); + 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 (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.streamFreq; + for (i = 0; map; map >>= 1, ++i) + { + if (map & 1) IWineD3DDevice_SetStreamSourceFreq(pDevice, i, This->streamFreq[i] | This->streamFlags[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.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); } diff --git a/reactos/dll/directx/wine/wined3d/surface.c b/reactos/dll/directx/wine/wined3d/surface.c index 01914030911..03d483a2ad0 100644 --- a/reactos/dll/directx/wine/wined3d/surface.c +++ b/reactos/dll/directx/wine/wined3d/surface.c @@ -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, diff --git a/reactos/dll/directx/wine/wined3d/surface_base.c b/reactos/dll/directx/wine/wined3d/surface_base.c index 2710a8f59c5..f023c2e4828 100644 --- a/reactos/dll/directx/wine/wined3d/surface_base.c +++ b/reactos/dll/directx/wine/wined3d/surface_base.c @@ -29,6 +29,7 @@ #include "config.h" #include "wine/port.h" #include "wined3d_private.h" +#include "float.h" #include @@ -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) diff --git a/reactos/dll/directx/wine/wined3d/surface_gdi.c b/reactos/dll/directx/wine/wined3d/surface_gdi.c index d06245866d0..eab5dde0bab 100644 --- a/reactos/dll/directx/wine/wined3d/surface_gdi.c +++ b/reactos/dll/directx/wine/wined3d/surface_gdi.c @@ -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, diff --git a/reactos/dll/directx/wine/wined3d/texture.c b/reactos/dll/directx/wine/wined3d/texture.c index 71fb455a35c..e83d869c29a 100644 --- a/reactos/dll/directx/wine/wined3d/texture.c +++ b/reactos/dll/directx/wine/wined3d/texture.c @@ -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 = diff --git a/reactos/dll/directx/wine/wined3d/utils.c b/reactos/dll/directx/wine/wined3d/utils.c index fd4f4ee1987..cc09584b726 100644 --- a/reactos/dll/directx/wine/wined3d/utils.c +++ b/reactos/dll/directx/wine/wined3d/utils.c @@ -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]; +} diff --git a/reactos/dll/directx/wine/wined3d/vertexbuffer.c b/reactos/dll/directx/wine/wined3d/vertexbuffer.c index 59640335ba7..0408819122c 100644 --- a/reactos/dll/directx/wine/wined3d/vertexbuffer.c +++ b/reactos/dll/directx/wine/wined3d/vertexbuffer.c @@ -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; diff --git a/reactos/dll/directx/wine/wined3d/vertexdeclaration.c b/reactos/dll/directx/wine/wined3d/vertexdeclaration.c index 7fc711b4521..f63e2e7ed23 100644 --- a/reactos/dll/directx/wine/wined3d/vertexdeclaration.c +++ b/reactos/dll/directx/wine/wined3d/vertexdeclaration.c @@ -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; } diff --git a/reactos/dll/directx/wine/wined3d/vertexshader.c b/reactos/dll/directx/wine/wined3d/vertexshader.c index 0f246f95867..339d955e230 100644 --- a/reactos/dll/directx/wine/wined3d/vertexshader.c +++ b/reactos/dll/directx/wine/wined3d/vertexshader.c @@ -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_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_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", 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); diff --git a/reactos/dll/directx/wine/wined3d/volume.c b/reactos/dll/directx/wine/wined3d/volume.c index 6700bb4a051..ceffae73d66 100644 --- a/reactos/dll/directx/wine/wined3d/volume.c +++ b/reactos/dll/directx/wine/wined3d/volume.c @@ -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 }; diff --git a/reactos/dll/directx/wine/wined3d/volumetexture.c b/reactos/dll/directx/wine/wined3d/volumetexture.c index 9da4c95f20d..ea8c07370d7 100644 --- a/reactos/dll/directx/wine/wined3d/volumetexture.c +++ b/reactos/dll/directx/wine/wined3d/volumetexture.c @@ -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 = diff --git a/reactos/dll/directx/wine/wined3d/wined3d.rbuild b/reactos/dll/directx/wine/wined3d/wined3d.rbuild index cf81629a24b..32e089c4106 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d.rbuild +++ b/reactos/dll/directx/wine/wined3d/wined3d.rbuild @@ -26,6 +26,7 @@ device.c directx.c drawprim.c + gl_compat.c glsl_shader.c indexbuffer.c nvidia_texture_shader.c @@ -52,4 +53,4 @@ version.rc wineheaders - \ No newline at end of file + diff --git a/reactos/dll/directx/wine/wined3d/wined3d_gl.h b/reactos/dll/directx/wine/wined3d/wined3d_gl.h index f92adc6a730..07ca0d51826 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_gl.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_gl.h @@ -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; diff --git a/reactos/dll/directx/wine/wined3d/wined3d_main.c b/reactos/dll/directx/wine/wined3d/wined3d_main.c index ee8f07f42ed..b401f942ff5 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_main.c +++ b/reactos/dll/directx/wine/wined3d/wined3d_main.c @@ -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) { } diff --git a/reactos/dll/directx/wine/wined3d/wined3d_private.h b/reactos/dll/directx/wine/wined3d/wined3d_private.h index 79617a5f493..0965a77fcd2 100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_private.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_private.h @@ -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, diff --git a/reactos/include/reactos/wine/wined3d.idl b/reactos/include/reactos/wine/wined3d.idl index abb0d3b13ef..2307f5d6091 100644 --- a/reactos/include/reactos/wine/wined3d.idl +++ b/reactos/include/reactos/wine/wined3d.idl @@ -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,