Apparently, DungeonSiege loves to play with viewports and Clear rectangles (which were not supported correctly in the D3D7 code as they were never different from full screen). Changelog: - added support for non-full screen viewports and clearing -- Lionel Ulmer - http://www.bbrox.org/
--- dlls/ddraw_CVS/d3ddevice/main.c Fri May 16 09:51:47 2003 +++ dlls/ddraw/d3ddevice/main.c Sun May 18 20:52:03 2003 @@ -1087,25 +1087,8 @@ /* Activate this viewport */ This->current_viewport->active_device = This; - This->current_viewport->activate(This->current_viewport); + This->current_viewport->activate(This->current_viewport); - /* And copy the values in the structure used by the device */ - if (This->current_viewport->use_vp2) { - This->active_viewport.dwX = This->current_viewport->viewports.vp2.dwX; - This->active_viewport.dwY = This->current_viewport->viewports.vp2.dwY; - This->active_viewport.dwHeight = This->current_viewport->viewports.vp2.dwHeight; - This->active_viewport.dwWidth = This->current_viewport->viewports.vp2.dwWidth; - This->active_viewport.dvMinZ = This->current_viewport->viewports.vp2.dvMinZ; - This->active_viewport.dvMaxZ = This->current_viewport->viewports.vp2.dvMaxZ; - } else { - This->active_viewport.dwX = This->current_viewport->viewports.vp1.dwX; - This->active_viewport.dwY = This->current_viewport->viewports.vp1.dwY; - This->active_viewport.dwHeight = This->current_viewport->viewports.vp1.dwHeight; - This->active_viewport.dwWidth = This->current_viewport->viewports.vp1.dwWidth; - This->active_viewport.dvMinZ = This->current_viewport->viewports.vp1.dvMinZ; - This->active_viewport.dvMaxZ = This->current_viewport->viewports.vp1.dvMaxZ; - } - return DD_OK; } --- dlls/ddraw_CVS/d3ddevice/mesa.c Sun May 18 23:27:25 2003 +++ dlls/ddraw/d3ddevice/mesa.c Sun May 18 23:37:45 2003 @@ -2163,24 +2163,51 @@ TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation); - if (dwIndex>=This->max_clipping_planes) { + if (dwIndex >= This->max_clipping_planes) { return DDERR_INVALIDPARAMS; } TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] ); - memcpy( This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4])); + memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4])); plane[0] = pPlaneEquation[0]; plane[1] = pPlaneEquation[1]; plane[2] = pPlaneEquation[2]; plane[3] = pPlaneEquation[3]; /* XXX: is here also code needed to handle the transformation of the world? */ - glClipPlane( GL_CLIP_PLANE0+dwIndex, (const GLdouble*)(&plane) ); + glClipPlane( GL_CLIP_PLANE0 + dwIndex, (const GLdouble*) (&plane) ); return D3D_OK; } +HRESULT WINAPI +GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface, + LPD3DVIEWPORT7 lpData) +{ + ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); + TRACE("(%p/%p)->(%p)\n", This, iface, lpData); + + if (TRACE_ON(ddraw)) { + TRACE(" viewport is : \n"); + TRACE(" - dwX = %ld dwY = %ld\n", + lpData->dwX, lpData->dwY); + TRACE(" - dwWidth = %ld dwHeight = %ld\n", + lpData->dwWidth, lpData->dwHeight); + TRACE(" - dvMinZ = %f dvMaxZ = %f\n", + lpData->dvMinZ, lpData->dvMaxZ); + } + This->active_viewport = *lpData; + + /* Set the viewport */ + glDepthRange(lpData->dvMinZ, lpData->dvMaxZ); + glViewport(lpData->dwX, + This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY), + lpData->dwWidth, lpData->dwHeight); + + return DD_OK; +} + #if !defined(__STRICT_ANSI__) && defined(__GNUC__) # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun)) #else @@ -2203,7 +2230,7 @@ XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear, XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform, XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform, - XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport, + XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport, XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform, XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport, XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial, @@ -2403,6 +2430,8 @@ GLbitfield bitfield = 0; GLint old_stencil_clear_value; GLfloat old_color_clear_value[4]; + D3DRECT rect; + int i; TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil); if (TRACE_ON(ddraw)) { @@ -2415,10 +2444,16 @@ } } - if (dwCount > 1) { - WARN(" Warning, this function only for now clears the whole screen...\n"); + if (dwCount == 0) { + /* Not sure if this is really needed... */ + dwCount = 1; + rect.u1.x1 = 0; + rect.u2.y1 = 0; + rect.u3.x2 = This->surface->surface_desc.dwWidth; + rect.u4.y2 = This->surface->surface_desc.dwHeight; + lpRects = ▭ } - + /* Clears the screen */ ENTER_GL(); if (dwFlags & D3DCLEAR_ZBUFFER) { @@ -2444,8 +2479,14 @@ ((dwColor >> 24) & 0xFF) / 255.0); TRACE(" color value (ARGB) : %08lx\n", dwColor); } - - glClear(bitfield); + + glEnable(GL_SCISSOR_TEST); + for (i = 0; i < dwCount; i++) { + glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2, + lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1); + glClear(bitfield); + } + glDisable(GL_SCISSOR_TEST); if (dwFlags & D3DCLEAR_ZBUFFER) { glDepthMask(ztest); @@ -2477,7 +2518,7 @@ /* This is easy to handle for the D3D Device... */ DWORD color = lpbltfx->u5.dwFillColor; TRACE(" executing D3D Device override.\n"); - d3ddevice_clear(This->d3ddevice, 0, NULL, D3DCLEAR_TARGET, color, 0.0, 0x00000000); + d3ddevice_clear(This->d3ddevice, 1, rdst, D3DCLEAR_TARGET, color, 0.0, 0x00000000); return DD_OK; } return DDERR_INVALIDPARAMS; --- dlls/ddraw_CVS/d3dviewport.c Thu Jan 30 22:07:23 2003 +++ dlls/ddraw/d3dviewport.c Sun May 18 20:54:28 2003 @@ -34,7 +34,8 @@ static void activate(IDirect3DViewportImpl* This) { IDirect3DLightImpl* light; - + D3DVIEWPORT7 vp; + /* Activate all the lights associated with this context */ light = This->lights; @@ -42,6 +43,26 @@ light->activate(light); light = light->next; } + + /* And copy the values in the structure used by the device */ + if (This->use_vp2) { + vp.dwX = This->viewports.vp2.dwX; + vp.dwY = This->viewports.vp2.dwY; + vp.dwHeight = This->viewports.vp2.dwHeight; + vp.dwWidth = This->viewports.vp2.dwWidth; + vp.dvMinZ = This->viewports.vp2.dvMinZ; + vp.dvMaxZ = This->viewports.vp2.dvMaxZ; + } else { + vp.dwX = This->viewports.vp1.dwX; + vp.dwY = This->viewports.vp1.dwY; + vp.dwHeight = This->viewports.vp1.dwHeight; + vp.dwWidth = This->viewports.vp1.dwWidth; + vp.dvMinZ = This->viewports.vp1.dvMinZ; + vp.dvMaxZ = This->viewports.vp1.dvMaxZ; + } + + /* And also set the viewport */ + IDirect3DDevice7_SetViewport(ICOM_INTERFACE(This->active_device, IDirect3DDevice7), &vp); }