| /* DirectDraw Base Functions | |
| * | |
| * Copyright 1997-1999 Marcus Meissner | |
| * Copyright 1998 Lionel Ulmer (most of Direct3D stuff) | |
| * Copyright 2000-2001 TransGaming Technologies Inc. | |
| * | |
| * This file contains the (internal) driver registration functions, | |
| * driver enumeration APIs and DirectDraw creation functions. | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #define GLPRIVATE_NO_REDEFINE | |
| #include "config.h" | |
| #include "wine/port.h" | |
| #include <assert.h> | |
| #include <stdarg.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #define COBJMACROS | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winnls.h" | |
| #include "winerror.h" | |
| #include "wingdi.h" | |
| #include "ddraw.h" | |
| #include "d3d.h" | |
| /* This for all the enumeration and creation of D3D-related objects */ | |
| #include "ddraw_private.h" | |
| #include "wine/debug.h" | |
| #include "wine/library.h" | |
| #include "gl_private.h" | |
| #undef GLPRIVATE_NO_REDEFINE | |
| #define MAX_DDRAW_DRIVERS 3 | |
| static const ddraw_driver* DDRAW_drivers[MAX_DDRAW_DRIVERS]; | |
| static int DDRAW_num_drivers; /* = 0 */ | |
| static int DDRAW_default_driver; | |
| void (*wine_tsx11_lock_ptr)(void) = NULL; | |
| void (*wine_tsx11_unlock_ptr)(void) = NULL; | |
| WINE_DEFAULT_DEBUG_CHANNEL(ddraw); | |
| /**********************************************************************/ | |
| typedef struct { | |
| LPVOID lpCallback; | |
| LPVOID lpContext; | |
| } DirectDrawEnumerateProcData; | |
| BOOL opengl_initialized = 0; | |
| #ifdef HAVE_OPENGL | |
| #include "mesa_private.h" | |
| static void *gl_handle = NULL; | |
| #define GL_API_FUNCTION(f) typeof(f) * p##f; | |
| #include "gl_api.h" | |
| #undef GL_API_FUNCTION | |
| #ifndef SONAME_LIBGL | |
| #define SONAME_LIBGL "libGL.so" | |
| #endif | |
| static BOOL DDRAW_bind_to_opengl( void ) | |
| { | |
| const char *glname = SONAME_LIBGL; | |
| gl_handle = wine_dlopen(glname, RTLD_NOW, NULL, 0); | |
| if (!gl_handle) { | |
| WARN("Wine cannot find the OpenGL graphics library (%s).\n",glname); | |
| return FALSE; | |
| } | |
| #define GL_API_FUNCTION(f) \ | |
| if((p##f = wine_dlsym(gl_handle, #f, NULL, 0)) == NULL) \ | |
| { \ | |
| WARN("Can't find symbol %s\n", #f); \ | |
| goto sym_not_found; \ | |
| } | |
| #include "gl_api.h" | |
| #undef GL_API_FUNCTION | |
| /* And now calls the function to initialize the various fields for the rendering devices */ | |
| return d3ddevice_init_at_startup(gl_handle); | |
| sym_not_found: | |
| WARN("Wine cannot find certain functions that it needs inside the OpenGL\n" | |
| "graphics library. To enable Wine to use OpenGL please upgrade\n" | |
| "your OpenGL libraries\n"); | |
| wine_dlclose(gl_handle, NULL, 0); | |
| gl_handle = NULL; | |
| return FALSE; | |
| } | |
| #endif /* HAVE_OPENGL */ | |
| BOOL s3tc_initialized = 0; | |
| static void *s3tc_handle = NULL; | |
| FUNC_FETCH_2D_TEXEL_RGBA_DXT1 fetch_2d_texel_rgba_dxt1; | |
| FUNC_FETCH_2D_TEXEL_RGBA_DXT3 fetch_2d_texel_rgba_dxt3; | |
| FUNC_FETCH_2D_TEXEL_RGBA_DXT5 fetch_2d_texel_rgba_dxt5; | |
| #ifndef SONAME_LIBTXC_DXTN | |
| #define SONAME_LIBTXC_DXTN "libtxc_dxtn.so" | |
| #endif | |
| static BOOL DDRAW_bind_to_s3tc( void ) | |
| { | |
| const char * const s3tcname = SONAME_LIBTXC_DXTN; | |
| s3tc_handle = wine_dlopen(s3tcname, RTLD_NOW, NULL, 0); | |
| if (!s3tc_handle) { | |
| TRACE("No S3TC software decompression library seems to be present (%s).\n",s3tcname); | |
| return FALSE; | |
| } | |
| TRACE("Found S3TC software decompression library (%s).\n",s3tcname); | |
| #define API_FUNCTION(f) \ | |
| if((f = wine_dlsym(s3tc_handle, #f, NULL, 0)) == NULL) \ | |
| { \ | |
| WARN("Can't find symbol %s\n", #f); \ | |
| goto sym_not_found; \ | |
| } | |
| API_FUNCTION(fetch_2d_texel_rgba_dxt1); | |
| API_FUNCTION(fetch_2d_texel_rgba_dxt3); | |
| API_FUNCTION(fetch_2d_texel_rgba_dxt5); | |
| #undef API_FUNCTION | |
| return TRUE; | |
| sym_not_found: | |
| WARN("Wine cannot find functions that are necessary for S3TC software decompression\n"); | |
| wine_dlclose(s3tc_handle, NULL, 0); | |
| s3tc_handle = NULL; | |
| return FALSE; | |
| } | |
| /******************************************************************************* | |
| * DirectDrawEnumerateExA (DDRAW.@) | |
| * | |
| * Enumerates all DirectDraw devices installed on the system. | |
| * | |
| * PARAMS | |
| * lpCallback [I] DDEnumCallbackEx function to be called with a description of | |
| * each enumerated HAL. | |
| * lpContext [I] application-defined value to be passed to the callback. | |
| * dwFlags [I] Specifies the enumeration scope. see msdn. | |
| * | |
| * RETURNS | |
| * Success: DD_OK. | |
| * Failure: DDERR_INVALIDPARAMS | |
| */ | |
| HRESULT WINAPI DirectDrawEnumerateExA( | |
| LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags) | |
| { | |
| int i; | |
| TRACE("(%p,%p, %08lx)\n", lpCallback, lpContext, dwFlags); | |
| if (TRACE_ON(ddraw)) { | |
| TRACE(" Flags : "); | |
| if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES) | |
| TRACE("DDENUM_ATTACHEDSECONDARYDEVICES "); | |
| if (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES) | |
| TRACE("DDENUM_DETACHEDSECONDARYDEVICES "); | |
| if (dwFlags & DDENUM_NONDISPLAYDEVICES) | |
| TRACE("DDENUM_NONDISPLAYDEVICES "); | |
| TRACE("\n"); | |
| } | |
| for (i=0; i<DDRAW_num_drivers; i++) | |
| { | |
| TRACE("Enumerating %s/%s interface\n", | |
| DDRAW_drivers[i]->info->szDriver, | |
| DDRAW_drivers[i]->info->szDescription); | |
| /* We have to pass NULL from the primary display device. | |
| * RoadRage chapter 6's enumeration routine expects it. */ | |
| if (!lpCallback((DDRAW_default_driver == i) ? NULL | |
| :(LPGUID)&DDRAW_drivers[i]->info->guidDeviceIdentifier, | |
| (LPSTR)DDRAW_drivers[i]->info->szDescription, | |
| (LPSTR)DDRAW_drivers[i]->info->szDriver, | |
| lpContext, 0)) | |
| return DD_OK; | |
| } | |
| /* Unsupported flags */ | |
| if (dwFlags & DDENUM_NONDISPLAYDEVICES) { | |
| FIXME("no non-display devices supported.\n"); | |
| } | |
| if (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES) { | |
| FIXME("no detached secondary devices supported.\n"); | |
| } | |
| return DD_OK; | |
| } | |
| /******************************************************************************* | |
| * DirectDrawEnumerateExW (DDRAW.@) | |
| */ | |
| static BOOL CALLBACK DirectDrawEnumerateExProcW( | |
| GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, | |
| LPVOID lpContext, HMONITOR hm) | |
| { | |
| INT len; | |
| BOOL bResult; | |
| LPWSTR lpDriverDescriptionW, lpDriverNameW; | |
| DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext; | |
| len = MultiByteToWideChar( CP_ACP, 0, lpDriverDescription, -1, NULL, 0 ); | |
| lpDriverDescriptionW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); | |
| MultiByteToWideChar( CP_ACP, 0, lpDriverDescription, -1, lpDriverDescriptionW, len ); | |
| len = MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, NULL, 0 ); | |
| lpDriverNameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); | |
| MultiByteToWideChar( CP_ACP, 0, lpDriverName, -1, lpDriverNameW, len ); | |
| bResult = (*(LPDDENUMCALLBACKEXW *) pEPD->lpCallback)(lpGUID, lpDriverDescriptionW, | |
| lpDriverNameW, pEPD->lpContext, hm); | |
| HeapFree(GetProcessHeap(), 0, lpDriverDescriptionW); | |
| HeapFree(GetProcessHeap(), 0, lpDriverNameW); | |
| return bResult; | |
| } | |
| HRESULT WINAPI DirectDrawEnumerateExW( | |
| LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags) | |
| { | |
| DirectDrawEnumerateProcData epd; | |
| epd.lpCallback = (LPVOID) lpCallback; | |
| epd.lpContext = lpContext; | |
| return DirectDrawEnumerateExA(DirectDrawEnumerateExProcW, (LPVOID) &epd, 0); | |
| } | |
| /*********************************************************************** | |
| * DirectDrawEnumerateA (DDRAW.@) | |
| */ | |
| static BOOL CALLBACK DirectDrawEnumerateProcA( | |
| GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, | |
| LPVOID lpContext, HMONITOR hm) | |
| { | |
| DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext; | |
| return ((LPDDENUMCALLBACKA) pEPD->lpCallback)( | |
| lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext); | |
| } | |
| HRESULT WINAPI DirectDrawEnumerateA( | |
| LPDDENUMCALLBACKA lpCallback, LPVOID lpContext) | |
| { | |
| DirectDrawEnumerateProcData epd; | |
| epd.lpCallback = (LPVOID) lpCallback; | |
| epd.lpContext = lpContext; | |
| return DirectDrawEnumerateExA(DirectDrawEnumerateProcA, (LPVOID) &epd, 0); | |
| } | |
| /*********************************************************************** | |
| * DirectDrawEnumerateW (DDRAW.@) | |
| */ | |
| static BOOL WINAPI DirectDrawEnumerateProcW( | |
| GUID *lpGUID, LPWSTR lpDriverDescription, LPWSTR lpDriverName, | |
| LPVOID lpContext, HMONITOR hm) | |
| { | |
| DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext; | |
| return ((LPDDENUMCALLBACKW) pEPD->lpCallback)( | |
| lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext); | |
| } | |
| HRESULT WINAPI DirectDrawEnumerateW( | |
| LPDDENUMCALLBACKW lpCallback, LPVOID lpContext) | |
| { | |
| DirectDrawEnumerateProcData epd; | |
| epd.lpCallback = (LPVOID) lpCallback; | |
| epd.lpContext = lpContext; | |
| return DirectDrawEnumerateExW(DirectDrawEnumerateProcW, (LPVOID) &epd, 0); | |
| } | |
| /*********************************************************************** | |
| * DirectDrawCreate (DDRAW.@) | |
| */ | |
| const ddraw_driver* DDRAW_FindDriver(const GUID* pGUID) | |
| { | |
| static const GUID zeroGUID; /* gets zero-inited */ | |
| TRACE("(%s)\n", pGUID ? debugstr_guid(pGUID) : "(null)"); | |
| if (DDRAW_num_drivers == 0) return NULL; | |
| if (pGUID == (LPGUID)DDCREATE_EMULATIONONLY | |
| || pGUID == (LPGUID)DDCREATE_HARDWAREONLY) | |
| pGUID = NULL; | |
| if (pGUID == NULL || memcmp(pGUID, &zeroGUID, sizeof(GUID)) == 0) | |
| { | |
| /* Use the default driver. */ | |
| return DDRAW_drivers[DDRAW_default_driver]; | |
| } | |
| else | |
| { | |
| /* Look for a matching GUID. */ | |
| int i; | |
| for (i=0; i < DDRAW_num_drivers; i++) | |
| { | |
| if (IsEqualGUID(pGUID, | |
| &DDRAW_drivers[i]->info->guidDeviceIdentifier)) | |
| break; | |
| } | |
| if (i < DDRAW_num_drivers) | |
| { | |
| return DDRAW_drivers[i]; | |
| } | |
| else | |
| { | |
| ERR("(%s): did not recognize requested GUID.\n",debugstr_guid(pGUID)); | |
| return NULL; | |
| } | |
| } | |
| } | |
| static HRESULT DDRAW_Create( | |
| LPGUID lpGUID, LPVOID *lplpDD, LPUNKNOWN pUnkOuter, REFIID iid, BOOL ex | |
| ) { | |
| const ddraw_driver* driver; | |
| LPDIRECTDRAW7 pDD; | |
| HRESULT hr; | |
| TRACE("(%s,%p,%p,%d)\n", debugstr_guid(lpGUID), lplpDD, pUnkOuter, ex); | |
| if (DDRAW_num_drivers == 0) | |
| { | |
| WARN("no DirectDraw drivers registered\n"); | |
| return DDERR_INVALIDDIRECTDRAWGUID; | |
| } | |
| if (lpGUID == (LPGUID)DDCREATE_EMULATIONONLY | |
| || lpGUID == (LPGUID)DDCREATE_HARDWAREONLY) | |
| lpGUID = NULL; | |
| if (pUnkOuter != NULL) | |
| return DDERR_INVALIDPARAMS; /* CLASS_E_NOAGGREGATION? */ | |
| driver = DDRAW_FindDriver(lpGUID); | |
| if (driver == NULL) return DDERR_INVALIDDIRECTDRAWGUID; | |
| hr = driver->create(lpGUID, &pDD, pUnkOuter, ex); | |
| if (FAILED(hr)) return hr; | |
| hr = IDirectDraw7_QueryInterface(pDD, iid, lplpDD); | |
| IDirectDraw7_Release(pDD); | |
| return hr; | |
| } | |
| /*********************************************************************** | |
| * DirectDrawCreate (DDRAW.@) | |
| * | |
| * Only creates legacy IDirectDraw interfaces. | |
| * Cannot create IDirectDraw7 interfaces. | |
| * In theory. | |
| */ | |
| HRESULT WINAPI DirectDrawCreate( | |
| LPGUID lpGUID, LPDIRECTDRAW* lplpDD, LPUNKNOWN pUnkOuter | |
| ) { | |
| TRACE("(%s,%p,%p)\n", debugstr_guid(lpGUID), lplpDD, pUnkOuter); | |
| return DDRAW_Create(lpGUID, (LPVOID*) lplpDD, pUnkOuter, &IID_IDirectDraw, FALSE); | |
| } | |
| /*********************************************************************** | |
| * DirectDrawCreateEx (DDRAW.@) | |
| * | |
| * Only creates new IDirectDraw7 interfaces. | |
| * Supposed to fail if legacy interfaces are requested. | |
| * In theory. | |
| */ | |
| HRESULT WINAPI DirectDrawCreateEx( | |
| LPGUID lpGUID, LPVOID* lplpDD, REFIID iid, LPUNKNOWN pUnkOuter | |
| ) { | |
| TRACE("(%s,%p,%s,%p)\n", debugstr_guid(lpGUID), lplpDD, debugstr_guid(iid), pUnkOuter); | |
| if (!IsEqualGUID(iid, &IID_IDirectDraw7)) | |
| return DDERR_INVALIDPARAMS; | |
| return DDRAW_Create(lpGUID, lplpDD, pUnkOuter, iid, TRUE); | |
| } | |
| extern HRESULT Uninit_DirectDraw_Create(const GUID*, LPDIRECTDRAW7*, | |
| LPUNKNOWN, BOOL); | |
| /* This is for the class factory. */ | |
| static HRESULT DDRAW_CreateDirectDraw(IUnknown* pUnkOuter, REFIID iid, | |
| LPVOID* ppObj) | |
| { | |
| LPDIRECTDRAW7 pDD; | |
| HRESULT hr; | |
| BOOL ex; | |
| TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppObj); | |
| /* This is a mighty hack :-) */ | |
| if (IsEqualGUID(iid, &IID_IDirectDraw7)) | |
| ex = TRUE; | |
| else | |
| ex = FALSE; | |
| hr = Uninit_DirectDraw_Create(NULL, &pDD, pUnkOuter, ex); | |
| if (FAILED(hr)) return hr; | |
| hr = IDirectDraw7_QueryInterface(pDD, iid, ppObj); | |
| IDirectDraw_Release(pDD); | |
| return hr; | |
| } | |
| /****************************************************************************** | |
| * DirectDraw ClassFactory | |
| */ | |
| typedef struct { | |
| ICOM_VFIELD_MULTI(IClassFactory); | |
| DWORD ref; | |
| HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID iid, | |
| LPVOID *ppObj); | |
| } IClassFactoryImpl; | |
| struct object_creation_info | |
| { | |
| const CLSID *clsid; | |
| HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, | |
| LPVOID *ppObj); | |
| }; | |
| /* There should be more, but these are the only ones listed in the header | |
| * file. */ | |
| extern HRESULT DDRAW_CreateDirectDrawClipper(IUnknown *pUnkOuter, REFIID riid, | |
| LPVOID *ppObj); | |
| static const struct object_creation_info object_creation[] = | |
| { | |
| { &CLSID_DirectDraw, DDRAW_CreateDirectDraw }, | |
| { &CLSID_DirectDraw7, DDRAW_CreateDirectDraw }, | |
| { &CLSID_DirectDrawClipper, DDRAW_CreateDirectDrawClipper } | |
| }; | |
| static HRESULT WINAPI | |
| DDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) | |
| { | |
| IClassFactoryImpl *This = (IClassFactoryImpl *)iface; | |
| TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj); | |
| if (IsEqualGUID(riid, &IID_IUnknown) | |
| || IsEqualGUID(riid, &IID_IClassFactory)) | |
| { | |
| IClassFactory_AddRef(iface); | |
| *ppobj = This; | |
| return S_OK; | |
| } | |
| WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj); | |
| return E_NOINTERFACE; | |
| } | |
| static ULONG WINAPI DDCF_AddRef(LPCLASSFACTORY iface) | |
| { | |
| IClassFactoryImpl *This = (IClassFactoryImpl *)iface; | |
| ULONG ref = InterlockedIncrement(&This->ref); | |
| TRACE("(%p)->() incrementing from %ld.\n", This, ref - 1); | |
| return ref; | |
| } | |
| static ULONG WINAPI DDCF_Release(LPCLASSFACTORY iface) | |
| { | |
| IClassFactoryImpl *This = (IClassFactoryImpl *)iface; | |
| ULONG ref = InterlockedDecrement(&This->ref); | |
| TRACE("(%p)->() decrementing from %ld.\n", This, ref+1); | |
| if (ref == 0) | |
| HeapFree(GetProcessHeap(), 0, This); | |
| return ref; | |
| } | |
| static HRESULT WINAPI DDCF_CreateInstance( | |
| LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj | |
| ) | |
| { | |
| IClassFactoryImpl *This = (IClassFactoryImpl *)iface; | |
| TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); | |
| return This->pfnCreateInstance(pOuter, riid, ppobj); | |
| } | |
| static HRESULT WINAPI DDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) | |
| { | |
| IClassFactoryImpl *This = (IClassFactoryImpl *)iface; | |
| FIXME("(%p)->(%d),stub!\n",This,dolock); | |
| return S_OK; | |
| } | |
| static IClassFactoryVtbl DDCF_Vtbl = | |
| { | |
| DDCF_QueryInterface, | |
| DDCF_AddRef, | |
| DDCF_Release, | |
| DDCF_CreateInstance, | |
| DDCF_LockServer | |
| }; | |
| /******************************************************************************* | |
| * DllGetClassObject [DDRAW.@] | |
| * Retrieves class object from a DLL object | |
| * | |
| * NOTES | |
| * Docs say returns STDAPI | |
| * | |
| * PARAMS | |
| * rclsid [I] CLSID for the class object | |
| * riid [I] Reference to identifier of interface for class object | |
| * ppv [O] Address of variable to receive interface pointer for riid | |
| * | |
| * RETURNS | |
| * Success: S_OK | |
| * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG, | |
| * E_UNEXPECTED | |
| */ | |
| DWORD WINAPI DDRAW_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv) | |
| { | |
| unsigned int i; | |
| IClassFactoryImpl *factory; | |
| TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); | |
| if ( !IsEqualGUID( &IID_IClassFactory, riid ) | |
| && ! IsEqualGUID( &IID_IUnknown, riid) ) | |
| return E_NOINTERFACE; | |
| for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) | |
| { | |
| if (IsEqualGUID(object_creation[i].clsid, rclsid)) | |
| break; | |
| } | |
| if (i == sizeof(object_creation)/sizeof(object_creation[0])) | |
| { | |
| FIXME("%s: no class found.\n", debugstr_guid(rclsid)); | |
| return CLASS_E_CLASSNOTAVAILABLE; | |
| } | |
| factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory)); | |
| if (factory == NULL) return E_OUTOFMEMORY; | |
| ICOM_INIT_INTERFACE(factory, IClassFactory, DDCF_Vtbl); | |
| factory->ref = 1; | |
| factory->pfnCreateInstance = object_creation[i].pfnCreateInstance; | |
| *ppv = ICOM_INTERFACE(factory, IClassFactory); | |
| return S_OK; | |
| } | |
| /******************************************************************************* | |
| * DllCanUnloadNow [DDRAW.@] Determines whether the DLL is in use. | |
| * | |
| * RETURNS | |
| * Success: S_OK | |
| * Failure: S_FALSE | |
| */ | |
| DWORD WINAPI DDRAW_DllCanUnloadNow(void) { | |
| FIXME("(void): stub\n"); | |
| return S_FALSE; | |
| } | |
| /****************************************************************************** | |
| * Initialisation | |
| */ | |
| /* Choose which driver is considered the primary display driver. It will | |
| * be created when we get a NULL guid for the DirectDrawCreate(Ex). */ | |
| static int DDRAW_ChooseDefaultDriver(void) | |
| { | |
| int i; | |
| int best = 0; | |
| int best_score = 0; | |
| assert(DDRAW_num_drivers > 0); | |
| /* This algorithm is really stupid. */ | |
| for (i=0; i < DDRAW_num_drivers; i++) | |
| { | |
| if (DDRAW_drivers[i]->preference > best_score) | |
| { | |
| best_score = DDRAW_drivers[i]->preference; | |
| best = i; | |
| } | |
| } | |
| assert(best_score > 0); | |
| return best; | |
| } | |
| /*********************************************************************** | |
| * DllMain (DDRAW.0) | |
| */ | |
| BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) | |
| { | |
| /* If we were sufficiently cool, DDraw drivers would just be COM | |
| * objects, registered with a particular component category. */ | |
| DDRAW_HAL_Init(hInstDLL, fdwReason, lpv); | |
| DDRAW_User_Init(hInstDLL, fdwReason, lpv); | |
| if (fdwReason == DLL_PROCESS_ATTACH) | |
| { | |
| HMODULE mod; | |
| DisableThreadLibraryCalls(hInstDLL); | |
| mod = GetModuleHandleA( "x11drv.dll" ); | |
| if (mod) | |
| { | |
| wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" ); | |
| wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" ); | |
| } | |
| #ifdef HAVE_OPENGL | |
| opengl_initialized = DDRAW_bind_to_opengl(); | |
| #endif /* HAVE_OPENGL */ | |
| s3tc_initialized = DDRAW_bind_to_s3tc(); | |
| } | |
| if (DDRAW_num_drivers > 0) | |
| DDRAW_default_driver = DDRAW_ChooseDefaultDriver(); | |
| return TRUE; | |
| } | |
| /* Register a direct draw driver. This should be called from your init | |
| * function. (That's why there is no locking: your init func is called from | |
| * our DllInit, which is serialised.) */ | |
| void DDRAW_register_driver(const ddraw_driver *driver) | |
| { | |
| int i; | |
| for (i = 0; i < DDRAW_num_drivers; i++) | |
| { | |
| if (DDRAW_drivers[i] == driver) | |
| { | |
| ERR("Driver reregistering %p\n", driver); | |
| return; | |
| } | |
| } | |
| if (DDRAW_num_drivers == sizeof(DDRAW_drivers)/sizeof(DDRAW_drivers[0])) | |
| { | |
| ERR("too many DDRAW drivers\n"); | |
| return; | |
| } | |
| DDRAW_drivers[DDRAW_num_drivers++] = driver; | |
| } | |
| /* This totally doesn't belong here. */ | |
| LONG DDRAW_width_bpp_to_pitch(DWORD width, DWORD bpp) | |
| { | |
| LONG pitch; | |
| assert(bpp != 0); /* keeps happening... */ | |
| if (bpp == 15) bpp = 16; | |
| pitch = width * (bpp / 8); | |
| return pitch + (8 - (pitch % 8)) % 8; | |
| } |