Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. EmulateOpenGL.cpp
  5. Abstract:
  6. Notes:
  7. This is a general purpose shim for Quake engine based games.
  8. History:
  9. 09/02/2000 linstev Created
  10. 11/30/2000 a-brienw Converted to shim version 2.
  11. 03/02/2001 a-brienw Cleared data structure on allocation and checked
  12. to see that DX was released on detach
  13. --*/
  14. #include "precomp.h"
  15. #include "EmulateOpenGL_opengl32.hpp"
  16. extern Globals *g_OpenGLValues;
  17. extern BOOL g_bDoTexelAlignmentHack;
  18. IMPLEMENT_SHIM_BEGIN(EmulateOpenGL)
  19. #include "ShimHookMacro.h"
  20. APIHOOK_ENUM_BEGIN
  21. APIHOOK_ENUM_ENTRY(LoadLibraryA)
  22. APIHOOK_ENUM_ENTRY(FreeLibrary)
  23. APIHOOK_ENUM_END
  24. /*++
  25. Parse the command line.
  26. --*/
  27. BOOL ParseCommandLine(const char * commandLine)
  28. {
  29. // Force the default values
  30. g_bDoTexelAlignmentHack = FALSE;
  31. // Search the beginning of the command line for these switches
  32. //
  33. // Switch Default Meaning
  34. //================ ======= =========================================================
  35. // TexelAlignment No Translate geometry by (-0.5 pixels in x, -0.5 pixels in y)
  36. // along the screen/viewport plane. This is achieved by
  37. // fudging the projection matrix that is passed to D3D.
  38. // The purpose of this hack is to allow D3D rendering to accomodate
  39. // content that was authored for OpenGL with the dependency that
  40. // sampled texels end up pixel-aligned when drawn. The root of the
  41. // problem is that D3D and OpenGL definitions of texel center
  42. // differ by 0.5.
  43. // The "ideal" fix would have perturbed texture coordinates
  44. // rather than geometry, perhaps using texture transform,
  45. // but this would be more of a perf. issue than just mucking with
  46. // the projection matrix. The drawback to mucking with the
  47. // projection matrix is that all geometry gets
  48. // drawn (very slightly) offset from the intended locations on screen.
  49. // Hence, we make this hack optional.
  50. // (it is currently needed by Kingpin: Life of Crime - Whistler bug 402471)
  51. //
  52. //
  53. CSTRING_TRY
  54. {
  55. CString csCl(commandLine);
  56. CStringParser csParser(csCl, L";");
  57. int argc = csParser.GetCount();
  58. if (csParser.GetCount() == 0)
  59. {
  60. return TRUE; // Not an error
  61. }
  62. for (int i = 0; i < argc; ++i)
  63. {
  64. CString & csArg = csParser[i];
  65. DPFN( eDbgLevelSpew, "Argv[%d] == (%S)", i, csArg.Get());
  66. if (csArg.CompareNoCase(L"TexelAlignment") == 0)
  67. {
  68. g_bDoTexelAlignmentHack = TRUE;
  69. }
  70. // else if(csArg.CompareNoCase(L"AddYourNewParametersHere") == 0) {}
  71. }
  72. }
  73. CSTRING_CATCH
  74. {
  75. return FALSE;
  76. }
  77. return TRUE;
  78. }
  79. /*++
  80. Determine if there are any accelerated pixel formats available. This is done
  81. by enumerating the pixel formats and testing for acceleration.
  82. --*/
  83. BOOL
  84. IsGLAccelerated()
  85. {
  86. HMODULE hMod = NULL;
  87. HDC hdc = NULL;
  88. int i;
  89. PIXELFORMATDESCRIPTOR pfd;
  90. _pfn_wglDescribePixelFormat pfnDescribePixelFormat;
  91. //
  92. // Cache the last result if we've been here before
  93. //
  94. static iFormat = -1;
  95. if (iFormat != -1)
  96. {
  97. goto Exit;
  98. }
  99. //
  100. // Load original opengl
  101. //
  102. hMod = LoadLibraryA("opengl32");
  103. if (!hMod)
  104. {
  105. LOG("EmulateOpenGL", eDbgLevelError, "Failed to load OpenGL32");
  106. goto Exit;
  107. }
  108. //
  109. // Get wglDescribePixelFormat so we can enumerate pixel formats
  110. //
  111. pfnDescribePixelFormat = (_pfn_wglDescribePixelFormat) GetProcAddress(
  112. hMod, "wglDescribePixelFormat");
  113. if (!pfnDescribePixelFormat)
  114. {
  115. LOG("EmulateOpenGL", eDbgLevelError, "API wglDescribePixelFormat not found in OpenGL32");
  116. goto Exit;
  117. }
  118. //
  119. // Get a Display DC for enumeration
  120. //
  121. hdc = GetDC(NULL);
  122. if (!hdc)
  123. {
  124. LOG("EmulateOpenGL", eDbgLevelError, "GetDC(NULL) Failed");
  125. goto Exit;
  126. }
  127. //
  128. // Run the list of pixel formats looking for any that are non-generic,
  129. // i.e. accelerated by an ICD
  130. //
  131. i = 1;
  132. iFormat = 0;
  133. while ((*pfnDescribePixelFormat)(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
  134. {
  135. if ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) &&
  136. (pfd.dwFlags & PFD_SUPPORT_OPENGL) &&
  137. (!(pfd.dwFlags & PFD_GENERIC_FORMAT)))
  138. {
  139. iFormat = i;
  140. break;
  141. }
  142. i++;
  143. }
  144. Exit:
  145. if (hdc)
  146. {
  147. ReleaseDC(NULL, hdc);
  148. }
  149. if (hMod)
  150. {
  151. FreeLibrary(hMod);
  152. }
  153. return (iFormat > 0);
  154. }
  155. /*++
  156. Redirect OpenGL LoadLibrary to the current DLL. Note we don't have to call
  157. LoadLibrary ourselves to increase the ref count, since we hook FreeLibrary to
  158. make sure we don't get freed.
  159. --*/
  160. HINSTANCE
  161. APIHOOK(LoadLibraryA)(LPCSTR lpLibFileName)
  162. {
  163. if (lpLibFileName &&
  164. (stristr(lpLibFileName, "opengl32") || stristr(lpLibFileName, "glide2x")))
  165. {
  166. if (!IsGLAccelerated())
  167. {
  168. #ifdef DODPFS
  169. LOG( "EmulateOpenGL",
  170. eDbgLevelInfo,
  171. "No OpenGL acceleration detected: QuakeGL wrapper enabled" );
  172. #endif
  173. return g_hinstDll;
  174. }
  175. else
  176. {
  177. #ifdef DODPFS
  178. LOG( "EmulateOpenGL",
  179. eDbgLevelInfo,
  180. "OpenGL acceleration detected: Wrapper disabled" );
  181. #endif
  182. }
  183. }
  184. return ORIGINAL_API(LoadLibraryA)(lpLibFileName);
  185. }
  186. /*++
  187. Since this module is the quake wrapper, make sure we don't free ourselves.
  188. --*/
  189. BOOL
  190. APIHOOK(FreeLibrary)(HMODULE hLibModule)
  191. {
  192. BOOL bRet;
  193. if (hLibModule == g_hinstDll)
  194. {
  195. bRet = TRUE;
  196. }
  197. else
  198. {
  199. bRet = ORIGINAL_API(FreeLibrary)(hLibModule);
  200. }
  201. return bRet;
  202. }
  203. /*++
  204. Register hooked functions
  205. --*/
  206. BOOL
  207. NOTIFY_FUNCTION(DWORD fdwReason)
  208. {
  209. BOOL bSuccess = TRUE;
  210. if (fdwReason == DLL_PROCESS_ATTACH)
  211. {
  212. g_OpenGLValues = new Globals;
  213. if (g_OpenGLValues != NULL)
  214. {
  215. memset(g_OpenGLValues, 0, sizeof(Globals));
  216. }
  217. bSuccess &= ParseCommandLine(COMMAND_LINE);
  218. }
  219. else if (fdwReason == DLL_PROCESS_DETACH)
  220. {
  221. if (g_OpenGLValues != NULL)
  222. {
  223. if (g_OpenGLValues->m_d3ddev != NULL)
  224. {
  225. g_OpenGLValues->m_d3ddev->Release();
  226. g_OpenGLValues->m_d3ddev = 0;
  227. }
  228. }
  229. }
  230. bSuccess &= (g_OpenGLValues != NULL);
  231. return bSuccess;
  232. }
  233. HOOK_BEGIN
  234. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryA)
  235. APIHOOK_ENTRY(KERNEL32.DLL, FreeLibrary)
  236. CALL_NOTIFY_FUNCTION
  237. HOOK_END
  238. IMPLEMENT_SHIM_END