wined3d: Implement support for per-stage texture stage constants.

This patch is loosely based on an earlier patch by Christian Costa.
This commit is contained in:
Henri Verbeet 2014-04-23 14:35:21 +02:00 committed by Alexandre Julliard
parent ac70dd2c97
commit 23eed88fde
2 changed files with 179 additions and 11 deletions

View File

@ -16407,6 +16407,146 @@ static void add_dirty_rect_test(void)
DestroyWindow(window);
}
static void test_per_stage_constant(void)
{
IDirect3DDevice9 *device;
IDirect3D9 *d3d;
D3DCOLOR color;
ULONG refcount;
D3DCAPS9 caps;
HWND window;
HRESULT hr;
static const struct
{
struct vec3 position;
D3DCOLOR diffuse;
}
quad[] =
{
{{-1.0f, -1.0f, 0.1f}, 0xffff0000},
{{-1.0f, 1.0f, 0.1f}, 0xffff0000},
{{ 1.0f, -1.0f, 0.1f}, 0xffff0000},
{{ 1.0f, 1.0f, 0.1f}, 0xffff0000},
};
window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 640, 480, NULL, NULL, NULL, NULL);
d3d = Direct3DCreate9(D3D_SDK_VERSION);
ok(!!d3d, "Failed to create a D3D object.\n");
if (!(device = create_device(d3d, window, window, TRUE)))
{
skip("Failed to create a D3D device, skipping tests.\n");
goto done;
}
hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
if (!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT))
{
skip("Per-stage constants not supported, skipping tests.\n");
IDirect3DDevice9_Release(device);
goto done;
}
hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_CONSTANT, 0x80a1b2c3);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_CONSTANT);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice9_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice9_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = getPixelColor(device, 320, 240);
ok(color_match(color, 0x00a1b2c3, 1), "Got unexpected color 0x%08x.\n", color);
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_CONSTANT | D3DTA_COMPLEMENT);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice9_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice9_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = getPixelColor(device, 320, 240);
ok(color_match(color, 0x005e4d3c, 1), "Got unexpected color 0x%08x.\n", color);
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_CONSTANT | D3DTA_ALPHAREPLICATE);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice9_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice9_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = getPixelColor(device, 320, 240);
ok(color_match(color, 0x00808080, 1), "Got unexpected color 0x%08x.\n", color);
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_CURRENT);
ok(SUCCEEDED(hr), "Failed to set texture stage state, hr %#x.\n", hr);
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice9_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice9_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = getPixelColor(device, 320, 240);
ok(color_match(color, 0x0080007f, 1), "Got unexpected color 0x%08x.\n", color);
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
refcount = IDirect3DDevice9_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
done:
IDirect3D9_Release(d3d);
DestroyWindow(window);
}
START_TEST(visual)
{
D3DADAPTER_IDENTIFIER9 identifier;
@ -16513,4 +16653,5 @@ START_TEST(visual)
multisampled_depth_buffer_test();
resz_test();
stencil_cull_test();
test_per_stage_constant();
}

View File

