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.

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