ddsurface.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Surface Modes
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. enum SurfaceMode {
  8. SurfaceModeDD,
  9. SurfaceModeLocked
  10. };
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // VideoSurface
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. class DDSurfaceImpl : public DDSurface {
  17. public:
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // Types
  21. //
  22. //////////////////////////////////////////////////////////////////////////////
  23. class SurfaceData {
  24. public:
  25. int m_id;
  26. TRef<PixelFormat> m_ppf;
  27. TRef<IDirectDrawSurfaceX> m_pdds;
  28. TRef<IDirect3DTextureX> m_pd3dtexture;
  29. };
  30. //////////////////////////////////////////////////////////////////////////////
  31. //
  32. // Members
  33. //
  34. //////////////////////////////////////////////////////////////////////////////
  35. TRef<PrivateEngine> m_pengine;
  36. TRef<DDDevice> m_pdddevice;
  37. TRef<IDirectDrawSurfaceX> m_pddsZBuffer;
  38. WinPoint m_size;
  39. WinPoint m_sizeSurface;
  40. SurfaceType m_stype;
  41. DDSDescription m_ddsdLocked;
  42. BYTE* m_pbits;
  43. int m_pitch;
  44. Color m_colorKey;
  45. TRef<PrivatePalette> m_ppalette;
  46. Color m_colorText;
  47. bool m_bTextureSize;
  48. bool m_bColorKey;
  49. bool m_bSharedMemory;
  50. //
  51. // Mip-Mapped levels
  52. //
  53. SurfaceData m_data;
  54. TVector<SurfaceData> m_datas;
  55. //
  56. // Converted detail levels
  57. //
  58. SurfaceData m_dataConverted;
  59. TVector<SurfaceData> m_datasConverted;
  60. //
  61. // Surface invalidation and modes
  62. //
  63. SurfaceMode m_mode;
  64. //////////////////////////////////////////////////////////////////////////////
  65. //
  66. //
  67. //
  68. //////////////////////////////////////////////////////////////////////////////
  69. void CalculateSurfaceSize()
  70. {
  71. m_sizeSurface = m_size;
  72. if (m_size.X() < 1) {
  73. ZAssert(m_size.X() == 0);
  74. m_sizeSurface.SetX(1);
  75. }
  76. if (m_size.Y() < 1) {
  77. ZAssert(m_size.Y() == 0);
  78. m_sizeSurface.SetY(1);
  79. }
  80. }
  81. //////////////////////////////////////////////////////////////////////////////
  82. //
  83. //
  84. //
  85. //////////////////////////////////////////////////////////////////////////////
  86. void Initialize()
  87. {
  88. CalculateSurfaceSize();
  89. m_bTextureSize =
  90. m_sizeSurface.Y() == (int)NextPowerOf2((DWORD)m_sizeSurface.Y())
  91. && m_sizeSurface.X() == (int)NextPowerOf2((DWORD)m_sizeSurface.X());
  92. m_bColorKey = false;
  93. m_colorKey = Color(0, 0, 0);
  94. m_data.m_id = 0;
  95. m_mode = SurfaceModeDD;
  96. m_pbits = NULL;
  97. }
  98. //////////////////////////////////////////////////////////////////////////////
  99. //
  100. //
  101. //
  102. //////////////////////////////////////////////////////////////////////////////
  103. void FinishConstruction()
  104. {
  105. //
  106. // Set the palette if there is one
  107. //
  108. if (m_ppalette) {
  109. m_data.m_pdds->SetPalette(m_ppalette->GetDDPal());
  110. }
  111. //
  112. // Get a texture handle if needed
  113. //
  114. if (m_bTextureSize && !m_stype.Test(SurfaceTypeVideo())) {
  115. DDCall(m_data.m_pdds->QueryInterface(IID_IDirect3DTextureX, (void**)&(m_data.m_pd3dtexture)));
  116. }
  117. }
  118. //////////////////////////////////////////////////////////////////////////////
  119. //
  120. // Create a video memory surface
  121. //
  122. //////////////////////////////////////////////////////////////////////////////
  123. DDSurfaceImpl(
  124. DDDevice* pdddevice,
  125. SurfaceType stype,
  126. PixelFormat* ppf,
  127. PrivatePalette* ppalette,
  128. const WinPoint& size
  129. ) :
  130. m_pdddevice(pdddevice),
  131. m_pengine(pdddevice->GetEngine()),
  132. m_stype(stype),
  133. m_ppalette(ppalette),
  134. m_size(size),
  135. m_bSharedMemory(false)
  136. {
  137. m_data.m_ppf = ppf;
  138. Initialize();
  139. //
  140. // Figure out the DD caps
  141. //
  142. DWORD caps = DDSCAPS_VIDEOMEMORY;
  143. if (Is3D()) {
  144. caps |= DDSCAPS_3DDEVICE;
  145. } else {
  146. if (m_bTextureSize) {
  147. caps |= DDSCAPS_TEXTURE;
  148. } else {
  149. caps |= DDSCAPS_OFFSCREENPLAIN;
  150. }
  151. }
  152. //
  153. // Create the surface
  154. //
  155. m_data.m_pdds = m_pdddevice->CreateSurface(size, caps, ppf, true);
  156. //
  157. // Was there enough memory to allocate the surface?
  158. //
  159. if (m_data.m_pdds != NULL) {
  160. //
  161. // Get the pitch
  162. //
  163. DDSDescription ddsd;
  164. DDCall(m_data.m_pdds->GetSurfaceDesc(&ddsd));
  165. m_pitch = ddsd.lPitch;
  166. //
  167. // Do any other common construction tasks
  168. //
  169. FinishConstruction();
  170. }
  171. }
  172. //////////////////////////////////////////////////////////////////////////////
  173. //
  174. // Wrap an previously created DirectDraw surface
  175. //
  176. //////////////////////////////////////////////////////////////////////////////
  177. DDSurfaceImpl(
  178. DDDevice* pdddevice,
  179. IDirectDrawSurfaceX* pdds,
  180. IDirectDrawSurfaceX* pddsZBuffer,
  181. PixelFormat* ppf,
  182. PrivatePalette* ppalette,
  183. SurfaceType stype
  184. ) :
  185. m_pdddevice(pdddevice),
  186. m_pengine(pdddevice->GetEngine()),
  187. m_pddsZBuffer(pddsZBuffer),
  188. m_ppalette(ppalette),
  189. m_stype(stype | SurfaceType2D()),
  190. m_bSharedMemory(false)
  191. {
  192. DDSDescription ddsd;
  193. DDCall(pdds->GetSurfaceDesc(&ddsd));
  194. m_data.m_pdds = pdds;
  195. m_data.m_ppf = ppf;
  196. m_size = WinPoint(ddsd.XSize(), ddsd.YSize());
  197. m_pitch = ddsd.Pitch();
  198. Initialize();
  199. }
  200. //////////////////////////////////////////////////////////////////////////////
  201. //
  202. // Create a surface from a binary representation
  203. //
  204. //////////////////////////////////////////////////////////////////////////////
  205. DDSurfaceImpl(
  206. DDDevice* pdddevice,
  207. SurfaceType stype,
  208. PixelFormat* ppf,
  209. PrivatePalette* ppalette,
  210. const WinPoint& size,
  211. int pitch,
  212. BYTE* pbits
  213. ) :
  214. m_pdddevice(pdddevice),
  215. m_pengine(pdddevice->GetEngine()),
  216. m_stype(stype),
  217. m_ppalette(ppalette),
  218. m_size(size)
  219. {
  220. //
  221. // Is the memory writable?
  222. //
  223. MEMORY_BASIC_INFORMATION meminfo;
  224. ZVerify(VirtualQuery(pbits, &meminfo, sizeof(meminfo)) == sizeof(meminfo));
  225. m_bSharedMemory =
  226. (
  227. (
  228. meminfo.Protect
  229. & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY)
  230. )
  231. != 0
  232. );
  233. //
  234. // initialize
  235. //
  236. m_pitch = pitch;
  237. m_data.m_ppf = ppf;
  238. Initialize();
  239. //
  240. // !!! Dreamcast doesn't support client allocated memory
  241. // what to do about that?
  242. //
  243. //
  244. // Figure out the DD caps
  245. //
  246. DWORD caps = DDSCAPS_SYSTEMMEMORY;
  247. if (Is3D()) {
  248. caps |= DDSCAPS_3DDEVICE;
  249. }
  250. if (m_bTextureSize) {
  251. caps |= DDSCAPS_TEXTURE;
  252. } else {
  253. caps |= DDSCAPS_OFFSCREENPLAIN;
  254. }
  255. //
  256. // Create the surface
  257. //
  258. DDSDescription ddsd;
  259. ddsd.dwFlags =
  260. DDSD_HEIGHT
  261. | DDSD_WIDTH
  262. | DDSD_CAPS
  263. | DDSD_PIXELFORMAT
  264. | DDSD_PITCH;
  265. ddsd.dwWidth = m_size.X();
  266. ddsd.dwHeight = m_size.Y();
  267. ddsd.lPitch = pitch;
  268. ddsd.ddsCaps.dwCaps = caps;
  269. ddsd.ddpfPixelFormat = m_data.m_ppf->GetDDPF();
  270. if (m_bSharedMemory) {
  271. //
  272. // use the passed in memory
  273. //
  274. ddsd.dwFlags = ddsd.dwFlags | DDSD_LPSURFACE;
  275. ddsd.lpSurface = pbits;
  276. HRESULT hr = m_pdddevice->GetDD()->CreateSurface(&ddsd, &m_data.m_pdds, NULL);
  277. DDCall(hr);
  278. #ifdef _DEBUG
  279. DDSDescription ddsd;
  280. DDCall(m_data.m_pdds->GetSurfaceDesc(&ddsd));
  281. ZAssert(pitch == ddsd.lPitch);
  282. #endif
  283. m_pitch = pitch;
  284. } else {
  285. //
  286. // Let directx allocate the memory
  287. //
  288. HRESULT hr = m_pdddevice->GetDD()->CreateSurface(&ddsd, &m_data.m_pdds, NULL);
  289. DDCall(hr);
  290. //
  291. // Copy the bits over
  292. //
  293. DDCall(m_data.m_pdds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL));
  294. m_pitch = ddsd.Pitch();
  295. ZAssert(pitch <= m_pitch);
  296. for (int y = 0; y < m_size.Y(); y++) {
  297. memcpy(
  298. ddsd.Pointer() + y * m_pitch,
  299. pbits + y * pitch,
  300. pitch
  301. );
  302. }
  303. DDCall(m_data.m_pdds->Unlock(NULL));
  304. }
  305. //
  306. // Do any other common construction tasks
  307. //
  308. FinishConstruction();
  309. }
  310. bool IsMemoryShared()
  311. {
  312. return m_bSharedMemory;
  313. }
  314. //////////////////////////////////////////////////////////////////////////////
  315. //
  316. //
  317. //
  318. //////////////////////////////////////////////////////////////////////////////
  319. bool IsValid()
  320. {
  321. return m_data.m_pdds != NULL;
  322. }
  323. //////////////////////////////////////////////////////////////////////////////
  324. //
  325. // Destructor
  326. //
  327. //////////////////////////////////////////////////////////////////////////////
  328. ~DDSurfaceImpl()
  329. {
  330. }
  331. //////////////////////////////////////////////////////////////////////////////
  332. //
  333. // Attach a ZBuffer surface
  334. //
  335. //////////////////////////////////////////////////////////////////////////////
  336. IDirectDrawSurfaceX* GetDDSXZBuffer()
  337. {
  338. if (HasZBuffer()) {
  339. if (m_pddsZBuffer == NULL) {
  340. DWORD caps = DDSCAPS_ZBUFFER;
  341. if (m_stype.Test(SurfaceTypeVideo())) {
  342. caps |= DDSCAPS_VIDEOMEMORY;
  343. } else {
  344. caps |= DDSCAPS_SYSTEMMEMORY;
  345. }
  346. m_pddsZBuffer =
  347. m_pdddevice->CreateSurface(
  348. m_size,
  349. caps,
  350. m_pdddevice->GetZBufferPixelFormat(),
  351. true
  352. );
  353. if (m_pddsZBuffer) {
  354. DDCall(m_data.m_pdds->AddAttachedSurface(m_pddsZBuffer));
  355. }
  356. }
  357. }
  358. return m_pddsZBuffer;
  359. }
  360. //////////////////////////////////////////////////////////////////////////////
  361. //
  362. // Surface updates
  363. //
  364. //////////////////////////////////////////////////////////////////////////////
  365. void SurfaceChanged()
  366. {
  367. m_data.m_id++;
  368. if (m_data.m_id < 0) m_data.m_id = 0;
  369. }
  370. //////////////////////////////////////////////////////////////////////////////
  371. //
  372. // Down Sample
  373. //
  374. //////////////////////////////////////////////////////////////////////////////
  375. static DWORD Unpack(WORD pixelWord)
  376. {
  377. DWORD pixel = pixelWord;
  378. return
  379. ((pixel & 0xf800) << 5)
  380. | ((pixel & 0x07e0) << 3)
  381. | ((pixel & 0x001f) );
  382. }
  383. static WORD Pack(DWORD pixel)
  384. {
  385. return
  386. (WORD)(
  387. ((pixel >> 5) & 0xf800)
  388. | ((pixel >> 3) & 0x07e0)
  389. | ((pixel ) & 0x001f)
  390. );
  391. }
  392. static WORD Average(WORD pixel0, WORD pixel1, WORD pixel2, WORD pixel3)
  393. {
  394. return
  395. Pack(
  396. (
  397. Unpack(pixel0)
  398. + Unpack(pixel1)
  399. + Unpack(pixel2)
  400. + Unpack(pixel3)
  401. ) >> 2
  402. );
  403. }
  404. static void DownSample(
  405. const WinPoint& sizeTarget,
  406. IDirectDrawSurfaceX* pddsTarget,
  407. IDirectDrawSurfaceX* pddsSource
  408. ) {
  409. DDSDescription ddsdSource;
  410. DDSDescription ddsdTarget;
  411. DDCall(pddsSource->Lock(NULL, &ddsdSource, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL));
  412. DDCall(pddsTarget->Lock(NULL, &ddsdTarget, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL));
  413. int pitchSource = ddsdSource.Pitch();
  414. int pitchTarget = ddsdTarget.Pitch();
  415. ZAssert(
  416. ddsdSource.GetPixelFormat().dwRGBBitCount
  417. == ddsdTarget.GetPixelFormat().dwRGBBitCount
  418. );
  419. switch (ddsdSource.GetPixelFormat().dwRGBBitCount) {
  420. case 16:
  421. {
  422. ZAssert(ddsdSource.GetPixelFormat().dwRBitMask == 0xf800);
  423. ZAssert(ddsdSource.GetPixelFormat().dwGBitMask == 0x07e0);
  424. ZAssert(ddsdSource.GetPixelFormat().dwBBitMask == 0x001f);
  425. ZAssert(ddsdSource.GetPixelFormat().dwRGBAlphaBitMask == 0x0000);
  426. WORD* psource = (WORD*)ddsdSource.Pointer();
  427. WORD* ptarget = (WORD*)ddsdTarget.Pointer();
  428. for (int y = sizeTarget.Y() - 1; y >= 0; y--) {
  429. for (int x = sizeTarget.X() - 1; x >= 0; x--) {
  430. ptarget[x] =
  431. Average(
  432. psource[x * 2],
  433. psource[x * 2 + 1],
  434. psource[x * 2 + pitchSource / 2],
  435. psource[x * 2 + 1 + pitchSource / 2]
  436. );
  437. }
  438. psource += 2 * pitchSource / 2;
  439. ptarget += pitchTarget / 2;
  440. }
  441. }
  442. break;
  443. case 24:
  444. {
  445. BYTE* psource = (BYTE*)ddsdSource.Pointer();
  446. BYTE* ptarget = (BYTE*)ddsdTarget.Pointer();
  447. for (int y = sizeTarget.Y() - 1; y >= 0; y--) {
  448. for (int x = sizeTarget.X() - 1; x >= 0; x--) {
  449. BYTE* psource0 = psource + x * 6;
  450. BYTE* psource1 = psource + x * 6 + 3;
  451. BYTE* psource2 = psource + x * 6 + pitchSource;
  452. BYTE* psource3 = psource + x * 6 + 3 + pitchSource;
  453. ptarget[x * 3 + 0] = (psource0[0] + psource1[0] + psource2[0] + psource3[0]) / 4;
  454. ptarget[x * 3 + 1] = (psource0[1] + psource1[1] + psource2[1] + psource3[1]) / 4;
  455. ptarget[x * 3 + 2] = (psource0[2] + psource1[2] + psource2[2] + psource3[2]) / 4;
  456. }
  457. psource += pitchSource * 2;
  458. ptarget += pitchTarget;
  459. }
  460. }
  461. break;
  462. default:
  463. ZError("DownSample: Invalid PixelFormat");
  464. };
  465. DDCall(pddsTarget->Unlock(NULL));
  466. DDCall(pddsSource->Unlock(NULL));
  467. }
  468. //////////////////////////////////////////////////////////////////////////////
  469. //
  470. // Construct a new lod or converted surface
  471. //
  472. //////////////////////////////////////////////////////////////////////////////
  473. void ConstructSurfaceData(SurfaceData& data, PixelFormat* ppf, const WinPoint& size)
  474. {
  475. data.m_id = -1;
  476. data.m_ppf = ppf;
  477. DWORD caps = DDSCAPS_SYSTEMMEMORY;
  478. if (m_bTextureSize/* && ppf->IsSoftwareTexture()*/) {
  479. caps |= DDSCAPS_TEXTURE;
  480. } else {
  481. caps |= DDSCAPS_OFFSCREENPLAIN;
  482. }
  483. data.m_pdds =
  484. m_pdddevice->CreateSurface(
  485. size,
  486. caps,
  487. ppf,
  488. false
  489. );
  490. if (HasColorKey()) {
  491. DDCOLORKEY key;
  492. key.dwColorSpaceLowValue =
  493. key.dwColorSpaceHighValue =
  494. ppf->MakePixel(GetColorKey()).Value();
  495. DDCall(data.m_pdds->SetColorKey(DDCKEY_SRCBLT, &key));
  496. }
  497. if (caps & DDSCAPS_TEXTURE) {
  498. DDCall(data.m_pdds->QueryInterface(IID_IDirect3DTextureX, (void**)&(data.m_pd3dtexture)));
  499. } else {
  500. data.m_pd3dtexture = NULL;
  501. }
  502. }
  503. //////////////////////////////////////////////////////////////////////////////
  504. //
  505. // Convert pixel formats using GDI
  506. //
  507. //////////////////////////////////////////////////////////////////////////////
  508. static void Convert(const WinPoint& size, IDirectDrawSurfaceX* pddsTarget, IDirectDrawSurfaceX* pddsSource)
  509. {
  510. HDC hdcSource;
  511. DDCall(pddsSource->GetDC(&hdcSource));
  512. HDC hdcTarget;
  513. DDCall(pddsTarget->GetDC(&hdcTarget));
  514. ZVerify(::BitBlt(hdcTarget, 0, 0, size.X(), size.Y(), hdcSource, 0, 0, SRCCOPY));
  515. DDCall(pddsTarget->ReleaseDC(hdcTarget));
  516. DDCall(pddsSource->ReleaseDC(hdcSource));
  517. }
  518. //////////////////////////////////////////////////////////////////////////////
  519. //
  520. // Make sure the bits for a converted surface are available and up to date.
  521. //
  522. //////////////////////////////////////////////////////////////////////////////
  523. void UpdateConvertedSurface(PixelFormat* ppf, const WinPoint& size, SurfaceData& data, const SurfaceData& dataSource)
  524. {
  525. if (ppf != data.m_ppf) {
  526. ConstructSurfaceData(data, ppf, size);
  527. }
  528. if (data.m_id != dataSource.m_id) {
  529. SetSurfaceMode(SurfaceModeDD);
  530. Convert(size, data.m_pdds, dataSource.m_pdds);
  531. data.m_id = dataSource.m_id;
  532. }
  533. }
  534. //////////////////////////////////////////////////////////////////////////////
  535. //
  536. // Get a surface with a certain pixel format.
  537. //
  538. //////////////////////////////////////////////////////////////////////////////
  539. IDirectDrawSurfaceX* GetDDSX()
  540. {
  541. SetSurfaceMode(SurfaceModeDD);
  542. return m_data.m_pdds;
  543. }
  544. IDirectDrawSurfaceX* GetDDSX(PixelFormat* ppf)
  545. {
  546. if (ppf == m_data.m_ppf) {
  547. SetSurfaceMode(SurfaceModeDD);
  548. return m_data.m_pdds;
  549. } else {
  550. UpdateConvertedSurface(ppf, m_size, m_dataConverted, m_data);
  551. return m_dataConverted.m_pdds;
  552. }
  553. }
  554. //////////////////////////////////////////////////////////////////////////////
  555. //
  556. // Get a texture with a certain pixel format.
  557. //
  558. //////////////////////////////////////////////////////////////////////////////
  559. IDirect3DTextureX* GetTextureX(PixelFormat* ppf, const WinPoint& size, int& id)
  560. {
  561. id = m_data.m_id;
  562. //
  563. // Return the fullsize surface if that's what's wanted.
  564. //
  565. if (size == m_size) {
  566. if (ppf == m_data.m_ppf) {
  567. SetSurfaceMode(SurfaceModeDD);
  568. #ifdef DREAMCAST
  569. if (!m_data.m_pd3dtexture) {
  570. DDCall(m_data.m_pdds->QueryInterface(IID_IDirect3DTextureX, (void**)&(m_data.m_pd3dtexture)));
  571. }
  572. #endif
  573. return m_data.m_pd3dtexture;
  574. }
  575. UpdateConvertedSurface(ppf, m_size, m_dataConverted, m_data);
  576. return m_dataConverted.m_pd3dtexture;
  577. }
  578. //
  579. // Need to return a lower level of detail
  580. //
  581. int index = 0;
  582. WinPoint sizeSource = m_size;
  583. while (true) {
  584. sizeSource.SetX(sizeSource.X() / 2);
  585. sizeSource.SetY(sizeSource.Y() / 2);
  586. //
  587. // Do we need to allocate a new lower level of detail?
  588. //
  589. if (index == m_datas.GetCount()) {
  590. m_datas.PushEnd();
  591. m_datasConverted.PushEnd();
  592. ConstructSurfaceData(m_datas.Get(index), m_data.m_ppf, sizeSource);
  593. }
  594. //
  595. // Do we need to update this level?
  596. //
  597. if (m_datas[index].m_id != m_data.m_id) {
  598. DownSample(
  599. sizeSource,
  600. m_datas[index].m_pdds,
  601. index == 0 ?
  602. m_data.m_pdds
  603. : m_datas[index - 1].m_pdds
  604. );
  605. m_datas.Get(index).m_id = m_data.m_id;
  606. }
  607. //
  608. // Did we find the right size?
  609. //
  610. if (sizeSource == size) {
  611. //
  612. // Does the format need to be converted?
  613. //
  614. if (ppf == m_data.m_ppf) {
  615. return m_datas[index].m_pd3dtexture;
  616. } else {
  617. UpdateConvertedSurface(ppf, size, m_datasConverted.Get(index), m_datas[index]);
  618. return m_datasConverted[index].m_pd3dtexture;
  619. }
  620. }
  621. index++;
  622. }
  623. }
  624. TRef<IDirectDrawSurface> GetDDS()
  625. {
  626. SetSurfaceMode(SurfaceModeDD);
  627. TRef<IDirectDrawSurface> pdds;
  628. DDCall(m_data.m_pdds->QueryInterface(IID_IDirectDrawSurface, (void**)&pdds));
  629. return pdds;
  630. }
  631. //////////////////////////////////////////////////////////////////////////////
  632. //
  633. // Surface Type
  634. //
  635. //////////////////////////////////////////////////////////////////////////////
  636. bool Is3D()
  637. {
  638. return m_stype.Test(SurfaceType3D());
  639. }
  640. bool HasZBuffer()
  641. {
  642. return m_stype.Test(SurfaceTypeZBuffer());
  643. }
  644. bool InVideoMemory()
  645. {
  646. return m_stype.Test(SurfaceTypeVideo()) != 0;
  647. }
  648. //////////////////////////////////////////////////////////////////////////////
  649. //
  650. // Attributes
  651. //
  652. //////////////////////////////////////////////////////////////////////////////
  653. PixelFormat* GetPixelFormat()
  654. {
  655. return m_data.m_ppf;
  656. }
  657. PrivatePalette* GetPalette()
  658. {
  659. return m_ppalette;
  660. }
  661. DDDevice* GetDDDevice()
  662. {
  663. return m_pdddevice;
  664. }
  665. Engine* GetEngine()
  666. {
  667. return m_pengine;
  668. }
  669. PrivateEngine* GetEngineImpl()
  670. {
  671. return m_pengine;
  672. }
  673. const WinPoint& GetSize()
  674. {
  675. return m_size;
  676. }
  677. SurfaceType GetSurfaceType()
  678. {
  679. return m_stype;
  680. }
  681. bool HasColorKey()
  682. {
  683. return m_bColorKey;
  684. }
  685. const Color& GetColorKey()
  686. {
  687. ZAssert(m_bColorKey);
  688. return m_colorKey;
  689. }
  690. void SetColorKey(const Color& color)
  691. {
  692. ZAssert(m_datas.GetCount() == 0);
  693. ZAssert(m_datasConverted.GetCount() == 0);
  694. m_bColorKey = true;
  695. m_colorKey = color;
  696. //
  697. // Update the ddraw surface
  698. //
  699. SetSurfaceMode(SurfaceModeDD);
  700. DDCOLORKEY key;
  701. key.dwColorSpaceLowValue =
  702. key.dwColorSpaceHighValue = m_data.m_ppf->MakePixel(m_colorKey).Value();
  703. DDCall(m_data.m_pdds->SetColorKey(DDCKEY_SRCBLT, &key));
  704. //
  705. // Update the converted ddraw surface
  706. //
  707. if (m_dataConverted.m_pdds) {
  708. DDCall(m_dataConverted.m_pdds->SetColorKey(DDCKEY_SRCBLT, &key));
  709. }
  710. SurfaceChanged();
  711. }
  712. int GetPitch()
  713. {
  714. return m_pitch;
  715. }
  716. BYTE* GetPointer()
  717. {
  718. if (m_pbits != NULL) {
  719. return m_pbits;
  720. } else {
  721. SetSurfaceMode(SurfaceModeLocked);
  722. BYTE* pbits = m_ddsdLocked.Pointer();
  723. if (pbits == NULL) {
  724. //
  725. // DDraw returned null. Allocate some memory so the caller won't crash.
  726. //
  727. m_pbits = new BYTE[m_pitch * m_size.Y()];
  728. return m_pbits;
  729. }
  730. return pbits;
  731. }
  732. }
  733. void ReleasePointer()
  734. {
  735. SetSurfaceMode(SurfaceModeDD);
  736. }
  737. //////////////////////////////////////////////////////////////////////////////
  738. //
  739. // Surface modes
  740. //
  741. //////////////////////////////////////////////////////////////////////////////
  742. void BeginScene()
  743. {
  744. SetSurfaceMode(SurfaceModeDD);
  745. }
  746. void EndScene()
  747. {
  748. }
  749. void SetSurfaceMode(SurfaceMode mode)
  750. {
  751. if (m_mode != mode) {
  752. //
  753. // switch back to DDMode
  754. //
  755. switch (m_mode) {
  756. case SurfaceModeLocked:
  757. if (m_pbits == NULL) {
  758. DDSCall(m_data.m_pdds->Unlock(NULL));
  759. }
  760. SurfaceChanged();
  761. break;
  762. }
  763. //
  764. // switch to the new mode
  765. //
  766. m_mode = mode;
  767. switch (mode) {
  768. case SurfaceModeLocked:
  769. DDSCall(m_data.m_pdds->Lock(NULL, &m_ddsdLocked, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL));
  770. break;
  771. }
  772. }
  773. }
  774. //////////////////////////////////////////////////////////////////////////////
  775. //
  776. // Blts to and from a dc
  777. //
  778. //////////////////////////////////////////////////////////////////////////////
  779. void BitBltFromDC(HDC hdc)
  780. {
  781. SetSurfaceMode(SurfaceModeDD);
  782. HDC hdcSurface;
  783. if (DDSCall(m_data.m_pdds->GetDC(&hdcSurface))) {
  784. ZVerify(::BitBlt(
  785. hdcSurface,
  786. 0,
  787. 0,
  788. m_size.X(),
  789. m_size.Y(),
  790. hdc,
  791. 0,
  792. 0,
  793. SRCCOPY
  794. ));
  795. DDSCall(m_data.m_pdds->ReleaseDC(hdcSurface));
  796. }
  797. SurfaceChanged();
  798. SetSurfaceMode(SurfaceModeDD);
  799. }
  800. //////////////////////////////////////////////////////////////////////////////
  801. //
  802. // StretchBlt
  803. //
  804. //////////////////////////////////////////////////////////////////////////////
  805. void UnclippedBlt(
  806. const WinRect& rectTarget,
  807. VideoSurface* psurfaceSource,
  808. const WinRect& rectSource,
  809. bool bColorKey
  810. ) {
  811. SetSurfaceMode(SurfaceModeDD);
  812. DWORD flags = bColorKey ? DDBLT_KEYSRC : 0;
  813. DDSurface* pddsurface; CastTo(pddsurface, psurfaceSource);
  814. DDSCall(m_data.m_pdds->Blt(
  815. (RECT*)&rectTarget,
  816. pddsurface->GetDDSX(),
  817. (RECT*)&rectSource,
  818. flags | DDBLT_WAIT,
  819. NULL
  820. ));
  821. }
  822. //////////////////////////////////////////////////////////////////////////////
  823. //
  824. // Blt
  825. //
  826. //////////////////////////////////////////////////////////////////////////////
  827. void UnclippedBlt(
  828. const WinRect& rect,
  829. IDirectDrawSurfaceX* pddsSource,
  830. const WinPoint& pointSource,
  831. bool bColorKey
  832. ) {
  833. SetSurfaceMode(SurfaceModeDD);
  834. DWORD flags = bColorKey ? DDBLT_KEYSRC : 0;
  835. WinRect rectSource(pointSource, pointSource + rect.Size());
  836. DDSCall(m_data.m_pdds->Blt(
  837. (RECT*)&rect,
  838. pddsSource,
  839. (RECT*)&rectSource,
  840. flags | DDBLT_WAIT,
  841. NULL
  842. ));
  843. }
  844. void UnclippedBlt(const WinRect& rect, VideoSurface* psurfaceSource, const WinPoint& pointSource)
  845. {
  846. DDSurface* pddsurface; CastTo(pddsurface, psurfaceSource);
  847. UnclippedBlt(rect, pddsurface->GetDDSX(), pointSource, pddsurface->HasColorKey());
  848. }
  849. //////////////////////////////////////////////////////////////////////////////
  850. //
  851. // Fill
  852. //
  853. //////////////////////////////////////////////////////////////////////////////
  854. void UnclippedFill(const WinRect& rect, Pixel pixel)
  855. {
  856. DDBltFX ddbltfx;
  857. ddbltfx.dwFillColor = pixel.Value();
  858. DDSCall(m_data.m_pdds->Blt(
  859. (RECT*)&rect,
  860. NULL,
  861. (RECT*)&rect,
  862. DDBLT_COLORFILL | DDBLT_WAIT,
  863. &ddbltfx
  864. ));
  865. }
  866. };
  867. //////////////////////////////////////////////////////////////////////////////
  868. //
  869. // Constructors
  870. //
  871. //////////////////////////////////////////////////////////////////////////////
  872. TRef<DDSurface> CreateDDSurface(
  873. DDDevice* pdddevice,
  874. SurfaceType stype,
  875. PixelFormat* ppf,
  876. PrivatePalette* ppalette,
  877. const WinPoint& size
  878. ) {
  879. TRef<DDSurface> pddsurface = new DDSurfaceImpl(pdddevice, stype, ppf, ppalette, size);
  880. if (pddsurface->IsValid()) {
  881. return pddsurface;
  882. } else {
  883. return NULL;
  884. }
  885. }
  886. TRef<DDSurface> CreateDDSurface(
  887. DDDevice* pdddevice,
  888. SurfaceType stype,
  889. PixelFormat* ppf,
  890. PrivatePalette* ppalette,
  891. const WinPoint& size,
  892. int pitch,
  893. BYTE* pbits
  894. ) {
  895. return new DDSurfaceImpl(pdddevice, stype, ppf, ppalette, size, pitch, pbits);
  896. }
  897. TRef<DDSurface> CreateDDSurface(
  898. DDDevice* pdddevice,
  899. IDirectDrawSurfaceX* pdds,
  900. IDirectDrawSurfaceX* pddsZBuffer,
  901. PixelFormat* ppf,
  902. PrivatePalette* ppalette,
  903. SurfaceType stype
  904. ) {
  905. return
  906. new DDSurfaceImpl(
  907. pdddevice,
  908. pdds,
  909. pddsZBuffer,
  910. ppf,
  911. ppalette,
  912. stype
  913. );
  914. }