vid_ddraw.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. #include <ddraw.h>
  2. #include <multimon.h>
  3. #include "main.h"
  4. #include "vid_subs.h"
  5. #include "vid_ddraw.h"
  6. #include "directdraw.h"
  7. #include "WinampAttributes.h"
  8. #include "../nsutil/image.h"
  9. DDrawVideoOutput ddrawVideo;
  10. #define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
  11. DDrawVideoOutput::DDrawVideoOutput()
  12. {
  13. lpDD = NULL;
  14. lpddsOverlay = NULL;
  15. lastresizerect.bottom = 0;
  16. lastresizerect.top = 0;
  17. lastresizerect.left = 0;
  18. lastresizerect.right = 0;
  19. lpddsPrimary = NULL;
  20. lpddsClipper = NULL;
  21. lpddsSTTemp = NULL;
  22. width = height = flip = 0;
  23. type = VIDEO_MAKETYPE('Y', 'V', '1', '2');
  24. uDestSizeAlign = uSrcSizeAlign = 0;
  25. dwUpdateFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
  26. m_depth = 16;
  27. initing = false;
  28. needchange = 0;
  29. m_palette = NULL;
  30. m_lastsubtitle = NULL;
  31. sttmp_w = sttmp_h = 0;
  32. subFont = NULL;
  33. m_sub_needremeasure = 0;
  34. m_fontsize = 0;
  35. memset(&winRect, 0, sizeof(winRect));
  36. }
  37. void DDrawVideoOutput::close()
  38. {
  39. if (lpddsSTTemp) lpddsSTTemp->Release(); lpddsSTTemp = 0;
  40. if (lpddsPrimary) lpddsPrimary->Release(); lpddsPrimary = 0;
  41. if (lpddsOverlay) lpddsOverlay->Release(); lpddsOverlay = 0;
  42. if (lpddsClipper) lpddsClipper->Release(); lpddsClipper = 0;
  43. if (lpDD) lpDD->Release(); lpDD = 0;// BU added NULL check in response to talkback
  44. if (subFont) DeleteObject(subFont); subFont = 0;
  45. // removeFullScreen();
  46. }
  47. DDrawVideoOutput::~DDrawVideoOutput()
  48. {
  49. DDrawVideoOutput::close();
  50. }
  51. void DDrawVideoOutput::drawSubtitle(SubsItem *item)
  52. {
  53. m_lastsubtitle = item;
  54. m_sub_needremeasure = 1;
  55. }
  56. int DDrawVideoOutput::create(HWND parent, VideoAspectAdjuster *_adjuster, int w, int h, unsigned int ptype, int flipit, double aspectratio)
  57. {
  58. needchange = 0;
  59. this->parent = parent;
  60. m_lastsubtitle = NULL;
  61. type = ptype;
  62. width = w;
  63. height = h;
  64. flip = flipit;
  65. adjuster = _adjuster;
  66. initing = true;
  67. HWND hwnd = this->parent;
  68. if (lpDD) lpDD->Release();
  69. lpDD = NULL;
  70. update_monitor_coords();
  71. if (_DirectDrawCreate)
  72. {
  73. if (!foundGUID) _DirectDrawCreate(NULL, &lpDD, NULL);
  74. else _DirectDrawCreate(&m_devguid, &lpDD, NULL);
  75. }
  76. if (!lpDD)
  77. {
  78. initing = false;
  79. return 0;
  80. }
  81. lpDD->SetCooperativeLevel(hwnd, DDSCL_NOWINDOWCHANGES | DDSCL_NORMAL);
  82. DDSURFACEDESC ddsd;
  83. INIT_DIRECTDRAW_STRUCT(ddsd);
  84. ddsd.dwFlags = DDSD_CAPS;
  85. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  86. HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpddsPrimary, NULL);
  87. if (FAILED(ddrval) || !lpddsPrimary)
  88. {
  89. initing = false;
  90. return 0;
  91. }
  92. HRESULT v = -1;
  93. DDSURFACEDESC DDsd = {sizeof(DDsd), };
  94. lpddsPrimary->GetSurfaceDesc(&ddsd);
  95. DDsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; //create the surface at screen depth
  96. DDsd.dwWidth = w;
  97. DDsd.dwHeight = h;
  98. DDsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN;
  99. if (config_video_ddraw) v = lpDD->CreateSurface(&DDsd, &lpddsOverlay, NULL);
  100. if (!config_video_ddraw || FAILED(v))
  101. {
  102. // fall back to system memory if video mem doesn't work
  103. DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
  104. v = lpDD->CreateSurface(&DDsd, &lpddsOverlay, NULL);
  105. }
  106. if (FAILED(v))
  107. {
  108. // this video card sucks then :)
  109. lpddsOverlay = NULL;
  110. initing = false;
  111. return 0;
  112. }
  113. // get the depth
  114. m_depth = 8;
  115. INIT_DIRECTDRAW_STRUCT(m_ddpf);
  116. if (lpddsOverlay->GetPixelFormat(&m_ddpf) >= 0)
  117. {
  118. m_depth = m_ddpf.dwRGBBitCount;
  119. if (m_depth == 16 && m_ddpf.dwGBitMask == 0x03e0) m_depth = 15;
  120. }
  121. if (lpDD->CreateClipper(0, &lpddsClipper, NULL) != DD_OK)
  122. {
  123. lpddsClipper = NULL;
  124. initing = false;
  125. return 0;
  126. }
  127. lpddsClipper->SetHWnd(0, hwnd);
  128. lpddsPrimary->SetClipper(lpddsClipper);
  129. initing = false;
  130. //get current monitor
  131. getViewport(&m_monRect, hwnd, 1, NULL);
  132. return 1;
  133. }
  134. bool DDrawVideoOutput::Paint(HWND hwnd)
  135. {
  136. RECT r;
  137. GetClientRect(hwnd, &r);
  138. RECT fullr = r;
  139. adjuster->adjustAspect(r);
  140. if (r.left != lastresizerect.left || r.right != lastresizerect.right || r.top != lastresizerect.top ||
  141. r.bottom != lastresizerect.bottom)
  142. {
  143. if (r.left != 0)
  144. {
  145. RECT tmp = {0, 0, r.left, fullr.bottom};
  146. InvalidateRect(hwnd, &tmp, TRUE);
  147. }
  148. if (r.right != fullr.right)
  149. {
  150. RECT tmp = {r.right, 0, fullr.right, fullr.bottom};
  151. InvalidateRect(hwnd, &tmp, TRUE);
  152. }
  153. if (r.top != 0)
  154. {
  155. RECT tmp = {r.left, 0, r.right, r.top};
  156. InvalidateRect(hwnd, &tmp, TRUE);
  157. }
  158. if (r.bottom != fullr.bottom)
  159. {
  160. RECT tmp = {r.left, r.bottom, r.right, fullr.bottom};
  161. InvalidateRect(hwnd, &tmp, TRUE);
  162. }
  163. lastresizerect = r;
  164. }
  165. ClientToScreen(hwnd, (LPPOINT)&r);
  166. ClientToScreen(hwnd, ((LPPOINT)&r) + 1);
  167. // transform coords from windows desktop coords (where 0,0==upper-left corner of box encompassing all monitors)
  168. // to the coords for the monitor we're displaying on:
  169. r.left -= m_mon_x;
  170. r.right -= m_mon_x;
  171. r.top -= m_mon_y;
  172. r.bottom -= m_mon_y;
  173. HDC hdc = NULL;
  174. HDC inhdc = NULL;
  175. RECT *pSrcRect = NULL;
  176. int needst = 0;
  177. SubsItem *mlst = m_lastsubtitle;
  178. if (mlst)
  179. {
  180. int curw = r.right - r.left, curh = r.bottom - r.top;
  181. if (!lpddsSTTemp || sttmp_w != curw || sttmp_h != curh)
  182. {
  183. if (lpddsSTTemp) lpddsSTTemp->Release();
  184. lpddsSTTemp = 0;
  185. HRESULT v = -1;
  186. DDSURFACEDESC DDsd = {sizeof(DDsd), };
  187. DDSURFACEDESC ddsd;
  188. INIT_DIRECTDRAW_STRUCT(ddsd);
  189. ddsd.dwFlags = DDSD_CAPS;
  190. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  191. lpddsPrimary->GetSurfaceDesc(&ddsd);
  192. DDsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; //create the surface at screen depth
  193. DDsd.dwWidth = sttmp_w = curw;
  194. DDsd.dwHeight = sttmp_h = curh;
  195. DDsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
  196. if (config_video_ddraw) v = lpDD->CreateSurface(&DDsd, &lpddsSTTemp, NULL);
  197. if (!config_video_ddraw || FAILED(v))
  198. {
  199. // fall back to system memory if video mem doesn't work
  200. DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
  201. lpDD->CreateSurface(&DDsd, &lpddsSTTemp, NULL);
  202. }
  203. m_sub_needremeasure = 1;
  204. }
  205. if (lpddsSTTemp) needst = 1;
  206. }
  207. if (needst)
  208. {
  209. HDC tmpdc = NULL;
  210. if (!config_video_ddraw || lpddsSTTemp->Blt(NULL, lpddsOverlay, NULL, DDBLT_WAIT, 0) != DD_OK)
  211. {
  212. // as a last resort, BitBlt().
  213. HDC tmpdc2;
  214. if (lpddsOverlay->GetDC(&tmpdc2) == DD_OK)
  215. {
  216. if (lpddsSTTemp->GetDC(&tmpdc) == DD_OK)
  217. {
  218. BitBlt(tmpdc, 0, 0, sttmp_w, sttmp_h, tmpdc2, 0, 0, SRCCOPY);
  219. }
  220. }
  221. }
  222. if (mlst && (tmpdc || lpddsSTTemp->GetDC(&tmpdc) == DD_OK))
  223. {
  224. int m_lastsubxp = mlst->xPos;
  225. int m_lastsubyp = mlst->yPos;
  226. RECT oldwinRect = winRect;
  227. GetClientRect(hwnd, &winRect);
  228. if (!subFont || ((winRect.bottom - winRect.top) != (oldwinRect.bottom - oldwinRect.top)) || m_fontsize != mlst->fontSize)
  229. {
  230. if (subFont) DeleteObject(subFont);
  231. m_fontsize = mlst->fontSize;
  232. subFont = CreateFontA(14 + m_fontsize + 18 * (winRect.bottom - winRect.top) / 768, 0, 0, 0, FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
  233. }
  234. HGDIOBJ oldobj = SelectObject(tmpdc, subFont);
  235. int centerflags = 0;
  236. if (m_lastsubxp < 127) centerflags |= DT_LEFT;
  237. else if (m_lastsubxp > 127) centerflags |= DT_RIGHT;
  238. else centerflags |= DT_CENTER;
  239. if (m_lastsubyp < 127) centerflags |= DT_TOP;
  240. else if (m_lastsubyp > 127) centerflags |= DT_BOTTOM;
  241. if (m_sub_needremeasure && mlst)
  242. {
  243. subRect = r;
  244. subRect.bottom -= subRect.top;
  245. subRect.right -= subRect.left;
  246. subRect.top = subRect.left = 0;
  247. SIZE s;
  248. GetTextExtentPoint32A(tmpdc, mlst->text, lstrlenA(mlst->text), &s);
  249. // calcul for multiline text
  250. const char *p = mlst->text;
  251. int n = 0;
  252. while (*p != 0) if (*p++ == '\n') n++;
  253. if (n) s.cy *= (n + 1);
  254. if (m_lastsubxp > 127) // towards the right
  255. {
  256. subRect.right -= ((subRect.right - subRect.left) * (255 - m_lastsubxp)) / 256;
  257. }
  258. else if (m_lastsubxp < 127)
  259. {
  260. subRect.left += ((subRect.right - subRect.left) * m_lastsubxp) / 256;
  261. }
  262. subRect.top += ((subRect.bottom - s.cy - subRect.top) * m_lastsubyp) / 255;
  263. subRect.bottom = subRect.top + s.cy;
  264. }
  265. SetBkMode(tmpdc, TRANSPARENT);
  266. // draw outline
  267. SetTextColor(tmpdc, RGB(0, 0, 0));
  268. int y = 1;
  269. int x = 1;
  270. RECT r2 = {subRect.left + x, subRect.top + y, subRect.right + x, subRect.bottom + y};
  271. if (mlst)
  272. {
  273. DrawTextA(tmpdc, mlst->text, -1, &r2, centerflags | DT_NOCLIP | DT_NOPREFIX);
  274. // draw text
  275. SetTextColor(tmpdc, RGB(mlst->colorRed, mlst->colorGreen, mlst->colorBlue));
  276. DrawTextA(tmpdc, mlst->text, -1, &subRect, centerflags | DT_NOCLIP | DT_NOPREFIX);
  277. }
  278. SelectObject(tmpdc, oldobj);
  279. lpddsSTTemp->ReleaseDC(tmpdc);
  280. }
  281. if (!config_video_ddraw || lpddsPrimary->Blt(&r, lpddsSTTemp, pSrcRect, DDBLT_WAIT, 0) != DD_OK)
  282. {
  283. // as a last resort, BitBlt().
  284. if (lpddsOverlay->GetDC(&inhdc) != DD_OK)
  285. {
  286. needchange = 1;
  287. return false;
  288. }
  289. if (lpddsPrimary->GetDC(&hdc) != DD_OK)
  290. {
  291. lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
  292. needchange = 1;
  293. return false;
  294. }
  295. int src_w = width;
  296. int src_h = pSrcRect ? (pSrcRect->bottom - pSrcRect->top) : height;
  297. if (r.right - r.left == src_w && r.bottom - r.top == src_h)
  298. BitBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, SRCCOPY);
  299. else
  300. StretchBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, src_w, src_h, SRCCOPY);
  301. }
  302. }
  303. else
  304. {
  305. if (!config_video_ddraw || lpddsPrimary->Blt(&r, lpddsOverlay, pSrcRect, DDBLT_WAIT, 0) != DD_OK)
  306. {
  307. // as a last resort, BitBlt().
  308. if (lpddsOverlay->GetDC(&inhdc) != DD_OK)
  309. {
  310. needchange = 1;
  311. return false;
  312. }
  313. if (lpddsPrimary->GetDC(&hdc) != DD_OK)
  314. {
  315. lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
  316. needchange = 1;
  317. return false;
  318. }
  319. int src_w = width;
  320. int src_h = pSrcRect ? (pSrcRect->bottom - pSrcRect->top) : height;
  321. if (r.right - r.left == src_w && r.bottom - r.top == src_h)
  322. BitBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, SRCCOPY);
  323. else
  324. StretchBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, src_w, src_h, SRCCOPY);
  325. }
  326. }
  327. if (hdc)
  328. {
  329. lpddsPrimary->ReleaseDC(hdc); hdc = NULL;
  330. }
  331. if (inhdc)
  332. {
  333. lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
  334. }
  335. return true;
  336. }
  337. int DDrawVideoOutput::onPaint(HWND hwnd)
  338. {
  339. // reblit the last frame
  340. if (lpddsPrimary)
  341. {
  342. PAINTSTRUCT p;
  343. BeginPaint(hwnd, &p);
  344. RECT r;
  345. GetClientRect(hwnd, &r);
  346. HRGN hrgn = CreateRectRgnIndirect(&r);
  347. HBRUSH b = (HBRUSH)GetStockObject(BLACK_BRUSH);
  348. FillRgn(p.hdc, hrgn, b);
  349. DeleteObject(b);
  350. DeleteObject(hrgn);
  351. if (Paint(hwnd))
  352. {
  353. EndPaint(hwnd, &p);
  354. return 1;
  355. }
  356. EndPaint(hwnd, &p);
  357. }
  358. return 0;
  359. }
  360. bool DDrawVideoOutput::LockSurface(DDSURFACEDESC *dd)
  361. {
  362. for (;;Sleep(0))
  363. {
  364. HRESULT hr = lpddsOverlay->Lock(0, dd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
  365. if (dd->lpSurface)
  366. break;
  367. if (hr == DDERR_SURFACELOST)
  368. {
  369. lpddsPrimary->Restore();
  370. lpddsOverlay->Restore();
  371. hr = lpddsOverlay->Lock(0, dd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0);
  372. if (hr == DDERR_SURFACELOST)
  373. return false;
  374. }
  375. else if (hr != DDERR_WASSTILLDRAWING)
  376. return false;
  377. }
  378. return true;
  379. }
  380. void DDrawVideoOutput::displayFrame(const char *buf, int size, int time)
  381. {
  382. DDSURFACEDESC dd = {sizeof(dd), };
  383. if (config_video_vsync2) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
  384. if (!LockSurface(&dd))
  385. {
  386. needchange = 1;
  387. return ;
  388. }
  389. if (type == VIDEO_MAKETYPE('Y', 'V', '1', '2'))
  390. {
  391. const YV12_PLANES *planes = (YV12_PLANES *)buf;
  392. // convert yv12 to rgb
  393. int bytes = m_depth >> 3;
  394. if (m_depth == 15) bytes = 2;
  395. int i, j, y00, y01, y10, y11, u, v;
  396. unsigned char *pY = (unsigned char *)planes->y.baseAddr;
  397. unsigned char *pU = (unsigned char *)planes->u.baseAddr;
  398. unsigned char *pV = (unsigned char *)planes->v.baseAddr;
  399. unsigned char *pOut = (unsigned char*)dd.lpSurface;
  400. const int rvScale = (int)(2.017 * 65536.0); //91881;
  401. const int gvScale = - (int)(0.392 * 65536.0); // -22553;
  402. const int guScale = - (int)(0.813 * 65536.0); // -46801;
  403. const int buScale = (int)(1.596 * 65536.0); //116129;
  404. const int yScale = (int)(1.164 * 65536.0); //(1.164*65536.0);
  405. int addOut = dd.lPitch * 2 - width * bytes;
  406. int yrb = planes->y.rowBytes;
  407. int addL = dd.lPitch;
  408. /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
  409. #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
  410. if (flip)
  411. {
  412. pOut += (dd.lPitch) * (height - 1);
  413. addOut = -dd.lPitch * 2 - width * bytes;
  414. addL = -addL;
  415. }
  416. for (j = 0; j <= height - 2; j += 2)
  417. {
  418. for (i = 0; i <= width - 2; i += 2)
  419. {
  420. y00 = *pY - 16;
  421. y01 = *(pY + 1) - 16;
  422. y10 = *(pY + yrb) - 16;
  423. y11 = *(pY + yrb + 1) - 16;
  424. u = (*pU++) - 128;
  425. v = (*pV++) - 128;
  426. {
  427. int r, g, b;
  428. g = guScale * v + gvScale * u;
  429. r = buScale * v;
  430. b = rvScale * u;
  431. y00 *= yScale; y01 *= yScale;
  432. y10 *= yScale; y11 *= yScale;
  433. switch (m_depth)
  434. {
  435. case 15:
  436. {
  437. unsigned short *rgb = (unsigned short *)pOut;
  438. rgb[0] = ((LIMIT(r + y00) >> 3) << 10) | ((LIMIT(g + y00) >> 3) << 5) | (LIMIT(b + y00) >> 3);
  439. rgb[1] = ((LIMIT(r + y01) >> 3) << 10) | ((LIMIT(g + y01) >> 3) << 5) | (LIMIT(b + y01) >> 3);
  440. rgb += addL / 2;
  441. rgb[0] = ((LIMIT(r + y10) >> 3) << 10) | ((LIMIT(g + y10) >> 3) << 5) | (LIMIT(b + y10) >> 3);
  442. rgb[1] = ((LIMIT(r + y11) >> 3) << 10) | ((LIMIT(g + y11) >> 3) << 5) | (LIMIT(b + y11) >> 3);
  443. }
  444. break;
  445. case 16:
  446. {
  447. unsigned short *rgb = (unsigned short *)pOut;
  448. rgb[0] = ((LIMIT(r + y00) >> 3) << 11) | ((LIMIT(g + y00) >> 2) << 5) | (LIMIT(b + y00) >> 3);
  449. rgb[1] = ((LIMIT(r + y01) >> 3) << 11) | ((LIMIT(g + y01) >> 2) << 5) | (LIMIT(b + y01) >> 3);
  450. rgb += addL / 2;
  451. rgb[0] = ((LIMIT(r + y10) >> 3) << 11) | ((LIMIT(g + y10) >> 2) << 5) | (LIMIT(b + y10) >> 3);
  452. rgb[1] = ((LIMIT(r + y11) >> 3) << 11) | ((LIMIT(g + y11) >> 2) << 5) | (LIMIT(b + y11) >> 3);
  453. }
  454. break;
  455. case 24:
  456. {
  457. unsigned char *rgb = pOut;
  458. /* Write out top two pixels */
  459. rgb[0] = LIMIT(b + y00); rgb[1] = LIMIT(g + y00); rgb[2] = LIMIT(r + y00);
  460. rgb[3] = LIMIT(b + y01); rgb[4] = LIMIT(g + y01); rgb[5] = LIMIT(r + y01);
  461. /* Skip down to next line to write out bottom two pixels */
  462. rgb += addL;
  463. rgb[0] = LIMIT(b + y10); rgb[1] = LIMIT(g + y10); rgb[2] = LIMIT(r + y10);
  464. rgb[3] = LIMIT(b + y11); rgb[4] = LIMIT(g + y11); rgb[5] = LIMIT(r + y11);
  465. }
  466. break;
  467. case 32:
  468. {
  469. unsigned char *rgb = pOut;
  470. /* Write out top two pixels */
  471. rgb[0] = LIMIT(b + y00); rgb[1] = LIMIT(g + y00); rgb[2] = LIMIT(r + y00);
  472. rgb[4] = LIMIT(b + y01); rgb[5] = LIMIT(g + y01); rgb[6] = LIMIT(r + y01);
  473. /* Skip down to next line to write out bottom two pixels */
  474. rgb += addL;
  475. rgb[0] = LIMIT(b + y10); rgb[1] = LIMIT(g + y10); rgb[2] = LIMIT(r + y10);
  476. rgb[4] = LIMIT(b + y11); rgb[5] = LIMIT(g + y11); rgb[6] = LIMIT(r + y11);
  477. }
  478. break;
  479. }
  480. }
  481. pY += 2;
  482. pOut += 2 * bytes;
  483. }
  484. pY += yrb + yrb - width;
  485. pU += planes->u.rowBytes - width / 2;
  486. pV += planes->v.rowBytes - width / 2;
  487. pOut += addOut;
  488. }
  489. }
  490. else if (type == VIDEO_MAKETYPE('R', 'G', '3', '2'))
  491. {
  492. //FUCKO: do we need to support 8bits depth?
  493. switch (m_depth)
  494. {
  495. case 15:
  496. { // convert RGB32 -> RGB16 (555)
  497. const char *a = buf;
  498. char *b = (char *)dd.lpSurface;
  499. int l = width * 4, l2 = dd.lPitch;
  500. int ladj = l;
  501. if (flip)
  502. {
  503. a += l * (height - 1); ladj = -ladj;
  504. }
  505. for (int i = 0;i < height;i++)
  506. {
  507. short *dest = (short *)b;
  508. int *src = (int *)a;
  509. for (int j = 0;j < width;j++)
  510. {
  511. int c = *(src++);
  512. int r = c >> 16;
  513. int g = (c >> 8) & 0xff;
  514. int b = (c) & 0xff;
  515. *(dest++) = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
  516. }
  517. a += ladj; b += l2;
  518. }
  519. }
  520. break;
  521. case 16:
  522. { // convert RGB32 -> RGB16
  523. //FUCKO: this assumes 565
  524. const char *a = buf;
  525. char *b = (char *)dd.lpSurface;
  526. int l = width * 4, l2 = dd.lPitch;
  527. int ladj = l;
  528. if (flip)
  529. {
  530. a += l * (height - 1); ladj = -ladj;
  531. }
  532. for (int i = 0;i < height;i++)
  533. {
  534. short *dest = (short *)b;
  535. int *src = (int *)a;
  536. for (int j = 0;j < width;j++)
  537. {
  538. //FUCKO: optimize here
  539. int c = *(src++);
  540. int r = c >> 16;
  541. int g = (c >> 8) & 0xff;
  542. int b = (c) & 0xff;
  543. *(dest++) = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  544. }
  545. a += ladj; b += l2;
  546. }
  547. }
  548. break;
  549. case 24:
  550. { // convert RGB32 -> RGB24
  551. const char *a = buf;
  552. char *b = (char *)dd.lpSurface;
  553. int l = width * 4, l2 = dd.lPitch;
  554. int ladj = l;
  555. if (flip)
  556. {
  557. a += l * (height - 1); ladj = -ladj;
  558. }
  559. for (int i = 0;i < height;i++)
  560. {
  561. char *dest = (char *)b;
  562. int *src = (int *)a;
  563. for (int j = 0;j < width;j++)
  564. {
  565. //FUCKO: optimize here
  566. int c = *(src++);
  567. int r = c >> 16;
  568. int g = (c >> 8) & 0xff;
  569. int b = (c) & 0xff;
  570. *dest++ = b;
  571. *dest++ = g;
  572. *dest++ = r;
  573. }
  574. a += ladj; b += l2;
  575. }
  576. }
  577. break;
  578. case 32:
  579. { // straight RGB32 copy
  580. if (flip)
  581. nsutil_image_CopyFlipped_U8((uint8_t *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*4, width, height);
  582. else
  583. nsutil_image_Copy_U8((uint8_t *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*4, width, height);
  584. }
  585. break;
  586. }
  587. }
  588. else if (type == VIDEO_MAKETYPE('Y', 'U', 'Y', '2') || type == VIDEO_MAKETYPE('U', 'Y', 'V', 'Y'))
  589. {
  590. //const char *a = buf;
  591. char *b = (char *)dd.lpSurface;
  592. int /*l = width * 2, */l2 = dd.lPitch;
  593. if (flip)
  594. {
  595. b += (height - 1) * l2;
  596. l2 = -l2;
  597. }
  598. switch (m_depth)
  599. {
  600. case 15:
  601. {
  602. // yuy2->rgb16 (555) conversion
  603. unsigned char *src = (unsigned char *)buf;
  604. unsigned short *dst = (unsigned short *)dd.lpSurface;
  605. int line, col; //, linewidth;
  606. int y, yy;
  607. int u, v;
  608. int vr, ug, vg, ub;
  609. unsigned char *py, *pu, *pv;
  610. //linewidth = width - (width >> 1);
  611. py = src;
  612. pu = src + 1;
  613. pv = src + 3;
  614. int pitchadd = dd.lPitch / 2 - width;
  615. for (line = 0; line < height; line++)
  616. {
  617. for (col = 0; col < width; col++)
  618. {
  619. #undef LIMIT
  620. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  621. y = *py;
  622. yy = y << 8;
  623. u = *pu - 128;
  624. ug = 88 * u;
  625. ub = 454 * u;
  626. v = *pv - 128;
  627. vg = 183 * v;
  628. vr = 359 * v;
  629. unsigned char b = LIMIT(yy + ub);
  630. unsigned char g = LIMIT(yy - ug - vg);
  631. unsigned char r = LIMIT(yy + vr);
  632. *(dst++) = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
  633. py += 2;
  634. if ((col & 1) == 1)
  635. {
  636. pu += 4; // skip yvy every second y
  637. pv += 4; // skip yuy every second y
  638. }
  639. } // ..for col
  640. dst += pitchadd;
  641. } /* ..for line */
  642. }
  643. break;
  644. case 16:
  645. {
  646. // yuy2->rgb16 conversion
  647. //FUCKO: only supports 565
  648. unsigned char *src = (unsigned char *)buf;
  649. unsigned short *dst = (unsigned short *)dd.lpSurface;
  650. int line, col; //, linewidth;
  651. int y, yy;
  652. int u, v;
  653. int vr, ug, vg, ub;
  654. unsigned char *py, *pu, *pv;
  655. //linewidth = width - (width >> 1);
  656. py = src;
  657. pu = src + 1;
  658. pv = src + 3;
  659. int pitchadd = dd.lPitch / 2 - width;
  660. for (line = 0; line < height; line++)
  661. {
  662. for (col = 0; col < width; col++)
  663. {
  664. #undef LIMIT
  665. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  666. y = *py;
  667. yy = y << 8;
  668. u = *pu - 128;
  669. ug = 88 * u;
  670. ub = 454 * u;
  671. v = *pv - 128;
  672. vg = 183 * v;
  673. vr = 359 * v;
  674. unsigned char b = LIMIT(yy + ub);
  675. unsigned char g = LIMIT(yy - ug - vg);
  676. unsigned char r = LIMIT(yy + vr);
  677. *(dst++) = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  678. py += 2;
  679. if ((col & 1))
  680. {
  681. pu += 4; // skip yvy every second y
  682. pv += 4; // skip yuy every second y
  683. }
  684. } // ..for col
  685. dst += pitchadd;
  686. } /* ..for line */
  687. }
  688. break;
  689. case 24:
  690. {
  691. // yuy2->rgb24 conversion
  692. unsigned char *src = (unsigned char *)buf;
  693. unsigned char *dst = (unsigned char *)dd.lpSurface;
  694. int line, col; //, linewidth;
  695. int y, yy;
  696. int u, v;
  697. int vr, ug, vg, ub;
  698. unsigned char *py, *pu, *pv;
  699. //linewidth = width - (width >> 1);
  700. py = src;
  701. pu = src + 1;
  702. pv = src + 3;
  703. int pitchadd = dd.lPitch - (width * 3);
  704. for (line = 0; line < height; line++)
  705. {
  706. for (col = 0; col < width; col++)
  707. {
  708. #undef LIMIT
  709. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  710. y = *py;
  711. yy = y << 8;
  712. u = *pu - 128;
  713. ug = 88 * u;
  714. ub = 454 * u;
  715. v = *pv - 128;
  716. vg = 183 * v;
  717. vr = 359 * v;
  718. *(dst++) = LIMIT(yy + ub);
  719. *(dst++) = LIMIT(yy - ug - vg);
  720. *(dst++) = LIMIT(yy + vr);
  721. py += 2;
  722. if ((col & 1) == 1)
  723. {
  724. pu += 4; // skip yvy every second y
  725. pv += 4; // skip yuy every second y
  726. }
  727. } // ..for col
  728. dst += pitchadd;
  729. } /* ..for line */
  730. }
  731. break;
  732. case 32:
  733. {
  734. // yuy2->rgb32 conversion
  735. unsigned char *src = (unsigned char *)buf;
  736. unsigned char *dst = (unsigned char *)dd.lpSurface;
  737. int line, col; //, linewidth;
  738. int y, yy;
  739. int u, v;
  740. int vr, ug, vg, ub;
  741. unsigned char *py, *pu, *pv;
  742. //linewidth = width - (width >> 1);
  743. py = src;
  744. pu = src + 1;
  745. pv = src + 3;
  746. int pitchadd = dd.lPitch - (width * 4);
  747. for (line = 0; line < height; line++)
  748. {
  749. for (col = 0; col < width; col++)
  750. {
  751. #undef LIMIT
  752. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  753. y = *py;
  754. yy = y << 8;
  755. u = *pu - 128;
  756. ug = 88 * u;
  757. ub = 454 * u;
  758. v = *pv - 128;
  759. vg = 183 * v;
  760. vr = 359 * v;
  761. *dst++ = LIMIT(yy + ub); // b
  762. *dst++ = LIMIT(yy - ug - vg); // g
  763. *dst++ = LIMIT(yy + vr); // r
  764. dst++;
  765. py += 2;
  766. if ((col & 1) == 1)
  767. {
  768. pu += 4; // skip yvy every second y
  769. pv += 4; // skip yuy every second y
  770. }
  771. } // ..for col
  772. dst += pitchadd;
  773. } /* ..for line */
  774. }
  775. break;
  776. }
  777. }
  778. else if (type == VIDEO_MAKETYPE('R', 'G', '2', '4'))
  779. {
  780. //FUCKO: only ->RGB32 conversion supported
  781. switch (m_depth)
  782. {
  783. case 32:
  784. {
  785. if (flip)
  786. nsutil_image_ConvertFlipped_RGB24_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*3, width, height);
  787. else
  788. nsutil_image_Convert_RGB24_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width*3, width, height);
  789. }
  790. break;
  791. }
  792. }
  793. else if (type == VIDEO_MAKETYPE('R', 'G', 'B', '8') && m_palette)
  794. {
  795. unsigned char *d = (unsigned char *)dd.lpSurface;
  796. int pitch = dd.lPitch;
  797. unsigned char *src = (unsigned char *)buf;
  798. int newwidth = (width + 3) & 0xfffc;
  799. src += newwidth * height - 1;
  800. for (int j = 0;j < height;j++)
  801. {
  802. switch (m_depth)
  803. {
  804. case 15:
  805. case 16:
  806. {
  807. unsigned short *dest = (unsigned short *)d;
  808. for (int i = 0;i < newwidth;i++)
  809. {
  810. unsigned char c = src[ -newwidth + 1 + i];
  811. RGBQUAD *rgb = &m_palette[c];
  812. switch (m_depth)
  813. {
  814. case 15: *(dest++) = ((rgb->rgbRed >> 3) << 10) | ((rgb->rgbGreen >> 3) << 5) | (rgb->rgbBlue >> 3); break;
  815. case 16: *(dest++) = ((rgb->rgbRed >> 3) << 11) | ((rgb->rgbGreen >> 2) << 5) | (rgb->rgbBlue >> 3); break;
  816. }
  817. }
  818. }
  819. break;
  820. case 24:
  821. {
  822. unsigned char *dest = d;
  823. for (int i = 0;i < newwidth;i++)
  824. {
  825. unsigned char c = src[ -newwidth + 1 + i];
  826. RGBQUAD *rgb = &m_palette[c];
  827. *dest++ = rgb->rgbBlue;
  828. *dest++ = rgb->rgbGreen;
  829. *dest++ = rgb->rgbRed;
  830. if (m_depth == 32) dest++;
  831. }
  832. }
  833. break;
  834. case 32:
  835. if (flip)
  836. nsutil_image_PaletteFlipped_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width, width, height, (RGB32 *)m_palette);
  837. else
  838. nsutil_image_Palette_RGB32((RGB32 *)dd.lpSurface, dd.lPitch, (const uint8_t *)buf, width, width, height, (RGB32 *)m_palette);
  839. break;
  840. }
  841. d += pitch;
  842. src -= newwidth;
  843. }
  844. }
  845. lpddsOverlay->Unlock(&dd);
  846. HWND hwnd = this->parent;
  847. if (!IsWindow(hwnd)) return ;
  848. // if(GetParent(hwnd)) hwnd=GetParent(hwnd);
  849. Paint(hwnd);
  850. }
  851. void DDrawVideoOutput::timerCallback()
  852. {
  853. //check if the video has been dragged to another monitor
  854. RECT curRect;
  855. getViewport(&curRect, parent, 1, NULL);
  856. if (memcmp(&curRect, &m_monRect, sizeof(RECT)))
  857. needchange = 1;
  858. }
  859. void DDrawVideoOutput::resetSubtitle()
  860. {
  861. m_lastsubtitle = 0;
  862. }
  863. void DDrawVideoOutput::Refresh()
  864. {
  865. // do nothing, we'll refresh on the next frame
  866. }