dddevice.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // DeviceTextureImpl
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class DeviceTexture : public IObject {
  8. private:
  9. //////////////////////////////////////////////////////////////////////////////
  10. //
  11. // Members
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. TRef<IDirectDrawSurfaceX> m_pdds;
  15. TRef<IDirect3DTextureX> m_pd3dtexture;
  16. DDSurface* m_pddsurface;
  17. int m_idSurface;
  18. TRef<PixelFormat> m_ppf;
  19. bool m_bMipMap;
  20. public:
  21. //////////////////////////////////////////////////////////////////////////////
  22. //
  23. // Constructor
  24. //
  25. //////////////////////////////////////////////////////////////////////////////
  26. DeviceTexture(
  27. DDDevice* pdddevice,
  28. D3DDevice* pd3dd,
  29. DDSurface* pddsurface,
  30. const WinPoint& size
  31. ) :
  32. m_pddsurface(pddsurface),
  33. m_idSurface(-1),
  34. m_ppf(pd3dd->GetTextureFormat()),
  35. m_bMipMap(false)
  36. {
  37. DWORD dw =
  38. DDSCAPS_TEXTURE
  39. | DDSCAPS_VIDEOMEMORY;
  40. #ifndef DREAMCAST // this flag can't be specified in order to do our copy instead of load hack
  41. dw |= DDSCAPS_ALLOCONLOAD;
  42. #endif
  43. if (m_bMipMap) {
  44. m_pdds = pdddevice->CreateMipMapTexture(size, m_ppf);
  45. } else {
  46. m_pdds = pdddevice->CreateSurface(size, dw, m_ppf, true);
  47. }
  48. if (m_pdds != NULL) {
  49. if (m_pddsurface->HasColorKey()) {
  50. DDCOLORKEY key;
  51. key.dwColorSpaceLowValue =
  52. key.dwColorSpaceHighValue =
  53. m_ppf->MakePixel(m_pddsurface->GetColorKey()).Value();
  54. DDCall(m_pdds->SetColorKey(DDCKEY_SRCBLT, &key));
  55. }
  56. DDCall(m_pdds->QueryInterface(IID_IDirect3DTextureX, (void**)&m_pd3dtexture));
  57. //
  58. // Try to load the surface
  59. //
  60. DoLoad(m_pd3dtexture, size);
  61. }
  62. }
  63. //////////////////////////////////////////////////////////////////////////////
  64. //
  65. // Methods
  66. //
  67. //////////////////////////////////////////////////////////////////////////////
  68. bool IsValid()
  69. {
  70. return m_pd3dtexture != NULL;
  71. }
  72. bool DoLoad(TRef<IDirect3DTextureX> pd3dtexture, WinPoint size)
  73. {
  74. #ifdef DREAMCAST
  75. TRef<IDirectDrawSurfaceX> pddsSrc;
  76. DDSDescription ddsdSrc;
  77. DDSDescription ddsdDest;
  78. DDCall(pd3dtexture->QueryInterface(IID_IDirectDrawSurfaceX, (void**)&pddsSrc));
  79. DDCall(pddsSrc->Lock(NULL, &ddsdSrc, DDLOCK_DYNAMIC | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL));
  80. DDCall(m_pdds->Lock(NULL, &ddsdDest, DDLOCK_DYNAMIC | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL));
  81. ZAssert(
  82. ddsdDest.Pitch() == ddsdSrc.Pitch()
  83. && ddsdDest.dwHeight == ddsdSrc.dwHeight
  84. );
  85. memcpy((void*)ddsdDest.Pointer(), (void*)ddsdSrc.Pointer(), ddsdSrc.Pitch() * ddsdSrc.dwHeight);
  86. DDCall(pddsSrc->Unlock(NULL));
  87. DDCall(m_pdds->Unlock(NULL));
  88. #else
  89. while (pd3dtexture != NULL) {
  90. HRESULT hr =
  91. pd3dtexture->Load(
  92. m_pddsurface->GetTextureX(m_ppf, size, m_idSurface)
  93. );
  94. if (FAILED(hr)) {
  95. //
  96. // couldn't load it free everything
  97. //
  98. if (
  99. hr != DDERR_SURFACELOST
  100. && hr != DDERR_SURFACEBUSY
  101. ) {
  102. DDCall(hr);
  103. }
  104. m_pd3dtexture = NULL;
  105. m_pdds = NULL;
  106. return false;
  107. }
  108. if (m_bMipMap) {
  109. size.SetX(size.X() / 2);
  110. size.SetY(size.Y() / 2);
  111. TRef<IDirectDrawSurfaceX> pdds;
  112. DDCall(pd3dtexture->QueryInterface(IID_IDirectDrawSurfaceX, (void**)&pdds));
  113. DDSCAPS2 ddsCaps;
  114. ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  115. DDCall(pdds->GetAttachedSurface(&ddsCaps, &pdds));
  116. DDCall(pdds->QueryInterface(IID_IDirect3DTextureX, (void**)&pd3dtexture));
  117. }
  118. return true;
  119. }
  120. #endif
  121. return true;
  122. }
  123. IDirect3DTextureX* GetTextureX(const WinPoint& size)
  124. {
  125. int idSave = m_idSurface;
  126. IDirect3DTextureX* pd3dtexture = m_pddsurface->GetTextureX(m_ppf, size, m_idSurface);
  127. if (idSave != m_idSurface) {
  128. if (!DoLoad(pd3dtexture, size)) {
  129. return NULL;
  130. }
  131. }
  132. return m_pd3dtexture;
  133. }
  134. };
  135. //////////////////////////////////////////////////////////////////////////////
  136. //
  137. // Direct Draw Device Implementation
  138. //
  139. //////////////////////////////////////////////////////////////////////////////
  140. WinPoint g_validModes[] =
  141. {
  142. WinPoint( 640, 480),
  143. WinPoint( 800, 600),
  144. WinPoint(1024, 768),
  145. WinPoint(1280, 1024),
  146. WinPoint(1600, 1200)
  147. };
  148. const int g_countValidModes = sizeof(g_validModes) / sizeof(g_validModes[0]);
  149. class DDDeviceImpl : public DDDevice {
  150. private:
  151. //////////////////////////////////////////////////////////////////////////////
  152. //
  153. // types
  154. //
  155. //////////////////////////////////////////////////////////////////////////////
  156. typedef TList<D3DDevice*> D3DDeviceList;
  157. typedef TList<Rasterizer*> RasterizerList;
  158. typedef TMap<DDSurface*, TRef<DeviceTexture> > DeviceTextureMap;
  159. //////////////////////////////////////////////////////////////////////////////
  160. //
  161. // members
  162. //
  163. //////////////////////////////////////////////////////////////////////////////
  164. TRef<DDDevice> m_pdddevicePrimary;
  165. TRef<IDirectDrawX> m_pdd;
  166. TRef<IDirect3DX> m_pd3d;
  167. DeviceTextureMap m_mapDeviceTextures;
  168. ZString m_strName;
  169. bool m_b3DAcceleration;
  170. bool m_bAllow3DAcceleration;
  171. PrivateEngine* m_pengine;
  172. D3DDeviceList m_listD3DDevices;
  173. RasterizerList m_listRasterizers;
  174. DDCaps m_ddcapsHW;
  175. DDCaps m_ddcapsSW;
  176. DWORD m_dwTotalVideoMemory;
  177. TRef<PixelFormat> m_ppfZBuffer;
  178. TVector<WinPoint> m_modes;
  179. //////////////////////////////////////////////////////////////////////////////
  180. //
  181. // Display mode enumeration
  182. //
  183. //////////////////////////////////////////////////////////////////////////////
  184. static HRESULT WINAPI StaticEnumModes(LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID pvoid)
  185. {
  186. DDDeviceImpl* pthis = (DDDeviceImpl*)pvoid;
  187. return pthis->EnumModes(*(DDSDescription*)lpDDSurfaceDesc);
  188. }
  189. HRESULT EnumModes(const DDSDescription& ddsd)
  190. {
  191. TRef<PixelFormat> ppf = m_pengine->GetPixelFormat(ddsd.GetPixelFormat());
  192. int xsize = ddsd.XSize();
  193. int ysize = ddsd.YSize();
  194. DWORD bits = ppf->PixelBits();
  195. DWORD dwNeededVideoMemory = 6 * xsize * ysize;
  196. if (
  197. bits == 16
  198. && xsize >= 640
  199. && ysize >= 480
  200. // !!! NT doesn't return the right value for TotalVideoMemory
  201. //&& dwNeededVideoMemory < m_dwTotalVideoMemory
  202. ) {
  203. for (int index = 0; index < g_countValidModes; index++) {
  204. if (
  205. xsize == g_validModes[index].X()
  206. && ysize == g_validModes[index].Y()
  207. ) {
  208. m_modes.PushEnd(ddsd.Size());
  209. break;
  210. }
  211. }
  212. }
  213. return D3DENUMRET_OK;
  214. }
  215. //////////////////////////////////////////////////////////////////////////////
  216. //
  217. // ZBuffer format enumeration
  218. //
  219. //////////////////////////////////////////////////////////////////////////////
  220. static HRESULT WINAPI StaticEnumZBufferFormats(
  221. DDPIXELFORMAT* pddpf,
  222. VOID* pvoid
  223. ) {
  224. DDDeviceImpl* pthis = (DDDeviceImpl*)pvoid;
  225. return pthis->EnumZBufferFormats(*(DDPixelFormat*)pddpf);
  226. }
  227. HRESULT EnumZBufferFormats(const DDPixelFormat& ddpf)
  228. {
  229. // , should we always choose the most bits or try to get 16bit?
  230. if(ddpf.dwZBufferBitDepth >= 16) {
  231. m_ppfZBuffer = m_pengine->GetPixelFormat(ddpf);
  232. return D3DENUMRET_CANCEL;
  233. }
  234. return D3DENUMRET_OK;
  235. }
  236. //////////////////////////////////////////////////////////////////////////////
  237. //
  238. // Initialize
  239. //
  240. //////////////////////////////////////////////////////////////////////////////
  241. void Initialize(IDirectDrawX* pdd)
  242. {
  243. if (pdd == NULL) {
  244. TRef<IDirectDraw> pddPrimary;
  245. HRESULT hr = DirectDrawCreate(NULL, &pddPrimary, NULL);
  246. if (SUCCEEDED(hr)) {
  247. DDCall(pddPrimary->QueryInterface(IID_IDirectDrawX, (void**)&m_pdd));
  248. }
  249. } else {
  250. m_pdd = pdd;
  251. }
  252. if (m_pdd) {
  253. //
  254. // Get Device Info
  255. //
  256. DDDeviceIdentifier dddi;
  257. m_pdd->GetDeviceIdentifier(&dddi, DDGDI_GETHOSTIDENTIFIER);
  258. m_strName = dddi.szDescription;
  259. //
  260. // Get device capabilities.
  261. //
  262. DDCall(m_pdd->GetCaps(&m_ddcapsHW, &m_ddcapsSW));
  263. //
  264. // Get the amount of video memory
  265. //
  266. DWORD dwFree;
  267. DDSCaps ddsc;
  268. ddsc.dwCaps = DDSCAPS_VIDEOMEMORY;
  269. HRESULT hr = m_pdd->GetAvailableVidMem(&ddsc, &m_dwTotalVideoMemory, &dwFree);
  270. if (DDERR_NODIRECTDRAWHW != hr)
  271. DDCall(hr);
  272. //
  273. // Does the driver support 3D with texture mapping and zbuffer?
  274. //
  275. DWORD ddsCaps = DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
  276. m_b3DAcceleration =
  277. ((m_ddcapsHW.dwCaps & DDCAPS_3D) != 0)
  278. && ((m_ddcapsHW.ddsCaps.dwCaps & ddsCaps ) == ddsCaps);
  279. //
  280. // Set the cooperative level to Normal
  281. //
  282. #ifndef DREAMCAST
  283. DDCall(m_pdd->SetCooperativeLevel(NULL, DDSCL_NORMAL));
  284. #endif
  285. //
  286. // Get the D3D pointer
  287. //
  288. DDCall(m_pdd->QueryInterface(IID_IDirect3DX, (void**)&m_pd3d));
  289. //
  290. // Enumerate the display modes
  291. //
  292. m_pdd->EnumDisplayModes(0, NULL, this, StaticEnumModes);
  293. //
  294. // Enumerate the zbuffer formats
  295. //
  296. #ifndef DREAMCAST
  297. m_pd3d->EnumZBufferFormats(GetIID(true), StaticEnumZBufferFormats, this);
  298. #endif
  299. }
  300. }
  301. public:
  302. //////////////////////////////////////////////////////////////////////////////
  303. //
  304. // Constructors
  305. //
  306. //////////////////////////////////////////////////////////////////////////////
  307. DDDeviceImpl(
  308. PrivateEngine* pengine,
  309. IDirectDrawX* pdd,
  310. bool bAllow3DAcceleration
  311. ) :
  312. m_pengine(pengine),
  313. m_bAllow3DAcceleration(bAllow3DAcceleration)
  314. {
  315. Initialize(pdd);
  316. }
  317. //////////////////////////////////////////////////////////////////////////////
  318. //
  319. // Termination
  320. //
  321. //////////////////////////////////////////////////////////////////////////////
  322. void FreeEverything()
  323. {
  324. m_mapDeviceTextures.SetEmpty();
  325. {
  326. D3DDeviceList::Iterator iter(m_listD3DDevices);
  327. while (!iter.End()) {
  328. iter.Value()->Terminate();
  329. iter.Next();
  330. }
  331. }
  332. {
  333. RasterizerList::Iterator iter(m_listRasterizers);
  334. while (!iter.End()) {
  335. iter.Value()->Terminate();
  336. iter.Next();
  337. }
  338. }
  339. }
  340. void Terminate()
  341. {
  342. FreeEverything();
  343. m_pd3d = NULL;
  344. m_pdd = NULL;
  345. }
  346. void Reset(IDirectDrawX* pdd)
  347. {
  348. Terminate();
  349. Initialize(pdd);
  350. }
  351. void RemoveD3DDevice(D3DDevice* pd3ddevice)
  352. {
  353. m_listD3DDevices.Remove(pd3ddevice);
  354. }
  355. void RemoveRasterizer(Rasterizer* praster)
  356. {
  357. m_listRasterizers.Remove(praster);
  358. }
  359. void AddRasterizer(Rasterizer* praster)
  360. {
  361. m_listRasterizers.PushFront(praster);
  362. }
  363. //////////////////////////////////////////////////////////////////////////////
  364. //
  365. // Validation
  366. //
  367. //////////////////////////////////////////////////////////////////////////////
  368. bool IsValid()
  369. {
  370. return m_pdd != NULL && m_pd3d != NULL;
  371. }
  372. //////////////////////////////////////////////////////////////////////////////
  373. //
  374. // Set Methods
  375. //
  376. //////////////////////////////////////////////////////////////////////////////
  377. void SetPrimaryDevice(DDDevice* pdddevice)
  378. {
  379. m_pdddevicePrimary = pdddevice;
  380. }
  381. //////////////////////////////////////////////////////////////////////////////
  382. //
  383. // Get Methods
  384. //
  385. //////////////////////////////////////////////////////////////////////////////
  386. HRESULT TestCooperativeLevel()
  387. {
  388. return m_pdd->TestCooperativeLevel();
  389. }
  390. const IID& GetIID(bool bAllowHAL)
  391. {
  392. if (m_b3DAcceleration && bAllowHAL) {
  393. return IID_IDirect3DHALDevice;
  394. } else {
  395. return IID_IDirect3DRGBDevice;
  396. }
  397. }
  398. IDirectDrawX* GetDD()
  399. {
  400. return m_pdd;
  401. }
  402. IDirect3DX* GetD3D()
  403. {
  404. return m_pd3d;
  405. }
  406. PrivateEngine* GetEngine()
  407. {
  408. return m_pengine;
  409. }
  410. PixelFormat* GetZBufferPixelFormat()
  411. {
  412. return m_ppfZBuffer;
  413. }
  414. bool Has3DAcceleration()
  415. {
  416. return m_b3DAcceleration;
  417. }
  418. void SetAllow3DAcceleration(bool bAllow3DAcceleration)
  419. {
  420. m_bAllow3DAcceleration = bAllow3DAcceleration;
  421. }
  422. bool GetAllow3DAcceleration()
  423. {
  424. return m_b3DAcceleration && m_bAllow3DAcceleration;
  425. }
  426. ZString GetName()
  427. {
  428. return m_strName;
  429. }
  430. WinPoint NextMode(const WinPoint& size)
  431. {
  432. int count = m_modes.GetCount();
  433. for(int index = 0; index < count; index++) {
  434. if (
  435. m_modes[index].X() > size.X()
  436. || m_modes[index].Y() > size.Y()
  437. ) {
  438. return m_modes[index];
  439. }
  440. }
  441. return m_modes[count - 1];
  442. }
  443. WinPoint PreviousMode(const WinPoint& size)
  444. {
  445. int count = m_modes.GetCount();
  446. for(int index = count - 1 ; index > 0; index--) {
  447. if (
  448. m_modes[index].X() < size.X()
  449. || m_modes[index].Y() < size.Y()
  450. ) {
  451. return m_modes[index];
  452. }
  453. }
  454. return m_modes[0];
  455. }
  456. void EliminateModes(const WinPoint& size)
  457. {
  458. int count = m_modes.GetCount();
  459. for(int index = 0; index < count; index++) {
  460. if (
  461. m_modes[index].X() >= size.X()
  462. && m_modes[index].Y() >= size.Y()
  463. ) {
  464. m_modes.SetCount(index);
  465. return;
  466. }
  467. }
  468. }
  469. //////////////////////////////////////////////////////////////////////////////
  470. //
  471. // Create a D3D Device
  472. //
  473. //////////////////////////////////////////////////////////////////////////////
  474. TRef<D3DDevice> CreateD3DDevice(DDSurface* pddsurface)
  475. {
  476. TRef<IDirect3DDeviceX> pd3dd;
  477. bool bAcceleration = m_bAllow3DAcceleration && pddsurface->InVideoMemory();
  478. pddsurface->GetDDSXZBuffer();
  479. HRESULT hr =
  480. m_pd3d->CreateDevice(
  481. GetIID(bAcceleration),
  482. pddsurface->GetDDSX(),
  483. &pd3dd
  484. #ifndef DREAMCAST
  485. ,NULL
  486. #endif
  487. );
  488. if (hr == DDERR_INVALIDPARAMS) {
  489. // this can happen if the surface is lost
  490. return NULL;
  491. }
  492. DDCall(hr);
  493. if (FAILED(hr)) {
  494. return NULL;
  495. }
  496. TRef<D3DDevice> pd3ddevice =
  497. ::CreateD3DDevice(
  498. this,
  499. pd3dd,
  500. m_b3DAcceleration && bAcceleration,
  501. m_pengine->GetPrimaryPixelFormat()
  502. );
  503. if (pd3ddevice != NULL) {
  504. m_listD3DDevices.PushFront(pd3ddevice);
  505. }
  506. return pd3ddevice;
  507. }
  508. //////////////////////////////////////////////////////////////////////////////
  509. //
  510. // Create a Direct Draw Surface
  511. //
  512. //////////////////////////////////////////////////////////////////////////////
  513. TRef<IDirectDrawSurfaceX> CreateSurface(
  514. const WinPoint& size,
  515. DWORD caps,
  516. PixelFormat* ppf,
  517. bool bAllocationCanFail
  518. ) {
  519. if (m_pdddevicePrimary != NULL && (caps & DDSCAPS_VIDEOMEMORY) == 0) {
  520. return m_pdddevicePrimary->CreateSurface(size, caps, ppf, bAllocationCanFail);
  521. } else {
  522. DDSDescription ddsd;
  523. ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS | DDSD_PIXELFORMAT;
  524. ddsd.dwWidth = size.X();
  525. ddsd.dwHeight = size.Y();
  526. ddsd.ddsCaps.dwCaps = caps;
  527. ddsd.ddpfPixelFormat = ppf->GetDDPF();
  528. TRef<IDirectDrawSurfaceX> pdds;
  529. HRESULT hr = m_pdd->CreateSurface(&ddsd, &pdds, NULL);
  530. if (
  531. hr == DDERR_OUTOFMEMORY
  532. || hr == DDERR_OUTOFVIDEOMEMORY
  533. ) {
  534. if (bAllocationCanFail) {
  535. return NULL;
  536. }
  537. }
  538. DDCall(hr);
  539. return pdds;
  540. }
  541. }
  542. //////////////////////////////////////////////////////////////////////////////
  543. //
  544. // Create a Mip Map texture Surface
  545. //
  546. //////////////////////////////////////////////////////////////////////////////
  547. TRef<IDirectDrawSurfaceX> CreateMipMapTexture(
  548. const WinPoint& size,
  549. PixelFormat* ppf
  550. ) {
  551. //
  552. // Figure out how many levels we need
  553. //
  554. int minSize = min(size.X(), size.Y());
  555. int maps = 0;
  556. while (minSize > 1) {
  557. maps++;
  558. minSize /= 2;
  559. }
  560. //
  561. // Create the surface
  562. //
  563. DDSDescription ddsd;
  564. ddsd.dwFlags =
  565. DDSD_HEIGHT
  566. | DDSD_WIDTH
  567. | DDSD_CAPS
  568. | DDSD_PIXELFORMAT
  569. | DDSD_MIPMAPCOUNT;
  570. ddsd.dwWidth = size.X();
  571. ddsd.dwHeight = size.Y();
  572. ddsd.dwMipMapCount = 2;//maps;
  573. ddsd.ddsCaps.dwCaps =
  574. DDSCAPS_VIDEOMEMORY
  575. | DDSCAPS_TEXTURE
  576. | DDSCAPS_MIPMAP
  577. | DDSCAPS_COMPLEX
  578. | DDSCAPS_ALLOCONLOAD;
  579. ddsd.ddpfPixelFormat = ppf->GetDDPF();
  580. TRef<IDirectDrawSurfaceX> pdds;
  581. HRESULT hr = m_pdd->CreateSurface(&ddsd, &pdds, NULL);
  582. //
  583. // Check for errors
  584. //
  585. if (
  586. hr == DDERR_OUTOFMEMORY
  587. || hr == DDERR_OUTOFVIDEOMEMORY
  588. ) {
  589. return NULL;
  590. }
  591. DDCall(hr);
  592. return pdds;
  593. }
  594. //////////////////////////////////////////////////////////////////////////////
  595. //
  596. // Texture Cache
  597. //
  598. //////////////////////////////////////////////////////////////////////////////
  599. void RevokeTextures()
  600. {
  601. m_mapDeviceTextures.SetEmpty();
  602. }
  603. void BeginScene()
  604. {
  605. }
  606. void EndScene()
  607. {
  608. }
  609. TRef<DeviceTexture> CreateDeviceTexture(D3DDevice* pd3dd, DDSurface* pddsurface, const WinPoint& size)
  610. {
  611. TRef<DeviceTexture> pdeviceTexture = new DeviceTexture(this, pd3dd, pddsurface, size);
  612. if (pdeviceTexture->IsValid()) {
  613. return pdeviceTexture;
  614. }
  615. return NULL;
  616. }
  617. IDirect3DTextureX* GetTextureX(D3DDevice* pd3dd, DDSurface* pddsurface)
  618. {
  619. WinPoint size = pddsurface->GetSize();
  620. WinPoint pointMin = pd3dd->GetMinTextureSize();
  621. WinPoint pointMax = pd3dd->GetMaxTextureSize();
  622. if (pointMin.X() != 0 || pointMin.Y() != 0) {
  623. while (
  624. size.X() < pointMin.X()
  625. || size.Y() < pointMin.Y()
  626. ) {
  627. size.SetX(size.X() * 2);
  628. size.SetY(size.Y() * 2);
  629. }
  630. }
  631. if (pointMax.X() != 0 || pointMax.Y() != 0) {
  632. while (
  633. size.X() > pointMax.X()
  634. || size.Y() > pointMax.Y()
  635. ) {
  636. size.SetX(size.X() / 2);
  637. size.SetY(size.Y() / 2);
  638. }
  639. }
  640. if (pd3dd->IsHardwareAccelerated()) {
  641. TRef<DeviceTexture> ptexture;
  642. if (!m_mapDeviceTextures.Find(pddsurface, ptexture)) {
  643. while (true) {
  644. ptexture = CreateDeviceTexture(pd3dd, pddsurface, size);
  645. if (ptexture) {
  646. m_mapDeviceTextures.Set(pddsurface, ptexture);
  647. break;
  648. }
  649. RevokeTextures();
  650. }
  651. }
  652. if (ptexture) {
  653. TRef<IDirect3DTextureX> pd3dtexture = ptexture->GetTextureX(size);
  654. if (pd3dtexture) {
  655. return pd3dtexture;
  656. }
  657. m_mapDeviceTextures.Remove(pddsurface);
  658. }
  659. return NULL;
  660. } else {
  661. int id;
  662. return pddsurface->GetTextureX(pd3dd->GetTextureFormat(), size, id);
  663. }
  664. }
  665. void RemoveSurface(DDSurface* pddsurface)
  666. {
  667. m_mapDeviceTextures.Remove(pddsurface);
  668. }
  669. //////////////////////////////////////////////////////////////////////////////
  670. //
  671. // Performance counters
  672. //
  673. //////////////////////////////////////////////////////////////////////////////
  674. int GetTotalTextureMemory()
  675. {
  676. if (m_b3DAcceleration) {
  677. DWORD dwTotal;
  678. DWORD dwFree;
  679. DDSCaps ddsc;
  680. memset(&ddsc, 0, sizeof(DDSCaps));
  681. ddsc.dwCaps = DDSCAPS_TEXTURE;
  682. DDCall(m_pdd->GetAvailableVidMem(&ddsc, &dwTotal, &dwFree));
  683. return dwTotal;
  684. } else {
  685. return 0;
  686. }
  687. }
  688. int GetAvailableTextureMemory()
  689. {
  690. if (m_b3DAcceleration) {
  691. DWORD dwTotal;
  692. DWORD dwFree;
  693. DDSCaps ddsc;
  694. memset(&ddsc, 0, sizeof(DDSCaps));
  695. ddsc.dwCaps = DDSCAPS_TEXTURE;
  696. DDCall(m_pdd->GetAvailableVidMem(&ddsc, &dwTotal, &dwFree));
  697. return dwFree;
  698. } else {
  699. return 0;
  700. }
  701. }
  702. int GetTotalVideoMemory()
  703. {
  704. if (m_b3DAcceleration) {
  705. DWORD dwTotal;
  706. DWORD dwFree;
  707. DDSCaps ddsc;
  708. memset(&ddsc, 0, sizeof(DDSCaps));
  709. ddsc.dwCaps = DDSCAPS_VIDEOMEMORY;
  710. DDCall(m_pdd->GetAvailableVidMem(&ddsc, &dwTotal, &dwFree));
  711. return dwTotal;
  712. } else {
  713. return 0;
  714. }
  715. }
  716. int GetAvailableVideoMemory()
  717. {
  718. if (m_b3DAcceleration) {
  719. DWORD dwTotal;
  720. DWORD dwFree;
  721. DDSCaps ddsc;
  722. memset(&ddsc, 0, sizeof(DDSCaps));
  723. ddsc.dwCaps = DDSCAPS_VIDEOMEMORY;
  724. DDCall(m_pdd->GetAvailableVidMem(&ddsc, &dwTotal, &dwFree));
  725. return dwFree;
  726. } else {
  727. return 0;
  728. }
  729. }
  730. };
  731. //////////////////////////////////////////////////////////////////////////////
  732. //
  733. // Performance counters
  734. //
  735. //////////////////////////////////////////////////////////////////////////////
  736. TRef<DDDevice> CreateDDDevice(PrivateEngine* pengine, bool bAllow3DAcceleration, IDirectDrawX* pdd)
  737. {
  738. return new DDDeviceImpl(pengine, pdd, bAllow3DAcceleration);
  739. }