VideoRenderer.cpp
上传用户:lusi_8715
上传日期:2007-01-08
资源大小:199k
文件大小:31k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************************
  2.  *                                                                                    *
  3.  * This application contains code from OpenDivX and is released as a "Larger Work"    *
  4.  * under that license. Consistant with that license, this application is released     *
  5.  * under the GNU General Public License.                                              *
  6.  *                                                                                    *
  7.  * The OpenDivX license can be found at: http://www.projectmayo.com/opendivx/docs.php *
  8.  * The GPL can be found at: http://www.gnu.org/copyleft/gpl.html                      *
  9.  *                                                                                    *
  10.  * Copyright (c) 2001 - Project Mayo                                                  *
  11.  *                                                                                    *
  12.  * Authors: Damien Chavarria <adrc at projectmayo.com>                                *
  13.  *                                                                                    *
  14.  **************************************************************************************/
  15. #include "VideoRenderer.h"
  16. /*
  17.  * Functions
  18.  */
  19. VideoRenderer::VideoRenderer()
  20. {
  21. /*
  22.  * By default, no filtering
  23.  */
  24. this->use_bilinear          = 0;
  25. this->fullscreen            = 0;
  26. this->change_fullscreen_res = 0;
  27. /*
  28.  * init DX pointers
  29.  */
  30. lpDD         = NULL;
  31. lpDDSPrimary = NULL;
  32. lpDDSBack    = NULL;
  33. lpDDSImage   = NULL;
  34. lpD3D        = NULL;
  35. lpDevice     = NULL;
  36. lpDDClipper  = NULL;
  37. }
  38. /*
  39.  * Sets the use of bilinear
  40.  * filtering
  41.  */
  42. int VideoRenderer::SetBilinear(int use_bilinear)
  43. {
  44. this->use_bilinear = use_bilinear;
  45. return 1;
  46. }
  47. /*
  48.  * Set Force of Fullscreen Resolution
  49.  *
  50.  */
  51. int VideoRenderer::SetChangeFullscreenRes(int change_full)
  52. {
  53. this->change_fullscreen_res = change_full;
  54. return 1;
  55. }
  56. /*
  57.  * Open the device
  58.  *
  59.  */
  60. int VideoRenderer::Open(HWND hwnd, BITMAPINFOHEADER *bih)
  61. {
  62. if(hwnd && bih) {
  63. this->hwnd = hwnd;
  64. this->bih  = bih;
  65. if(this->use_bilinear) {
  66. this->ddrval = DirectDrawCreateEx(NULL, (void **) &this->lpDD, IID_IDirectDraw7, NULL);
  67. if(ddrval != DD_OK) {
  68. MessageBox(NULL, "This version of the "Playah" requires DirectX 7.0", "Fatal Error", MB_OK);
  69. return 0;
  70. }
  71. ddrval = lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
  72.     if(ddrval != DD_OK) {
  73.     MessageBox(hwnd, "Error intializing Cooperative Level", "Fatal Error", MB_OK); 
  74. return 0;
  75. }
  76.     memset( &ddsd, 0, sizeof(ddsd) );
  77. ddsd.dwSize = sizeof( ddsd );
  78.     ddsd.dwFlags           = DDSD_CAPS;
  79. ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE;
  80.     ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
  81.     if(ddrval != DD_OK) {
  82. return 0;
  83. }
  84.     /*
  85.  * Now set Clipping
  86.  */
  87.     ddrval = lpDD->CreateClipper(0, &lpDDClipper, NULL);
  88. if(ddrval != DD_OK) {
  89. MessageBox(hwnd, "Error Creating Clipper", "Fatal Error", MB_OK); 
  90. return 0;
  91. }
  92.     ddrval = lpDDClipper->SetHWnd(0, hwnd);
  93. if(ddrval != DD_OK) {
  94. MessageBox(hwnd, "Error Assigning Clipper", "Fatal Error", MB_OK); 
  95. return 0;
  96. }
  97.    ddrval = lpDDSPrimary->SetClipper(lpDDClipper);
  98. if(ddrval != DD_OK) {
  99. MessageBox(hwnd, "Error Assigning Clipper to Surface", "Fatal Error", MB_OK); 
  100. return 0;
  101. }
  102.            /*
  103. * Finally Create Back Surface
  104. */
  105.     
  106. ZeroMemory(&ddsd, sizeof(ddsd));
  107.     
  108. ddsd.dwSize   = sizeof(ddsd);
  109. ddsd.dwFlags  = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; 
  110. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
  111. ddsd.dwWidth  = 1920;
  112. ddsd.dwHeight = 1440;
  113. if (lpDD->CreateSurface(&ddsd, &lpDDSBack, NULL) != DD_OK) {
  114.     
  115. MessageBox(NULL, "Problem with back surface", "", MB_OK);
  116. return 0;
  117. }
  118. /*
  119.      * Now the 3D part
  120.     */
  121. ddrval = lpDD->QueryInterface(IID_IDirect3D7, (LPVOID *) &this->lpD3D);
  122. if(ddrval != DD_OK) {
  123. MessageBox(NULL, "Cannot init Direct3D", "", MB_OK);
  124. }
  125. if (lpD3D->CreateDevice(IID_IDirect3DTnLHalDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  126. if (lpD3D->CreateDevice(IID_IDirect3DHALDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  127. if (lpD3D->CreateDevice(IID_IDirect3DMMXDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  128. if (lpD3D->CreateDevice(IID_IDirect3DRGBDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  129. MessageBox(NULL, "Could not create any 3D device", "Error", MB_OK);
  130. return 0;
  131. }
  132. }
  133. }
  134. }
  135. D3DVIEWPORT7 view;
  136. view.dwX=0;
  137. view.dwY=0; 
  138. view.dwWidth=1920;
  139. view.dwHeight=1440; 
  140. view.dvMinZ=0.0f;
  141. view.dvMaxZ=1.0f;
  142. lpDevice->SetViewport(& view);
  143. /*
  144.  * AND request filtering
  145. */
  146. lpDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
  147. lpDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_LINEAR);
  148. /*
  149.  * Create the texture surface
  150.  *
  151.  */
  152. ZeroMemory(&ddsd, sizeof(ddsd));
  153.     
  154. ddsd.dwSize = sizeof(ddsd);
  155. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; 
  156. ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
  157. ddsd.dwWidth = bih->biWidth;
  158. ddsd.dwHeight = bih->biHeight;
  159. if (lpDD->CreateSurface(&ddsd, &lpDDSImage, NULL) != DD_OK) {
  160.     
  161. MessageBox(NULL, "Problem with image surface", "", MB_OK);
  162. return 0;
  163. }
  164. /*
  165.  * Check for capabilities
  166.  */
  167. D3DDEVICEDESC7 ddDesc;
  168. lpDevice->GetCaps(&ddDesc);
  169. if (ddDesc.deviceGUID==IID_IDirect3DHALDevice || ddDesc.deviceGUID==IID_IDirect3DTnLHalDevice) {
  170. ddsd.ddsCaps.dwCaps2=DDSCAPS2_TEXTUREMANAGE;
  171. }
  172. else {
  173. ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  174. }
  175. /*
  176.  * Check for old cards problems
  177. */
  178. if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ) {
  179. for (ddsd.dwWidth=1; bih->biWidth > ddsd.dwWidth; ddsd.dwWidth <<= 1);
  180. for (ddsd.dwHeight=1; bih->biHeight > ddsd.dwHeight; ddsd.dwHeight <<= 1);
  181. }
  182. if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
  183. if (ddsd.dwWidth > ddsd.dwHeight )
  184. ddsd.dwHeight=ddsd.dwWidth;
  185. else
  186. ddsd.dwWidth=ddsd.dwHeight;
  187. }
  188. if (lpDD->CreateSurface(&ddsd, &lpDDSImage, NULL) != DD_OK) {
  189.     
  190. MessageBox(NULL, "Problem with back surface", "", MB_OK);
  191. return 0;
  192. }
  193. lpDDSImage->Restore();
  194. lpDevice->SetTexture(0, lpDDSImage);
  195. }
  196. else {
  197. /*
  198.  * No 3D/filtering here!
  199.  */
  200. this->ddrval = DirectDrawCreateEx(NULL, (void **) &this->lpDD, IID_IDirectDraw7, NULL);
  201. if(ddrval != DD_OK) {
  202. MessageBox(NULL, "Couldn't initialize DirectDraw", "", MB_OK);
  203. return 0;
  204. }
  205. ddrval = lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
  206.     if(ddrval != DD_OK) {
  207.         MessageBox(hwnd, "Error intializing Cooperative Level", "Fatal Error", MB_OK); 
  208. return 0;
  209. }
  210. memset( &ddsd, 0, sizeof(ddsd) );
  211.     ddsd.dwSize = sizeof( ddsd );
  212.     ddsd.dwFlags           = DDSD_CAPS;
  213. ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
  214.     ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
  215.     if(ddrval != DD_OK ) {
  216. return 0;
  217. }
  218.     /*
  219.  * Now set Clipping
  220.  */
  221.     ddrval = lpDD->CreateClipper(0, &lpDDClipper, NULL);
  222.     if(ddrval != DD_OK) {
  223.         MessageBox(hwnd, "Error Creating Clipper", "Fatal Error", MB_OK); 
  224.    return 0;
  225. }
  226.     ddrval = lpDDClipper->SetHWnd(0, hwnd);
  227.     if(ddrval != DD_OK) {
  228.         MessageBox(hwnd, "Error Assigning Clipper", "Fatal Error", MB_OK); 
  229.     return 0;
  230. }
  231.     ddrval = lpDDSPrimary->SetClipper(lpDDClipper);
  232.     if(ddrval != DD_OK) {
  233.   MessageBox(hwnd, "Error Assigning Clipper to Surface", "Fatal Error", MB_OK); 
  234.   return 0;
  235. }
  236. /*
  237.  * Finally Create Back Surface and BITMAP
  238. */
  239. ZeroMemory(&ddsd, sizeof(ddsd));
  240.     
  241. ddsd.dwSize = sizeof(ddsd);
  242. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  243. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  244.     ddsd.dwWidth  = bih->biWidth;
  245. ddsd.dwHeight = bih->biHeight;
  246. if (lpDD->CreateSurface(&ddsd, &lpDDSBack, NULL) != DD_OK) {
  247. MessageBox(NULL, "Cannot create back buffer!", "", MB_OK);
  248. return 0;
  249. }
  250. }
  251. }
  252. return 1;
  253. }
  254. VideoRenderer::~VideoRenderer()
  255. {
  256. }
  257. /*
  258.  * Setup the two modes in fullscreen
  259.  *
  260.  */
  261. int VideoRenderer::OpenFullscreen(HWND hwnd, BITMAPINFOHEADER *bih)
  262. {
  263. this->hwnd = hwnd;
  264. this->bih  = bih;
  265. if(this->use_bilinear) {
  266. this->ddrval = DirectDrawCreateEx(NULL, (void **) &this->lpDD, IID_IDirectDraw7, NULL);
  267. if(ddrval != DD_OK) {
  268. return 0;
  269. }
  270. ddrval = lpDD->SetCooperativeLevel(this->hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  271. if(ddrval != DD_OK) {
  272. MessageBox(NULL, "cannot get exclusive mode!", "", MB_OK);
  273. return 0;
  274. }
  275. /*
  276.  * Check if display mode has been forced
  277.  *
  278.  */
  279. if(this->change_fullscreen_res == 0) {
  280. DDSURFACEDESC2 ddDesc;
  281. memset(&ddDesc, 0, sizeof(DDSURFACEDESC2));
  282. ddDesc.dwSize = sizeof(DDSURFACEDESC2);
  283. /*
  284.  * We need to know witch resolution
  285.  * we are in...
  286.  */
  287. ddrval = lpDD->GetDisplayMode(&ddDesc);
  288. if(ddrval != DD_OK) {
  289. MessageBox(hwnd, "DirectDraw: Cannot get Display Resolution", "", MB_OK);
  290. return 0;
  291. }
  292. ddrval = lpDD->SetDisplayMode( ddDesc.dwWidth, ddDesc.dwHeight, ddDesc.ddpfPixelFormat.dwRGBBitCount, 0, 0 );
  293. if(ddrval == DD_OK) {
  294. screen_size_x = ddDesc.dwWidth;
  295. screen_size_y = ddDesc.dwHeight;
  296. goto done;
  297. }
  298. return 0;
  299. }
  300. else {
  301. /*
  302.  * We need to find the best display mode
  303.    *
  304.  */
  305. screen_size_x = 320;
  306. screen_size_y = 200;
  307. if(bih->biWidth <= 320 && bih->biHeight <= 200) {
  308. ddrval = lpDD->SetDisplayMode( 320, 200, 16, 0, 0 );
  309. if(ddrval == DD_OK) {
  310. goto done;
  311. }
  312. else {
  313. ddrval = lpDD->SetDisplayMode( 320, 200, 32, 0, 0 );
  314. if(ddrval == DD_OK) {
  315. goto done;
  316. }
  317. }
  318. }
  319. if(bih->biWidth <= 400 && bih->biHeight <= 300) {
  320. ddrval = lpDD->SetDisplayMode( 400, 300, 16, 0, 0 );
  321. if(ddrval == DD_OK) {
  322. screen_size_x = 400;
  323. screen_size_y = 300;
  324. goto done;
  325. }
  326. else {
  327. ddrval = lpDD->SetDisplayMode( 400, 300, 32, 0, 0 );
  328. if(ddrval == DD_OK) {
  329. screen_size_x = 400;
  330. screen_size_y = 300;
  331. goto done;
  332. }
  333. }
  334. }
  335. if(bih->biWidth <= 640 && bih->biHeight <= 480) {
  336. ddrval = lpDD->SetDisplayMode( 640, 480, 16, 0, 0 );
  337. if(ddrval == DD_OK) {
  338. screen_size_x = 640;
  339. screen_size_y = 480;
  340. goto done;
  341. }
  342. else {
  343. ddrval = lpDD->SetDisplayMode( 640, 480, 32, 0, 0 );
  344. if(ddrval == DD_OK) {
  345. screen_size_x = 640;
  346. screen_size_y = 480;
  347. goto done;
  348. }
  349. }
  350. }
  351. if(bih->biWidth <= 800 && bih->biHeight <= 600) {
  352. ddrval = lpDD->SetDisplayMode( 800, 600, 16, 0, 0 );
  353. if(ddrval == DD_OK) {
  354. screen_size_x = 800;
  355. screen_size_y = 600;
  356. goto done;
  357. }
  358. else {
  359. ddrval = lpDD->SetDisplayMode( 800, 600, 32, 0, 0 );
  360. if(ddrval == DD_OK) {
  361. screen_size_x = 800;
  362. screen_size_y = 600;
  363. goto done;
  364. }
  365. }
  366. }
  367. if(bih->biWidth <= 1024 && bih->biHeight <= 768) {
  368. ddrval = lpDD->SetDisplayMode( 1024, 768, 16, 0, 0 );
  369. if(ddrval == DD_OK) {
  370. screen_size_x = 1024;
  371. screen_size_y = 768;
  372. goto done;
  373. }
  374. else {
  375. ddrval = lpDD->SetDisplayMode( 1024, 768, 32, 0, 0 );
  376. if(ddrval == DD_OK) {
  377. screen_size_x = 1024;
  378. screen_size_y = 768;
  379. goto done;
  380. }
  381. }
  382. }
  383. }
  384. done:
  385. if(ddrval != DD_OK) {
  386.    MessageBox(hwnd, "Error intializing Cooperative Level", "Fatal Error", MB_OK); 
  387. return 0;
  388. }
  389. memset( &ddsd, 0, sizeof(ddsd) );
  390. ddsd.dwSize = sizeof( ddsd );
  391. ddsd.dwFlags           = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  392. ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
  393. ddsd.dwBackBufferCount = 1;
  394.     ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
  395.     if(ddrval != DD_OK) {
  396.     MessageBox(hwnd, "Error Creating Surface 3", "Fatal Error", MB_OK); 
  397. return 0;
  398. }
  399. DDSCAPS2 ddscaps;
  400. ZeroMemory(&ddscaps, sizeof(ddscaps));
  401. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  402. ddrval         = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
  403. /*
  404.  * Now the 3D part
  405.  */
  406. ddrval = lpDD->QueryInterface(IID_IDirect3D7, (LPVOID *) &this->lpD3D);
  407. if(ddrval != DD_OK) {
  408. MessageBox(NULL, "Cannot init Direct3D", "", MB_OK);
  409. }
  410. if (lpD3D->CreateDevice(IID_IDirect3DTnLHalDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  411. if (lpD3D->CreateDevice(IID_IDirect3DHALDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  412. if (lpD3D->CreateDevice(IID_IDirect3DMMXDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  413. if (lpD3D->CreateDevice(IID_IDirect3DRGBDevice, lpDDSBack, &lpDevice) != D3D_OK) {
  414. MessageBox(NULL, "Could not create any 3D device", "Error", MB_OK);
  415. return 0;
  416. }
  417. }
  418. }
  419. }
  420. D3DVIEWPORT7 view;
  421. view.dwX=0;
  422. view.dwY=0; 
  423. view.dwWidth=screen_size_x;
  424. view.dwHeight=screen_size_y; 
  425. view.dvMinZ=0.0f;
  426. view.dvMaxZ=1.0f;
  427. lpDevice->SetViewport(& view);
  428. /*
  429.  * AND request filtering
  430.  */
  431. lpDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
  432. lpDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFG_LINEAR);
  433. /*
  434.  * now create the image surface
  435.  *
  436.  */
  437. ZeroMemory(&ddsd, sizeof(ddsd));
  438.     
  439. ddsd.dwSize = sizeof(ddsd);
  440. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  441. ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
  442. ddsd.dwWidth  = bih->biWidth;
  443. ddsd.dwHeight = bih->biHeight;
  444. D3DDEVICEDESC7 ddDesc;
  445. lpDevice->GetCaps(&ddDesc);
  446. if (ddDesc.deviceGUID==IID_IDirect3DHALDevice || ddDesc.deviceGUID==IID_IDirect3DTnLHalDevice) {
  447. ddsd.ddsCaps.dwCaps2=DDSCAPS2_TEXTUREMANAGE;
  448. }
  449. else {
  450. ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  451. }
  452. /*
  453.  * Check for old cards problems
  454.  */
  455. if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ) {
  456. for (ddsd.dwWidth=1; bih->biWidth > ddsd.dwWidth; ddsd.dwWidth <<= 1);
  457. for (ddsd.dwHeight=1; bih->biHeight > ddsd.dwHeight; ddsd.dwHeight <<= 1);
  458. }
  459. if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
  460. if (ddsd.dwWidth > ddsd.dwHeight )
  461. ddsd.dwHeight=ddsd.dwWidth;
  462. else
  463. ddsd.dwWidth=ddsd.dwHeight;
  464. }
  465. if (lpDD->CreateSurface(&ddsd, &lpDDSImage, NULL) != DD_OK) {
  466. MessageBox(NULL, "Cannot create back buffer!", "", MB_OK);
  467. return 0;
  468. }
  469. /*
  470.  * and the pixels
  471.  *
  472.  */
  473. video_width   = screen_size_x;
  474. video_height  = bih->biHeight*screen_size_x/bih->biWidth;
  475. lpDevice->SetTexture(0, lpDDSImage);
  476. }
  477. else {
  478. /*
  479.  * No 3D here!
  480.  */
  481. this->hwnd = hwnd;
  482. this->bih  = bih;
  483. this->ddrval = DirectDrawCreateEx(NULL, (void **) &this->lpDD, IID_IDirectDraw7, NULL);
  484. if(ddrval != DD_OK) {
  485. return 0;
  486. }
  487. ddrval = lpDD->SetCooperativeLevel(this->hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  488. if(ddrval != DD_OK) {
  489. MessageBox(NULL, "cannot get exclusive mode!", "", MB_OK);
  490. return 0;
  491. }
  492. if(this->change_fullscreen_res == 0) {
  493. DDSURFACEDESC2 ddDesc;
  494. memset(&ddDesc, 0, sizeof(DDSURFACEDESC2));
  495. ddDesc.dwSize = sizeof(DDSURFACEDESC2);
  496. /*
  497.  * We need to know witch resolution
  498.  * we are in...
  499.  */
  500. ddrval = lpDD->GetDisplayMode(&ddDesc);
  501. if(ddrval != DD_OK) {
  502. MessageBox(hwnd, "DirectDraw: Cannot get Display Resolution", "", MB_OK);
  503. return 0;
  504. }
  505. ddrval = lpDD->SetDisplayMode( ddDesc.dwWidth, ddDesc.dwHeight, ddDesc.ddpfPixelFormat.dwRGBBitCount, 0, 0 );
  506. if(ddrval == DD_OK) {
  507. screen_size_x = ddDesc.dwWidth;
  508. screen_size_y = ddDesc.dwHeight;
  509. goto done;
  510. }
  511. return 0;
  512. }
  513. else {
  514.    /*
  515.  * We need to find the best display mode
  516.    *
  517.  */
  518. screen_size_x = 320;
  519. screen_size_y = 200;
  520. if(bih->biWidth <= 320 && bih->biHeight <= 200) {
  521. ddrval = lpDD->SetDisplayMode( 320, 200, 16, 0, 0 );
  522. if(ddrval == DD_OK) {
  523. goto done2;
  524. }
  525. else {
  526. ddrval = lpDD->SetDisplayMode( 320, 200, 32, 0, 0 );
  527. if(ddrval == DD_OK) {
  528. goto done2;
  529. }
  530. }
  531. }
  532. if(bih->biWidth <= 400 && bih->biHeight <= 300) {
  533. ddrval = lpDD->SetDisplayMode( 400, 300, 16, 0, 0 );
  534. if(ddrval == DD_OK) {
  535. screen_size_x = 400;
  536. screen_size_y = 300;
  537. goto done2;
  538. }
  539. else {
  540. ddrval = lpDD->SetDisplayMode( 400, 300, 32, 0, 0 );
  541. if(ddrval == DD_OK) {
  542. screen_size_x = 400;
  543. screen_size_y = 300;
  544. goto done2;
  545. }
  546. }
  547. }
  548. if(bih->biWidth <= 640 && bih->biHeight <= 480) {
  549. ddrval = lpDD->SetDisplayMode( 640, 480, 16, 0, 0 );
  550. if(ddrval == DD_OK) {
  551. screen_size_x = 640;
  552. screen_size_y = 480;
  553. goto done2;
  554. }
  555. else {
  556. ddrval = lpDD->SetDisplayMode( 640, 480, 32, 0, 0 );
  557. if(ddrval == DD_OK) {
  558. screen_size_x = 640;
  559. screen_size_y = 480;
  560. goto done2;
  561. }
  562. }
  563. }
  564. if(bih->biWidth <= 800 && bih->biHeight <= 600) {
  565. ddrval = lpDD->SetDisplayMode( 800, 600, 16, 0, 0 );
  566. if(ddrval == DD_OK) {
  567. screen_size_x = 800;
  568. screen_size_y = 600;
  569. goto done2;
  570. }
  571. else {
  572. ddrval = lpDD->SetDisplayMode( 800, 600, 32, 0, 0 );
  573. if(ddrval == DD_OK) {
  574. screen_size_x = 800;
  575. screen_size_y = 600;
  576. goto done2;
  577. }
  578. }
  579. }
  580. if(bih->biWidth <= 1024 && bih->biHeight <= 768) {
  581. ddrval = lpDD->SetDisplayMode( 1024, 768, 16, 0, 0 );
  582. if(ddrval == DD_OK) {
  583. screen_size_x = 1024;
  584. screen_size_y = 768;
  585. goto done2;
  586. }
  587. else {
  588. ddrval = lpDD->SetDisplayMode( 1024, 768, 32, 0, 0 );
  589. if(ddrval == DD_OK) {
  590. screen_size_x = 1024;
  591. screen_size_y = 768;
  592. goto done2;
  593. }
  594. }
  595. }
  596.     }
  597. done2:
  598. if(ddrval != DD_OK) {
  599.    MessageBox(hwnd, "Error intializing Cooperative Level", "Fatal Error", MB_OK); 
  600. return 0;
  601. }
  602. memset( &ddsd, 0, sizeof(ddsd) );
  603. ddsd.dwSize = sizeof( ddsd );
  604. ddsd.dwFlags           = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  605. ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  606. ddsd.dwBackBufferCount = 1;
  607.     ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
  608.     if(ddrval != DD_OK) {
  609.     MessageBox(hwnd, "Error Creating Surface 4", "Fatal Error", MB_OK); 
  610. return 0;
  611. }
  612. DDSCAPS2 ddscaps;
  613. ZeroMemory(&ddscaps, sizeof(ddscaps));
  614. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  615. ddrval         = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
  616. /*
  617.  * now create the image surface
  618.  *
  619.  */
  620. ZeroMemory(&ddsd, sizeof(ddsd));
  621.     
  622. ddsd.dwSize = sizeof(ddsd);
  623. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  624. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  625. ddsd.dwWidth  = bih->biWidth;
  626. ddsd.dwHeight = bih->biHeight;
  627. if (lpDD->CreateSurface(&ddsd, &lpDDSImage, NULL) != DD_OK) {
  628. MessageBox(NULL, "Cannot create back buffer!", "", MB_OK);
  629. return 0;
  630. }
  631. /*
  632.  * and the pixels
  633.  *
  634.  */
  635. video_width   = screen_size_x;
  636. video_height  = bih->biHeight*screen_size_x/bih->biWidth;
  637. }
  638. return 1;
  639. }
  640. BOOL VideoRenderer::restoreAll( void )
  641. {
  642.     return lpDDSPrimary->Restore() == DD_OK &&
  643.            lpDDSBack->Restore() == DD_OK;
  644. }
  645. int VideoRenderer::Fullscreen(int onOff)
  646. {
  647. if(!this->fullscreen && onOff) {
  648. /*
  649.  * we're going to fullscreen
  650.  */
  651. this->Close();
  652. this->OpenFullscreen(this->hwnd, this->bih);
  653. this->fullscreen = TRUE;
  654. }
  655. else {
  656. if(this->fullscreen && !onOff) {
  657. this->Close();
  658. this->Open(this->hwnd, this->bih);
  659. this->fullscreen = FALSE;
  660. }
  661. }
  662. return 1;
  663. }
  664. /*
  665.  * Set/Get the video modes
  666.  */
  667. int VideoRenderer::GetVideoMode() {
  668. DDSURFACEDESC2  desc;
  669. int mode = 0, result = VIDEO_MODE_ERROR;
  670. if(this->use_bilinear ) {
  671. /*
  672.  * Lock the surface
  673.  */
  674. ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
  675. desc.dwSize = sizeof(DDSURFACEDESC2);
  676. this->lpDDSImage->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  677. mode = desc.ddpfPixelFormat.dwRGBBitCount;
  678. this->lpDDSImage->Unlock(NULL);
  679. }
  680. else {
  681. ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
  682. desc.dwSize = sizeof(DDSURFACEDESC2);
  683. this->lpDDSBack->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  684. mode = desc.ddpfPixelFormat.dwRGBBitCount;
  685. this->lpDDSBack->Unlock(NULL);
  686. }
  687. switch(mode) {
  688. case 16:
  689. result = VIDEO_MODE_RGB16;
  690. break;
  691. case 24:
  692. result = VIDEO_MODE_RGB24;
  693. break;
  694. case 32:
  695. result = VIDEO_MODE_RGB32;
  696. break;
  697. default:
  698. break;
  699. }
  700. return result;
  701. }
  702. int VideoRenderer::SetCodecVideoMode(int depth) {
  703. this->codecDepth = depth;
  704. return 1;
  705. }
  706. /*
  707.  * Performs all needed 
  708.  * video conversions
  709.  *
  710.  */
  711. int VideoRenderer::copyPixels(void *src, void *dst, int in_depth, int out_depth, int width, int height, int pitch) {
  712. int i, j, line;
  713. switch(out_depth) {
  714. case 16:
  715. switch(in_depth) {
  716. case VIDEO_MODE_RGB16:
  717. line = 2*width;
  718. for(i=0; i < height; i++) {
  719. memcpy((void *) ((char *) dst + pitch*(height - i - 1)), 
  720.    (void *) ((char *) src + i*line), line);
  721. }
  722. break;
  723. default:
  724. char  *_src = (char  *) src;
  725. short *_dst = (short *) dst;
  726. for(j = 0; j < height; j++) {
  727. for(i = 0; i < width; i++) {
  728.       char r = *_src++;
  729.           char g = *_src++;
  730.   char b = *_src++;
  731.               *(_dst + pitch/2*(height - j - 1) + i) = ( (r & 0xF8) >> 3)  |
  732.            ( (g & 0xFC) << 3 ) |
  733.    ( (b & 0xF8) << 8 );
  734. }
  735. }
  736. break;
  737. }
  738. break;
  739. case 24:
  740. /*
  741.  * in_depth will always be 24
  742.  */
  743. line = 3*width;
  744. for(j = 0; j < height; j++) {
  745. memcpy((char *) dst + pitch*(height - j - 1),
  746.    (char *) src + line*j, line);
  747. }
  748. break;
  749. case 32:
  750. switch(in_depth) {
  751. case VIDEO_MODE_RGB24:
  752. for(j = 0; j < height; j++) {
  753. for(i = 0; i < width; i++) {
  754. memcpy((char *) dst + pitch*(height - j - 1) + 4*i,
  755.    (char *) src + 3*width*j + (3*i),
  756.    3);
  757. }
  758. }
  759. break;
  760. case VIDEO_MODE_RGB32:
  761. line = 4*width;
  762. for(j = 0; j < height; j++) {
  763. memcpy((char *) dst + pitch*(height - j - 1),
  764.    (char *) src + line*j, line);
  765. }
  766. break;
  767. }
  768. break;
  769. default:
  770. break;
  771. }
  772. return 0;
  773. }
  774. /*
  775.  * Draws in Fullscreen
  776.  *
  777.  */
  778. int VideoRenderer::DrawFullscreen(char *buffer)
  779. {
  780. DDSURFACEDESC2  desc;
  781. long i, j;
  782. if(buffer != NULL) {
  783. if(this->use_bilinear ) {
  784. /*
  785.  * Lock the surface
  786.  */
  787. ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
  788. desc.dwSize = sizeof(DDSURFACEDESC2);
  789. this->lpDDSImage->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  790. /*
  791.  * Copy the pixels
  792.  */
  793. this->copyPixels(buffer, desc.lpSurface, this->codecDepth, desc.ddpfPixelFormat.dwRGBBitCount, bih->biWidth, bih->biHeight, desc.lPitch);
  794. this->lpDDSImage->Unlock(NULL);
  795. /*
  796.  * Now Blit to the window
  797.  */
  798. DDBLTFX bltfx;
  799. ZeroMemory(&bltfx, sizeof(bltfx)); // Sets dwFillColor to 0 as well
  800. bltfx.dwSize = sizeof(bltfx);
  801. lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &bltfx);
  802. if(this->hwnd) {
  803. D3DTLVERTEX square1[4];
  804. square1[0] = D3DTLVERTEX(D3DVECTOR(0, (screen_size_y - video_height)/2, 0), 1.0, RGBA_MAKE(255,255,255,255),0, 0.0, 0.0);
  805. square1[1] = D3DTLVERTEX(D3DVECTOR(screen_size_x, (screen_size_y - video_height)/2, 0), 1.0, RGBA_MAKE(255,255,255,255),0, (float)bih->biWidth/(float)desc.dwWidth, 0.0);
  806. square1[2] = D3DTLVERTEX(D3DVECTOR(0,  (screen_size_y - video_height)/2 + video_height, 0.0), 1.0, RGBA_MAKE(255,255,255,255),0, 0.0, (float)bih->biHeight/(float)desc.dwHeight);
  807. square1[3] = D3DTLVERTEX(D3DVECTOR(screen_size_x, (screen_size_y - video_height)/2 + video_height, 0.0), 1.0, RGBA_MAKE(255,255,255,255),0, (float)bih->biWidth/(float)desc.dwWidth, (float)bih->biHeight/(float)desc.dwHeight);
  808. if( SUCCEEDED( lpDevice->BeginScene() ) ) {
  809. lpDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, square1, 4, 0);
  810. lpDevice->EndScene();
  811. }
  812. }
  813. }
  814. else {
  815. ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
  816. desc.dwSize = sizeof(DDSURFACEDESC2);
  817. this->lpDDSImage->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  818. /*
  819.  * Copy the pixels
  820.  */
  821. this->copyPixels(buffer, desc.lpSurface, this->codecDepth, desc.ddpfPixelFormat.dwRGBBitCount, bih->biWidth, bih->biHeight, desc.lPitch);
  822. this->lpDDSImage->Unlock(NULL);
  823. /*
  824.  * Clear the back buffer
  825.  *
  826.  */
  827. DDBLTFX bltfx;
  828. ZeroMemory(&bltfx, sizeof(bltfx)); // Sets dwFillColor to 0 as well
  829. bltfx.dwSize = sizeof(bltfx);
  830. lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &bltfx);
  831. /*
  832.  * Now Blit to the Back Buffer
  833.  */
  834. RECT rcRect, dst;
  835. rcRect.left   = 0;
  836. rcRect.top    = 0;
  837. rcRect.right  = this->bih->biWidth;
  838. rcRect.bottom = this->bih->biHeight;
  839. dst.left   = 0;
  840. dst.top    = (screen_size_y - video_height)/2;
  841. dst.right  = screen_size_x;
  842. dst.bottom = (screen_size_y - video_height)/2 + video_height;
  843. ddrval = lpDDSBack->Blt( &dst, lpDDSImage, &rcRect, DDBLT_ASYNC, NULL);
  844. }
  845. this->lpDDSPrimary->Flip(0, DDFLIP_WAIT);
  846.   }
  847.   return 1;
  848. }
  849. /*
  850.  * Draw NOT in fullscreen
  851.  *
  852.  */
  853. int VideoRenderer::Draw(char *buffer, int has_subtitles)
  854. {
  855. DDSURFACEDESC2 desc;
  856. long i, j;
  857. /*
  858.  * Get a pointer to pixels 
  859.  * and memcopy them
  860.  */
  861. if(buffer != NULL && this->lpDDSPrimary != NULL) {
  862. if(this->use_bilinear) {
  863. ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
  864. desc.dwSize = sizeof(DDSURFACEDESC2);
  865. if(this->lpDDSImage != NULL) {
  866. ddrval = this->lpDDSImage->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  867. }
  868. if(ddrval != DD_OK) {
  869. if( ddrval == DDERR_SURFACEBUSY ) {
  870. this->lpDDSImage->Unlock(NULL);
  871. ddrval = this->lpDDSImage->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  872. if(ddrval != DD_OK) {
  873. MessageBox(NULL, "Couldn't lock either", "Error", MB_OK);
  874. return 0;
  875. }
  876. }
  877. }
  878. /*
  879.  * Copy the pixels
  880.  */
  881. this->copyPixels(buffer, desc.lpSurface, this->codecDepth, desc.ddpfPixelFormat.dwRGBBitCount, bih->biWidth, bih->biHeight, desc.lPitch);
  882. this->lpDDSImage->Unlock(NULL);
  883. /*
  884.  * Now Blit to the window
  885.  */
  886. if(this->hwnd) {
  887. RECT                rcRect;
  888. RECT                destRect;
  889. POINT               pt;
  890. GetClientRect( hwnd, &destRect );
  891. /*
  892.  * squeeze rect so that
  893.  * we have space for controls
  894.  */
  895. destRect.left   += 7;
  896. destRect.right  -= 8;
  897. destRect.top    += 22;
  898. destRect.bottom -= 115;
  899. destRect.bottom -= has_subtitles ? 50 : 0;
  900. pt.x = pt.y = 0;
  901. ClientToScreen( hwnd, &pt );
  902. OffsetRect(&destRect, pt.x, pt.y);
  903. D3DTLVERTEX square1[4];
  904. square1[0] = D3DTLVERTEX(D3DVECTOR(0, 0, 0.0), 1.0, RGBA_MAKE(255,255,255,255),0, 0.0, 0.0);
  905. square1[1] = D3DTLVERTEX(D3DVECTOR(destRect.right - destRect.left, 0,    0.0), 1.0, RGBA_MAKE(255,255,255,255),0, (float)bih->biWidth/(float)desc.dwWidth, 0.0);
  906. square1[2] = D3DTLVERTEX(D3DVECTOR(0,  destRect.bottom - destRect.top, 0.0), 1.0, RGBA_MAKE(255,255,255,255),0, 0.0, (float)bih->biHeight/(float)desc.dwHeight);
  907. square1[3] = D3DTLVERTEX(D3DVECTOR(destRect.right - destRect.left, destRect.bottom - destRect.top, 0.0), 1.0, RGBA_MAKE(255,255,255,255),0, (float)bih->biWidth/(float)desc.dwWidth, (float)bih->biHeight/(float)desc.dwHeight);
  908. rcRect.left   = 0;
  909. rcRect.top    = 0;
  910. rcRect.right  = destRect.right - destRect.left;
  911. rcRect.bottom = destRect.bottom - destRect.top;
  912. if( SUCCEEDED( lpDevice->BeginScene() ) ) {
  913. lpDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, square1, 4, 0);
  914. lpDevice->EndScene();
  915. }
  916. while( 1 )
  917. {
  918. ddrval = lpDDSPrimary->Blt( &destRect, lpDDSBack, &rcRect, DDBLT_ASYNC, NULL );
  919. if( ddrval == DD_OK )
  920. {
  921. break;
  922. }
  923. if( ddrval == DDERR_SURFACELOST )
  924. {
  925. if(!this->restoreAll())
  926. {
  927. return 0;
  928. }
  929. }
  930. if( ddrval != DDERR_WASSTILLDRAWING )
  931. {
  932. return 0;
  933. }
  934. }
  935. }
  936. }
  937. else {
  938. /*
  939.  * Get a pointer to pixels 
  940.  * and memcopy them
  941.  */
  942. ZeroMemory(&desc, sizeof(DDSURFACEDESC2));
  943. desc.dwSize = sizeof(DDSURFACEDESC2);
  944. this->lpDDSBack->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY, NULL);
  945. /*
  946.  * Copy the pixels
  947.  */
  948. this->copyPixels(buffer, desc.lpSurface, this->codecDepth, desc.ddpfPixelFormat.dwRGBBitCount, bih->biWidth, bih->biHeight, desc.lPitch);
  949. this->lpDDSBack->Unlock(NULL);
  950. /*
  951.  * Now Blit to the window
  952.  */
  953. if(this->hwnd) {
  954. RECT                rcRect;
  955. RECT                destRect;
  956. POINT               pt;
  957.         rcRect.left   = 0;
  958.     rcRect.top    = 0;
  959. rcRect.right  = this->bih->biWidth;
  960. rcRect.bottom = this->bih->biHeight;
  961. GetClientRect( hwnd, &destRect );
  962. /*
  963.  * squeeze rect so that
  964.  * we have space for controls
  965. */
  966. destRect.left   += 7;
  967. destRect.right  -= 8;
  968. destRect.top    += 22;
  969. destRect.bottom -= 115;
  970. destRect.bottom -= has_subtitles ? 50 : 0;
  971. pt.x = pt.y = 0;
  972. ClientToScreen( hwnd, &pt );
  973. OffsetRect(&destRect, pt.x, pt.y);
  974. while( 1 )
  975. {
  976. ddrval = lpDDSPrimary->Blt( &destRect, lpDDSBack, &rcRect, DDBLT_ASYNC, NULL );
  977. if( ddrval == DD_OK )
  978. {
  979. break;
  980. }
  981. if( ddrval == DDERR_SURFACELOST )
  982. {
  983. if(!this->restoreAll())
  984. {
  985. return 0;
  986. }
  987. }
  988. if( ddrval != DDERR_WASSTILLDRAWING )
  989. {
  990. return 0;
  991. }
  992. }
  993. if(ddrval != DD_OK)
  994. {
  995. return 0;
  996. }
  997. }
  998. }
  999.   }
  1000.   return 1;
  1001. }
  1002. int VideoRenderer::Close()
  1003. {
  1004. if(this->lpDD) {
  1005. if(this->fullscreen) {
  1006. lpDD->RestoreDisplayMode();
  1007. lpDD->SetCooperativeLevel(this->hwnd, DDSCL_NORMAL);
  1008. }
  1009. lpDD->Release();
  1010. lpDD = NULL;
  1011. if(this->use_bilinear) {
  1012. if( this->lpDDSImage != NULL )
  1013. {
  1014. lpDDSImage->Release();
  1015.     lpDDSImage = NULL;
  1016.    }
  1017. }
  1018. if( this->lpDDSBack != NULL )
  1019. {
  1020.             lpDDSBack->Release();
  1021.                 lpDDSBack = NULL;
  1022.             }
  1023. if( this->lpDDSPrimary != NULL )
  1024. {
  1025.             lpDDSPrimary->Release();
  1026.                 lpDDSPrimary = NULL;
  1027.             }
  1028. }
  1029. if(this->lpD3D) {
  1030. this->lpD3D->Release();
  1031. this->lpD3D = NULL;
  1032. }
  1033. return 1;
  1034. }