@ -129,6 +129,7 @@ struct glsl_ps_program
GLint bumpenv_mat_location[MAX_TEXTURES];
GLint bumpenv_lum_scale_location[MAX_TEXTURES];
GLint bumpenv_lum_offset_location[MAX_TEXTURES];
GLint tss_constant_location[MAX_TEXTURES];
GLint tex_factor_location;
GLint specular_enable_location;
GLint ycorrection_location;
@ -868,6 +869,15 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
else
GL_EXTCALL(glUniform4fARB(prog->ps.specular_enable_location, 0.0f, 0.0f, 0.0f, 0.0f));
for (i = 0; i < MAX_TEXTURES; ++i)
{
if (prog->ps.tss_constant_location[i] == -1)
continue;
D3DCOLORTOGLFLOAT4(state->texture_states[i][WINED3D_TSS_CONSTANT], col);
GL_EXTCALL(glUniform4fvARB(prog->ps.tss_constant_location[i], 1, col));
}
checkGLcall("fixed function uniforms");
}
@ -5083,17 +5093,16 @@ static const char *shader_glsl_get_ffp_fragment_op_arg(struct wined3d_shader_buf
break;
case WINED3DTA_CONSTANT:
FIXME("Per-stage constants not implemented.\n");
switch (stage)
{
case 0: ret = "const0"; break;
case 1: ret = "const1"; break;
case 2: ret = "const2"; break;
case 3: ret = "const3"; break;
case 4: ret = "const4"; break;
case 5: ret = "const5"; break;
case 6: ret = "const6"; break;
case 7: ret = "const7"; break;
case 0: ret = "tss_const0"; break;
case 1: ret = "tss_const1"; break;
case 2: ret = "tss_const2"; break;
case 3: ret = "tss_const3"; break;
case 4: ret = "tss_const4"; break;
case 5: ret = "tss_const5"; break;
case 6: ret = "tss_const6"; break;
case 7: ret = "tss_const7"; break;
default:
ret = "<invalid constant>";
break;
@ -5284,8 +5293,8 @@ static void shader_glsl_ffp_fragment_op(struct wined3d_shader_buffer *buffer, un
static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buffer *buffer,
const struct ffp_frag_settings *settings, const struct wined3d_gl_info *gl_info)
{
BYTE lum_map = 0, bump_map = 0, tex_map = 0, tss_const_map = 0;
BOOL tempreg_used = FALSE, tfactor_used = FALSE;
BYTE lum_map = 0, bump_map = 0, tex_map = 0;
const char *final_combiner_src = "ret";
UINT lowest_disabled_stage;
GLhandleARB shader_obj;
@ -5312,6 +5321,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
tempreg_used = TRUE;
if (settings->op[stage].dst == tempreg)
tempreg_used = TRUE;
if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
tss_const_map |= 1 << stage;
switch (settings->op[stage].cop)
{
@ -5347,6 +5358,8 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
tfactor_used = TRUE;
if (arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP)
tempreg_used = TRUE;
if (arg0 == WINED3DTA_CONSTANT || arg1 == WINED3DTA_CONSTANT || arg2 == WINED3DTA_CONSTANT)
tss_const_map |= 1 << stage;
}
lowest_disabled_stage = stage;
@ -5363,6 +5376,9 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
for (stage = 0; stage < MAX_TEXTURES; ++stage)
{
if (tss_const_map & (1 << stage))
shader_addline(buffer, "uniform vec4 tss_const%u;\n", stage);
if (!(tex_map & (1 << stage)))
continue;
@ -5723,6 +5739,8 @@ static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *
ps->bumpenv_lum_scale_location[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
snprintf(name, sizeof(name), "bumpenv_lum_offset%u", i);
ps->bumpenv_lum_offset_location[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
snprintf(name, sizeof(name), "tss_const%u", i);
ps->tss_constant_location[i] = GL_EXTCALL(glGetUniformLocationARB(program_id, name));
}
ps->tex_factor_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "tex_factor"));
@ -7027,7 +7045,8 @@ static void glsl_fragment_pipe_get_caps(const struct wined3d_gl_info *gl_info, s
{
caps->wined3d_caps = WINED3D_FRAGMENT_CAP_PROJ_CONTROL
| WINED3D_FRAGMENT_CAP_SRGB_WRITE;
caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP
| WINED3DPMISCCAPS_PERSTAGECONSTANT;
caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE
| WINED3DTEXOPCAPS_SELECTARG1
| WINED3DTEXOPCAPS_SELECTARG2
@ -7253,6 +7272,14 @@ static const struct StateEntryTemplate glsl_fragment_pipe_state_template[] =
{STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), glsl_fragment_pipe_tex_transform }, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), {STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_fragment_pipe_invalidate_constants}, WINED3D_GL_EXT_NONE },
{0 /* Terminate */, {0, 0 }, WINED3D_GL_EXT_NONE },
};