vid_ddraw.cpp 25 KB

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