- add direct3d configuration on winecfg graphics panel
[wine] / programs / winecfg / x11drvdlg.c
1 /*
2  * Graphics configuration code
3  *
4  * Copyright 2003 Mark Westcott
5  * Copyright 2003-2004 Mike Hearn
6  * Copyright 2005 Raphael Junqueira
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winreg.h>
31 #include <wine/debug.h>
32
33 #include "resource.h"
34 #include "winecfg.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
37
38 #define RES_MAXLEN 5 /* the maximum number of characters in a screen dimension. 5 digits should be plenty, what kind of crazy person runs their screen >10,000 pixels across? */
39
40
41 static const char* D3D_VS_Modes[] = {
42   "hardware",
43   "none",
44   "emulation",
45   NULL
46 };
47
48
49 int updating_ui;
50
51 static void update_gui_for_desktop_mode(HWND dialog) {
52     WINE_TRACE("\n");
53
54     updating_ui = TRUE;
55     
56     /* do we have desktop mode enabled? */
57     if (reg_key_exists(config_key, keypath("X11 Driver"), "Desktop"))
58     {
59         char* buf, *bufindex;
60         CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_CHECKED);
61         
62         enable(IDC_DESKTOP_WIDTH);
63         enable(IDC_DESKTOP_HEIGHT);
64         enable(IDC_DESKTOP_SIZE);
65         enable(IDC_DESKTOP_BY);
66
67         buf = get_reg_key(config_key, keypath("X11 Driver"), "Desktop", "640x480");
68         bufindex = strchr(buf, 'x');
69         if (bufindex) {
70             *bufindex = 0;
71             ++bufindex;
72             SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), buf);
73             SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), bufindex);
74         } else {
75             WINE_TRACE("Desktop registry entry is malformed");
76             SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "640");
77             SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "480");
78         }
79
80         HeapFree(GetProcessHeap(), 0, buf);
81     }
82     else
83     {
84         CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_UNCHECKED);
85         
86         disable(IDC_DESKTOP_WIDTH);
87         disable(IDC_DESKTOP_HEIGHT);
88         disable(IDC_DESKTOP_SIZE);
89         disable(IDC_DESKTOP_BY);
90
91         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "");
92         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "");
93     }
94
95     updating_ui = FALSE;
96 }
97
98 static void init_dialog (HWND dialog)
99 {
100     unsigned int it;
101     char* buf;
102
103     update_gui_for_desktop_mode(dialog);
104
105     updating_ui = TRUE;
106     
107     SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_RESETCONTENT, 0, 0);
108     SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "8 bit");
109     SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "16 bit");
110     SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "24 bit");
111     SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "32 bit"); /* is this valid? */
112
113     buf = get_reg_key(config_key, keypath("X11 Driver"), "ScreenDepth", "24");
114     if (strcmp(buf, "8") == 0)
115         SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_SETCURSEL, 0, 0);
116     else if (strcmp(buf, "16") == 0)
117         SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_SETCURSEL, 1, 0);
118     else if (strcmp(buf, "24") == 0)
119         SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_SETCURSEL, 2, 0);
120     else if (strcmp(buf, "32") == 0)
121         SendDlgItemMessage(dialog, IDC_SCREEN_DEPTH, CB_SETCURSEL, 3, 0);
122     else
123         WINE_ERR("Invalid screen depth read from registry (%s)\n", buf);
124     HeapFree(GetProcessHeap(), 0, buf);
125
126     SendDlgItemMessage(dialog, IDC_DESKTOP_WIDTH, EM_LIMITTEXT, RES_MAXLEN, 0);
127     SendDlgItemMessage(dialog, IDC_DESKTOP_HEIGHT, EM_LIMITTEXT, RES_MAXLEN, 0);
128
129     buf = get_reg_key(config_key, keypath("X11 Driver"), "DXGrab", "Y");
130     if (IS_OPTION_TRUE(*buf))
131         CheckDlgButton(dialog, IDC_DX_MOUSE_GRAB, BST_CHECKED);
132     else
133         CheckDlgButton(dialog, IDC_DX_MOUSE_GRAB, BST_UNCHECKED);
134     HeapFree(GetProcessHeap(), 0, buf);
135
136     buf = get_reg_key(config_key, keypath("X11 Driver"), "DesktopDoubleBuffered", "Y");
137     if (IS_OPTION_TRUE(*buf))
138         CheckDlgButton(dialog, IDC_DOUBLE_BUFFER, BST_CHECKED);
139     else
140         CheckDlgButton(dialog, IDC_DOUBLE_BUFFER, BST_UNCHECKED);
141     HeapFree(GetProcessHeap(), 0, buf);
142
143     SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_RESETCONTENT, 0, 0);
144     for (it = 0; NULL != D3D_VS_Modes[it]; ++it) {
145       SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_ADDSTRING, 0, (LPARAM) D3D_VS_Modes[it]);
146     }  
147     buf = get_reg_key(config_key, keypath("Direct3D"), "VertexShaderMode", "hardware"); 
148     for (it = 0; NULL != D3D_VS_Modes[it]; ++it) {
149       if (strcmp(buf, D3D_VS_Modes[it]) == 0) {
150         SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_SETCURSEL, it, 0);
151         break ;
152       }
153     }
154     if (NULL == D3D_VS_Modes[it]) {
155       WINE_ERR("Invalid Direct3D VertexShader Mode read from registry (%s)\n", buf);
156     }
157     HeapFree(GetProcessHeap(), 0, buf);
158
159     buf = get_reg_key(config_key, keypath("Direct3D"), "PixelShaderMode", "enabled");
160     if (!strcmp(buf, "enabled"))
161       CheckDlgButton(dialog, IDC_D3D_PSHADER_MODE, BST_CHECKED);
162     else
163       CheckDlgButton(dialog, IDC_D3D_PSHADER_MODE, BST_UNCHECKED);
164     HeapFree(GetProcessHeap(), 0, buf);
165
166     updating_ui = FALSE;
167 }
168
169 static void set_from_desktop_edits(HWND dialog) {
170     char *width, *height, *new;
171
172     if (updating_ui) return;
173     
174     WINE_TRACE("\n");
175
176     width = get_text(dialog, IDC_DESKTOP_WIDTH);
177     height = get_text(dialog, IDC_DESKTOP_HEIGHT);
178
179     if (width == NULL || strcmp(width, "") == 0) {
180         HeapFree(GetProcessHeap(), 0, width);
181         width = strdupA("640");
182     }
183     
184     if (height == NULL || strcmp(height, "") == 0) {
185         HeapFree(GetProcessHeap(), 0, height);
186         height = strdupA("480");
187     }
188
189     new = HeapAlloc(GetProcessHeap(), 0, strlen(width) + strlen(height) + 2 /* x + terminator */);
190     sprintf(new, "%sx%s", width, height);
191     set_reg_key(config_key, keypath("X11 Driver"), "Desktop", new);
192     
193     HeapFree(GetProcessHeap(), 0, width);
194     HeapFree(GetProcessHeap(), 0, height);
195     HeapFree(GetProcessHeap(), 0, new);
196 }
197
198 static void on_enable_desktop_clicked(HWND dialog) {
199     WINE_TRACE("\n");
200     
201     if (IsDlgButtonChecked(dialog, IDC_ENABLE_DESKTOP) == BST_CHECKED) {
202         set_from_desktop_edits(dialog);
203     } else {
204         set_reg_key(config_key, keypath("X11 Driver"), "Desktop", NULL);
205     }
206     
207     update_gui_for_desktop_mode(dialog);
208 }
209
210 static void on_screen_depth_changed(HWND dialog) {
211     char *newvalue = get_text(dialog, IDC_SCREEN_DEPTH);
212     char *spaceIndex = strchr(newvalue, ' ');
213     
214     WINE_TRACE("newvalue=%s\n", newvalue);
215     if (updating_ui) return;
216
217     *spaceIndex = '\0';
218     set_reg_key(config_key, keypath("X11 Driver"), "ScreenDepth", newvalue);
219     HeapFree(GetProcessHeap(), 0, newvalue);
220 }
221
222 static void on_dx_mouse_grab_clicked(HWND dialog) {
223     if (IsDlgButtonChecked(dialog, IDC_DX_MOUSE_GRAB) == BST_CHECKED) 
224         set_reg_key(config_key, keypath("X11 Driver"), "DXGrab", "Y");
225     else
226         set_reg_key(config_key, keypath("X11 Driver"), "DXGrab", "N");
227 }
228
229
230 static void on_double_buffer_clicked(HWND dialog) {
231     if (IsDlgButtonChecked(dialog, IDC_DOUBLE_BUFFER) == BST_CHECKED)
232         set_reg_key(config_key, keypath("X11 Driver"), "DesktopDoubleBuffered", "Y");
233     else
234         set_reg_key(config_key, keypath("X11 Driver"), "DesktopDoubleBuffered", "N");
235 }
236
237 static void on_d3d_vshader_mode_changed(HWND dialog) {
238   int selected_mode = SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_GETCURSEL, 0, 0);  
239   set_reg_key(config_key, keypath("Direct3D"), "VertexShaderMode", D3D_VS_Modes[selected_mode]); 
240 }
241
242 static void on_d3d_pshader_mode_clicked(HWND dialog) {
243     if (IsDlgButtonChecked(dialog, IDC_D3D_PSHADER_MODE) == BST_CHECKED)
244         set_reg_key(config_key, keypath("Direct3D"), "PixelShaderMode", "enabled");
245     else
246         set_reg_key(config_key, keypath("Direct3D"), "PixelShaderMode", "disabled");
247 }
248
249 INT_PTR CALLBACK
250 GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
251 {
252     switch (uMsg) {
253         case WM_INITDIALOG:
254             break;
255
256         case WM_SHOWWINDOW:
257             set_window_title(hDlg);
258             break;
259             
260         case WM_COMMAND:
261             switch(HIWORD(wParam)) {
262                 case EN_CHANGE: {
263                     if (updating_ui) break;
264                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
265                     if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updating_ui )
266                         set_from_desktop_edits(hDlg);
267                     break;
268                 }
269                 case BN_CLICKED: {
270                     if (updating_ui) break;
271                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
272                     switch(LOWORD(wParam)) {
273                         case IDC_ENABLE_DESKTOP: on_enable_desktop_clicked(hDlg); break;
274                         case IDC_DX_MOUSE_GRAB:  on_dx_mouse_grab_clicked(hDlg); break;
275                         case IDC_DOUBLE_BUFFER:  on_double_buffer_clicked(hDlg); break;
276                         case IDC_D3D_PSHADER_MODE: on_d3d_pshader_mode_clicked(hDlg); break;
277                     }
278                     break;
279                 }
280                 case CBN_SELCHANGE: {
281                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
282                     switch (LOWORD(wParam)) {
283                     case IDC_SCREEN_DEPTH: on_screen_depth_changed(hDlg); break;
284                     case IDC_D3D_VSHADER_MODE: on_d3d_vshader_mode_changed(hDlg); break;
285                     }
286                     break;
287                 }
288                     
289                 default:
290                     break;
291             }
292             break;
293         
294         
295         case WM_NOTIFY:
296             switch (((LPNMHDR)lParam)->code) {
297                 case PSN_KILLACTIVE: {
298                     SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
299                     break;
300                 }
301                 case PSN_APPLY: {
302                     apply();
303                     SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
304                     break;
305                 }
306                 case PSN_SETACTIVE: {
307                     init_dialog (hDlg);
308                     break;
309                 }
310             }
311             break;
312
313         default:
314             break;
315     }
316     return FALSE;
317 }