VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/wined3d_main.c@ 40588

Last change on this file since 40588 was 39602, checked in by vboxsync, 13 years ago

wine/XPDM: 1. Additional swapchain creation fixes 2. De-libwine'ize wined3d 3. Single context per swapchain 4. wine & crOgl current context sync fixes 5. Proper Get/ReleaseDC handling

  • Property svn:eol-style set to native
File size: 17.3 KB
Line 
1/*
2 * Direct3D wine internal interface main
3 *
4 * Copyright 2002-2003 The wine-d3d team
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2004 Jason Edmeades
7 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
8 * Copyright 2009 Henri Verbeet for CodeWeavers
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25/*
26 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
27 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
28 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
29 * a choice of LGPL license versions is made available with the language indicating
30 * that LGPLv2 or any later version may be used, or where a choice of which version
31 * of the LGPL is applied is otherwise unspecified.
32 */
33#define VBOX_WINE_DEBUG_DEFINES
34
35#include "config.h"
36
37#include "initguid.h"
38#include "wined3d_private.h"
39
40WINE_DEFAULT_DEBUG_CHANNEL(d3d);
41
42struct wined3d_wndproc
43{
44 HWND window;
45 WNDPROC proc;
46 IWineD3DDeviceImpl *device;
47};
48
49struct wined3d_wndproc_table
50{
51 struct wined3d_wndproc *entries;
52 unsigned int count;
53 unsigned int size;
54};
55
56static struct wined3d_wndproc_table wndproc_table;
57
58int num_lock = 0;
59void (*CDECL wine_tsx11_lock_ptr)(void) = NULL;
60void (*CDECL wine_tsx11_unlock_ptr)(void) = NULL;
61
62static CRITICAL_SECTION wined3d_cs;
63static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
64{
65 0, 0, &wined3d_cs,
66 {&wined3d_cs_debug.ProcessLocksList,
67 &wined3d_cs_debug.ProcessLocksList},
68 0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs")}
69};
70static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0};
71
72/* When updating default value here, make sure to update winecfg as well,
73 * where appropriate. */
74wined3d_settings_t wined3d_settings =
75{
76 VS_HW, /* Hardware by default */
77 PS_HW, /* Hardware by default */
78 TRUE, /* Use of GLSL enabled by default */
79#ifdef VBOX_WITH_WDDM
80 ORM_FBO, /* Use FBO to do offscreen rendering */
81#else
82 ORM_BACKBUFFER, /* Use backbuffer to do offscreen rendering */
83#endif
84 RTL_READTEX, /* Default render target locking method */
85 PCI_VENDOR_NONE,/* PCI Vendor ID */
86 PCI_DEVICE_NONE,/* PCI Device ID */
87 0, /* The default of memory is set in FillGLCaps */
88 NULL, /* No wine logo by default */
89 FALSE, /* Disable multisampling for now due to Nvidia driver bugs which happens for some users */
90 FALSE, /* No strict draw ordering. */
91};
92
93IWineD3D * WINAPI WineDirect3DCreate(UINT version, IUnknown *parent)
94{
95 IWineD3DImpl *object;
96 HRESULT hr;
97
98 hr = VBoxExtCheckInit();
99 if (FAILED(hr))
100 {
101 ERR("VBoxExtCheckInit failed, hr (0x%x)\n", hr);
102 return NULL;
103 }
104
105 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
106 if (!object)
107 {
108 ERR("Failed to allocate wined3d object memory.\n");
109 VBoxExtCheckTerm();
110 return NULL;
111 }
112
113 hr = wined3d_init(object, version, parent);
114 if (FAILED(hr))
115 {
116 WARN("Failed to initialize wined3d object, hr %#x.\n", hr);
117 HeapFree(GetProcessHeap(), 0, object);
118#ifdef VBOX_WITH_WDDM
119 VBoxExtCheckTerm();
120#endif
121 return NULL;
122 }
123
124 TRACE("Created wined3d object %p for d3d%d support.\n", object, version);
125
126 return (IWineD3D *)object;
127}
128
129static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char* name, char* buffer, DWORD size)
130{
131 if (0 != appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE) buffer, &size )) return 0;
132 if (0 != defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE) buffer, &size )) return 0;
133 return ERROR_FILE_NOT_FOUND;
134}
135
136static inline DWORD get_config_key_dword(HKEY defkey, HKEY appkey, const char* name, DWORD *data)
137{
138 DWORD type;
139 DWORD size = sizeof(DWORD);
140 if (0 != appkey && !RegQueryValueExA( appkey, name, 0, &type, (LPBYTE) data, &size ) && (type == REG_DWORD)) return 0;
141 if (0 != defkey && !RegQueryValueExA( defkey, name, 0, &type, (LPBYTE) data, &size ) && (type == REG_DWORD)) return 0;
142 return ERROR_FILE_NOT_FOUND;
143}
144
145static void CDECL wined3d_do_nothing(void)
146{
147}
148
149static void WINAPI wined3d_mutex_init(void)
150{
151 InitializeCriticalSection(&wined3d_cs);
152}
153
154static void WINAPI wined3d_mutex_term(void)
155{
156 DeleteCriticalSection(&wined3d_cs);
157}
158
159static BOOL wined3d_dll_init(HINSTANCE hInstDLL)
160{
161 DWORD wined3d_context_tls_idx;
162 HMODULE mod;
163 char buffer[MAX_PATH+10];
164 DWORD size = sizeof(buffer);
165 HKEY hkey = 0;
166 HKEY appkey = 0;
167 DWORD len, tmpvalue;
168 WNDCLASSA wc;
169
170 wined3d_mutex_init();
171
172 wined3d_context_tls_idx = TlsAlloc();
173 if (wined3d_context_tls_idx == TLS_OUT_OF_INDEXES)
174 {
175 DWORD err = GetLastError();
176 ERR("Failed to allocate context TLS index, err %#x.\n", err);
177
178 wined3d_mutex_term();
179 return FALSE;
180 }
181 context_set_tls_idx(wined3d_context_tls_idx);
182
183 /* We need our own window class for a fake window which we use to retrieve GL capabilities */
184 /* We might need CS_OWNDC in the future if we notice strange things on Windows.
185 * Various articles/posts about OpenGL problems on Windows recommend this. */
186 wc.style = CS_HREDRAW | CS_VREDRAW;
187 wc.lpfnWndProc = DefWindowProcA;
188 wc.cbClsExtra = 0;
189 wc.cbWndExtra = 0;
190 wc.hInstance = hInstDLL;
191 wc.hIcon = LoadIconA(NULL, (LPCSTR)IDI_WINLOGO);
192 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
193 wc.hbrBackground = NULL;
194 wc.lpszMenuName = NULL;
195 wc.lpszClassName = WINED3D_OPENGL_WINDOW_CLASS_NAME;
196
197 if (!RegisterClassA(&wc))
198 {
199 ERR("Failed to register window class 'WineD3D_OpenGL'!\n");
200 if (!TlsFree(wined3d_context_tls_idx))
201 {
202 DWORD err = GetLastError();
203 ERR("Failed to free context TLS index, err %#x.\n", err);
204 }
205
206 wined3d_mutex_term();
207
208 return FALSE;
209 }
210
211 DisableThreadLibraryCalls(hInstDLL);
212
213 mod = GetModuleHandleA( "winex11.drv" );
214 if (mod)
215 {
216 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
217 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
218 }
219 else /* We are most likely on Windows */
220 {
221 wine_tsx11_lock_ptr = wined3d_do_nothing;
222 wine_tsx11_unlock_ptr = wined3d_do_nothing;
223 }
224 /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
225 if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey ) ) hkey = 0;
226
227 len = GetModuleFileNameA( 0, buffer, MAX_PATH );
228 if (len && len < MAX_PATH)
229 {
230 HKEY tmpkey;
231 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
232 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
233 {
234 char *p, *appname = buffer;
235 if ((p = strrchr( appname, '/' ))) appname = p + 1;
236 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
237 strcat( appname, "\\Direct3D" );
238 TRACE("appname = [%s]\n", appname);
239 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
240 RegCloseKey( tmpkey );
241 }
242 }
243
244 if ( 0 != hkey || 0 != appkey )
245 {
246 if ( !get_config_key( hkey, appkey, "VertexShaderMode", buffer, size) )
247 {
248 if (!strcmp(buffer,"none"))
249 {
250 TRACE("Disable vertex shaders\n");
251 wined3d_settings.vs_mode = VS_NONE;
252 }
253 }
254 if ( !get_config_key( hkey, appkey, "PixelShaderMode", buffer, size) )
255 {
256 if (!strcmp(buffer,"enabled"))
257 {
258 TRACE("Allow pixel shaders\n");
259 wined3d_settings.ps_mode = PS_HW;
260 }
261 if (!strcmp(buffer,"disabled"))
262 {
263 TRACE("Disable pixel shaders\n");
264 wined3d_settings.ps_mode = PS_NONE;
265 }
266 }
267 if ( !get_config_key( hkey, appkey, "UseGLSL", buffer, size) )
268 {
269 if (!strcmp(buffer,"disabled"))
270 {
271 TRACE("Use of GL Shading Language disabled\n");
272 wined3d_settings.glslRequested = FALSE;
273 }
274 }
275 if ( !get_config_key( hkey, appkey, "OffscreenRenderingMode", buffer, size) )
276 {
277 if (!strcmp(buffer,"backbuffer"))
278 {
279 TRACE("Using the backbuffer for offscreen rendering\n");
280 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
281 }
282 else if (!strcmp(buffer,"fbo"))
283 {
284 TRACE("Using FBOs for offscreen rendering\n");
285 wined3d_settings.offscreen_rendering_mode = ORM_FBO;
286 }
287 }
288 if ( !get_config_key( hkey, appkey, "RenderTargetLockMode", buffer, size) )
289 {
290 if (!strcmp(buffer,"disabled"))
291 {
292 TRACE("Disabling render target locking\n");
293 wined3d_settings.rendertargetlock_mode = RTL_DISABLE;
294 }
295 else if (!strcmp(buffer,"readdraw"))
296 {
297 TRACE("Using glReadPixels for render target reading and glDrawPixels for writing\n");
298 wined3d_settings.rendertargetlock_mode = RTL_READDRAW;
299 }
300 else if (!strcmp(buffer,"readtex"))
301 {
302 TRACE("Using glReadPixels for render target reading and textures for writing\n");
303 wined3d_settings.rendertargetlock_mode = RTL_READTEX;
304 }
305 }
306 if ( !get_config_key_dword( hkey, appkey, "VideoPciDeviceID", &tmpvalue) )
307 {
308 int pci_device_id = tmpvalue;
309
310 /* A pci device id is 16-bit */
311 if(pci_device_id > 0xffff)
312 {
313 ERR("Invalid value for VideoPciDeviceID. The value should be smaller or equal to 65535 or 0xffff\n");
314 }
315 else
316 {
317 TRACE("Using PCI Device ID %04x\n", pci_device_id);
318 wined3d_settings.pci_device_id = pci_device_id;
319 }
320 }
321 if ( !get_config_key_dword( hkey, appkey, "VideoPciVendorID", &tmpvalue) )
322 {
323 int pci_vendor_id = tmpvalue;
324
325 /* A pci device id is 16-bit */
326 if(pci_vendor_id > 0xffff)
327 {
328 ERR("Invalid value for VideoPciVendorID. The value should be smaller or equal to 65535 or 0xffff\n");
329 }
330 else
331 {
332 TRACE("Using PCI Vendor ID %04x\n", pci_vendor_id);
333 wined3d_settings.pci_vendor_id = pci_vendor_id;
334 }
335 }
336 if ( !get_config_key( hkey, appkey, "VideoMemorySize", buffer, size) )
337 {
338 int TmpVideoMemorySize = atoi(buffer);
339 if(TmpVideoMemorySize > 0)
340 {
341 wined3d_settings.emulated_textureram = TmpVideoMemorySize *1024*1024;
342 TRACE("Use %iMB = %d byte for emulated_textureram\n",
343 TmpVideoMemorySize,
344 wined3d_settings.emulated_textureram);
345 }
346 else
347 ERR("VideoMemorySize is %i but must be >0\n", TmpVideoMemorySize);
348 }
349 if ( !get_config_key( hkey, appkey, "WineLogo", buffer, size) )
350 {
351 size_t len = strlen(buffer) + 1;
352
353 wined3d_settings.logo = HeapAlloc(GetProcessHeap(), 0, len);
354 if (!wined3d_settings.logo) ERR("Failed to allocate logo path memory.\n");
355 else memcpy(wined3d_settings.logo, buffer, len);
356 }
357 if ( !get_config_key( hkey, appkey, "Multisampling", buffer, size) )
358 {
359 if (!strcmp(buffer,"enabled"))
360 {
361 TRACE("Allow multisampling\n");
362 wined3d_settings.allow_multisampling = TRUE;
363 }
364 }
365 if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size)
366 && !strcmp(buffer,"enabled"))
367 {
368 TRACE("Enforcing strict draw ordering.\n");
369 wined3d_settings.strict_draw_ordering = TRUE;
370 }
371 }
372 if (wined3d_settings.vs_mode == VS_HW)
373 TRACE("Allow HW vertex shaders\n");
374 if (wined3d_settings.ps_mode == PS_NONE)
375 TRACE("Disable pixel shaders\n");
376 if (wined3d_settings.glslRequested)
377 TRACE("If supported by your system, GL Shading Language will be used\n");
378
379 if (appkey) RegCloseKey( appkey );
380 if (hkey) RegCloseKey( hkey );
381
382 return TRUE;
383}
384
385static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL)
386{
387 DWORD wined3d_context_tls_idx = context_get_tls_idx();
388 unsigned int i;
389
390 if (!TlsFree(wined3d_context_tls_idx))
391 {
392 DWORD err = GetLastError();
393 ERR("Failed to free context TLS index, err %#x.\n", err);
394 }
395
396 for (i = 0; i < wndproc_table.count; ++i)
397 {
398 struct wined3d_wndproc *entry = &wndproc_table.entries[i];
399 SetWindowLongPtrW(entry->window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
400 }
401 HeapFree(GetProcessHeap(), 0, wndproc_table.entries);
402
403 HeapFree(GetProcessHeap(), 0, wined3d_settings.logo);
404 UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
405
406 wined3d_mutex_term();
407
408 return TRUE;
409}
410
411void WINAPI wined3d_mutex_lock(void)
412{
413 EnterCriticalSection(&wined3d_cs);
414}
415
416void WINAPI wined3d_mutex_unlock(void)
417{
418 LeaveCriticalSection(&wined3d_cs);
419}
420
421#ifndef VBOX_WITH_WDDM
422static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
423{
424 unsigned int i;
425
426 for (i = 0; i < wndproc_table.count; ++i)
427 {
428 if (wndproc_table.entries[i].window == window)
429 {
430 return &wndproc_table.entries[i];
431 }
432 }
433
434 return NULL;
435}
436
437static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
438{
439 struct wined3d_wndproc *entry;
440 IWineD3DDeviceImpl *device;
441 WNDPROC proc;
442
443 wined3d_mutex_lock();
444 entry = wined3d_find_wndproc(window);
445
446 if (!entry)
447 {
448 wined3d_mutex_unlock();
449 ERR("Window %p is not registered with wined3d.\n", window);
450 return DefWindowProcW(window, message, wparam, lparam);
451 }
452
453 device = entry->device;
454 proc = entry->proc;
455 wined3d_mutex_unlock();
456
457 return device_process_message(device, window, message, wparam, lparam, proc);
458}
459
460BOOL wined3d_register_window(HWND window, IWineD3DDeviceImpl *device)
461{
462 struct wined3d_wndproc *entry;
463
464 wined3d_mutex_lock();
465
466 if (wndproc_table.size == wndproc_table.count)
467 {
468 unsigned int new_size = max(1, wndproc_table.size * 2);
469 struct wined3d_wndproc *new_entries;
470
471 if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries));
472 else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries));
473
474 if (!new_entries)
475 {
476 wined3d_mutex_unlock();
477 ERR("Failed to grow table.\n");
478 return FALSE;
479 }
480
481 wndproc_table.entries = new_entries;
482 wndproc_table.size = new_size;
483 }
484
485 entry = &wndproc_table.entries[wndproc_table.count++];
486 entry->window = window;
487 entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
488 entry->device = device;
489
490 wined3d_mutex_unlock();
491
492 return TRUE;
493}
494
495void wined3d_unregister_window(HWND window)
496{
497 unsigned int i;
498
499 wined3d_mutex_lock();
500 for (i = 0; i < wndproc_table.count; ++i)
501 {
502 if (wndproc_table.entries[i].window == window)
503 {
504 struct wined3d_wndproc *entry = &wndproc_table.entries[i];
505 struct wined3d_wndproc *last = &wndproc_table.entries[--wndproc_table.count];
506
507 if (GetWindowLongPtrW(window, GWLP_WNDPROC) == (LONG_PTR)wined3d_wndproc)
508 SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc);
509 if (entry != last) *entry = *last;
510 wined3d_mutex_unlock();
511
512 return;
513 }
514 }
515 wined3d_mutex_unlock();
516
517 ERR("Window %p is not registered with wined3d.\n", window);
518}
519#endif
520/* At process attach */
521BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
522{
523 TRACE("WineD3D DLLMain Reason=%u\n", fdwReason);
524
525 switch (fdwReason)
526 {
527 case DLL_PROCESS_ATTACH:
528 return wined3d_dll_init(hInstDLL);
529
530 case DLL_PROCESS_DETACH:
531 return wined3d_dll_destroy(hInstDLL);
532
533 case DLL_THREAD_DETACH:
534 {
535#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
536 context_clear_on_thread_detach();
537#else
538 if (!context_set_current(NULL))
539 {
540 ERR("Failed to clear current context.\n");
541 }
542#endif
543 return TRUE;
544 }
545
546 default:
547 return TRUE;
548 }
549}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette