Stefan Dösinger : wined3d: Implement texbem in arb, improve it in glsl.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Feb 15 05:27:58 CST 2007
Module: wine
Branch: master
Commit: 99576ea24e2dd87be5be147bdfd92ec32c36cd22
URL: http://source.winehq.org/git/wine.git/?a=commit;h=99576ea24e2dd87be5be147bdfd92ec32c36cd22
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Thu Feb 15 03:00:57 2007 +0100
wined3d: Implement texbem in arb, improve it in glsl.
---
dlls/wined3d/arb_program_shader.c | 53 ++++++++++++++++++++++++++++++++++++-
dlls/wined3d/glsl_shader.c | 47 ++++++++++++++++++++++++++++----
2 files changed, 93 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 86e8430..4742447 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -119,6 +119,15 @@ void shader_arb_load_constants(
GL_LIMITS(pshader_constantsF),
stateBlock->pixelShaderConstantF,
&stateBlock->set_pconstantsF);
+ if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst) {
+ /* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the
+ * number of the constant to load the matrix into.
+ * The state manager takes care that this function is always called if the bump env matrix changes
+ */
+ IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader;
+ float *data = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVMAT00];
+ GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst, data));
+ }
}
}
@@ -159,6 +168,19 @@ void shader_generate_arb_declarations(
shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", i, i);
}
+ if(reg_maps->bumpmat /* Only a pshader can use texbem */) {
+ /* If the shader does not use all available constants, use the next free constant to load the bump mapping environment matrix from
+ * the stateblock into the shader. If no constant is available don't load, texbem will then just sample the texture without applying
+ * bump mapping.
+ */
+ if(max_constantsF < GL_LIMITS(pshader_constantsF)) {
+ ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst = max_constantsF;
+ shader_addline(buffer, "PARAM bumpenvmat = program.env[%d];\n", ((IWineD3DPixelShaderImpl *)This)->bumpenvmatconst);
+ } else {
+ FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n");
+ }
+ }
+
/* Need to PARAM the environment parameters (constants) so we can use relative addressing */
shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
max_constantsF, max_constantsF - 1);
@@ -662,7 +684,7 @@ void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) {
}
void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
-
+#if 0
SHADER_BUFFER* buffer = arg->buffer;
DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK;
DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK;
@@ -672,6 +694,35 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) {
sprintf(dst_str, "T%u", reg1);
shader_addline(buffer, "ADD TMP.rg, fragment.texcoord[%u], T%u;\n", reg1, reg2);
shader_hw_sample(arg, reg1, dst_str, "TMP");
+#endif
+ IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+
+ DWORD dst = arg->dst;
+ DWORD src = arg->src[0] & WINED3DSP_REGNUM_MASK;
+ SHADER_BUFFER* buffer = arg->buffer;
+
+ char reg_coord[40];
+ DWORD reg_dest_code;
+
+ /* All versions have a destination register */
+ reg_dest_code = dst & WINED3DSP_REGNUM_MASK;
+ /* Can directly use the name because texbem is only valid for <= 1.3 shaders */
+ pshader_get_register_name(dst, reg_coord);
+
+ if(This->bumpenvmatconst) {
+ /*shader_addline(buffer, "MOV T%u, fragment.texcoord[%u];\n", 1, 1); Not needed - done already */
+ shader_addline(buffer, "SWZ TMP2, bumpenvmat, x, z, 0, 0;\n");
+ shader_addline(buffer, "DP3 TMP.r, TMP2, T%u;\n", src);
+ shader_addline(buffer, "SWZ TMP2, bumpenvmat, y, w, 0, 0;\n");
+ shader_addline(buffer, "DP3 TMP.g, TMP2, T%u;\n", src);
+ shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord);
+ /* Not sure about this, but hl2 needs it. It uses a projected texture with texbem and depends on the 4th coordinate */
+ shader_addline(buffer, "MOV TMP.a, %s;\n", reg_coord);
+ shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP");
+ } else {
+ /* Without a bump matrix loaded, just sample with the unmodified coordinates */
+ shader_hw_sample(arg, reg_dest_code, reg_coord, reg_coord);
+ }
}
void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) {
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 566442b..f270af7 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -1767,15 +1767,50 @@ void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
/** Process the WINED3DSIO_TEXBEM instruction in GLSL.
* Apply a fake bump map transform.
- * FIXME: Should apply the BUMPMAPENV matrix. For now, just sample the texture */
+ * texbem is pshader <= 1.3 only, this saves a few version checks
+ */
void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
+ IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
+ IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
+ char dst_swizzle[6];
+ glsl_sample_function_t sample_function;
+ DWORD sampler_type;
+ DWORD sampler_idx;
+ BOOL projected;
+ DWORD mask = 0;
+ DWORD flags;
+ char coord_mask[6];
+
+ /* All versions have a destination register */
+ shader_glsl_append_dst(arg->buffer, arg);
+
+ sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
+ flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
+
+ /* TODO: Does texbem even support projected textures? half-life 2 uses it */
+ if (flags & WINED3DTTFF_PROJECTED) {
+ projected = TRUE;
+ switch (flags & ~WINED3DTTFF_PROJECTED) {
+ case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break;
+ case WINED3DTTFF_COUNT2: mask = WINED3DSP_WRITEMASK_1; break;
+ case WINED3DTTFF_COUNT3: mask = WINED3DSP_WRITEMASK_2; break;
+ case WINED3DTTFF_COUNT4:
+ case WINED3DTTFF_DISABLE: mask = WINED3DSP_WRITEMASK_3; break;
+ }
+ } else {
+ projected = FALSE;
+ }
+
+ sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
+ shader_glsl_get_sample_function(sampler_type, projected, &sample_function);
+ mask |= sample_function.coord_mask;
- DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK;
- DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK;
+ shader_glsl_get_write_mask(arg->dst, dst_swizzle);
- FIXME("Not applying the BUMPMAPENV matrix for pixel shader instruction texbem.\n");
- shader_addline(arg->buffer, "T%u = texture2D(Psampler%u, gl_TexCoord[%u].xy + T%u.xy);\n",
- reg1, reg1, reg1, reg2);
+ shader_glsl_get_write_mask(mask, coord_mask);
+ FIXME("Bump map transform not handled yet\n");
+ shader_addline(arg->buffer, "%s(Psampler%u, T%u%s)%s);\n",
+ sample_function.name, sampler_idx, sampler_idx, coord_mask, dst_swizzle);
}
/** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
More information about the wine-cvs
mailing list