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.

412 lines
10 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: clear.cxx
  3. *
  4. * Window clearing functions
  5. *
  6. * Copyright (c) 1996 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <windows.h>
  13. #include <sys/timeb.h>
  14. #include <GL/gl.h>
  15. #include <sys/types.h>
  16. #include <sys/timeb.h>
  17. #include <time.h>
  18. #include <math.h>
  19. #include "mtk.h"
  20. #include "timer.hxx"
  21. #include "util.hxx"
  22. #include "clear.hxx"
  23. #define SS_CLEAR_BASE_DIV 32
  24. #define SS_CLEAR_BASE_SIZE 16
  25. /******************************Public*Routine******************************\
  26. * ss_RectWipeClear
  27. *
  28. * Clears by drawing top, bottom, left, right rectangles that shrink in size
  29. * towards the center.
  30. *
  31. * Calibration is used to try to maintain an ideal clear time.
  32. *
  33. \**************************************************************************/
  34. int
  35. mtk_RectWipeClear( int width, int height, int repCount )
  36. {
  37. int i, j, xinc, yinc, numDivs;
  38. int xmin, xmax, ymin, ymax;
  39. int w, h;
  40. BOOL bCalibrate = FALSE;
  41. float elapsed;
  42. static float idealTime = 0.7f;
  43. TIMER timer;
  44. xinc = 1;
  45. yinc = 1;
  46. numDivs = height; // assumes height <= width
  47. xmin = ymin = 0;
  48. xmax = width-1;
  49. ymax = height-1;
  50. glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
  51. glEnable( GL_SCISSOR_TEST );
  52. if( repCount == 0 ) {
  53. bCalibrate = TRUE;
  54. repCount = 1;
  55. timer.Start();
  56. }
  57. for( i = 0; i < (numDivs/2); i ++ ) {
  58. w = xmax - xmin + 1;
  59. h = ymax - ymin + 1;
  60. for( j = 0; j < repCount; j ++ ) {
  61. // bottom
  62. glScissor( xmin, ymin, w, 1 );
  63. glClear( GL_COLOR_BUFFER_BIT );
  64. // left
  65. glScissor( xmin, ymin, 1, h );
  66. glClear( GL_COLOR_BUFFER_BIT );
  67. // right
  68. glScissor( xmax, ymin, 1, h );
  69. glClear( GL_COLOR_BUFFER_BIT );
  70. // top
  71. glScissor( xmin, ymax, w, 1 );
  72. glClear( GL_COLOR_BUFFER_BIT );
  73. glFlush(); // to eliminate 'bursts'
  74. }
  75. xmin += xinc;
  76. xmax -= xinc;
  77. ymin += yinc;
  78. ymax -= yinc;
  79. }
  80. if( bCalibrate ) {
  81. elapsed = timer.Stop();
  82. // try to maintain ideal clear time
  83. if( elapsed < idealTime ) {
  84. // increase repCount to slow down the clear
  85. if( elapsed == 0.0 )
  86. repCount = 10; // just in case
  87. else
  88. repCount = (int) ((idealTime / elapsed) + 0.5);
  89. }
  90. }
  91. glDisable( GL_SCISSOR_TEST );
  92. return repCount;
  93. }
  94. #define SS_CLEAR_BASE_DIV 32
  95. /******************************Public*Routine******************************\
  96. *
  97. * SS_DIGITAL_DISSOLVE_CLEAR constructor
  98. *
  99. \**************************************************************************/
  100. SS_DIGITAL_DISSOLVE_CLEAR::
  101. SS_DIGITAL_DISSOLVE_CLEAR()
  102. {
  103. rectBuf = NULL;
  104. rectBufSize = 0;
  105. rectSize = SS_CLEAR_BASE_SIZE;
  106. }
  107. /******************************Public*Routine******************************\
  108. *
  109. * SS_DIGITAL_DISSOLVE_CLEAR destructor
  110. *
  111. \**************************************************************************/
  112. SS_DIGITAL_DISSOLVE_CLEAR::
  113. ~SS_DIGITAL_DISSOLVE_CLEAR()
  114. {
  115. if( rectBuf )
  116. LocalFree( rectBuf );
  117. }
  118. /******************************Public*Routine******************************\
  119. * CalibrateClear
  120. *
  121. * Try to calibrate the clear so it takes the specified time
  122. \**************************************************************************/
  123. //#define AUTO_CALIBRATE 1
  124. int SS_DIGITAL_DISSOLVE_CLEAR::
  125. CalibrateClear( int width, int height, float fClearTime )
  126. {
  127. float factor;
  128. int idealNRects;
  129. int nRects;
  130. int baseSize;
  131. TIMER timer;
  132. float elapsed;
  133. baseSize = (width < height ? width : height) / SS_CLEAR_BASE_DIV;
  134. if( baseSize == 0 )
  135. baseSize = 1;
  136. timer.Start();
  137. #ifdef AUTO_CALIBRATE
  138. // Clear a small region (quarter-screen) and extrapolate
  139. Clear( width >> 1, height >> 1, baseSize );
  140. #else
  141. Clear( width, height, baseSize );
  142. #endif
  143. elapsed = timer.Stop();
  144. #ifdef AUTO_CALIBRATE
  145. // extrapolate to full screen time
  146. // mf: this approximation resulted in clears being somewhat less than ideal
  147. // I guess this means more time than I thought was spent in scanning up
  148. // or down for uncleared rects
  149. elapsed *= 4.0f;
  150. #endif
  151. // Adjust size of rects for ideal clear time
  152. if( elapsed <= 0.0f ) {
  153. rectSize = 1;
  154. return rectSize;
  155. }
  156. nRects = RectangleCount( width, height, baseSize );
  157. factor = fClearTime / elapsed;
  158. idealNRects = (int) (factor * (float)nRects);
  159. rectSize = (int) (sqrt( (double)(width*height) / (double)idealNRects ) + 0.5);
  160. if( rectSize == 0 )
  161. rectSize = 1;
  162. return rectSize;
  163. }
  164. /******************************Public*Routine******************************\
  165. *
  166. * SS_DIGITAL_DISSOLVE_CLEAR::Clear
  167. *
  168. * Clears by drawing random rectangles
  169. *
  170. \**************************************************************************/
  171. BOOL SS_DIGITAL_DISSOLVE_CLEAR::
  172. Clear( int width, int height )
  173. {
  174. return Clear( width, height, rectSize );
  175. }
  176. BOOL SS_DIGITAL_DISSOLVE_CLEAR::
  177. Clear( int width, int height, int size )
  178. {
  179. BOOL *pRect;
  180. BOOL bCalibrate = FALSE;
  181. int count, nRects;
  182. int i, xdim, ydim;
  183. static float idealTime = 2.0f;
  184. if( (size <= 0) || !width || !height )
  185. return FALSE;
  186. // determine xdim, ydim from size
  187. xdim = SS_ROUND_UP( (float)width / (float)size );
  188. ydim = SS_ROUND_UP( (float)height / (float) size );
  189. // figure out how many rects needed
  190. count = nRects = xdim * ydim;
  191. // make sure enough room
  192. if( !ValidateBufSize( nRects ) )
  193. return FALSE;
  194. // reset the rect array to uncleared
  195. pRect = rectBuf;
  196. for( i = 0; i < count; i ++, pRect++ )
  197. *pRect = FALSE;
  198. // Clear random rectangles
  199. glEnable( GL_SCISSOR_TEST );
  200. while( count ) {
  201. // pick a random rect
  202. i = ss_iRand( nRects );
  203. if( rectBuf[i] ) {
  204. // This rect has already been cleared - find an empty one
  205. // Scan up and down from x,y, looking at the array linearly
  206. int up, down;
  207. BOOL searchUp = FALSE;
  208. up = down = i;
  209. pRect = rectBuf;
  210. while( *(pRect + i) ) {
  211. if( searchUp ) {
  212. // search up side
  213. if( up < (nRects-1) ) {
  214. up++;
  215. }
  216. i = up;
  217. } else {
  218. // search down side
  219. if( down > 0 ) {
  220. down--;
  221. }
  222. i = down;
  223. }
  224. searchUp = !searchUp;
  225. }
  226. }
  227. // clear the x,y rect
  228. glScissor( (i % xdim)*size, (i / xdim)*size, size, size );
  229. glClear( GL_COLOR_BUFFER_BIT );
  230. glFlush();
  231. rectBuf[i] = TRUE; // mark as taken
  232. count--;
  233. }
  234. glDisable( GL_SCISSOR_TEST );
  235. return TRUE;
  236. }
  237. /******************************Public*Routine******************************\
  238. * RectangleCount
  239. *
  240. \**************************************************************************/
  241. int SS_DIGITAL_DISSOLVE_CLEAR::
  242. RectangleCount( int width, int height, int size )
  243. {
  244. return SS_ROUND_UP( (float)width / (float)size ) *
  245. SS_ROUND_UP( (float)height / (float) size );
  246. }
  247. /******************************Public*Routine******************************\
  248. * ValidateBufSize
  249. *
  250. \**************************************************************************/
  251. BOOL SS_DIGITAL_DISSOLVE_CLEAR::
  252. ValidateBufSize( int nRects )
  253. {
  254. if( nRects > rectBufSize ) {
  255. // need a bigger rect buf
  256. BOOL *r = (BOOL *) LocalAlloc( LMEM_FIXED, sizeof(BOOL) * nRects );
  257. if( !r )
  258. return FALSE;
  259. if( rectBuf )
  260. LocalFree( rectBuf );
  261. rectBuf = r;
  262. rectBufSize = nRects;
  263. }
  264. return TRUE;
  265. }
  266. /******************************Public*Routine******************************\
  267. * DrawGdiRect
  268. *
  269. * Clears the rect with the brush
  270. \**************************************************************************/
  271. void
  272. DrawGdiRect( HDC hdc, HBRUSH hbr, RECT *pRect )
  273. {
  274. if( pRect == NULL )
  275. return;
  276. FillRect( hdc, pRect, hbr );
  277. GdiFlush();
  278. }
  279. #ifdef SS_INITIAL_CLEAR
  280. /*-----------------------------------------------------------------------
  281. |
  282. | RectWipeClear(width, height):
  283. | - Does a rectangular wipe (or clear) by drawing in a sequence
  284. | of rectangles using Gdi
  285. | MOD: add calibrator capability to adjust speed for different
  286. | architectures
  287. | MOD: this can be further optimized by caching the brush
  288. |
  289. -----------------------------------------------------------------------*/
  290. void
  291. mtk_GdiRectWipeClear( HWND hwnd, int width, int height )
  292. {
  293. HDC hdc;
  294. HBRUSH hbr;
  295. RECT rect;
  296. int i, j, xinc, yinc, numDivs = 500;
  297. int xmin, xmax, ymin, ymax;
  298. int repCount = 10;
  299. xinc = 1;
  300. yinc = 1;
  301. numDivs = height;
  302. xmin = ymin = 0;
  303. xmax = width;
  304. ymax = height;
  305. hdc = GetDC( hwnd );
  306. hbr = CreateSolidBrush( RGB( 0, 0, 0 ) );
  307. for( i = 0; i < (numDivs/2 - 1); i ++ ) {
  308. for( j = 0; j < repCount; j ++ ) {
  309. rect.left = xmin; rect.top = ymin;
  310. rect.right = xmax; rect.bottom = ymin + yinc;
  311. FillRect( hdc, &rect, hbr );
  312. rect.top = ymax - yinc;
  313. rect.bottom = ymax;
  314. FillRect( hdc, &rect, hbr );
  315. rect.top = ymin + yinc;
  316. rect.right = xmin + xinc; rect.bottom = ymax - yinc;
  317. FillRect( hdc, &rect, hbr );
  318. rect.left = xmax - xinc; rect.top = ymin + yinc;
  319. rect.right = xmax; rect.bottom = ymax - yinc;
  320. FillRect( hdc, &rect, hbr );
  321. }
  322. xmin += xinc;
  323. xmax -= xinc;
  324. ymin += yinc;
  325. ymax -= yinc;
  326. }
  327. // clear last square in middle
  328. rect.left = xmin; rect.top = ymin;
  329. rect.right = xmax; rect.bottom = ymax;
  330. FillRect( hdc, &rect, hbr );
  331. DeleteObject( hbr );
  332. ReleaseDC( hwnd, hdc );
  333. GdiFlush();
  334. }
  335. #endif // SS_INITIAL_CLEAR