Hi all, Please disregard my previous mail about the critical sections... It was my fault, playing with two different sections and not taking care of the order I entered them (and thus created a nice deadlock). With this patch, I played DungeonSiege for quite some time without any graphical glitches related to threading (there are still some texturing issues). And as DungeonSiege is the most ugly game I know related to threading, I suppose it must work relatively well now :-) Changelog: - remove some extraneous saving of the read buffer settings - cleaned-up the GL / device critical section handling -- Lionel Ulmer - http://www.bbrox.org/
--- dlls/ddraw_CVS/d3ddevice/mesa.c Mon May 26 13:50:09 2003 +++ dlls/ddraw/d3ddevice/mesa.c Mon May 26 14:36:43 2003 @@ -1099,27 +1099,24 @@ IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This; int num_active_stages = 0; + /* This is to prevent 'thread contention' between a thread locking the device and another + doing 3D display on it... */ + EnterCriticalSection(&(This->crit)); + ENTER_GL(); if (glThis->state == SURFACE_MEMORY_DIRTY) { This->flush_to_framebuffer(This, NULL, glThis->lock_surf); } - LEAVE_GL(); glThis->state = SURFACE_GL; /* Compute the number of active texture stages */ while (This->current_texture[num_active_stages] != NULL) num_active_stages++; - /* This is to prevent 'thread contention' between a thread locking the device and another - doing 3D display on it... */ - EnterCriticalSection(&(This->crit)); - if (TRACE_ON(ddraw)) { TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType); } - ENTER_GL(); - /* Just a hack for now.. Will have to find better algorithm :-/ */ if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) { vertex_lighted = TRUE; @@ -1965,9 +1962,7 @@ } if ((dwState & 0xFF) != D3DTTFF_DISABLE) { - LEAVE_GL(); This->matrices_updated(This, TEXMAT0_CHANGED << dwStage); - ENTER_GL(); } if (handled == TRUE) { @@ -2815,7 +2810,6 @@ /* If the surface is already in memory, no need to do anything here... */ GLenum buffer_type; GLenum buffer_color; - GLenum prev_read; RECT loc_rect; int y; char *dst; @@ -2826,18 +2820,6 @@ may only write to the device... But when we will blit it back to the screen, we need also to blit correctly the parts the application did not overwrite... */ - ENTER_GL(); - - glGetIntegerv(GL_READ_BUFFER, &prev_read); - glFlush(); - - if (is_front == TRUE) - /* Application wants to lock the front buffer */ - glReadBuffer(GL_FRONT); - else - /* Application wants to lock the back buffer */ - glReadBuffer(GL_BACK); - if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) && (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) && (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) && @@ -2855,10 +2837,18 @@ glPixelStorei(GL_PACK_SWAP_BYTES, TRUE); } else { ERR(" unsupported pixel format at device locking.\n"); - LEAVE_GL(); return; } + ENTER_GL(); + + if (is_front == TRUE) + /* Application wants to lock the front buffer */ + glReadBuffer(GL_FRONT); + else + /* Application wants to lock the back buffer */ + glReadBuffer(GL_BACK); + /* Just a hack while waiting for proper rectangle support */ pRect = NULL; if (pRect == NULL) { @@ -2881,7 +2871,6 @@ dst += This->surface_desc.u1.lPitch; } - glReadBuffer(prev_read); glPixelStorei(GL_PACK_SWAP_BYTES, FALSE); if (is_front) @@ -2919,8 +2908,8 @@ GLint tex_state; int x, y; - /* This is to prevent another thread to actually lock the buffer while we flush it on screen */ - EnterCriticalSection(&(d3d_dev->crit)); + /* Note : no need here to lock the 'device critical section' as we are already protected by + the GL critical section. */ loc_rect.top = 0; loc_rect.left = 0; @@ -2962,7 +2951,6 @@ glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE); } else { ERR(" unsupported pixel format at frame buffer flush.\n"); - LeaveCriticalSection(&(d3d_dev->crit)); return; } @@ -2972,6 +2960,8 @@ 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(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom, loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top); @@ -3039,9 +3029,11 @@ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_tex); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env); - LEAVE_GL(); + 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); - ENTER_GL(); #if 0 /* I keep this code here as it's very useful to debug :-) */ { @@ -3056,9 +3048,6 @@ } } #endif - - /* And leave the critical section... */ - LeaveCriticalSection(&(d3d_dev->crit)); } static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect) @@ -3236,9 +3225,7 @@ /* Initialisation */ TRACE(" setting current context\n"); - LEAVE_GL(); object->set_context(object); - ENTER_GL(); TRACE(" current context set\n"); /* allocate the clipping planes */ --- dlls/ddraw_CVS/mesa.c Sat May 24 18:00:35 2003 +++ dlls/ddraw/mesa.c Mon May 26 14:06:20 2003 @@ -101,11 +101,9 @@ case D3DRENDERSTATE_TEXTUREHANDLE: { /* 1 */ IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState; - LEAVE_GL(); IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7), 0, ICOM_INTERFACE(tex, IDirectDrawSurface7)); - ENTER_GL(); } break; case D3DRENDERSTATE_TEXTUREADDRESSU: /* 44 */ @@ -117,11 +115,9 @@ else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSU) d3dTexStageStateType = D3DTSS_ADDRESSU; else d3dTexStageStateType = D3DTSS_ADDRESSV; - LEAVE_GL(); IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, d3dTexStageStateType, dwRenderState); - ENTER_GL(); } break; case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */ @@ -218,9 +214,7 @@ } if (tex_mag != 0xFFFFFFFF) { - LEAVE_GL(); IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MAGFILTER, tex_mag); - ENTER_GL(); } } break; @@ -239,9 +233,7 @@ } if (tex_min != 0xFFFFFFFF) { - LEAVE_GL(); IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MINFILTER, tex_min); - ENTER_GL(); } } break;