Commit 5ab9d85c authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Implement texbeml.

parent 0ed81b20
......@@ -198,6 +198,7 @@ HRESULT shader_get_registers_used(
char pshader = shader_is_pshader_version(This->baseShader.hex_version);
reg_maps->bumpmat = -1;
reg_maps->luminanceparams = -1;
if (pToken == NULL)
return WINED3D_OK;
......@@ -354,11 +355,15 @@ HRESULT shader_get_registers_used(
}
/* texbem is only valid with < 1.4 pixel shaders */
if(WINED3DSIO_TEXBEM == curOpcode->opcode) {
if(WINED3DSIO_TEXBEM == curOpcode->opcode ||
WINED3DSIO_TEXBEML == curOpcode->opcode) {
if(reg_maps->bumpmat != -1 && reg_maps->bumpmat != sampler_code) {
FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n");
} else {
reg_maps->bumpmat = sampler_code;
if(WINED3DSIO_TEXBEML == curOpcode->opcode) {
reg_maps->luminanceparams = sampler_code;
}
}
}
}
......
......@@ -389,7 +389,25 @@ void shader_glsl_load_constants(
pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat"));
checkGLcall("glGetUniformLocationARB");
GL_EXTCALL(glUniformMatrix2fvARB(pos, 1, 0, data));
checkGLcall("glUniform4fvARB");
checkGLcall("glUniformMatrix2fvARB");
/* texbeml needs the luminance scale and offset too. If texbeml is used, needsbumpmat
* is set too, so we can check that in the needsbumpmat check
*/
if(((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams != -1) {
int stage = ((IWineD3DPixelShaderImpl *) pshader)->baseShader.reg_maps.luminanceparams;
GLfloat *scale = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
GLfloat *offset = (GLfloat *) &stateBlock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
pos = GL_EXTCALL(glGetUniformLocationARB(programId, "luminancescale"));
checkGLcall("glGetUniformLocationARB");
GL_EXTCALL(glUniform1fvARB(pos, 1, scale));
checkGLcall("glUniform1fvARB");
pos = GL_EXTCALL(glGetUniformLocationARB(programId, "luminanceoffset"));
checkGLcall("glGetUniformLocationARB");
GL_EXTCALL(glUniform1fvARB(pos, 1, offset));
checkGLcall("glUniform1fvARB");
}
}
}
}
......@@ -429,8 +447,13 @@ void shader_generate_glsl_declarations(
if(!pshader)
shader_addline(buffer, "uniform vec4 posFixup;\n");
else if(reg_maps->bumpmat != -1)
else if(reg_maps->bumpmat != -1) {
shader_addline(buffer, "uniform mat2 bumpenvmat;\n");
if(reg_maps->luminanceparams) {
shader_addline(buffer, "uniform float luminancescale;\n");
shader_addline(buffer, "uniform float luminanceoffset;\n");
}
}
/* Declare texture samplers */
for (i = 0; i < This->baseShader.limits.sampler; i++) {
......@@ -1974,8 +1997,16 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &coord_param);
if(arg->opcode->opcode == WINED3DSIO_TEXBEML) {
glsl_src_param_t luminance_param;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &luminance_param);
shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )*(%s * luminancescale + luminanceoffset))%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask,
luminance_param.param_str, dst_swizzle);
} else {
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle);
}
}
void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) {
......
......@@ -223,7 +223,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{WINED3DSIO_TEX, "texld", "undefined", 1, 2, pshader_hw_tex, pshader_glsl_tex, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_TEX, "texld", "undefined", 1, 3, pshader_hw_tex, pshader_glsl_tex, WINED3DPS_VERSION(2,0), -1},
{WINED3DSIO_TEXBEM, "texbem", "undefined", 1, 2, pshader_hw_texbem, pshader_glsl_texbem, 0, WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXBEML, "texbeml", GLNAME_REQUIRE_GLSL, 1, 2, pshader_hw_texbem, pshader_glsl_texbem, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2AR,"texreg2ar","undefined", 1, 2, pshader_hw_texreg2ar, pshader_glsl_texreg2ar, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2GB,"texreg2gb","undefined", 1, 2, pshader_hw_texreg2gb, pshader_glsl_texreg2gb, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)},
{WINED3DSIO_TEXREG2RGB, "texreg2rgb", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texreg2rgb, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)},
......
......@@ -2139,6 +2139,20 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
}
}
static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
/* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
* has an update pending
*/
if(isStateDirty(context, STATE_VDECL) ||
isStateDirty(context, STATE_PIXELSHADER)) {
return;
}
device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
}
static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
union {
......@@ -2146,6 +2160,17 @@ static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, W
float f;
} tmpvalue;
if(stateblock->pixelShader && stage != 0 &&
((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) {
/* The pixel shader has to know the luminance scale. Do a constants update if it
* isn't scheduled anyway
*/
if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
!isStateDirty(context, STATE_PIXELSHADER)) {
shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
}
}
tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
if(tmpvalue.f != 0.0) {
FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
......@@ -2159,6 +2184,17 @@ static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock,
float f;
} tmpvalue;
if(stateblock->pixelShader && 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
* isn't scheduled anyway
*/
if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
!isStateDirty(context, STATE_PIXELSHADER)) {
shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
}
}
tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
if(tmpvalue.f != 0.0) {
FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
......@@ -2278,20 +2314,6 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont
}
}
static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
/* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
* has an update pending
*/
if(isStateDirty(context, STATE_VDECL) ||
isStateDirty(context, STATE_PIXELSHADER)) {
return;
}
device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
}
static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
BOOL use_pshader = use_ps(device);
......
......@@ -1657,7 +1657,7 @@ typedef struct shader_reg_maps {
/* Sampler usage tokens
* Use 0 as default (bit 31 is always 1 on a valid token) */
DWORD samplers[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)];
char bumpmat;
char bumpmat, luminanceparams;
/* Whether or not a loop is used in this shader */
char loop;
......
......@@ -3346,9 +3346,9 @@ typedef enum _GL_SupportedExt {
USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FARBPROC, glUniform2fARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FARBPROC, glUniform3fARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FARBPROC, glUniform4fARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM3IVARBPROC, glUniform3fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM1FVARBPROC, glUniform1fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM2FVARBPROC, glUniform2fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM3FVARBPROC, glUniform3fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM4FVARBPROC, glUniform4fvARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM1IVARBPROC, glUniform1ivARB); \
USE_GL_FUNC(WINED3D_PFNGLUNIFORM2IVARBPROC, glUniform2ivARB); \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment