diff --git a/dlls/ddraw/d3d_private.h b/dlls/ddraw/d3d_private.h index cc8b8dff4ed..37b10b2bdbd 100644 --- a/dlls/ddraw/d3d_private.h +++ b/dlls/ddraw/d3d_private.h @@ -204,7 +204,8 @@ struct IDirect3DDeviceImpl D3DVIEWPORT7 active_viewport; IDirectDrawSurfaceImpl *current_texture[MAX_TEXTURES]; - + IDirectDrawSurfaceImpl *current_zbuffer; + /* Current transformation matrices */ D3DMATRIX *world_mat; D3DMATRIX *view_mat; diff --git a/dlls/ddraw/d3ddevice/mesa.c b/dlls/ddraw/d3ddevice/mesa.c index 4b0309adc0e..4cb330fb421 100644 --- a/dlls/ddraw/d3ddevice/mesa.c +++ b/dlls/ddraw/d3ddevice/mesa.c @@ -1096,6 +1096,54 @@ GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface, return ret_value; } +static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) { + static BOOLEAN first = TRUE; + IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev; + int row; + GLenum type; + + if (first == TRUE) { + MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n"); + first = FALSE; + } + + TRACE("flushing ZBuffer back to GL\n"); + + if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) { + gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO; + d3ddevice_set_ortho(d3d_dev); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST); + if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case + in some drivers... + */ + switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) { + case 16: type = GL_UNSIGNED_SHORT; break; + case 32: type = GL_UNSIGNED_INT; break; + default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state; + } + + for (row = 0; row < surf->surface_desc.dwHeight; row++) { + /* glRasterPos3d(0.0, row + 1.0, 0.5); */ + glRasterPos2i(0, row + 1); + glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type, + ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch)); + } + + restore_state: + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) + glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1])); + if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST); +} + /* These are the various handler used in the generic path */ inline static void handle_xyz(D3DVALUE *coords) { glVertex3fv(coords); @@ -1251,8 +1299,26 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This, if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) { This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]); } - glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL; + + if (This->current_zbuffer == NULL) { + /* Search for an attached ZBuffer */ + static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 }; + LPDIRECTDRAWSURFACE7 zbuf; + HRESULT hr; + + hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7), + (DDSCAPS2 *) &zbuf_caps, &zbuf); + if (!FAILED(hr)) { + This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf); + IDirectDrawSurface7_Release(zbuf); + } + } + if (This->current_zbuffer != NULL) { + if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) { + flush_zbuffer_to_GL(This, NULL, This->current_zbuffer); + } + } /* Just a hack for now.. Will have to find better algorithm :-/ */ if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) { @@ -1270,7 +1336,6 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This, glThis->current_active_tex_unit = GL_TEXTURE0_WINE; } - draw_primitive_handle_GL_state(This, (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ, vertex_lighted); @@ -3160,11 +3225,11 @@ d3ddevice_set_ortho(IDirect3DDeviceImpl *This) to OpenGL screen coordinates (ie the upper left corner is not the same). For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */ - trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0; - trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0; - trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0; - trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0; - + trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0; + trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0; + trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0; + trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0; + ENTER_GL(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -3874,6 +3939,7 @@ static void fill_opengl_primcaps(D3DPRIMCAPS *pc) static void fill_caps(void) { GLint max_clip_planes; + GLint depth_bits; /* Fill first all the fields with default values which will be overriden later on with correct ones from the GL code @@ -3886,7 +3952,6 @@ static void fill_caps(void) fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps)); fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps)); opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32; - opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; opengl_device_caps.dwMinTextureWidth = 1; opengl_device_caps.dwMinTextureHeight = 1; opengl_device_caps.dwMaxTextureWidth = 1024; @@ -3937,6 +4002,15 @@ static void fill_caps(void) glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes); opengl_device_caps.wMaxUserClipPlanes = max_clip_planes; TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes); + + glGetIntegerv(GL_DEPTH_BITS, &depth_bits); + TRACE(": Z bits = %d\n", depth_bits); + switch (depth_bits) { + case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break; + case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_24; break; + case 32: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_32; break; + default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break; + } } BOOL diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 0b6f081b16d..d951bb563a2 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -322,6 +322,7 @@ struct IDirectDrawSurfaceImpl LPVOID tex_private; void (*lock_update_prev)(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags); void (*unlock_update_prev)(IDirectDrawSurfaceImpl* This, LPCRECT pRect); + BOOLEAN (*get_dirty_status)(IDirectDrawSurfaceImpl* This, LPCRECT pRect); }; /***************************************************************************** diff --git a/dlls/ddraw/dsurface/fakezbuffer.c b/dlls/ddraw/dsurface/fakezbuffer.c index cf858c83aa8..f871c0e8900 100644 --- a/dlls/ddraw/dsurface/fakezbuffer.c +++ b/dlls/ddraw/dsurface/fakezbuffer.c @@ -48,12 +48,34 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw); static ICOM_VTABLE(IDirectDrawSurface7) FakeZBuffer_IDirectDrawSurface7_VTable; +#ifdef HAVE_OPENGL +static void zbuffer_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags) +{ + /* Note that this does not do anything for now... At least it's not needed for Grim Fandango :-) */ +} + +static void zbuffer_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect) +{ + ((FakeZBuffer_DirectDrawSurfaceImpl *) This->private)->in_memory = TRUE; +} + +static BOOLEAN zbuffer_get_dirty_status(IDirectDrawSurfaceImpl* This, LPCRECT pRect) +{ + if (((FakeZBuffer_DirectDrawSurfaceImpl *) This->private)->in_memory == TRUE) { + ((FakeZBuffer_DirectDrawSurfaceImpl *) This->private)->in_memory = FALSE; + return TRUE; + } + return FALSE; +} +#endif + HRESULT FakeZBuffer_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This, IDirectDrawImpl *pDD, const DDSURFACEDESC2 *pDDSD) { HRESULT hr; - + BYTE zdepth = 16; /* Default value.. Should use the one from GL */ + assert(pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER); hr = Main_DirectDrawSurface_Construct(This, pDD, pDDSD); @@ -65,6 +87,33 @@ HRESULT FakeZBuffer_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This, This->final_release = FakeZBuffer_DirectDrawSurface_final_release; This->duplicate_surface = FakeZBuffer_DirectDrawSurface_duplicate_surface; +#ifdef HAVE_OPENGL + if (opengl_initialized) { + This->lock_update = zbuffer_lock_update; + This->unlock_update = zbuffer_unlock_update; + This->get_dirty_status = zbuffer_get_dirty_status; + } +#endif + + + /* Beginning of some D3D hacks :-) */ + if (This->surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH) { + zdepth = This->surface_desc.u2.dwMipMapCount; /* This is where the Z buffer depth is stored in 'old' versions */ + } + + if ((This->surface_desc.dwFlags & DDSD_PIXELFORMAT) == 0) { + This->surface_desc.dwFlags |= DDSD_PIXELFORMAT; + This->surface_desc.u4.ddpfPixelFormat.dwSize = sizeof(This->surface_desc.u4.ddpfPixelFormat); + This->surface_desc.u4.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER; + This->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth = zdepth; + } + if ((This->surface_desc.dwFlags & DDSD_PITCH) == 0) { + This->surface_desc.dwFlags |= DDSD_PITCH; + This->surface_desc.u1.lPitch = ((zdepth + 7) / 8) * This->surface_desc.dwWidth; + } + This->surface_desc.lpSurface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + This->surface_desc.u1.lPitch * This->surface_desc.dwHeight); + return DD_OK; } diff --git a/dlls/ddraw/dsurface/fakezbuffer.h b/dlls/ddraw/dsurface/fakezbuffer.h index a7867c6ee13..8c3d728322c 100644 --- a/dlls/ddraw/dsurface/fakezbuffer.h +++ b/dlls/ddraw/dsurface/fakezbuffer.h @@ -19,14 +19,9 @@ #ifndef DDRAW_DSURFACE_FAKEZBUFFER_H_INCLUDED #define DDRAW_DSURFACE_FAKEZBUFFER_H_INCLUDED -struct FakeZBuffer_DirectDrawSurfaceImpl_Part -{ - int dummy; -}; - typedef struct { - struct FakeZBuffer_DirectDrawSurfaceImpl_Part fakezbuffer; + BOOLEAN in_memory; } FakeZBuffer_DirectDrawSurfaceImpl; HRESULT diff --git a/dlls/ddraw/gl_api.h b/dlls/ddraw/gl_api.h index 9e95fd01734..c2e80f545d9 100644 --- a/dlls/ddraw/gl_api.h +++ b/dlls/ddraw/gl_api.h @@ -38,6 +38,7 @@ GL_API_FUNCTION(glClipPlane) GL_API_FUNCTION(glColor3f) GL_API_FUNCTION(glColor3ub) GL_API_FUNCTION(glColor4ub) +GL_API_FUNCTION(glColorMask) GL_API_FUNCTION(glColorMaterial) GL_API_FUNCTION(glCopyPixels) GL_API_FUNCTION(glCopyTexSubImage2D) @@ -76,11 +77,13 @@ GL_API_FUNCTION(glMatrixMode) GL_API_FUNCTION(glMultMatrixf) GL_API_FUNCTION(glNormal3f) GL_API_FUNCTION(glNormal3fv) +GL_API_FUNCTION(glOrtho) GL_API_FUNCTION(glPixelStorei) GL_API_FUNCTION(glPolygonMode) GL_API_FUNCTION(glPolygonOffset) GL_API_FUNCTION(glPopMatrix) GL_API_FUNCTION(glPushMatrix) +GL_API_FUNCTION(glRasterPos2i) GL_API_FUNCTION(glRasterPos3d) GL_API_FUNCTION(glReadBuffer) GL_API_FUNCTION(glReadPixels) diff --git a/dlls/ddraw/gl_private.h b/dlls/ddraw/gl_private.h index cb330e1c0d7..978ba7e257d 100644 --- a/dlls/ddraw/gl_private.h +++ b/dlls/ddraw/gl_private.h @@ -81,6 +81,7 @@ #define glColor3f pglColor3f #define glColor3ub pglColor3ub #define glColor4ub pglColor4ub +#define glColorMask pglColorMask #define glCopyPixels pglCopyPixels #define glCopyTexSubImage2D pglCopyTexSubImage2D #define glColorMaterial pglColorMaterial @@ -119,11 +120,13 @@ #define glMultMatrixf pglMultMatrixf #define glNormal3f pglNormal3f #define glNormal3fv pglNormal3fv +#define glOrtho pglOrtho #define glPixelStorei pglPixelStorei #define glPolygonMode pglPolygonMode #define glPolygonOffset pglPolygonOffset #define glPopMatrix pglPopMatrix #define glPushMatrix pglPushMatrix +#define glRasterPos2i pglRasterPos2i #define glRasterPos3d pglRasterPos3d #define glReadBuffer pglReadBuffer #define glReadPixels pglReadPixels diff --git a/dlls/ddraw/helper.c b/dlls/ddraw/helper.c index 52fb146e237..e20359e62c0 100644 --- a/dlls/ddraw/helper.c +++ b/dlls/ddraw/helper.c @@ -351,6 +351,7 @@ void DDRAW_dump_surface_desc(const DDSURFACEDESC2 *lpddsd) ME(DDSD_LINEARSIZE, DDRAW_dump_DWORD, u1.dwLinearSize), ME(DDSD_BACKBUFFERCOUNT, DDRAW_dump_DWORD, dwBackBufferCount), ME(DDSD_MIPMAPCOUNT, DDRAW_dump_DWORD, u2.dwMipMapCount), + ME(DDSD_ZBUFFERBITDEPTH, DDRAW_dump_DWORD, u2.dwMipMapCount), /* This is for 'old-style' D3D */ ME(DDSD_REFRESHRATE, DDRAW_dump_DWORD, u2.dwRefreshRate), ME(DDSD_ALPHABITDEPTH, DDRAW_dump_DWORD, dwAlphaBitDepth), ME(DDSD_LPSURFACE, DDRAW_dump_PTR, lpSurface),