SDL_dx5video.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:72k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_dx5video.c,v 1.4 2002/04/22 21:38:05 wmay Exp $";
  21. #endif
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <malloc.h>
  25. #include <windows.h>
  26. #include "directx.h"
  27. /* Not yet in the mingw32 cross-compile headers */
  28. #ifndef CDS_FULLSCREEN
  29. #define CDS_FULLSCREEN 4
  30. #endif
  31. #include "SDL_error.h"
  32. #include "SDL_timer.h"
  33. #include "SDL_events.h"
  34. #include "SDL_syswm.h"
  35. #include "SDL_sysvideo.h"
  36. #include "SDL_RLEaccel_c.h"
  37. #include "SDL_blit.h"
  38. #include "SDL_pixels_c.h"
  39. #include "SDL_dx5video.h"
  40. #include "SDL_syswm_c.h"
  41. #include "SDL_sysmouse_c.h"
  42. #include "SDL_dx5events_c.h"
  43. #include "SDL_dx5yuv_c.h"
  44. #include "SDL_wingl_c.h"
  45. /* DirectX function pointers for video and events */
  46. HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
  47. HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
  48. /* This is the rect EnumModes2 uses */
  49. struct DX5EnumRect {
  50. SDL_Rect r;
  51. struct DX5EnumRect* next;
  52. };
  53. static struct DX5EnumRect *enumlists[NUM_MODELISTS];
  54. /*
  55.  * Experimentally determined values for c_cfDI* constants used in DirectX 5.0
  56.  */
  57. /* Keyboard */
  58. static DIOBJECTDATAFORMAT KBD_fmt[] = {
  59. { &GUID_Key, 0, 0x8000000C, 0x00000000 },
  60. { &GUID_Key, 1, 0x8000010C, 0x00000000 },
  61. { &GUID_Key, 2, 0x8000020C, 0x00000000 },
  62. { &GUID_Key, 3, 0x8000030C, 0x00000000 },
  63. { &GUID_Key, 4, 0x8000040C, 0x00000000 },
  64. { &GUID_Key, 5, 0x8000050C, 0x00000000 },
  65. { &GUID_Key, 6, 0x8000060C, 0x00000000 },
  66. { &GUID_Key, 7, 0x8000070C, 0x00000000 },
  67. { &GUID_Key, 8, 0x8000080C, 0x00000000 },
  68. { &GUID_Key, 9, 0x8000090C, 0x00000000 },
  69. { &GUID_Key, 10, 0x80000A0C, 0x00000000 },
  70. { &GUID_Key, 11, 0x80000B0C, 0x00000000 },
  71. { &GUID_Key, 12, 0x80000C0C, 0x00000000 },
  72. { &GUID_Key, 13, 0x80000D0C, 0x00000000 },
  73. { &GUID_Key, 14, 0x80000E0C, 0x00000000 },
  74. { &GUID_Key, 15, 0x80000F0C, 0x00000000 },
  75. { &GUID_Key, 16, 0x8000100C, 0x00000000 },
  76. { &GUID_Key, 17, 0x8000110C, 0x00000000 },
  77. { &GUID_Key, 18, 0x8000120C, 0x00000000 },
  78. { &GUID_Key, 19, 0x8000130C, 0x00000000 },
  79. { &GUID_Key, 20, 0x8000140C, 0x00000000 },
  80. { &GUID_Key, 21, 0x8000150C, 0x00000000 },
  81. { &GUID_Key, 22, 0x8000160C, 0x00000000 },
  82. { &GUID_Key, 23, 0x8000170C, 0x00000000 },
  83. { &GUID_Key, 24, 0x8000180C, 0x00000000 },
  84. { &GUID_Key, 25, 0x8000190C, 0x00000000 },
  85. { &GUID_Key, 26, 0x80001A0C, 0x00000000 },
  86. { &GUID_Key, 27, 0x80001B0C, 0x00000000 },
  87. { &GUID_Key, 28, 0x80001C0C, 0x00000000 },
  88. { &GUID_Key, 29, 0x80001D0C, 0x00000000 },
  89. { &GUID_Key, 30, 0x80001E0C, 0x00000000 },
  90. { &GUID_Key, 31, 0x80001F0C, 0x00000000 },
  91. { &GUID_Key, 32, 0x8000200C, 0x00000000 },
  92. { &GUID_Key, 33, 0x8000210C, 0x00000000 },
  93. { &GUID_Key, 34, 0x8000220C, 0x00000000 },
  94. { &GUID_Key, 35, 0x8000230C, 0x00000000 },
  95. { &GUID_Key, 36, 0x8000240C, 0x00000000 },
  96. { &GUID_Key, 37, 0x8000250C, 0x00000000 },
  97. { &GUID_Key, 38, 0x8000260C, 0x00000000 },
  98. { &GUID_Key, 39, 0x8000270C, 0x00000000 },
  99. { &GUID_Key, 40, 0x8000280C, 0x00000000 },
  100. { &GUID_Key, 41, 0x8000290C, 0x00000000 },
  101. { &GUID_Key, 42, 0x80002A0C, 0x00000000 },
  102. { &GUID_Key, 43, 0x80002B0C, 0x00000000 },
  103. { &GUID_Key, 44, 0x80002C0C, 0x00000000 },
  104. { &GUID_Key, 45, 0x80002D0C, 0x00000000 },
  105. { &GUID_Key, 46, 0x80002E0C, 0x00000000 },
  106. { &GUID_Key, 47, 0x80002F0C, 0x00000000 },
  107. { &GUID_Key, 48, 0x8000300C, 0x00000000 },
  108. { &GUID_Key, 49, 0x8000310C, 0x00000000 },
  109. { &GUID_Key, 50, 0x8000320C, 0x00000000 },
  110. { &GUID_Key, 51, 0x8000330C, 0x00000000 },
  111. { &GUID_Key, 52, 0x8000340C, 0x00000000 },
  112. { &GUID_Key, 53, 0x8000350C, 0x00000000 },
  113. { &GUID_Key, 54, 0x8000360C, 0x00000000 },
  114. { &GUID_Key, 55, 0x8000370C, 0x00000000 },
  115. { &GUID_Key, 56, 0x8000380C, 0x00000000 },
  116. { &GUID_Key, 57, 0x8000390C, 0x00000000 },
  117. { &GUID_Key, 58, 0x80003A0C, 0x00000000 },
  118. { &GUID_Key, 59, 0x80003B0C, 0x00000000 },
  119. { &GUID_Key, 60, 0x80003C0C, 0x00000000 },
  120. { &GUID_Key, 61, 0x80003D0C, 0x00000000 },
  121. { &GUID_Key, 62, 0x80003E0C, 0x00000000 },
  122. { &GUID_Key, 63, 0x80003F0C, 0x00000000 },
  123. { &GUID_Key, 64, 0x8000400C, 0x00000000 },
  124. { &GUID_Key, 65, 0x8000410C, 0x00000000 },
  125. { &GUID_Key, 66, 0x8000420C, 0x00000000 },
  126. { &GUID_Key, 67, 0x8000430C, 0x00000000 },
  127. { &GUID_Key, 68, 0x8000440C, 0x00000000 },
  128. { &GUID_Key, 69, 0x8000450C, 0x00000000 },
  129. { &GUID_Key, 70, 0x8000460C, 0x00000000 },
  130. { &GUID_Key, 71, 0x8000470C, 0x00000000 },
  131. { &GUID_Key, 72, 0x8000480C, 0x00000000 },
  132. { &GUID_Key, 73, 0x8000490C, 0x00000000 },
  133. { &GUID_Key, 74, 0x80004A0C, 0x00000000 },
  134. { &GUID_Key, 75, 0x80004B0C, 0x00000000 },
  135. { &GUID_Key, 76, 0x80004C0C, 0x00000000 },
  136. { &GUID_Key, 77, 0x80004D0C, 0x00000000 },
  137. { &GUID_Key, 78, 0x80004E0C, 0x00000000 },
  138. { &GUID_Key, 79, 0x80004F0C, 0x00000000 },
  139. { &GUID_Key, 80, 0x8000500C, 0x00000000 },
  140. { &GUID_Key, 81, 0x8000510C, 0x00000000 },
  141. { &GUID_Key, 82, 0x8000520C, 0x00000000 },
  142. { &GUID_Key, 83, 0x8000530C, 0x00000000 },
  143. { &GUID_Key, 84, 0x8000540C, 0x00000000 },
  144. { &GUID_Key, 85, 0x8000550C, 0x00000000 },
  145. { &GUID_Key, 86, 0x8000560C, 0x00000000 },
  146. { &GUID_Key, 87, 0x8000570C, 0x00000000 },
  147. { &GUID_Key, 88, 0x8000580C, 0x00000000 },
  148. { &GUID_Key, 89, 0x8000590C, 0x00000000 },
  149. { &GUID_Key, 90, 0x80005A0C, 0x00000000 },
  150. { &GUID_Key, 91, 0x80005B0C, 0x00000000 },
  151. { &GUID_Key, 92, 0x80005C0C, 0x00000000 },
  152. { &GUID_Key, 93, 0x80005D0C, 0x00000000 },
  153. { &GUID_Key, 94, 0x80005E0C, 0x00000000 },
  154. { &GUID_Key, 95, 0x80005F0C, 0x00000000 },
  155. { &GUID_Key, 96, 0x8000600C, 0x00000000 },
  156. { &GUID_Key, 97, 0x8000610C, 0x00000000 },
  157. { &GUID_Key, 98, 0x8000620C, 0x00000000 },
  158. { &GUID_Key, 99, 0x8000630C, 0x00000000 },
  159. { &GUID_Key, 100, 0x8000640C, 0x00000000 },
  160. { &GUID_Key, 101, 0x8000650C, 0x00000000 },
  161. { &GUID_Key, 102, 0x8000660C, 0x00000000 },
  162. { &GUID_Key, 103, 0x8000670C, 0x00000000 },
  163. { &GUID_Key, 104, 0x8000680C, 0x00000000 },
  164. { &GUID_Key, 105, 0x8000690C, 0x00000000 },
  165. { &GUID_Key, 106, 0x80006A0C, 0x00000000 },
  166. { &GUID_Key, 107, 0x80006B0C, 0x00000000 },
  167. { &GUID_Key, 108, 0x80006C0C, 0x00000000 },
  168. { &GUID_Key, 109, 0x80006D0C, 0x00000000 },
  169. { &GUID_Key, 110, 0x80006E0C, 0x00000000 },
  170. { &GUID_Key, 111, 0x80006F0C, 0x00000000 },
  171. { &GUID_Key, 112, 0x8000700C, 0x00000000 },
  172. { &GUID_Key, 113, 0x8000710C, 0x00000000 },
  173. { &GUID_Key, 114, 0x8000720C, 0x00000000 },
  174. { &GUID_Key, 115, 0x8000730C, 0x00000000 },
  175. { &GUID_Key, 116, 0x8000740C, 0x00000000 },
  176. { &GUID_Key, 117, 0x8000750C, 0x00000000 },
  177. { &GUID_Key, 118, 0x8000760C, 0x00000000 },
  178. { &GUID_Key, 119, 0x8000770C, 0x00000000 },
  179. { &GUID_Key, 120, 0x8000780C, 0x00000000 },
  180. { &GUID_Key, 121, 0x8000790C, 0x00000000 },
  181. { &GUID_Key, 122, 0x80007A0C, 0x00000000 },
  182. { &GUID_Key, 123, 0x80007B0C, 0x00000000 },
  183. { &GUID_Key, 124, 0x80007C0C, 0x00000000 },
  184. { &GUID_Key, 125, 0x80007D0C, 0x00000000 },
  185. { &GUID_Key, 126, 0x80007E0C, 0x00000000 },
  186. { &GUID_Key, 127, 0x80007F0C, 0x00000000 },
  187. { &GUID_Key, 128, 0x8000800C, 0x00000000 },
  188. { &GUID_Key, 129, 0x8000810C, 0x00000000 },
  189. { &GUID_Key, 130, 0x8000820C, 0x00000000 },
  190. { &GUID_Key, 131, 0x8000830C, 0x00000000 },
  191. { &GUID_Key, 132, 0x8000840C, 0x00000000 },
  192. { &GUID_Key, 133, 0x8000850C, 0x00000000 },
  193. { &GUID_Key, 134, 0x8000860C, 0x00000000 },
  194. { &GUID_Key, 135, 0x8000870C, 0x00000000 },
  195. { &GUID_Key, 136, 0x8000880C, 0x00000000 },
  196. { &GUID_Key, 137, 0x8000890C, 0x00000000 },
  197. { &GUID_Key, 138, 0x80008A0C, 0x00000000 },
  198. { &GUID_Key, 139, 0x80008B0C, 0x00000000 },
  199. { &GUID_Key, 140, 0x80008C0C, 0x00000000 },
  200. { &GUID_Key, 141, 0x80008D0C, 0x00000000 },
  201. { &GUID_Key, 142, 0x80008E0C, 0x00000000 },
  202. { &GUID_Key, 143, 0x80008F0C, 0x00000000 },
  203. { &GUID_Key, 144, 0x8000900C, 0x00000000 },
  204. { &GUID_Key, 145, 0x8000910C, 0x00000000 },
  205. { &GUID_Key, 146, 0x8000920C, 0x00000000 },
  206. { &GUID_Key, 147, 0x8000930C, 0x00000000 },
  207. { &GUID_Key, 148, 0x8000940C, 0x00000000 },
  208. { &GUID_Key, 149, 0x8000950C, 0x00000000 },
  209. { &GUID_Key, 150, 0x8000960C, 0x00000000 },
  210. { &GUID_Key, 151, 0x8000970C, 0x00000000 },
  211. { &GUID_Key, 152, 0x8000980C, 0x00000000 },
  212. { &GUID_Key, 153, 0x8000990C, 0x00000000 },
  213. { &GUID_Key, 154, 0x80009A0C, 0x00000000 },
  214. { &GUID_Key, 155, 0x80009B0C, 0x00000000 },
  215. { &GUID_Key, 156, 0x80009C0C, 0x00000000 },
  216. { &GUID_Key, 157, 0x80009D0C, 0x00000000 },
  217. { &GUID_Key, 158, 0x80009E0C, 0x00000000 },
  218. { &GUID_Key, 159, 0x80009F0C, 0x00000000 },
  219. { &GUID_Key, 160, 0x8000A00C, 0x00000000 },
  220. { &GUID_Key, 161, 0x8000A10C, 0x00000000 },
  221. { &GUID_Key, 162, 0x8000A20C, 0x00000000 },
  222. { &GUID_Key, 163, 0x8000A30C, 0x00000000 },
  223. { &GUID_Key, 164, 0x8000A40C, 0x00000000 },
  224. { &GUID_Key, 165, 0x8000A50C, 0x00000000 },
  225. { &GUID_Key, 166, 0x8000A60C, 0x00000000 },
  226. { &GUID_Key, 167, 0x8000A70C, 0x00000000 },
  227. { &GUID_Key, 168, 0x8000A80C, 0x00000000 },
  228. { &GUID_Key, 169, 0x8000A90C, 0x00000000 },
  229. { &GUID_Key, 170, 0x8000AA0C, 0x00000000 },
  230. { &GUID_Key, 171, 0x8000AB0C, 0x00000000 },
  231. { &GUID_Key, 172, 0x8000AC0C, 0x00000000 },
  232. { &GUID_Key, 173, 0x8000AD0C, 0x00000000 },
  233. { &GUID_Key, 174, 0x8000AE0C, 0x00000000 },
  234. { &GUID_Key, 175, 0x8000AF0C, 0x00000000 },
  235. { &GUID_Key, 176, 0x8000B00C, 0x00000000 },
  236. { &GUID_Key, 177, 0x8000B10C, 0x00000000 },
  237. { &GUID_Key, 178, 0x8000B20C, 0x00000000 },
  238. { &GUID_Key, 179, 0x8000B30C, 0x00000000 },
  239. { &GUID_Key, 180, 0x8000B40C, 0x00000000 },
  240. { &GUID_Key, 181, 0x8000B50C, 0x00000000 },
  241. { &GUID_Key, 182, 0x8000B60C, 0x00000000 },
  242. { &GUID_Key, 183, 0x8000B70C, 0x00000000 },
  243. { &GUID_Key, 184, 0x8000B80C, 0x00000000 },
  244. { &GUID_Key, 185, 0x8000B90C, 0x00000000 },
  245. { &GUID_Key, 186, 0x8000BA0C, 0x00000000 },
  246. { &GUID_Key, 187, 0x8000BB0C, 0x00000000 },
  247. { &GUID_Key, 188, 0x8000BC0C, 0x00000000 },
  248. { &GUID_Key, 189, 0x8000BD0C, 0x00000000 },
  249. { &GUID_Key, 190, 0x8000BE0C, 0x00000000 },
  250. { &GUID_Key, 191, 0x8000BF0C, 0x00000000 },
  251. { &GUID_Key, 192, 0x8000C00C, 0x00000000 },
  252. { &GUID_Key, 193, 0x8000C10C, 0x00000000 },
  253. { &GUID_Key, 194, 0x8000C20C, 0x00000000 },
  254. { &GUID_Key, 195, 0x8000C30C, 0x00000000 },
  255. { &GUID_Key, 196, 0x8000C40C, 0x00000000 },
  256. { &GUID_Key, 197, 0x8000C50C, 0x00000000 },
  257. { &GUID_Key, 198, 0x8000C60C, 0x00000000 },
  258. { &GUID_Key, 199, 0x8000C70C, 0x00000000 },
  259. { &GUID_Key, 200, 0x8000C80C, 0x00000000 },
  260. { &GUID_Key, 201, 0x8000C90C, 0x00000000 },
  261. { &GUID_Key, 202, 0x8000CA0C, 0x00000000 },
  262. { &GUID_Key, 203, 0x8000CB0C, 0x00000000 },
  263. { &GUID_Key, 204, 0x8000CC0C, 0x00000000 },
  264. { &GUID_Key, 205, 0x8000CD0C, 0x00000000 },
  265. { &GUID_Key, 206, 0x8000CE0C, 0x00000000 },
  266. { &GUID_Key, 207, 0x8000CF0C, 0x00000000 },
  267. { &GUID_Key, 208, 0x8000D00C, 0x00000000 },
  268. { &GUID_Key, 209, 0x8000D10C, 0x00000000 },
  269. { &GUID_Key, 210, 0x8000D20C, 0x00000000 },
  270. { &GUID_Key, 211, 0x8000D30C, 0x00000000 },
  271. { &GUID_Key, 212, 0x8000D40C, 0x00000000 },
  272. { &GUID_Key, 213, 0x8000D50C, 0x00000000 },
  273. { &GUID_Key, 214, 0x8000D60C, 0x00000000 },
  274. { &GUID_Key, 215, 0x8000D70C, 0x00000000 },
  275. { &GUID_Key, 216, 0x8000D80C, 0x00000000 },
  276. { &GUID_Key, 217, 0x8000D90C, 0x00000000 },
  277. { &GUID_Key, 218, 0x8000DA0C, 0x00000000 },
  278. { &GUID_Key, 219, 0x8000DB0C, 0x00000000 },
  279. { &GUID_Key, 220, 0x8000DC0C, 0x00000000 },
  280. { &GUID_Key, 221, 0x8000DD0C, 0x00000000 },
  281. { &GUID_Key, 222, 0x8000DE0C, 0x00000000 },
  282. { &GUID_Key, 223, 0x8000DF0C, 0x00000000 },
  283. { &GUID_Key, 224, 0x8000E00C, 0x00000000 },
  284. { &GUID_Key, 225, 0x8000E10C, 0x00000000 },
  285. { &GUID_Key, 226, 0x8000E20C, 0x00000000 },
  286. { &GUID_Key, 227, 0x8000E30C, 0x00000000 },
  287. { &GUID_Key, 228, 0x8000E40C, 0x00000000 },
  288. { &GUID_Key, 229, 0x8000E50C, 0x00000000 },
  289. { &GUID_Key, 230, 0x8000E60C, 0x00000000 },
  290. { &GUID_Key, 231, 0x8000E70C, 0x00000000 },
  291. { &GUID_Key, 232, 0x8000E80C, 0x00000000 },
  292. { &GUID_Key, 233, 0x8000E90C, 0x00000000 },
  293. { &GUID_Key, 234, 0x8000EA0C, 0x00000000 },
  294. { &GUID_Key, 235, 0x8000EB0C, 0x00000000 },
  295. { &GUID_Key, 236, 0x8000EC0C, 0x00000000 },
  296. { &GUID_Key, 237, 0x8000ED0C, 0x00000000 },
  297. { &GUID_Key, 238, 0x8000EE0C, 0x00000000 },
  298. { &GUID_Key, 239, 0x8000EF0C, 0x00000000 },
  299. { &GUID_Key, 240, 0x8000F00C, 0x00000000 },
  300. { &GUID_Key, 241, 0x8000F10C, 0x00000000 },
  301. { &GUID_Key, 242, 0x8000F20C, 0x00000000 },
  302. { &GUID_Key, 243, 0x8000F30C, 0x00000000 },
  303. { &GUID_Key, 244, 0x8000F40C, 0x00000000 },
  304. { &GUID_Key, 245, 0x8000F50C, 0x00000000 },
  305. { &GUID_Key, 246, 0x8000F60C, 0x00000000 },
  306. { &GUID_Key, 247, 0x8000F70C, 0x00000000 },
  307. { &GUID_Key, 248, 0x8000F80C, 0x00000000 },
  308. { &GUID_Key, 249, 0x8000F90C, 0x00000000 },
  309. { &GUID_Key, 250, 0x8000FA0C, 0x00000000 },
  310. { &GUID_Key, 251, 0x8000FB0C, 0x00000000 },
  311. { &GUID_Key, 252, 0x8000FC0C, 0x00000000 },
  312. { &GUID_Key, 253, 0x8000FD0C, 0x00000000 },
  313. { &GUID_Key, 254, 0x8000FE0C, 0x00000000 },
  314. { &GUID_Key, 255, 0x8000FF0C, 0x00000000 },
  315. };
  316. const DIDATAFORMAT c_dfDIKeyboard = { 24, 16, 0x00000002, 256, 256, KBD_fmt };
  317. /* Mouse */
  318. static DIOBJECTDATAFORMAT PTR_fmt[] = {
  319. { &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 },
  320. { &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 },
  321. { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 },
  322. { NULL, 12, 0x00FFFF0C, 0x00000000 },
  323. { NULL, 13, 0x00FFFF0C, 0x00000000 },
  324. { NULL, 14, 0x80FFFF0C, 0x00000000 },
  325. { NULL, 15, 0x80FFFF0C, 0x00000000 },
  326. };
  327. const DIDATAFORMAT c_dfDIMouse = { 24, 16, 0x00000002, 16, 7, PTR_fmt };
  328. /* Joystick */
  329. static DIOBJECTDATAFORMAT JOY_fmt[] = {
  330. { &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 },
  331. { &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 },
  332. { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 },
  333. { &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 },
  334. { &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 },
  335. { &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 },
  336. { &GUID_Slider, 24, 0x80FFFF03, 0x00000100 },
  337. { &GUID_Slider, 28, 0x80FFFF03, 0x00000100 },
  338. { &GUID_POV, 32, 0x80FFFF10, 0x00000000 },
  339. { &GUID_POV, 36, 0x80FFFF10, 0x00000000 },
  340. { &GUID_POV, 40, 0x80FFFF10, 0x00000000 },
  341. { &GUID_POV, 44, 0x80FFFF10, 0x00000000 },
  342. { NULL, 48, 0x80FFFF0C, 0x00000000 },
  343. { NULL, 49, 0x80FFFF0C, 0x00000000 },
  344. { NULL, 50, 0x80FFFF0C, 0x00000000 },
  345. { NULL, 51, 0x80FFFF0C, 0x00000000 },
  346. { NULL, 52, 0x80FFFF0C, 0x00000000 },
  347. { NULL, 53, 0x80FFFF0C, 0x00000000 },
  348. { NULL, 54, 0x80FFFF0C, 0x00000000 },
  349. { NULL, 55, 0x80FFFF0C, 0x00000000 },
  350. { NULL, 56, 0x80FFFF0C, 0x00000000 },
  351. { NULL, 57, 0x80FFFF0C, 0x00000000 },
  352. { NULL, 58, 0x80FFFF0C, 0x00000000 },
  353. { NULL, 59, 0x80FFFF0C, 0x00000000 },
  354. { NULL, 60, 0x80FFFF0C, 0x00000000 },
  355. { NULL, 61, 0x80FFFF0C, 0x00000000 },
  356. { NULL, 62, 0x80FFFF0C, 0x00000000 },
  357. { NULL, 63, 0x80FFFF0C, 0x00000000 },
  358. { NULL, 64, 0x80FFFF0C, 0x00000000 },
  359. { NULL, 65, 0x80FFFF0C, 0x00000000 },
  360. { NULL, 66, 0x80FFFF0C, 0x00000000 },
  361. { NULL, 67, 0x80FFFF0C, 0x00000000 },
  362. { NULL, 68, 0x80FFFF0C, 0x00000000 },
  363. { NULL, 69, 0x80FFFF0C, 0x00000000 },
  364. { NULL, 70, 0x80FFFF0C, 0x00000000 },
  365. { NULL, 71, 0x80FFFF0C, 0x00000000 },
  366. { NULL, 72, 0x80FFFF0C, 0x00000000 },
  367. { NULL, 73, 0x80FFFF0C, 0x00000000 },
  368. { NULL, 74, 0x80FFFF0C, 0x00000000 },
  369. { NULL, 75, 0x80FFFF0C, 0x00000000 },
  370. { NULL, 76, 0x80FFFF0C, 0x00000000 },
  371. { NULL, 77, 0x80FFFF0C, 0x00000000 },
  372. { NULL, 78, 0x80FFFF0C, 0x00000000 },
  373. { NULL, 79, 0x80FFFF0C, 0x00000000 },
  374. };
  375. const DIDATAFORMAT c_dfDIJoystick = { 24, 16, 0x00000001, 80, 44, JOY_fmt };
  376. /* Initialization/Query functions */
  377. static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat);
  378. static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
  379. static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
  380. static int DX5_SetColors(_THIS, int firstcolor, int ncolors,
  381.  SDL_Color *colors);
  382. static int DX5_SetGammaRamp(_THIS, Uint16 *ramp);
  383. static int DX5_GetGammaRamp(_THIS, Uint16 *ramp);
  384. static void DX5_VideoQuit(_THIS);
  385. /* Hardware surface functions */
  386. static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface);
  387. static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
  388. static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
  389. static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
  390. static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
  391. static int DX5_LockHWSurface(_THIS, SDL_Surface *surface);
  392. static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface);
  393. static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface);
  394. static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface);
  395. static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
  396. LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
  397. /* Windows message handling functions */
  398. static void DX5_RealizePalette(_THIS);
  399. static void DX5_PaletteChanged(_THIS, HWND window);
  400. static void DX5_WinPAINT(_THIS, HDC hdc);
  401. /* WinDIB driver functions for manipulating gamma ramps */
  402. extern int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
  403. extern int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
  404. extern void DIB_QuitGamma(_THIS);
  405. /* DX5 driver bootstrap functions */
  406. static int DX5_Available(void)
  407. {
  408. HINSTANCE DInputDLL;
  409. HINSTANCE DDrawDLL;
  410. int dinput_ok;
  411. int ddraw_ok;
  412. /* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */
  413. dinput_ok = 0;
  414. DInputDLL = LoadLibrary("DINPUT.DLL");
  415. if ( DInputDLL != NULL ) {
  416. dinput_ok = 1;
  417.    FreeLibrary(DInputDLL);
  418. }
  419. ddraw_ok = 0;
  420. DDrawDLL = LoadLibrary("DDRAW.DLL");
  421. if ( DDrawDLL != NULL ) {
  422.   HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
  423.   LPDIRECTDRAW DDraw;
  424.   /* Try to create a valid DirectDraw object */
  425.   DDrawCreate = (void *)GetProcAddress(DDrawDLL, "DirectDrawCreate");
  426.   if ( (DDrawCreate != NULL)
  427. && !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) {
  428.     if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
  429. NULL, DDSCL_NORMAL)) ) {
  430.       DDSURFACEDESC desc;
  431.       LPDIRECTDRAWSURFACE  DDrawSurf;
  432.       LPDIRECTDRAWSURFACE3 DDrawSurf3;
  433.       /* Try to create a DirectDrawSurface3 object */
  434.       memset(&desc, 0, sizeof(desc));
  435.       desc.dwSize = sizeof(desc);
  436.       desc.dwFlags = DDSD_CAPS;
  437.       desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
  438.       if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc,
  439. &DDrawSurf, NULL)) ) {
  440.         if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf,
  441. &IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) {
  442.           /* Yay! */
  443.   ddraw_ok = 1;
  444.           /* Clean up.. */
  445.           IDirectDrawSurface3_Release(DDrawSurf3);
  446.         }
  447.         IDirectDrawSurface_Release(DDrawSurf);
  448.       }
  449.     }
  450.     IDirectDraw_Release(DDraw);
  451.   }
  452.   FreeLibrary(DDrawDLL);
  453. }
  454. return(dinput_ok && ddraw_ok);
  455. }
  456. /* Functions for loading the DirectX functions dynamically */
  457. static HINSTANCE DDrawDLL = NULL;
  458. static HINSTANCE DInputDLL = NULL;
  459. static void DX5_Unload(void)
  460. {
  461. if ( DDrawDLL != NULL ) {
  462. FreeLibrary(DDrawDLL);
  463. DDrawCreate = NULL;
  464. DDrawDLL = NULL;
  465. }
  466. if ( DInputDLL != NULL ) {
  467. FreeLibrary(DInputDLL);
  468. DInputCreate = NULL;
  469. DInputDLL = NULL;
  470. }
  471. }
  472. static int DX5_Load(void)
  473. {
  474. int status;
  475. DX5_Unload();
  476. DDrawDLL = LoadLibrary("DDRAW.DLL");
  477. if ( DDrawDLL != NULL ) {
  478. DDrawCreate = (void *)GetProcAddress(DDrawDLL,
  479. "DirectDrawCreate");
  480. }
  481. DInputDLL = LoadLibrary("DINPUT.DLL");
  482. if ( DInputDLL != NULL ) {
  483. DInputCreate = (void *)GetProcAddress(DInputDLL,
  484. "DirectInputCreateA");
  485. }
  486. if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) {
  487. status = 0;
  488. } else {
  489. DX5_Unload();
  490. status = -1;
  491. }
  492. return status;
  493. }
  494. static void DX5_DeleteDevice(SDL_VideoDevice *this)
  495. {
  496. /* Free DirectDraw object */
  497. if ( ddraw2 != NULL ) {
  498. IDirectDraw2_Release(ddraw2);
  499. }
  500. DX5_Unload();
  501. if ( this ) {
  502. if ( this->hidden ) {
  503. free(this->hidden);
  504. }
  505. if ( this->gl_data ) {
  506. free(this->gl_data);
  507. }
  508. free(this);
  509. }
  510. }
  511. static SDL_VideoDevice *DX5_CreateDevice(int devindex)
  512. {
  513. SDL_VideoDevice *device;
  514. /* Load DirectX */
  515. if ( DX5_Load() < 0 ) {
  516. return(NULL);
  517. }
  518. /* Initialize all variables that we clean on shutdown */
  519. device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
  520. if ( device ) {
  521. memset(device, 0, (sizeof *device));
  522. device->hidden = (struct SDL_PrivateVideoData *)
  523. malloc((sizeof *device->hidden));
  524. device->gl_data = (struct SDL_PrivateGLData *)
  525. malloc((sizeof *device->gl_data));
  526. }
  527. if ( (device == NULL) || (device->hidden == NULL) ||
  528.                  (device->gl_data == NULL) ) {
  529. SDL_OutOfMemory();
  530. DX5_DeleteDevice(device);
  531. return(NULL);
  532. }
  533. memset(device->hidden, 0, (sizeof *device->hidden));
  534. memset(device->gl_data, 0, (sizeof *device->gl_data));
  535. /* Set the function pointers */
  536. device->VideoInit = DX5_VideoInit;
  537. device->ListModes = DX5_ListModes;
  538. device->SetVideoMode = DX5_SetVideoMode;
  539. device->UpdateMouse = WIN_UpdateMouse;
  540. device->CreateYUVOverlay = DX5_CreateYUVOverlay;
  541. device->SetColors = DX5_SetColors;
  542. device->UpdateRects = NULL;
  543. device->VideoQuit = DX5_VideoQuit;
  544. device->AllocHWSurface = DX5_AllocHWSurface;
  545. device->CheckHWBlit = DX5_CheckHWBlit;
  546. device->FillHWRect = DX5_FillHWRect;
  547. device->SetHWColorKey = DX5_SetHWColorKey;
  548. device->SetHWAlpha = DX5_SetHWAlpha;
  549. device->LockHWSurface = DX5_LockHWSurface;
  550. device->UnlockHWSurface = DX5_UnlockHWSurface;
  551. device->FlipHWSurface = DX5_FlipHWSurface;
  552. device->FreeHWSurface = DX5_FreeHWSurface;
  553. device->SetGammaRamp = DX5_SetGammaRamp;
  554. device->GetGammaRamp = DX5_GetGammaRamp;
  555. #ifdef HAVE_OPENGL
  556.         device->GL_LoadLibrary = WIN_GL_LoadLibrary;
  557.         device->GL_GetProcAddress = WIN_GL_GetProcAddress;
  558.         device->GL_GetAttribute = WIN_GL_GetAttribute;
  559.         device->GL_MakeCurrent = WIN_GL_MakeCurrent;
  560.         device->GL_SwapBuffers = WIN_GL_SwapBuffers;
  561. #endif
  562. device->SetCaption = WIN_SetWMCaption;
  563. device->SetIcon = WIN_SetWMIcon;
  564. device->IconifyWindow = WIN_IconifyWindow;
  565. device->GrabInput = WIN_GrabInput;
  566. device->GetWMInfo = WIN_GetWMInfo;
  567. device->FreeWMCursor = WIN_FreeWMCursor;
  568. device->CreateWMCursor = WIN_CreateWMCursor;
  569. device->ShowWMCursor = WIN_ShowWMCursor;
  570. device->WarpWMCursor = WIN_WarpWMCursor;
  571. device->CheckMouseMode = WIN_CheckMouseMode;
  572. device->InitOSKeymap = DX5_InitOSKeymap;
  573. device->PumpEvents = DX5_PumpEvents;
  574. /* Set up the windows message handling functions */
  575. WIN_RealizePalette = DX5_RealizePalette;
  576. WIN_PaletteChanged = DX5_PaletteChanged;
  577. WIN_WinPAINT = DX5_WinPAINT;
  578. HandleMessage = DX5_HandleMessage;
  579. device->free = DX5_DeleteDevice;
  580. /* We're finally ready */
  581. return device;
  582. }
  583. VideoBootStrap DIRECTX_bootstrap = {
  584. "directx", "Win95/98/2000 DirectX",
  585. DX5_Available, DX5_CreateDevice
  586. };
  587. static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata)
  588. {
  589. SDL_VideoDevice *this = (SDL_VideoDevice *)udata;
  590. struct DX5EnumRect *enumrect;
  591. #if defined(NONAMELESSUNION)
  592. int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
  593. #else
  594. int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
  595. #endif
  596. switch (bpp)  {
  597. case 8:
  598. case 16:
  599. case 24:
  600. case 32:
  601. bpp /= 8; --bpp;
  602. ++SDL_nummodes[bpp];
  603. enumrect = (struct DX5EnumRect*)malloc(sizeof(struct DX5EnumRect));
  604. if ( !enumrect ) {
  605. SDL_OutOfMemory();
  606. return(DDENUMRET_CANCEL);
  607. }
  608. enumrect->r.x = 0;
  609. enumrect->r.y = 0;
  610. enumrect->r.w = (Uint16)desc->dwWidth;
  611. enumrect->r.h = (Uint16)desc->dwHeight;
  612. enumrect->next = enumlists[bpp];
  613. enumlists[bpp] = enumrect;
  614. break;
  615. }
  616. return(DDENUMRET_OK);
  617. }
  618. void SetDDerror(const char *function, int code)
  619. {
  620. static char *error;
  621. static char  errbuf[BUFSIZ];
  622. errbuf[0] = 0;
  623. switch (code) {
  624. case DDERR_GENERIC:
  625. error = "Undefined error!";
  626. break;
  627. case DDERR_EXCEPTION:
  628. error = "Exception encountered";
  629. break;
  630. case DDERR_INVALIDOBJECT:
  631. error = "Invalid object";
  632. break;
  633. case DDERR_INVALIDPARAMS:
  634. error = "Invalid parameters";
  635. break;
  636. case DDERR_NOTFOUND:
  637. error = "Object not found";
  638. break;
  639. case DDERR_INVALIDRECT:
  640. error = "Invalid rectangle";
  641. break;
  642. case DDERR_INVALIDCAPS:
  643. error = "Invalid caps member";
  644. break;
  645. case DDERR_INVALIDPIXELFORMAT:
  646. error = "Invalid pixel format";
  647. break;
  648. case DDERR_OUTOFMEMORY:
  649. error = "Out of memory";
  650. break;
  651. case DDERR_OUTOFVIDEOMEMORY:
  652. error = "Out of video memory";
  653. break;
  654. case DDERR_SURFACEBUSY:
  655. error = "Surface busy";
  656. break;
  657. case DDERR_SURFACELOST:
  658. error = "Surface was lost";
  659. break;
  660. case DDERR_WASSTILLDRAWING:
  661. error = "DirectDraw is still drawing";
  662. break;
  663. case DDERR_INVALIDSURFACETYPE:
  664. error = "Invalid surface type";
  665. break;
  666. case DDERR_NOEXCLUSIVEMODE:
  667. error = "Not in exclusive access mode";
  668. break;
  669. case DDERR_NOPALETTEATTACHED:
  670. error = "No palette attached";
  671. break;
  672. case DDERR_NOPALETTEHW:
  673. error = "No palette hardware";
  674. break;
  675. case DDERR_NOT8BITCOLOR:
  676. error = "Not 8-bit color";
  677. break;
  678. case DDERR_EXCLUSIVEMODEALREADYSET:
  679. error = "Exclusive mode was already set";
  680. break;
  681. case DDERR_HWNDALREADYSET:
  682. error = "Window handle already set";
  683. break;
  684. case DDERR_HWNDSUBCLASSED:
  685. error = "Window handle is subclassed";
  686. break;
  687. case DDERR_NOBLTHW:
  688. error = "No blit hardware";
  689. break;
  690. case DDERR_IMPLICITLYCREATED:
  691. error = "Surface was implicitly created";
  692. break;
  693. case DDERR_INCOMPATIBLEPRIMARY:
  694. error = "Incompatible primary surface";
  695. break;
  696. case DDERR_NOCOOPERATIVELEVELSET:
  697. error = "No cooperative level set";
  698. break;
  699. case DDERR_NODIRECTDRAWHW:
  700. error = "No DirectDraw hardware";
  701. break;
  702. case DDERR_NOEMULATION:
  703. error = "No emulation available";
  704. break;
  705. case DDERR_NOFLIPHW:
  706. error = "No flip hardware";
  707. break;
  708. case DDERR_NOTFLIPPABLE:
  709. error = "Surface not flippable";
  710. break;
  711. case DDERR_PRIMARYSURFACEALREADYEXISTS:
  712. error = "Primary surface already exists";
  713. break;
  714. case DDERR_UNSUPPORTEDMODE:
  715. error = "Unsupported mode";
  716. break;
  717. case DDERR_WRONGMODE:
  718. error = "Surface created in different mode";
  719. break;
  720. case DDERR_UNSUPPORTED:
  721. error = "Operation not supported";
  722. break;
  723. case E_NOINTERFACE:
  724. error = "Interface not present";
  725. break;
  726. default:
  727. sprintf(errbuf, "%s: Unknown DirectDraw error: 0x%x",
  728. function, code);
  729. break;
  730. }
  731. if ( ! errbuf[0] ) {
  732. sprintf(errbuf, "%s: %s", function, error);
  733. }
  734. SDL_SetError("%s", errbuf);
  735. return;
  736. }
  737. static int DX5_UpdateVideoInfo(_THIS)
  738. {
  739. /* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */
  740. #if DIRECTDRAW_VERSION <= 0x300
  741. #error Your version of DirectX must be greater than or equal to 5.0
  742. #endif
  743. #ifndef IDirectDrawGammaControl_SetGammaRamp
  744. /*if gamma is undefined then we really have directx <= 0x500*/
  745. DDCAPS DDCaps;
  746. #else
  747. DDCAPS_DX5 DDCaps;
  748. #endif
  749. HRESULT result;
  750. /* Fill in our hardware acceleration capabilities */
  751. memset(&DDCaps, 0, sizeof(DDCaps));
  752. DDCaps.dwSize = sizeof(DDCaps);
  753. result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL);
  754. if ( result != DD_OK ) {
  755. SetDDerror("DirectDraw2::GetCaps", result);
  756. return(-1);
  757. }
  758. this->info.hw_available = 1;
  759. if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) {
  760. this->info.blit_hw = 1;
  761. }
  762. if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) &&
  763.      ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) {
  764. this->info.blit_hw_CC = 1;
  765. }
  766. if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) {
  767. /* This is only for alpha channel, and DirectX 6
  768.    doesn't support 2D alpha blits yet, so set it 0
  769.  */
  770. this->info.blit_hw_A = 0;
  771. }
  772. if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) {
  773. this->info.blit_sw = 1;
  774. /* This isn't necessarily true, but the HEL will cover us */
  775. this->info.blit_sw_CC = this->info.blit_hw_CC;
  776. this->info.blit_sw_A = this->info.blit_hw_A;
  777. }
  778. if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) {
  779. this->info.blit_fill = 1;
  780. }
  781. /* Find out how much video memory is available */
  782. { DDSCAPS ddsCaps;
  783.   DWORD total_mem;
  784. ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
  785. result = IDirectDraw2_GetAvailableVidMem(ddraw2,
  786. &ddsCaps, &total_mem, NULL);
  787. if ( result != DD_OK ) {
  788. total_mem = DDCaps.dwVidMemTotal; 
  789. }
  790. this->info.video_mem = total_mem/1024;
  791. }
  792. return(0);
  793. }
  794. int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat)
  795. {
  796. HRESULT result;
  797. LPDIRECTDRAW ddraw;
  798. int i, j;
  799. HDC hdc;
  800. /* Intialize everything */
  801. ddraw2 = NULL;
  802. SDL_primary = NULL;
  803. SDL_clipper = NULL;
  804. SDL_palette = NULL;
  805. for ( i=0; i<NUM_MODELISTS; ++i ) {
  806. SDL_nummodes[i] = 0;
  807. SDL_modelist[i] = NULL;
  808. SDL_modeindex[i] = 0;
  809. }
  810. colorchange_expected = 0;
  811. /* Create the window */
  812. if ( DX5_CreateWindow(this) < 0 ) {
  813. return(-1);
  814. }
  815. #ifndef DISABLE_AUDIO
  816. DX5_SoundFocus(SDL_Window);
  817. #endif
  818. /* Create the DirectDraw object */
  819. result = DDrawCreate(NULL, &ddraw, NULL);
  820. if ( result != DD_OK ) {
  821. SetDDerror("DirectDrawCreate", result);
  822. return(-1);
  823. }
  824. result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2,
  825. (LPVOID *)&ddraw2);
  826. IDirectDraw_Release(ddraw);
  827. if ( result != DD_OK ) {
  828. SetDDerror("DirectDraw::QueryInterface", result);
  829. return(-1);
  830. }
  831. /* Determine the screen depth */
  832. hdc = GetDC(SDL_Window);
  833. vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) *
  834. GetDeviceCaps(hdc,BITSPIXEL);
  835. ReleaseDC(SDL_Window, hdc);
  836. /* Enumerate the available fullscreen modes */
  837. for ( i=0; i<NUM_MODELISTS; ++i )
  838. enumlists[i] = NULL;
  839. result = IDirectDraw2_EnumDisplayModes(ddraw2,0,NULL,this,EnumModes2);
  840. if ( result != DD_OK ) {
  841. SetDDerror("DirectDraw2::EnumDisplayModes", result);
  842. return(-1);
  843. }
  844. for ( i=0; i<NUM_MODELISTS; ++i ) {
  845. struct DX5EnumRect *rect;
  846. SDL_modelist[i] = (SDL_Rect **)
  847. malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *));
  848. if ( SDL_modelist[i] == NULL ) {
  849. SDL_OutOfMemory();
  850. return(-1);
  851. }
  852. for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
  853. SDL_modelist[i][j]=(SDL_Rect *)rect;
  854. }
  855. SDL_modelist[i][j] = NULL;
  856. }
  857. /* Fill in some window manager capabilities */
  858. this->info.wm_available = 1;
  859. /* Fill in the video hardware capabilities */
  860. DX5_UpdateVideoInfo(this);
  861. return(0);
  862. }
  863. SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
  864. {
  865. int bpp;
  866. bpp = format->BitsPerPixel;
  867. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  868. /* FIXME:  No support for 1 bpp or 4 bpp formats */
  869. switch (bpp) {  /* Does windows support other BPP? */
  870. case 8:
  871. case 16:
  872. case 24:
  873. case 32:
  874. bpp = (bpp/8)-1;
  875. if ( SDL_nummodes[bpp] > 0 )
  876. return(SDL_modelist[bpp]);
  877. /* Fall through */
  878. default:
  879. return((SDL_Rect **)0);
  880. }
  881. } else {
  882. if ( this->screen->format->BitsPerPixel == bpp ) {
  883. return((SDL_Rect **)-1);
  884. } else {
  885. return((SDL_Rect **)0);
  886. }
  887. }
  888. }
  889. /* Various screen update functions available */
  890. static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects);
  891. static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
  892. SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
  893. int width, int height, int bpp, Uint32 flags)
  894. {
  895. SDL_Surface *video;
  896. HRESULT result;
  897. DWORD sharemode;
  898. DWORD style;
  899. const DWORD directstyle =
  900. (WS_POPUP);
  901. const DWORD windowstyle = 
  902. (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
  903. const DWORD resizestyle =
  904. (WS_THICKFRAME|WS_MAXIMIZEBOX);
  905. DDSURFACEDESC ddsd;
  906. LPDIRECTDRAWSURFACE  dd_surface1;
  907. LPDIRECTDRAWSURFACE3 dd_surface3;
  908. BOOL was_visible;
  909. #ifdef DDRAW_DEBUG
  910.  fprintf(stderr, "Setting %dx%dx%d video moden", width, height, bpp);
  911. #endif
  912. /* See whether or not we should center the window */
  913. was_visible = IsWindowVisible(SDL_Window);
  914. /* Clean up any previous DirectDraw surfaces */
  915. if ( current->hwdata ) {
  916. this->FreeHWSurface(this, current);
  917. current->hwdata = NULL;
  918. }
  919. if ( SDL_primary != NULL ) {
  920. IDirectDrawSurface3_Release(SDL_primary);
  921. SDL_primary = NULL;
  922. }
  923. /* Unset any previous OpenGL fullscreen mode */
  924. if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  925.                        (SDL_OPENGL|SDL_FULLSCREEN) ) {
  926. ChangeDisplaySettings(NULL, 0);
  927. }
  928. /* Clean up any GL context that may be hanging around */
  929. if ( current->flags & SDL_OPENGL ) {
  930. WIN_GL_ShutDown(this);
  931. }
  932. /* If we are setting a GL mode, use GDI, not DirectX (yuck) */
  933. if ( flags & SDL_OPENGL ) {
  934. RECT bounds;
  935. int x, y;
  936. Uint32 Rmask, Gmask, Bmask;
  937. /* Recalculate the bitmasks if necessary */
  938. if ( bpp == current->format->BitsPerPixel ) {
  939. video = current;
  940. } else {
  941. switch (bpp) {
  942.     case 15:
  943.     case 16:
  944. if ( 0 /*DIB_SussScreenDepth() == 15*/ ) {
  945. /* 5-5-5 */
  946. Rmask = 0x00007c00;
  947. Gmask = 0x000003e0;
  948. Bmask = 0x0000001f;
  949. } else {
  950. /* 5-6-5 */
  951. Rmask = 0x0000f800;
  952. Gmask = 0x000007e0;
  953. Bmask = 0x0000001f;
  954. }
  955. break;
  956.     case 24:
  957.     case 32:
  958. /* GDI defined as 8-8-8 */
  959. Rmask = 0x00ff0000;
  960. Gmask = 0x0000ff00;
  961. Bmask = 0x000000ff;
  962. break;
  963.     default:
  964. Rmask = 0x00000000;
  965. Gmask = 0x00000000;
  966. Bmask = 0x00000000;
  967. break;
  968. }
  969. video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp,
  970.                              Rmask, Gmask, Bmask, 0);
  971. if ( video == NULL ) {
  972. SDL_OutOfMemory();
  973. return(NULL);
  974. }
  975. }
  976. /* Fill in part of the video surface */
  977. video->flags = 0; /* Clear flags */
  978. video->w = width;
  979. video->h = height;
  980. video->pitch = SDL_CalculatePitch(video);
  981. /* Set fullscreen mode if appropriate.
  982.    Ugh, since our list of valid video modes comes from
  983.    the DirectX driver, we may not actually be able to
  984.    change to the desired resolution here.
  985.    FIXME: Should we do a closest match?
  986.  */
  987. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  988. DEVMODE settings;
  989. memset(&settings, 0, sizeof(DEVMODE));
  990. settings.dmSize = sizeof(DEVMODE);
  991. settings.dmBitsPerPel = video->format->BitsPerPixel;
  992. settings.dmPelsWidth = width;
  993. settings.dmPelsHeight = height;
  994. settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  995. if ( ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL ) {
  996. video->flags |= SDL_FULLSCREEN;
  997. SDL_fullscreen_mode = settings;
  998. }
  999. }
  1000. style = GetWindowLong(SDL_Window, GWL_STYLE);
  1001. style &= ~(resizestyle|WS_MAXIMIZE);
  1002. if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1003. style &= ~windowstyle;
  1004. style |= directstyle;
  1005. } else {
  1006. if ( flags & SDL_NOFRAME ) {
  1007. style &= ~windowstyle;
  1008. style |= directstyle;
  1009. video->flags |= SDL_NOFRAME;
  1010. } else {
  1011. style &= ~directstyle;
  1012. style |= windowstyle;
  1013. if ( flags & SDL_RESIZABLE ) {
  1014. style |= resizestyle;
  1015. video->flags |= SDL_RESIZABLE;
  1016. }
  1017. }
  1018. if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1019. }
  1020. SetWindowLong(SDL_Window, GWL_STYLE, style);
  1021. /* Resize the window (copied from SDL WinDIB driver) */
  1022. if ( SDL_windowid == NULL ) {
  1023. UINT swp_flags;
  1024. SDL_resizing = 1;
  1025. bounds.left = 0;
  1026. bounds.top = 0;
  1027. bounds.right = video->w;
  1028. bounds.bottom = video->h;
  1029. AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), FALSE);
  1030. width = bounds.right-bounds.left;
  1031. height = bounds.bottom-bounds.top;
  1032. x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1033. y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1034. if ( y < 0 ) { /* Cover up title bar for more client area */
  1035. y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1036. }
  1037. swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW);
  1038. if ( was_visible && !(flags & SDL_FULLSCREEN) ) {
  1039. swp_flags |= SWP_NOMOVE;
  1040. }
  1041. SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
  1042. SDL_resizing = 0;
  1043. SetForegroundWindow(SDL_Window);
  1044. }
  1045. /* Set up for OpenGL */
  1046. if ( WIN_GL_SetupWindow(this) < 0 ) {
  1047. return(NULL);
  1048. }
  1049. video->flags |= SDL_OPENGL;
  1050. return(video);
  1051. }
  1052. /* Set the appropriate window style */
  1053. style = GetWindowLong(SDL_Window, GWL_STYLE);
  1054. style &= ~(resizestyle|WS_MAXIMIZE);
  1055. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1056. style &= ~windowstyle;
  1057. style |= directstyle;
  1058. } else {
  1059. if ( flags & SDL_NOFRAME ) {
  1060. style &= ~windowstyle;
  1061. style |= directstyle;
  1062. } else {
  1063. style &= ~directstyle;
  1064. style |= windowstyle;
  1065. if ( flags & SDL_RESIZABLE ) {
  1066. style |= resizestyle;
  1067. }
  1068. }
  1069. if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
  1070. }
  1071. SetWindowLong(SDL_Window, GWL_STYLE, style);
  1072. /* Set DirectDraw sharing mode.. exclusive when fullscreen */
  1073. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1074. sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT;
  1075. } else {
  1076. sharemode = DDSCL_NORMAL;
  1077. }
  1078. result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode);
  1079. if ( result != DD_OK ) {
  1080. SetDDerror("DirectDraw2::SetCooperativeLevel", result);
  1081. return(NULL);
  1082. }
  1083. /* Set the display mode, if we are in fullscreen mode */
  1084. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1085. /* Cover up desktop during mode change */
  1086. SDL_resizing = 1;
  1087. SetWindowPos(SDL_Window, NULL, 0, 0, 
  1088. GetSystemMetrics(SM_CXSCREEN),
  1089. GetSystemMetrics(SM_CYSCREEN),
  1090. (SWP_NOCOPYBITS | SWP_NOZORDER));
  1091. SDL_resizing = 0;
  1092. ShowWindow(SDL_Window, SW_SHOW);
  1093. while ( GetForegroundWindow() != SDL_Window ) {
  1094. SetForegroundWindow(SDL_Window);
  1095. SDL_Delay(100);
  1096. }
  1097. result = IDirectDraw2_SetDisplayMode(ddraw2, width, height,
  1098. bpp, 0, 0);
  1099. if ( result != DD_OK ) {
  1100. /* We couldn't set fullscreen mode, try window */
  1101. return(DX5_SetVideoMode(this, current,
  1102. width, height, bpp, flags & ~SDL_FULLSCREEN)); 
  1103. }
  1104. DX5_DInputReset(this, 1);
  1105. } else {
  1106. DX5_DInputReset(this, 0);
  1107. }
  1108. DX5_UpdateVideoInfo(this);
  1109. /* Create a primary DirectDraw surface */
  1110. memset(&ddsd, 0, sizeof(ddsd));
  1111. ddsd.dwSize = sizeof(ddsd);
  1112. ddsd.dwFlags = DDSD_CAPS;
  1113. ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY);
  1114. if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1115. /* There's no windowed double-buffering */
  1116. flags &= ~SDL_DOUBLEBUF;
  1117. }
  1118. if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1119. ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
  1120. ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1121. ddsd.dwBackBufferCount = 1;
  1122. }
  1123. result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); 
  1124. if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) {
  1125. ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
  1126. ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP);
  1127. ddsd.dwBackBufferCount = 0;
  1128. result = IDirectDraw2_CreateSurface(ddraw2,
  1129. &ddsd, &dd_surface1, NULL); 
  1130. }
  1131. if ( result != DD_OK ) {
  1132. SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result);
  1133. return(NULL);
  1134. }
  1135. result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1136. &IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary);
  1137. if ( result != DD_OK ) {
  1138. SetDDerror("DirectDrawSurface::QueryInterface", result);
  1139. return(NULL);
  1140. }
  1141. result = IDirectDrawSurface_Release(dd_surface1);
  1142. if ( result != DD_OK ) {
  1143. SetDDerror("DirectDrawSurface::Release", result);
  1144. return(NULL);
  1145. }
  1146. /* Get the format of the primary DirectDraw surface */
  1147. memset(&ddsd, 0, sizeof(ddsd));
  1148. ddsd.dwSize = sizeof(ddsd);
  1149. ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS;
  1150. result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd);
  1151. if ( result != DD_OK ) {
  1152. SetDDerror("DirectDrawSurface::Release", result);
  1153. return(NULL);
  1154. }
  1155. if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) {
  1156. SDL_SetError("Primary DDRAW surface is not RGB format");
  1157. return(NULL);
  1158. }
  1159. /* Free old palette and create a new one if we're in 8-bit mode */
  1160. if ( SDL_palette != NULL ) {
  1161. IDirectDrawPalette_Release(SDL_palette);
  1162. SDL_palette = NULL;
  1163. }
  1164. #if defined(NONAMELESSUNION)
  1165. if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) {
  1166. #else
  1167. if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
  1168. #endif
  1169. int i;
  1170. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1171. /* We have access to the entire palette */
  1172. for ( i=0; i<256; ++i ) {
  1173. SDL_colors[i].peFlags =
  1174. (PC_NOCOLLAPSE|PC_RESERVED);
  1175. SDL_colors[i].peRed = 0;
  1176. SDL_colors[i].peGreen = 0;
  1177. SDL_colors[i].peBlue = 0;
  1178. }
  1179. } else {
  1180. /* First 10 colors are reserved by Windows */
  1181. for ( i=0; i<10; ++i ) {
  1182. SDL_colors[i].peFlags = PC_EXPLICIT;
  1183. SDL_colors[i].peRed = i;
  1184. SDL_colors[i].peGreen = 0;
  1185. SDL_colors[i].peBlue = 0;
  1186. }
  1187. for ( i=10; i<(10+236); ++i ) {
  1188. SDL_colors[i].peFlags = PC_NOCOLLAPSE;
  1189. SDL_colors[i].peRed = 0;
  1190. SDL_colors[i].peGreen = 0;
  1191. SDL_colors[i].peBlue = 0;
  1192. }
  1193. /* Last 10 colors are reserved by Windows */
  1194. for ( i=246; i<256; ++i ) {
  1195. SDL_colors[i].peFlags = PC_EXPLICIT;
  1196. SDL_colors[i].peRed = i;
  1197. SDL_colors[i].peGreen = 0;
  1198. SDL_colors[i].peBlue = 0;
  1199. }
  1200. }
  1201. result = IDirectDraw2_CreatePalette(ddraw2,
  1202.       (DDPCAPS_8BIT|DDPCAPS_ALLOW256),
  1203. SDL_colors, &SDL_palette, NULL);
  1204. if ( result != DD_OK ) {
  1205. SetDDerror("DirectDraw2::CreatePalette", result);
  1206. return(NULL);
  1207. }
  1208. result = IDirectDrawSurface3_SetPalette(SDL_primary,
  1209. SDL_palette);
  1210. if ( result != DD_OK ) {
  1211. SetDDerror("DirectDrawSurface3::SetPalette", result);
  1212. return(NULL);
  1213. }
  1214. }
  1215. /* Create our video surface using the same pixel format */
  1216. video = current;
  1217. if ( (width != video->w) || (height != video->h)
  1218. || (video->format->BitsPerPixel != 
  1219. #if defined(NONAMELESSUNION)
  1220. ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) {
  1221. #else
  1222. ddsd.ddpfPixelFormat.dwRGBBitCount) ) {
  1223. #endif
  1224. SDL_FreeSurface(video);
  1225. video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0,
  1226. #if defined(NONAMELESSUNION)
  1227. ddsd.ddpfPixelFormat.u1.dwRGBBitCount,
  1228. ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1229. ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1230. ddsd.ddpfPixelFormat.u4.dwBBitMask,
  1231. #else
  1232. ddsd.ddpfPixelFormat.dwRGBBitCount,
  1233. ddsd.ddpfPixelFormat.dwRBitMask,
  1234. ddsd.ddpfPixelFormat.dwGBitMask,
  1235. ddsd.ddpfPixelFormat.dwBBitMask,
  1236. #endif
  1237. 0);
  1238. if ( video == NULL ) {
  1239. SDL_OutOfMemory();
  1240. return(NULL);
  1241. }
  1242. video->w = width;
  1243. video->h = height;
  1244. video->pitch = 0;
  1245. }
  1246. video->flags = 0; /* Clear flags */
  1247. /* If not fullscreen, locking is possible, but it doesn't do what 
  1248.    the caller really expects -- if the locked surface is written to,
  1249.    the appropriate portion of the entire screen is modified, not 
  1250.    the application window, as we would like.
  1251.    Note that it is still possible to write directly to display
  1252.    memory, but the application must respect the clip list of
  1253.    the surface.  There might be some odd timing interactions
  1254.    involving clip list updates and background refreshing as
  1255.    Windows moves other windows across our window.
  1256.    We currently don't support this, even though it might be a
  1257.    good idea since BeOS has an implementation of BDirectWindow
  1258.    that does the same thing.  This would be most useful for
  1259.    applications that do complete screen updates every frame.
  1260.     -- Fixme?
  1261. */
  1262. if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1263. /* Necessary if we're going from fullscreen to window */
  1264. if ( video->pixels == NULL ) {
  1265. video->pitch = (width*video->format->BytesPerPixel);
  1266. /* Pitch needs to be QWORD (8-byte) aligned */
  1267. video->pitch = (video->pitch + 7) & ~7;
  1268. video->pixels = (void *)malloc(video->h*video->pitch);
  1269. if ( video->pixels == NULL ) {
  1270. if ( video != current ) {
  1271. SDL_FreeSurface(video);
  1272. }
  1273. SDL_OutOfMemory();
  1274. return(NULL);
  1275. }
  1276. }
  1277. dd_surface3 = NULL;
  1278. video->flags |= SDL_SWSURFACE;
  1279. if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) {
  1280. video->flags |= SDL_RESIZABLE;
  1281. }
  1282. if ( flags & SDL_NOFRAME ) {
  1283. video->flags |= SDL_NOFRAME;
  1284. }
  1285. } else {
  1286. /* Necessary if we're going from window to fullscreen */
  1287. if ( video->pixels != NULL ) {
  1288. free(video->pixels);
  1289. video->pixels = NULL;
  1290. }
  1291. dd_surface3 = SDL_primary;
  1292. video->flags |= SDL_HWSURFACE;
  1293. }
  1294. /* See if the primary surface has double-buffering enabled */
  1295. if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) {
  1296. video->flags |= SDL_DOUBLEBUF;
  1297. }
  1298. /* Allocate the SDL surface associated with the primary surface */
  1299. if ( DX5_AllocDDSurface(this, video, dd_surface3,
  1300.                         video->flags&SDL_HWSURFACE) < 0 ) {
  1301. if ( video != current ) {
  1302. SDL_FreeSurface(video);
  1303. }
  1304. return(NULL);
  1305. }
  1306. /* Use the appropriate blitting function */
  1307. if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1308. video->flags |= SDL_FULLSCREEN;
  1309. if ( video->format->palette != NULL ) {
  1310. video->flags |= SDL_HWPALETTE;
  1311. }
  1312. this->UpdateRects = DX5_DirectUpdate;
  1313. } else {
  1314. this->UpdateRects = DX5_WindowUpdate;
  1315. }
  1316. /* Make our window the proper size, set the clipper, then show it */
  1317. if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) {
  1318. RECT bounds;
  1319. int  x, y;
  1320. UINT swp_flags;
  1321. /* Create and set a clipper on our primary surface */
  1322. if ( SDL_clipper == NULL ) {
  1323. result = IDirectDraw2_CreateClipper(ddraw2,
  1324. 0, &SDL_clipper, NULL);
  1325. if ( result != DD_OK ) {
  1326. if ( video != current ) {
  1327. SDL_FreeSurface(video);
  1328. }
  1329. SetDDerror("DirectDraw2::CreateClipper",result);
  1330. return(NULL);
  1331. }
  1332. }
  1333. result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window);
  1334. if ( result != DD_OK ) {
  1335. if ( video != current ) {
  1336. SDL_FreeSurface(video);
  1337. }
  1338. SetDDerror("DirectDrawClipper::SetHWnd", result);
  1339. return(NULL);
  1340. }
  1341. result = IDirectDrawSurface3_SetClipper(SDL_primary,
  1342. SDL_clipper);
  1343. if ( result != DD_OK ) {
  1344. if ( video != current ) {
  1345. SDL_FreeSurface(video);
  1346. }
  1347. SetDDerror("DirectDrawSurface3::SetClipper", result);
  1348. return(NULL);
  1349. }
  1350. /* Set the size of the window, centering and adjusting */
  1351. SDL_resizing = 1;
  1352. bounds.left = 0;
  1353. bounds.top = 0;
  1354. bounds.right = video->w;
  1355. bounds.bottom = video->h;
  1356. AdjustWindowRect(&bounds, GetWindowLong(SDL_Window, GWL_STYLE),
  1357. FALSE);
  1358. width = bounds.right-bounds.left;
  1359. height = bounds.bottom-bounds.top;
  1360. x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
  1361. y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
  1362. if ( y < 0 ) { /* Cover up title bar for more client area */
  1363. y -= GetSystemMetrics(SM_CYCAPTION)/2;
  1364. }
  1365. swp_flags = (SWP_NOCOPYBITS | SWP_NOZORDER);
  1366. if ( was_visible ) {
  1367. swp_flags |= SWP_NOMOVE;
  1368. }
  1369. SetWindowPos(SDL_Window, NULL, x, y, width, height, swp_flags);
  1370. SDL_resizing = 0;
  1371. }
  1372. ShowWindow(SDL_Window, SW_SHOW);
  1373. SetForegroundWindow(SDL_Window);
  1374. /* We're live! */
  1375. return(video);
  1376. }
  1377. struct private_hwdata {
  1378. LPDIRECTDRAWSURFACE3 dd_surface;
  1379. LPDIRECTDRAWSURFACE3 dd_writebuf;
  1380. };
  1381. static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, 
  1382. LPDIRECTDRAWSURFACE3 requested, Uint32 flag)
  1383. {
  1384. LPDIRECTDRAWSURFACE  dd_surface1;
  1385. LPDIRECTDRAWSURFACE3 dd_surface3;
  1386. DDSURFACEDESC ddsd;
  1387. HRESULT result;
  1388. /* Clear the hardware flag, in case we fail */
  1389. surface->flags &= ~flag;
  1390. /* Allocate the hardware acceleration data */
  1391. surface->hwdata = (struct private_hwdata *)
  1392. malloc(sizeof(*surface->hwdata));
  1393. if ( surface->hwdata == NULL ) {
  1394. SDL_OutOfMemory();
  1395. return(-1);
  1396. }
  1397. dd_surface3 = NULL;
  1398. /* Set up the surface description */
  1399. memset(&ddsd, 0, sizeof(ddsd));
  1400. ddsd.dwSize = sizeof(ddsd);
  1401. ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|
  1402. DDSD_PITCH|DDSD_PIXELFORMAT);
  1403. ddsd.dwWidth = surface->w;
  1404. ddsd.dwHeight= surface->h;
  1405. #if defined(NONAMELESSUNION)
  1406. ddsd.u1.lPitch = surface->pitch;
  1407. #else
  1408. ddsd.lPitch = surface->pitch;
  1409. #endif
  1410. if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1411. ddsd.ddsCaps.dwCaps =
  1412. (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY);
  1413. } else {
  1414. ddsd.ddsCaps.dwCaps =
  1415. (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
  1416. }
  1417. ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
  1418. ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  1419. if ( surface->format->palette ) {
  1420. ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  1421. }
  1422. #if defined(NONAMELESSUNION)
  1423. ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel;
  1424. ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask;
  1425. ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask;
  1426. ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask;
  1427. #else
  1428. ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel;
  1429. ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask;
  1430. ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask;
  1431. ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask;
  1432. #endif
  1433. /* Create the DirectDraw video surface */
  1434. if ( requested != NULL ) {
  1435. dd_surface3 = requested;
  1436. } else {
  1437. result = IDirectDraw2_CreateSurface(ddraw2,
  1438. &ddsd, &dd_surface1, NULL); 
  1439. if ( result != DD_OK ) {
  1440. SetDDerror("DirectDraw2::CreateSurface", result);
  1441. goto error_end;
  1442. }
  1443. result = IDirectDrawSurface_QueryInterface(dd_surface1,
  1444. &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3);
  1445. IDirectDrawSurface_Release(dd_surface1);
  1446. if ( result != DD_OK ) {
  1447. SetDDerror("DirectDrawSurface::QueryInterface", result);
  1448. goto error_end;
  1449. }
  1450. }
  1451. if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  1452. /* Check to see whether the surface actually ended up
  1453.    in video memory, and fail if not.  We expect the
  1454.    surfaces we create here to actually be in hardware!
  1455. */
  1456. result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps);
  1457. if ( result != DD_OK ) {
  1458. SetDDerror("DirectDrawSurface3::GetCaps", result);
  1459. goto error_end;
  1460. }
  1461. if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) !=
  1462. DDSCAPS_VIDEOMEMORY ) {
  1463. SDL_SetError("No room in video memory");
  1464. goto error_end;
  1465. }
  1466. } else {
  1467. /* Try to hook our surface memory */
  1468. ddsd.dwFlags = DDSD_LPSURFACE;
  1469. ddsd.lpSurface = surface->pixels;
  1470. result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3,
  1471. &ddsd, 0);
  1472. if ( result != DD_OK ) {
  1473. SetDDerror("DirectDraw2::SetSurfaceDesc", result);
  1474. goto error_end;
  1475. }
  1476. }
  1477. /* Make sure the surface format was set properly */
  1478. memset(&ddsd, 0, sizeof(ddsd));
  1479. ddsd.dwSize = sizeof(ddsd);
  1480. result = IDirectDrawSurface3_Lock(dd_surface3, NULL,
  1481. &ddsd, DDLOCK_NOSYSLOCK, NULL);
  1482. if ( result != DD_OK ) {
  1483. SetDDerror("DirectDrawSurface3::Lock", result);
  1484. goto error_end;
  1485. }
  1486. IDirectDrawSurface3_Unlock(dd_surface3, NULL);
  1487. if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1488. if ( ddsd.lpSurface != surface->pixels ) {
  1489. SDL_SetError("DDraw didn't use SDL surface memory");
  1490. goto error_end;
  1491. }
  1492. if (
  1493. #if defined(NONAMELESSUNION)
  1494. ddsd.u1.lPitch
  1495. #else
  1496. ddsd.lPitch
  1497. #endif
  1498.  != (LONG)surface->pitch ) {
  1499. SDL_SetError("DDraw created surface with wrong pitch");
  1500. goto error_end;
  1501. }
  1502. } else {
  1503. #if defined(NONAMELESSUNION)
  1504. surface->pitch = (Uint16)ddsd.u1.lPitch;
  1505. #else
  1506. surface->pitch = (Uint16)ddsd.lPitch;
  1507. #endif
  1508. }
  1509. #if defined(NONAMELESSUNION)
  1510. if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != 
  1511. surface->format->BitsPerPixel) ||
  1512.      (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) ||
  1513.      (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) ||
  1514.      (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){
  1515. #else
  1516. if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != 
  1517. surface->format->BitsPerPixel) ||
  1518.      (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) ||
  1519.      (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) ||
  1520.      (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){
  1521. #endif
  1522. SDL_SetError("DDraw didn't use SDL surface description");
  1523. goto error_end;
  1524. }
  1525. if ( (ddsd.dwWidth != (DWORD)surface->w) ||
  1526. (ddsd.dwHeight != (DWORD)surface->h) ) {
  1527. SDL_SetError("DDraw created surface with wrong size");
  1528. goto error_end;
  1529. }
  1530. /* Set the surface private data */
  1531. surface->flags |= flag;
  1532. surface->hwdata->dd_surface = dd_surface3;
  1533. if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
  1534. LPDIRECTDRAWSURFACE3 dd_writebuf;
  1535. ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  1536. result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3,
  1537. &ddsd.ddsCaps, &dd_writebuf);
  1538. if ( result != DD_OK ) {
  1539. SetDDerror("DirectDrawSurface3::GetAttachedSurface",
  1540. result);
  1541. } else {
  1542. dd_surface3 = dd_writebuf;
  1543. }
  1544. }
  1545. surface->hwdata->dd_writebuf = dd_surface3;
  1546. /* We're ready to go! */
  1547. return(0);
  1548. /* Okay, so goto's are cheesy, but there are so many possible
  1549.    errors in this function, and the cleanup is the same in 
  1550.    every single case.  Is there a better way, other than deeply
  1551.    nesting the code?
  1552. */
  1553. error_end:
  1554. if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) {
  1555. IDirectDrawSurface_Release(dd_surface3);
  1556. }
  1557. free(surface->hwdata);
  1558. surface->hwdata = NULL;
  1559. return(-1);
  1560. }
  1561. static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface)
  1562. {
  1563. /* DDraw limitation -- you need to set cooperative level first */
  1564. if ( SDL_primary == NULL ) {
  1565. SDL_SetError("You must set a non-GL video mode first");
  1566. return(-1);
  1567. }
  1568. return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE));
  1569. }
  1570. #ifdef DDRAW_DEBUG
  1571. void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags)
  1572. {
  1573. DDSURFACEDESC ddsd;
  1574. /* Lock and load! */
  1575. memset(&ddsd, 0, sizeof(ddsd));
  1576. ddsd.dwSize = sizeof(ddsd);
  1577. if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd,
  1578. (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) {
  1579. return;
  1580. }
  1581. IDirectDrawSurface3_Unlock(surface, NULL);
  1582. fprintf(stderr, "%s:n", title);
  1583. fprintf(stderr, "tSize: %dx%d in %s at %ld bpp (pitch = %ld)n",
  1584. ddsd.dwWidth, ddsd.dwHeight,
  1585. (flags & SDL_HWSURFACE) ? "hardware" : "software",
  1586. #if defined(NONAMELESSUNION)
  1587. ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch);
  1588. #else
  1589. ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch);
  1590. #endif
  1591. fprintf(stderr, "tR = 0x%X, G = 0x%X, B = 0x%Xn", 
  1592. #if defined(NONAMELESSUNION)
  1593.       ddsd.ddpfPixelFormat.u2.dwRBitMask,
  1594.       ddsd.ddpfPixelFormat.u3.dwGBitMask,
  1595.       ddsd.ddpfPixelFormat.u4.dwBBitMask);
  1596. #else
  1597.       ddsd.ddpfPixelFormat.dwRBitMask,
  1598.       ddsd.ddpfPixelFormat.dwGBitMask,
  1599.       ddsd.ddpfPixelFormat.dwBBitMask);
  1600. #endif
  1601. }
  1602. #endif /* DDRAW_DEBUG */
  1603. static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
  1604. SDL_Surface *dst, SDL_Rect *dstrect)
  1605. {
  1606. LPDIRECTDRAWSURFACE3 src_surface;
  1607. LPDIRECTDRAWSURFACE3 dst_surface;
  1608. DWORD flags;
  1609. RECT rect;
  1610. HRESULT result;
  1611. /* Set it up.. the desination must have a DDRAW surface */
  1612. src_surface = src->hwdata->dd_writebuf;
  1613. dst_surface = dst->hwdata->dd_writebuf;
  1614. rect.top    = srcrect->y;
  1615. rect.bottom = srcrect->y+srcrect->h;
  1616. rect.left   = srcrect->x;
  1617. rect.right  = srcrect->x+srcrect->w;
  1618. if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY )
  1619. flags = DDBLTFAST_SRCCOLORKEY;
  1620. else
  1621. flags = DDBLTFAST_NOCOLORKEY;
  1622. /* FIXME:  We can remove this flag for _really_ fast blit queuing,
  1623.            but it will affect the return values of locks and flips.
  1624.  */
  1625. flags |= DDBLTFAST_WAIT;
  1626. /* Do the blit! */
  1627. result = IDirectDrawSurface3_BltFast(dst_surface,
  1628. dstrect->x, dstrect->y, src_surface, &rect, flags);
  1629. if ( result != DD_OK ) {
  1630. if ( result == DDERR_SURFACELOST ) {
  1631. result = IDirectDrawSurface3_Restore(src_surface);
  1632. result = IDirectDrawSurface3_Restore(dst_surface);
  1633. /* The surfaces need to be reloaded with artwork */
  1634. SDL_SetError("Blit surfaces were lost, reload them");
  1635. return(-2);
  1636. }
  1637. SetDDerror("IDirectDrawSurface3::BltFast", result);
  1638. #ifdef DDRAW_DEBUG
  1639.  fprintf(stderr, "Original dest rect: %dx%d at %d,%dn", dstrect->w, dstrect->h, dstrect->x, dstrect->y);
  1640.  fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)n",
  1641. (src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst,
  1642. dstrect->x, dstrect->y);
  1643.   PrintSurface("SRC", src_surface, src->flags);
  1644.   PrintSurface("DST", dst_surface, dst->flags);
  1645.  fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)n",
  1646. rect.left, rect.top, rect.right, rect.bottom);
  1647. #endif
  1648. /* Unexpected error, fall back to software blit */
  1649. return(src->map->sw_blit(src, srcrect, dst, dstrect));
  1650. }
  1651. return(0);
  1652. }
  1653. static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
  1654. {
  1655. int accelerated;
  1656. /* We need to have a DDraw surface for HW blits */
  1657. if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) {
  1658. /* Allocate a DDraw surface for the blit */
  1659. if ( src->hwdata == NULL ) {
  1660. DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE);
  1661. }
  1662. }
  1663. if ( src->hwdata == NULL ) {
  1664. return(0);
  1665. }
  1666. /* Set initial acceleration on */
  1667. src->flags |= SDL_HWACCEL;
  1668. /* Set the surface attributes */
  1669. if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
  1670. if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) {
  1671. src->flags &= ~SDL_HWACCEL;
  1672. }
  1673. }
  1674. if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
  1675. if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) {
  1676. src->flags &= ~SDL_HWACCEL;
  1677. }
  1678. }
  1679. /* Check to see if final surface blit is accelerated */
  1680. accelerated = !!(src->flags & SDL_HWACCEL);
  1681. if ( accelerated ) {
  1682. #ifdef DDRAW_DEBUG
  1683.   fprintf(stderr, "Setting accelerated blit on 0x%pn", src);
  1684. #endif
  1685. src->map->hw_blit = DX5_HWAccelBlit;
  1686. }
  1687. return(accelerated);
  1688. }
  1689. static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1690. {
  1691. LPDIRECTDRAWSURFACE3 dst_surface;
  1692. RECT area;
  1693. DDBLTFX bltfx;
  1694. HRESULT result;
  1695. #ifdef DDRAW_DEBUG
  1696.  fprintf(stderr, "HW accelerated fill at (%d,%d)n", dstrect->x, dstrect->y);
  1697. #endif
  1698. dst_surface = dst->hwdata->dd_writebuf;
  1699. area.top = dstrect->y;
  1700. area.bottom = dstrect->y+dstrect->h;
  1701. area.left = dstrect->x;
  1702. area.right = dstrect->x+dstrect->w;
  1703. bltfx.dwSize = sizeof(bltfx);
  1704. #if defined(NONAMELESSUNION)
  1705. bltfx.u5.dwFillColor = color;
  1706. #else
  1707. bltfx.dwFillColor = color;
  1708. #endif
  1709. result = IDirectDrawSurface3_Blt(dst_surface,
  1710. &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1711. if ( result == DDERR_SURFACELOST ) {
  1712. IDirectDrawSurface3_Restore(dst_surface);
  1713. result = IDirectDrawSurface3_Blt(dst_surface,
  1714. &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx);
  1715. }
  1716. if ( result != DD_OK ) {
  1717. SetDDerror("IDirectDrawSurface3::Blt", result);
  1718. return(-1);
  1719. }
  1720. return(0);
  1721. }
  1722. static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
  1723. {
  1724. DDCOLORKEY colorkey;
  1725. HRESULT result;
  1726. /* Set the surface colorkey */
  1727. colorkey.dwColorSpaceLowValue = key;
  1728. colorkey.dwColorSpaceHighValue = key;
  1729. result = IDirectDrawSurface3_SetColorKey(
  1730. surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey);
  1731. if ( result != DD_OK ) {
  1732. SetDDerror("IDirectDrawSurface3::SetColorKey", result);
  1733. return(-1);
  1734. }
  1735. return(0);
  1736. }
  1737. static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
  1738. {
  1739. return(-1);
  1740. }
  1741. static int DX5_LockHWSurface(_THIS, SDL_Surface *surface)
  1742. {
  1743. HRESULT result;
  1744. LPDIRECTDRAWSURFACE3 dd_surface;
  1745. DDSURFACEDESC ddsd;
  1746. /* Lock and load! */
  1747. dd_surface = surface->hwdata->dd_writebuf;
  1748. memset(&ddsd, 0, sizeof(ddsd));
  1749. ddsd.dwSize = sizeof(ddsd);
  1750. result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd,
  1751. (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1752. if ( result == DDERR_SURFACELOST ) {
  1753. result = IDirectDrawSurface3_Restore(
  1754. surface->hwdata->dd_surface);
  1755. result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, 
  1756. (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL);
  1757. }
  1758. if ( result != DD_OK ) {
  1759. SetDDerror("DirectDrawSurface3::Lock", result);
  1760. return(-1);
  1761. }
  1762. /* Pitch might have changed -- recalculate pitch and offset */
  1763. #if defined(NONAMELESSUNION)
  1764. if ( surface->pitch != ddsd.u1.lPitch ) {
  1765. surface->pitch = ddsd.u1.lPitch;
  1766. #else
  1767. if ( surface->pitch != ddsd.lPitch ) {
  1768. surface->pitch = (Uint16)ddsd.lPitch;
  1769. #endif
  1770. surface->offset =
  1771. ((ddsd.dwHeight-surface->h)/2)*surface->pitch +
  1772. ((ddsd.dwWidth-surface->w)/2)*
  1773. surface->format->BytesPerPixel;
  1774. }
  1775. surface->pixels = ddsd.lpSurface;
  1776. return(0);
  1777. }
  1778. static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface)
  1779. {
  1780. IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL);
  1781. surface->pixels = NULL;
  1782. }
  1783. static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface)
  1784. {
  1785. HRESULT result;
  1786. LPDIRECTDRAWSURFACE3 dd_surface;
  1787. dd_surface = surface->hwdata->dd_surface;
  1788. result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
  1789. if ( result == DDERR_SURFACELOST ) {
  1790. result = IDirectDrawSurface3_Restore(
  1791. surface->hwdata->dd_surface);
  1792. result = IDirectDrawSurface3_Flip(dd_surface,NULL,DDFLIP_WAIT);
  1793. }
  1794. if ( result != DD_OK ) {
  1795. SetDDerror("DirectDrawSurface3::Flip", result);
  1796. return(-1);
  1797. }
  1798. return(0);
  1799. }
  1800. static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface)
  1801. {
  1802. if ( surface->hwdata ) {
  1803. if ( surface->hwdata->dd_surface != SDL_primary ) {
  1804. IDirectDrawSurface3_Release(surface->hwdata->dd_surface);
  1805. }
  1806. free(surface->hwdata);
  1807. surface->hwdata = NULL;
  1808. }
  1809. }
  1810. void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects)
  1811. {
  1812. HRESULT result;
  1813. int i;
  1814. RECT src, dst;
  1815. for ( i=0; i<numrects; ++i ) {
  1816. src.top = rects[i].y;
  1817. src.bottom = rects[i].y+rects[i].h;
  1818. src.left = rects[i].x;
  1819. src.right = rects[i].x+rects[i].w;
  1820. dst.top = SDL_bounds.top+src.top;
  1821. dst.left = SDL_bounds.left+src.left;
  1822. dst.bottom = SDL_bounds.top+src.bottom;
  1823. dst.right = SDL_bounds.left+src.right;
  1824. result = IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  1825. this->screen->hwdata->dd_surface, &src,
  1826. DDBLT_WAIT, NULL);
  1827. /* Doh!  Check for lost surface and restore it */
  1828. if ( result == DDERR_SURFACELOST ) {
  1829. IDirectDrawSurface3_Restore(SDL_primary);
  1830. IDirectDrawSurface3_Blt(SDL_primary, &dst, 
  1831. this->screen->hwdata->dd_surface, &src,
  1832. DDBLT_WAIT, NULL);
  1833. }
  1834. }
  1835. }
  1836. void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
  1837. {
  1838. }
  1839. /* Compress a full palette into the limited number of colors given to us
  1840.    by windows.
  1841.    The "best" way to do this is to sort the colors by diversity and place
  1842.    the most diverse colors into the limited palette.  Unfortunately this
  1843.    results in widely varying colors being displayed in the interval during
  1844.    which the windows palette has been set, and the mapping of the shadow
  1845.    surface to the new palette.  This is especially noticeable during fades.
  1846.    To deal with this problem, we can copy a predetermined portion of the
  1847.    full palette, and use that as the limited palette.  This allows colors
  1848.    to fade smoothly as the remapping is very similar on each palette change.
  1849.    Unfortunately, this breaks applications which partition the palette into
  1850.    distinct and widely varying areas, expecting all colors to be available.
  1851.    I'm making them both available, chosen at compile time.
  1852.    If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION,
  1853.    otherwise the sort-by-diversity algorithm will be used.
  1854. */
  1855. #define SIMPLE_COMPRESSION
  1856. #define CS_CS_DIST(A, B) ({
  1857. int r = (A.r - B.r);
  1858. int g = (A.g - B.g);
  1859. int b = (A.b - B.b);
  1860. (r*r + g*g + b*b);
  1861. })
  1862. static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors)
  1863. {
  1864. #ifdef SIMPLE_COMPRESSION
  1865. int i, j;
  1866. #else
  1867. static SDL_Color zero = { 0, 0, 0, 0 };
  1868. int i, j;
  1869. int max, dist;
  1870. int prev, next;
  1871. int *pool;
  1872. int *seen, *order;
  1873. #endif
  1874. /* Does this happen? */
  1875. if ( maxcolors > ncolors ) {
  1876. maxcolors = ncolors;
  1877. }
  1878. #ifdef SIMPLE_COMPRESSION
  1879. /* Just copy the first "maxcolors" colors */
  1880. for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  1881. SDL_colors[j].peRed = colors[i].r;
  1882. SDL_colors[j].peGreen = colors[i].g;
  1883. SDL_colors[j].peBlue = colors[i].b;
  1884. }
  1885. #else
  1886. /* Allocate memory for the arrays we use */
  1887. pool = (int *)alloca(2*ncolors*sizeof(int));
  1888. if ( pool == NULL ) {
  1889. /* No worries, just return */;
  1890. return;
  1891. }
  1892. seen = pool;
  1893. memset(seen, 0, ncolors*sizeof(int));
  1894. order = pool+ncolors;
  1895. /* Start with the brightest color */
  1896. max = 0;
  1897. for ( i=0; i<ncolors; ++i ) {
  1898. dist = CS_CS_DIST(zero, colors[i]);
  1899. if ( dist >= max ) {
  1900. max = dist;
  1901. next = i;
  1902. }
  1903. }
  1904. j = 0;
  1905. order[j++] = next;
  1906. seen[next] = 1;
  1907. prev = next;
  1908. /* Keep going through all the colors */
  1909. while ( j < maxcolors ) {
  1910. max = 0;
  1911. for ( i=0; i<ncolors; ++i ) {
  1912. if ( seen[i] ) {
  1913. continue;
  1914. }
  1915. dist = CS_CS_DIST(colors[i], colors[prev]);
  1916. if ( dist >= max ) {
  1917. max = dist;
  1918. next = i;
  1919. }
  1920. }
  1921. order[j++] = next;
  1922. seen[next] = 1;
  1923. prev = next;
  1924. }
  1925. /* Compress the colors to the palette */
  1926. for ( j=10, i=0; i<maxcolors; ++i, ++j ) {
  1927. SDL_colors[j].peRed = colors[order[i]].r;
  1928. SDL_colors[j].peGreen = colors[order[i]].g;
  1929. SDL_colors[j].peBlue = colors[order[i]].b;
  1930. }
  1931. #endif /* SIMPLE_COMPRESSION */
  1932. }
  1933. /* Set the system colormap in both fullscreen and windowed modes */
  1934. int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  1935. {
  1936. int i;
  1937. int alloct_all;
  1938. /* Copy palette colors into display palette */
  1939. alloct_all = 0;
  1940. if ( SDL_palette != NULL ) {
  1941. if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
  1942. /* We can set all entries explicitly */
  1943. for ( i=0; i< ncolors; ++i ) {
  1944.         int j = firstcolor + i;
  1945. SDL_colors[j].peRed = colors[i].r;
  1946. SDL_colors[j].peGreen = colors[i].g;
  1947. SDL_colors[j].peBlue = colors[i].b;
  1948. }
  1949. IDirectDrawPalette_SetEntries(SDL_palette, 0,
  1950. firstcolor, ncolors, &SDL_colors[firstcolor]);
  1951. alloct_all = 1;
  1952. } else {
  1953. /* Grab the 236 most diverse colors in the palette */
  1954. DX5_CompressPalette(this, colors, ncolors, 236);
  1955. /* This sends an WM_PALETTECHANGED message to us */
  1956. colorchange_expected = 1;
  1957. IDirectDrawPalette_SetEntries(SDL_palette, 0,
  1958. 0, 256, SDL_colors);
  1959. }
  1960. }
  1961. return(alloct_all);
  1962. }
  1963. /* Gamma code is only available on DirectX 7 and newer */
  1964. static int DX5_SetGammaRamp(_THIS, Uint16 *ramp)
  1965. {
  1966. #ifdef IDirectDrawGammaControl_SetGammaRamp
  1967. LPDIRECTDRAWGAMMACONTROL gamma;
  1968. DDGAMMARAMP gamma_ramp;
  1969. HRESULT result;
  1970. #endif
  1971. /* In windowed or OpenGL mode, use windib gamma code */
  1972. if ( ! DDRAW_FULLSCREEN() ) {
  1973. return DIB_SetGammaRamp(this, ramp);
  1974. }
  1975. #ifndef IDirectDrawGammaControl_SetGammaRamp
  1976. SDL_SetError("SDL compiled without DirectX gamma ramp support");
  1977. return -1;
  1978. #else
  1979. /* Check for a video mode! */
  1980. if ( ! SDL_primary ) {
  1981. SDL_SetError("A video mode must be set for gamma correction");
  1982. return(-1);
  1983. }
  1984. /* Get the gamma control object */
  1985. result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  1986. &IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  1987. if ( result != DD_OK ) {
  1988. SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  1989. return(-1);
  1990. }
  1991. /* Set up the gamma ramp */
  1992. memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp));
  1993. memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp));
  1994. memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp));
  1995. result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp);
  1996. if ( result != DD_OK ) {
  1997. SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result);
  1998. }
  1999. /* Release the interface and return */
  2000. IDirectDrawGammaControl_Release(gamma);
  2001. return (result == DD_OK) ? 0 : -1;
  2002. #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2003. }
  2004. static int DX5_GetGammaRamp(_THIS, Uint16 *ramp)
  2005. {
  2006. #ifdef IDirectDrawGammaControl_SetGammaRamp
  2007. LPDIRECTDRAWGAMMACONTROL gamma;
  2008. DDGAMMARAMP gamma_ramp;
  2009. HRESULT result;
  2010. #endif
  2011. /* In windowed or OpenGL mode, use windib gamma code */
  2012. if ( ! DDRAW_FULLSCREEN() ) {
  2013. return DIB_GetGammaRamp(this, ramp);
  2014. }
  2015. #ifndef IDirectDrawGammaControl_SetGammaRamp
  2016. SDL_SetError("SDL compiled without DirectX gamma ramp support");
  2017. return -1;
  2018. #else
  2019. /* Check for a video mode! */
  2020. if ( ! SDL_primary ) {
  2021. SDL_SetError("A video mode must be set for gamma correction");
  2022. return(-1);
  2023. }
  2024. /* Get the gamma control object */
  2025. result = IDirectDrawSurface3_QueryInterface(SDL_primary,
  2026. &IID_IDirectDrawGammaControl, (LPVOID *)&gamma);
  2027. if ( result != DD_OK ) {
  2028. SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result);
  2029. return(-1);
  2030. }
  2031. /* Set up the gamma ramp */
  2032. result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp);
  2033. if ( result == DD_OK ) {
  2034. memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp));
  2035. memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp));
  2036. memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp));
  2037. } else {
  2038. SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result);
  2039. }
  2040. /* Release the interface and return */
  2041. IDirectDrawGammaControl_Release(gamma);
  2042. return (result == DD_OK) ? 0 : -1;
  2043. #endif /* !IDirectDrawGammaControl_SetGammaRamp */
  2044. }
  2045. void DX5_VideoQuit(_THIS)
  2046. {
  2047. int i, j;
  2048. /* If we're fullscreen GL, we need to reset the display */
  2049. if ( this->screen != NULL ) {
  2050. if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) ==
  2051.                             (SDL_OPENGL|SDL_FULLSCREEN) ) {
  2052. ChangeDisplaySettings(NULL, 0);
  2053. }
  2054. if ( this->screen->flags & SDL_OPENGL ) {
  2055. WIN_GL_ShutDown(this);
  2056. }
  2057. }
  2058. /* Free any palettes we used */
  2059. if ( SDL_palette != NULL ) {
  2060. IDirectDrawPalette_Release(SDL_palette);
  2061. SDL_palette = NULL;
  2062. }
  2063. /* Allow the primary surface to be freed */
  2064. if ( SDL_primary != NULL ) {
  2065. SDL_primary = NULL;
  2066. }
  2067. /* Free video mode lists */
  2068. for ( i=0; i<NUM_MODELISTS; ++i ) {
  2069. if ( SDL_modelist[i] != NULL ) {
  2070. for ( j=0; SDL_modelist[i][j]; ++j )
  2071. free(SDL_modelist[i][j]);
  2072. free(SDL_modelist[i]);
  2073. SDL_modelist[i] = NULL;
  2074. }
  2075. }
  2076. /* Free the window */
  2077. DIB_QuitGamma(this);
  2078. if ( SDL_Window ) {
  2079. DX5_DestroyWindow(this);
  2080. }
  2081. /* Free our window icon */
  2082. if ( screen_icn ) {
  2083. DestroyIcon(screen_icn);
  2084. screen_icn = NULL;
  2085. }
  2086. }
  2087. /* Exported for the windows message loop only */
  2088. void DX5_RealizePalette(_THIS)
  2089. {
  2090. if ( SDL_palette ) {
  2091. IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette);
  2092. }
  2093. }
  2094. static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping)
  2095. {
  2096. int row, col;
  2097. Uint8 *pixels;
  2098. if ( surface->w && surface->h ) {
  2099. if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2100. if ( this->LockHWSurface(this, surface) < 0 ) {
  2101. return;
  2102. }
  2103. }
  2104. for ( row=0; row<surface->h; ++row ) {
  2105. pixels = (Uint8 *)surface->pixels+row*surface->pitch;
  2106. for ( col=0; col<surface->w; ++col, ++pixels ) {
  2107. *pixels = mapping[*pixels];
  2108. }
  2109. }
  2110. if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  2111. this->UnlockHWSurface(this, surface);
  2112. }
  2113. SDL_UpdateRect(surface, 0, 0, 0, 0);
  2114. }
  2115. }
  2116. void DX5_PaletteChanged(_THIS, HWND window)
  2117. {
  2118. SDL_Palette *palette;
  2119. SDL_Color *saved = NULL;
  2120. HDC hdc;
  2121. int i;
  2122. PALETTEENTRY *entries;
  2123. /* This is true when the window is closing */
  2124. if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) )
  2125. return;
  2126. /* We need to get the colors as they were set */
  2127. palette = this->physpal;
  2128. if(!palette)
  2129.         palette = SDL_VideoSurface->format->palette;
  2130. if ( palette == NULL ) { /* Sometimes we don't have a palette */
  2131. return;
  2132. }
  2133. entries = (PALETTEENTRY *)alloca(palette->ncolors*sizeof(*entries));
  2134. hdc = GetDC(window);
  2135. GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries);
  2136. ReleaseDC(window, hdc);
  2137. if ( ! colorchange_expected ) {
  2138. saved = (SDL_Color *)alloca(palette->ncolors*sizeof(SDL_Color));
  2139. memcpy(saved, palette->colors, 
  2140. palette->ncolors*sizeof(SDL_Color));
  2141. }
  2142. for ( i=0; i<palette->ncolors; ++i ) {
  2143. palette->colors[i].r = entries[i].peRed;
  2144. palette->colors[i].g = entries[i].peGreen;
  2145. palette->colors[i].b = entries[i].peBlue;
  2146. }
  2147. if ( ! colorchange_expected ) {
  2148. Uint8 mapping[256];
  2149. memset(mapping, 0, sizeof(mapping));
  2150. for ( i=0; i<palette->ncolors; ++i ) {
  2151. mapping[i] = SDL_FindColor(palette,
  2152. saved[i].r, saved[i].g, saved[i].b);
  2153. }
  2154. DX5_Recolor8Bit(this, SDL_VideoSurface, mapping);
  2155. }
  2156. colorchange_expected = 0;
  2157. /* Notify all mapped surfaces of the change */
  2158. SDL_FormatChanged(SDL_VideoSurface);
  2159. }
  2160. /* Exported for the windows message loop only */
  2161. void DX5_WinPAINT(_THIS, HDC hdc)
  2162. {
  2163. SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0);
  2164. }