vid_ddraw.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. #include "main.h"
  2. #include "vid_ddraw.h"
  3. #include "directdraw.h"
  4. void *frame;
  5. int width, height, flip;
  6. int needchange;
  7. unsigned int type;
  8. LPDIRECTDRAW lpDD;
  9. LPDIRECTDRAWSURFACE lpddsOverlay, lpddsPrimary;
  10. DDCAPS capsDrv;
  11. unsigned int uDestSizeAlign, uSrcSizeAlign;
  12. DWORD dwUpdateFlags;
  13. RECT rs, rd;
  14. RECT lastresizerect;
  15. bool initing;
  16. LPDIRECTDRAWCLIPPER lpddsClipper;
  17. DDPIXELFORMAT m_ddpf;
  18. int m_depth;
  19. RGBQUAD *m_palette;
  20. RECT winRect;
  21. RECT m_monRect;
  22. void getViewport(RECT *r, HWND wnd, int full, RECT *sr);
  23. #define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
  24. DDrawVideoOutput::DDrawVideoOutput() : frame(0), width(0), height(0),
  25. flip(0), type(0), uDestSizeAlign(0),
  26. uSrcSizeAlign(0), dwUpdateFlags(0),
  27. m_depth(0)
  28. {
  29. lpDD = NULL;
  30. lpddsOverlay = NULL;
  31. lastresizerect.bottom = 0;
  32. lastresizerect.top = 0;
  33. lastresizerect.left = 0;
  34. lastresizerect.right = 0;
  35. lpddsPrimary = NULL;
  36. lpddsClipper = NULL;
  37. initing = false;
  38. needchange = 0;
  39. m_palette = NULL;
  40. memset(&winRect, 0, sizeof(winRect));
  41. }
  42. void DDrawVideoOutput::close()
  43. {
  44. // LPDIRECTDRAWSURFACE o=lpddsOverlay;
  45. lpddsOverlay = NULL;
  46. // if(o) o->Release();
  47. //if(lpddsPrimary) lpddsPrimary->Release();
  48. // if(lpddsClipper) lpddsClipper->Release();
  49. if (lpDD) lpDD->Release(); lpDD = 0;// BU added NULL check in response to talkback
  50. // removeFullScreen();
  51. }
  52. DDrawVideoOutput::~DDrawVideoOutput()
  53. {
  54. DDrawVideoOutput::close();
  55. }
  56. void DDrawVideoOutput::drawSubtitle(SubsItem *item)
  57. {
  58. }
  59. int DDrawVideoOutput::create(HWND parent, VideoAspectAdjuster *_adjuster, int w, int h, unsigned int ptype, int flipit, double aspectratio)
  60. {
  61. this->parent = parent;
  62. type = ptype;
  63. width = w;
  64. height = h;
  65. flip = flipit;
  66. adjuster = _adjuster;
  67. initing = true;
  68. HWND hwnd = this->parent;
  69. if (lpDD) lpDD->Release();
  70. lpDD = NULL;
  71. update_monitor_coords();
  72. if (!foundGUID) DDrawCreate(NULL, &lpDD, NULL);
  73. else DDrawCreate(&m_devguid, &lpDD, NULL);
  74. if (!lpDD)
  75. {
  76. initing = false;
  77. return 0;
  78. }
  79. lpDD->SetCooperativeLevel(hwnd, DDSCL_NOWINDOWCHANGES | DDSCL_NORMAL);
  80. DDSURFACEDESC ddsd;
  81. INIT_DIRECTDRAW_STRUCT(ddsd);
  82. ddsd.dwFlags = DDSD_CAPS;
  83. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  84. HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpddsPrimary, NULL );
  85. if (FAILED(ddrval) || !lpddsPrimary)
  86. {
  87. initing=false;
  88. return 0;
  89. }
  90. HRESULT v = -1;
  91. DDSURFACEDESC DDsd = {sizeof(DDsd), };
  92. lpddsPrimary->GetSurfaceDesc(&ddsd);
  93. DDsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; //create the surface at screen depth
  94. DDsd.dwWidth = w;
  95. DDsd.dwHeight = h;
  96. DDsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
  97. if (config_video.ddraw()) v = lpDD->CreateSurface(&DDsd, &lpddsOverlay, NULL);
  98. if (!config_video.ddraw() || FAILED(v))
  99. {
  100. // fall back to system memory if video mem doesn't work
  101. DDsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
  102. v = lpDD->CreateSurface(&DDsd, &lpddsOverlay, NULL);
  103. }
  104. if (FAILED(v))
  105. {
  106. // this video card sucks then :)
  107. lpddsOverlay = NULL;
  108. initing = false;
  109. return 0;
  110. }
  111. // get the depth
  112. m_depth = 8;
  113. INIT_DIRECTDRAW_STRUCT(m_ddpf);
  114. if (lpddsOverlay->GetPixelFormat(&m_ddpf) >= 0)
  115. {
  116. m_depth = m_ddpf.dwRGBBitCount;
  117. if (m_depth == 16 && m_ddpf.dwGBitMask == 0x03e0) m_depth = 15;
  118. }
  119. if (lpDD->CreateClipper(0, &lpddsClipper, NULL) != DD_OK)
  120. {
  121. lpddsOverlay = NULL;
  122. initing = false;
  123. return 0;
  124. }
  125. lpddsClipper->SetHWnd(0, hwnd);
  126. lpddsPrimary->SetClipper(lpddsClipper);
  127. initing = false;
  128. //get current monitor
  129. getViewport(&m_monRect, hwnd, 1, NULL);
  130. return 1;
  131. }
  132. int DDrawVideoOutput::onPaint(HWND hwnd)
  133. {
  134. return 0;
  135. }
  136. void DDrawVideoOutput::displayFrame(const char * /*buf*/, int size, int time)
  137. {
  138. DDSURFACEDESC dd = {sizeof(dd), };
  139. if (config_video.vsync()) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
  140. if (lpddsOverlay->Lock(NULL, &dd, DDLOCK_WAIT, NULL) != DD_OK)
  141. {
  142. needchange = 1;
  143. return ;
  144. }
  145. if (type == VIDEO_MAKETYPE('Y', 'V', '1', '2'))
  146. {
  147. const YV12_PLANES *planes = (YV12_PLANES *)frame;
  148. // convert yv12 to rgb
  149. int bytes = m_depth >> 3;
  150. if (m_depth == 15) bytes = 2;
  151. int i, j, y00, y01, y10, y11, u, v;
  152. unsigned char *pY = (unsigned char *)planes->y.baseAddr;
  153. unsigned char *pU = (unsigned char *)planes->u.baseAddr;
  154. unsigned char *pV = (unsigned char *)planes->v.baseAddr;
  155. unsigned char *pOut = (unsigned char*)dd.lpSurface;
  156. const int rvScale = (int) (2.017 * 65536.0); //91881;
  157. const int gvScale = - (int) (0.392 * 65536.0); // -22553;
  158. const int guScale = - (int) (0.813 * 65536.0); // -46801;
  159. const int buScale = (int) (1.596 * 65536.0); //116129;
  160. const int yScale = (int)( 1.164 * 65536.0 ); //(1.164*65536.0);
  161. int addOut = dd.lPitch * 2 - width * bytes;
  162. int yrb = planes->y.rowBytes;
  163. int addL = dd.lPitch;
  164. /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
  165. #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
  166. if (flip)
  167. {
  168. pOut += (dd.lPitch) * (height - 1);
  169. addOut = -dd.lPitch * 2 - width * bytes;
  170. addL = -addL;
  171. }
  172. for (j = 0; j <= height - 2; j += 2)
  173. {
  174. for (i = 0; i <= width - 2; i += 2)
  175. {
  176. y00 = *pY - 16;
  177. y01 = *(pY + 1) - 16;
  178. y10 = *(pY + yrb) - 16;
  179. y11 = *(pY + yrb + 1) - 16;
  180. u = (*pU++) - 128;
  181. v = (*pV++) - 128;
  182. {
  183. int r, g, b;
  184. g = guScale * v + gvScale * u;
  185. r = buScale * v;
  186. b = rvScale * u;
  187. y00 *= yScale; y01 *= yScale;
  188. y10 *= yScale; y11 *= yScale;
  189. switch (m_depth)
  190. {
  191. case 15:
  192. {
  193. unsigned short *rgb = (unsigned short *)pOut;
  194. rgb[0] = ((LIMIT(r + y00) >> 3) << 10) | ((LIMIT(g + y00) >> 3) << 5) | (LIMIT(b + y00) >> 3);
  195. rgb[1] = ((LIMIT(r + y01) >> 3) << 10) | ((LIMIT(g + y01) >> 3) << 5) | (LIMIT(b + y01) >> 3);
  196. rgb += addL / 2;
  197. rgb[0] = ((LIMIT(r + y10) >> 3) << 10) | ((LIMIT(g + y10) >> 3) << 5) | (LIMIT(b + y10) >> 3);
  198. rgb[1] = ((LIMIT(r + y11) >> 3) << 10) | ((LIMIT(g + y11) >> 3) << 5) | (LIMIT(b + y11) >> 3);
  199. }
  200. break;
  201. case 16:
  202. {
  203. unsigned short *rgb = (unsigned short *)pOut;
  204. rgb[0] = ((LIMIT(r + y00) >> 3) << 11) | ((LIMIT(g + y00) >> 2) << 5) | (LIMIT(b + y00) >> 3);
  205. rgb[1] = ((LIMIT(r + y01) >> 3) << 11) | ((LIMIT(g + y01) >> 2) << 5) | (LIMIT(b + y01) >> 3);
  206. rgb += addL / 2;
  207. rgb[0] = ((LIMIT(r + y10) >> 3) << 11) | ((LIMIT(g + y10) >> 2) << 5) | (LIMIT(b + y10) >> 3);
  208. rgb[1] = ((LIMIT(r + y11) >> 3) << 11) | ((LIMIT(g + y11) >> 2) << 5) | (LIMIT(b + y11) >> 3);
  209. }
  210. break;
  211. case 24:
  212. {
  213. unsigned char *rgb = pOut;
  214. /* Write out top two pixels */
  215. rgb[0] = LIMIT(b + y00); rgb[1] = LIMIT(g + y00); rgb[2] = LIMIT(r + y00);
  216. rgb[3] = LIMIT(b + y01); rgb[4] = LIMIT(g + y01); rgb[5] = LIMIT(r + y01);
  217. /* Skip down to next line to write out bottom two pixels */
  218. rgb += addL;
  219. rgb[0] = LIMIT(b + y10); rgb[1] = LIMIT(g + y10); rgb[2] = LIMIT(r + y10);
  220. rgb[3] = LIMIT(b + y11); rgb[4] = LIMIT(g + y11); rgb[5] = LIMIT(r + y11);
  221. }
  222. break;
  223. case 32:
  224. {
  225. unsigned char *rgb = pOut;
  226. /* Write out top two pixels */
  227. rgb[0] = LIMIT(b + y00); rgb[1] = LIMIT(g + y00); rgb[2] = LIMIT(r + y00);
  228. rgb[4] = LIMIT(b + y01); rgb[5] = LIMIT(g + y01); rgb[6] = LIMIT(r + y01);
  229. /* Skip down to next line to write out bottom two pixels */
  230. rgb += addL;
  231. rgb[0] = LIMIT(b + y10); rgb[1] = LIMIT(g + y10); rgb[2] = LIMIT(r + y10);
  232. rgb[4] = LIMIT(b + y11); rgb[5] = LIMIT(g + y11); rgb[6] = LIMIT(r + y11);
  233. }
  234. break;
  235. }
  236. }
  237. pY += 2;
  238. pOut += 2 * bytes;
  239. }
  240. pY += yrb + yrb - width;
  241. pU += planes->u.rowBytes - width / 2;
  242. pV += planes->v.rowBytes - width / 2;
  243. pOut += addOut;
  244. }
  245. }
  246. else if (type == VIDEO_MAKETYPE('R', 'G', '3', '2'))
  247. {
  248. //FUCKO: do we need to support 8bits depth?
  249. switch (m_depth)
  250. {
  251. case 15:
  252. { // convert RGB32 -> RGB16 (555)
  253. const char *a = (const char *)frame;
  254. char *b = (char *)dd.lpSurface;
  255. int l = width * 4, l2 = dd.lPitch;
  256. int ladj = l;
  257. if (flip) { a += l * (height - 1); ladj = -ladj; }
  258. for (int i = 0;i < height;i++)
  259. {
  260. short *dest = (short *)b;
  261. int *src = (int *)a;
  262. for (int j = 0;j < width;j++)
  263. {
  264. int c = *(src++);
  265. int r = c >> 16;
  266. int g = (c >> 8) & 0xff;
  267. int b = (c) & 0xff;
  268. *(dest++) = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
  269. }
  270. a += ladj; b += l2;
  271. }
  272. }
  273. break;
  274. case 16:
  275. { // convert RGB32 -> RGB16
  276. //FUCKO: this assumes 565
  277. const char *a = (const char *)frame;
  278. char *b = (char *)dd.lpSurface;
  279. int l = width * 4, l2 = dd.lPitch;
  280. int ladj = l;
  281. if (flip) { a += l * (height - 1); ladj = -ladj; }
  282. for (int i = 0;i < height;i++)
  283. {
  284. short *dest = (short *)b;
  285. int *src = (int *)a;
  286. for (int j = 0;j < width;j++)
  287. {
  288. //FUCKO: optimize here
  289. int c = *(src++);
  290. int r = c >> 16;
  291. int g = (c >> 8) & 0xff;
  292. int b = (c) & 0xff;
  293. *(dest++) = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  294. }
  295. a += ladj; b += l2;
  296. }
  297. }
  298. break;
  299. case 24:
  300. { // convert RGB32 -> RGB24
  301. const char *a = (const char *)frame;
  302. char *b = (char *)dd.lpSurface;
  303. int l = width * 4, l2 = dd.lPitch;
  304. int ladj = l;
  305. if (flip) { a += l * (height - 1); ladj = -ladj; }
  306. for (int i = 0;i < height;i++)
  307. {
  308. char *dest = (char *)b;
  309. int *src = (int *)a;
  310. for (int j = 0;j < width;j++)
  311. {
  312. //FUCKO: optimize here
  313. int c = *(src++);
  314. int r = c >> 16;
  315. int g = (c >> 8) & 0xff;
  316. int b = (c) & 0xff;
  317. *dest++ = b;
  318. *dest++ = g;
  319. *dest++ = r;
  320. }
  321. a += ladj; b += l2;
  322. }
  323. }
  324. break;
  325. case 32:
  326. { // straight RGB32 copy
  327. const char *a = (const char *)frame;
  328. char *b = (char *)dd.lpSurface;
  329. int l = width * 4, l2 = dd.lPitch;
  330. int ladj = l;
  331. if (flip) { a += l * (height - 1); ladj = -ladj; }
  332. for (int i = 0;i < height;i++)
  333. {
  334. memcpy(b, a, l);
  335. a += ladj; b += l2;
  336. }
  337. }
  338. break;
  339. }
  340. }
  341. else if (type == VIDEO_MAKETYPE('Y', 'U', 'Y', '2') || type == VIDEO_MAKETYPE('U', 'Y', 'V', 'Y'))
  342. {
  343. //const char *a = (const char *)frame;
  344. //char *b = (char *)dd.lpSurface;
  345. int /*l = width * 2, */l2 = dd.lPitch;
  346. if (flip)
  347. {
  348. //b += (height - 1) * l2;
  349. l2 = -l2;
  350. }
  351. switch (m_depth)
  352. {
  353. case 15:
  354. {
  355. // yuy2->rgb16 (555) conversion
  356. unsigned char *src = (unsigned char *)frame;
  357. unsigned short *dst = (unsigned short *)dd.lpSurface;
  358. int line, col; //, linewidth;
  359. int y, yy;
  360. int u, v;
  361. int vr, ug, vg, ub;
  362. unsigned char *py, *pu, *pv;
  363. //linewidth = width - (width >> 1);
  364. py = src;
  365. pu = src + 1;
  366. pv = src + 3;
  367. int pitchadd = dd.lPitch / 2 - width;
  368. for (line = 0; line < height; line++)
  369. {
  370. for (col = 0; col < width; col++)
  371. {
  372. #undef LIMIT
  373. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  374. y = *py;
  375. yy = y << 8;
  376. u = *pu - 128;
  377. ug = 88 * u;
  378. ub = 454 * u;
  379. v = *pv - 128;
  380. vg = 183 * v;
  381. vr = 359 * v;
  382. unsigned char b = LIMIT(yy + ub );
  383. unsigned char g = LIMIT(yy - ug - vg);
  384. unsigned char r = LIMIT(yy + vr);
  385. *(dst++) = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
  386. py += 2;
  387. if ( (col & 1) == 1)
  388. {
  389. pu += 4; // skip yvy every second y
  390. pv += 4; // skip yuy every second y
  391. }
  392. } // ..for col
  393. dst += pitchadd;
  394. } /* ..for line */
  395. }
  396. break;
  397. case 16:
  398. {
  399. // yuy2->rgb16 conversion
  400. //FUCKO: only supports 565
  401. unsigned char *src = (unsigned char *)frame;
  402. unsigned short *dst = (unsigned short *)dd.lpSurface;
  403. int line, col; //, linewidth;
  404. int y, yy;
  405. int u, v;
  406. int vr, ug, vg, ub;
  407. unsigned char *py, *pu, *pv;
  408. //linewidth = width - (width >> 1);
  409. py = src;
  410. pu = src + 1;
  411. pv = src + 3;
  412. int pitchadd = dd.lPitch / 2 - width;
  413. for (line = 0; line < height; line++)
  414. {
  415. for (col = 0; col < width; col++)
  416. {
  417. #undef LIMIT
  418. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  419. y = *py;
  420. yy = y << 8;
  421. u = *pu - 128;
  422. ug = 88 * u;
  423. ub = 454 * u;
  424. v = *pv - 128;
  425. vg = 183 * v;
  426. vr = 359 * v;
  427. unsigned char b = LIMIT(yy + ub );
  428. unsigned char g = LIMIT(yy - ug - vg);
  429. unsigned char r = LIMIT(yy + vr);
  430. *(dst++) = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  431. py += 2;
  432. if ( (col & 1) )
  433. {
  434. pu += 4; // skip yvy every second y
  435. pv += 4; // skip yuy every second y
  436. }
  437. } // ..for col
  438. dst += pitchadd;
  439. } /* ..for line */
  440. }
  441. break;
  442. case 24:
  443. {
  444. // yuy2->rgb24 conversion
  445. unsigned char *src = (unsigned char *)frame;
  446. unsigned char *dst = (unsigned char *)dd.lpSurface;
  447. int line, col; //, linewidth;
  448. int y, yy;
  449. int u, v;
  450. int vr, ug, vg, ub;
  451. unsigned char *py, *pu, *pv;
  452. //linewidth = width - (width >> 1);
  453. py = src;
  454. pu = src + 1;
  455. pv = src + 3;
  456. int pitchadd = dd.lPitch - (width * 3);
  457. for (line = 0; line < height; line++)
  458. {
  459. for (col = 0; col < width; col++)
  460. {
  461. #undef LIMIT
  462. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  463. y = *py;
  464. yy = y << 8;
  465. u = *pu - 128;
  466. ug = 88 * u;
  467. ub = 454 * u;
  468. v = *pv - 128;
  469. vg = 183 * v;
  470. vr = 359 * v;
  471. *(dst++) = LIMIT(yy + ub );
  472. *(dst++) = LIMIT(yy - ug - vg);
  473. *(dst++) = LIMIT(yy + vr);
  474. py += 2;
  475. if ( (col & 1) == 1)
  476. {
  477. pu += 4; // skip yvy every second y
  478. pv += 4; // skip yuy every second y
  479. }
  480. } // ..for col
  481. dst += pitchadd;
  482. } /* ..for line */
  483. }
  484. break;
  485. case 32:
  486. {
  487. // yuy2->rgb32 conversion
  488. unsigned char *src = (unsigned char *)frame;
  489. unsigned char *dst = (unsigned char *)dd.lpSurface;
  490. int line, col; //, linewidth;
  491. int y, yy;
  492. int u, v;
  493. int vr, ug, vg, ub;
  494. unsigned char *py, *pu, *pv;
  495. //linewidth = width - (width >> 1);
  496. py = src;
  497. pu = src + 1;
  498. pv = src + 3;
  499. int pitchadd = dd.lPitch - (width * 4);
  500. for (line = 0; line < height; line++)
  501. {
  502. for (col = 0; col < width; col++)
  503. {
  504. #undef LIMIT
  505. #define LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
  506. y = *py;
  507. yy = y << 8;
  508. u = *pu - 128;
  509. ug = 88 * u;
  510. ub = 454 * u;
  511. v = *pv - 128;
  512. vg = 183 * v;
  513. vr = 359 * v;
  514. *dst++ = LIMIT(yy + ub ); // b
  515. *dst++ = LIMIT(yy - ug - vg); // g
  516. *dst++ = LIMIT(yy + vr); // r
  517. dst++;
  518. py += 2;
  519. if ( (col & 1) == 1)
  520. {
  521. pu += 4; // skip yvy every second y
  522. pv += 4; // skip yuy every second y
  523. }
  524. } // ..for col
  525. dst += pitchadd;
  526. } /* ..for line */
  527. }
  528. break;
  529. }
  530. }
  531. else if (type == VIDEO_MAKETYPE('R', 'G', '2', '4'))
  532. {
  533. //FUCKO: only ->RGB32 conversion supported
  534. switch (m_depth)
  535. {
  536. case 32:
  537. {
  538. const char *a = (const char *)frame;
  539. char *b = (char *)dd.lpSurface;
  540. int l = width, l2 = dd.lPitch;
  541. int ladj = l * 3;
  542. if (!flip) ladj = 0;
  543. if (flip) { a += (l * 3) * (height - 1); ladj = -(ladj + l * 3); }
  544. l2 -= l * 4;
  545. for (int i = 0;i < height;i++)
  546. {
  547. //memcpy(b,a,l);
  548. for (int j = 0;j < l;j++)
  549. {
  550. b[0] = a[0];
  551. b[1] = a[1];
  552. b[2] = a[2];
  553. b += 4; a += 3;
  554. }
  555. a += ladj; b += l2;
  556. }
  557. }
  558. break;
  559. }
  560. }
  561. else if (type == VIDEO_MAKETYPE('R', 'G', 'B', '8') && m_palette)
  562. {
  563. unsigned char *d = (unsigned char *)dd.lpSurface;
  564. int pitch = dd.lPitch;
  565. unsigned char *src = (unsigned char *)frame;
  566. int newwidth = (width + 3) & 0xfffc;
  567. src += newwidth * height - 1;
  568. for (int j = 0;j < height;j++)
  569. {
  570. switch (m_depth)
  571. {
  572. case 15:
  573. case 16:
  574. {
  575. unsigned short *dest = (unsigned short *)d;
  576. for (int i = 0;i < newwidth;i++)
  577. {
  578. unsigned char c = src[ -newwidth + 1 + i];
  579. RGBQUAD *rgb = &m_palette[c];
  580. switch (m_depth)
  581. {
  582. case 15: *(dest++) = ((rgb->rgbRed >> 3) << 10) | ((rgb->rgbGreen >> 3) << 5) | (rgb->rgbBlue >> 3); break;
  583. case 16: *(dest++) = ((rgb->rgbRed >> 3) << 11) | ((rgb->rgbGreen >> 2) << 5) | (rgb->rgbBlue >> 3); break;
  584. }
  585. }
  586. }
  587. break;
  588. case 24:
  589. case 32:
  590. {
  591. unsigned char *dest = d;
  592. for (int i = 0;i < newwidth;i++)
  593. {
  594. unsigned char c = src[ -newwidth + 1 + i];
  595. RGBQUAD *rgb = &m_palette[c];
  596. *dest++ = rgb->rgbBlue;
  597. *dest++ = rgb->rgbGreen;
  598. *dest++ = rgb->rgbRed;
  599. if (m_depth == 32) dest++;
  600. }
  601. }
  602. break;
  603. }
  604. d += pitch;
  605. src -= newwidth;
  606. }
  607. }
  608. lpddsOverlay->Unlock(&dd);
  609. RECT r;
  610. HWND hwnd = this->parent;
  611. if (!IsWindow(hwnd)) return ;
  612. // if(GetParent(hwnd)) hwnd=GetParent(hwnd);
  613. GetClientRect(hwnd, &r);
  614. RECT fullr = r;
  615. adjuster->adjustAspect(r);
  616. if (r.left != lastresizerect.left || r.right != lastresizerect.right || r.top != lastresizerect.top ||
  617. r.bottom != lastresizerect.bottom)
  618. {
  619. if (r.left != 0)
  620. {
  621. RECT tmp = {0, 0, r.left, fullr.bottom};
  622. InvalidateRect(hwnd, &tmp, TRUE);
  623. }
  624. if (r.right != fullr.right)
  625. {
  626. RECT tmp = {r.right, 0, fullr.right, fullr.bottom};
  627. InvalidateRect(hwnd, &tmp, TRUE);
  628. }
  629. if (r.top != 0)
  630. {
  631. RECT tmp = {r.left, 0, r.right, r.top};
  632. InvalidateRect(hwnd, &tmp, TRUE);
  633. }
  634. if (r.bottom != fullr.bottom)
  635. {
  636. RECT tmp = {r.left, r.bottom, r.right, fullr.bottom};
  637. InvalidateRect(hwnd, &tmp, TRUE);
  638. }
  639. lastresizerect = r;
  640. }
  641. ClientToScreen(hwnd, (LPPOINT)&r);
  642. ClientToScreen(hwnd, ((LPPOINT)&r) + 1);
  643. // transform coords from windows desktop coords (where 0,0==upper-left corner of box encompassing all monitors)
  644. // to the coords for the monitor we're displaying on:
  645. r.left -= m_mon_x;
  646. r.right -= m_mon_x;
  647. r.top -= m_mon_y;
  648. r.bottom -= m_mon_y;
  649. HDC hdc = NULL;
  650. HDC inhdc = NULL;
  651. RECT *pSrcRect = NULL;
  652. {
  653. if (!config_video.ddraw() || lpddsPrimary->Blt(&r, lpddsOverlay, pSrcRect, DDBLT_WAIT, 0) != DD_OK)
  654. {
  655. // as a last resort, BitBlt().
  656. if (lpddsOverlay->GetDC(&inhdc) != DD_OK)
  657. {
  658. needchange = 1;
  659. return ;
  660. }
  661. if (lpddsPrimary->GetDC(&hdc) != DD_OK)
  662. {
  663. lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL;
  664. needchange = 1;
  665. return ;
  666. }
  667. int src_w = width;
  668. int src_h = pSrcRect ? (pSrcRect->bottom - pSrcRect->top) : height;
  669. if (r.right - r.left == src_w && r.bottom - r.top == src_h)
  670. BitBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, SRCCOPY);
  671. else
  672. StretchBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, inhdc, 0, 0, src_w, src_h, SRCCOPY);
  673. }
  674. }
  675. if (hdc) { lpddsPrimary->ReleaseDC(hdc); hdc = NULL; }
  676. if (inhdc) { lpddsOverlay->ReleaseDC(inhdc); inhdc = NULL; }
  677. }
  678. void DDrawVideoOutput::timerCallback()
  679. {
  680. //check if the video has been dragged to another monitor
  681. RECT curRect;
  682. getViewport(&curRect, parent, 1, NULL);
  683. if (memcmp(&curRect, &m_monRect, sizeof(RECT)))
  684. needchange = 1;
  685. }
  686. void DDrawVideoOutput::resetSubtitle()
  687. {
  688. }
  689. void DDrawVideoOutput::Refresh()
  690. {
  691. // do nothing, we'll refresh on the next frame
  692. }