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

635 lines
17 KiB

  1. #include "stdafx.h"
  2. #include "mswebdvd.h"
  3. #include "msdvd.h"
  4. #include "ddrawobj.h"
  5. //
  6. // CDDrawDVD constructor
  7. //
  8. CDDrawDVD::CDDrawDVD(CMSWebDVD *pDVD)
  9. {
  10. m_pDVD = pDVD;
  11. // Default colors to be used for filling
  12. m_VideoKeyColor = RGB(255, 0, 255) ;
  13. m_pOverlayCallback = new CComObject<COverlayCallback> ;
  14. CComVariant vData;
  15. vData.vt = VT_VOID;
  16. vData.byref = this;
  17. if(m_pOverlayCallback){
  18. m_pOverlayCallback->SetDDrawDVD(vData);
  19. }
  20. }
  21. //
  22. // CDDrawDVD destructor
  23. //
  24. CDDrawDVD::~CDDrawDVD(void)
  25. {
  26. }
  27. /*************************************************************************/
  28. /* Function: SetupDDraw */
  29. /* Description: Creates DDrawObject and Surface */
  30. /*************************************************************************/
  31. HRESULT CDDrawDVD::SetupDDraw(const AMDDRAWGUID* lpDDGUID, HWND hwnd){
  32. // DO NOT CALL TWICE !!!
  33. // WILL CRASH OV MIXER DJ
  34. HRESULT hr = E_UNEXPECTED;
  35. if(!::IsWindow(hwnd)){
  36. return(hr);
  37. }/* end of if statement */
  38. m_pDDObject.Release();
  39. hr = ::DirectDrawCreate(lpDDGUID->lpGUID, &m_pDDObject, NULL);
  40. if(FAILED(hr)){
  41. return(hr);
  42. }/* end of if statement */
  43. hr = m_pDDObject->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
  44. if(FAILED(hr)){
  45. m_pDDObject.Release();
  46. return(hr);
  47. }/* end of if statement */
  48. DDSURFACEDESC ddsd;
  49. ::ZeroMemory(&ddsd, sizeof(ddsd));
  50. ddsd.dwSize = sizeof(ddsd);
  51. ddsd.dwFlags = DDSD_CAPS;
  52. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  53. m_pPrimary.Release();
  54. hr = m_pDDObject->CreateSurface(&ddsd, &m_pPrimary, NULL);
  55. if(FAILED(hr)){
  56. m_pDDObject.Release();
  57. return(hr);
  58. }/* end of if statement */
  59. CComPtr<IDirectDrawClipper> pClipper;
  60. hr = m_pDDObject->CreateClipper(0, &pClipper, NULL);
  61. if(FAILED(hr)){
  62. m_pPrimary.Release();
  63. m_pDDObject.Release();
  64. return(hr);
  65. }/* end of if statement */
  66. hr = pClipper->SetHWnd(0, hwnd);
  67. if(FAILED(hr)){
  68. m_pPrimary.Release();
  69. m_pDDObject.Release();
  70. pClipper.Release();
  71. return(hr);
  72. }/* end of if statement */
  73. hr = m_pPrimary->SetClipper(pClipper);
  74. if (FAILED(hr)){
  75. m_pPrimary.Release();
  76. m_pDDObject.Release();
  77. pClipper.Release();
  78. return(hr);
  79. }/* end of if statement */
  80. /*
  81. * We release the clipper interface after attaching it to the surface
  82. * as we don't need to use it again and the surface holds a reference
  83. * to the clipper when its been attached. The clipper will therefore
  84. * be released when the surface is released.
  85. */
  86. pClipper.Release();
  87. return(hr);
  88. }/* end of function SetupDDraw */
  89. /*************************************************************/
  90. /* Name:
  91. /* Description:
  92. /*************************************************************/
  93. HRESULT CDDrawDVD::SetColorKey(COLORREF colorKey)
  94. {
  95. m_VideoKeyColor = colorKey;
  96. // if 256 color mode, force to set back to magenta
  97. HWND hwnd = ::GetDesktopWindow();
  98. HDC hdc = ::GetWindowDC(hwnd);
  99. if(NULL == hdc){
  100. return(E_UNEXPECTED);
  101. }/* end of if statement */
  102. HRESULT hr = S_OK;
  103. if ((::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == RC_PALETTE)
  104. {
  105. if (m_VideoKeyColor != MAGENTA_COLOR_KEY) {
  106. hr = m_pDVD->put_ColorKey(MAGENTA_COLOR_KEY);
  107. if (SUCCEEDED(hr))
  108. m_VideoKeyColor = MAGENTA_COLOR_KEY;
  109. }
  110. }
  111. ::ReleaseDC(hwnd, hdc);
  112. return hr ;
  113. }
  114. /*************************************************************/
  115. /* Name:
  116. /* Description:
  117. /*************************************************************/
  118. COLORREF CDDrawDVD::GetColorKey()
  119. {
  120. // if 256 color mode, force to set back to magenta
  121. HWND hwnd = ::GetDesktopWindow();
  122. HDC hdc = ::GetWindowDC(hwnd);
  123. if(NULL == hdc){
  124. return(E_UNEXPECTED);
  125. }/* end of if statement */
  126. if ((::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == RC_PALETTE)
  127. {
  128. if (m_VideoKeyColor != MAGENTA_COLOR_KEY) {
  129. if (SUCCEEDED(m_pDVD->put_ColorKey(MAGENTA_COLOR_KEY)))
  130. m_VideoKeyColor = MAGENTA_COLOR_KEY;
  131. }
  132. }
  133. ::ReleaseDC(hwnd, hdc);
  134. return m_VideoKeyColor;
  135. }
  136. /*************************************************************************/
  137. /* Function: HasOverlay */
  138. /* Description: Tells us if the video card support overlay. */
  139. /*************************************************************************/
  140. HRESULT CDDrawDVD::HasOverlay(){
  141. HRESULT hr = S_OK;
  142. if(!m_pDDObject){
  143. return(E_UNEXPECTED);
  144. }/* end of if statement */
  145. DDCAPS caps;
  146. ::ZeroMemory(&caps, sizeof(DDCAPS));
  147. caps.dwSize = sizeof(DDCAPS);
  148. hr = m_pDDObject->GetCaps(&caps, NULL);
  149. if(FAILED(hr)){
  150. return(hr);
  151. }/* end of if statement */
  152. if(caps.dwMaxVisibleOverlays > 0){
  153. hr = S_OK;
  154. }
  155. else {
  156. hr = S_FALSE;
  157. }/* end of if statement */
  158. return(hr);
  159. }/* end of function HasOverlay */
  160. /*************************************************************************/
  161. /* Function: HasAvailableOverlay */
  162. /* Description: Tells us if the overlay is used. */
  163. /*************************************************************************/
  164. HRESULT CDDrawDVD::HasAvailableOverlay(){
  165. HRESULT hr = S_OK;
  166. if(!m_pDDObject){
  167. return(E_UNEXPECTED);
  168. }/* end of if statement */
  169. DDCAPS caps;
  170. ::ZeroMemory(&caps, sizeof(DDCAPS));
  171. caps.dwSize = sizeof(DDCAPS);
  172. hr = m_pDDObject->GetCaps(&caps, NULL);
  173. if(FAILED(hr)){
  174. return(hr);
  175. }/* end of if statement */
  176. if((caps.dwMaxVisibleOverlays > 0) && (caps.dwMaxVisibleOverlays > caps.dwCurrVisibleOverlays)){
  177. hr = S_OK;
  178. }
  179. else {
  180. hr = S_FALSE;
  181. }/* end of if statement */
  182. return(hr);
  183. }/* end of function HasAvailableOverlay */
  184. /*************************************************************************/
  185. /* Function: GetOverlayMaxStretch */
  186. /* Description: Tells us the maximum stretch factors of overlay. */
  187. /*************************************************************************/
  188. HRESULT CDDrawDVD::GetOverlayMaxStretch(DWORD *pdwMaxStretch){
  189. HRESULT hr = S_OK;
  190. if(!m_pDDObject){
  191. return(E_UNEXPECTED);
  192. }/* end of if statement */
  193. DDCAPS caps;
  194. ::ZeroMemory(&caps, sizeof(DDCAPS));
  195. caps.dwSize = sizeof(DDCAPS);
  196. hr = m_pDDObject->GetCaps(&caps, NULL);
  197. if(FAILED(hr)){
  198. return(hr);
  199. }/* end of if statement */
  200. if (caps.dwCaps & DDCAPS_OVERLAYSTRETCH && caps.dwMaxOverlayStretch!=0) {
  201. *pdwMaxStretch = caps.dwMaxOverlayStretch/2;
  202. }
  203. else {
  204. #ifdef _DEBUG
  205. ::MessageBox(::GetFocus(), TEXT("Overlay can't stretch"), TEXT("Error"), MB_OK) ;
  206. #endif
  207. }
  208. return(hr);
  209. }/* end of function GetOverlayMaxStretch */
  210. // convert a RGB color to a pysical color.
  211. // we do this by leting GDI SetPixel() do the color matching
  212. // then we lock the memory and see what it got mapped to.
  213. HRESULT CDDrawDVD::DDColorMatchOffscreen(COLORREF rgb, DWORD* dwColor)
  214. {
  215. HDC hdc;
  216. *dwColor = CLR_INVALID;
  217. DDSURFACEDESC ddsd;
  218. IDirectDrawSurface* pdds;
  219. LPDIRECTDRAW pdd = GetDDrawObj();
  220. HRESULT hr = S_OK;
  221. ZeroMemory(&ddsd, sizeof(ddsd)) ;
  222. ddsd.dwSize = sizeof(ddsd) ;
  223. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  224. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  225. ddsd.dwWidth = 8;
  226. ddsd.dwHeight = 8;
  227. hr = pdd->CreateSurface(&ddsd, &pdds, NULL);
  228. if (hr != DD_OK) {
  229. return 0;
  230. }
  231. // use GDI SetPixel to color match for us
  232. if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  233. {
  234. // set our value
  235. SetPixel(hdc, 0, 0, rgb);
  236. pdds->ReleaseDC(hdc);
  237. }
  238. // now lock the surface so we can read back the converted color
  239. ZeroMemory(&ddsd, sizeof(ddsd)) ;
  240. ddsd.dwSize = sizeof(ddsd) ;
  241. while ((hr = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
  242. ;
  243. if (hr == DD_OK)
  244. {
  245. // get DWORD
  246. DWORD temp = *(DWORD *)ddsd.lpSurface;
  247. // mask it to bpp
  248. if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
  249. temp &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;
  250. pdds->Unlock(NULL);
  251. *dwColor = temp;
  252. hr = S_OK;
  253. }
  254. pdds->Release();
  255. return hr;
  256. }
  257. /*************************************************************/
  258. /* Name: CreateDIBBrush
  259. /* Description:
  260. /*************************************************************/
  261. HRESULT CDDrawDVD::CreateDIBBrush(COLORREF rgb, HBRUSH *phBrush)
  262. {
  263. #if 1
  264. HDC hdc;
  265. DDSURFACEDESC ddsd;
  266. IDirectDrawSurface* pdds;
  267. LPDIRECTDRAW pdd = GetDDrawObj();
  268. HRESULT hr = S_OK;
  269. ZeroMemory(&ddsd, sizeof(ddsd)) ;
  270. ddsd.dwSize = sizeof(ddsd) ;
  271. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  272. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  273. ddsd.dwWidth = 8;
  274. ddsd.dwHeight = 8;
  275. hr = pdd->CreateSurface(&ddsd, &pdds, NULL);
  276. if (hr != DD_OK) {
  277. return 0;
  278. }
  279. // use GDI SetPixel to color match for us
  280. if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
  281. {
  282. // set our value
  283. SetPixel(hdc, 0, 0, rgb);
  284. pdds->ReleaseDC(hdc);
  285. }
  286. // now lock the surface so we can read back the converted color
  287. ZeroMemory(&ddsd, sizeof(ddsd)) ;
  288. ddsd.dwSize = sizeof(ddsd) ;
  289. while ((hr = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
  290. ;
  291. DWORD temp = CLR_INVALID;
  292. if (hr == DD_OK)
  293. {
  294. // get DWORD
  295. temp = *((DWORD *)ddsd.lpSurface);
  296. // mask it to bpp
  297. if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
  298. temp &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;
  299. pdds->Unlock(NULL);
  300. hr = S_OK;
  301. }
  302. ::ZeroMemory(&ddsd, sizeof(ddsd)) ;
  303. ddsd.dwSize = sizeof(ddsd) ;
  304. hr = pdds->GetSurfaceDesc(&ddsd) ;
  305. if (! (SUCCEEDED(hr) && (ddsd.dwFlags & DDSD_WIDTH) && (ddsd.dwFlags & DDSD_HEIGHT)) ) {
  306. return hr;
  307. }
  308. if (hr == DD_OK && temp != CLR_INVALID) {
  309. DDBLTFX ddBltFx;
  310. ::ZeroMemory(&ddBltFx, sizeof(ddBltFx)) ;
  311. ddBltFx.dwSize = sizeof(DDBLTFX);
  312. ddBltFx.dwFillColor = temp;
  313. RECT rc;
  314. ::SetRect(&rc, 0, 0, ddsd.dwWidth, ddsd.dwHeight);
  315. hr = pdds->Blt(&rc, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddBltFx);
  316. if (FAILED(hr)) {
  317. return hr;
  318. }
  319. DWORD dwBitCount = ddsd.ddpfPixelFormat.dwRGBBitCount;
  320. DWORD dwWidth = WIDTHBYTES(ddsd.dwWidth*dwBitCount);
  321. DWORD dwSizeImage = ddsd.dwHeight*dwWidth;
  322. BYTE *packedDIB = new BYTE[sizeof(BITMAPINFOHEADER) + dwSizeImage + 1024];
  323. BITMAPINFOHEADER *lpbmi = (BITMAPINFOHEADER*) packedDIB;
  324. ::ZeroMemory(lpbmi, sizeof(BITMAPINFOHEADER));
  325. lpbmi->biSize = sizeof(BITMAPINFOHEADER);
  326. lpbmi->biBitCount = (WORD)dwBitCount;
  327. lpbmi->biWidth = ddsd.dwWidth;
  328. lpbmi->biHeight = ddsd.dwHeight;
  329. lpbmi->biPlanes = 1;
  330. LPDWORD pdw = (LPDWORD)DibColors(lpbmi);
  331. switch (dwBitCount) {
  332. case 8: {
  333. lpbmi->biCompression = BI_RGB;
  334. lpbmi->biClrUsed = 256;
  335. for (int i=0; i<(int)lpbmi->biClrUsed/16; i++)
  336. {
  337. *pdw++ = 0x00000000; // 0000 black
  338. *pdw++ = 0x00800000; // 0001 dark red
  339. *pdw++ = 0x00008000; // 0010 dark green
  340. *pdw++ = 0x00808000; // 0011 mustard
  341. *pdw++ = 0x00000080; // 0100 dark blue
  342. *pdw++ = 0x00800080; // 0101 purple
  343. *pdw++ = 0x00008080; // 0110 dark turquoise
  344. *pdw++ = 0x00C0C0C0; // 1000 gray
  345. *pdw++ = 0x00808080; // 0111 dark gray
  346. *pdw++ = 0x00FF0000; // 1001 red
  347. *pdw++ = 0x0000FF00; // 1010 green
  348. *pdw++ = 0x00FFFF00; // 1011 yellow
  349. *pdw++ = 0x000000FF; // 1100 blue
  350. *pdw++ = 0x00FF00FF; // 1101 pink (magenta)
  351. *pdw++ = 0x0000FFFF; // 1110 cyan
  352. *pdw++ = 0x00FFFFFF; // 1111 white
  353. }
  354. break;
  355. }
  356. case 16:
  357. lpbmi->biCompression = BI_BITFIELDS;
  358. lpbmi->biClrUsed = 3;
  359. pdw[0] = ddsd.ddpfPixelFormat.dwRBitMask ;
  360. pdw[1] = ddsd.ddpfPixelFormat.dwGBitMask ;
  361. pdw[2] = ddsd.ddpfPixelFormat.dwBBitMask ;
  362. break;
  363. case 24:
  364. case 32:
  365. lpbmi->biCompression = BI_RGB;
  366. lpbmi->biClrUsed = 0;
  367. break;
  368. }
  369. ZeroMemory(&ddsd, sizeof(ddsd)) ;
  370. ddsd.dwSize = sizeof(ddsd) ;
  371. while ((hr = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
  372. ;
  373. if (hr != DD_OK)
  374. return hr;
  375. BYTE *lpTempSurf = (BYTE *)ddsd.lpSurface;
  376. for (DWORD i=0; i<ddsd.dwHeight; i++) {
  377. ::memcpy((BYTE*) DibPtr(lpbmi)+i*dwWidth,
  378. lpTempSurf+i*ddsd.lPitch, dwWidth);
  379. }
  380. pdds->Unlock(NULL);
  381. *phBrush = ::CreateDIBPatternBrushPt((LPVOID) packedDIB, DIB_RGB_COLORS);
  382. }
  383. pdds->Release();
  384. #else
  385. HRESULT hr = S_OK;
  386. typedef struct {
  387. BYTE rgb[3];
  388. } RGB;
  389. typedef struct {
  390. BITMAPINFOHEADER bmiHeader;
  391. RGB pBits[8][8];
  392. } PackedDIB;
  393. PackedDIB packedDIB;
  394. ::ZeroMemory(&packedDIB, sizeof(PackedDIB));
  395. packedDIB.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  396. packedDIB.bmiHeader.biCompression = BI_RGB;
  397. packedDIB.bmiHeader.biBitCount = 24;
  398. packedDIB.bmiHeader.biHeight = 8;
  399. packedDIB.bmiHeader.biWidth = 8;
  400. packedDIB.bmiHeader.biPlanes = 1;
  401. for (int i=0; i<8; i++) {
  402. for (int j=0; j<8; j++)
  403. packedDIB.pBits[i][j] = *((RGB*)&rgb);
  404. }
  405. *phBrush = ::CreateDIBPatternBrushPt((LPVOID)&packedDIB, DIB_RGB_COLORS);
  406. #endif
  407. return hr;
  408. }
  409. /* COverlayCallback */
  410. /*************************************************************/
  411. /* Name: OnUpdateOverlay
  412. /* Description:
  413. /*************************************************************/
  414. HRESULT STDMETHODCALLTYPE COverlayCallback::OnUpdateOverlay(BOOL bBefore,
  415. DWORD dwFlags,
  416. BOOL bOldVisible,
  417. const RECT *prcSrcOld,
  418. const RECT *prcDestOld,
  419. BOOL bNewVisible,
  420. const RECT *prcSrcNew,
  421. const RECT *prcDestNew)
  422. {
  423. if (bBefore)
  424. return S_OK;
  425. if(!prcSrcOld || !prcDestOld || !prcSrcNew || !prcDestNew){
  426. return E_POINTER;
  427. }
  428. CMSWebDVD *pDVD = m_pDDrawDVD->GetDVD();
  429. ATLASSERT(pDVD);
  430. if (m_dwWidth != (DWORD)RECTWIDTH(prcDestNew) ||
  431. m_dwHeight != (DWORD)RECTHEIGHT(prcDestNew) ||
  432. m_dwARWidth != (DWORD)RECTWIDTH(prcDestNew) ||
  433. m_dwARHeight != (DWORD)RECTHEIGHT(prcDestNew)) {
  434. m_dwWidth = (DWORD)RECTWIDTH(prcDestNew);
  435. m_dwHeight = (DWORD)RECTHEIGHT(prcDestNew);
  436. m_dwARWidth = (DWORD)RECTWIDTH(prcDestNew);
  437. m_dwARHeight = (DWORD)RECTHEIGHT(prcDestNew);
  438. return pDVD->UpdateOverlay();
  439. } /* end of if statement */
  440. return S_OK;
  441. }
  442. /*************************************************************/
  443. /* Name: OnUpdateColorKey
  444. /* Description:
  445. /*************************************************************/
  446. HRESULT STDMETHODCALLTYPE COverlayCallback::OnUpdateColorKey(COLORKEY const *pKey, DWORD dwColor)
  447. {
  448. m_pDDrawDVD->SetColorKey(pKey->HighColorValue);
  449. return S_OK ;
  450. }
  451. /*************************************************************/
  452. /* Name: OnUpdateSize
  453. /* Description:
  454. /*************************************************************/
  455. HRESULT STDMETHODCALLTYPE COverlayCallback::OnUpdateSize(DWORD dwWidth, DWORD dwHeight,
  456. DWORD dwARWidth, DWORD dwARHeight)
  457. {
  458. CMSWebDVD *pDVD = m_pDDrawDVD->GetDVD();
  459. ATLASSERT(pDVD);
  460. if (m_dwWidth != dwWidth ||
  461. m_dwHeight != dwHeight ||
  462. m_dwARWidth != dwARWidth ||
  463. m_dwARHeight != dwARHeight) {
  464. m_dwWidth = dwWidth;
  465. m_dwHeight = dwHeight;
  466. m_dwARWidth = dwARWidth;
  467. m_dwARHeight = dwARHeight;
  468. return pDVD->UpdateOverlay();
  469. } /* end of if statement */
  470. return S_OK;
  471. }
  472. /*************************************************************/
  473. /* Name: SetDDrawDVD
  474. /* Description:
  475. /*************************************************************/
  476. STDMETHODIMP COverlayCallback::SetDDrawDVD(VARIANT pDDrawDVD)
  477. {
  478. switch(pDDrawDVD.vt){
  479. case VT_VOID: {
  480. m_pDDrawDVD = static_cast<CDDrawDVD*> (pDDrawDVD.byref);
  481. break;
  482. }
  483. } /* end of switch statement */
  484. return S_OK;
  485. }