Commit b6ddd8ca authored by Lionel Ulmer's avatar Lionel Ulmer Committed by Alexandre Julliard

Better color-keying support.

parent b95693c6
...@@ -163,10 +163,8 @@ static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT ...@@ -163,10 +163,8 @@ static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT
if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE); if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
if (use_alpha) { if (use_alpha) {
if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST); if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) || if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) { glAlphaFunc(GL_NOTEQUAL, 0.0);
glAlphaFunc(GL_GREATER, 0.0);
}
} else { } else {
if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST); if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
} }
...@@ -190,11 +188,8 @@ static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DW ...@@ -190,11 +188,8 @@ static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DW
else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0)) else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
glDisable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST);
if (use_alpha) { if (use_alpha) {
if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) || if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) { glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref);
glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
}
} }
if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST); if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE); if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
...@@ -2152,6 +2147,7 @@ draw_primitive_handle_textures(IDirect3DDeviceImpl *This) ...@@ -2152,6 +2147,7 @@ draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
{ {
IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This; IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
DWORD stage; DWORD stage;
BOOLEAN enable_colorkey = FALSE;
for (stage = 0; stage < MAX_TEXTURES; stage++) { for (stage = 0; stage < MAX_TEXTURES; stage++) {
IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage]; IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
...@@ -2208,6 +2204,55 @@ draw_primitive_handle_textures(IDirect3DDeviceImpl *This) ...@@ -2208,6 +2204,55 @@ draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
This will also update the various texture parameters if needed. This will also update the various texture parameters if needed.
*/ */
gltex_upload_texture(surf_ptr, This, stage); gltex_upload_texture(surf_ptr, This, stage);
/* And finally check for color-keying (only on first stage) */
if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
if (stage == 0) {
enable_colorkey = TRUE;
} else {
static BOOL warn = FALSE;
if (warn == FALSE) {
warn = TRUE;
WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
}
}
} else {
if (stage == 0) {
enable_colorkey = FALSE;
}
}
}
/* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
(glThis->version == 1)) &&
(enable_colorkey)) {
TRACE(" colorkey activated.\n");
if (glThis->alpha_test == FALSE) {
glEnable(GL_ALPHA_TEST);
glThis->alpha_test = TRUE;
}
if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) {
static BOOL warn = FALSE;
if (warn == FALSE) {
warn = TRUE;
WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
}
}
glThis->current_alpha_test_func = GL_NOTEQUAL;
glThis->current_alpha_test_ref = 0.0;
glAlphaFunc(GL_NOTEQUAL, 0.0);
}
/* Some sanity checks should be added here if a game mixes alphatest + color keying...
Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
} else {
if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
glDisable(GL_ALPHA_TEST);
glThis->alpha_test = FALSE;
}
/* Maybe we should restore here the application-given alpha test states ? */
} }
return stage; return stage;
...@@ -3712,7 +3757,7 @@ apply_texture_state(IDirect3DDeviceImpl *This) ...@@ -3712,7 +3757,7 @@ apply_texture_state(IDirect3DDeviceImpl *This)
} }
HRESULT HRESULT
d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface) d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface)
{ {
IDirect3DDeviceImpl *object; IDirect3DDeviceImpl *object;
IDirect3DDeviceGLImpl *gl_object; IDirect3DDeviceGLImpl *gl_object;
...@@ -3745,6 +3790,13 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur ...@@ -3745,6 +3790,13 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur
TRACE(" device critical section : %p\n", &(object->crit)); TRACE(" device critical section : %p\n", &(object->crit));
/* This is just a hack for some badly done games :-/ */
if (from_surface) {
gl_object->version = 1;
TRACE(" using D3D1 special hacks.\n");
} else
gl_object->version = 7;
device_context = GetDC(surface->ddraw_owner->window); device_context = GetDC(surface->ddraw_owner->window);
gl_object->display = get_display(device_context); gl_object->display = get_display(device_context);
gl_object->drawable = get_drawable(device_context); gl_object->drawable = get_drawable(device_context);
...@@ -3868,6 +3920,9 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur ...@@ -3868,6 +3920,9 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur
if (GL_extensions.glActiveTexture != NULL) { if (GL_extensions.glActiveTexture != NULL) {
GL_extensions.glActiveTexture(GL_TEXTURE0_WINE); GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
} }
gl_object->current_alpha_test_ref = 0.0;
gl_object->current_alpha_test_func = GL_ALWAYS;
glAlphaFunc(GL_ALWAYS, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDrawBuffer(buffer); glDrawBuffer(buffer);
......
...@@ -146,7 +146,7 @@ create_device_helper(IDirectDrawImpl *This, ...@@ -146,7 +146,7 @@ create_device_helper(IDirectDrawImpl *This,
IDirect3DDeviceImpl *lpd3ddev; IDirect3DDeviceImpl *lpd3ddev;
HRESULT ret_value; HRESULT ret_value;
ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS); ret_value = d3ddevice_create(&lpd3ddev, This, lpDDS, FALSE);
if (FAILED(ret_value)) return ret_value; if (FAILED(ret_value)) return ret_value;
if ((iid == NULL) || if ((iid == NULL) ||
......
...@@ -189,7 +189,7 @@ Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid, ...@@ -189,7 +189,7 @@ Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
IDirect3DDeviceImpl *d3ddevimpl; IDirect3DDeviceImpl *d3ddevimpl;
HRESULT ret_value; HRESULT ret_value;
ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This); ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, TRUE);
if (FAILED(ret_value)) return ret_value; if (FAILED(ret_value)) return ret_value;
*ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice); *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
......
...@@ -333,9 +333,16 @@ void set_render_state(IDirect3DDeviceImpl* This, ...@@ -333,9 +333,16 @@ void set_render_state(IDirect3DDeviceImpl* This,
break; break;
case D3DRENDERSTATE_ALPHAREF: /* 24 */ case D3DRENDERSTATE_ALPHAREF: /* 24 */
case D3DRENDERSTATE_ALPHAFUNC: /* 25 */ case D3DRENDERSTATE_ALPHAFUNC: { /* 25 */
glAlphaFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]), GLenum func = convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]);
(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0); GLclampf ref = (lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0;
if ((func != glThis->current_alpha_test_func) || (ref != glThis->current_alpha_test_ref)) {
glAlphaFunc(func, ref);
glThis->current_alpha_test_func = func;
glThis->current_alpha_test_ref = ref;
}
}
break; break;
case D3DRENDERSTATE_DITHERENABLE: /* 26 */ case D3DRENDERSTATE_DITHERENABLE: /* 26 */
...@@ -352,6 +359,11 @@ void set_render_state(IDirect3DDeviceImpl* This, ...@@ -352,6 +359,11 @@ void set_render_state(IDirect3DDeviceImpl* This,
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
glThis->blending = dwRenderState; glThis->blending = dwRenderState;
/* Hack for some old games ... */
if (glThis->version == 1) {
lpStateBlock->render_state[D3DRENDERSTATE_COLORKEYENABLE - 1] = dwRenderState;
}
break; break;
case D3DRENDERSTATE_FOGENABLE: /* 28 */ case D3DRENDERSTATE_FOGENABLE: /* 28 */
...@@ -395,13 +407,7 @@ void set_render_state(IDirect3DDeviceImpl* This, ...@@ -395,13 +407,7 @@ void set_render_state(IDirect3DDeviceImpl* This,
break; break;
case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */ case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */
/* This needs to be fixed. */ /* Nothing done here, only storage matters. */
if ((dwRenderState != 0) && (glThis->blending == 0)) {
glEnable(GL_BLEND);
} else if ((dwRenderState == 0) && (glThis->blending != 0)) {
glDisable(GL_BLEND);
}
glThis->blending = dwRenderState;
break; break;
case D3DRENDERSTATE_MIPMAPLODBIAS: /* 46 */ case D3DRENDERSTATE_MIPMAPLODBIAS: /* 46 */
...@@ -927,6 +933,8 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v ...@@ -927,6 +933,8 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
/* Used when converting stuff */ /* Used when converting stuff */
line_increase = src_d->u1.lPitch - (width * bpp); line_increase = src_d->u1.lPitch - (width * bpp);
TRACE(" uploading texture to memory using conversion %d.\n", convert_type);
switch (convert_type) { switch (convert_type) {
case CONVERT_PALETTED: { case CONVERT_PALETTED: {
IDirectDrawPaletteImpl* pal = current_surface->palette; IDirectDrawPaletteImpl* pal = current_surface->palette;
...@@ -996,7 +1004,7 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v ...@@ -996,7 +1004,7 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
for (y = 0; y < height; y++) { for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) { for (x = 0; x < width; x++) {
WORD color = *src++; WORD color = *src++;
*dst = ((color & 0xFFD0) | ((color & 0x1F) << 1)); *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0x0001; *dst |= 0x0001;
......
...@@ -117,6 +117,9 @@ typedef struct IDirect3DDeviceGLImpl ...@@ -117,6 +117,9 @@ typedef struct IDirect3DDeviceGLImpl
/* The last type of vertex drawn */ /* The last type of vertex drawn */
GL_TRANSFORM_STATE transform_state; GL_TRANSFORM_STATE transform_state;
/* Maybe a hack, but it works */
DWORD version;
/* Used to handle fogging faster... */ /* Used to handle fogging faster... */
BYTE fog_table[3 * 0x10000]; /* 3 is for R, G and B BYTE fog_table[3 * 0x10000]; /* 3 is for R, G and B
0x10000 is 0xFF for the vertex color and 0x10000 is 0xFF for the vertex color and
...@@ -142,6 +145,8 @@ typedef struct IDirect3DDeviceGLImpl ...@@ -142,6 +145,8 @@ typedef struct IDirect3DDeviceGLImpl
DWORD prev_clear_stencil; DWORD prev_clear_stencil;
D3DVALUE prev_clear_Z; D3DVALUE prev_clear_Z;
BOOLEAN depth_mask, depth_test, alpha_test, stencil_test, cull_face, lighting, blending, fogging; BOOLEAN depth_mask, depth_test, alpha_test, stencil_test, cull_face, lighting, blending, fogging;
GLenum current_alpha_test_func;
GLclampf current_alpha_test_ref;
GLenum current_tex_env; GLenum current_tex_env;
GLenum current_active_tex_unit; GLenum current_active_tex_unit;
} IDirect3DDeviceGLImpl; } IDirect3DDeviceGLImpl;
...@@ -180,7 +185,7 @@ extern HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirect ...@@ -180,7 +185,7 @@ extern HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirect
extern HRESULT d3dmaterial_create(IDirect3DMaterialImpl **obj, IDirectDrawImpl *d3d); extern HRESULT d3dmaterial_create(IDirect3DMaterialImpl **obj, IDirectDrawImpl *d3d);
extern HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d); extern HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d);
extern HRESULT d3dvertexbuffer_create(IDirect3DVertexBufferImpl **obj, IDirectDrawImpl *d3d, LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc, DWORD dwFlags); extern HRESULT d3dvertexbuffer_create(IDirect3DVertexBufferImpl **obj, IDirectDrawImpl *d3d, LPD3DVERTEXBUFFERDESC lpD3DVertBufDesc, DWORD dwFlags);
extern HRESULT d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface); extern HRESULT d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface);
/* Used for Direct3D to request the device to enumerate itself */ /* Used for Direct3D to request the device to enumerate itself */
extern HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version) ; extern HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version) ;
......
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