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

1148 lines
22 KiB

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <windows.h>
  7. #include <vfw.h>
  8. #include <gldd.h>
  9. #include <gl/glu.h>
  10. #include <gl/glaux.h>
  11. #define PI 3.14159265358979323846
  12. #define NLETTERS 64
  13. #define FIRST_LETTER '@'
  14. #define NOBJS 6
  15. GLenum doubleBuffer;
  16. GLenum videoMemory;
  17. GLenum noSwap;
  18. GLenum noClear;
  19. GLenum fullScreen;
  20. GLenum useMcd;
  21. GLenum modeX;
  22. GLenum stretch;
  23. GLenum paletted;
  24. GLenum timings;
  25. GLenum spin;
  26. GLenum updateMovie = GL_TRUE;
  27. GLenum linearFilter = GL_FALSE;
  28. int fullWidth, fullHeight, fullDepth;
  29. int winWidth, winHeight;
  30. int texWidth, texHeight;
  31. int movX, movY;
  32. int movWidth, movHeight;
  33. GLuint clearBits;
  34. DWORD ticks;
  35. int frames;
  36. GLint letters;
  37. GLYPHMETRICSFLOAT letterMetrics[NLETTERS];
  38. double xrot, yrot;
  39. GLDDWINDOW gwMain = NULL;
  40. PFNGLCOLORTABLEEXTPROC pfnColorTableEXT;
  41. PFNGLCOLORSUBTABLEEXTPROC pfnColorSubTableEXT;
  42. LPDIRECTDRAWSURFACE pddsTex;
  43. DDSURFACEDESC ddsdTex;
  44. char *aviFileName = "d:\\winnt\\clock.avi";
  45. PAVISTREAM aviStream;
  46. long aviLength;
  47. long curFrame;
  48. PGETFRAME aviGetFrame;
  49. BITMAPINFO *pbmiMovie;
  50. typedef struct _Object
  51. {
  52. void (*build_fn)(void);
  53. GLenum canCull;
  54. GLenum needsZ;
  55. GLint dlist;
  56. } Object;
  57. int objIdx = 0;
  58. float c[6][4][3] = {
  59. {
  60. {
  61. 1.0f, 1.0f, -1.0f
  62. },
  63. {
  64. -1.0f, 1.0f, -1.0f
  65. },
  66. {
  67. -1.0f, -1.0f, -1.0f
  68. },
  69. {
  70. 1.0f, -1.0f, -1.0f
  71. }
  72. },
  73. {
  74. {
  75. 1.0f, 1.0f, 1.0f
  76. },
  77. {
  78. 1.0f, 1.0f, -1.0f
  79. },
  80. {
  81. 1.0f, -1.0f, -1.0f
  82. },
  83. {
  84. 1.0f, -1.0f, 1.0f
  85. }
  86. },
  87. {
  88. {
  89. -1.0f, 1.0f, 1.0f
  90. },
  91. {
  92. 1.0f, 1.0f, 1.0f
  93. },
  94. {
  95. 1.0f, -1.0f, 1.0f
  96. },
  97. {
  98. -1.0f, -1.0f, 1.0f
  99. }
  100. },
  101. {
  102. {
  103. -1.0f, 1.0f, -1.0f
  104. },
  105. {
  106. -1.0f, 1.0f, 1.0f
  107. },
  108. {
  109. -1.0f, -1.0f, 1.0f
  110. },
  111. {
  112. -1.0f, -1.0f, -1.0f
  113. }
  114. },
  115. {
  116. {
  117. -1.0f, 1.0f, 1.0f
  118. },
  119. {
  120. -1.0f, 1.0f, -1.0f
  121. },
  122. {
  123. 1.0f, 1.0f, -1.0f
  124. },
  125. {
  126. 1.0f, 1.0f, 1.0f
  127. }
  128. },
  129. {
  130. {
  131. -1.0f, -1.0f, -1.0f
  132. },
  133. {
  134. -1.0f, -1.0f, 1.0f
  135. },
  136. {
  137. 1.0f, -1.0f, 1.0f
  138. },
  139. {
  140. 1.0f, -1.0f, -1.0f
  141. }
  142. }
  143. };
  144. float n[6][3] = {
  145. {
  146. 0.0f, 0.0f, -1.0f
  147. },
  148. {
  149. 1.0f, 0.0f, 0.0f
  150. },
  151. {
  152. 0.0f, 0.0f, 1.0f
  153. },
  154. {
  155. -1.0f, 0.0f, 0.0f
  156. },
  157. {
  158. 0.0f, 1.0f, 0.0f
  159. },
  160. {
  161. 0.0f, -1.0f, 0.0f
  162. }
  163. };
  164. float t[6][4][2] = {
  165. {
  166. {
  167. 1.0f, 1.0f
  168. },
  169. {
  170. -0.0f, 1.0f
  171. },
  172. {
  173. -0.0f, -0.0f
  174. },
  175. {
  176. 1.0f, -0.0f
  177. }
  178. },
  179. {
  180. {
  181. 1.0f, 1.0f
  182. },
  183. {
  184. -0.0f, 1.0f
  185. },
  186. {
  187. -0.0f, -0.0f
  188. },
  189. {
  190. 1.0f, -0.0f
  191. }
  192. },
  193. {
  194. {
  195. -0.0f, 1.0f
  196. },
  197. {
  198. 1.0f, 1.0f
  199. },
  200. {
  201. 1.0f, -0.0f
  202. },
  203. {
  204. -0.0f, -0.0f
  205. }
  206. },
  207. {
  208. {
  209. 1.0f, 1.0f
  210. },
  211. {
  212. -0.0f, 1.0f
  213. },
  214. {
  215. -0.0f, -0.0f
  216. },
  217. {
  218. 1.0f, -0.0f
  219. }
  220. },
  221. {
  222. {
  223. 1.0f, 1.0f
  224. },
  225. {
  226. -0.0f, 1.0f
  227. },
  228. {
  229. -0.0f, -0.0f
  230. },
  231. {
  232. 1.0f, -0.0f
  233. }
  234. },
  235. {
  236. {
  237. 1.0f, 1.0f
  238. },
  239. {
  240. -0.0f, 1.0f
  241. },
  242. {
  243. -0.0f, -0.0f
  244. },
  245. {
  246. 1.0f, -0.0f
  247. }
  248. },
  249. };
  250. void BuildSphere(void)
  251. {
  252. GLUquadricObj *quadObj;
  253. quadObj = gluNewQuadric ();
  254. gluQuadricDrawStyle (quadObj, GLU_FILL);
  255. gluQuadricNormals (quadObj, GLU_SMOOTH);
  256. gluQuadricTexture (quadObj, GL_TRUE);
  257. gluSphere (quadObj, 1.0, 16, 16);
  258. gluDeleteQuadric(quadObj);
  259. }
  260. void BuildCube(void)
  261. {
  262. GLint i;
  263. for (i = 0; i < 6; i++)
  264. {
  265. glBegin(GL_POLYGON);
  266. glNormal3fv(n[i]); glTexCoord2fv(t[i][0]); glVertex3fv(c[i][0]);
  267. glNormal3fv(n[i]); glTexCoord2fv(t[i][3]); glVertex3fv(c[i][3]);
  268. glNormal3fv(n[i]); glTexCoord2fv(t[i][2]); glVertex3fv(c[i][2]);
  269. glNormal3fv(n[i]); glTexCoord2fv(t[i][1]); glVertex3fv(c[i][1]);
  270. glEnd();
  271. }
  272. }
  273. void BuildCylinder(void)
  274. {
  275. GLUquadricObj *quadObj;
  276. glPushMatrix ();
  277. glRotatef ((GLfloat)90.0, (GLfloat)1.0, (GLfloat)0.0, (GLfloat)0.0);
  278. glTranslatef ((GLfloat)0.0, (GLfloat)0.0, (GLfloat)-1.0);
  279. quadObj = gluNewQuadric ();
  280. gluQuadricDrawStyle (quadObj, GLU_FILL);
  281. gluQuadricTexture (quadObj, GL_TRUE);
  282. gluCylinder (quadObj, 1.0, 1.0, 1.5, 20, 2);
  283. glPopMatrix ();
  284. gluDeleteQuadric(quadObj);
  285. }
  286. void BuildCone(void)
  287. {
  288. GLUquadricObj *quadObj;
  289. quadObj = gluNewQuadric ();
  290. gluQuadricDrawStyle (quadObj, GLU_FILL);
  291. gluQuadricTexture (quadObj, GL_TRUE);
  292. gluCylinder (quadObj, 1.0, 0.0, 1.5, 20, 2);
  293. gluDeleteQuadric(quadObj);
  294. }
  295. void BuildTeapot(void)
  296. {
  297. auxSolidTeapot(1.0);
  298. }
  299. #define STRING "OpenGL"
  300. void BuildString(void)
  301. {
  302. char *str;
  303. int i, l;
  304. float wd, ht;
  305. GLfloat fv4[4];
  306. str = STRING;
  307. l = strlen(str);
  308. wd = 0.0f;
  309. for (i = 0; i < l-1; i++)
  310. {
  311. wd += letterMetrics[str[i]-FIRST_LETTER].gmfCellIncX;
  312. }
  313. wd += letterMetrics[str[i]-FIRST_LETTER].gmfBlackBoxX;
  314. ht = letterMetrics[str[0]-FIRST_LETTER].gmfBlackBoxY;
  315. glPushMatrix();
  316. glScalef(1.0f, 2.0f, 1.0f);
  317. glTranslatef(-wd/2.0f, -ht/2.0f, 0.0f);
  318. fv4[0] = 1.0f/wd;
  319. fv4[1] = 0.0f;
  320. fv4[2] = 0.0f;
  321. fv4[3] = 0.0f;
  322. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
  323. glTexGenfv(GL_S, GL_EYE_PLANE, fv4 );
  324. fv4[0] = 0.0f;
  325. fv4[1] = -1.0f/ht;
  326. fv4[2] = 0.0f;
  327. fv4[3] = 0.0f;
  328. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
  329. glTexGenfv(GL_T, GL_EYE_PLANE, fv4 );
  330. glEnable(GL_TEXTURE_GEN_S);
  331. glEnable(GL_TEXTURE_GEN_T);
  332. glListBase(letters-FIRST_LETTER);
  333. glCallLists(l, GL_UNSIGNED_BYTE, str);
  334. glListBase(0);
  335. glPopMatrix();
  336. glDisable(GL_TEXTURE_GEN_S);
  337. glDisable(GL_TEXTURE_GEN_T);
  338. }
  339. Object objects[NOBJS] =
  340. {
  341. BuildCube, GL_TRUE, GL_FALSE, 0,
  342. BuildSphere, GL_TRUE, GL_FALSE, 0,
  343. BuildCylinder, GL_FALSE, GL_TRUE, 0,
  344. BuildCone, GL_FALSE, GL_TRUE, 0,
  345. BuildTeapot, GL_FALSE, GL_TRUE, 0,
  346. BuildString, GL_TRUE, GL_TRUE, 0,
  347. };
  348. void BuildLists(void)
  349. {
  350. int i;
  351. GLint base;
  352. base = glGenLists(NOBJS);
  353. for (i = 0; i < NOBJS; i++)
  354. {
  355. objects[i].dlist = base+i;
  356. glNewList(objects[i].dlist, GL_COMPILE);
  357. objects[i].build_fn();
  358. glEndList();
  359. }
  360. }
  361. void Quit(char *fmt, ...)
  362. {
  363. va_list args;
  364. if (fmt != NULL)
  365. {
  366. va_start(args, fmt);
  367. vprintf(fmt, args);
  368. va_end(args);
  369. }
  370. if (aviGetFrame != NULL)
  371. {
  372. AVIStreamGetFrameClose(aviGetFrame);
  373. }
  374. if (aviStream != NULL)
  375. {
  376. AVIStreamRelease(aviStream);
  377. AVIFileExit();
  378. }
  379. if (gwMain != NULL)
  380. {
  381. glddDestroyWindow(gwMain);
  382. }
  383. exit(1);
  384. }
  385. void Draw(void)
  386. {
  387. DWORD fticks;
  388. fticks = GetTickCount();
  389. glClear(clearBits);
  390. glLoadIdentity();
  391. glRotated(xrot, 1.0, 0.0, 0.0);
  392. glRotated(yrot, 0.0, 1.0, 0.0);
  393. glCallList(objects[objIdx].dlist);
  394. glFlush();
  395. if (doubleBuffer && !noSwap)
  396. {
  397. glddSwapBuffers(gwMain);
  398. }
  399. ticks += GetTickCount()-fticks;
  400. frames++;
  401. if (timings && ticks > 1000)
  402. {
  403. printf("%d frames in %d ticks, %.3lf f/s\n", frames, ticks,
  404. (double)frames*1000.0/ticks);
  405. frames = 0;
  406. ticks = 0;
  407. }
  408. }
  409. void *UpdateBmi(BITMAPINFO *pbmi)
  410. {
  411. if (pbmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER))
  412. {
  413. Quit("Unknown stream format data\n");
  414. }
  415. memcpy(pbmiMovie->bmiColors, pbmi->bmiColors, 256*sizeof(RGBQUAD));
  416. // Return pointer to data after BITMAPINFO
  417. return pbmi->bmiColors+256;
  418. }
  419. void FrameToTex(long frame)
  420. {
  421. HDC hdc;
  422. HRESULT hr;
  423. LPVOID pvFrame, pvData;
  424. pvFrame = AVIStreamGetFrame(aviGetFrame, frame);
  425. if (pvFrame == NULL)
  426. {
  427. Quit("AVIStreamGetFrame failed\n");
  428. }
  429. // Skip past BITMAPINFO at start of frame.
  430. // If it becomes interesting to support palette changes per frame
  431. // this should call UpdateBmi
  432. #if 0
  433. pvData = (LPVOID)((BYTE *)pvFrame+sizeof(BITMAPINFO)+255*sizeof(RGBQUAD));
  434. #else
  435. pvData = UpdateBmi(pvFrame);
  436. if (paletted)
  437. {
  438. pfnColorSubTableEXT(GL_TEXTURE_2D, 0, 256, GL_BGRA_EXT,
  439. GL_UNSIGNED_BYTE, pbmiMovie->bmiColors);
  440. }
  441. #endif
  442. if (stretch)
  443. {
  444. hr = pddsTex->lpVtbl->GetDC(pddsTex, &hdc);
  445. if (hr != DD_OK)
  446. {
  447. Quit("Stretch GetDC failed, 0x%08lX\n", hr);
  448. }
  449. StretchDIBits(hdc, 0, 0, texWidth, texHeight,
  450. 0, 0, movWidth, movHeight, pvData, pbmiMovie,
  451. DIB_RGB_COLORS, SRCCOPY);
  452. pddsTex->lpVtbl->ReleaseDC(pddsTex, hdc);
  453. }
  454. else if (!paletted)
  455. {
  456. hr = pddsTex->lpVtbl->GetDC(pddsTex, &hdc);
  457. if (hr != DD_OK)
  458. {
  459. Quit("Set GetDC failed, 0x%08lX\n", hr);
  460. }
  461. // The only AVI sources currently allowed are 8bpp so if the texture
  462. // isn't paletted a conversion is necessary
  463. SetDIBitsToDevice(hdc, movX, movY, movWidth, movHeight,
  464. 0, 0, 0, movHeight, pvData, pbmiMovie,
  465. DIB_RGB_COLORS);
  466. pddsTex->lpVtbl->ReleaseDC(pddsTex, hdc);
  467. }
  468. else
  469. {
  470. UINT cbLine;
  471. int y;
  472. BYTE *pbSrc, *pbDst;
  473. HRESULT hr;
  474. hr = pddsTex->lpVtbl->Lock(pddsTex, NULL, &ddsdTex,
  475. DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
  476. NULL);
  477. if (hr != S_OK)
  478. {
  479. Quit("Unable to lock texture, 0x%08lX\n", hr);
  480. }
  481. cbLine = (movWidth+3) & ~3;
  482. pbSrc = (BYTE *)pvData;
  483. pbDst = (BYTE *)ddsdTex.lpSurface+ddsdTex.lPitch*movY+movX;
  484. #if 1
  485. for (y = 0; y < movHeight; y++)
  486. {
  487. memcpy(pbDst, pbSrc, movWidth);
  488. pbSrc += cbLine;
  489. pbDst += ddsdTex.lPitch;
  490. }
  491. #else
  492. for (y = 0; y < movHeight; y++)
  493. {
  494. memset(pbDst, y*256/movHeight, movWidth);
  495. pbSrc += cbLine;
  496. pbDst += ddsdTex.lPitch;
  497. }
  498. #endif
  499. pddsTex->lpVtbl->Unlock(pddsTex, ddsdTex.lpSurface);
  500. }
  501. }
  502. void Animate(GLDDWINDOW gw)
  503. {
  504. if (updateMovie)
  505. {
  506. if (++curFrame == aviLength)
  507. {
  508. curFrame = 0;
  509. }
  510. FrameToTex(curFrame);
  511. }
  512. if (spin)
  513. {
  514. xrot += 2;
  515. yrot += 3;
  516. }
  517. Draw();
  518. }
  519. void SetView(void)
  520. {
  521. glMatrixMode(GL_PROJECTION);
  522. glLoadIdentity();
  523. gluPerspective(45.0, (double)winWidth/winHeight, 0.1, 10);
  524. gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  525. glMatrixMode(GL_MODELVIEW);
  526. }
  527. void ToggleGl(GLenum state)
  528. {
  529. if (glIsEnabled(state))
  530. {
  531. glDisable(state);
  532. }
  533. else
  534. {
  535. glEnable(state);
  536. }
  537. }
  538. void SetObject(int idx)
  539. {
  540. objIdx = idx;
  541. clearBits = GL_COLOR_BUFFER_BIT;
  542. if (objects[objIdx].canCull)
  543. {
  544. glFrontFace(GL_CCW);
  545. glCullFace(GL_BACK);
  546. glEnable(GL_CULL_FACE);
  547. }
  548. else
  549. {
  550. glDisable(GL_CULL_FACE);
  551. }
  552. if (objects[objIdx].needsZ)
  553. {
  554. clearBits |= GL_DEPTH_BUFFER_BIT;
  555. glEnable(GL_DEPTH_TEST);
  556. }
  557. else
  558. {
  559. glDisable(GL_DEPTH_TEST);
  560. }
  561. }
  562. void SetTexFilter(void)
  563. {
  564. GLenum filter;
  565. filter = linearFilter ? GL_LINEAR : GL_NEAREST;
  566. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
  567. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
  568. }
  569. void ClearTex(void)
  570. {
  571. DDBLTFX ddbltfx;
  572. RECT drct;
  573. HRESULT hr;
  574. drct.left = 0;
  575. drct.top = 0;
  576. drct.right = texWidth;
  577. drct.bottom = texHeight;
  578. memset(&ddbltfx, 0, sizeof(ddbltfx));
  579. ddbltfx.dwSize = sizeof(ddbltfx);
  580. ddbltfx.dwFillColor = 0;
  581. hr = pddsTex->lpVtbl->Blt(pddsTex, &drct, NULL, NULL,
  582. DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
  583. if (hr != DD_OK)
  584. {
  585. Quit("Blt failed, 0x%08lX\n", hr);
  586. }
  587. }
  588. void Key(UINT key)
  589. {
  590. switch(key)
  591. {
  592. case VK_ESCAPE:
  593. Quit(NULL);
  594. break;
  595. case VK_SPACE:
  596. spin = !spin;
  597. break;
  598. case 'D':
  599. ToggleGl(GL_DITHER);
  600. break;
  601. case 'F':
  602. linearFilter = !linearFilter;
  603. SetTexFilter();
  604. break;
  605. case 'H':
  606. stretch = !stretch;
  607. break;
  608. case 'M':
  609. updateMovie = !updateMovie;
  610. break;
  611. case 'O':
  612. if (++objIdx == NOBJS)
  613. {
  614. objIdx = 0;
  615. }
  616. SetObject(objIdx);
  617. break;
  618. case 'S':
  619. spin = !spin;
  620. break;
  621. case 'T':
  622. timings = !timings;
  623. frames = 0;
  624. ticks = 0;
  625. break;
  626. case 'X':
  627. ToggleGl(GL_TEXTURE_2D);
  628. break;
  629. default:
  630. break;
  631. }
  632. }
  633. BOOL Message(GLDDWINDOW gw, HWND hwnd, UINT uiMsg, WPARAM wpm, LPARAM lpm,
  634. LRESULT *plr)
  635. {
  636. switch(uiMsg)
  637. {
  638. case WM_KEYDOWN:
  639. Key((UINT)wpm);
  640. break;
  641. case WM_SIZE:
  642. winWidth = LOWORD(lpm);
  643. winHeight = HIWORD(lpm);
  644. SetView();
  645. break;
  646. default:
  647. return FALSE;
  648. }
  649. *plr = 0;
  650. return TRUE;
  651. }
  652. void GetStreamFormat(void)
  653. {
  654. HRESULT hr;
  655. LONG fmtSize;
  656. void *pvFmt;
  657. hr = AVIStreamFormatSize(aviStream, 0, &fmtSize);
  658. if (hr != S_OK)
  659. {
  660. Quit("AVIStreamFormatSize failed, 0x%08lX\n", hr);
  661. }
  662. pvFmt = malloc(fmtSize);
  663. if (pvFmt == NULL)
  664. {
  665. Quit("Unable to allocate format buffer\n");
  666. }
  667. hr = AVIStreamReadFormat(aviStream, 0, pvFmt, &fmtSize);
  668. if (hr != S_OK)
  669. {
  670. Quit("AVIStreamReadFormat failed, 0x%08lX\n", hr);
  671. }
  672. UpdateBmi((BITMAPINFO *)pvFmt);
  673. free(pvFmt);
  674. }
  675. void OpenMovie(void)
  676. {
  677. HRESULT hr;
  678. AVISTREAMINFO sinfo;
  679. BITMAPINFOHEADER *pbmih;
  680. AVIFileInit();
  681. hr = AVIStreamOpenFromFile(&aviStream, aviFileName, streamtypeVIDEO,
  682. 0, OF_READ | OF_SHARE_DENY_WRITE, NULL);
  683. if (hr != S_OK)
  684. {
  685. Quit("AVIStreamOpenFromFile failed, 0x%08lX\n", hr);
  686. }
  687. aviLength = AVIStreamLength(aviStream);
  688. hr = AVIStreamInfo(aviStream, &sinfo, sizeof(sinfo));
  689. if (hr != S_OK)
  690. {
  691. Quit("AVIStreamInfo failed, 0x%08lX\n", hr);
  692. }
  693. if (sinfo.dwFlags & AVISTREAMINFO_FORMATCHANGES)
  694. {
  695. printf("WARNING: Stream contains format changes, unhandled\n");
  696. }
  697. GetStreamFormat();
  698. movWidth = sinfo.rcFrame.right-sinfo.rcFrame.left;
  699. movHeight = sinfo.rcFrame.bottom-sinfo.rcFrame.top;
  700. #if 1
  701. printf("Movie '%s' is %d x %d\n", aviFileName, movWidth, movHeight);
  702. #endif
  703. #if 0
  704. if ((movWidth & (movWidth-1)) != 0 ||
  705. (movHeight & (movHeight-1)) != 0)
  706. {
  707. Quit("Movie must have frames that are a power of two in size, "
  708. "movie is %d x %d\n", movWidth, movHeight);
  709. }
  710. #endif
  711. pbmih = &pbmiMovie->bmiHeader;
  712. memset(pbmih, 0, sizeof(BITMAPINFOHEADER));
  713. pbmih->biSize = sizeof(BITMAPINFOHEADER);
  714. pbmih->biWidth = movWidth;
  715. pbmih->biHeight = movHeight;
  716. pbmih->biPlanes = 1;
  717. pbmih->biBitCount = 8;
  718. pbmih->biCompression = BI_RGB;
  719. aviGetFrame = AVIStreamGetFrameOpen(aviStream, pbmih);
  720. if (aviGetFrame == NULL)
  721. {
  722. Quit("AVIStreamGetFrameOpen failed\n");
  723. }
  724. }
  725. BOOL WINAPI texCallback(LPDDSURFACEDESC pddsd, LPVOID pv)
  726. {
  727. if ((paletted && pddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) ||
  728. (!paletted && pddsd->ddpfPixelFormat.dwFlags == DDPF_RGB))
  729. {
  730. ddsdTex = *pddsd;
  731. return FALSE;
  732. }
  733. else
  734. {
  735. return TRUE;
  736. }
  737. }
  738. void CreateTex(int minWidth, int minHeight)
  739. {
  740. LPDIRECTDRAW pdd;
  741. HRESULT hr;
  742. texWidth = 1;
  743. texHeight = 1;
  744. while (texWidth < minWidth && texWidth < winWidth)
  745. {
  746. texWidth *= 2;
  747. }
  748. if (texWidth > winWidth)
  749. {
  750. texWidth /= 2;
  751. }
  752. while (texHeight < minHeight && texHeight < winHeight)
  753. {
  754. texHeight *= 2;
  755. }
  756. if (texHeight > winHeight)
  757. {
  758. texHeight /= 2;
  759. }
  760. if (!wglEnumTextureFormats(texCallback, NULL))
  761. {
  762. Quit("wglEnumTextureFormats failed, %d\n", GetLastError());
  763. }
  764. hr = DirectDrawCreate(NULL, &pdd, NULL);
  765. if (hr != DD_OK)
  766. {
  767. Quit("DirectDrawCreate failed, 0x%08lX\n", hr);
  768. }
  769. hr = pdd->lpVtbl->SetCooperativeLevel(pdd, NULL, DDSCL_NORMAL);
  770. if (hr != DD_OK)
  771. {
  772. Quit("SetCooperativeLevel failed, 0x%08lX\n", hr);
  773. }
  774. ddsdTex.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
  775. ddsdTex.dwWidth = texWidth;
  776. ddsdTex.dwHeight = texHeight;
  777. ddsdTex.ddsCaps.dwCaps &= ~DDSCAPS_MIPMAP;
  778. hr = pdd->lpVtbl->CreateSurface(pdd, &ddsdTex, &pddsTex, NULL);
  779. if (hr != DD_OK)
  780. {
  781. Quit("Texture CreateSurface failed, 0x%08lX\n", hr);
  782. }
  783. ClearTex();
  784. }
  785. void Init(void)
  786. {
  787. HDC hdc, screen;
  788. HFONT fnt;
  789. pfnColorTableEXT = (PFNGLCOLORTABLEEXTPROC)
  790. wglGetProcAddress("glColorTableEXT");
  791. if (pfnColorTableEXT == NULL)
  792. {
  793. Quit("glColorTableEXT not supported\n");
  794. }
  795. pfnColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)
  796. wglGetProcAddress("glColorSubTableEXT");
  797. if (pfnColorSubTableEXT == NULL)
  798. {
  799. Quit("glColorSubTableEXT not supported\n");
  800. }
  801. pbmiMovie = (BITMAPINFO *)malloc(sizeof(BITMAPINFO)+255*sizeof(RGBQUAD));
  802. if (pbmiMovie == NULL)
  803. {
  804. Quit("Unable to allocate pbmiMovie\n");
  805. }
  806. OpenMovie();
  807. // Must come after movie is open so width and height are set
  808. CreateTex(movWidth, movHeight);
  809. movX = (texWidth-movWidth)/2;
  810. movY = (texHeight-movHeight)/2;
  811. wglBindDirectDrawTexture(pddsTex);
  812. // Create texture palette if necessary
  813. if (paletted)
  814. {
  815. pfnColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256, GL_BGRA_EXT,
  816. GL_UNSIGNED_BYTE, pbmiMovie->bmiColors);
  817. }
  818. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  819. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  820. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  821. linearFilter = GL_FALSE;
  822. SetTexFilter();
  823. glEnable(GL_TEXTURE_2D);
  824. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  825. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  826. // Fill in initial movie frame
  827. curFrame = 0;
  828. FrameToTex(curFrame);
  829. // Provide letters for objects to compose themselves from
  830. screen = GetDC(NULL);
  831. hdc = CreateCompatibleDC(screen);
  832. if (hdc == NULL)
  833. {
  834. Quit("CreateCompatibleDC failed, %d\n", GetLastError());
  835. }
  836. fnt = CreateFont(72, 0, 0, 0, FW_HEAVY, FALSE, FALSE, FALSE,
  837. ANSI_CHARSET, OUT_TT_ONLY_PRECIS,
  838. CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH |
  839. TMPF_TRUETYPE | FF_DONTCARE, "Arial");
  840. if (fnt == NULL)
  841. {
  842. Quit("CreateFont failed, %d\n", GetLastError());
  843. }
  844. SelectObject(hdc, fnt);
  845. letters = glGenLists(NLETTERS);
  846. if (!wglUseFontOutlines(hdc, FIRST_LETTER, NLETTERS, letters, 0.0f, 0.1f,
  847. WGL_FONT_POLYGONS, letterMetrics))
  848. {
  849. Quit("wglUseFontOutlines failed, %d\n", GetLastError());
  850. }
  851. DeleteDC(hdc);
  852. DeleteObject(fnt);
  853. ReleaseDC(NULL, screen);
  854. BuildLists();
  855. SetObject(0);
  856. xrot = 0.0;
  857. yrot = 0.0;
  858. SetView();
  859. }
  860. GLenum Args(int argc, char **argv)
  861. {
  862. GLint i;
  863. winWidth = 320;
  864. winHeight = 320;
  865. doubleBuffer = GL_TRUE;
  866. videoMemory = GL_FALSE;
  867. noSwap = GL_FALSE;
  868. noClear = GL_FALSE;
  869. fullScreen = GL_FALSE;
  870. fullWidth = 640;
  871. fullHeight = 480;
  872. fullDepth = 16;
  873. useMcd = GL_FALSE;
  874. modeX = GL_FALSE;
  875. stretch = GL_TRUE;
  876. paletted = GL_TRUE;
  877. timings = GL_FALSE;
  878. spin = GL_TRUE;
  879. for (i = 1; i < argc; i++) {
  880. if (strcmp(argv[i], "-sb") == 0) {
  881. doubleBuffer = GL_FALSE;
  882. } else if (strcmp(argv[i], "-db") == 0) {
  883. doubleBuffer = GL_TRUE;
  884. } else if (strcmp(argv[i], "-rgb") == 0) {
  885. paletted = GL_FALSE;
  886. } else if (strcmp(argv[i], "-stretch") == 0) {
  887. stretch = GL_TRUE;
  888. } else if (strcmp(argv[i], "-nostretch") == 0) {
  889. stretch = GL_FALSE;
  890. } else if (strcmp(argv[i], "-nospin") == 0) {
  891. spin = GL_FALSE;
  892. } else if (strcmp(argv[i], "-vm") == 0) {
  893. videoMemory = GL_TRUE;
  894. } else if (strcmp(argv[i], "-noswap") == 0) {
  895. noSwap = GL_TRUE;
  896. } else if (strcmp(argv[i], "-noclear") == 0) {
  897. noClear = GL_TRUE;
  898. } else if (strcmp(argv[i], "-full") == 0) {
  899. fullScreen = GL_TRUE;
  900. } else if (strcmp(argv[i], "-modex") == 0) {
  901. modeX = GL_TRUE;
  902. fullWidth = 320;
  903. fullHeight = 240;
  904. fullDepth = 8;
  905. } else if (strcmp(argv[i], "-mcd") == 0) {
  906. useMcd = GL_TRUE;
  907. } else if (strcmp(argv[i], "-surf") == 0) {
  908. if (i+2 >= argc ||
  909. argv[i+1][0] == '-' ||
  910. argv[i+2][0] == '-')
  911. {
  912. printf("-surf (No numbers).\n");
  913. return GL_FALSE;
  914. }
  915. else
  916. {
  917. winWidth = atoi(argv[++i]);
  918. winHeight = atoi(argv[++i]);
  919. }
  920. } else if (strcmp(argv[i], "-fdim") == 0) {
  921. if (i+3 >= argc ||
  922. argv[i+1][0] == '-' ||
  923. argv[i+2][0] == '-' ||
  924. argv[i+3][0] == '-')
  925. {
  926. printf("-fdim (No numbers).\n");
  927. return GL_FALSE;
  928. }
  929. else
  930. {
  931. fullWidth = atoi(argv[++i]);
  932. fullHeight = atoi(argv[++i]);
  933. fullDepth = atoi(argv[++i]);
  934. }
  935. } else if (strcmp(argv[i], "-mov") == 0) {
  936. if (i+1 >= argc ||
  937. argv[i+1][0] == '-')
  938. {
  939. printf("-mov (No filename).\n");
  940. return GL_FALSE;
  941. }
  942. else
  943. {
  944. aviFileName = argv[++i];
  945. }
  946. } else {
  947. printf("%s (Bad option).\n", argv[i]);
  948. return GL_FALSE;
  949. }
  950. }
  951. return GL_TRUE;
  952. }
  953. void __cdecl main(int argc, char **argv)
  954. {
  955. DWORD dwFlags;
  956. GLDDWINDOW gw;
  957. if (Args(argc, argv) == GL_FALSE) {
  958. exit(1);
  959. }
  960. dwFlags = GLDD_Z_BUFFER_16;
  961. dwFlags |= doubleBuffer ? GLDD_BACK_BUFFER : 0;
  962. dwFlags |= videoMemory ? GLDD_VIDEO_MEMORY : 0;
  963. dwFlags |= useMcd ? GLDD_GENERIC_ACCELERATED : 0;
  964. if (fullScreen)
  965. {
  966. dwFlags |= GLDD_FULL_SCREEN;
  967. dwFlags |= modeX ? GLDD_USE_MODE_X : 0;
  968. winWidth = fullWidth;
  969. winHeight = fullHeight;
  970. }
  971. gw = glddCreateWindow("Video Texture", 10, 30, winWidth, winHeight,
  972. fullDepth, dwFlags);
  973. if (gw == NULL)
  974. {
  975. printf("glddCreateWindow failed with 0x%08lX\n", glddGetLastError());
  976. exit(1);
  977. }
  978. gwMain = gw;
  979. glddMakeCurrent(gw);
  980. Init();
  981. glddIdleCallback(gw, Animate);
  982. glddMessageCallback(gw, Message);
  983. glddRun(gw);
  984. Quit(NULL);
  985. }