wined3d: Implement IWineD3DDevice::SetDisplayMode.
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index a612f99..776fca6 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1316,7 +1316,10 @@
*(pPresentationParameters->BackBufferWidth),
*(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
-
+ /* For GetDisplayMode */
+ This->ddraw_width = devmode.dmPelsWidth;
+ This->ddraw_height = devmode.dmPelsHeight;
+ This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
}
@@ -1866,8 +1869,60 @@
}
HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
- FIXME("This call is a d3d7 merge stub. It will be implemented later\n");
- return WINED3DERR_INVALIDCALL;
+ DEVMODEW devmode;
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ LONG ret;
+
+ TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
+
+ /* Resize the screen even without a window:
+ * The app could have unset it with SetCooperativeLevel, but not called
+ * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
+ * but we don't have any hwnd
+ */
+
+ devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+ devmode.dmBitsPerPel = D3DFmtGetBpp(This, pMode->Format) * 8;
+ if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
+ devmode.dmPelsWidth = pMode->Width;
+ devmode.dmPelsHeight = pMode->Height;
+
+ devmode.dmDisplayFrequency = pMode->RefreshRate;
+ if (pMode->RefreshRate != 0) {
+ devmode.dmFields |= DM_DISPLAYFREQUENCY;
+ }
+
+ /* Only change the mode if necessary */
+ if( (This->ddraw_width == pMode->Width) &&
+ (This->ddraw_height == pMode->Height) &&
+ (This->ddraw_format == pMode->Format) &&
+ (pMode->RefreshRate == 0) ) {
+ return D3D_OK;
+ }
+
+ ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
+ if (ret != DISP_CHANGE_SUCCESSFUL) {
+ if(devmode.dmDisplayFrequency != 0) {
+ WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
+ devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
+ devmode.dmDisplayFrequency = 0;
+ ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
+ }
+ if(ret != DISP_CHANGE_SUCCESSFUL) {
+ return DDERR_INVALIDMODE;
+ }
+ }
+
+ /* Store the new values */
+ This->ddraw_width = pMode->Width;
+ This->ddraw_height = pMode->Height;
+ This->ddraw_format = pMode->Format;
+
+ /* Only do this with a window of course */
+ if(This->ddraw_window)
+ MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
+
+ return WINED3D_OK;
}
HRESULT WINAPI IWineD3DDeviceImpl_EnumZBufferFormats(IWineD3DDevice *iface, D3DCB_ENUMPIXELFORMATS Callback, void *Context) {
@@ -5265,13 +5320,29 @@
IWineD3DSwapChain *swapChain;
HRESULT hr;
- hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
- if (hr == WINED3D_OK) {
- hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
- IWineD3DSwapChain_Release(swapChain);
+ if(iSwapChain > 0) {
+ hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
+ if (hr == WINED3D_OK) {
+ hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
+ IWineD3DSwapChain_Release(swapChain);
+ } else {
+ FIXME("(%p) Error getting display mode\n", This);
+ }
} else {
- FIXME("(%p) Error getting display mode\n", This);
+ /* Don't read the real display mode,
+ but return the stored mode instead. X11 can't change the color
+ depth, and some apps are pretty angry if they SetDisplayMode from
+ 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
+
+ Also don't relay to the swapchain because with ddraw it's possible
+ that there isn't a swapchain at all */
+ pMode->Width = This->ddraw_width;
+ pMode->Height = This->ddraw_height;
+ pMode->Format = This->ddraw_format;
+ pMode->RefreshRate = 0;
+ hr = WINED3D_OK;
}
+
return hr;
}
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 9b1813a..788fbf0 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -1772,6 +1772,7 @@
IWineD3DDeviceImpl *object = NULL;
IWineD3DImpl *This = (IWineD3DImpl *)iface;
+ HDC hDC;
/* Validate the adapter number */
if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
@@ -1831,6 +1832,13 @@
/* set the state of the device to valid */
object->state = WINED3D_OK;
+ /* Get the initial screen setup for ddraw */
+ object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
+ object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
+ hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
+ object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
+ DeleteDC(hDC);
+
return WINED3D_OK;
create_device_error:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6754877..ebb2d86 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -567,6 +567,8 @@
/* DirectDraw stuff */
HWND ddraw_window;
IWineD3DSurface *ddraw_primary;
+ DWORD ddraw_width, ddraw_height;
+ WINED3DFORMAT ddraw_format;
} IWineD3DDeviceImpl;