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.

1124 lines
29 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mtkwin.cxx
  3. *
  4. * Copyright (c) 1996 Microsoft Corporation
  5. *
  6. \**************************************************************************/
  7. #include "mtk.hxx"
  8. #include "glutil.hxx"
  9. #include "mtkwin.hxx"
  10. #include "mtkwproc.hxx"
  11. #include "mtkinit.hxx"
  12. /**************************************************************************\
  13. * MTKWIN constructor
  14. *
  15. \**************************************************************************/
  16. MTKWIN::MTKWIN()
  17. {
  18. Reset();
  19. }
  20. /**************************************************************************\
  21. * Reset
  22. *
  23. * Reset parameters to default init state
  24. \**************************************************************************/
  25. void
  26. MTKWIN::Reset()
  27. {
  28. // Basic initialization
  29. bOwnWindow = FALSE;
  30. wFlags = 0;
  31. hwnd = 0;
  32. hdc = 0;
  33. hrc = 0;
  34. pos.x = pos.y = 0;
  35. size.width = size.height = 0;
  36. pBackBitmap = NULL;
  37. pBackgroundBitmap = NULL;
  38. bDoubleBuf = FALSE;
  39. bFullScreen = FALSE;
  40. execRefCount = 0;
  41. ReshapeFunc = NULL;
  42. RepaintFunc = NULL;
  43. DisplayFunc = NULL;
  44. MouseMoveFunc = NULL;
  45. MouseDownFunc = NULL;
  46. MouseUpFunc = NULL;
  47. KeyDownFunc = NULL;
  48. FinishFunc = NULL;
  49. DataPtr = NULL;
  50. }
  51. /**************************************************************************\
  52. * MTKWIN destructor
  53. *
  54. * This can be called when a window is closed, or by the ss client
  55. *
  56. \**************************************************************************/
  57. MTKWIN::~MTKWIN()
  58. {
  59. //mf: !!! we're in trouble if user calls this directly, because would then need to
  60. // post a DESTROY msg, here putting us in an endless loop...
  61. // -> could have a flag set so we know if user or internal call
  62. //mf: another potential timing problem here : If user calls MTKWIN::Return(),
  63. // which posts an MTK_WM_RETURN msg to the windows queue, and then calls here
  64. // before the msg is processed, we could delete the MTKWIN here before exiting
  65. // the msg loop. So here we should make sure the msg loop is exited by
  66. // calling Return() or something. This should be easy to verify via a
  67. // reference count
  68. if( execRefCount ) {
  69. SS_ERROR1( "MTKWIN::~MTKWIN : execRefCount is %d\n", execRefCount );
  70. // mf: ? can we exit the msg loop here ?
  71. //mf: this din't get through
  72. #if 1
  73. SendMessage( hwnd, MTK_WM_RETURN, 0, 0l );
  74. #else
  75. if( ! PostMessage( hwnd, MTK_WM_RETURN, 0, 0l ) )
  76. SS_ERROR( "MTKWIN dtor : MTK_WM_RETURN msg not posted\n" );
  77. #endif
  78. }
  79. if( pBackBitmap )
  80. delete pBackBitmap;
  81. if( pBackgroundBitmap )
  82. delete pBackgroundBitmap;
  83. if( hwnd ) {
  84. animator.Stop();
  85. // Remove from SSWTable
  86. sswTable.Remove( hwnd );
  87. }
  88. // Clean up GL
  89. //mf: !!!
  90. //mf: This assumes FinishFunc is only related to gl
  91. if( hrc ) {
  92. // FinishFunc still needs gl
  93. if( FinishFunc )
  94. #if 0
  95. (*FinishFunc)( DataPtr );
  96. #else
  97. (*FinishFunc)();
  98. #endif
  99. wglMakeCurrent( NULL, NULL );
  100. if( ! (wFlags & SS_HRC_PROXY_BIT) )
  101. wglDeleteContext( hrc );
  102. }
  103. // Release the dc
  104. if( hdc ) {
  105. HWND hwndForHdc = hwnd;
  106. ReleaseDC(hwndForHdc, hdc);
  107. }
  108. }
  109. /**************************************************************************\
  110. * Create
  111. *
  112. * Create window.
  113. *
  114. \**************************************************************************/
  115. BOOL
  116. MTKWIN::Create( LPCTSTR pszWindowTitle, ISIZE *pSize, IPOINT2D *pPos,
  117. UINT winConfig, WNDPROC userWndProc )
  118. {
  119. HWND hwndParent;
  120. UINT uStyle = 0;
  121. UINT uExStyle = 0;
  122. HINSTANCE hInstance;
  123. int width, height;
  124. if( ! mtk_Init( this ) )
  125. return FALSE;
  126. bOwnWindow = TRUE; // We're creating the window, it's not a wrapper
  127. if( winConfig & MTK_FULLSCREEN ) {
  128. //mf: this really only valid if no border
  129. bFullScreen = TRUE;
  130. pos.x = 0;
  131. pos.y = 0;
  132. size.width = GetSystemMetrics( SM_CXSCREEN );
  133. size.height = GetSystemMetrics( SM_CYSCREEN );
  134. uExStyle |= WS_EX_TOPMOST;
  135. } else {
  136. pos = *pPos;
  137. size = *pSize;
  138. }
  139. LPCTSTR pszClass;
  140. HBRUSH hBrush = ghbrbg;
  141. HCURSOR hCursor = ghArrowCursor;
  142. WNDPROC wndProc;
  143. if( bTransparent = (winConfig & MTK_TRANSPARENT) ) {
  144. uExStyle |= WS_EX_TRANSPARENT;
  145. hBrush = NULL;
  146. }
  147. //mf: if winsize, winpos NULL, pick default size, pos
  148. if( winConfig & MTK_NOBORDER ) {
  149. uStyle |= WS_POPUP;
  150. width = size.width;
  151. height = size.height;
  152. } else {
  153. uStyle |= WS_OVERLAPPEDWINDOW;
  154. /*
  155. * Make window large enough to hold a client area of requested size
  156. */
  157. RECT WinRect;
  158. //mf: either of these should work
  159. #if 0
  160. WinRect.left = 0;
  161. WinRect.right = size.width;
  162. WinRect.top = 0;
  163. WinRect.bottom = size.height;
  164. #else
  165. WinRect.left = pos.x;
  166. WinRect.right = pos.x + size.width;
  167. WinRect.top = pos.y;
  168. WinRect.bottom = pos.y + size.height;
  169. #endif
  170. AdjustWindowRectEx(&WinRect, uStyle, FALSE, uExStyle );
  171. width = WinRect.right - WinRect.left;
  172. height = WinRect.bottom - WinRect.top;
  173. }
  174. if( winConfig & MTK_NOCURSOR )
  175. hCursor = NULL;
  176. if( userWndProc )
  177. wndProc = userWndProc;
  178. else
  179. wndProc = mtkWndProc;
  180. // Register window class
  181. pszClass = mtk_RegisterClass( wndProc, NULL, hBrush, hCursor );
  182. hInstance = GetModuleHandle( NULL );
  183. hwndParent = NULL; // for now
  184. hwnd = CreateWindowEx(
  185. uExStyle,
  186. pszClass,
  187. pszWindowTitle,
  188. uStyle,
  189. pos.x,
  190. pos.y,
  191. width,
  192. height,
  193. hwndParent,
  194. NULL, // menu
  195. hInstance,
  196. (LPVOID) this
  197. );
  198. if (!hwnd) {
  199. SS_WARNING( "SSW::CreateSSWindow : CreateWindowEx failure\n" );
  200. return FALSE;
  201. }
  202. if( bTransparent ) {
  203. // Create a bitmap buffer that tracks the window size. This will be
  204. // used to store a window background.
  205. ConfigureForGdi();
  206. pBackgroundBitmap = new MTKBMP( hdc );
  207. if( !pBackgroundBitmap ) {
  208. SS_WARNING( "MTKWIN::Create: couldn't create background bitmap\n" );
  209. } else {
  210. // Set bitmap's size to the window's size
  211. pBackgroundBitmap->Resize( &size );
  212. }
  213. }
  214. animator.SetHwnd( hwnd );
  215. ShowWindow(hwnd, SW_SHOW);
  216. return TRUE;
  217. }
  218. /**************************************************************************\
  219. * ConfigureForGdi
  220. *
  221. * Creates an hdc for the window
  222. *
  223. \**************************************************************************/
  224. BOOL
  225. MTKWIN::ConfigureForGdi()
  226. {
  227. if( hdc )
  228. // already configured
  229. return TRUE;
  230. // Figure window to get hdc from
  231. #if 0
  232. HWND hwndForHdc = hwnd ? hwnd : psswParent ? psswParent->hwnd : NULL;
  233. #else
  234. HWND hwndForHdc = hwnd;
  235. #endif
  236. if( !hwndForHdc || !(hdc = GetDC(hwndForHdc)) ) {
  237. SS_WARNING( "SSW::ConfigureForGdi failed\n" );
  238. return FALSE;
  239. }
  240. return TRUE;
  241. }
  242. /**************************************************************************\
  243. * ConfigureForGL
  244. *
  245. * Creates a GL rendering context for the specified window
  246. *
  247. \**************************************************************************/
  248. BOOL
  249. MTKWIN::Config( UINT glConfig )
  250. {
  251. return Config( glConfig, NULL );
  252. }
  253. BOOL
  254. MTKWIN::Config( UINT glConfig, PVOID pConfigData )
  255. {
  256. if( hrc )
  257. // Already configured...
  258. return TRUE;
  259. if( ConfigureForGdi() &&
  260. (hrc = hrcSetupGL( glConfig, pConfigData )) )
  261. return TRUE;
  262. SS_WARNING( "SSW::ConfigureForGL failed\n" );
  263. return FALSE;
  264. }
  265. /**************************************************************************\
  266. * hrcSetupGL
  267. *
  268. * Setup OpenGL.
  269. *
  270. \**************************************************************************/
  271. #define NULL_RC ((HGLRC) 0)
  272. HGLRC
  273. MTKWIN::hrcSetupGL( UINT glConfig, PVOID pData )
  274. {
  275. HGLRC hrc;
  276. HDC hgldc;
  277. int pfFlags = 0;
  278. PIXELFORMATDESCRIPTOR pfd = {0};
  279. // Setup pixel format flags
  280. // Double buffering can either be done with a double-buffered pixel
  281. // format, or by using a local back buffer bitmap that tracks the window
  282. // size. The latter allows us more control with buffer swaps.
  283. bDoubleBuf = glConfig & MTK_DOUBLE;
  284. BOOL bBitmapBackBuf = glConfig & MTK_BITMAP;
  285. if( bDoubleBuf ) {
  286. if( bBitmapBackBuf )
  287. pfFlags |= SS_BITMAP_BIT;
  288. else
  289. pfFlags |= SS_DOUBLEBUF_BIT;
  290. }
  291. if( glConfig & MTK_DEPTH )
  292. pfFlags |= SS_DEPTH32_BIT;
  293. if( glConfig & MTK_DEPTH16 )
  294. pfFlags |= SS_DEPTH16_BIT;
  295. if( glConfig & MTK_ALPHA )
  296. pfFlags |= SS_ALPHA_BIT;
  297. // If preview mode or config mode, don't allow pixel formats that need
  298. // the system palette, as this will create much ugliness.
  299. if( !bFullScreen )
  300. pfFlags |= SS_NO_SYSTEM_PALETTE_BIT;
  301. //mf: don't really need pixel format for window if using back bitmap method,
  302. // but if user wants to draw to front buffer, then we'll need it. So, we'll
  303. // always set it here.
  304. if( !SSU_SetupPixelFormat( hdc, pfFlags, &pfd ) )
  305. return NULL_RC;
  306. //mf: ???
  307. // Update pfFlags based on pfd returned
  308. // !!! mf: klugey, fix after SUR
  309. // (for now, the only ones we care about are the generic/accelerated flags)
  310. if( (pfd.dwFlags & (PFD_GENERIC_FORMAT|PFD_GENERIC_ACCELERATED))
  311. == PFD_GENERIC_FORMAT )
  312. pfFlags |= SS_GENERIC_UNACCELERATED_BIT;
  313. if( SSU_bNeedPalette( &pfd ) ) {
  314. // Note: even if bStretch, need to set up palette here so they match
  315. if( !gpssPal ) {
  316. SS_PAL *pssPal;
  317. #if 1
  318. BOOL bTakeOverPalette = bFullScreen ? TRUE : FALSE;
  319. #else
  320. //mf: For next rev, we don't have to force palette takeover - but it will
  321. // automically be invoked for any case like MCD, etc.
  322. BOOL bTakeOverPalette = FALSE;
  323. #endif
  324. // The global palette has not been created yet - do it
  325. // SS_PAL creation requires pixel format descriptor for color bit
  326. // information, etc. (the pfd is cached in SS_PAL, since for
  327. // palette purposes it is the same for all windows)
  328. pssPal = new SS_PAL( hdc, &pfd, bTakeOverPalette );
  329. if( !pssPal )
  330. return NULL_RC;
  331. // Set approppriate palette manage proc
  332. if( bFullScreen )
  333. pssPal->paletteManageProc = FullScreenPaletteManageProc;
  334. else
  335. // use regular palette manager proc
  336. pssPal->paletteManageProc = PaletteManageProc;
  337. gpssPal = pssPal;
  338. }
  339. // Realize the global palette in this window
  340. //mf: assume we're realizing in foreground
  341. HWND hwndPal = hwnd;
  342. if( hwndPal )
  343. gpssPal->Realize( hwndPal, hdc, FALSE );
  344. }
  345. if( bBitmapBackBuf ) {
  346. pBackBitmap = new MTKBMP( hdc );
  347. if( !pBackBitmap ) {
  348. SS_WARNING( "MTKWIN::hrcSetupGL : couldn't create back bitmap\n" );
  349. return NULL_RC;
  350. }
  351. // Set bitmap's size to the window's size
  352. pBackBitmap->Resize( &size );
  353. hgldc = pBackBitmap->hdc;
  354. // Setup pixelformat
  355. if( !SSU_SetupPixelFormat( hgldc, pfFlags, &pfd ) )
  356. return NULL_RC;
  357. // If window needed a palette, so does the bitmap...
  358. if( gpssPal )
  359. SSDIB_UpdateColorTable( hgldc, hdc, gpssPal->hPal );
  360. } else {
  361. hgldc = hdc;
  362. }
  363. // Create a new hrc
  364. hrc = wglCreateContext(hgldc);
  365. if( !hrc || !wglMakeCurrent(hgldc, hrc) ) {
  366. SS_WARNING( "SSW::hrcSetupGL : hrc context failure\n" );
  367. return NULL_RC;
  368. }
  369. SS_DBGLEVEL2( SS_LEVEL_INFO,
  370. "SSW::hrcSetupGL: wglMakeCurrent( hrc=0x%x, hwnd=0x%x )\n", hrc, hwnd );
  371. //mf: Note that these queries are based on a single gl window screen saver. In
  372. // a more complicated scenario, these capabilities could be queried on a
  373. // per-window basis (since support could vary with pixel formats).
  374. gGLCaps.Query();
  375. // Send another reshape msg to the app, since the first one on window
  376. // create would have been sent before we had an rc
  377. Reshape();
  378. return hrc;
  379. }
  380. /**************************************************************************\
  381. * MakeCurrent
  382. *
  383. * Call wglMakeCurrent for this window's hrc. Note: an ss client may have
  384. * more than one hrc (e.g. pipes), in which case it is the client's
  385. * responsibility to make current.
  386. \**************************************************************************/
  387. void
  388. MTKWIN::MakeCurrent()
  389. {
  390. if( ! wglMakeCurrent( hdc, hrc ) )
  391. SS_WARNING( "SSW::MakeCurrent : wglMakeCurrent failure\n" );
  392. }
  393. // Callback functions:
  394. /******************************Public*Routine******************************\
  395. * ss_ReshapeFunc
  396. *
  397. \**************************************************************************/
  398. void
  399. MTKWIN::SetReshapeFunc(MTK_RESHAPEPROC Func)
  400. {
  401. ReshapeFunc = Func;
  402. }
  403. /******************************Public*Routine******************************\
  404. * ss_RepaintFunc
  405. *
  406. \**************************************************************************/
  407. void
  408. MTKWIN::SetRepaintFunc(MTK_REPAINTPROC Func)
  409. {
  410. RepaintFunc = Func;
  411. }
  412. void
  413. MTKWIN::SetDisplayFunc(MTK_DISPLAYPROC Func)
  414. {
  415. DisplayFunc = Func;
  416. }
  417. /******************************Public*Routine******************************\
  418. * SetAnimateFunc
  419. *
  420. \**************************************************************************/
  421. void
  422. MTKWIN::SetAnimateFunc(MTK_ANIMATEPROC Func )
  423. {
  424. animator.SetFunc( Func );
  425. // If we are in msg loop and Func is non-NULL, have to make sure
  426. // animator starts again... (awkward). If animator was already started,
  427. // this will do nothing
  428. if( execRefCount && Func )
  429. animator.Start();
  430. }
  431. /******************************Public*Routine******************************\
  432. * Animate
  433. *
  434. * Call the animation function
  435. *
  436. * If animate mode is interval (as opposed to continuous),
  437. * animate the number of supplied frames. The animation count is decremented
  438. * by the WndProc processing the WM_TIMER messages. Exits the msg loop when
  439. * the desired number fo frames has been animated.
  440. *
  441. \**************************************************************************/
  442. //mf: had to rename from Animate to mtkAnimate due to name conflicts at link
  443. // time
  444. void
  445. MTKWIN::mtkAnimate()
  446. {
  447. if( ! animator.Draw() )
  448. Return();
  449. }
  450. /******************************Public*Routine******************************\
  451. * SetAnimateMode
  452. *
  453. *
  454. \**************************************************************************/
  455. void
  456. MTKWIN::SetAnimateMode( UINT mode, float *fParam )
  457. {
  458. animator.SetMode( mode, fParam );
  459. }
  460. /******************************Public*Routine******************************\
  461. * Exec
  462. *
  463. * Starts the message loop for the window.
  464. *
  465. * If an animation has been requested prior to this call, then a new animation
  466. * timer is setup. This msg loop can terminate in the following ways :
  467. * 1) The window is closed
  468. * 2) An interval animation was requested, and the required number of frames
  469. * have been drawn
  470. * 3) The user calls MTKWIN::Return(), which will cause the MTKWIN::Exec()
  471. * call to return
  472. *
  473. * For now :
  474. * Returns TRUE on normal termination, FALSE if the window it's animating in
  475. * gets closed.
  476. *
  477. \**************************************************************************/
  478. BOOL
  479. MTKWIN::Exec()
  480. {
  481. // If user is already in here, get out
  482. if( execRefCount )
  483. return TRUE;
  484. execRefCount++;
  485. // Stop any existing timer (this will flush WM_TIMER msg's)
  486. animator.Stop();
  487. // Start new animation timer (if animator modes are set)
  488. animator.Start();
  489. MSG msg;
  490. BOOL bNotQuitMsg;
  491. while( bNotQuitMsg = GetMessage( &msg, hwnd, 0, 0 ) )
  492. {
  493. if( msg.message == MTK_WM_RETURN ) {
  494. // User or mtk wants to terminate msg loop and return control
  495. // (mf: could pick up return parameter here...)
  496. // SS_DBGPRINT1( "MTKWIN::Exec got WM_RETURN for %p\n", this );
  497. break;
  498. }
  499. //mf: ? better way of doing this ?
  500. else if( ! msg.hwnd ) {
  501. // Window has been destroyed, get out !
  502. SS_DBGPRINT( "MTKWIN::Exec : hwnd = 0, forcing msg loop exit\n" );
  503. return FALSE;
  504. }
  505. TranslateMessage( &msg );
  506. DispatchMessage( &msg );
  507. }
  508. animator.Stop();
  509. execRefCount--;
  510. if( bNotQuitMsg )
  511. return TRUE;
  512. else {
  513. SS_DBGPRINT1( "MTKWIN::Exec got WM_QUIT for %p\n", this );
  514. return FALSE;
  515. }
  516. }
  517. /******************************Public*Routine******************************\
  518. * Return
  519. *
  520. * Called by the user when they want to return from the Exec() call which
  521. * started the message loop.
  522. *
  523. * mf: could include parameter here
  524. *
  525. \**************************************************************************/
  526. void
  527. MTKWIN::Return()
  528. {
  529. animator.Stop();
  530. PostMessage( hwnd, MTK_WM_RETURN, 0, 0l );
  531. }
  532. void
  533. MTKWIN::SetMouseMoveFunc(MTK_MOUSEMOVEPROC Func)
  534. {
  535. MouseMoveFunc = Func;
  536. }
  537. void
  538. MTKWIN::SetMouseUpFunc(MTK_MOUSEUPPROC Func)
  539. {
  540. MouseUpFunc = Func;
  541. }
  542. void
  543. MTKWIN::SetMouseDownFunc(MTK_MOUSEDOWNPROC Func)
  544. {
  545. MouseDownFunc = Func;
  546. }
  547. void
  548. MTKWIN::SetKeyDownFunc(MTK_KEYDOWNPROC Func)
  549. {
  550. KeyDownFunc = Func;
  551. }
  552. void
  553. MTKWIN::GetMouseLoc( int *x, int *y )
  554. {
  555. POINT Point;
  556. *x = 0;
  557. *y = 0;
  558. GetCursorPos(&Point);
  559. /*
  560. * GetCursorPos returns screen coordinates,
  561. * we want window coordinates
  562. */
  563. *x = Point.x - pos.x;
  564. *y = Point.y - pos.y;
  565. }
  566. void
  567. MTKWIN::Close()
  568. {
  569. DestroyWindow( hwnd );
  570. }
  571. /******************************Public*Routine******************************\
  572. * ss_FinishFunc
  573. *
  574. \**************************************************************************/
  575. void
  576. MTKWIN::SetFinishFunc(MTK_FINISHPROC Func)
  577. {
  578. FinishFunc = Func;
  579. }
  580. /**************************************************************************\
  581. * Resize
  582. *
  583. * Resize wrapper
  584. *
  585. * Called in response to WM_SIZE.
  586. *
  587. \**************************************************************************/
  588. void
  589. MTKWIN::Resize( int width, int height )
  590. {
  591. size.width = width;
  592. size.height = height;
  593. if( pBackBitmap )
  594. pBackBitmap->Resize( &size );
  595. if( pBackgroundBitmap )
  596. pBackgroundBitmap->Resize( &size );
  597. Reshape();
  598. }
  599. /**************************************************************************\
  600. * Repaint
  601. *
  602. * Repaint wrapper
  603. *
  604. * Called in response to WM_PAINT.
  605. *
  606. \**************************************************************************/
  607. #define NULL_UPDATE_RECT( pRect ) \
  608. ( ((pRect)->left == 0) && \
  609. ((pRect)->right == 0) && \
  610. ((pRect)->top == 0) && \
  611. ((pRect)->bottom == 0) )
  612. void
  613. MTKWIN::Repaint( BOOL bCheckUpdateRect )
  614. {
  615. if( !hwnd )
  616. return;
  617. RECT rect, *pRect = NULL;
  618. if( bCheckUpdateRect ) {
  619. GetUpdateRect( hwnd, &rect, FALSE );
  620. //mf
  621. SS_DBGPRINT4( "MTKWIN::Repaint rect: %d - %d, %d - %d\n", rect.left, rect.right,
  622. rect.top, rect.bottom );
  623. // mf: Above supposed to return NULL if rect is all 0's,
  624. // but this doesn't happen
  625. if( NULL_UPDATE_RECT( &rect ) )
  626. return;
  627. pRect = ▭
  628. }
  629. // transparent window thing
  630. if( pBackgroundBitmap ) {
  631. if( !pRect ) {
  632. // UpdateBg doesn't handle null rect
  633. pRect = ▭
  634. GetClientRect( hwnd, pRect );
  635. }
  636. UpdateBackgroundBitmap( pRect );
  637. }
  638. #if 0
  639. if( RepaintFunc )
  640. (*RepaintFunc)( pRect );
  641. #else
  642. #if 0
  643. Display();
  644. #else
  645. //mf: test: ? help bg update problem ?? nope, din't seem to...
  646. MSG Message;
  647. if (!PeekMessage(&Message, hwnd, MTK_WM_REDRAW, MTK_WM_REDRAW, PM_NOREMOVE) )
  648. {
  649. PostMessage( hwnd, MTK_WM_REDRAW, 0, 0l );
  650. }
  651. #endif
  652. #endif
  653. }
  654. void
  655. MTKWIN::Display()
  656. {
  657. if( DisplayFunc )
  658. (*DisplayFunc)();
  659. }
  660. //mf: not using these in current scheme, although might if use 'ss' mode
  661. #if 0
  662. /**************************************************************************\
  663. * UpdateWindow
  664. *
  665. * Update the window
  666. *
  667. * Currently this assumes all windows are being animated (i.e. not showing
  668. * a static image)
  669. *
  670. * Things *must* happen in the order defined here, so they work on generic as
  671. * well as hardware implementations.
  672. * Note: Move must happen after SwapBuf, and will cause some encroaching on
  673. * the current display, as the parent window repaints after the move. Therefore
  674. * apps must take care to leave an empty border around their rendered image,
  675. * equal to the maximum window move delta.
  676. *
  677. \**************************************************************************/
  678. void
  679. MTKWIN::UpdateWindow()
  680. {
  681. if( !AnimateFunc )
  682. return;
  683. // bDoubleBuf and pStretch should be mutually exclusive...
  684. if( bDoubleBuf ) {
  685. UpdateDoubleBufWin();
  686. } else {
  687. //mf: ? where's the clearing here ? (true, no one uses this path...)
  688. #if 0
  689. (*AnimateFunc)( DataPtr );
  690. #else
  691. (*AnimateFunc)();
  692. #endif
  693. }
  694. }
  695. /**************************************************************************\
  696. * UpdateDoubleBufWin
  697. *
  698. * This is used when moving a double buffered window around. It will
  699. * work for all configurations.
  700. *
  701. \**************************************************************************/
  702. void
  703. MTKWIN::UpdateDoubleBufWin()
  704. {
  705. RECT updateRect;
  706. // Update the back buffer
  707. #if 0
  708. (*AnimateFunc)( DataPtr );
  709. #else
  710. (*AnimateFunc)();
  711. #endif
  712. // Swap to the new window position
  713. SwapBuffers( hdc );
  714. }
  715. #endif
  716. /**************************************************************************\
  717. * GetSSWindowRect
  718. *
  719. * Return window position and size in supplied RECT structure
  720. *
  721. * - This rect is relative to the parent
  722. \**************************************************************************/
  723. void
  724. MTKWIN::GetSSWindowRect( LPRECT lpRect )
  725. {
  726. lpRect->left = pos.x;
  727. lpRect->top = pos.y;
  728. lpRect->right = pos.x + size.width;
  729. lpRect->bottom = pos.y + size.height;
  730. }
  731. /**************************************************************************\
  732. * GLPosY
  733. *
  734. * Return y-coord of window position in GL coordinates (a win32 window position
  735. * (starts from top left, while GL starts from bottom left)
  736. *
  737. \**************************************************************************/
  738. int
  739. MTKWIN::GLPosY()
  740. {
  741. //mf: !!!
  742. #if 0
  743. return psswParent->size.height - size.height - pos.y;
  744. #else
  745. return 0;
  746. #endif
  747. }
  748. /**************************************************************************\
  749. * SwapBuffers
  750. *
  751. \**************************************************************************/
  752. //mf: name problem...
  753. void
  754. MTKWIN::mtkSwapBuffers()
  755. {
  756. if( bDoubleBuf ) {
  757. if( pBackBitmap )
  758. CopyBackBuffer();
  759. else
  760. SwapBuffers( hdc );
  761. }
  762. }
  763. /**************************************************************************\
  764. *
  765. *
  766. \**************************************************************************/
  767. void
  768. MTKWIN::Flush()
  769. {
  770. glFlush();
  771. if( bDoubleBuf ) {
  772. mtkSwapBuffers();
  773. }
  774. }
  775. /**************************************************************************\
  776. * CopyBackBuffer
  777. *
  778. * Like SwapBuffers, but copies from local bitmap to front buffer
  779. *
  780. * Also capable of copying over 1 or more rects of the bitmap, rather than the
  781. * whole thing. mf: Might need local implementation of swaphintrect here, to
  782. * collect and reduce the rects
  783. \**************************************************************************/
  784. void
  785. MTKWIN::CopyBackBuffer()
  786. {
  787. if( !pBackBitmap )
  788. return;
  789. // Do a BitBlt from back buffer to the window (may as well put stretch in
  790. // here ?
  791. if( (size.width == pBackBitmap->size.width) &&
  792. (size.height == pBackBitmap->size.height) ) // buffers same size
  793. {
  794. BitBlt(hdc, 0, 0, size.width, size.height,
  795. pBackBitmap->hdc, 0, 0, SRCCOPY);
  796. }
  797. else
  798. {
  799. SS_WARNING( "MTKWIN::CopyBackBuffer: bitmap size mismatch\n" );
  800. StretchBlt(hdc, 0, 0,
  801. size.width, size.height,
  802. pBackBitmap->hdc, 0, 0,
  803. pBackBitmap->size.width, pBackBitmap->size.height,
  804. SRCCOPY);
  805. }
  806. GdiFlush();
  807. }
  808. /**************************************************************************\
  809. * UpdateBackgroundBitmap
  810. *
  811. * Updates the background bitmap with screen bits
  812. *
  813. \**************************************************************************/
  814. void
  815. MTKWIN::UpdateBackgroundBitmap( RECT *pRect )
  816. {
  817. if( !pBackgroundBitmap ) {
  818. SS_WARNING( "MTKWIN::UpdateBackgroundBitmap : No background bitmap\n" );
  819. return;
  820. }
  821. // mf:!!! handle update rect parameter
  822. MTKBMP *pBmpDest = pBackgroundBitmap;
  823. // Get a screen DC
  824. HDC hdcScreen = GetDC( NULL );
  825. #if DBG
  826. if( !hdcScreen ) {
  827. SS_WARNING( "MTKWIN::UpdateBackgroundBitmap : failed to get screen hdc\n" );
  828. return;
  829. }
  830. #endif
  831. //mf
  832. #if 0
  833. SS_DBGPRINT4( "MTKWIN::UpdateBackgroundBitmap : %d - %d, %d - %d\n", pRect->left, pRect->right,
  834. pRect->top, pRect->bottom );
  835. #endif
  836. // Calc the screen origin of the window
  837. RECT screenRect = {0, 0 }; // just need left and top points
  838. MapWindowPoints( hwnd, NULL, (POINT *) &screenRect, 2 );
  839. // Offset screenRect with the supplied rect
  840. screenRect.left += pRect->left;
  841. screenRect.top += pRect->top;
  842. // Set update size
  843. //mf: thought I should have to add 1 here, but I guess pRect is non-inclusive...
  844. ISIZE updateSize = { pRect->right - pRect->left,
  845. pRect->bottom - pRect->top };
  846. if( (size.width == pBmpDest->size.width) &&
  847. (size.height == pBmpDest->size.height) ) // buffers same size
  848. {
  849. BitBlt(pBmpDest->hdc,
  850. pRect->left, pRect->top,
  851. updateSize.width, updateSize.height,
  852. hdcScreen,
  853. screenRect.left, screenRect.top, SRCCOPY);
  854. }
  855. else
  856. {
  857. #if 0
  858. //mf: ignore this for now
  859. // Shouldn't happen, since BackgroundBitmap tracks window size
  860. StretchBlt(pBmpDest->hdc, 0, 0,
  861. pBmpDest->size.width, pBmpDest->size.height,
  862. hdcScreen, screenRect.left, screenRect.top,
  863. size.width, size.height,
  864. SRCCOPY);
  865. #else
  866. SS_WARNING( "MTKWIN::UpdateBackgroundBitmap : bitmap size mismatch\n" );
  867. #endif
  868. }
  869. GdiFlush();
  870. }
  871. /**************************************************************************\
  872. * ClearToBackground
  873. *
  874. * Copy from the background bitmap to the window. If the window is doublebuf,
  875. * then we copy to the backbuffer instead of the window.
  876. *
  877. \**************************************************************************/
  878. void
  879. MTKWIN::ClearToBackground()
  880. {
  881. if( !pBackgroundBitmap ) {
  882. SS_WARNING( "MTKWIN::ClearToBackgournd : No background bitmap\n" );
  883. return;
  884. }
  885. MTKBMP *pBmpSrc = pBackgroundBitmap;
  886. HDC hdcDest;
  887. if( bDoubleBuf ) {
  888. if( !pBackBitmap )
  889. return;
  890. //mf: assumption here that backbitmap size is same as window
  891. hdcDest = pBackBitmap->hdc;
  892. } else
  893. hdcDest = hdc;
  894. if( (size.width == pBmpSrc->size.width) &&
  895. (size.height == pBmpSrc->size.height) ) // buffers same size
  896. {
  897. BitBlt(hdcDest, 0, 0, size.width, size.height,
  898. pBmpSrc->hdc, 0, 0, SRCCOPY);
  899. }
  900. else
  901. {
  902. StretchBlt(hdcDest, 0, 0,
  903. size.width, size.height,
  904. pBmpSrc->hdc, 0, 0,
  905. pBmpSrc->size.width, pBmpSrc->size.height,
  906. SRCCOPY);
  907. }
  908. GdiFlush();
  909. }
  910. /**************************************************************************\
  911. * Reshape
  912. *
  913. * Reshape wrapper
  914. * Sends reshape msg to screen saver
  915. * This is the size of the surface that gl renders onto, which can be a bitmap.
  916. *
  917. \**************************************************************************/
  918. void
  919. MTKWIN::Reshape()
  920. {
  921. // Point to size of window, or bitmap if it has one
  922. ISIZE *pSize = &size;
  923. // If the window has an hrc, set default viewport
  924. //mf: so app doesn't have to worry about it ?
  925. if( hrc ) {
  926. glViewport( 0, 0, pSize->width, pSize->height );
  927. }
  928. if( ReshapeFunc ) {
  929. #if 0
  930. (*ReshapeFunc)( pSize->width, pSize->height, DataPtr );
  931. #else
  932. (*ReshapeFunc)( pSize->width, pSize->height );
  933. #endif
  934. }
  935. }
  936. /******************************Public*Routine******************************\
  937. * GdiClear
  938. *
  939. * Clears window using Gdi FillRect
  940. \**************************************************************************/
  941. void
  942. MTKWIN::GdiClear()
  943. {
  944. if( !hdc )
  945. return;
  946. RECT rect;
  947. GetClientRect( hwnd, &rect );
  948. //mf: rect is exclusive, so shouldn't we have to add 1 ?
  949. FillRect( hdc, &rect, ghbrbg );
  950. GdiFlush();
  951. }
  952. //mf: unicode...
  953. void
  954. MTKWIN::SetTitle( char *title )
  955. {
  956. SetWindowText( hwnd, title );
  957. }