From b6ddd8cadbe4d228bc037435397d41dd4a761ab7 Mon Sep 17 00:00:00 2001 From: Lionel Ulmer Date: Tue, 11 Nov 2003 00:31:16 +0000 Subject: [PATCH] Better color-keying support. --- dlls/ddraw/d3ddevice/mesa.c | 77 ++++++++++++++++++++++++++++++++++++++------- dlls/ddraw/direct3d/mesa.c | 2 +- dlls/ddraw/dsurface/main.c | 2 +- dlls/ddraw/mesa.c | 32 ++++++++++++------- dlls/ddraw/mesa_private.h | 7 ++++- 5 files changed, 94 insertions(+), 26 deletions(-) diff --git a/dlls/ddraw/d3ddevice/mesa.c b/dlls/ddraw/d3ddevice/mesa.c index 12539ad43f4..dd8211fb022 100644 --- a/dlls/ddraw/d3ddevice/mesa.c +++ b/dlls/ddraw/d3ddevice/mesa.c @@ -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 (use_alpha) { if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST); - if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) || - ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) { - glAlphaFunc(GL_GREATER, 0.0); - } + if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0)) + glAlphaFunc(GL_NOTEQUAL, 0.0); } else { 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 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0)) glDisable(GL_ALPHA_TEST); if (use_alpha) { - if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) || - ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) { - 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->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0)) + glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref); } if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST); if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE); @@ -2152,6 +2147,7 @@ draw_primitive_handle_textures(IDirect3DDeviceImpl *This) { IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This; DWORD stage; + BOOLEAN enable_colorkey = FALSE; for (stage = 0; stage < MAX_TEXTURES; stage++) { IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage]; @@ -2208,8 +2204,57 @@ draw_primitive_handle_textures(IDirect3DDeviceImpl *This) This will also update the various texture parameters if needed. */ 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; } @@ -3712,7 +3757,7 @@ apply_texture_state(IDirect3DDeviceImpl *This) } HRESULT -d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface) +d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, BOOLEAN from_surface) { IDirect3DDeviceImpl *object; IDirect3DDeviceGLImpl *gl_object; @@ -3744,7 +3789,14 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur InitializeCriticalSection(&(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); gl_object->display = get_display(device_context); gl_object->drawable = get_drawable(device_context); @@ -3868,6 +3920,9 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur if (GL_extensions.glActiveTexture != NULL) { 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); glDrawBuffer(buffer); diff --git a/dlls/ddraw/direct3d/mesa.c b/dlls/ddraw/direct3d/mesa.c index 77ef7fbc5dd..b98c457cb8d 100644 --- a/dlls/ddraw/direct3d/mesa.c +++ b/dlls/ddraw/direct3d/mesa.c @@ -146,7 +146,7 @@ create_device_helper(IDirectDrawImpl *This, IDirect3DDeviceImpl *lpd3ddev; 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 ((iid == NULL) || diff --git a/dlls/ddraw/dsurface/main.c b/dlls/ddraw/dsurface/main.c index bf510db9ea2..32641796a85 100644 --- a/dlls/ddraw/dsurface/main.c +++ b/dlls/ddraw/dsurface/main.c @@ -189,7 +189,7 @@ Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid, IDirect3DDeviceImpl *d3ddevimpl; 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; *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice); diff --git a/dlls/ddraw/mesa.c b/dlls/ddraw/mesa.c index dfb1f12d2ff..2e325ef7cfa 100644 --- a/dlls/ddraw/mesa.c +++ b/dlls/ddraw/mesa.c @@ -332,10 +332,17 @@ void set_render_state(IDirect3DDeviceImpl* This, glDepthFunc(convert_D3D_compare_to_GL(dwRenderState)); break; - case D3DRENDERSTATE_ALPHAREF: /* 24 */ - case D3DRENDERSTATE_ALPHAFUNC: /* 25 */ - glAlphaFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]), - (lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0); + case D3DRENDERSTATE_ALPHAREF: /* 24 */ + case D3DRENDERSTATE_ALPHAFUNC: { /* 25 */ + GLenum func = convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]); + 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; case D3DRENDERSTATE_DITHERENABLE: /* 26 */ @@ -352,6 +359,11 @@ void set_render_state(IDirect3DDeviceImpl* This, glDisable(GL_BLEND); } glThis->blending = dwRenderState; + + /* Hack for some old games ... */ + if (glThis->version == 1) { + lpStateBlock->render_state[D3DRENDERSTATE_COLORKEYENABLE - 1] = dwRenderState; + } break; case D3DRENDERSTATE_FOGENABLE: /* 28 */ @@ -395,13 +407,7 @@ void set_render_state(IDirect3DDeviceImpl* This, break; case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */ - /* This needs to be fixed. */ - if ((dwRenderState != 0) && (glThis->blending == 0)) { - glEnable(GL_BLEND); - } else if ((dwRenderState == 0) && (glThis->blending != 0)) { - glDisable(GL_BLEND); - } - glThis->blending = dwRenderState; + /* Nothing done here, only storage matters. */ break; case D3DRENDERSTATE_MIPMAPLODBIAS: /* 46 */ @@ -926,6 +932,8 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v /* Used when converting stuff */ line_increase = src_d->u1.lPitch - (width * bpp); + + TRACE(" uploading texture to memory using conversion %d.\n", convert_type); switch (convert_type) { case CONVERT_PALETTED: { @@ -996,7 +1004,7 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { WORD color = *src++; - *dst = ((color & 0xFFD0) | ((color & 0x1F) << 1)); + *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1)); if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) *dst |= 0x0001; diff --git a/dlls/ddraw/mesa_private.h b/dlls/ddraw/mesa_private.h index 9ac00bd84f7..d8eb4acc890 100644 --- a/dlls/ddraw/mesa_private.h +++ b/dlls/ddraw/mesa_private.h @@ -117,6 +117,9 @@ typedef struct IDirect3DDeviceGLImpl /* The last type of vertex drawn */ GL_TRANSFORM_STATE transform_state; + /* Maybe a hack, but it works */ + DWORD version; + /* Used to handle fogging faster... */ BYTE fog_table[3 * 0x10000]; /* 3 is for R, G and B 0x10000 is 0xFF for the vertex color and @@ -142,6 +145,8 @@ typedef struct IDirect3DDeviceGLImpl DWORD prev_clear_stencil; D3DVALUE prev_clear_Z; 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_active_tex_unit; } IDirect3DDeviceGLImpl; @@ -180,7 +185,7 @@ extern HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirect extern HRESULT d3dmaterial_create(IDirect3DMaterialImpl **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 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 */ extern HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version) ; -- 2.11.4.GIT