Changelog: - GL state change optimizations - some more preparations for GL-accelerated Blts - added debug code to compute FPS (nice when adding optimizations) -- Lionel Ulmer - http://www.bbrox.org/
--- dlls/ddraw_CVS/d3d_private.h Fri Jun 6 21:24:12 2003 +++ dlls/ddraw/d3d_private.h Sat Jun 14 17:51:48 2003 @@ -205,6 +205,7 @@ D3DMATRIX *view_mat; D3DMATRIX *proj_mat; D3DMATRIX *tex_mat[MAX_TEXTURES]; + BOOLEAN tex_mat_is_identity[MAX_TEXTURES]; /* Current material used in D3D7 mode */ D3DMATERIAL7 current_material; --- dlls/ddraw_CVS/d3ddevice/mesa.c Sat Jun 14 11:16:57 2003 +++ dlls/ddraw/d3ddevice/mesa.c Sun Jun 15 02:06:46 2003 @@ -39,6 +39,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw); WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom); +#undef COMPUTE_FPS + /* x11drv GDI escapes */ #define X11DRV_ESCAPE 6789 enum x11drv_escape_codes @@ -99,6 +101,19 @@ return drawable; } +#ifdef COMPUTE_FPS + +#define MEASUREMENT_WINDOW 20 +#define NUMBER_OF_WINDOWS 4 + +static LONGLONG perf_freq; +static LONGLONG perf_storage[NUMBER_OF_WINDOWS]; +static LONGLONG prev_time = 0; +static unsigned int current_window; +static unsigned int measurements_in_window; +static unsigned int valid_windows; + +#endif static BOOL opengl_flip( LPVOID dev, LPVOID drawable) { @@ -114,6 +129,58 @@ gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL; glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable); LEAVE_GL(); + +#ifdef COMPUTE_FPS + { + LONGLONG current_time; + LONGLONG frame_duration; + QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time); + + if (prev_time != 0) { + LONGLONG total_time = 0; + int tot_meas; + + frame_duration = current_time - prev_time; + prev_time = current_time; + + perf_storage[current_window] += frame_duration; + measurements_in_window++; + + if (measurements_in_window >= MEASUREMENT_WINDOW) { + current_window++; + valid_windows++; + + if (valid_windows < NUMBER_OF_WINDOWS) { + int i; + tot_meas = valid_windows * MEASUREMENT_WINDOW; + for (i = 0; i < valid_windows; i++) { + total_time += perf_storage[i]; + } + } else { + int i; + tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW; + for (i = 0; i < NUMBER_OF_WINDOWS; i++) { + total_time += perf_storage[i]; + } + } + + DPRINTF("FPS : %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time); + + if (current_window >= NUMBER_OF_WINDOWS) { + current_window = 0; + } + perf_storage[current_window] = 0; + } + } else { + prev_time = current_time; + memset(perf_storage, 0, sizeof(perf_storage)); + current_window = 0; + valid_windows = 0; + measurements_in_window = 0; + QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq); + } + } +#endif return TRUE; } @@ -785,15 +852,20 @@ } else if ((vertex_transformed == TRUE) && (glThis->transform_state != GL_TRANSFORM_ORTHO)) { /* Set our orthographic projection */ - glThis->transform_state = GL_TRANSFORM_ORTHO; - d3ddevice_set_ortho(This); + if (glThis->transform_state != GL_TRANSFORM_ORTHO) { + glThis->transform_state = GL_TRANSFORM_ORTHO; + d3ddevice_set_ortho(This); + } } /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call if no fogging state change occured */ if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) { if (vertex_transformed == TRUE) { - glDisable(GL_FOG); + if (glThis->fogging != 0) { + glDisable(GL_FOG); + glThis->fogging = 0; + } /* Now check if our fog_table still corresponds to the current vertex color. Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */ if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) || @@ -817,20 +889,36 @@ glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1])); glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1])); } - glEnable(GL_FOG); + if (glThis->fogging == 0) { + glEnable(GL_FOG); + glThis->fogging = 1; + } } else { - glDisable(GL_FOG); + if (glThis->fogging != 0) { + glDisable(GL_FOG); + glThis->fogging = 0; + } } } } else { - glDisable(GL_FOG); + if (glThis->fogging != 0) { + glDisable(GL_FOG); + glThis->fogging = 0; + } } /* Handle the 'no-normal' case */ - if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) - glEnable(GL_LIGHTING); - else - glDisable(GL_LIGHTING); + if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) { + if (glThis->lighting == 0) { + glEnable(GL_LIGHTING); + glThis->lighting = 1; + } + } else { + if (glThis->lighting != 0) { + glDisable(GL_LIGHTING); + glThis->lighting = 0; + } + } /* Handle the code for pre-vertex material properties */ if (vertex_transformed == FALSE) { @@ -1540,6 +1628,7 @@ DWORD dwState) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); + IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This; const char *type; DWORD prev_state; @@ -1685,7 +1774,10 @@ /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */ if (dwState != D3DTOP_DISABLE) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + if (glThis->current_tex_env != GL_COMBINE_EXT) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + glThis->current_tex_env = GL_COMBINE_EXT; + } } /* Now set up the operand correctly */ @@ -2148,17 +2240,25 @@ TRACE(" - dvMinZ = %f dvMaxZ = %f\n", lpData->dvMinZ, lpData->dvMaxZ); } - This->active_viewport = *lpData; - ENTER_GL(); /* Set the viewport */ - glDepthRange(lpData->dvMinZ, lpData->dvMaxZ); - glViewport(lpData->dwX, - This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY), - lpData->dwWidth, lpData->dwHeight); + if ((lpData->dvMinZ != This->active_viewport.dvMinZ) || + (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) { + glDepthRange(lpData->dvMinZ, lpData->dvMaxZ); + } + if ((lpData->dwX != This->active_viewport.dwX) || + (lpData->dwY != This->active_viewport.dwY) || + (lpData->dwWidth != This->active_viewport.dwWidth) || + (lpData->dwHeight != This->active_viewport.dwHeight)) { + glViewport(lpData->dwX, + This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY), + lpData->dwWidth, lpData->dwHeight); + } LEAVE_GL(); + + This->active_viewport = *lpData; return DD_OK; } @@ -2382,7 +2482,6 @@ DWORD dwStencil) { IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This; - GLboolean ztest; GLbitfield bitfield = 0; D3DRECT rect; int i; @@ -2420,22 +2519,32 @@ if (dwFlags & D3DCLEAR_ZBUFFER) { bitfield |= GL_DEPTH_BUFFER_BIT; - glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest); - glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */ - glClearDepth(dvZ); + if (glThis->depth_mask == FALSE) { + glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */ + } + if (dvZ != glThis->prev_clear_Z) { + glClearDepth(dvZ); + glThis->prev_clear_Z = dvZ; + } TRACE(" depth value : %f\n", dvZ); } if (dwFlags & D3DCLEAR_STENCIL) { bitfield |= GL_STENCIL_BUFFER_BIT; - glClearStencil(dwStencil); + if (dwStencil != glThis->prev_clear_stencil) { + glClearStencil(dwStencil); + glThis->prev_clear_stencil = dwStencil; + } TRACE(" stencil value : %ld\n", dwStencil); } if (dwFlags & D3DCLEAR_TARGET) { bitfield |= GL_COLOR_BUFFER_BIT; - glClearColor(((dwColor >> 16) & 0xFF) / 255.0, - ((dwColor >> 8) & 0xFF) / 255.0, - ((dwColor >> 0) & 0xFF) / 255.0, - ((dwColor >> 24) & 0xFF) / 255.0); + if (dwColor != glThis->prev_clear_color) { + glClearColor(((dwColor >> 16) & 0xFF) / 255.0, + ((dwColor >> 8) & 0xFF) / 255.0, + ((dwColor >> 0) & 0xFF) / 255.0, + ((dwColor >> 24) & 0xFF) / 255.0); + glThis->prev_clear_color = dwColor; + } TRACE(" color value (ARGB) : %08lx\n", dwColor); } @@ -2448,7 +2557,7 @@ glDisable(GL_SCISSOR_TEST); if (dwFlags & D3DCLEAR_ZBUFFER) { - if (ztest == 0) glDepthMask(ztest); + if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE); } LEAVE_GL(); @@ -2761,10 +2870,20 @@ /* No multi-texturing support for now ... */ glMatrixMode(GL_TEXTURE); glLoadMatrixf((float *) This->tex_mat[tex_stage]); + if (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE))) { + This->tex_mat_is_identity[tex_stage] = FALSE; + } else { + This->tex_mat_is_identity[tex_stage] = TRUE; + } } } else { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + if (tex_stage == 0) { + if (This->tex_mat_is_identity[tex_stage] == FALSE) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + This->tex_mat_is_identity[tex_stage] = TRUE; + } + } } } } @@ -2933,39 +3052,133 @@ #define UNLOCK_TEX_SIZE 256 +#define DEPTH_RANGE_BIT (0x00000001 << 0) +#define VIEWPORT_BIT (0x00000001 << 1) + +static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) { + IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev; + DWORD opt_bitmap = 0x00000000; + + if (gl_d3d_dev->unlock_tex == 0) { + glGenTextures(1, &gl_d3d_dev->unlock_tex); + glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex); + *initial = TRUE; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } else { + glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex); + } + if (d3d_dev->tex_mat_is_identity[0] == FALSE) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + } + + if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) { + gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO; + d3ddevice_set_ortho(d3d_dev); + } + + if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST); + if ((gl_d3d_dev->current_bound_texture[0] == NULL) || + (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)) + glEnable(GL_TEXTURE_2D); + glEnable(GL_SCISSOR_TEST); + if ((d3d_dev->active_viewport.dvMinZ != 0.0) || + (d3d_dev->active_viewport.dvMaxZ != 1.0)) { + glDepthRange(0.0, 1.0); + opt_bitmap |= DEPTH_RANGE_BIT; + } + if ((d3d_dev->active_viewport.dwX != 0) || + (d3d_dev->active_viewport.dwY != 0) || + (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) || + (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) { + glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight); + opt_bitmap |= VIEWPORT_BIT; + } + glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom, + pRect->right - pRect->left, pRect->bottom - pRect->top); + if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING); + 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); + } + } else { + if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST); + } + if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST); + if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND); + if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG); + if (gl_d3d_dev->current_tex_env != GL_REPLACE) + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + return opt_bitmap; +} + +static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) { + IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev; + + /* And restore all the various states modified by this code */ + if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST); + if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING); + if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0)) + glEnable(GL_ALPHA_TEST); + 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->stencil_test != 0) glEnable(GL_STENCIL_TEST); + if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE); + if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND); + if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG); + glDisable(GL_SCISSOR_TEST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env); + if (opt_bitmap & DEPTH_RANGE_BIT) { + glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ); + } + if (opt_bitmap & VIEWPORT_BIT) { + glViewport(d3d_dev->active_viewport.dwX, + d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY), + d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight); + } + if (d3d_dev->tex_mat_is_identity[0] == FALSE) { + d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED); + } + + /* This is a hack to prevent querying the current texture from GL. Basically, at the next + DrawPrimitive call, this will bind the correct texture to this stage. */ + gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001; + if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D); +} + static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) { RECT loc_rect; IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev; - GLint depth_test, alpha_test, cull_face, lighting, tex_env, blend, stencil_test, fog; int x, y; BOOLEAN initial = FALSE; - + DWORD opt_bitmap; + /* Note : no need here to lock the 'device critical section' as we are already protected by the GL critical section. */ if (pRect == NULL) { loc_rect.top = 0; loc_rect.left = 0; - loc_rect.bottom = surf->surface_desc.dwHeight; - loc_rect.right = surf->surface_desc.dwWidth; + loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight; + loc_rect.right = d3d_dev->surface->surface_desc.dwWidth; pRect = &loc_rect; } TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom); - /* This is a hack to prevent querying the current texture from GL */ - gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001; - - if (gl_d3d_dev->unlock_tex == 0) { - glGenTextures(1, &gl_d3d_dev->unlock_tex); - glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex); - initial = TRUE; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } else { - glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex); - } - + opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial); if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format, initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) { @@ -2973,36 +3186,6 @@ return; } - glGetIntegerv(GL_DEPTH_TEST, &depth_test); - glGetIntegerv(GL_ALPHA_TEST, &alpha_test); - glGetIntegerv(GL_STENCIL_TEST, &stencil_test); - glGetIntegerv(GL_CULL_FACE, &cull_face); - glGetIntegerv(GL_LIGHTING, &lighting); - glGetIntegerv(GL_BLEND, &blend); - glGetIntegerv(GL_FOG, &fog); - glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - /* TODO: scissor test if ever we use it ! */ - - gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO; - d3ddevice_set_ortho(d3d_dev); - - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - glEnable(GL_SCISSOR_TEST); - glDepthRange(0.0, 1.0); - glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight); - glScissor(pRect->left, surf->surface_desc.dwHeight - pRect->bottom, - pRect->right - pRect->left, pRect->bottom - pRect->top); - glDisable(GL_LIGHTING); - glDisable(GL_CULL_FACE); - glDisable(GL_ALPHA_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_BLEND); - glDisable(GL_FOG); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) { for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) { /* First, upload the texture... */ @@ -3030,24 +3213,8 @@ } upload_surface_to_tex_memory_release(); + d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE); - /* And restore all the various states modified by this code */ - if (depth_test != 0) glEnable(GL_DEPTH_TEST); - if (lighting != 0) glEnable(GL_LIGHTING); - if (alpha_test != 0) glEnable(GL_ALPHA_TEST); - if (stencil_test != 0) glEnable(GL_STENCIL_TEST); - if (cull_face != 0) glEnable(GL_CULL_FACE); - if (blend != 0) glEnable(GL_BLEND); - if (fog != 0) glEnable(GL_FOG); - glDisable(GL_SCISSOR_TEST); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env); - glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ); - glViewport(d3d_dev->active_viewport.dwX, - d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY), - d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight); - d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED); #if 0 /* I keep this code here as it's very useful to debug :-) */ { @@ -3251,6 +3418,7 @@ for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) { object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float)); memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float)); + object->tex_mat_is_identity[tex_num] = TRUE; } /* Initialisation */ @@ -3269,8 +3437,24 @@ object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane)); glHint(GL_FOG_HINT,GL_NICEST); - + + /* Initialize the various GL contexts to be in sync with what we store locally */ + glClearDepth(0.0); + glClearStencil(0); glClearColor(0.0, 0.0, 0.0, 0.0); + glDepthMask(GL_TRUE); + gl_object->depth_mask = TRUE; + glEnable(GL_DEPTH_TEST); + gl_object->depth_test = TRUE; + glDisable(GL_ALPHA_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_BLEND); + glDisable(GL_FOG); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + gl_object->current_tex_env = GL_REPLACE; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDrawBuffer(buffer); glReadBuffer(buffer); --- dlls/ddraw_CVS/ddraw/main.c Fri Jun 6 21:24:12 2003 +++ dlls/ddraw/ddraw/main.c Sat Jun 14 12:31:32 2003 @@ -368,7 +368,7 @@ } /* Check also for the MIPMAP / MIPMAPCOUNT flags. - TODO: check if Windows 'auto-builds' somehow the mip-map levels */ + As checked on Windows, this is the right behaviour. No mipmaps seem to be generated. */ if (((ddsd.dwFlags & DDSD_MIPMAPCOUNT) == 0) && ((ddsd.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != 0)) { ddsd.dwFlags |= DDSD_MIPMAPCOUNT; --- dlls/ddraw_CVS/mesa.c Fri Jun 6 21:24:12 2003 +++ dlls/ddraw/mesa.c Sun Jun 15 01:01:15 2003 @@ -147,12 +147,15 @@ updated either.. No idea about what happens in D3D. Maybe replacing the Z function by ALWAYS would be a better idea. */ - if (dwRenderState == D3DZB_TRUE) + if ((dwRenderState == D3DZB_TRUE) && (glThis->depth_test == FALSE)) { glEnable(GL_DEPTH_TEST); - else if (dwRenderState == D3DZB_FALSE) + glThis->depth_test = TRUE; + } else if ((dwRenderState == D3DZB_FALSE) && (glThis->depth_test == TRUE)) { glDisable(GL_DEPTH_TEST); - else { + glThis->depth_test = FALSE; + } else if (glThis->depth_test == FALSE) { glEnable(GL_DEPTH_TEST); + glThis->depth_test = TRUE; WARN(" w-buffering not supported.\n"); } break; @@ -187,17 +190,19 @@ break; case D3DRENDERSTATE_ZWRITEENABLE: /* 14 */ - if (dwRenderState) + if ((dwRenderState != FALSE) && (glThis->depth_mask == FALSE)) glDepthMask(GL_TRUE); - else + else if ((dwRenderState == FALSE) && (glThis->depth_mask != FALSE)) glDepthMask(GL_FALSE); + glThis->depth_mask = dwRenderState; break; case D3DRENDERSTATE_ALPHATESTENABLE: /* 15 */ - if (dwRenderState) + if ((dwRenderState != 0) && (glThis->alpha_test == FALSE)) glEnable(GL_ALPHA_TEST); - else + else if ((dwRenderState == 0) && (glThis->alpha_test != FALSE)) glDisable(GL_ALPHA_TEST); + glThis->alpha_test = dwRenderState; break; case D3DRENDERSTATE_TEXTUREMAG: { /* 17 */ @@ -249,13 +254,22 @@ switch ((D3DTEXTUREBLEND) dwRenderState) { case D3DTBLEND_DECAL: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + if (glThis->current_tex_env != GL_REPLACE) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glThis->current_tex_env = GL_REPLACE; + } break; case D3DTBLEND_DECALALPHA: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + if (glThis->current_tex_env != GL_REPLACE) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glThis->current_tex_env = GL_DECAL; + } break; case D3DTBLEND_MODULATE: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if (glThis->current_tex_env != GL_MODULATE) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glThis->current_tex_env = GL_MODULATE; + } break; case D3DTBLEND_MODULATEALPHA: IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); @@ -273,15 +287,24 @@ case D3DRENDERSTATE_CULLMODE: /* 22 */ switch ((D3DCULL) dwRenderState) { case D3DCULL_NONE: - glDisable(GL_CULL_FACE); + if (glThis->cull_face != 0) { + glDisable(GL_CULL_FACE); + glThis->cull_face = 0; + } break; case D3DCULL_CW: - glEnable(GL_CULL_FACE); + if (glThis->cull_face == 0) { + glEnable(GL_CULL_FACE); + glThis->cull_face = 1; + } glFrontFace(GL_CCW); glCullFace(GL_BACK); break; case D3DCULL_CCW: - glEnable(GL_CULL_FACE); + if (glThis->cull_face == 0) { + glEnable(GL_CULL_FACE); + glThis->cull_face = 1; + } glFrontFace(GL_CW); glCullFace(GL_BACK); break; @@ -308,11 +331,12 @@ break; case D3DRENDERSTATE_ALPHABLENDENABLE: /* 27 */ - if (dwRenderState) { + if ((dwRenderState != 0) && (glThis->blending == 0)) { glEnable(GL_BLEND); - } else { + } else if ((dwRenderState == 0) && (glThis->blending != 0)) { glDisable(GL_BLEND); } + glThis->blending = dwRenderState; break; case D3DRENDERSTATE_FOGENABLE: /* 28 */ @@ -357,10 +381,12 @@ case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */ /* This needs to be fixed. */ - if (dwRenderState) + if ((dwRenderState != 0) && (glThis->blending == 0)) { glEnable(GL_BLEND); - else + } else if ((dwRenderState == 0) && (glThis->blending != 0)) { glDisable(GL_BLEND); + } + glThis->blending = dwRenderState; break; case D3DRENDERSTATE_ZBIAS: /* 47 */ @@ -381,10 +407,11 @@ break; case D3DRENDERSTATE_STENCILENABLE: /* 52 */ - if (dwRenderState) + if ((dwRenderState != 0) && (glThis->stencil_test == 0)) glEnable(GL_STENCIL_TEST); - else + else if ((dwRenderState == 0) && (glThis->stencil_test != 0)) glDisable(GL_STENCIL_TEST); + glThis->stencil_test = dwRenderState; break; case D3DRENDERSTATE_STENCILFAIL: /* 53 */ @@ -441,10 +468,7 @@ break; case D3DRENDERSTATE_LIGHTING: /* 137 */ - if (dwRenderState) - glEnable(GL_LIGHTING); - else - glDisable(GL_LIGHTING); + /* Nothing to do, only storage matters... */ break; case D3DRENDERSTATE_AMBIENT: { /* 139 */ --- dlls/ddraw_CVS/mesa_private.h Fri Jun 6 21:24:12 2003 +++ dlls/ddraw/mesa_private.h Sat Jun 14 17:44:07 2003 @@ -136,6 +136,13 @@ RECT lock_rect[2]; /* This is just here to print-out a nice warning if we have two successive locks */ BOOLEAN lock_rect_valid[2]; + + /* This is used to optimize some stuff */ + DWORD prev_clear_color; + DWORD prev_clear_stencil; + D3DVALUE prev_clear_Z; + BOOLEAN depth_mask, depth_test, alpha_test, stencil_test, cull_face, lighting, blending, fogging; + GLenum current_tex_env; } IDirect3DDeviceGLImpl; /* This is for the OpenGL additions... */ @@ -179,6 +186,9 @@ BOOLEAN need_to_alloc, BOOLEAN need_alpha_ck, DWORD tex_width, DWORD tex_height); extern HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, void **temp_buffer); extern HRESULT upload_surface_to_tex_memory_release(void); + +/* Some utilities functions needed to be shared.. */ +extern GLenum convert_D3D_compare_to_GL(D3DCMPFUNC dwRenderState) ; #endif /* HAVE_OPENGL */