Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwined3d_main.c
Go to the documentation of this file.
00001 /* 00002 * Direct3D wine internal interface main 00003 * 00004 * Copyright 2002-2003 The wine-d3d team 00005 * Copyright 2002-2003 Raphael Junqueira 00006 * Copyright 2004 Jason Edmeades 00007 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers 00008 * Copyright 2009 Henri Verbeet for CodeWeavers 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 */ 00024 00025 #include "config.h" 00026 00027 #include "initguid.h" 00028 #include "wined3d_private.h" 00029 00030 WINE_DEFAULT_DEBUG_CHANNEL(d3d); 00031 WINE_DECLARE_DEBUG_CHANNEL(winediag); 00032 00033 struct wined3d_wndproc 00034 { 00035 HWND window; 00036 BOOL unicode; 00037 WNDPROC proc; 00038 struct wined3d_device *device; 00039 }; 00040 00041 struct wined3d_wndproc_table 00042 { 00043 struct wined3d_wndproc *entries; 00044 unsigned int count; 00045 unsigned int size; 00046 }; 00047 00048 static struct wined3d_wndproc_table wndproc_table; 00049 00050 int num_lock = 0; 00051 void (CDECL *wine_tsx11_lock_ptr)(void) = NULL; 00052 void (CDECL *wine_tsx11_unlock_ptr)(void) = NULL; 00053 00054 static CRITICAL_SECTION wined3d_cs; 00055 static CRITICAL_SECTION_DEBUG wined3d_cs_debug = 00056 { 00057 0, 0, &wined3d_cs, 00058 {&wined3d_cs_debug.ProcessLocksList, 00059 &wined3d_cs_debug.ProcessLocksList}, 00060 0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs")} 00061 }; 00062 static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0}; 00063 00064 static CRITICAL_SECTION wined3d_wndproc_cs; 00065 static CRITICAL_SECTION_DEBUG wined3d_wndproc_cs_debug = 00066 { 00067 0, 0, &wined3d_wndproc_cs, 00068 {&wined3d_wndproc_cs_debug.ProcessLocksList, 00069 &wined3d_wndproc_cs_debug.ProcessLocksList}, 00070 0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_wndproc_cs")} 00071 }; 00072 static CRITICAL_SECTION wined3d_wndproc_cs = {&wined3d_wndproc_cs_debug, -1, 0, 0, 0, 0}; 00073 00074 /* When updating default value here, make sure to update winecfg as well, 00075 * where appropriate. */ 00076 struct wined3d_settings wined3d_settings = 00077 { 00078 VS_HW, /* Hardware by default */ 00079 PS_HW, /* Hardware by default */ 00080 TRUE, /* Use of GLSL enabled by default */ 00081 ORM_FBO, /* Use FBOs to do offscreen rendering */ 00082 RTL_READTEX, /* Default render target locking method */ 00083 PCI_VENDOR_NONE,/* PCI Vendor ID */ 00084 PCI_DEVICE_NONE,/* PCI Device ID */ 00085 0, /* The default of memory is set in init_driver_info */ 00086 NULL, /* No wine logo by default */ 00087 TRUE, /* Multisampling enabled by default. */ 00088 FALSE, /* No strict draw ordering. */ 00089 FALSE, /* Try to render onscreen by default. */ 00090 }; 00091 00092 /* Do not call while under the GL lock. */ 00093 struct wined3d * CDECL wined3d_create(UINT version, DWORD flags, void *parent) 00094 { 00095 struct wined3d *object; 00096 HRESULT hr; 00097 00098 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); 00099 if (!object) 00100 { 00101 ERR("Failed to allocate wined3d object memory.\n"); 00102 return NULL; 00103 } 00104 00105 hr = wined3d_init(object, version, flags, parent); 00106 if (FAILED(hr)) 00107 { 00108 WARN("Failed to initialize wined3d object, hr %#x.\n", hr); 00109 HeapFree(GetProcessHeap(), 0, object); 00110 return NULL; 00111 } 00112 00113 TRACE("Created wined3d object %p for d3d%d support.\n", object, version); 00114 00115 return object; 00116 } 00117 00118 static DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name, char *buffer, DWORD size) 00119 { 00120 if (appkey && !RegQueryValueExA(appkey, name, 0, NULL, (BYTE *)buffer, &size)) return 0; 00121 if (defkey && !RegQueryValueExA(defkey, name, 0, NULL, (BYTE *)buffer, &size)) return 0; 00122 return ERROR_FILE_NOT_FOUND; 00123 } 00124 00125 static DWORD get_config_key_dword(HKEY defkey, HKEY appkey, const char *name, DWORD *data) 00126 { 00127 DWORD type; 00128 DWORD size = sizeof(DWORD); 00129 if (appkey && !RegQueryValueExA(appkey, name, 0, &type, (BYTE *)data, &size) && (type == REG_DWORD)) return 0; 00130 if (defkey && !RegQueryValueExA(defkey, name, 0, &type, (BYTE *)data, &size) && (type == REG_DWORD)) return 0; 00131 return ERROR_FILE_NOT_FOUND; 00132 } 00133 00134 static void CDECL wined3d_do_nothing(void) 00135 { 00136 } 00137 00138 static BOOL wined3d_dll_init(HINSTANCE hInstDLL) 00139 { 00140 DWORD wined3d_context_tls_idx; 00141 HMODULE mod; 00142 char buffer[MAX_PATH+10]; 00143 DWORD size = sizeof(buffer); 00144 HKEY hkey = 0; 00145 HKEY appkey = 0; 00146 DWORD len, tmpvalue; 00147 WNDCLASSA wc; 00148 00149 wined3d_context_tls_idx = TlsAlloc(); 00150 if (wined3d_context_tls_idx == TLS_OUT_OF_INDEXES) 00151 { 00152 DWORD err = GetLastError(); 00153 ERR("Failed to allocate context TLS index, err %#x.\n", err); 00154 return FALSE; 00155 } 00156 context_set_tls_idx(wined3d_context_tls_idx); 00157 00158 /* We need our own window class for a fake window which we use to retrieve GL capabilities */ 00159 /* We might need CS_OWNDC in the future if we notice strange things on Windows. 00160 * Various articles/posts about OpenGL problems on Windows recommend this. */ 00161 wc.style = CS_HREDRAW | CS_VREDRAW; 00162 wc.lpfnWndProc = DefWindowProcA; 00163 wc.cbClsExtra = 0; 00164 wc.cbWndExtra = 0; 00165 wc.hInstance = hInstDLL; 00166 wc.hIcon = LoadIconA(NULL, (LPCSTR)IDI_WINLOGO); 00167 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); 00168 wc.hbrBackground = NULL; 00169 wc.lpszMenuName = NULL; 00170 wc.lpszClassName = WINED3D_OPENGL_WINDOW_CLASS_NAME; 00171 00172 if (!RegisterClassA(&wc)) 00173 { 00174 ERR("Failed to register window class 'WineD3D_OpenGL'!\n"); 00175 if (!TlsFree(wined3d_context_tls_idx)) 00176 { 00177 DWORD err = GetLastError(); 00178 ERR("Failed to free context TLS index, err %#x.\n", err); 00179 } 00180 return FALSE; 00181 } 00182 00183 DisableThreadLibraryCalls(hInstDLL); 00184 00185 mod = GetModuleHandleA( "winex11.drv" ); 00186 if (mod) 00187 { 00188 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" ); 00189 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" ); 00190 } 00191 else /* We are most likely on Windows */ 00192 { 00193 wine_tsx11_lock_ptr = wined3d_do_nothing; 00194 wine_tsx11_unlock_ptr = wined3d_do_nothing; 00195 } 00196 /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */ 00197 if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey ) ) hkey = 0; 00198 00199 len = GetModuleFileNameA( 0, buffer, MAX_PATH ); 00200 if (len && len < MAX_PATH) 00201 { 00202 HKEY tmpkey; 00203 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */ 00204 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey )) 00205 { 00206 char *p, *appname = buffer; 00207 if ((p = strrchr( appname, '/' ))) appname = p + 1; 00208 if ((p = strrchr( appname, '\\' ))) appname = p + 1; 00209 strcat( appname, "\\Direct3D" ); 00210 TRACE("appname = [%s]\n", appname); 00211 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0; 00212 RegCloseKey( tmpkey ); 00213 } 00214 } 00215 00216 if (hkey || appkey) 00217 { 00218 if ( !get_config_key( hkey, appkey, "VertexShaderMode", buffer, size) ) 00219 { 00220 if (!strcmp(buffer,"none")) 00221 { 00222 TRACE("Disable vertex shaders\n"); 00223 wined3d_settings.vs_mode = VS_NONE; 00224 } 00225 } 00226 if ( !get_config_key( hkey, appkey, "PixelShaderMode", buffer, size) ) 00227 { 00228 if (!strcmp(buffer,"enabled")) 00229 { 00230 TRACE("Allow pixel shaders\n"); 00231 wined3d_settings.ps_mode = PS_HW; 00232 } 00233 if (!strcmp(buffer,"disabled")) 00234 { 00235 TRACE("Disable pixel shaders\n"); 00236 wined3d_settings.ps_mode = PS_NONE; 00237 } 00238 } 00239 if ( !get_config_key( hkey, appkey, "UseGLSL", buffer, size) ) 00240 { 00241 if (!strcmp(buffer,"disabled")) 00242 { 00243 ERR_(winediag)("The GLSL shader backend has been disabled. You get to keep all the pieces if it breaks.\n"); 00244 TRACE("Use of GL Shading Language disabled\n"); 00245 wined3d_settings.glslRequested = FALSE; 00246 } 00247 } 00248 if ( !get_config_key( hkey, appkey, "OffscreenRenderingMode", buffer, size) ) 00249 { 00250 if (!strcmp(buffer,"backbuffer")) 00251 { 00252 TRACE("Using the backbuffer for offscreen rendering\n"); 00253 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER; 00254 } 00255 else if (!strcmp(buffer,"fbo")) 00256 { 00257 TRACE("Using FBOs for offscreen rendering\n"); 00258 wined3d_settings.offscreen_rendering_mode = ORM_FBO; 00259 } 00260 } 00261 if ( !get_config_key( hkey, appkey, "RenderTargetLockMode", buffer, size) ) 00262 { 00263 if (!strcmp(buffer,"readdraw")) 00264 { 00265 TRACE("Using glReadPixels for render target reading and glDrawPixels for writing\n"); 00266 wined3d_settings.rendertargetlock_mode = RTL_READDRAW; 00267 } 00268 else if (!strcmp(buffer,"readtex")) 00269 { 00270 TRACE("Using glReadPixels for render target reading and textures for writing\n"); 00271 wined3d_settings.rendertargetlock_mode = RTL_READTEX; 00272 } 00273 } 00274 if ( !get_config_key_dword( hkey, appkey, "VideoPciDeviceID", &tmpvalue) ) 00275 { 00276 int pci_device_id = tmpvalue; 00277 00278 /* A pci device id is 16-bit */ 00279 if(pci_device_id > 0xffff) 00280 { 00281 ERR("Invalid value for VideoPciDeviceID. The value should be smaller or equal to 65535 or 0xffff\n"); 00282 } 00283 else 00284 { 00285 TRACE("Using PCI Device ID %04x\n", pci_device_id); 00286 wined3d_settings.pci_device_id = pci_device_id; 00287 } 00288 } 00289 if ( !get_config_key_dword( hkey, appkey, "VideoPciVendorID", &tmpvalue) ) 00290 { 00291 int pci_vendor_id = tmpvalue; 00292 00293 /* A pci device id is 16-bit */ 00294 if(pci_vendor_id > 0xffff) 00295 { 00296 ERR("Invalid value for VideoPciVendorID. The value should be smaller or equal to 65535 or 0xffff\n"); 00297 } 00298 else 00299 { 00300 TRACE("Using PCI Vendor ID %04x\n", pci_vendor_id); 00301 wined3d_settings.pci_vendor_id = pci_vendor_id; 00302 } 00303 } 00304 if ( !get_config_key( hkey, appkey, "VideoMemorySize", buffer, size) ) 00305 { 00306 int TmpVideoMemorySize = atoi(buffer); 00307 if(TmpVideoMemorySize > 0) 00308 { 00309 wined3d_settings.emulated_textureram = TmpVideoMemorySize *1024*1024; 00310 TRACE("Use %iMB = %d byte for emulated_textureram\n", 00311 TmpVideoMemorySize, 00312 wined3d_settings.emulated_textureram); 00313 } 00314 else 00315 ERR("VideoMemorySize is %i but must be >0\n", TmpVideoMemorySize); 00316 } 00317 if ( !get_config_key( hkey, appkey, "WineLogo", buffer, size) ) 00318 { 00319 size_t len = strlen(buffer) + 1; 00320 00321 wined3d_settings.logo = HeapAlloc(GetProcessHeap(), 0, len); 00322 if (!wined3d_settings.logo) ERR("Failed to allocate logo path memory.\n"); 00323 else memcpy(wined3d_settings.logo, buffer, len); 00324 } 00325 if ( !get_config_key( hkey, appkey, "Multisampling", buffer, size) ) 00326 { 00327 if (!strcmp(buffer, "disabled")) 00328 { 00329 TRACE("Multisampling disabled.\n"); 00330 wined3d_settings.allow_multisampling = FALSE; 00331 } 00332 } 00333 if (!get_config_key(hkey, appkey, "StrictDrawOrdering", buffer, size) 00334 && !strcmp(buffer,"enabled")) 00335 { 00336 TRACE("Enforcing strict draw ordering.\n"); 00337 wined3d_settings.strict_draw_ordering = TRUE; 00338 } 00339 if (!get_config_key(hkey, appkey, "AlwaysOffscreen", buffer, size) 00340 && !strcmp(buffer,"enabled")) 00341 { 00342 TRACE("Always rendering backbuffers offscreen.\n"); 00343 wined3d_settings.always_offscreen = TRUE; 00344 } 00345 } 00346 if (wined3d_settings.vs_mode == VS_HW) 00347 TRACE("Allow HW vertex shaders\n"); 00348 if (wined3d_settings.ps_mode == PS_NONE) 00349 TRACE("Disable pixel shaders\n"); 00350 if (wined3d_settings.glslRequested) 00351 TRACE("If supported by your system, GL Shading Language will be used\n"); 00352 00353 if (appkey) RegCloseKey( appkey ); 00354 if (hkey) RegCloseKey( hkey ); 00355 00356 return TRUE; 00357 } 00358 00359 static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL) 00360 { 00361 DWORD wined3d_context_tls_idx = context_get_tls_idx(); 00362 unsigned int i; 00363 00364 if (!TlsFree(wined3d_context_tls_idx)) 00365 { 00366 DWORD err = GetLastError(); 00367 ERR("Failed to free context TLS index, err %#x.\n", err); 00368 } 00369 00370 for (i = 0; i < wndproc_table.count; ++i) 00371 { 00372 /* Trying to unregister these would be futile. These entries can only 00373 * exist if either we skipped them in wined3d_unregister_window() due 00374 * to the application replacing the wndproc after the entry was 00375 * registered, or if the application still has an active wined3d 00376 * device. In the latter case the application has bigger problems than 00377 * these entries. */ 00378 WARN("Leftover wndproc table entry %p.\n", &wndproc_table.entries[i]); 00379 } 00380 HeapFree(GetProcessHeap(), 0, wndproc_table.entries); 00381 00382 HeapFree(GetProcessHeap(), 0, wined3d_settings.logo); 00383 UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL); 00384 00385 DeleteCriticalSection(&wined3d_wndproc_cs); 00386 DeleteCriticalSection(&wined3d_cs); 00387 return TRUE; 00388 } 00389 00390 void WINAPI wined3d_mutex_lock(void) 00391 { 00392 EnterCriticalSection(&wined3d_cs); 00393 } 00394 00395 void WINAPI wined3d_mutex_unlock(void) 00396 { 00397 LeaveCriticalSection(&wined3d_cs); 00398 } 00399 00400 static void wined3d_wndproc_mutex_lock(void) 00401 { 00402 EnterCriticalSection(&wined3d_wndproc_cs); 00403 } 00404 00405 static void wined3d_wndproc_mutex_unlock(void) 00406 { 00407 LeaveCriticalSection(&wined3d_wndproc_cs); 00408 } 00409 00410 static struct wined3d_wndproc *wined3d_find_wndproc(HWND window) 00411 { 00412 unsigned int i; 00413 00414 for (i = 0; i < wndproc_table.count; ++i) 00415 { 00416 if (wndproc_table.entries[i].window == window) 00417 { 00418 return &wndproc_table.entries[i]; 00419 } 00420 } 00421 00422 return NULL; 00423 } 00424 00425 static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) 00426 { 00427 struct wined3d_wndproc *entry; 00428 struct wined3d_device *device; 00429 BOOL unicode; 00430 WNDPROC proc; 00431 00432 wined3d_wndproc_mutex_lock(); 00433 entry = wined3d_find_wndproc(window); 00434 00435 if (!entry) 00436 { 00437 wined3d_wndproc_mutex_unlock(); 00438 ERR("Window %p is not registered with wined3d.\n", window); 00439 return DefWindowProcW(window, message, wparam, lparam); 00440 } 00441 00442 device = entry->device; 00443 unicode = entry->unicode; 00444 proc = entry->proc; 00445 wined3d_wndproc_mutex_unlock(); 00446 00447 return device_process_message(device, window, unicode, message, wparam, lparam, proc); 00448 } 00449 00450 BOOL wined3d_register_window(HWND window, struct wined3d_device *device) 00451 { 00452 struct wined3d_wndproc *entry; 00453 00454 wined3d_wndproc_mutex_lock(); 00455 00456 if (wined3d_find_wndproc(window)) 00457 { 00458 wined3d_wndproc_mutex_unlock(); 00459 WARN("Window %p is already registered with wined3d.\n", window); 00460 return TRUE; 00461 } 00462 00463 if (wndproc_table.size == wndproc_table.count) 00464 { 00465 unsigned int new_size = max(1, wndproc_table.size * 2); 00466 struct wined3d_wndproc *new_entries; 00467 00468 if (!wndproc_table.entries) new_entries = HeapAlloc(GetProcessHeap(), 0, new_size * sizeof(*new_entries)); 00469 else new_entries = HeapReAlloc(GetProcessHeap(), 0, wndproc_table.entries, new_size * sizeof(*new_entries)); 00470 00471 if (!new_entries) 00472 { 00473 wined3d_wndproc_mutex_unlock(); 00474 ERR("Failed to grow table.\n"); 00475 return FALSE; 00476 } 00477 00478 wndproc_table.entries = new_entries; 00479 wndproc_table.size = new_size; 00480 } 00481 00482 entry = &wndproc_table.entries[wndproc_table.count++]; 00483 entry->window = window; 00484 entry->unicode = IsWindowUnicode(window); 00485 /* Set a window proc that matches the window. Some applications (e.g. NoX) 00486 * replace the window proc after we've set ours, and expect to be able to 00487 * call the previous one (ours) directly, without using CallWindowProc(). */ 00488 if (entry->unicode) 00489 entry->proc = (WNDPROC)SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc); 00490 else 00491 entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc); 00492 entry->device = device; 00493 00494 wined3d_wndproc_mutex_unlock(); 00495 00496 return TRUE; 00497 } 00498 00499 void wined3d_unregister_window(HWND window) 00500 { 00501 struct wined3d_wndproc *entry, *last; 00502 LONG_PTR proc; 00503 00504 wined3d_wndproc_mutex_lock(); 00505 00506 if (!(entry = wined3d_find_wndproc(window))) 00507 { 00508 wined3d_wndproc_mutex_unlock(); 00509 ERR("Window %p is not registered with wined3d.\n", window); 00510 return; 00511 } 00512 00513 if (entry->unicode) 00514 { 00515 proc = GetWindowLongPtrW(window, GWLP_WNDPROC); 00516 if (proc != (LONG_PTR)wined3d_wndproc) 00517 { 00518 wined3d_wndproc_mutex_unlock(); 00519 WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n", 00520 window, proc, wined3d_wndproc); 00521 return; 00522 } 00523 00524 SetWindowLongPtrW(window, GWLP_WNDPROC, (LONG_PTR)entry->proc); 00525 } 00526 else 00527 { 00528 proc = GetWindowLongPtrA(window, GWLP_WNDPROC); 00529 if (proc != (LONG_PTR)wined3d_wndproc) 00530 { 00531 wined3d_wndproc_mutex_unlock(); 00532 WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n", 00533 window, proc, wined3d_wndproc); 00534 return; 00535 } 00536 00537 SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)entry->proc); 00538 } 00539 00540 last = &wndproc_table.entries[--wndproc_table.count]; 00541 if (entry != last) *entry = *last; 00542 00543 wined3d_wndproc_mutex_unlock(); 00544 } 00545 00546 /* At process attach */ 00547 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 00548 { 00549 TRACE("WineD3D DLLMain Reason=%u\n", fdwReason); 00550 00551 switch (fdwReason) 00552 { 00553 case DLL_PROCESS_ATTACH: 00554 return wined3d_dll_init(hInstDLL); 00555 00556 case DLL_PROCESS_DETACH: 00557 return wined3d_dll_destroy(hInstDLL); 00558 00559 case DLL_THREAD_DETACH: 00560 { 00561 if (!context_set_current(NULL)) 00562 { 00563 ERR("Failed to clear current context.\n"); 00564 } 00565 return TRUE; 00566 } 00567 00568 default: 00569 return TRUE; 00570 } 00571 } Generated on Thu May 24 2012 04:22:39 for ReactOS by
1.7.6.1
|