2 * Wine X11drv display settings functions
4 * Copyright 2003 Alexander James Pasadyn
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(x11settings
);
34 * The DDHALMODEINFO type is used to hold all the mode information.
35 * This is done because the array of DDHALMODEINFO structures must be
36 * created for use by DirectDraw anyway.
38 static LPDDHALMODEINFO dd_modes
= NULL
;
39 static unsigned int dd_mode_count
= 0;
40 static unsigned int dd_max_modes
= 0;
41 static int dd_mode_default
= 0;
42 static const unsigned int depths
[] = {8, 16, 32};
44 /* pointers to functions that actually do the hard stuff */
45 static int (*pGetCurrentMode
)(void);
46 static LONG (*pSetCurrentMode
)(int mode
);
47 static const char *handler_name
;
50 * Set the handlers for resolution changing functions
51 * and initialize the master list of modes
53 LPDDHALMODEINFO
X11DRV_Settings_SetHandlers(const char *name
,
60 pGetCurrentMode
= pNewGCM
;
61 pSetCurrentMode
= pNewSCM
;
62 TRACE("Resolution settings now handled by: %s\n", name
);
64 /* leave room for other depths */
65 dd_max_modes
= (3+1)*(nmodes
);
67 dd_max_modes
= nmodes
;
71 TRACE("Destroying old display modes array\n");
72 HeapFree(GetProcessHeap(), 0, dd_modes
);
74 dd_modes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DDHALMODEINFO
) * dd_max_modes
);
76 TRACE("Initialized new display modes array\n");
80 /* Add one mode to the master list */
81 void X11DRV_Settings_AddOneMode(unsigned int width
, unsigned int height
, unsigned int bpp
, unsigned int freq
)
83 LPDDHALMODEINFO info
= &(dd_modes
[dd_mode_count
]);
84 DWORD dwBpp
= screen_depth
;
85 if (dd_mode_count
>= dd_max_modes
)
87 ERR("Maximum modes (%d) exceeded\n", dd_max_modes
);
90 if (dwBpp
== 24) dwBpp
= 32;
91 if (bpp
== 0) bpp
= dwBpp
;
92 info
->dwWidth
= width
;
93 info
->dwHeight
= height
;
94 info
->wRefreshRate
= freq
;
100 info
->dwBBitMask
= 0;
101 info
->dwAlphaBitMask
= 0;
102 TRACE("initialized mode %d: %dx%dx%d @%d Hz (%s)\n",
103 dd_mode_count
, width
, height
, bpp
, freq
, handler_name
);
107 /* copy all the current modes using the other color depths */
108 void X11DRV_Settings_AddDepthModes(void)
111 int existing_modes
= dd_mode_count
;
112 DWORD dwBpp
= screen_depth
;
113 if (dwBpp
== 24) dwBpp
= 32;
116 if (depths
[j
] != dwBpp
)
118 for (i
=0; i
< existing_modes
; i
++)
120 X11DRV_Settings_AddOneMode(dd_modes
[i
].dwWidth
, dd_modes
[i
].dwHeight
,
121 depths
[j
], dd_modes
[i
].wRefreshRate
);
127 /* set the default mode */
128 void X11DRV_Settings_SetDefaultMode(int mode
)
130 dd_mode_default
= mode
;
133 /* return the number of modes that are initialized */
134 unsigned int X11DRV_Settings_GetModeCount(void)
136 return dd_mode_count
;
139 /***********************************************************************
140 * Default handlers if resolution switching is not enabled
143 static int X11DRV_nores_GetCurrentMode(void)
147 static LONG
X11DRV_nores_SetCurrentMode(int mode
)
149 TRACE("Ignoring mode change request\n");
150 return DISP_CHANGE_FAILED
;
152 /* default handler only gets the current X desktop resolution */
153 void X11DRV_Settings_Init(void)
155 X11DRV_Settings_SetHandlers("NoRes",
156 X11DRV_nores_GetCurrentMode
,
157 X11DRV_nores_SetCurrentMode
,
159 X11DRV_Settings_AddOneMode(screen_width
, screen_height
, 0, 60);
162 /***********************************************************************
163 * EnumDisplaySettingsEx (X11DRV.@)
166 BOOL
X11DRV_EnumDisplaySettingsEx( LPCWSTR name
, DWORD n
, LPDEVMODEW devmode
, DWORD flags
)
168 DWORD dwBpp
= screen_depth
;
169 if (dwBpp
== 24) dwBpp
= 32;
170 devmode
->dmDisplayFlags
= 0;
171 devmode
->dmDisplayFrequency
= 0;
172 devmode
->dmSize
= sizeof(DEVMODEW
);
173 if (n
== ENUM_CURRENT_SETTINGS
)
175 TRACE("mode %d (current) -- getting current mode (%s)\n", n
, handler_name
);
176 n
= pGetCurrentMode();
178 if (n
== ENUM_REGISTRY_SETTINGS
)
180 TRACE("mode %d (registry) -- getting default mode (%s)\n", n
, handler_name
);
183 if (n
< dd_mode_count
)
185 devmode
->dmPelsWidth
= dd_modes
[n
].dwWidth
;
186 devmode
->dmPelsHeight
= dd_modes
[n
].dwHeight
;
187 devmode
->dmBitsPerPel
= dd_modes
[n
].dwBPP
;
188 devmode
->dmDisplayFrequency
= dd_modes
[n
].wRefreshRate
;
189 devmode
->dmFields
= (DM_PELSWIDTH
|DM_PELSHEIGHT
|DM_BITSPERPEL
);
190 if (devmode
->dmDisplayFrequency
)
192 devmode
->dmFields
|= DM_DISPLAYFREQUENCY
;
193 TRACE("mode %d -- %dx%dx%dbpp @%d Hz (%s)\n", n
,
194 devmode
->dmPelsWidth
, devmode
->dmPelsHeight
, devmode
->dmBitsPerPel
,
195 devmode
->dmDisplayFrequency
, handler_name
);
199 TRACE("mode %d -- %dx%dx%dbpp (%s)\n", n
,
200 devmode
->dmPelsWidth
, devmode
->dmPelsHeight
, devmode
->dmBitsPerPel
,
205 TRACE("mode %d -- not present (%s)\n", n
, handler_name
);
209 #define _X_FIELD(prefix, bits) if ((fields) & prefix##_##bits) {p+=sprintf(p, "%s%s", first ? "" : ",", #bits); first=FALSE;}
210 static const char * _CDS_flags(DWORD fields
)
215 _X_FIELD(CDS
,UPDATEREGISTRY
);_X_FIELD(CDS
,TEST
);_X_FIELD(CDS
,FULLSCREEN
);
216 _X_FIELD(CDS
,GLOBAL
);_X_FIELD(CDS
,SET_PRIMARY
);_X_FIELD(CDS
,RESET
);
217 _X_FIELD(CDS
,SETRECT
);_X_FIELD(CDS
,NORESET
);
219 return wine_dbg_sprintf("%s", buf
);
221 static const char * _DM_fields(DWORD fields
)
226 _X_FIELD(DM
,BITSPERPEL
);_X_FIELD(DM
,PELSWIDTH
);_X_FIELD(DM
,PELSHEIGHT
);
227 _X_FIELD(DM
,DISPLAYFLAGS
);_X_FIELD(DM
,DISPLAYFREQUENCY
);_X_FIELD(DM
,POSITION
);
229 return wine_dbg_sprintf("%s", buf
);
233 /***********************************************************************
234 * ChangeDisplaySettingsEx (X11DRV.@)
237 LONG
X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname
, LPDEVMODEW devmode
,
238 HWND hwnd
, DWORD flags
, LPVOID lpvoid
)
242 BOOL def_mode
= TRUE
;
244 TRACE("(%s,%p,%p,0x%08x,%p)\n",debugstr_w(devname
),devmode
,hwnd
,flags
,lpvoid
);
245 TRACE("flags=%s\n",_CDS_flags(flags
));
248 TRACE("DM_fields=%s\n",_DM_fields(devmode
->dmFields
));
249 TRACE("width=%d height=%d bpp=%d freq=%d (%s)\n",
250 devmode
->dmPelsWidth
,devmode
->dmPelsHeight
,
251 devmode
->dmBitsPerPel
,devmode
->dmDisplayFrequency
, handler_name
);
253 dwBpp
= (devmode
->dmBitsPerPel
== 24) ? 32 : devmode
->dmBitsPerPel
;
254 if (devmode
->dmFields
& DM_BITSPERPEL
) def_mode
&= !dwBpp
;
255 if (devmode
->dmFields
& DM_PELSWIDTH
) def_mode
&= !devmode
->dmPelsWidth
;
256 if (devmode
->dmFields
& DM_PELSHEIGHT
) def_mode
&= !devmode
->dmPelsHeight
;
257 if (devmode
->dmFields
& DM_DISPLAYFREQUENCY
) def_mode
&= !devmode
->dmDisplayFrequency
;
262 TRACE("Return to original display mode (%s)\n", handler_name
);
263 if (!X11DRV_EnumDisplaySettingsEx(devname
, dd_mode_default
, &dm
, 0))
265 ERR("Default mode not found!\n");
266 return DISP_CHANGE_BADMODE
;
270 dwBpp
= !dwBpp
? dd_modes
[dd_mode_default
].dwBPP
: dwBpp
;
272 if ((devmode
->dmFields
& (DM_PELSWIDTH
| DM_PELSHEIGHT
)) != (DM_PELSWIDTH
| DM_PELSHEIGHT
))
273 return DISP_CHANGE_BADMODE
;
275 for (i
= 0; i
< dd_mode_count
; i
++)
277 if (devmode
->dmFields
& DM_BITSPERPEL
)
279 if (dwBpp
!= dd_modes
[i
].dwBPP
)
282 if (devmode
->dmFields
& DM_PELSWIDTH
)
284 if (devmode
->dmPelsWidth
!= dd_modes
[i
].dwWidth
)
287 if (devmode
->dmFields
& DM_PELSHEIGHT
)
289 if (devmode
->dmPelsHeight
!= dd_modes
[i
].dwHeight
)
292 if ((devmode
->dmFields
& DM_DISPLAYFREQUENCY
) && (dd_modes
[i
].wRefreshRate
!= 0) &&
293 devmode
->dmDisplayFrequency
!= 0)
295 if (devmode
->dmDisplayFrequency
!= dd_modes
[i
].wRefreshRate
)
298 /* we have a valid mode */
299 TRACE("Requested display settings match mode %d (%s)\n", i
, handler_name
);
300 if (!(flags
& CDS_TEST
))
301 return pSetCurrentMode(i
);
302 return DISP_CHANGE_SUCCESSFUL
;
305 /* no valid modes found */
306 ERR("No matching mode found! (%s)\n", handler_name
);
307 return DISP_CHANGE_BADMODE
;
313 /***********************************************************************
314 * DirectDraw HAL interface
317 static DWORD PASCAL
X11DRV_Settings_SetMode(LPDDHAL_SETMODEDATA data
)
319 TRACE("Mode %d requested by DDHAL (%s)\n", data
->dwModeIndex
, handler_name
);
320 switch (pSetCurrentMode(data
->dwModeIndex
))
322 case DISP_CHANGE_SUCCESSFUL
:
323 X11DRV_DDHAL_SwitchMode(data
->dwModeIndex
, NULL
, NULL
);
324 data
->ddRVal
= DD_OK
;
326 case DISP_CHANGE_BADMODE
:
327 data
->ddRVal
= DDERR_WRONGMODE
;
330 data
->ddRVal
= DDERR_UNSUPPORTEDMODE
;
332 return DDHAL_DRIVER_HANDLED
;
334 int X11DRV_Settings_CreateDriver(LPDDHALINFO info
)
336 if (!dd_mode_count
) return 0; /* no settings defined */
338 TRACE("Setting up display settings for DDRAW (%s)\n", handler_name
);
339 info
->dwNumModes
= dd_mode_count
;
340 info
->lpModeInfo
= dd_modes
;
341 X11DRV_DDHAL_SwitchMode(pGetCurrentMode(), NULL
, NULL
);
342 info
->lpDDCallbacks
->SetMode
= X11DRV_Settings_SetMode
;