engine.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Engine Implementation
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class EngineImpl : public PrivateEngine {
  8. private:
  9. //////////////////////////////////////////////////////////////////////////////
  10. //
  11. // types
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. typedef TList<PrivateSurface*> SurfaceList;
  15. typedef TList<DeviceDependant*> DeviceDependantList;
  16. //////////////////////////////////////////////////////////////////////////////
  17. //
  18. // members
  19. //
  20. //////////////////////////////////////////////////////////////////////////////
  21. //
  22. // State
  23. //
  24. bool m_bValid;
  25. bool m_bValidDevice;
  26. bool m_bFullscreen;
  27. bool m_bAllowSecondary;
  28. bool m_bAllow3DAcceleration;
  29. bool m_b3DAccelerationImportant;
  30. //
  31. // Direct Draw Devices
  32. //
  33. TRef<DDDevice> m_pdddevice;
  34. TRef<DDDevice> m_pdddeviceFullscreen;
  35. TRef<DDDevice> m_pdddevicePrimary;
  36. TRef<DDDevice> m_pdddeviceSecondary;
  37. //
  38. //
  39. //
  40. TRef<PixelFormat> m_ppf;
  41. TRef<IDirectDrawSurfaceX> m_pdds;
  42. HWND m_hwndClip;
  43. WinPoint m_pointPrimary;
  44. HWND m_hwndFocus;
  45. WinPoint m_pointFullscreen;
  46. WinPoint m_pointFullscreenCurrent;
  47. TRef<PrivateSurface> m_psurfaceBack;
  48. TRef<IDirectDrawClipper> m_pddClipper;
  49. float m_gamma;
  50. //
  51. // Surface Cache
  52. //
  53. DeviceDependantList m_listDeviceDependant;
  54. SurfaceList m_listSurfaces;
  55. SurfaceList m_listDeviceFormatSurfaces;
  56. //////////////////////////////////////////////////////////////////////////////
  57. //
  58. // Direct Draw Device Enumeration
  59. //
  60. //////////////////////////////////////////////////////////////////////////////
  61. static BOOL PASCAL StaticDDDeviceCallback(
  62. GUID FAR* lpGuid,
  63. LPTSTR lpDriverDesc,
  64. LPTSTR lpDriverName,
  65. LPVOID lpvoid
  66. ) {
  67. EngineImpl* pthis = (EngineImpl*)lpvoid;
  68. return pthis->DDDeviceCallback(lpGuid, lpDriverDesc, lpDriverName);
  69. }
  70. BOOL DDDeviceCallback(
  71. GUID FAR* lpGuid,
  72. LPTSTR lpDriverDesc,
  73. LPTSTR lpDriverName
  74. ) {
  75. if (lpGuid != NULL) {
  76. //
  77. // Create the DD device.
  78. //
  79. TRef<IDirectDraw> pdd;
  80. HRESULT hr = DirectDrawCreate(lpGuid, &pdd, NULL);
  81. if (SUCCEEDED(hr)) {
  82. TRef<IDirectDrawX> pddx;
  83. DDCall(pdd->QueryInterface(IID_IDirectDrawX, (void**)&pddx));
  84. //
  85. // Create a device data object
  86. //
  87. TRef<DDDevice> pdddevice = CreateDDDevice(this, m_bAllow3DAcceleration, pddx);
  88. if (pdddevice->IsValid()) {
  89. pdddevice->SetPrimaryDevice(m_pdddevicePrimary);
  90. //
  91. // If the device has 3D acceleration we'll use it as our secondary device
  92. //
  93. if (
  94. pdddevice->Has3DAcceleration()
  95. && (pdddevice->GetZBufferPixelFormat() != NULL)
  96. ) {
  97. m_pdddeviceSecondary = pdddevice;
  98. }
  99. }
  100. }
  101. }
  102. return DDENUMRET_OK;
  103. }
  104. //////////////////////////////////////////////////////////////////////////////
  105. //
  106. // Constructor
  107. //
  108. //////////////////////////////////////////////////////////////////////////////
  109. public:
  110. EngineImpl(bool bAllow3DAcceleration, bool bAllowSecondary) :
  111. m_pointFullscreen(640, 480),
  112. m_pointFullscreenCurrent(0, 0),
  113. m_bFullscreen(false),
  114. m_bAllow3DAcceleration(bAllow3DAcceleration),
  115. m_bAllowSecondary(bAllowSecondary),
  116. m_b3DAccelerationImportant(false),
  117. m_bValid(false),
  118. m_bValidDevice(false),
  119. m_hwndFocus(NULL),
  120. m_hwndClip(NULL),
  121. m_gamma(1.0f)
  122. {
  123. //
  124. // Get the primary device
  125. //
  126. m_pdddevicePrimary = CreateDDDevice(this, m_bAllow3DAcceleration, NULL);
  127. if (!m_pdddevicePrimary->IsValid()) {
  128. // !!! replace with a ZErrorHandler call
  129. ::MessageBox(
  130. NULL,
  131. "Unable to create primary DirectDraw Device.\n"
  132. "Please update your DirectX installation",
  133. "Initialization Error",
  134. MB_ICONEXCLAMATION | MB_OK
  135. );
  136. return;
  137. }
  138. //
  139. // Search for other devices with 3D support for fullscreen
  140. //
  141. DDCall(DirectDrawEnumerate(StaticDDDeviceCallback, this));
  142. //
  143. // Start on the primary device
  144. //
  145. m_pdddevice = m_pdddevicePrimary;
  146. //
  147. // Create a default pixel format
  148. //
  149. m_ppf = new PixelFormat(16, 0xf800, 0x07e0, 0x001f, 0x0000);
  150. }
  151. private:
  152. //////////////////////////////////////////////////////////////////////////////
  153. //
  154. // Destructor
  155. //
  156. //////////////////////////////////////////////////////////////////////////////
  157. ~EngineImpl()
  158. {
  159. }
  160. //////////////////////////////////////////////////////////////////////////////
  161. //
  162. // Terminate Dependants
  163. //
  164. //////////////////////////////////////////////////////////////////////////////
  165. void ClearDependants()
  166. {
  167. {
  168. DeviceDependantList::Iterator iter(m_listDeviceDependant);
  169. while (!iter.End()) {
  170. iter.Value()->ClearDevice();
  171. iter.Next();
  172. }
  173. }
  174. {
  175. SurfaceList::Iterator iter(m_listSurfaces);
  176. while (!iter.End()) {
  177. iter.Value()->ClearDevice();
  178. iter.Next();
  179. }
  180. }
  181. }
  182. //////////////////////////////////////////////////////////////////////////////
  183. //
  184. // Device Termination
  185. //
  186. //////////////////////////////////////////////////////////////////////////////
  187. void TerminateDevice()
  188. {
  189. ClearDependants();
  190. m_hwndClip = NULL;
  191. m_psurfaceBack = NULL;
  192. m_pddClipper = NULL;
  193. m_pdds = NULL;
  194. m_pdddevice->FreeEverything();
  195. m_pdddevice = NULL;
  196. }
  197. //////////////////////////////////////////////////////////////////////////////
  198. //
  199. // Termination
  200. //
  201. //////////////////////////////////////////////////////////////////////////////
  202. void Terminate()
  203. {
  204. ClearDependants();
  205. m_hwndClip = NULL;
  206. m_psurfaceBack = NULL;
  207. m_pddClipper = NULL;
  208. m_pdds = NULL;
  209. m_pdddevice = NULL;
  210. m_pdddevicePrimary->Terminate();
  211. if (m_pdddeviceSecondary != NULL) {
  212. m_pdddeviceSecondary->Terminate();
  213. }
  214. }
  215. //////////////////////////////////////////////////////////////////////////////
  216. //
  217. //
  218. //
  219. //////////////////////////////////////////////////////////////////////////////
  220. DDDevice* GetCurrentDevice()
  221. {
  222. return m_pdddevice;
  223. }
  224. DDDevice* GetPrimaryDevice()
  225. {
  226. return m_pdddevicePrimary;
  227. }
  228. DDSDescription GetPrimaryDDSD()
  229. {
  230. DDSDescription ddsd;
  231. DDCall(m_pdds->GetSurfaceDesc(&ddsd));
  232. return ddsd;
  233. }
  234. //////////////////////////////////////////////////////////////////////////////
  235. //
  236. // Validation
  237. //
  238. //////////////////////////////////////////////////////////////////////////////
  239. bool IsValid()
  240. {
  241. return m_pdddevicePrimary->IsValid();
  242. }
  243. //////////////////////////////////////////////////////////////////////////////
  244. //
  245. //
  246. //
  247. //////////////////////////////////////////////////////////////////////////////
  248. void SetFocusWindow(Window* pwindow, bool bStartFullscreen)
  249. {
  250. //
  251. // This function can only be called once
  252. //
  253. ZAssert(m_hwndFocus == NULL && pwindow->GetHWND() != NULL);
  254. ZAssert(!m_bValid);
  255. m_hwndFocus = pwindow->GetHWND();
  256. m_bFullscreen = bStartFullscreen;
  257. }
  258. //////////////////////////////////////////////////////////////////////////////
  259. //
  260. // Device Initialization
  261. //
  262. //////////////////////////////////////////////////////////////////////////////
  263. void UpdateSurfacesPixelFormat()
  264. {
  265. //
  266. // Tell all the Device format surfaces their new pixel format
  267. //
  268. {
  269. SurfaceList::Iterator iterSurface(m_listDeviceFormatSurfaces);
  270. while (!iterSurface.End()) {
  271. iterSurface.Value()->SetPixelFormat(m_ppf);
  272. iterSurface.Next();
  273. }
  274. }
  275. }
  276. //////////////////////////////////////////////////////////////////////////////
  277. //
  278. // SetGammaRamp
  279. //
  280. //////////////////////////////////////////////////////////////////////////////
  281. void SetGammaRamp()
  282. {
  283. if (m_pdds) {
  284. TRef<IDirectDrawGammaControlX> pddGammaControl;
  285. DDCall(m_pdds->QueryInterface(IID_IDirectDrawGammaControlX, (void**)&(pddGammaControl)));
  286. DDGAMMARAMP gammaRamp;
  287. for (int index = 0; index < 256; index ++) {
  288. float value = (float)index / 255;
  289. float level = pow(value, 1.0f / m_gamma);
  290. //float level = (m_gamma - 1) + (1 - (m_gamma - 1)) * value;
  291. int ilevel = MakeInt(level * 65535.0f);
  292. gammaRamp.red [index] = ilevel;
  293. gammaRamp.green[index] = ilevel;
  294. gammaRamp.blue [index] = ilevel;
  295. };
  296. //
  297. // zero is always black
  298. //
  299. gammaRamp.red [0] = 0;
  300. gammaRamp.green[0] = 0;
  301. gammaRamp.blue [0] = 0;
  302. pddGammaControl->SetGammaRamp(0, &gammaRamp);
  303. }
  304. }
  305. void SetGammaLevel(float value)
  306. {
  307. m_gamma = bound(value, 1.0f, 2.0f);
  308. SetGammaRamp();
  309. }
  310. float GetGammaLevel()
  311. {
  312. return m_gamma;
  313. }
  314. //////////////////////////////////////////////////////////////////////////////
  315. //
  316. // Create Primary Surface
  317. //
  318. //////////////////////////////////////////////////////////////////////////////
  319. bool CreatePrimarySurface()
  320. {
  321. //
  322. // Create the surface
  323. //
  324. DDSDescription ddsd;
  325. ddsd.dwFlags = DDSD_CAPS;
  326. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  327. m_pdds = NULL;
  328. DDCall(m_pdddevice->GetDD()->CreateSurface(&ddsd, &m_pdds, NULL));
  329. if (m_pdds == NULL) {
  330. return false;
  331. }
  332. //
  333. // Update the gamma ramp
  334. //
  335. SetGammaRamp();
  336. //
  337. // Get the pixel format
  338. //
  339. DDCall(m_pdds->GetSurfaceDesc(&ddsd));
  340. m_ppf = GetPixelFormat(ddsd.GetPixelFormat());
  341. //
  342. // Create a clipper for the surface
  343. //
  344. DDCall(m_pdddevice->GetDD()->CreateClipper(0, &m_pddClipper, NULL));
  345. DDCall(m_pdds->SetClipper(m_pddClipper));
  346. return true;
  347. };
  348. //////////////////////////////////////////////////////////////////////////////
  349. //
  350. // Switch to windowed
  351. //
  352. //////////////////////////////////////////////////////////////////////////////
  353. bool InitializeWindowed()
  354. {
  355. if (g_bWindowLog) {
  356. ZDebugOutput("InitializeWindowed\n");
  357. }
  358. //
  359. // If we were fullscreen go back to windowed mode
  360. //
  361. if (m_pdddeviceFullscreen != NULL) {
  362. if (g_bWindowLog) {
  363. ZDebugOutput("SetCooperativeLevel(Normal)\n");
  364. }
  365. DDCall(m_pdddeviceFullscreen->GetDD()->SetCooperativeLevel(NULL, DDSCL_NORMAL));
  366. m_pdddeviceFullscreen = NULL;
  367. }
  368. //
  369. // Free up all the device specific objects
  370. //
  371. TerminateDevice();
  372. //
  373. // switch to the windowed device
  374. //
  375. m_pdddevice = m_pdddevicePrimary;
  376. m_pointFullscreenCurrent = WinPoint(0, 0);
  377. //
  378. // Get the primary surface
  379. //
  380. if (!CreatePrimarySurface()) {
  381. return false;
  382. }
  383. //
  384. // If the primary surface isn't 16bpp go to fullscreen automatically
  385. //
  386. if (m_ppf->PixelBits() != 16) {
  387. m_bFullscreen = true;
  388. return false;
  389. }
  390. //
  391. // Update any device format surfaces
  392. //
  393. UpdateSurfacesPixelFormat();
  394. if (g_bWindowLog) {
  395. ZDebugOutput("InitializeWindowed exiting\n");
  396. }
  397. return true;
  398. }
  399. //////////////////////////////////////////////////////////////////////////////
  400. //
  401. // Create Fullscreen Surface
  402. //
  403. //////////////////////////////////////////////////////////////////////////////
  404. bool CreateFullscreenSurface(DDDevice* pdddevice, bool& bError)
  405. {
  406. bError = false;
  407. HRESULT hr;
  408. //
  409. // Create a double buffered surface
  410. //
  411. DDSDescription ddsd;
  412. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  413. ddsd.ddsCaps.dwCaps =
  414. DDSCAPS_PRIMARYSURFACE
  415. | DDSCAPS_FLIP
  416. | DDSCAPS_COMPLEX
  417. | DDSCAPS_3DDEVICE;
  418. ddsd.dwBackBufferCount = 1;
  419. hr = pdddevice->GetDD()->CreateSurface(&ddsd, &m_pdds, NULL);
  420. if (hr == DDERR_OUTOFVIDEOMEMORY) {
  421. ZAssert(m_pdds == NULL);
  422. if (g_bWindowLog) {
  423. ZDebugOutput("Not enough memory for primary surface\n");
  424. }
  425. return false;
  426. }
  427. if (hr == DDERR_NOEXCLUSIVEMODE) {
  428. ZAssert(m_pdds == NULL);
  429. if (g_bWindowLog) {
  430. ZDebugOutput("Exclusive mode was lost\n");
  431. }
  432. bError = true;
  433. return false;
  434. }
  435. if (hr == DDERR_UNSUPPORTEDMODE) {
  436. ZAssert(m_pdds == NULL);
  437. if (g_bWindowLog) {
  438. ZDebugOutput("Unsupported mode\n");
  439. }
  440. bError = true;
  441. return false;
  442. }
  443. DDCall(hr);
  444. if (m_pdds == NULL) {
  445. return false;
  446. }
  447. //
  448. // Create a clipper for the surface
  449. //
  450. #ifndef DREAMCAST
  451. DDCall(pdddevice->GetDD()->CreateClipper(0, &m_pddClipper, NULL));
  452. DDCall(m_pdds->SetClipper(m_pddClipper));
  453. #endif
  454. //
  455. // Update the gamma ramp
  456. //
  457. SetGammaRamp();
  458. //
  459. // Get the pixel format
  460. //
  461. DDCall(m_pdds->GetSurfaceDesc(&ddsd));
  462. m_ppf = GetPixelFormat(ddsd.GetPixelFormat());
  463. //
  464. // Create the ZBuffer
  465. //
  466. TRef<IDirectDrawSurfaceX> pddsZBuffer;
  467. if (pdddevice->GetAllow3DAcceleration()) {
  468. #ifdef DREAMCAST
  469. ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH;
  470. ddsd.dwWidth = ddsd.dwWidth;
  471. ddsd.dwHeight = ddsd.dwHeight;
  472. ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
  473. ddsd.dwZBufferBitDepth = 16UL;
  474. ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
  475. ddsd.ddpfPixelFormat.dwZBufferBitDepth = 16UL;
  476. #else
  477. ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS | DDSD_PIXELFORMAT;
  478. ddsd.dwWidth = ddsd.dwWidth;
  479. ddsd.dwHeight = ddsd.dwHeight;
  480. ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
  481. ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  482. ddsd.ddpfPixelFormat = pdddevice->GetZBufferPixelFormat()->GetDDPF();
  483. #endif
  484. hr = pdddevice->GetDD()->CreateSurface(&ddsd, &pddsZBuffer, NULL);
  485. if (hr == DDERR_OUTOFVIDEOMEMORY) {
  486. if (g_bWindowLog) {
  487. ZDebugOutput("Not enough memory for ZBuffer\n");
  488. }
  489. m_pdds = NULL;
  490. return false;
  491. }
  492. if (hr == DDERR_NOZBUFFERHW) {
  493. if (g_bWindowLog) {
  494. ZDebugOutput("Device doesn't support ZBuffers\n");
  495. }
  496. m_pdds = NULL;
  497. return false;
  498. }
  499. DDCall(hr);
  500. }
  501. //
  502. // Get the back buffer
  503. //
  504. DDSCaps caps;
  505. caps.dwCaps = DDSCAPS_BACKBUFFER;
  506. TRef<IDirectDrawSurfaceX> pddsBack;
  507. DDCall(m_pdds->GetAttachedSurface(&caps, &pddsBack));
  508. if (pddsBack == NULL) {
  509. m_pdds = NULL;
  510. return false;
  511. }
  512. //
  513. // Attach the ZBuffer to the back buffer
  514. //
  515. if (pddsZBuffer) {
  516. if (FAILED(pddsBack->AddAttachedSurface(pddsZBuffer))) {
  517. m_pdds = NULL;
  518. return false;
  519. }
  520. }
  521. //
  522. // Create a surface wrapper
  523. //
  524. SurfaceType stype = SurfaceType2D() | SurfaceType3D() | SurfaceTypeZBuffer() | SurfaceTypeVideo();
  525. m_psurfaceBack =
  526. CreatePrivateSurface(
  527. this,
  528. CreateDDSurface(
  529. pdddevice,
  530. pddsBack,
  531. pddsZBuffer,
  532. m_ppf,
  533. NULL,
  534. stype
  535. ),
  536. NULL
  537. );
  538. //
  539. // Fill the surface with black
  540. //
  541. m_psurfaceBack->FillSurface(Color::Black());
  542. Flip();
  543. m_psurfaceBack->FillSurface(Color::Black());
  544. return true;
  545. }
  546. //////////////////////////////////////////////////////////////////////////////
  547. //
  548. // Switch to a device at a certain resolution
  549. //
  550. //////////////////////////////////////////////////////////////////////////////
  551. bool SwitchToFullscreenDevice(DDDevice* pdddevice, const WinPoint& size, bool& bError)
  552. {
  553. bError = false;
  554. if (g_bWindowLog) {
  555. ZDebugOutput(
  556. "SwitchToFullscreenDevice( "
  557. + pdddevice->GetName()
  558. + ", resolution: "
  559. + GetString(size)
  560. + ")\n"
  561. );
  562. }
  563. //
  564. // If switching to a different device go to normal mode
  565. //
  566. if (m_pdddeviceFullscreen != NULL && m_pdddeviceFullscreen != pdddevice) {
  567. if (g_bWindowLog) {
  568. ZDebugOutput("SetCooperativeLevel(" + pdddevice->GetName() + ", Normal)\n");
  569. }
  570. DDCall(m_pdddeviceFullscreen->GetDD()->SetCooperativeLevel(NULL, DDSCL_NORMAL));
  571. m_pdddeviceFullscreen = NULL;
  572. }
  573. //
  574. // Free up all the device specific objects
  575. //
  576. TerminateDevice();
  577. m_pdddevice = pdddevice;
  578. //
  579. // If this is a new fullscreen device go to exclusive mode
  580. //
  581. if (m_pdddeviceFullscreen != pdddevice) {
  582. if (g_bWindowLog) {
  583. ZDebugOutput("SetCooperativeLevel(" + pdddevice->GetName() + ", Exclusive)\n");
  584. }
  585. HRESULT hr =
  586. pdddevice->GetDD()->SetCooperativeLevel(
  587. m_hwndFocus,
  588. DDSCL_EXCLUSIVE
  589. | DDSCL_FULLSCREEN
  590. );
  591. if (hr == DDERR_EXCLUSIVEMODEALREADYSET) {
  592. if (g_bWindowLog) {
  593. ZDebugOutput("Can't set exclusive mode\n");
  594. }
  595. bError = true;
  596. return false;
  597. }
  598. DDCall(hr);
  599. m_pdddeviceFullscreen = pdddevice;
  600. }
  601. //
  602. // Switch resolutions
  603. //
  604. HRESULT hr =
  605. m_pdddevice->GetDD()->SetDisplayMode(
  606. size.X(),
  607. size.Y(),
  608. 16,
  609. 0,
  610. 0
  611. );
  612. if (
  613. hr == DDERR_NOEXCLUSIVEMODE
  614. || hr == DDERR_UNSUPPORTED
  615. ) {
  616. if (g_bWindowLog) {
  617. ZDebugOutput("Error setting display mode\n");
  618. }
  619. bError = true;
  620. return false;
  621. }
  622. if (hr == DDERR_INVALIDMODE) {
  623. pdddevice->EliminateModes(size);
  624. if (g_bWindowLog) {
  625. ZDebugOutput("Invalid resolution\n");
  626. }
  627. return false;
  628. }
  629. DDCall(hr);
  630. //
  631. // Create the primary surface and back buffer
  632. //
  633. if (!CreateFullscreenSurface(pdddevice, bError)) {
  634. return false;
  635. }
  636. //
  637. // Everything worked. Update any device format surfaces.
  638. //
  639. UpdateSurfacesPixelFormat();
  640. if (g_bWindowLog) {
  641. ZDebugOutput("SwitchToFullscreenDevice exiting\n");
  642. }
  643. return true;
  644. }
  645. //////////////////////////////////////////////////////////////////////////////
  646. //
  647. // Switch to full screen
  648. //
  649. //////////////////////////////////////////////////////////////////////////////
  650. bool InitializeFullscreen(bool& bChanges)
  651. {
  652. if (g_bWindowLog) {
  653. ZDebugOutput("InitalizeFullscreen()\n");
  654. }
  655. //
  656. // Try the secondary device first
  657. //
  658. DDDevice* pdddevice;
  659. if (
  660. m_bAllowSecondary
  661. && m_bAllow3DAcceleration
  662. && m_b3DAccelerationImportant
  663. && m_pdddeviceSecondary != NULL
  664. && m_pdddeviceSecondary->GetAllow3DAcceleration()
  665. ) {
  666. pdddevice = m_pdddeviceSecondary;
  667. } else {
  668. pdddevice = m_pdddevicePrimary;
  669. }
  670. //
  671. // Don't do anything if we don't need to change the device
  672. // or resolution
  673. //
  674. if (
  675. m_bValidDevice
  676. && m_pdddevice == pdddevice
  677. && m_pointFullscreenCurrent == m_pointFullscreen
  678. ) {
  679. ZDebugOutput("Device and resolution match\n");
  680. return true;
  681. }
  682. //
  683. // Try different resolutions until we find one that actually works
  684. //
  685. bChanges = true;
  686. while (true) {
  687. //
  688. // Try the current resolution
  689. //
  690. bool bError;
  691. if (SwitchToFullscreenDevice(pdddevice, m_pointFullscreen, bError)) {
  692. m_pointFullscreenCurrent = m_pointFullscreen;
  693. return true;
  694. }
  695. //
  696. // If there was an error just return
  697. //
  698. if (bError) {
  699. return false;
  700. }
  701. //
  702. // Didn't work goto to the next lower resolution
  703. //
  704. WinPoint pointNew = pdddevice->PreviousMode(m_pointFullscreen);
  705. if (pointNew == m_pointFullscreen) {
  706. if (g_bWindowLog) {
  707. ZDebugOutput("No more valid resolutions\n");
  708. }
  709. return false;
  710. }
  711. m_pointFullscreen = pointNew;
  712. }
  713. }
  714. //////////////////////////////////////////////////////////////////////////////
  715. //
  716. //
  717. //
  718. //////////////////////////////////////////////////////////////////////////////
  719. void DebugSetWindowed()
  720. {
  721. #ifndef DREAMCAST
  722. if (m_pdddevice != NULL) {
  723. m_pdddevice->GetDD()->SetCooperativeLevel(NULL, DDSCL_NORMAL);
  724. }
  725. #endif
  726. }
  727. //////////////////////////////////////////////////////////////////////////////
  728. //
  729. // Set Attributes
  730. //
  731. //////////////////////////////////////////////////////////////////////////////
  732. void SetAllowSecondary(bool bAllowSecondary)
  733. {
  734. if (m_bAllowSecondary != bAllowSecondary) {
  735. m_bAllowSecondary = bAllowSecondary;
  736. m_bValid = false;
  737. m_bValidDevice = false;
  738. }
  739. }
  740. void SetAllow3DAcceleration(bool bAllow3DAcceleration)
  741. {
  742. if (m_bAllow3DAcceleration != bAllow3DAcceleration) {
  743. m_bAllow3DAcceleration = bAllow3DAcceleration;
  744. m_pdddevicePrimary->SetAllow3DAcceleration(m_bAllow3DAcceleration);
  745. m_bValid = false;
  746. m_bValidDevice = false;
  747. }
  748. }
  749. void Set3DAccelerationImportant(bool b3DAccelerationImportant)
  750. {
  751. if (m_b3DAccelerationImportant != b3DAccelerationImportant) {
  752. m_b3DAccelerationImportant = b3DAccelerationImportant;
  753. m_bValid = false;
  754. }
  755. }
  756. void SetFullscreen(bool bFullscreen)
  757. {
  758. if (m_bFullscreen != bFullscreen) {
  759. m_bFullscreen = bFullscreen;
  760. m_bValid = false;
  761. m_bValidDevice = false;
  762. }
  763. }
  764. void SetFullscreenSize(const WinPoint& point)
  765. {
  766. if (g_bWindowLog) {
  767. ZDebugOutput("Engine::SetFullscreenSize(" + GetString(point) + ")\n");
  768. }
  769. if (m_pointFullscreen != point) {
  770. m_pointFullscreen = point;
  771. m_bValid = false;
  772. }
  773. if (g_bWindowLog) {
  774. ZDebugOutput("Engine::SetFullscreenSize() Exiting\n");
  775. }
  776. }
  777. void ChangeFullscreenSize(bool bLarger)
  778. {
  779. WinPoint point;
  780. if (bLarger) {
  781. point = m_pdddevice->NextMode(m_pointFullscreen);
  782. } else {
  783. point = m_pdddevice->PreviousMode(m_pointFullscreen);
  784. }
  785. SetFullscreenSize(point);
  786. }
  787. //////////////////////////////////////////////////////////////////////////////
  788. //
  789. // Get Attributes
  790. //
  791. //////////////////////////////////////////////////////////////////////////////
  792. bool GetAllowSecondary()
  793. {
  794. return m_bAllowSecondary;
  795. }
  796. bool GetAllow3DAcceleration()
  797. {
  798. return m_bAllow3DAcceleration;
  799. }
  800. bool Get3DAccelerationImportant()
  801. {
  802. return m_b3DAccelerationImportant;
  803. }
  804. const WinPoint& GetFullscreenSize()
  805. {
  806. return m_pointFullscreen;
  807. }
  808. bool IsFullscreen()
  809. {
  810. return m_bFullscreen;
  811. }
  812. bool PrimaryHas3DAcceleration()
  813. {
  814. return
  815. m_pdddevicePrimary->Has3DAcceleration()
  816. && (m_pdddevicePrimary->GetZBufferPixelFormat() != NULL);
  817. }
  818. ZString GetDeviceName()
  819. {
  820. return m_pdddevice->GetName();
  821. }
  822. bool GetUsing3DAcceleration()
  823. {
  824. return m_pdddevice->GetAllow3DAcceleration();
  825. }
  826. PrivateSurface* GetBackBuffer()
  827. {
  828. return m_psurfaceBack;
  829. }
  830. //////////////////////////////////////////////////////////////////////////////
  831. //
  832. //
  833. //
  834. //////////////////////////////////////////////////////////////////////////////
  835. bool DeviceOK(bool& bChanges)
  836. {
  837. if (!m_bValid) {
  838. if (m_bFullscreen) {
  839. m_bValid = InitializeFullscreen(bChanges);
  840. } else {
  841. bChanges = true;
  842. m_bValid = InitializeWindowed();
  843. }
  844. m_bValidDevice = m_bValid;
  845. }
  846. return m_bValid;
  847. }
  848. bool IsDeviceReady(bool& bChanges)
  849. {
  850. bChanges = false;
  851. if (m_pdddevice) {
  852. HRESULT hr = m_pdddevice->TestCooperativeLevel();
  853. switch (hr) {
  854. case DD_OK:
  855. return DeviceOK(bChanges);
  856. case DDERR_NOEXCLUSIVEMODE:
  857. //
  858. // fullscreen but not active
  859. //
  860. m_bValidDevice = false;
  861. m_bValid = false;
  862. break;
  863. case DDERR_EXCLUSIVEMODEALREADYSET:
  864. //
  865. // windowed somebody else is fullscreen
  866. //
  867. m_bValidDevice = false;
  868. m_bValid = false;
  869. break;
  870. case DDERR_WRONGMODE:
  871. //
  872. // windowed the pixel depth has changed
  873. //
  874. m_pdddevicePrimary->Reset(NULL);
  875. m_bValidDevice = false;
  876. m_bValid = false;
  877. return DeviceOK(bChanges);
  878. default:
  879. ZError("Unexpected result\n");
  880. }
  881. }
  882. return false;
  883. }
  884. //////////////////////////////////////////////////////////////////////////////
  885. //
  886. // Screen updates
  887. //
  888. //////////////////////////////////////////////////////////////////////////////
  889. void Flip()
  890. {
  891. ZAssert(m_pdddeviceFullscreen);
  892. DDSurface* pddsurface; CastTo(pddsurface, m_psurfaceBack->GetVideoSurface());
  893. pddsurface->GetDDSX();
  894. HRESULT hr = m_pdds->Flip(NULL, DDFLIP_WAIT);
  895. if (
  896. hr == DDERR_NOEXCLUSIVEMODE
  897. || hr == DDERR_SURFACELOST
  898. ) {
  899. // These errors are ok if we are no longer active.
  900. } else {
  901. DDCall(hr);
  902. }
  903. }
  904. void BltToWindow(Window* pwindow, const WinPoint& point, Surface* psurface, const WinRect& rectSource)
  905. {
  906. if (m_pdddeviceFullscreen == NULL) {
  907. if (m_hwndClip != pwindow->GetHWND()) {
  908. m_hwndClip = pwindow->GetHWND();
  909. DDCall(m_pddClipper->SetHWnd(0, m_hwndClip));
  910. }
  911. m_pointPrimary = pwindow->ClientToScreen(WinPoint(0, 0));
  912. WinRect
  913. rectTarget(
  914. m_pointPrimary + point,
  915. m_pointPrimary + point + rectSource.Size()
  916. );
  917. PrivateSurface* pprivateSurface; CastTo(pprivateSurface, psurface);
  918. DDSurface* pddsurface; CastTo(pddsurface, pprivateSurface->GetVideoSurface());
  919. HRESULT hr =
  920. m_pdds->Blt(
  921. (RECT*)&rectTarget,
  922. pddsurface->GetDDSX(),
  923. (RECT*)&rectSource,
  924. DDBLT_WAIT,
  925. NULL
  926. );
  927. }
  928. }
  929. //////////////////////////////////////////////////////////////////////////////
  930. //
  931. // Pixel Format cache
  932. //
  933. //////////////////////////////////////////////////////////////////////////////
  934. TVector<TRef<PixelFormat> > m_ppfs;
  935. TRef<PixelFormat> GetPixelFormat(const DDPixelFormat& ddpf)
  936. {
  937. int count = m_ppfs.GetCount();
  938. for(int index = 0; index < count; index++) {
  939. if (m_ppfs[index]->Equivalent(ddpf)) {
  940. return m_ppfs[index];
  941. }
  942. }
  943. TRef<PixelFormat> ppf = new PixelFormat(ddpf);
  944. m_ppfs.PushEnd(ppf);
  945. return ppf;
  946. }
  947. TRef<PixelFormat> GetPixelFormat(
  948. int bits,
  949. DWORD redMask,
  950. DWORD greenMask,
  951. DWORD blueMask,
  952. DWORD alphaMask
  953. ) {
  954. DDPixelFormat ddpf;
  955. ddpf.dwSize = sizeof(DDPIXELFORMAT);
  956. ddpf.dwFlags = DDPF_RGB;
  957. ddpf.dwFourCC = 0;
  958. ddpf.dwRGBBitCount = bits;
  959. ddpf.dwRBitMask = redMask;
  960. ddpf.dwGBitMask = greenMask;
  961. ddpf.dwBBitMask = blueMask;
  962. ddpf.dwRGBAlphaBitMask = alphaMask;
  963. return GetPixelFormat(ddpf);
  964. }
  965. PixelFormat* GetPrimaryPixelFormat()
  966. {
  967. return m_ppf;
  968. }
  969. //////////////////////////////////////////////////////////////////////////////
  970. //
  971. // Performance Counters
  972. //
  973. //////////////////////////////////////////////////////////////////////////////
  974. int GetTotalTextureMemory() { return m_pdddevice->GetTotalTextureMemory(); }
  975. int GetAvailableTextureMemory() { return m_pdddevice->GetAvailableTextureMemory(); }
  976. int GetTotalVideoMemory() { return m_pdddevice->GetTotalVideoMemory(); }
  977. int GetAvailableVideoMemory() { return m_pdddevice->GetAvailableVideoMemory(); }
  978. //////////////////////////////////////////////////////////////////////////////
  979. //
  980. // Surface Cache
  981. //
  982. //////////////////////////////////////////////////////////////////////////////
  983. void AddDeviceDependant(DeviceDependant* pdeviceDependant)
  984. {
  985. m_listDeviceDependant.PushFront(pdeviceDependant);
  986. }
  987. void RemoveDeviceDependant(DeviceDependant* pdeviceDependant)
  988. {
  989. m_listDeviceDependant.Remove(pdeviceDependant);
  990. }
  991. void RemovePrivateSurface(PrivateSurface* psurface)
  992. {
  993. //
  994. // Remove from the surface lists
  995. //
  996. m_listDeviceFormatSurfaces.Remove(psurface);
  997. m_listSurfaces.Remove(psurface);
  998. //
  999. // free up any device textures
  1000. //
  1001. DDSurface* pddsurface; CastTo(pddsurface, psurface->GetVideoSurfaceNoAlloc());
  1002. if (pddsurface) {
  1003. m_pdddevicePrimary->RemoveSurface(pddsurface);
  1004. if (m_pdddeviceSecondary != NULL) {
  1005. m_pdddeviceSecondary->RemoveSurface(pddsurface);
  1006. }
  1007. }
  1008. }
  1009. //////////////////////////////////////////////////////////////////////////////
  1010. //
  1011. // VideoSurface Constructors
  1012. //
  1013. //////////////////////////////////////////////////////////////////////////////
  1014. TRef<VideoSurface> CreateVideoSurface(
  1015. SurfaceType stype,
  1016. PixelFormat* ppf,
  1017. PrivatePalette* ppalette,
  1018. const WinPoint& size,
  1019. int pitch,
  1020. BYTE* pbits
  1021. ) {
  1022. if (stype.Test(SurfaceTypeVideo())) {
  1023. return
  1024. CreateDDSurface(
  1025. m_pdddevice,
  1026. stype,
  1027. m_ppf,
  1028. NULL,
  1029. size
  1030. );
  1031. } else {
  1032. PrivatePalette* pprivatePalette; CastTo(pprivatePalette, ppalette);
  1033. return
  1034. CreateDDSurface(
  1035. m_pdddevicePrimary,
  1036. stype,
  1037. ppf,
  1038. ppalette,
  1039. size,
  1040. pitch,
  1041. pbits
  1042. );
  1043. }
  1044. }
  1045. //////////////////////////////////////////////////////////////////////////////
  1046. //
  1047. // Surface Constructors
  1048. //
  1049. //////////////////////////////////////////////////////////////////////////////
  1050. TRef<PrivateSurface> AddSurface(PrivateSurface* psurface, bool bDevice)
  1051. {
  1052. m_listSurfaces.PushEnd(psurface);
  1053. if (bDevice) {
  1054. m_listDeviceFormatSurfaces.PushEnd(psurface);
  1055. }
  1056. return psurface;
  1057. }
  1058. //////////////////////////////////////////////////////////////////////////////
  1059. //
  1060. // Create a surface with the specified pixel format
  1061. //
  1062. //////////////////////////////////////////////////////////////////////////////
  1063. TRef<Surface> CreateSurface(
  1064. const WinPoint& size,
  1065. PixelFormat* ppf,
  1066. Palette* ppalette,
  1067. SurfaceType stype,
  1068. SurfaceSite* psite
  1069. ) {
  1070. PrivatePalette* pprivatePalette; CastTo(pprivatePalette, ppalette);
  1071. return
  1072. AddSurface(
  1073. CreatePrivateSurface(
  1074. this,
  1075. ppf,
  1076. pprivatePalette,
  1077. size,
  1078. stype,
  1079. psite
  1080. ),
  1081. false
  1082. );
  1083. }
  1084. //////////////////////////////////////////////////////////////////////////////
  1085. //
  1086. // Create a device format surface
  1087. //
  1088. //////////////////////////////////////////////////////////////////////////////
  1089. TRef<Surface> CreateSurface(
  1090. const WinPoint& size,
  1091. SurfaceType stype,
  1092. SurfaceSite* psite
  1093. ) {
  1094. if (stype.Test(SurfaceTypeVideo())) {
  1095. TRef<DDSurface> pddsurface =
  1096. CreateDDSurface(
  1097. m_pdddevice,
  1098. stype,
  1099. m_ppf,
  1100. NULL,
  1101. size
  1102. );
  1103. if (pddsurface != NULL) {
  1104. TRef<PrivateSurface> psurface = CreatePrivateSurface(this, pddsurface, psite);
  1105. return AddSurface(psurface, true);
  1106. }
  1107. return NULL;
  1108. } else {
  1109. return
  1110. AddSurface(
  1111. CreatePrivateSurface(
  1112. this,
  1113. m_ppf,
  1114. NULL,
  1115. size,
  1116. stype,
  1117. psite
  1118. ),
  1119. true
  1120. );
  1121. }
  1122. }
  1123. //////////////////////////////////////////////////////////////////////////////
  1124. //
  1125. //
  1126. //
  1127. //////////////////////////////////////////////////////////////////////////////
  1128. TRef<PrivateSurface> CreateCompatibleSurface(
  1129. PrivateSurface* psurface,
  1130. const WinPoint& size,
  1131. SurfaceType stype,
  1132. SurfaceSite* psite
  1133. ) {
  1134. PrivatePalette* pprivatePalette; CastTo(pprivatePalette, psurface->GetPalette());
  1135. return
  1136. AddSurface(
  1137. CreatePrivateSurface(
  1138. this,
  1139. psurface->GetPixelFormat(),
  1140. pprivatePalette,
  1141. size,
  1142. stype,
  1143. psite
  1144. ),
  1145. false
  1146. );
  1147. }
  1148. //////////////////////////////////////////////////////////////////////////////
  1149. //
  1150. //
  1151. //
  1152. //////////////////////////////////////////////////////////////////////////////
  1153. TRef<Surface> CreateSurface(HBITMAP hbitmap)
  1154. {
  1155. //
  1156. // Get the bitmap size
  1157. //
  1158. BITMAP bm;
  1159. ZVerify(::GetObject(hbitmap, sizeof(bm), &bm));
  1160. //
  1161. // Create a DC for the bitmap
  1162. //
  1163. HDC hdcBitmap = ::CreateCompatibleDC(NULL);
  1164. ZAssert(hdcBitmap != NULL);
  1165. HBITMAP hbitmapOld = (HBITMAP)::SelectObject(hdcBitmap, hbitmap);
  1166. ZAssert(hbitmapOld != NULL);
  1167. //
  1168. // Create a surface whose pixel format matches the bitmap
  1169. //
  1170. DDPixelFormat ddpf;
  1171. TRef<IDirectDrawPaletteX> pddpal;
  1172. ZVerify(FillDDPF(ddpf, m_pdddevicePrimary->GetDD(), hdcBitmap, hbitmap, &pddpal));
  1173. TRef<PrivatePalette> ppalette;
  1174. if (pddpal) {
  1175. ppalette = CreatePaletteImpl(pddpal);
  1176. }
  1177. //
  1178. // Create the source surface
  1179. //
  1180. TRef<PrivateSurface> psurface =
  1181. CreatePrivateSurface(
  1182. this,
  1183. GetPixelFormat(ddpf),
  1184. ppalette,
  1185. WinPoint(bm.bmWidth, bm.bmHeight),
  1186. SurfaceType2D(),
  1187. NULL
  1188. );
  1189. //
  1190. // Copy the bitmap to the surface
  1191. //
  1192. psurface->BitBltFromDC(hdcBitmap);
  1193. //
  1194. // Release the DC we created
  1195. //
  1196. ZVerify(::SelectObject(hdcBitmap, hbitmapOld));
  1197. ZVerify(::DeleteDC(hdcBitmap));
  1198. return AddSurface(psurface, false);
  1199. }
  1200. //////////////////////////////////////////////////////////////////////////////
  1201. //
  1202. //
  1203. //
  1204. //////////////////////////////////////////////////////////////////////////////
  1205. TRef<Surface> CreateSurface(
  1206. const WinPoint& size,
  1207. PixelFormat* ppf,
  1208. Palette* ppalette,
  1209. int pitch,
  1210. BYTE* pdata,
  1211. IObject* pobjectMemory
  1212. ) {
  1213. PrivatePalette* pprivatePalette; CastTo(pprivatePalette, ppalette);
  1214. return
  1215. AddSurface(
  1216. CreatePrivateSurface(
  1217. this,
  1218. ppf,
  1219. pprivatePalette,
  1220. size,
  1221. pitch,
  1222. pdata,
  1223. pobjectMemory
  1224. ),
  1225. false
  1226. );
  1227. }
  1228. };
  1229. //////////////////////////////////////////////////////////////////////////////
  1230. //
  1231. //
  1232. //
  1233. //////////////////////////////////////////////////////////////////////////////
  1234. TRef<Engine> CreateEngine(bool bAllow3DAcceleration, bool bAllowSecondary)
  1235. {
  1236. return new EngineImpl(bAllow3DAcceleration, bAllowSecondary);
  1237. }