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.

4082 lines
119 KiB

  1. /*
  2. ** Copyright 1991,1992, Silicon Graphics, Inc.
  3. ** All Rights Reserved.
  4. **
  5. ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6. ** the contents of this file may not be disclosed to third parties, copied or
  7. ** duplicated in any form, in whole or in part, without the prior written
  8. ** permission of Silicon Graphics, Inc.
  9. **
  10. ** RESTRICTED RIGHTS LEGEND:
  11. ** Use, duplication or disclosure by the Government is subject to restrictions
  12. ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13. ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14. ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15. ** rights reserved under the Copyright Laws of the United States.
  16. */
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. #include "imports.h"
  20. #include "gencx.h"
  21. #include "px_fast.h"
  22. // Disable long to float conversion warning. see also context.h
  23. #pragma warning (disable:4244)
  24. /*
  25. ** This routine clips a draw pixels box, and sets up a bunch of
  26. ** variables required for drawing the box. These are some of them:
  27. **
  28. ** startCol - The first column that will be drawn.
  29. ** x - Effective raster position. This will be set up so that
  30. ** every time zoomx is added, a change in the integer portion
  31. ** of x indicates that a pixel should rendered (unpacked).
  32. ** columns - The total number of columns that will be rendered.
  33. **
  34. ** Others are startRow, y, rows.
  35. **
  36. ** Yet other variables may be modified, such as width, height, skipPixels,
  37. ** skipLines.
  38. **
  39. ** The clipping routine is written very carefully so that a fragment will
  40. ** be rasterized by a pixel if it's center falls within the range
  41. ** [x, x+zoomx) x [y, y+zoomy).
  42. */
  43. GLboolean FASTCALL __glClipDrawPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  44. {
  45. GLint skipPixels;
  46. GLint skipRows;
  47. GLint width, height;
  48. GLint tempint;
  49. GLint endCol, endRow;
  50. __GLfloat x,y,x2,y2;
  51. __GLfloat zoomx, zoomy;
  52. __GLfloat clipLeft, clipRight, clipBottom, clipTop;
  53. zoomx = spanInfo->zoomx;
  54. zoomy = spanInfo->zoomy;
  55. if (zoomx == __glZero || zoomy == __glZero) {
  56. return GL_FALSE;
  57. }
  58. skipPixels = skipRows = 0;
  59. width = spanInfo->width;
  60. height = spanInfo->height;
  61. clipLeft = gc->transform.clipX0 + __glHalf;
  62. clipBottom = gc->transform.clipY0 + __glHalf;
  63. clipRight = gc->transform.clipX1 - gc->constants.viewportAlmostHalf;
  64. clipTop = gc->transform.clipY1 - gc->constants.viewportAlmostHalf;
  65. x = spanInfo->x;
  66. y = spanInfo->y;
  67. x2 = x + zoomx * width;
  68. y2 = y + zoomy * height;
  69. if (zoomx > 0) {
  70. /* Zoomx is positive, clip the left edge */
  71. if (x > clipLeft) {
  72. /* Clip to the first fragment that will be produced */
  73. clipLeft = (GLint) (x + gc->constants.viewportAlmostHalf);
  74. clipLeft += __glHalf;
  75. }
  76. skipPixels = (clipLeft-x) / zoomx;
  77. if (skipPixels >= width) return GL_FALSE;
  78. width -= skipPixels;
  79. spanInfo->startCol = clipLeft;
  80. x = x + skipPixels * zoomx;
  81. spanInfo->x = x + gc->constants.viewportAlmostHalf;
  82. spanInfo->srcSkipPixels += skipPixels;
  83. /* Zoomx is positive, clip the right edge */
  84. if (x2 < clipRight) {
  85. /* Clip to the last fragment that will be produced */
  86. clipRight = (GLint) (x2 + gc->constants.viewportAlmostHalf);
  87. clipRight -= gc->constants.viewportAlmostHalf;
  88. }
  89. tempint = (x2-clipRight) / zoomx;
  90. if (tempint >= width) return GL_FALSE;
  91. width -= tempint;
  92. endCol = (GLint) clipRight + 1;
  93. spanInfo->endCol = endCol;
  94. spanInfo->columns = endCol - spanInfo->startCol;
  95. } else /* zoomx < 0 */ {
  96. /* Zoomx is negative, clip the right edge */
  97. if (x < clipRight) {
  98. /* Clip to the first fragment that will be produced */
  99. clipRight = (GLint) (x + gc->constants.viewportAlmostHalf);
  100. clipRight -= gc->constants.viewportAlmostHalf;
  101. }
  102. skipPixels = (clipRight-x) / zoomx;
  103. if (skipPixels >= width) return GL_FALSE;
  104. width -= skipPixels;
  105. spanInfo->startCol = clipRight;
  106. x = x + skipPixels * zoomx;
  107. spanInfo->x = x + gc->constants.viewportAlmostHalf - __glOne;
  108. spanInfo->srcSkipPixels += skipPixels;
  109. /* Zoomx is negative, clip the left edge */
  110. if (x2 > clipLeft) {
  111. clipLeft = (GLint) (x2 + gc->constants.viewportAlmostHalf);
  112. clipLeft += __glHalf;
  113. }
  114. tempint = (x2-clipLeft) / zoomx;
  115. if (tempint >= width) return GL_FALSE;
  116. width -= tempint;
  117. endCol = (GLint) clipLeft - 1;
  118. spanInfo->endCol = endCol;
  119. spanInfo->columns = spanInfo->startCol - endCol;
  120. }
  121. if (zoomy > 0) {
  122. /* Zoomy is positive, clip the bottom edge */
  123. if (y > clipBottom) {
  124. /* Clip to the first row that will be produced */
  125. clipBottom = (GLint) (y + gc->constants.viewportAlmostHalf);
  126. clipBottom += __glHalf;
  127. }
  128. skipRows = (clipBottom-y) / zoomy;
  129. if (skipRows >= height) return GL_FALSE;
  130. height -= skipRows;
  131. spanInfo->startRow = clipBottom;
  132. y = y + skipRows * zoomy;
  133. spanInfo->y = y + gc->constants.viewportAlmostHalf;
  134. spanInfo->srcSkipLines += skipRows;
  135. /* Zoomy is positive, clip the top edge */
  136. if (y2 < clipTop) {
  137. /* Clip to the last row that will be produced */
  138. clipTop = (GLint) (y2 + gc->constants.viewportAlmostHalf);
  139. clipTop -= gc->constants.viewportAlmostHalf;
  140. }
  141. tempint = (y2-clipTop) / zoomy;
  142. if (tempint >= height) return GL_FALSE;
  143. height -= tempint;
  144. endRow = (GLint) clipTop + 1;
  145. spanInfo->rows = endRow - spanInfo->startRow;
  146. } else /* zoomy < 0 */ {
  147. /* Zoomy is negative, clip the top edge */
  148. if (y < clipTop) {
  149. /* Clip to the first row that will be produced */
  150. clipTop = (GLint) (y + gc->constants.viewportAlmostHalf);
  151. clipTop -= gc->constants.viewportAlmostHalf;
  152. }
  153. skipRows = (clipTop-y) / zoomy;
  154. if (skipRows >= height) return GL_FALSE;
  155. height -= skipRows;
  156. spanInfo->startRow = clipTop;
  157. y = y + skipRows * zoomy;
  158. /* spanInfo->y = y - __glHalf; */
  159. spanInfo->y = y + gc->constants.viewportAlmostHalf - __glOne;
  160. spanInfo->srcSkipLines += skipRows;
  161. /* Zoomy is negative, clip the bottom edge */
  162. if (y2 > clipBottom) {
  163. clipBottom = (GLint) (y2 + gc->constants.viewportAlmostHalf);
  164. clipBottom += __glHalf;
  165. }
  166. tempint = (y2-clipBottom) / zoomy;
  167. if (tempint >= height) return GL_FALSE;
  168. height -= tempint;
  169. endRow = (GLint) clipBottom - 1;
  170. spanInfo->rows = spanInfo->startRow - endRow;
  171. }
  172. spanInfo->width = width;
  173. spanInfo->height = height;
  174. if (zoomx < 0) zoomx = -zoomx;
  175. if (zoomx >= 1) {
  176. spanInfo->realWidth = width;
  177. } else {
  178. spanInfo->realWidth = spanInfo->columns;
  179. }
  180. return GL_TRUE;
  181. }
  182. /*
  183. ** This routine computes spanInfo->pixelArray if needed.
  184. **
  185. ** If |zoomx| > 1.0, this array contains counts for how many times to
  186. ** replicate a given pixel. For example, if zoomx is 2.0, this array will
  187. ** contain all 2's. If zoomx is 1.5, then every other entry will contain
  188. ** a 2, and every other entry will contain a 1.
  189. **
  190. ** if |zoomx| < 1.0, this array contains counts for how many pixels to
  191. ** skip. For example, if zoomx is 0.5, every entry in the array will contain
  192. ** a 2 (indicating to skip forward two pixels [only past one]). If zoomx is
  193. ** .666, then every other entry will be a 2, and every other entry will be
  194. ** a 1.
  195. */
  196. void FASTCALL __glComputeSpanPixelArray(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  197. {
  198. GLint width, intx;
  199. __GLfloat zoomx, oldx, newx;
  200. GLint i;
  201. GLshort *array;
  202. zoomx = spanInfo->zoomx;
  203. if (zoomx > (__GLfloat) -1.0 && zoomx < __glOne) {
  204. GLint lasti;
  205. /* Build pixel skip array */
  206. width = spanInfo->width;
  207. oldx = spanInfo->x;
  208. array = spanInfo->pixelArray;
  209. intx = (GLint) oldx;
  210. newx = oldx;
  211. lasti = 0;
  212. for (i=0; i<width; i++) {
  213. /* Skip groups which will not be rasterized */
  214. newx += zoomx;
  215. while ((GLint) newx == intx && i<width) {
  216. newx += zoomx;
  217. i++;
  218. }
  219. ASSERTOPENGL(i != width, "Pixel skip array overflow\n");
  220. if (i != 0) {
  221. *array++ = (GLshort) (i - lasti);
  222. }
  223. lasti = i;
  224. intx = (GLint) newx;
  225. }
  226. *array++ = 1;
  227. } else if (zoomx < (__GLfloat) -1.0 || zoomx > __glOne) {
  228. __GLfloat right;
  229. GLint iright;
  230. GLint coladd, column;
  231. GLint startCol;
  232. /* Build pixel replication array */
  233. width = spanInfo->realWidth - 1;
  234. startCol = spanInfo->startCol;
  235. column = startCol;
  236. coladd = spanInfo->coladd;
  237. array = spanInfo->pixelArray;
  238. right = spanInfo->x;
  239. for (i=0; i<width; i++) {
  240. right = right + zoomx;
  241. iright = right;
  242. *array++ = (GLshort) (iright - column);
  243. column = iright;
  244. }
  245. if (coladd == 1) {
  246. *array++ = (GLshort) (spanInfo->columns - (column - startCol));
  247. } else {
  248. *array++ = (GLshort) ((startCol - column) - spanInfo->columns);
  249. }
  250. }
  251. }
  252. /*
  253. ** Initialize the spanInfo structure. If "packed" is true, the structure
  254. ** is initialized for unpacking data from a display list. If "packed" is
  255. ** false, it is initialized for unpacking data from the user's data space.
  256. */
  257. void FASTCALL __glLoadUnpackModes(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  258. GLboolean packed)
  259. {
  260. if (packed) {
  261. /*
  262. ** Data came from a display list.
  263. */
  264. spanInfo->srcAlignment = 1;
  265. spanInfo->srcSkipPixels = 0;
  266. spanInfo->srcSkipLines = 0;
  267. spanInfo->srcLsbFirst = GL_FALSE;
  268. spanInfo->srcSwapBytes = GL_FALSE;
  269. spanInfo->srcLineLength = spanInfo->width;
  270. } else {
  271. GLint lineLength;
  272. /*
  273. ** Data came straight from the application.
  274. */
  275. lineLength = gc->state.pixel.unpackModes.lineLength;
  276. spanInfo->srcAlignment = gc->state.pixel.unpackModes.alignment;
  277. spanInfo->srcSkipPixels = gc->state.pixel.unpackModes.skipPixels;
  278. spanInfo->srcSkipLines = gc->state.pixel.unpackModes.skipLines;
  279. spanInfo->srcLsbFirst = gc->state.pixel.unpackModes.lsbFirst;
  280. spanInfo->srcSwapBytes = gc->state.pixel.unpackModes.swapEndian;
  281. #ifdef NT
  282. /* XXX! kluge? (mf) : Since the routines that unpack incoming data from
  283. glTexImage commands use spanInfo->realWidth to determine how
  284. much to unpack, set this approppriately when lineLength > 0
  285. */
  286. if (lineLength <= 0)
  287. lineLength = spanInfo->width;
  288. else
  289. spanInfo->realWidth = lineLength; /* otherwise, use value for
  290. realWidth already set */
  291. #else
  292. if (lineLength <= 0) lineLength = spanInfo->width;
  293. #endif
  294. spanInfo->srcLineLength = lineLength;
  295. }
  296. }
  297. void __glInitDrawPixelsInfo(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  298. GLint width, GLint height, GLenum format,
  299. GLenum type, const GLvoid *pixels)
  300. {
  301. __GLfloat x,y;
  302. __GLfloat zoomx, zoomy;
  303. x = gc->state.current.rasterPos.window.x;
  304. y = gc->state.current.rasterPos.window.y;
  305. spanInfo->x = x;
  306. spanInfo->y = y;
  307. spanInfo->fragz = gc->state.current.rasterPos.window.z;
  308. zoomx = gc->state.pixel.transferMode.zoomX;
  309. if (zoomx > __glZero) {
  310. if (zoomx < __glOne) {
  311. spanInfo->rendZoomx = __glOne;
  312. } else {
  313. spanInfo->rendZoomx = zoomx;
  314. }
  315. spanInfo->coladd = 1;
  316. } else {
  317. if (zoomx > (GLfloat) -1.0) {
  318. spanInfo->rendZoomx = (GLfloat) -1.0;
  319. } else {
  320. spanInfo->rendZoomx = zoomx;
  321. }
  322. spanInfo->coladd = -1;
  323. }
  324. spanInfo->zoomx = zoomx;
  325. zoomy = gc->state.pixel.transferMode.zoomY;
  326. if (gc->constants.yInverted) {
  327. zoomy = -zoomy;
  328. }
  329. if (zoomy > __glZero) {
  330. spanInfo->rowadd = 1;
  331. } else {
  332. spanInfo->rowadd = -1;
  333. }
  334. spanInfo->zoomy = zoomy;
  335. spanInfo->width = width;
  336. spanInfo->height = height;
  337. if (format == GL_COLOR_INDEX && gc->modes.rgbMode) {
  338. spanInfo->dstFormat = GL_RGBA;
  339. } else {
  340. spanInfo->dstFormat = format;
  341. }
  342. spanInfo->srcFormat = format;
  343. spanInfo->srcType = type;
  344. spanInfo->srcImage = pixels;
  345. }
  346. /*
  347. ** This is the generic DrawPixels routine. It applies four span modification
  348. ** routines followed by a span rendering routine.
  349. */
  350. void FASTCALL __glDrawPixels4(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  351. {
  352. int i;
  353. __GLfloat zoomy, newy;
  354. GLint inty, height, width;
  355. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  356. GLvoid *inspan, GLvoid *outspan);
  357. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  358. GLvoid *inspan, GLvoid *outspan);
  359. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  360. GLvoid *inspan, GLvoid *outspan);
  361. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  362. GLvoid *inspan, GLvoid *outspan);
  363. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  364. GLvoid *inspan);
  365. #ifdef NT
  366. GLubyte *spanData1, *spanData2;
  367. GLshort *pixelArray;
  368. width = spanInfo->width * 4 * sizeof(GLfloat);
  369. spanData1 = gcTempAlloc(gc, width);
  370. spanData2 = gcTempAlloc(gc, width);
  371. width = spanInfo->width * sizeof(GLshort);
  372. pixelArray = gcTempAlloc(gc, width);
  373. if (!spanData1 || !spanData2 || !pixelArray)
  374. goto __glDrawPixels4_exit;
  375. #else
  376. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  377. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  378. #endif
  379. spanInfo->pixelArray = pixelArray;
  380. __glComputeSpanPixelArray(gc, spanInfo);
  381. span1 = spanInfo->spanModifier[0];
  382. span2 = spanInfo->spanModifier[1];
  383. span3 = spanInfo->spanModifier[2];
  384. span4 = spanInfo->spanModifier[3];
  385. render = spanInfo->spanRender;
  386. zoomy = spanInfo->zoomy;
  387. inty = (GLint) spanInfo->y;
  388. newy = spanInfo->y;
  389. height = spanInfo->height;
  390. width = spanInfo->width;
  391. for (i=0; i<height; i++) {
  392. spanInfo->y = newy;
  393. newy += zoomy;
  394. while ((GLint) newy == inty && i<height) {
  395. spanInfo->y = newy;
  396. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  397. spanInfo->srcRowIncrement;
  398. newy += zoomy;
  399. i++;
  400. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  401. }
  402. inty = (GLint) newy;
  403. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  404. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  405. spanInfo->srcRowIncrement;
  406. (*span2)(gc, spanInfo, spanData1, spanData2);
  407. (*span3)(gc, spanInfo, spanData2, spanData1);
  408. (*span4)(gc, spanInfo, spanData1, spanData2);
  409. (*render)(gc, spanInfo, spanData2);
  410. }
  411. #ifdef NT
  412. __glDrawPixels4_exit:
  413. if (spanData1) gcTempFree(gc, spanData1);
  414. if (spanData2) gcTempFree(gc, spanData2);
  415. if (pixelArray) gcTempFree(gc, pixelArray);
  416. #endif
  417. }
  418. /*
  419. ** This is the generic DrawPixels routine. It applies three span modification
  420. ** routines followed by a span rendering routine.
  421. */
  422. void FASTCALL __glDrawPixels3(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  423. {
  424. int i;
  425. __GLfloat zoomy, newy;
  426. GLint inty, height, width;
  427. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  428. GLvoid *inspan, GLvoid *outspan);
  429. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  430. GLvoid *inspan, GLvoid *outspan);
  431. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  432. GLvoid *inspan, GLvoid *outspan);
  433. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  434. GLvoid *inspan);
  435. #ifdef NT
  436. GLubyte *spanData1, *spanData2;
  437. GLshort *pixelArray;
  438. width = spanInfo->width * 4 * sizeof(GLfloat);
  439. spanData1 = gcTempAlloc(gc, width);
  440. spanData2 = gcTempAlloc(gc, width);
  441. width = spanInfo->width * sizeof(GLshort);
  442. pixelArray = gcTempAlloc(gc, width);
  443. if (!spanData1 || !spanData2 || !pixelArray)
  444. goto __glDrawPixels3_exit;
  445. #else
  446. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  447. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  448. #endif
  449. spanInfo->pixelArray = pixelArray;
  450. __glComputeSpanPixelArray(gc, spanInfo);
  451. span1 = spanInfo->spanModifier[0];
  452. span2 = spanInfo->spanModifier[1];
  453. span3 = spanInfo->spanModifier[2];
  454. render = spanInfo->spanRender;
  455. zoomy = spanInfo->zoomy;
  456. inty = (GLint) spanInfo->y;
  457. newy = spanInfo->y;
  458. height = spanInfo->height;
  459. width = spanInfo->width;
  460. for (i=0; i<height; i++) {
  461. spanInfo->y = newy;
  462. newy += zoomy;
  463. while ((GLint) newy == inty && i<height) {
  464. spanInfo->y = newy;
  465. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  466. spanInfo->srcRowIncrement;
  467. newy += zoomy;
  468. i++;
  469. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  470. }
  471. inty = (GLint) newy;
  472. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  473. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  474. spanInfo->srcRowIncrement;
  475. (*span2)(gc, spanInfo, spanData1, spanData2);
  476. (*span3)(gc, spanInfo, spanData2, spanData1);
  477. (*render)(gc, spanInfo, spanData1);
  478. }
  479. #ifdef NT
  480. __glDrawPixels3_exit:
  481. if (spanData1) gcTempFree(gc, spanData1);
  482. if (spanData2) gcTempFree(gc, spanData2);
  483. if (pixelArray) gcTempFree(gc, pixelArray);
  484. #endif
  485. }
  486. /*
  487. ** This is the generic DrawPixels routine. It applies two span modification
  488. ** routines followed by a span rendering routine.
  489. */
  490. void FASTCALL __glDrawPixels2(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  491. {
  492. int i;
  493. __GLfloat zoomy, newy;
  494. GLint inty, height, width;
  495. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  496. GLvoid *inspan, GLvoid *outspan);
  497. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  498. GLvoid *inspan, GLvoid *outspan);
  499. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  500. GLvoid *inspan);
  501. #ifdef NT
  502. GLubyte *spanData1, *spanData2;
  503. GLshort *pixelArray;
  504. width = spanInfo->width * 4 * sizeof(GLfloat);
  505. spanData1 = gcTempAlloc(gc, width);
  506. spanData2 = gcTempAlloc(gc, width);
  507. width = spanInfo->width * sizeof(GLshort);
  508. pixelArray = gcTempAlloc(gc, width);
  509. if (!spanData1 || !spanData2 || !pixelArray)
  510. goto __glDrawPixels2_exit;
  511. #else
  512. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  513. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  514. #endif
  515. spanInfo->pixelArray = pixelArray;
  516. __glComputeSpanPixelArray(gc, spanInfo);
  517. span1 = spanInfo->spanModifier[0];
  518. span2 = spanInfo->spanModifier[1];
  519. render = spanInfo->spanRender;
  520. zoomy = spanInfo->zoomy;
  521. inty = (GLint) spanInfo->y;
  522. newy = spanInfo->y;
  523. height = spanInfo->height;
  524. width = spanInfo->width;
  525. for (i=0; i<height; i++) {
  526. spanInfo->y = newy;
  527. newy += zoomy;
  528. while ((GLint) newy == inty && i<height) {
  529. spanInfo->y = newy;
  530. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  531. spanInfo->srcRowIncrement;
  532. newy += zoomy;
  533. i++;
  534. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  535. }
  536. inty = (GLint) newy;
  537. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  538. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  539. spanInfo->srcRowIncrement;
  540. (*span2)(gc, spanInfo, spanData1, spanData2);
  541. (*render)(gc, spanInfo, spanData2);
  542. }
  543. #ifdef NT
  544. __glDrawPixels2_exit:
  545. if (spanData1) gcTempFree(gc, spanData1);
  546. if (spanData2) gcTempFree(gc, spanData2);
  547. if (pixelArray) gcTempFree(gc, pixelArray);
  548. #endif
  549. }
  550. /*
  551. ** Draw pixels with only one span modification routine.
  552. */
  553. void FASTCALL __glDrawPixels1(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  554. {
  555. int i;
  556. __GLfloat zoomy, newy;
  557. GLint inty, height;
  558. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  559. GLvoid *inspan, GLvoid *outspan);
  560. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  561. GLvoid *inspan);
  562. #ifdef NT
  563. GLubyte *spanData1;
  564. GLshort *pixelArray;
  565. spanData1 = gcTempAlloc(gc, spanInfo->width * 4 * sizeof(GLfloat));
  566. pixelArray = gcTempAlloc(gc, spanInfo->width * sizeof(GLshort));
  567. if (!spanData1 || !pixelArray)
  568. goto __glDrawPixels1_exit;
  569. #else
  570. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  571. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  572. #endif
  573. spanInfo->pixelArray = pixelArray;
  574. __glComputeSpanPixelArray(gc, spanInfo);
  575. span1 = spanInfo->spanModifier[0];
  576. render = spanInfo->spanRender;
  577. zoomy = spanInfo->zoomy;
  578. inty = (GLint) spanInfo->y;
  579. newy = spanInfo->y;
  580. height = spanInfo->height;
  581. for (i=0; i<height; i++) {
  582. spanInfo->y = newy;
  583. newy += zoomy;
  584. while ((GLint) newy == inty && i<height) {
  585. spanInfo->y = newy;
  586. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  587. spanInfo->srcRowIncrement;
  588. newy += zoomy;
  589. i++;
  590. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  591. }
  592. inty = (GLint) newy;
  593. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  594. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  595. spanInfo->srcRowIncrement;
  596. (*render)(gc, spanInfo, spanData1);
  597. }
  598. #ifdef NT
  599. __glDrawPixels1_exit:
  600. if (spanData1) gcTempFree(gc, spanData1);
  601. if (pixelArray) gcTempFree(gc, pixelArray);
  602. #endif
  603. }
  604. /*
  605. ** Draw pixels with no span modification routines.
  606. */
  607. void FASTCALL __glDrawPixels0(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  608. {
  609. int i;
  610. __GLfloat zoomy, newy;
  611. GLint inty, height;
  612. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  613. GLvoid *inspan);
  614. #ifdef NT
  615. GLshort *pixelArray;
  616. pixelArray = gcTempAlloc(gc, spanInfo->width * sizeof(GLshort));
  617. if (!pixelArray)
  618. return;
  619. #else
  620. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  621. #endif
  622. spanInfo->pixelArray = pixelArray;
  623. __glComputeSpanPixelArray(gc, spanInfo);
  624. render = spanInfo->spanRender;
  625. zoomy = spanInfo->zoomy;
  626. inty = (GLint) spanInfo->y;
  627. newy = spanInfo->y;
  628. height = spanInfo->height;
  629. for (i=0; i<height; i++) {
  630. spanInfo->y = newy;
  631. newy += zoomy;
  632. while ((GLint) newy == inty && i<height) {
  633. spanInfo->y = newy;
  634. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  635. spanInfo->srcRowIncrement;
  636. newy += zoomy;
  637. i++;
  638. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  639. }
  640. inty = (GLint) newy;
  641. (*render)(gc, spanInfo, spanInfo->srcCurrent);
  642. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  643. spanInfo->srcRowIncrement;
  644. }
  645. #ifdef NT
  646. gcTempFree(gc, pixelArray);
  647. #endif
  648. }
  649. /*
  650. ** Generic implementation of a DrawPixels picker. Any machine specific
  651. ** implementation should provide their own.
  652. */
  653. void __glSlowPickDrawPixels(__GLcontext *gc, GLint width, GLint height,
  654. GLenum format, GLenum type, const GLvoid *pixels,
  655. GLboolean packed)
  656. {
  657. __GLpixelSpanInfo spanInfo;
  658. __glInitDrawPixelsInfo(gc, &spanInfo, width, height, format, type, pixels);
  659. __glLoadUnpackModes(gc, &spanInfo, packed);
  660. if (!__glClipDrawPixels(gc, &spanInfo)) return;
  661. __glInitUnpacker(gc, &spanInfo);
  662. __glGenericPickDrawPixels(gc, &spanInfo);
  663. }
  664. /*
  665. ** Generic picker for DrawPixels. This should be called if no machine
  666. ** specific path is provided for this specific version of DrawPixels.
  667. */
  668. void FASTCALL __glGenericPickDrawPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  669. {
  670. __GLpixelMachine *pm;
  671. void (FASTCALL *dpfn)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo);
  672. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  673. GLvoid *inspan);
  674. GLint spanCount;
  675. GLboolean zoomx1; /* -1 <= zoomx <= 1? */
  676. GLboolean zoomx2; /* zoomx <= -1 || zoomx >= 1 */
  677. __GLfloat zoomx;
  678. GLboolean packedUserData;
  679. GLenum type, format;
  680. GLboolean skip;
  681. GLboolean swap;
  682. GLboolean align;
  683. GLboolean convert;
  684. GLboolean expand;
  685. GLboolean clamp;
  686. spanCount = 0;
  687. pm = &gc->pixel;
  688. zoomx = gc->state.pixel.transferMode.zoomX;
  689. if (zoomx >= (__GLfloat) -1.0 && zoomx <= __glOne) {
  690. zoomx1 = GL_TRUE;
  691. } else {
  692. zoomx1 = GL_FALSE;
  693. }
  694. if (zoomx <= (__GLfloat) -1.0 || zoomx >= __glOne) {
  695. zoomx2 = GL_TRUE;
  696. } else {
  697. zoomx2 = GL_FALSE;
  698. }
  699. packedUserData = spanInfo->srcPackedData && zoomx2;
  700. type = spanInfo->srcType;
  701. format = spanInfo->srcFormat;
  702. if (spanInfo->srcSwapBytes && spanInfo->srcElementSize > 1) {
  703. swap = GL_TRUE;
  704. } else {
  705. swap = GL_FALSE;
  706. }
  707. if (zoomx2 || type == GL_BITMAP) {
  708. skip = GL_FALSE;
  709. } else {
  710. skip = GL_TRUE;
  711. }
  712. if (type != GL_BITMAP &&
  713. (((INT_PTR) (spanInfo->srcImage)) & (spanInfo->srcElementSize - 1))) {
  714. align = GL_TRUE;
  715. } else {
  716. align = GL_FALSE;
  717. }
  718. if (type == GL_FLOAT || type == GL_BITMAP) {
  719. convert = GL_FALSE;
  720. } else {
  721. convert = GL_TRUE;
  722. }
  723. /*
  724. ** Clamp types only if index or not modifying (because converting
  725. ** float types means clamping, and that is only done if not modifying),
  726. ** and only if they might need clamping (UNSIGNED types never do).
  727. */
  728. if (type == GL_BITMAP || type == GL_UNSIGNED_BYTE ||
  729. type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT ||
  730. format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX ||
  731. (format == GL_DEPTH_COMPONENT && pm->modifyDepth) ||
  732. (format != GL_DEPTH_COMPONENT && pm->modifyRGBA)) {
  733. clamp = GL_FALSE;
  734. } else {
  735. clamp = GL_TRUE;
  736. }
  737. #ifdef NT
  738. // Special case RGB drawing to use a DIB
  739. // Also special case loading the Z buffer
  740. if (format == GL_RGB || format == GL_BGR_EXT || format == GL_BGRA_EXT)
  741. {
  742. GLuint enables = gc->state.enables.general;
  743. // If the input is unsigned bytes with DWORD aligned scanlines
  744. // and no unusual lengths, then it's almost compatible with
  745. // a 24-bit RGB DIB. The only problem is that OpenGL sees
  746. // it as BGR so the bytes need to be swapped. Since we need to
  747. // copy the data to swap the bytes, we adjust line lengths and
  748. // alignment then, allowing nearly any unsigned byte input format
  749. //
  750. // Other things that can't be allowed are depth testing,
  751. // fogging, blending or anything that prevents the input data
  752. // from going directly into the destination buffer
  753. if (zoomx == __glOne &&
  754. gc->state.pixel.transferMode.zoomY == __glOne &&
  755. type == GL_UNSIGNED_BYTE &&
  756. !pm->modifyRGBA &&
  757. (enables & (__GL_DITHER_ENABLE |
  758. __GL_ALPHA_TEST_ENABLE |
  759. __GL_STENCIL_TEST_ENABLE |
  760. __GL_DEPTH_TEST_ENABLE |
  761. __GL_BLEND_ENABLE |
  762. __GL_INDEX_LOGIC_OP_ENABLE |
  763. __GL_COLOR_LOGIC_OP_ENABLE |
  764. __GL_FOG_ENABLE)) == 0 &&
  765. gc->state.raster.drawBuffer != GL_NONE &&
  766. gc->state.raster.drawBuffer != GL_FRONT_AND_BACK &&
  767. !gc->texture.textureEnabled &&
  768. (gc->drawBuffer->buf.flags & COLORMASK_ON) == 0
  769. #ifdef _MCD_
  770. && ((__GLGENcontext *)gc)->pMcdState == NULL
  771. #endif
  772. )
  773. {
  774. if (DrawRgbPixels(gc, spanInfo))
  775. {
  776. return;
  777. }
  778. }
  779. }
  780. else if (format == GL_DEPTH_COMPONENT)
  781. {
  782. // If the Z test is GL_ALWAYS and there is no draw buffer
  783. // then the application is simply loading Z values into
  784. // the Z buffer.
  785. if (zoomx == __glOne &&
  786. gc->state.pixel.transferMode.zoomY == __glOne &&
  787. !swap &&
  788. (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT) &&
  789. !pm->modifyDepth &&
  790. gc->state.raster.drawBuffer == GL_NONE &&
  791. (gc->state.enables.general & __GL_DEPTH_TEST_ENABLE) &&
  792. gc->state.depth.testFunc == GL_ALWAYS &&
  793. gc->modes.haveDepthBuffer
  794. #ifdef _MCD_
  795. && ((__GLGENcontext *)gc)->pMcdState == NULL
  796. #endif
  797. )
  798. {
  799. if (StoreZPixels(gc, spanInfo))
  800. {
  801. return;
  802. }
  803. }
  804. }
  805. #endif
  806. /*
  807. ** First step: convert data into a packed readable format
  808. ** (RED, BYTE), (LUMINANCE, UNSIGNED_INT), etc... This stage
  809. ** simply packs the user's data, but performs no conversion on it.
  810. **
  811. ** Packing can consist of:
  812. ** - aligning the data
  813. ** - skipping pixels if |xzoom| is < 1
  814. ** - swapping bytes if necessary
  815. */
  816. if (swap) {
  817. if (skip) {
  818. if (spanInfo->srcElementSize == 2) {
  819. spanInfo->spanModifier[spanCount++] =
  820. __glSpanSwapAndSkipBytes2;
  821. } else /* spanInfo->srcElementSize == 4 */ {
  822. spanInfo->spanModifier[spanCount++] =
  823. __glSpanSwapAndSkipBytes4;
  824. }
  825. } else {
  826. if (spanInfo->srcElementSize == 2) {
  827. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes2;
  828. } else /* spanInfo->srcElementSize == 4 */ {
  829. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes4;
  830. }
  831. }
  832. } else if (align) {
  833. if (skip) {
  834. if (spanInfo->srcElementSize == 2) {
  835. spanInfo->spanModifier[spanCount++] = __glSpanSlowSkipPixels2;
  836. } else /* spanInfo->srcElementSize == 4 */ {
  837. spanInfo->spanModifier[spanCount++] = __glSpanSlowSkipPixels4;
  838. }
  839. } else {
  840. if (spanInfo->srcElementSize == 2) {
  841. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels2;
  842. } else /* spanInfo->srcElementSize == 4 */ {
  843. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels4;
  844. }
  845. }
  846. } else if (skip) {
  847. if (spanInfo->srcElementSize == 1) {
  848. spanInfo->spanModifier[spanCount++] = __glSpanSkipPixels1;
  849. } else if (spanInfo->srcElementSize == 2) {
  850. spanInfo->spanModifier[spanCount++] = __glSpanSkipPixels2;
  851. } else /* spanInfo->srcElementSize == 4 */ {
  852. spanInfo->spanModifier[spanCount++] = __glSpanSkipPixels4;
  853. }
  854. }
  855. /*
  856. ** Second step: conversion to float
  857. ** All formats are converted into floating point (including GL_BITMAP).
  858. */
  859. if (convert) {
  860. if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX) {
  861. /* Index conversion */
  862. switch(type) {
  863. case GL_BYTE:
  864. spanInfo->spanModifier[spanCount++] = __glSpanUnpackByteI;
  865. break;
  866. case GL_UNSIGNED_BYTE:
  867. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUbyteI;
  868. break;
  869. case GL_SHORT:
  870. spanInfo->spanModifier[spanCount++] = __glSpanUnpackShortI;
  871. break;
  872. case GL_UNSIGNED_SHORT:
  873. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUshortI;
  874. break;
  875. case GL_INT:
  876. spanInfo->spanModifier[spanCount++] = __glSpanUnpackIntI;
  877. break;
  878. case GL_UNSIGNED_INT:
  879. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUintI;
  880. break;
  881. }
  882. } else {
  883. /* Component conversion */
  884. switch(type) {
  885. case GL_BYTE:
  886. spanInfo->spanModifier[spanCount++] = __glSpanUnpackByte;
  887. break;
  888. case GL_UNSIGNED_BYTE:
  889. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUbyte;
  890. break;
  891. case GL_SHORT:
  892. spanInfo->spanModifier[spanCount++] = __glSpanUnpackShort;
  893. break;
  894. case GL_UNSIGNED_SHORT:
  895. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUshort;
  896. break;
  897. case GL_INT:
  898. spanInfo->spanModifier[spanCount++] = __glSpanUnpackInt;
  899. break;
  900. case GL_UNSIGNED_INT:
  901. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUint;
  902. break;
  903. }
  904. }
  905. }
  906. if (clamp) {
  907. switch(type) {
  908. case GL_BYTE:
  909. case GL_SHORT:
  910. case GL_INT:
  911. spanInfo->spanModifier[spanCount++] = __glSpanClampSigned;
  912. break;
  913. case GL_FLOAT:
  914. spanInfo->spanModifier[spanCount++] = __glSpanClampFloat;
  915. break;
  916. }
  917. }
  918. if (type == GL_BITMAP) {
  919. if (zoomx2) {
  920. spanInfo->spanModifier[spanCount++] = __glSpanUnpackBitmap2;
  921. } else {
  922. spanInfo->spanModifier[spanCount++] = __glSpanUnpackBitmap;
  923. }
  924. }
  925. /*
  926. ** Third step: Modification and color scaling
  927. **
  928. ** Spans are modified if necessary (color biasing, maps, shift,
  929. ** scale), and RGBA colors are scaled. Also, all RGBA derivative
  930. ** formats (RED, LUMINANCE, ALPHA, etc.) are converted to RGBA.
  931. ** The only four span formats that survive this stage are:
  932. **
  933. ** (COLOR_INDEX, FLOAT),
  934. ** (STENCIL_INDEX, FLOAT),
  935. ** (DEPTH_COMPONENT, FLOAT),
  936. ** (RGBA, FLOAT),
  937. */
  938. switch(format) {
  939. case GL_RED:
  940. if (pm->modifyRGBA) {
  941. spanInfo->spanModifier[spanCount++] = __glSpanModifyRed;
  942. } else {
  943. spanInfo->spanModifier[spanCount++] = __glSpanExpandRed;
  944. }
  945. break;
  946. case GL_GREEN:
  947. if (pm->modifyRGBA) {
  948. spanInfo->spanModifier[spanCount++] = __glSpanModifyGreen;
  949. } else {
  950. spanInfo->spanModifier[spanCount++] = __glSpanExpandGreen;
  951. }
  952. break;
  953. case GL_BLUE:
  954. if (pm->modifyRGBA) {
  955. spanInfo->spanModifier[spanCount++] = __glSpanModifyBlue;
  956. } else {
  957. spanInfo->spanModifier[spanCount++] = __glSpanExpandBlue;
  958. }
  959. break;
  960. case GL_ALPHA:
  961. if (pm->modifyRGBA) {
  962. spanInfo->spanModifier[spanCount++] = __glSpanModifyAlpha;
  963. } else {
  964. spanInfo->spanModifier[spanCount++] = __glSpanExpandAlpha;
  965. }
  966. break;
  967. case GL_RGB:
  968. if (pm->modifyRGBA) {
  969. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGB;
  970. } else {
  971. spanInfo->spanModifier[spanCount++] = __glSpanExpandRGB;
  972. }
  973. break;
  974. #ifdef GL_EXT_bgra
  975. case GL_BGR_EXT:
  976. if (pm->modifyRGBA) {
  977. // __glSpanModifyRGB handles both RGB and BGR
  978. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGB;
  979. } else {
  980. spanInfo->spanModifier[spanCount++] = __glSpanExpandBGR;
  981. }
  982. break;
  983. #endif
  984. case GL_LUMINANCE:
  985. if (pm->modifyRGBA) {
  986. spanInfo->spanModifier[spanCount++] = __glSpanModifyLuminance;
  987. } else {
  988. spanInfo->spanModifier[spanCount++] = __glSpanExpandLuminance;
  989. }
  990. break;
  991. case GL_LUMINANCE_ALPHA:
  992. if (pm->modifyRGBA) {
  993. spanInfo->spanModifier[spanCount++] = __glSpanModifyLuminanceAlpha;
  994. } else {
  995. spanInfo->spanModifier[spanCount++] = __glSpanExpandLuminanceAlpha;
  996. }
  997. break;
  998. case GL_RGBA:
  999. if (pm->modifyRGBA) {
  1000. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGBA;
  1001. } else {
  1002. spanInfo->spanModifier[spanCount++] = __glSpanScaleRGBA;
  1003. }
  1004. break;
  1005. #ifdef GL_EXT_bgra
  1006. case GL_BGRA_EXT:
  1007. if (pm->modifyRGBA) {
  1008. // __glSpanModifyRGBA handles both RGBA and BGRA
  1009. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGBA;
  1010. } else {
  1011. spanInfo->spanModifier[spanCount++] = __glSpanScaleBGRA;
  1012. }
  1013. break;
  1014. #endif
  1015. case GL_DEPTH_COMPONENT:
  1016. if (pm->modifyDepth) {
  1017. spanInfo->spanModifier[spanCount++] = __glSpanModifyDepth;
  1018. }
  1019. break;
  1020. case GL_STENCIL_INDEX:
  1021. if (pm->modifyStencil) {
  1022. spanInfo->spanModifier[spanCount++] = __glSpanModifyStencil;
  1023. }
  1024. break;
  1025. case GL_COLOR_INDEX:
  1026. if (pm->modifyCI) {
  1027. spanInfo->spanModifier[spanCount++] = __glSpanModifyCI;
  1028. }
  1029. break;
  1030. }
  1031. /*
  1032. ** Fourth step: Rendering
  1033. **
  1034. ** The spans are rendered. If |xzoom| > 1, then the span renderer
  1035. ** is responsible for pixel replication.
  1036. */
  1037. switch(spanInfo->dstFormat) {
  1038. case GL_RGBA:
  1039. case GL_RGB:
  1040. case GL_RED:
  1041. case GL_GREEN:
  1042. case GL_BLUE:
  1043. case GL_ALPHA:
  1044. case GL_LUMINANCE:
  1045. case GL_LUMINANCE_ALPHA:
  1046. #ifdef GL_EXT_bgra
  1047. case GL_BGRA_EXT:
  1048. case GL_BGR_EXT:
  1049. #endif
  1050. if (zoomx1) {
  1051. render = gc->procs.pixel.spanRenderRGBA2;
  1052. } else {
  1053. render = gc->procs.pixel.spanRenderRGBA;
  1054. }
  1055. break;
  1056. case GL_DEPTH_COMPONENT:
  1057. if (zoomx1) {
  1058. render = gc->procs.pixel.spanRenderDepth2;
  1059. } else {
  1060. render = gc->procs.pixel.spanRenderDepth;
  1061. }
  1062. break;
  1063. case GL_COLOR_INDEX:
  1064. if (zoomx1) {
  1065. render = gc->procs.pixel.spanRenderCI2;
  1066. } else {
  1067. render = gc->procs.pixel.spanRenderCI;
  1068. }
  1069. break;
  1070. case GL_STENCIL_INDEX:
  1071. if (zoomx1) {
  1072. render = gc->procs.pixel.spanRenderStencil2;
  1073. } else {
  1074. render = gc->procs.pixel.spanRenderStencil;
  1075. }
  1076. break;
  1077. }
  1078. /*
  1079. ** Optimization attempt.
  1080. **
  1081. ** There are some format, type combinations that are expected to be
  1082. ** common. This code optimizes a few of those cases. Specifically,
  1083. ** these modes include: (GL_UNSIGNED_BYTE, GL_RGB),
  1084. ** (GL_UNSIGNED_BYTE, GL_RGBA), (GL_UNSIGNED_BYTE, GL_COLOR_INDEX),
  1085. ** (GL_UNSIGNED_BYTE, GL_STENCIL_INDEX),
  1086. ** (GL_UNSIGNED_SHORT, GL_COLOR_INDEX),
  1087. ** (GL_UNSIGNED_SHORT, GL_STENCIL_INDEX),
  1088. ** (GL_UNSIGNED_INT, GL_DEPTH_COMPONENT)
  1089. */
  1090. switch(type) {
  1091. case GL_UNSIGNED_BYTE:
  1092. switch(format) {
  1093. case GL_RGB:
  1094. spanCount = 0;
  1095. if (packedUserData) {
  1096. /* no span unpacking is necessary! */
  1097. } else {
  1098. /* zoomx2 must not be true, or packedUserData would be set
  1099. */
  1100. ASSERTOPENGL(!zoomx2, "zoomx2 is set\n");
  1101. spanInfo->spanModifier[spanCount++] = __glSpanUnpackRGBubyte;
  1102. }
  1103. if (!pm->modifyRGBA) {
  1104. pm->redCurMap = pm->redMap;
  1105. pm->greenCurMap = pm->greenMap;
  1106. pm->blueCurMap = pm->blueMap;
  1107. pm->alphaCurMap = pm->alphaMap;
  1108. if (zoomx1) {
  1109. render = __glSpanRenderRGBubyte2;
  1110. } else {
  1111. render = __glSpanRenderRGBubyte;
  1112. }
  1113. } else {
  1114. if (!pm->rgbaCurrent) {
  1115. __glBuildRGBAModifyTables(gc, pm);
  1116. }
  1117. pm->redCurMap = pm->redModMap;
  1118. pm->greenCurMap = pm->greenModMap;
  1119. pm->blueCurMap = pm->blueModMap;
  1120. pm->alphaCurMap = pm->alphaModMap;
  1121. if (zoomx1) {
  1122. render = __glSpanRenderRGBubyte2;
  1123. } else {
  1124. render = __glSpanRenderRGBubyte;
  1125. }
  1126. }
  1127. break;
  1128. case GL_RGBA:
  1129. spanCount = 0;
  1130. if (packedUserData) {
  1131. /* no span unpacking is necessary! */
  1132. } else {
  1133. /* zoomx2 must not be true, or packedUserData would be set
  1134. */
  1135. ASSERTOPENGL(!zoomx2, "zoomx2 is set\n");
  1136. spanInfo->spanModifier[spanCount++] = __glSpanUnpackRGBAubyte;
  1137. }
  1138. if (!pm->modifyRGBA) {
  1139. pm->redCurMap = pm->redMap;
  1140. pm->greenCurMap = pm->greenMap;
  1141. pm->blueCurMap = pm->blueMap;
  1142. pm->alphaCurMap = pm->alphaMap;
  1143. } else {
  1144. if (!pm->rgbaCurrent) {
  1145. __glBuildRGBAModifyTables(gc, pm);
  1146. }
  1147. pm->redCurMap = pm->redModMap;
  1148. pm->greenCurMap = pm->greenModMap;
  1149. pm->blueCurMap = pm->blueModMap;
  1150. pm->alphaCurMap = pm->alphaModMap;
  1151. }
  1152. if (zoomx1) {
  1153. render = __glSpanRenderRGBAubyte2;
  1154. } else {
  1155. render = __glSpanRenderRGBAubyte;
  1156. }
  1157. break;
  1158. case GL_STENCIL_INDEX:
  1159. if (!pm->modifyStencil) {
  1160. spanCount = 0;
  1161. if (packedUserData) {
  1162. /* no span unpacking is necessary! */
  1163. } else {
  1164. /* zoomx2 must not be true, or packedUserData would be set
  1165. */
  1166. ASSERTOPENGL(!zoomx2, "zoomx2 is set\n");
  1167. spanInfo->spanModifier[spanCount++] =
  1168. __glSpanUnpackIndexUbyte;
  1169. }
  1170. if (zoomx1) {
  1171. render = __glSpanRenderStencilUbyte2;
  1172. } else {
  1173. render = __glSpanRenderStencilUbyte;
  1174. }
  1175. }
  1176. break;
  1177. case GL_COLOR_INDEX:
  1178. spanCount = 0;
  1179. if (packedUserData) {
  1180. /* no span unpacking is necessary! */
  1181. } else {
  1182. /* zoomx2 must not be true, or packedUserData would be set
  1183. */
  1184. ASSERTOPENGL(!zoomx2, "zoomx2 is set\n");
  1185. spanInfo->spanModifier[spanCount++] =
  1186. __glSpanUnpackIndexUbyte;
  1187. }
  1188. if (!pm->modifyCI) {
  1189. pm->iCurMap = pm->iMap;
  1190. if (zoomx1) {
  1191. render = __glSpanRenderCIubyte2;
  1192. } else {
  1193. render = __glSpanRenderCIubyte;
  1194. }
  1195. } else {
  1196. if (gc->modes.rgbMode) {
  1197. if (!pm->iToRGBACurrent) {
  1198. __glBuildItoRGBAModifyTables(gc, pm);
  1199. }
  1200. pm->redCurMap = pm->iToRMap;
  1201. pm->greenCurMap = pm->iToGMap;
  1202. pm->blueCurMap = pm->iToBMap;
  1203. pm->alphaCurMap = pm->iToAMap;
  1204. if (zoomx1) {
  1205. render = __glSpanRenderCIubyte4;
  1206. } else {
  1207. render = __glSpanRenderCIubyte3;
  1208. }
  1209. } else {
  1210. if (!pm->iToICurrent) {
  1211. __glBuildItoIModifyTables(gc, pm);
  1212. }
  1213. pm->iCurMap = pm->iToIMap;
  1214. if (zoomx1) {
  1215. render = __glSpanRenderCIubyte2;
  1216. } else {
  1217. render = __glSpanRenderCIubyte;
  1218. }
  1219. }
  1220. }
  1221. break;
  1222. default:
  1223. break;
  1224. }
  1225. break;
  1226. case GL_UNSIGNED_SHORT:
  1227. switch(format) {
  1228. case GL_STENCIL_INDEX:
  1229. if (!pm->modifyStencil) {
  1230. /* Back off conversion to float */
  1231. ASSERTOPENGL(convert, "convert not set\n");
  1232. spanCount--;
  1233. if (zoomx1) {
  1234. render = __glSpanRenderStencilUshort2;
  1235. } else {
  1236. render = __glSpanRenderStencilUshort;
  1237. }
  1238. }
  1239. break;
  1240. case GL_COLOR_INDEX:
  1241. if (!pm->modifyCI) {
  1242. /* Back off conversion to float */
  1243. ASSERTOPENGL(convert, "convert not set\n");
  1244. spanCount--;
  1245. if (zoomx1) {
  1246. render = __glSpanRenderCIushort2;
  1247. } else {
  1248. render = __glSpanRenderCIushort;
  1249. }
  1250. }
  1251. break;
  1252. default:
  1253. break;
  1254. }
  1255. break;
  1256. case GL_UNSIGNED_INT:
  1257. switch(format) {
  1258. case GL_DEPTH_COMPONENT:
  1259. if (!pm->modifyDepth) {
  1260. if (gc->depthBuffer.scale == 0xffffffff) {
  1261. // XXX we never set depthBuffer.scale to 0xffffffff in NT!
  1262. // XXX write optimize code for 16-bit z buffers?
  1263. /* Back off conversion to float */
  1264. ASSERTOPENGL(convert, "convert not set\n");
  1265. spanCount--;
  1266. if (zoomx1) {
  1267. render = __glSpanRenderDepthUint2;
  1268. } else {
  1269. render = __glSpanRenderDepthUint;
  1270. }
  1271. } else if (gc->depthBuffer.scale == 0x7fffffff) {
  1272. /* Back off conversion to float */
  1273. ASSERTOPENGL(convert, "convert not set\n");
  1274. spanCount--;
  1275. if (zoomx1) {
  1276. render = __glSpanRenderDepth2Uint2;
  1277. } else {
  1278. render = __glSpanRenderDepth2Uint;
  1279. }
  1280. }
  1281. }
  1282. break;
  1283. default:
  1284. break;
  1285. }
  1286. break;
  1287. default:
  1288. break;
  1289. }
  1290. /*
  1291. ** Pick a DrawPixels function that applies the correct number of
  1292. ** span modifiers.
  1293. */
  1294. switch(spanCount) {
  1295. case 0:
  1296. dpfn = __glDrawPixels0;
  1297. break;
  1298. case 1:
  1299. dpfn = __glDrawPixels1;
  1300. break;
  1301. case 2:
  1302. dpfn = __glDrawPixels2;
  1303. break;
  1304. case 3:
  1305. dpfn = __glDrawPixels3;
  1306. break;
  1307. default:
  1308. ASSERTOPENGL(FALSE, "Default hit\n");
  1309. case 4:
  1310. dpfn = __glDrawPixels4;
  1311. break;
  1312. }
  1313. spanInfo->spanRender = render;
  1314. (*dpfn)(gc, spanInfo);
  1315. }
  1316. /*
  1317. ** This routine clips ReadPixels calls so that only fragments which are
  1318. ** owned by this context will be read and copied into the user's data.
  1319. ** Parts of the ReadPixels rectangle lying outside of the window will
  1320. ** be ignored.
  1321. */
  1322. GLboolean FASTCALL __glClipReadPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1323. {
  1324. GLint clipLeft, clipRight, clipTop, clipBottom;
  1325. GLint x,y,x2,y2;
  1326. GLint skipPixels, skipRows;
  1327. GLint width, height;
  1328. GLint tempint;
  1329. __GLGENcontext *gengc = (__GLGENcontext *) gc;
  1330. GLGENwindow *pwnd = gengc->pwndLocked;
  1331. width = spanInfo->width;
  1332. height = spanInfo->height;
  1333. x = spanInfo->readX;
  1334. y = spanInfo->readY;
  1335. x2 = x + spanInfo->width;
  1336. if (gc->constants.yInverted) {
  1337. y2 = y - spanInfo->height;
  1338. } else {
  1339. y2 = y + spanInfo->height;
  1340. }
  1341. if (pwnd &&
  1342. (pwnd->rclBounds.left < pwnd->rclBounds.right) &&
  1343. (pwnd->rclBounds.top < pwnd->rclBounds.bottom)) {
  1344. clipLeft = (pwnd->rclBounds.left - pwnd->rclClient.left)
  1345. + gc->constants.viewportXAdjust;
  1346. clipRight = (pwnd->rclBounds.right - pwnd->rclClient.left)
  1347. + gc->constants.viewportXAdjust;
  1348. if (gc->constants.yInverted) {
  1349. clipBottom = (pwnd->rclBounds.top - pwnd->rclClient.top)
  1350. + gc->constants.viewportYAdjust;
  1351. clipTop = (pwnd->rclBounds.bottom - pwnd->rclClient.top)
  1352. + gc->constants.viewportYAdjust;
  1353. } else {
  1354. clipBottom = (gc->constants.height -
  1355. (pwnd->rclBounds.bottom - pwnd->rclClient.top))
  1356. + gc->constants.viewportYAdjust;
  1357. clipTop = (gc->constants.height -
  1358. (pwnd->rclBounds.top - pwnd->rclClient.top))
  1359. + gc->constants.viewportYAdjust;
  1360. }
  1361. } else {
  1362. clipLeft = gc->constants.viewportXAdjust;
  1363. clipRight = gc->constants.viewportXAdjust;
  1364. clipBottom = gc->constants.viewportYAdjust;
  1365. clipTop = gc->constants.viewportYAdjust;
  1366. }
  1367. skipPixels = 0;
  1368. skipRows = 0;
  1369. if (x < clipLeft) {
  1370. skipPixels = clipLeft - x;
  1371. if (skipPixels > width) return GL_FALSE;
  1372. width -= skipPixels;
  1373. x = clipLeft;
  1374. spanInfo->dstSkipPixels += skipPixels;
  1375. spanInfo->readX = x;
  1376. }
  1377. if (x2 > clipRight) {
  1378. tempint = x2 - clipRight;
  1379. if (tempint > width) return GL_FALSE;
  1380. width -= tempint;
  1381. }
  1382. if (gc->constants.yInverted) {
  1383. if (y >= clipTop) {
  1384. skipRows = y - clipTop + 1;
  1385. if (skipRows > height) return GL_FALSE;
  1386. height -= skipRows;
  1387. y = clipTop - 1;
  1388. spanInfo->dstSkipLines += skipRows;
  1389. spanInfo->readY = y;
  1390. }
  1391. if (y2 < clipBottom - 1) {
  1392. tempint = clipBottom - y2 - 1;
  1393. if (tempint > height) return GL_FALSE;
  1394. height -= tempint;
  1395. }
  1396. } else {
  1397. if (y < clipBottom) {
  1398. skipRows = clipBottom - y;
  1399. if (skipRows > height) return GL_FALSE;
  1400. height -= skipRows;
  1401. y = clipBottom;
  1402. spanInfo->dstSkipLines += skipRows;
  1403. spanInfo->readY = y;
  1404. }
  1405. if (y2 > clipTop) {
  1406. tempint = y2 - clipTop;
  1407. if (tempint > height) return GL_FALSE;
  1408. height -= tempint;
  1409. }
  1410. }
  1411. spanInfo->width = width;
  1412. spanInfo->height = height;
  1413. spanInfo->realWidth = width;
  1414. return GL_TRUE;
  1415. }
  1416. /*
  1417. ** Initialize the spanInfo structure for packing data into the user's data
  1418. ** space.
  1419. */
  1420. void FASTCALL __glLoadPackModes(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1421. {
  1422. GLint lineLength = gc->state.pixel.packModes.lineLength;
  1423. spanInfo->dstAlignment = gc->state.pixel.packModes.alignment;
  1424. spanInfo->dstSkipPixels = gc->state.pixel.packModes.skipPixels;
  1425. spanInfo->dstSkipLines = gc->state.pixel.packModes.skipLines;
  1426. spanInfo->dstLsbFirst = gc->state.pixel.packModes.lsbFirst;
  1427. spanInfo->dstSwapBytes = gc->state.pixel.packModes.swapEndian;
  1428. if (lineLength <= 0) lineLength = spanInfo->width;
  1429. spanInfo->dstLineLength = lineLength;
  1430. }
  1431. void __glInitReadPixelsInfo(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1432. GLint x, GLint y, GLint width, GLint height,
  1433. GLenum format, GLenum type, const GLvoid *pixels)
  1434. {
  1435. spanInfo->readX = x + gc->constants.viewportXAdjust;
  1436. if (gc->constants.yInverted) {
  1437. spanInfo->readY = (gc->constants.height - y - 1) +
  1438. gc->constants.viewportYAdjust;
  1439. } else {
  1440. spanInfo->readY = y + gc->constants.viewportYAdjust;
  1441. }
  1442. spanInfo->width = width;
  1443. spanInfo->height = height;
  1444. spanInfo->dstFormat = format;
  1445. spanInfo->dstType = type;
  1446. spanInfo->dstImage = pixels;
  1447. spanInfo->zoomx = __glOne;
  1448. spanInfo->x = __glZero;
  1449. __glLoadPackModes(gc, spanInfo);
  1450. }
  1451. /*
  1452. ** A simple generic ReadPixels routine with five span modifiers.
  1453. */
  1454. void FASTCALL __glReadPixels5(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1455. {
  1456. GLint i, ySign;
  1457. GLint height;
  1458. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1459. GLvoid *inspan, GLvoid *outspan);
  1460. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1461. GLvoid *inspan, GLvoid *outspan);
  1462. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1463. GLvoid *inspan, GLvoid *outspan);
  1464. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1465. GLvoid *inspan, GLvoid *outspan);
  1466. void (*span5)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1467. GLvoid *inspan, GLvoid *outspan);
  1468. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1469. GLvoid *outspan);
  1470. #ifdef NT
  1471. GLubyte *spanData1, *spanData2;
  1472. i = spanInfo->width * 4 * sizeof(GLfloat);
  1473. spanData1 = gcTempAlloc(gc, i);
  1474. spanData2 = gcTempAlloc(gc, i);
  1475. if (!spanData1 || !spanData2)
  1476. goto __glReadPixels5_exit;
  1477. #else
  1478. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  1479. #endif
  1480. span1 = spanInfo->spanModifier[0];
  1481. span2 = spanInfo->spanModifier[1];
  1482. span3 = spanInfo->spanModifier[2];
  1483. span4 = spanInfo->spanModifier[3];
  1484. span5 = spanInfo->spanModifier[4];
  1485. reader = spanInfo->spanReader;
  1486. ySign = gc->constants.ySign;
  1487. height = spanInfo->height;
  1488. for (i=0; i<height; i++) {
  1489. (*reader)(gc, spanInfo, spanData1);
  1490. (*span1)(gc, spanInfo, spanData1, spanData2);
  1491. (*span2)(gc, spanInfo, spanData2, spanData1);
  1492. (*span3)(gc, spanInfo, spanData1, spanData2);
  1493. (*span4)(gc, spanInfo, spanData2, spanData1);
  1494. (*span5)(gc, spanInfo, spanData1, spanInfo->dstCurrent);
  1495. spanInfo->dstCurrent = (GLvoid *) ((GLubyte *) spanInfo->dstCurrent +
  1496. spanInfo->dstRowIncrement);
  1497. spanInfo->readY += ySign;
  1498. }
  1499. #ifdef NT
  1500. __glReadPixels5_exit:
  1501. if (spanData1) gcTempFree(gc, spanData1);
  1502. if (spanData2) gcTempFree(gc, spanData2);
  1503. #endif
  1504. }
  1505. /*
  1506. ** A simple generic ReadPixels routine with three span modifiers.
  1507. */
  1508. void FASTCALL __glReadPixels4(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1509. {
  1510. GLint i, ySign;
  1511. GLint height;
  1512. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1513. GLvoid *inspan, GLvoid *outspan);
  1514. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1515. GLvoid *inspan, GLvoid *outspan);
  1516. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1517. GLvoid *inspan, GLvoid *outspan);
  1518. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1519. GLvoid *inspan, GLvoid *outspan);
  1520. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1521. GLvoid *outspan);
  1522. #ifdef NT
  1523. GLubyte *spanData1, *spanData2;
  1524. i = spanInfo->width * 4 * sizeof(GLfloat);
  1525. spanData1 = gcTempAlloc(gc, i);
  1526. spanData2 = gcTempAlloc(gc, i);
  1527. if (!spanData1 || !spanData2)
  1528. goto __glReadPixels4_exit;
  1529. #else
  1530. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  1531. #endif
  1532. span1 = spanInfo->spanModifier[0];
  1533. span2 = spanInfo->spanModifier[1];
  1534. span3 = spanInfo->spanModifier[2];
  1535. span4 = spanInfo->spanModifier[3];
  1536. reader = spanInfo->spanReader;
  1537. ySign = gc->constants.ySign;
  1538. height = spanInfo->height;
  1539. for (i=0; i<height; i++) {
  1540. (*reader)(gc, spanInfo, spanData1);
  1541. (*span1)(gc, spanInfo, spanData1, spanData2);
  1542. (*span2)(gc, spanInfo, spanData2, spanData1);
  1543. (*span3)(gc, spanInfo, spanData1, spanData2);
  1544. (*span4)(gc, spanInfo, spanData2, spanInfo->dstCurrent);
  1545. spanInfo->dstCurrent = (GLvoid *) ((GLubyte *) spanInfo->dstCurrent +
  1546. spanInfo->dstRowIncrement);
  1547. spanInfo->readY += ySign;
  1548. }
  1549. #ifdef NT
  1550. __glReadPixels4_exit:
  1551. if (spanData1) gcTempFree(gc, spanData1);
  1552. if (spanData2) gcTempFree(gc, spanData2);
  1553. #endif
  1554. }
  1555. /*
  1556. ** A simple generic ReadPixels routine with four span modifiers.
  1557. */
  1558. void FASTCALL __glReadPixels3(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1559. {
  1560. GLint i, ySign;
  1561. GLint height;
  1562. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1563. GLvoid *inspan, GLvoid *outspan);
  1564. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1565. GLvoid *inspan, GLvoid *outspan);
  1566. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1567. GLvoid *inspan, GLvoid *outspan);
  1568. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1569. GLvoid *outspan);
  1570. #ifdef NT
  1571. GLubyte *spanData1, *spanData2;
  1572. i = spanInfo->width * 4 * sizeof(GLfloat);
  1573. spanData1 = gcTempAlloc(gc, i);
  1574. spanData2 = gcTempAlloc(gc, i);
  1575. if (!spanData1 || !spanData2)
  1576. goto __glReadPixels3_exit;
  1577. #else
  1578. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  1579. #endif
  1580. span1 = spanInfo->spanModifier[0];
  1581. span2 = spanInfo->spanModifier[1];
  1582. span3 = spanInfo->spanModifier[2];
  1583. reader = spanInfo->spanReader;
  1584. ySign = gc->constants.ySign;
  1585. height = spanInfo->height;
  1586. for (i=0; i<height; i++) {
  1587. (*reader)(gc, spanInfo, spanData1);
  1588. (*span1)(gc, spanInfo, spanData1, spanData2);
  1589. (*span2)(gc, spanInfo, spanData2, spanData1);
  1590. (*span3)(gc, spanInfo, spanData1, spanInfo->dstCurrent);
  1591. spanInfo->dstCurrent = (GLvoid *) ((GLubyte *) spanInfo->dstCurrent +
  1592. spanInfo->dstRowIncrement);
  1593. spanInfo->readY += ySign;
  1594. }
  1595. #ifdef NT
  1596. __glReadPixels3_exit:
  1597. if (spanData1) gcTempFree(gc, spanData1);
  1598. if (spanData2) gcTempFree(gc, spanData2);
  1599. #endif
  1600. }
  1601. /*
  1602. ** A simple generic ReadPixels routine with two span modifiers.
  1603. */
  1604. void FASTCALL __glReadPixels2(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1605. {
  1606. GLint i, ySign;
  1607. GLint height;
  1608. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1609. GLvoid *inspan, GLvoid *outspan);
  1610. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1611. GLvoid *inspan, GLvoid *outspan);
  1612. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1613. GLvoid *outspan);
  1614. #ifdef NT
  1615. GLubyte *spanData1, *spanData2;
  1616. i = spanInfo->width * 4 * sizeof(GLfloat);
  1617. spanData1 = gcTempAlloc(gc, i);
  1618. spanData2 = gcTempAlloc(gc, i);
  1619. if (!spanData1 || !spanData2)
  1620. goto __glReadPixels2_exit;
  1621. #else
  1622. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  1623. #endif
  1624. span1 = spanInfo->spanModifier[0];
  1625. span2 = spanInfo->spanModifier[1];
  1626. reader = spanInfo->spanReader;
  1627. ySign = gc->constants.ySign;
  1628. height = spanInfo->height;
  1629. for (i=0; i<height; i++) {
  1630. (*reader)(gc, spanInfo, spanData1);
  1631. (*span1)(gc, spanInfo, spanData1, spanData2);
  1632. (*span2)(gc, spanInfo, spanData2, spanInfo->dstCurrent);
  1633. spanInfo->dstCurrent = (GLvoid *) ((GLubyte *) spanInfo->dstCurrent +
  1634. spanInfo->dstRowIncrement);
  1635. spanInfo->readY += ySign;
  1636. }
  1637. #ifdef NT
  1638. __glReadPixels2_exit:
  1639. if (spanData1) gcTempFree(gc, spanData1);
  1640. if (spanData2) gcTempFree(gc, spanData2);
  1641. #endif
  1642. }
  1643. /*
  1644. ** A simple generic ReadPixels routine with one span modifier.
  1645. */
  1646. void FASTCALL __glReadPixels1(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1647. {
  1648. GLint i, ySign;
  1649. GLint height;
  1650. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1651. GLvoid *inspan, GLvoid *outspan);
  1652. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1653. GLvoid *outspan);
  1654. #ifdef NT
  1655. GLubyte *spanData1;
  1656. spanData1 = gcTempAlloc(gc, spanInfo->width * 4 * sizeof(GLfloat));
  1657. if (!spanData1)
  1658. return;
  1659. #else
  1660. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  1661. #endif
  1662. span1 = spanInfo->spanModifier[0];
  1663. reader = spanInfo->spanReader;
  1664. ySign = gc->constants.ySign;
  1665. height = spanInfo->height;
  1666. for (i=0; i<height; i++) {
  1667. (*reader)(gc, spanInfo, spanData1);
  1668. (*span1)(gc, spanInfo, spanData1, spanInfo->dstCurrent);
  1669. spanInfo->dstCurrent = (GLvoid *) ((GLubyte *) spanInfo->dstCurrent +
  1670. spanInfo->dstRowIncrement);
  1671. spanInfo->readY += ySign;
  1672. }
  1673. #ifdef NT
  1674. gcTempFree(gc, spanData1);
  1675. #endif
  1676. }
  1677. /*
  1678. ** A simple generic ReadPixels routine with no span modifiers.
  1679. */
  1680. void FASTCALL __glReadPixels0(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1681. {
  1682. GLint i, ySign;
  1683. GLint height;
  1684. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1685. GLvoid *outspan);
  1686. reader = spanInfo->spanReader;
  1687. ySign = gc->constants.ySign;
  1688. height = spanInfo->height;
  1689. for (i=0; i<height; i++) {
  1690. (*reader)(gc, spanInfo, spanInfo->dstCurrent);
  1691. spanInfo->dstCurrent = (GLvoid *) ((GLubyte *) spanInfo->dstCurrent +
  1692. spanInfo->dstRowIncrement);
  1693. spanInfo->readY += ySign;
  1694. }
  1695. }
  1696. /*
  1697. ** Generic implementation of a ReadPixels picker. Any machine specific
  1698. ** implementation should provide their own.
  1699. */
  1700. void __glSlowPickReadPixels(__GLcontext *gc, GLint x, GLint y,
  1701. GLsizei width, GLsizei height,
  1702. GLenum format, GLenum type, const GLvoid *pixels)
  1703. {
  1704. __GLpixelSpanInfo spanInfo;
  1705. __glInitReadPixelsInfo(gc, &spanInfo, x, y, width, height, format,
  1706. type, pixels);
  1707. if (!__glClipReadPixels(gc, &spanInfo)) return;
  1708. __glInitPacker(gc, &spanInfo);
  1709. __glGenericPickReadPixels(gc, &spanInfo);
  1710. }
  1711. /*
  1712. ** Generic picker for ReadPixels. This should be called if no machine
  1713. ** specific path is provided for this specific version of ReadPixels.
  1714. */
  1715. void FASTCALL __glGenericPickReadPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1716. {
  1717. __GLpixelMachine *pm;
  1718. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  1719. GLvoid *outspan);
  1720. void (FASTCALL *rpfn)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo);
  1721. GLint spanCount;
  1722. GLenum type, format;
  1723. GLboolean isIndex;
  1724. spanCount = 0;
  1725. type = spanInfo->dstType;
  1726. format = spanInfo->dstFormat;
  1727. pm = &gc->pixel;
  1728. #ifdef NT
  1729. // Special case RGB reading to use a DIB
  1730. // Also special case reading the Z buffer
  1731. if (format == GL_RGB || format == GL_BGR_EXT || format == GL_BGRA_EXT)
  1732. {
  1733. GLuint enables = gc->state.enables.general;
  1734. if (type == GL_UNSIGNED_BYTE &&
  1735. !pm->modifyRGBA &&
  1736. gc->state.pixel.transferMode.indexShift == 0 &&
  1737. gc->state.pixel.transferMode.indexOffset == 0
  1738. #ifdef _MCD_
  1739. && ((__GLGENcontext *)gc)->pMcdState == NULL
  1740. #endif
  1741. )
  1742. {
  1743. if (ReadRgbPixels(gc, spanInfo))
  1744. {
  1745. return;
  1746. }
  1747. }
  1748. }
  1749. else if (format == GL_DEPTH_COMPONENT)
  1750. {
  1751. if (!spanInfo->dstSwapBytes &&
  1752. (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT) &&
  1753. !pm->modifyDepth &&
  1754. gc->modes.haveDepthBuffer
  1755. #ifdef _MCD_
  1756. && ((__GLGENcontext *)gc)->pMcdState == NULL
  1757. #endif
  1758. )
  1759. {
  1760. if (ReadZPixels(gc, spanInfo))
  1761. {
  1762. return;
  1763. }
  1764. }
  1765. }
  1766. #endif
  1767. // The read functions always retrieve __GLcolors so the source
  1768. // data format is always GL_RGBA. It's important to set this
  1769. // because some routines handle both RGB and BGR ordering and
  1770. // look at the srcFormat to determine what to do.
  1771. spanInfo->srcFormat = GL_RGBA;
  1772. /*
  1773. ** First step: Read and modify a span. RGBA spans are scaled when
  1774. ** this step is finished.
  1775. */
  1776. switch(format) {
  1777. case GL_RGB:
  1778. case GL_RED:
  1779. case GL_GREEN:
  1780. case GL_BLUE:
  1781. case GL_LUMINANCE:
  1782. case GL_LUMINANCE_ALPHA:
  1783. case GL_ALPHA:
  1784. case GL_RGBA:
  1785. #ifdef GL_EXT_bgra
  1786. case GL_BGRA_EXT:
  1787. case GL_BGR_EXT:
  1788. #endif
  1789. if (gc->modes.rgbMode) {
  1790. reader = gc->procs.pixel.spanReadRGBA2;
  1791. if (pm->modifyRGBA) {
  1792. spanInfo->spanModifier[spanCount++] = __glSpanUnscaleRGBA;
  1793. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGBA;
  1794. }
  1795. } else {
  1796. reader = gc->procs.pixel.spanReadCI2;
  1797. spanInfo->spanModifier[spanCount++] = __glSpanModifyCI;
  1798. }
  1799. isIndex = GL_FALSE;
  1800. break;
  1801. case GL_DEPTH_COMPONENT:
  1802. reader = gc->procs.pixel.spanReadDepth2;
  1803. if (pm->modifyDepth) {
  1804. spanInfo->spanModifier[spanCount++] = __glSpanModifyDepth;
  1805. }
  1806. isIndex = GL_FALSE;
  1807. break;
  1808. case GL_STENCIL_INDEX:
  1809. reader = gc->procs.pixel.spanReadStencil2;
  1810. if (pm->modifyStencil) {
  1811. spanInfo->spanModifier[spanCount++] = __glSpanModifyStencil;
  1812. }
  1813. isIndex = GL_TRUE;
  1814. break;
  1815. case GL_COLOR_INDEX:
  1816. reader = gc->procs.pixel.spanReadCI2;
  1817. if (pm->modifyCI) {
  1818. spanInfo->spanModifier[spanCount++] = __glSpanModifyCI;
  1819. }
  1820. isIndex = GL_TRUE;
  1821. break;
  1822. }
  1823. /*
  1824. ** Second step: Reduce RGBA spans to appropriate derivative (RED,
  1825. ** LUMINANCE, ALPHA, etc.).
  1826. */
  1827. switch(format) {
  1828. case GL_RGB:
  1829. spanInfo->spanModifier[spanCount++] = __glSpanReduceRGB;
  1830. break;
  1831. #ifdef GL_EXT_bgra
  1832. case GL_BGR_EXT:
  1833. spanInfo->spanModifier[spanCount++] = __glSpanReduceBGR;
  1834. break;
  1835. #endif
  1836. case GL_RED:
  1837. spanInfo->spanModifier[spanCount++] = __glSpanReduceRed;
  1838. break;
  1839. case GL_GREEN:
  1840. spanInfo->spanModifier[spanCount++] = __glSpanReduceGreen;
  1841. break;
  1842. case GL_BLUE:
  1843. spanInfo->spanModifier[spanCount++] = __glSpanReduceBlue;
  1844. break;
  1845. case GL_LUMINANCE:
  1846. spanInfo->spanModifier[spanCount++] = __glSpanReduceLuminance;
  1847. break;
  1848. case GL_LUMINANCE_ALPHA:
  1849. spanInfo->spanModifier[spanCount++] = __glSpanReduceLuminanceAlpha;
  1850. break;
  1851. case GL_ALPHA:
  1852. spanInfo->spanModifier[spanCount++] = __glSpanReduceAlpha;
  1853. break;
  1854. case GL_RGBA:
  1855. spanInfo->spanModifier[spanCount++] = __glSpanUnscaleRGBA;
  1856. break;
  1857. #ifdef GL_EXT_bgra
  1858. case GL_BGRA_EXT:
  1859. spanInfo->spanModifier[spanCount++] = __glSpanUnscaleBGRA;
  1860. break;
  1861. #endif
  1862. }
  1863. /*
  1864. ** Third step: Conversion from FLOAT to user requested type.
  1865. */
  1866. if (isIndex) {
  1867. switch(type) {
  1868. case GL_BYTE:
  1869. spanInfo->spanModifier[spanCount++] = __glSpanPackByteI;
  1870. break;
  1871. case GL_UNSIGNED_BYTE:
  1872. spanInfo->spanModifier[spanCount++] = __glSpanPackUbyteI;
  1873. break;
  1874. case GL_SHORT:
  1875. spanInfo->spanModifier[spanCount++] = __glSpanPackShortI;
  1876. break;
  1877. case GL_UNSIGNED_SHORT:
  1878. spanInfo->spanModifier[spanCount++] = __glSpanPackUshortI;
  1879. break;
  1880. case GL_INT:
  1881. spanInfo->spanModifier[spanCount++] = __glSpanPackIntI;
  1882. break;
  1883. case GL_UNSIGNED_INT:
  1884. spanInfo->spanModifier[spanCount++] = __glSpanPackUintI;
  1885. break;
  1886. case GL_BITMAP:
  1887. spanInfo->spanModifier[spanCount++] = __glSpanPackBitmap;
  1888. break;
  1889. }
  1890. } else {
  1891. switch(type) {
  1892. case GL_BYTE:
  1893. spanInfo->spanModifier[spanCount++] = __glSpanPackByte;
  1894. break;
  1895. case GL_UNSIGNED_BYTE:
  1896. spanInfo->spanModifier[spanCount++] = __glSpanPackUbyte;
  1897. break;
  1898. case GL_SHORT:
  1899. spanInfo->spanModifier[spanCount++] = __glSpanPackShort;
  1900. break;
  1901. case GL_UNSIGNED_SHORT:
  1902. spanInfo->spanModifier[spanCount++] = __glSpanPackUshort;
  1903. break;
  1904. case GL_INT:
  1905. spanInfo->spanModifier[spanCount++] = __glSpanPackInt;
  1906. break;
  1907. case GL_UNSIGNED_INT:
  1908. spanInfo->spanModifier[spanCount++] = __glSpanPackUint;
  1909. break;
  1910. }
  1911. }
  1912. /*
  1913. ** Fourth step: Mis-align data as needed, and perform byte swapping
  1914. ** if requested by the user.
  1915. */
  1916. if (spanInfo->dstSwapBytes) {
  1917. /* Byte swapping is necessary */
  1918. if (spanInfo->dstElementSize == 2) {
  1919. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes2Dst;
  1920. } else if (spanInfo->dstElementSize == 4) {
  1921. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes4Dst;
  1922. }
  1923. } else if (type != GL_BITMAP &&
  1924. (((INT_PTR) (spanInfo->dstImage)) & (spanInfo->dstElementSize - 1))) {
  1925. /* Alignment is necessary */
  1926. if (spanInfo->dstElementSize == 2) {
  1927. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels2Dst;
  1928. } else if (spanInfo->dstElementSize == 4) {
  1929. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels4Dst;
  1930. }
  1931. }
  1932. /*
  1933. ** Pick a ReadPixels routine that uses the right number of span
  1934. ** modifiers.
  1935. */
  1936. spanInfo->spanReader = reader;
  1937. switch(spanCount) {
  1938. case 0:
  1939. rpfn = __glReadPixels0;
  1940. break;
  1941. case 1:
  1942. rpfn = __glReadPixels1;
  1943. break;
  1944. case 2:
  1945. rpfn = __glReadPixels2;
  1946. break;
  1947. case 3:
  1948. rpfn = __glReadPixels3;
  1949. break;
  1950. case 4:
  1951. rpfn = __glReadPixels4;
  1952. break;
  1953. default:
  1954. ASSERTOPENGL(FALSE, "Default hit\n");
  1955. case 5:
  1956. rpfn = __glReadPixels5;
  1957. break;
  1958. }
  1959. (*rpfn)(gc, spanInfo);
  1960. }
  1961. /*
  1962. ** This routine does two clips. It clips like the DrawPixel clipper so
  1963. ** that if you try to copy to off window pixels, nothing will be done, and it
  1964. ** also clips like the ReadPixel clipper so that if you try to copy from
  1965. ** off window pixels, nothing will be done.
  1966. */
  1967. GLboolean FASTCALL __glClipCopyPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  1968. {
  1969. __GLfloat num, den;
  1970. __GLfloat rpyUp, rpyDown;
  1971. GLint rowsUp, rowsDown, startUp, startDown;
  1972. __GLfloat midPoint;
  1973. GLint intMidPoint, rowCount;
  1974. GLint width, height;
  1975. GLint readX, readY;
  1976. __GLfloat zoomx, zoomy;
  1977. __GLfloat rpx, rpy;
  1978. __GLfloat rx1, rx2, ry1, ry2, wx1, wx2, wy1, wy2;
  1979. __GLfloat abszoomy;
  1980. GLint readUp, readDown;
  1981. /*
  1982. ** NOTE:
  1983. ** A "nice" thing we could do for our application writers would be
  1984. ** to copy white when they try to copy from off window memory. This
  1985. ** would alert them to a bug in their program which they could then
  1986. ** fix.
  1987. **
  1988. ** However, that seems like unnecessary code which would never be used
  1989. ** anyway (no reason to bloat unnecessarily).
  1990. */
  1991. /*
  1992. ** We take the easy approach, and just call the DrawPixels and ReadPixels
  1993. ** clippers directly.
  1994. */
  1995. spanInfo->dstSkipLines = 0;
  1996. spanInfo->dstSkipPixels = 0;
  1997. if (!__glClipReadPixels(gc, spanInfo)) return GL_FALSE;
  1998. spanInfo->x += spanInfo->dstSkipPixels * spanInfo->zoomx;
  1999. spanInfo->y += spanInfo->dstSkipLines * spanInfo->zoomy;
  2000. spanInfo->srcSkipLines = 0;
  2001. spanInfo->srcSkipPixels = 0;
  2002. if (!__glClipDrawPixels(gc, spanInfo)) return GL_FALSE;
  2003. spanInfo->readX += spanInfo->srcSkipPixels;
  2004. if (gc->constants.yInverted) {
  2005. spanInfo->readY -= spanInfo->srcSkipLines;
  2006. } else {
  2007. spanInfo->readY += spanInfo->srcSkipLines;
  2008. }
  2009. /*
  2010. ** Now for the incredibly tricky part!
  2011. **
  2012. ** This code attempts to deal with overlapping CopyPixels regions.
  2013. ** It is a very difficult problem given that zoomy may be negative.
  2014. ** The IrisGL used a cheap hack to solve this problem, which is
  2015. ** to read in the entire source image, and then write the destination
  2016. ** image. The problem with this approach, of course, is that it
  2017. ** requires a large amount of memory.
  2018. **
  2019. ** If zoomy can only be positive, then any image can be copied by
  2020. ** copying a single span at a time, as long as you are careful about
  2021. ** what order you process the spans. However, since zoomy may be
  2022. ** negative, the worst case images require copying two spans at
  2023. ** a time. This means reading both spans, possibly modifying them,
  2024. ** and then writing them back out.
  2025. **
  2026. ** An example of this can be seen as follows: Suppose an image
  2027. ** covering 4 spans is copied onto itself with a zoomy of -1. This
  2028. ** means that the first row will be copied to the fourth row,
  2029. ** and the fourth row will be copied to the first row. In order
  2030. ** to accomplish both of these copies, they must be performed
  2031. ** simultaneously (after all, if you copy the first row to
  2032. ** the fourth row first, then you have just destroyed the data
  2033. ** on the fourth row, and you can no longer copy it!).
  2034. **
  2035. ** In the most general case, any rectangular image can be copied
  2036. ** by simultaneously iterating two spans over the source image
  2037. ** and copying as you go. Sometimes these spans will start at
  2038. ** the outside of the image and move their way inwards meeting
  2039. ** in the middle, and sometimes they will start in the middle
  2040. ** and work their way outward.
  2041. **
  2042. ** The middle point where the spans both start or end depends
  2043. ** upon how the source and destination images overlap. This point
  2044. ** may be exactly in the middle, or at either end. This means
  2045. ** that you may only end up with just a single span iterating over the
  2046. ** entire image (starting at one end and moving to the other).
  2047. **
  2048. ** The code that follows computes if the images overlap, and if they
  2049. ** do, how two spans can be used to iterate over the source image
  2050. ** so that it can be successfully copied to the destination image.
  2051. **
  2052. ** The following fields in the spanInfo record will be set in the
  2053. ** process of making these calculations:
  2054. **
  2055. ** overlap - set to GL_TRUE if the regions overlap at all. Set to
  2056. ** GL_FALSE otherwise.
  2057. **
  2058. ** rowsUp, rowsDown - The number of rows of the source image that
  2059. ** need to be dealt with by the span that moves up
  2060. ** over the source image and the one that moves down
  2061. ** over the source image. For example, if rowsUp is
  2062. ** equal to 10 and rowsDown is 0, then all 10 rows of
  2063. ** the image should be copied by the up moving span
  2064. ** (the one that starts at readY and works it's way
  2065. ** up to readY+height).
  2066. **
  2067. ** startUp, startDown - At what relative points in time the spans should
  2068. ** start iterating. For example, if startUp is 0
  2069. ** and startDown is 2, then the up moving span
  2070. ** should be started first, and after it has
  2071. ** iterated over 2 rows of the source image then
  2072. ** the down moving span should be started.
  2073. **
  2074. ** rpyUp, rpyDown - The starting raster positions for the two spans.
  2075. ** These numbers are not exactly what they claim to
  2076. ** be, but they are close. They should be used by
  2077. ** the span iterators in the following manner: When
  2078. ** the up moving span starts, it starts iterating
  2079. ** the float "rp_y" at rpyUp. After reading and
  2080. ** modifying a span, the span is written to rows
  2081. ** floor(rp_y) through floor(rp_y+zoomy) of the
  2082. ** screen (not-inclusive of floor(rp_y+zoomy)).
  2083. ** rp_y is then incremented by zoomy. The same
  2084. ** algorithm is applied to the down moving span except
  2085. ** that zoomy is subtracted from rp_y instead of
  2086. ** being added.
  2087. **
  2088. ** readUp, readDown - The spans that are to be used for reading from
  2089. ** the source image. The up moving span should start
  2090. ** reading at line "readUp", and the down moving span
  2091. ** should start at "readDown".
  2092. **
  2093. ** Remember that the up moving and down moving spans must be iterated
  2094. ** over the image simultaneously such that both spans are read before
  2095. ** either one is written.
  2096. **
  2097. ** The actual algorithm applied here took many many hours of scratch
  2098. ** paper, and graph diagrams to derive. It is very complicated, and
  2099. ** hard to understand. Do not attempt to change it without first
  2100. ** understanding what it does completely.
  2101. **
  2102. ** In a nutshell, it first computes what span of the source image
  2103. ** will be copied onto itself (if any), and if |zoomy| < 1 it starts the
  2104. ** up and down moving spans there and moves them outwards, or if
  2105. ** |zoomy| >= 1 it starts the spans at the outside of the image
  2106. ** and moves them inward so that they meet at the computed point.
  2107. **
  2108. ** Computing what span of the source image copies onto itself is
  2109. ** relatively easy. For any span j of the source image from 0 through
  2110. ** height, the span is read from row "readY + j" and written to
  2111. ** any row centers falling within the range "rp_y + j * zoomy" through
  2112. ** "rp_y + (j+1) * zoomy". If you set these equations equal to
  2113. ** each other (and subtract 0.5 from the raster position -- effectively
  2114. ** moving the row centers from X.5 to X.0), you can determine that for
  2115. ** j = (readY - (rpy - 0.5)) / (zoomy-1) the source image concides with
  2116. ** the destination image. This is a floating point solution to a discrete
  2117. ** problem, meaning that it is not a complete solution, but that is
  2118. ** the general idea. Explaining this algorithm in any more detail would
  2119. ** take another 1000 lines of comments, so I will leave it at that.
  2120. */
  2121. width = spanInfo->width;
  2122. height = spanInfo->height;
  2123. rpx = spanInfo->x;
  2124. rpy = spanInfo->y;
  2125. readX = spanInfo->readX;
  2126. readY = spanInfo->readY;
  2127. zoomx = spanInfo->zoomx;
  2128. zoomy = spanInfo->zoomy;
  2129. /* First check if the regions overlap at all */
  2130. if (gc->constants.yInverted) {
  2131. ry1 = readY - height + __glHalf;
  2132. ry2 = readY - gc->constants.viewportAlmostHalf;
  2133. } else {
  2134. ry1 = readY + __glHalf;
  2135. ry2 = readY + height - gc->constants.viewportAlmostHalf;
  2136. }
  2137. rx1 = readX + __glHalf;
  2138. rx2 = readX + width - gc->constants.viewportAlmostHalf;
  2139. if (zoomx > 0) {
  2140. /* Undo some math done by ClipDrawPixels */
  2141. rpx = rpx - gc->constants.viewportAlmostHalf;
  2142. wx1 = rpx;
  2143. wx2 = rpx + zoomx * width;
  2144. } else {
  2145. /* Undo some math done by ClipDrawPixels */
  2146. rpx = rpx - gc->constants.viewportAlmostHalf + __glOne;
  2147. wx1 = rpx + zoomx * width;
  2148. wx2 = rpx;
  2149. }
  2150. if (zoomy > 0) {
  2151. /* Undo some math done by ClipDrawPixels */
  2152. rpy = rpy - gc->constants.viewportAlmostHalf;
  2153. abszoomy = zoomy;
  2154. wy1 = rpy;
  2155. wy2 = rpy + zoomy * height;
  2156. } else {
  2157. /* Undo some math done by ClipDrawPixels */
  2158. rpy = rpy - gc->constants.viewportAlmostHalf + __glOne;
  2159. abszoomy = -zoomy;
  2160. wy1 = rpy + zoomy * height;
  2161. wy2 = rpy;
  2162. }
  2163. if (rx2 < wx1 || wx2 < rx1 || ry2 < wy1 || wy2 < ry1) {
  2164. /* No overlap! */
  2165. spanInfo->overlap = GL_FALSE;
  2166. spanInfo->rowsUp = height;
  2167. spanInfo->rowsDown = 0;
  2168. spanInfo->startUp = 0;
  2169. spanInfo->startDown = 0;
  2170. spanInfo->rpyUp = rpy;
  2171. spanInfo->rpyDown = rpy;
  2172. return GL_TRUE;
  2173. }
  2174. spanInfo->overlap = GL_TRUE;
  2175. /* Time to compute how we should set up our spans */
  2176. if (gc->constants.yInverted) {
  2177. num = (rpy - (__GLfloat) 0.5) - readY;
  2178. den = -zoomy - 1;
  2179. } else {
  2180. num = readY - (rpy - (__GLfloat) 0.5);
  2181. den = zoomy - 1;
  2182. }
  2183. startDown = startUp = 0;
  2184. rowsUp = rowsDown = 0;
  2185. rpyUp = rpy;
  2186. rpyDown = rpy + zoomy*height;
  2187. readUp = readY;
  2188. if (gc->constants.yInverted) {
  2189. readDown = readY - height + 1;
  2190. } else {
  2191. readDown = readY + height - 1;
  2192. }
  2193. if (den == __glZero) {
  2194. /* Better not divide! */
  2195. if (num > 0) {
  2196. midPoint = height;
  2197. } else {
  2198. midPoint = 0;
  2199. }
  2200. } else {
  2201. midPoint = num/den;
  2202. if (midPoint < 0) {
  2203. midPoint = 0;
  2204. } else if (midPoint > height) {
  2205. midPoint = height;
  2206. }
  2207. }
  2208. if (midPoint == 0) {
  2209. /* Only one span needed */
  2210. if (abszoomy < __glOne) {
  2211. rowsUp = height;
  2212. } else {
  2213. rowsDown = height;
  2214. }
  2215. } else if (midPoint == height) {
  2216. /* Only one span needed */
  2217. if (abszoomy < __glOne) {
  2218. rowsDown = height;
  2219. } else {
  2220. rowsUp = height;
  2221. }
  2222. } else {
  2223. /* Almost definitely need two spans to copy this image! */
  2224. intMidPoint = __GL_CEILF(midPoint);
  2225. rowCount = height - intMidPoint;
  2226. if (intMidPoint > rowCount) {
  2227. rowCount = intMidPoint;
  2228. }
  2229. if (abszoomy > __glOne) {
  2230. GLint temp;
  2231. /* Move from outside of image inward */
  2232. startUp = rowCount - intMidPoint;
  2233. startDown = rowCount - (height - intMidPoint);
  2234. rowsUp = intMidPoint;
  2235. rowsDown = height - rowsUp;
  2236. if (gc->constants.yInverted) {
  2237. temp = readY - intMidPoint + 1;
  2238. } else {
  2239. temp = readY + intMidPoint - 1;
  2240. }
  2241. if (__GL_FLOORF( (temp -
  2242. (rpy-__glHalf-gc->constants.viewportEpsilon))
  2243. / zoomy) == intMidPoint-1) {
  2244. /*
  2245. ** row "intMidPoint-1" copies exactly onto itself. Let's
  2246. ** make it the midpoint which we converge to.
  2247. */
  2248. if (startDown) {
  2249. startDown--;
  2250. } else {
  2251. startUp++;
  2252. }
  2253. }
  2254. } else {
  2255. /* Move from inside of image outward */
  2256. rowsDown = intMidPoint;
  2257. rowsUp = height - rowsDown;
  2258. rpyUp = rpyDown = rpy + zoomy * intMidPoint;
  2259. if (gc->constants.yInverted) {
  2260. readUp = readY - intMidPoint;
  2261. readDown = readY - intMidPoint + 1;
  2262. } else {
  2263. readUp = readY + intMidPoint;
  2264. readDown = readY + intMidPoint - 1;
  2265. }
  2266. if (__GL_FLOORF( (readDown -
  2267. (rpy-__glHalf-gc->constants.viewportEpsilon))
  2268. / zoomy) == intMidPoint-1) {
  2269. /*
  2270. ** row "intMidPoint-1" copies exactly onto itself. Let's
  2271. ** make it the midpoint which we diverge from.
  2272. */
  2273. startUp = 1;
  2274. }
  2275. }
  2276. }
  2277. /*
  2278. ** Adjust rpyUp and rpyDown so that they will change integer values
  2279. ** when fragments should be produced. This basically takes the 0.5
  2280. ** out of the inner loop when these spans are actually iterated.
  2281. */
  2282. if (zoomy > 0) {
  2283. spanInfo->rpyUp = rpyUp + gc->constants.viewportAlmostHalf;
  2284. spanInfo->rpyDown = rpyDown + gc->constants.viewportAlmostHalf -
  2285. __glOne;
  2286. } else {
  2287. spanInfo->rpyUp = rpyUp + gc->constants.viewportAlmostHalf - __glOne;
  2288. spanInfo->rpyDown = rpyDown + gc->constants.viewportAlmostHalf;
  2289. }
  2290. spanInfo->startUp = startUp;
  2291. spanInfo->startDown = startDown;
  2292. spanInfo->rowsUp = rowsUp;
  2293. spanInfo->rowsDown = rowsDown;
  2294. spanInfo->readUp = readUp;
  2295. spanInfo->readDown = readDown;
  2296. return GL_TRUE;
  2297. }
  2298. void __glInitCopyPixelsInfo(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2299. GLint x, GLint y, GLint width, GLint height,
  2300. GLenum format)
  2301. {
  2302. __GLfloat rpx, rpy;
  2303. __GLfloat zoomx, zoomy;
  2304. rpx = gc->state.current.rasterPos.window.x;
  2305. rpy = gc->state.current.rasterPos.window.y;
  2306. spanInfo->fragz = gc->state.current.rasterPos.window.z;
  2307. spanInfo->x = rpx;
  2308. spanInfo->y = rpy;
  2309. zoomx = gc->state.pixel.transferMode.zoomX;
  2310. if (zoomx > __glZero) {
  2311. if (zoomx < __glOne) {
  2312. spanInfo->rendZoomx = __glOne;
  2313. } else {
  2314. spanInfo->rendZoomx = zoomx;
  2315. }
  2316. spanInfo->coladd = 1;
  2317. } else {
  2318. if (zoomx > (GLfloat) -1.0) {
  2319. spanInfo->rendZoomx = (GLfloat) -1.0;
  2320. } else {
  2321. spanInfo->rendZoomx = zoomx;
  2322. }
  2323. spanInfo->coladd = -1;
  2324. }
  2325. spanInfo->zoomx = zoomx;
  2326. zoomy = gc->state.pixel.transferMode.zoomY;
  2327. if (gc->constants.yInverted) {
  2328. zoomy = -zoomy;
  2329. }
  2330. if (zoomy > __glZero) {
  2331. spanInfo->rowadd = 1;
  2332. } else {
  2333. spanInfo->rowadd = -1;
  2334. }
  2335. spanInfo->zoomy = zoomy;
  2336. spanInfo->readX = x + gc->constants.viewportXAdjust;
  2337. if (gc->constants.yInverted) {
  2338. spanInfo->readY = (gc->constants.height - y - 1) +
  2339. gc->constants.viewportYAdjust;
  2340. } else {
  2341. spanInfo->readY = y + gc->constants.viewportYAdjust;
  2342. }
  2343. spanInfo->dstFormat = spanInfo->srcFormat = format;
  2344. spanInfo->width = width;
  2345. spanInfo->height = height;
  2346. }
  2347. /*
  2348. ** A CopyPixels with two span modifiers.
  2349. */
  2350. void FASTCALL __glCopyPixels2(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  2351. {
  2352. __GLfloat newy;
  2353. __GLfloat zoomy;
  2354. GLint inty, i, ySign;
  2355. GLint height;
  2356. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2357. GLvoid *outspan);
  2358. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2359. GLvoid *inspan, GLvoid *outspan);
  2360. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2361. GLvoid *inspan, GLvoid *outspan);
  2362. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2363. GLvoid *inspan);
  2364. #ifdef NT
  2365. GLubyte *spanData1, *spanData2;
  2366. GLshort *pixelArray;
  2367. i = spanInfo->width * 4 * sizeof(GLfloat);
  2368. spanData1 = gcTempAlloc(gc, i);
  2369. spanData2 = gcTempAlloc(gc, i);
  2370. i = spanInfo->width * sizeof(GLshort);
  2371. pixelArray = gcTempAlloc(gc, i);
  2372. if (!spanData1 || !spanData2 || !pixelArray)
  2373. goto __glCopyPixels2_exit;
  2374. #else
  2375. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  2376. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  2377. #endif
  2378. spanInfo->pixelArray = pixelArray;
  2379. __glComputeSpanPixelArray(gc, spanInfo);
  2380. if (spanInfo->overlap) {
  2381. #ifdef NT
  2382. gcTempFree(gc, spanData1);
  2383. gcTempFree(gc, spanData2);
  2384. #endif
  2385. __glCopyPixelsOverlapping(gc, spanInfo, 2);
  2386. #ifdef NT
  2387. gcTempFree(gc, pixelArray);
  2388. #endif
  2389. return;
  2390. }
  2391. reader = spanInfo->spanReader;
  2392. span1 = spanInfo->spanModifier[0];
  2393. span2 = spanInfo->spanModifier[1];
  2394. render = spanInfo->spanRender;
  2395. ySign = gc->constants.ySign;
  2396. zoomy = spanInfo->zoomy;
  2397. inty = (GLint) spanInfo->y;
  2398. newy = spanInfo->y;
  2399. height = spanInfo->height;
  2400. for (i=0; i<height; i++) {
  2401. spanInfo->y = newy;
  2402. newy += zoomy;
  2403. while ((GLint) newy == inty && i<height) {
  2404. spanInfo->readY += ySign;
  2405. spanInfo->y = newy;
  2406. newy += zoomy;
  2407. i++;
  2408. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  2409. }
  2410. inty = (GLint) newy;
  2411. (*reader)(gc, spanInfo, spanData1);
  2412. (*span1)(gc, spanInfo, spanData1, spanData2);
  2413. (*span2)(gc, spanInfo, spanData2, spanData1);
  2414. (*render)(gc, spanInfo, spanData1);
  2415. spanInfo->readY += ySign;
  2416. }
  2417. #ifdef NT
  2418. __glCopyPixels2_exit:
  2419. if (spanData1) gcTempFree(gc, spanData1);
  2420. if (spanData2) gcTempFree(gc, spanData2);
  2421. if (pixelArray) gcTempFree(gc, pixelArray);
  2422. #endif
  2423. }
  2424. /*
  2425. ** A CopyPixels with one span modifier.
  2426. */
  2427. void FASTCALL __glCopyPixels1(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  2428. {
  2429. __GLfloat newy;
  2430. __GLfloat zoomy;
  2431. GLint inty, i, ySign;
  2432. GLint height;
  2433. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2434. GLvoid *outspan);
  2435. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2436. GLvoid *inspan, GLvoid *outspan);
  2437. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2438. GLvoid *inspan);
  2439. #ifdef NT
  2440. GLubyte *spanData1, *spanData2;
  2441. GLshort *pixelArray;
  2442. i = spanInfo->width * 4 * sizeof(GLfloat);
  2443. spanData1 = gcTempAlloc(gc, i);
  2444. spanData2 = gcTempAlloc(gc, i);
  2445. i = spanInfo->width * sizeof(GLshort);
  2446. pixelArray = gcTempAlloc(gc, i);
  2447. if (!spanData1 || !spanData2 || !pixelArray)
  2448. goto __glCopyPixels1_exit;
  2449. #else
  2450. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  2451. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  2452. #endif
  2453. spanInfo->pixelArray = pixelArray;
  2454. __glComputeSpanPixelArray(gc, spanInfo);
  2455. if (spanInfo->overlap) {
  2456. #ifdef NT
  2457. gcTempFree(gc, spanData1);
  2458. gcTempFree(gc, spanData2);
  2459. #endif
  2460. __glCopyPixelsOverlapping(gc, spanInfo, 1);
  2461. #ifdef NT
  2462. gcTempFree(gc, pixelArray);
  2463. #endif
  2464. return;
  2465. }
  2466. reader = spanInfo->spanReader;
  2467. span1 = spanInfo->spanModifier[0];
  2468. render = spanInfo->spanRender;
  2469. ySign = gc->constants.ySign;
  2470. zoomy = spanInfo->zoomy;
  2471. inty = (GLint) spanInfo->y;
  2472. newy = spanInfo->y;
  2473. height = spanInfo->height;
  2474. for (i=0; i<height; i++) {
  2475. spanInfo->y = newy;
  2476. newy += zoomy;
  2477. while ((GLint) newy == inty && i<height) {
  2478. spanInfo->readY += ySign;
  2479. spanInfo->y = newy;
  2480. newy += zoomy;
  2481. i++;
  2482. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  2483. }
  2484. inty = (GLint) newy;
  2485. (*reader)(gc, spanInfo, spanData1);
  2486. (*span1)(gc, spanInfo, spanData1, spanData2);
  2487. (*render)(gc, spanInfo, spanData2);
  2488. spanInfo->readY += ySign;
  2489. }
  2490. #ifdef NT
  2491. __glCopyPixels1_exit:
  2492. if (spanData1) gcTempFree(gc, spanData1);
  2493. if (spanData2) gcTempFree(gc, spanData2);
  2494. if (pixelArray) gcTempFree(gc, pixelArray);
  2495. #endif
  2496. }
  2497. /*
  2498. ** Copy pixels with no span modifiers.
  2499. */
  2500. void FASTCALL __glCopyPixels0(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  2501. {
  2502. __GLfloat newy;
  2503. __GLfloat zoomy;
  2504. GLint inty, i, ySign;
  2505. GLint height;
  2506. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2507. GLvoid *outspan);
  2508. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2509. GLvoid *inspan);
  2510. #ifdef NT
  2511. GLubyte *spanData1;
  2512. GLshort *pixelArray;
  2513. spanData1 = gcTempAlloc(gc, spanInfo->width * 4 * sizeof(GLfloat));
  2514. pixelArray = gcTempAlloc(gc, spanInfo->width * sizeof(GLshort));
  2515. if (!spanData1 || !pixelArray)
  2516. goto __glCopyPixels0_exit;
  2517. #else
  2518. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  2519. GLshort pixelArray[__GL_MAX_MAX_VIEWPORT];
  2520. #endif
  2521. spanInfo->pixelArray = pixelArray;
  2522. __glComputeSpanPixelArray(gc, spanInfo);
  2523. if (spanInfo->overlap) {
  2524. #ifdef NT
  2525. gcTempFree(gc, spanData1);
  2526. #endif
  2527. __glCopyPixelsOverlapping(gc, spanInfo, 0);
  2528. #ifdef NT
  2529. gcTempFree(gc, pixelArray);
  2530. #endif
  2531. return;
  2532. }
  2533. reader = spanInfo->spanReader;
  2534. render = spanInfo->spanRender;
  2535. ySign = gc->constants.ySign;
  2536. zoomy = spanInfo->zoomy;
  2537. inty = (GLint) spanInfo->y;
  2538. newy = spanInfo->y;
  2539. height = spanInfo->height;
  2540. for (i=0; i<height; i++) {
  2541. spanInfo->y = newy;
  2542. newy += zoomy;
  2543. while ((GLint) newy == inty && i<height) {
  2544. spanInfo->readY += ySign;
  2545. spanInfo->y = newy;
  2546. newy += zoomy;
  2547. i++;
  2548. ASSERTOPENGL(i != height, "Zoomed off surface\n");
  2549. }
  2550. inty = (GLint) newy;
  2551. (*reader)(gc, spanInfo, spanData1);
  2552. (*render)(gc, spanInfo, spanData1);
  2553. spanInfo->readY += ySign;
  2554. }
  2555. #ifdef NT
  2556. __glCopyPixels0_exit:
  2557. if (spanData1) gcTempFree(gc, spanData1);
  2558. if (pixelArray) gcTempFree(gc, pixelArray);
  2559. #endif
  2560. }
  2561. /*
  2562. ** Yick!
  2563. **
  2564. ** This routine is provided to perform CopyPixels when the source and
  2565. ** destination images overlap.
  2566. **
  2567. ** It is not designed to go particularly fast, but then overlapping
  2568. ** copies is probably not too common, and this routine is not typically a
  2569. ** large part of the execution overhead anyway.
  2570. **
  2571. ** For more information on copying an image which overlaps its destination,
  2572. ** check out the hairy comment within the __glClipCopyPixels function.
  2573. */
  2574. void FASTCALL __glCopyPixelsOverlapping(__GLcontext *gc,
  2575. __GLpixelSpanInfo *spanInfo, GLint modifiers)
  2576. {
  2577. GLint i;
  2578. __GLfloat zoomy, newy;
  2579. GLint inty, ySign;
  2580. GLubyte *outSpan1, *outSpan2;
  2581. GLint rowsUp, rowsDown;
  2582. GLint startUp, startDown;
  2583. __GLfloat rpyUp, rpyDown;
  2584. GLint readUp, readDown;
  2585. GLint gotUp, gotDown;
  2586. __GLpixelSpanInfo downSpanInfo;
  2587. GLint clipLow, clipHigh;
  2588. GLint startRow, endRow;
  2589. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2590. GLvoid *outspan);
  2591. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2592. GLvoid *inspan);
  2593. #ifdef NT
  2594. GLubyte *spanData1, *spanData2, *spanData3;
  2595. i = spanInfo->width * 4 * sizeof(GLfloat);
  2596. spanData1 = gcTempAlloc(gc, i);
  2597. spanData2 = gcTempAlloc(gc, i);
  2598. spanData3 = gcTempAlloc(gc, i);
  2599. if (!spanData1 || !spanData2 || !spanData3)
  2600. goto __glCopyPixelsOverlapping_exit;
  2601. #else
  2602. GLubyte spanData1[__GL_MAX_SPAN_SIZE], spanData2[__GL_MAX_SPAN_SIZE];
  2603. GLubyte spanData3[__GL_MAX_SPAN_SIZE];
  2604. #endif
  2605. reader = spanInfo->spanReader;
  2606. render = spanInfo->spanRender;
  2607. if (modifiers & 1) {
  2608. outSpan1 = outSpan2 = spanData3;
  2609. } else {
  2610. outSpan1 = spanData1;
  2611. outSpan2 = spanData2;
  2612. }
  2613. zoomy = spanInfo->zoomy;
  2614. rowsUp = spanInfo->rowsUp;
  2615. rowsDown = spanInfo->rowsDown;
  2616. startUp = spanInfo->startUp;
  2617. startDown = spanInfo->startDown;
  2618. rpyUp = spanInfo->rpyUp;
  2619. rpyDown = spanInfo->rpyDown;
  2620. readUp = spanInfo->readUp;
  2621. readDown = spanInfo->readDown;
  2622. downSpanInfo = *spanInfo;
  2623. downSpanInfo.rowadd = -spanInfo->rowadd;
  2624. downSpanInfo.zoomy = -zoomy;
  2625. spanInfo->y = rpyUp;
  2626. downSpanInfo.y = rpyDown;
  2627. spanInfo->readY = readUp;
  2628. downSpanInfo.readY = readDown;
  2629. gotUp = gotDown = 0;
  2630. ySign = gc->constants.ySign;
  2631. /* Clip upgoing and downgoing spans */
  2632. if (zoomy > 0) {
  2633. clipLow = spanInfo->startRow;
  2634. clipHigh = spanInfo->startRow + spanInfo->rows - 1;
  2635. /* Clip down span first */
  2636. startRow = (GLint) rpyDown;
  2637. endRow = (GLint) (rpyDown - zoomy*rowsDown) + 1;
  2638. if (startRow > clipHigh) startRow = clipHigh;
  2639. if (endRow < clipLow) endRow = clipLow;
  2640. downSpanInfo.startRow = startRow;
  2641. downSpanInfo.rows = startRow - endRow + 1;
  2642. /* Now clip up span */
  2643. startRow = (GLint) rpyUp;
  2644. endRow = (GLint) (rpyUp + zoomy*rowsUp) - 1;
  2645. if (startRow < clipLow) startRow = clipLow;
  2646. if (endRow > clipHigh) endRow = clipHigh;
  2647. spanInfo->startRow = startRow;
  2648. spanInfo->rows = endRow - startRow + 1;
  2649. } else /* zoomy < 0 */ {
  2650. clipHigh = spanInfo->startRow;
  2651. clipLow = spanInfo->startRow - spanInfo->rows + 1;
  2652. /* Clip down span first */
  2653. startRow = (GLint) rpyDown;
  2654. endRow = (GLint) (rpyDown - zoomy*rowsDown) - 1;
  2655. if (startRow < clipLow) startRow = clipLow;
  2656. if (endRow > clipHigh) endRow = clipHigh;
  2657. downSpanInfo.startRow = startRow;
  2658. downSpanInfo.rows = endRow - startRow + 1;
  2659. /* Now clip up span */
  2660. startRow = (GLint) rpyUp;
  2661. endRow = (GLint) (rpyUp + zoomy*rowsUp) + 1;
  2662. if (startRow > clipHigh) startRow = clipHigh;
  2663. if (endRow < clipLow) endRow = clipLow;
  2664. spanInfo->startRow = startRow;
  2665. spanInfo->rows = startRow - endRow + 1;
  2666. }
  2667. while (rowsUp && rowsDown) {
  2668. if (startUp) {
  2669. startUp--;
  2670. } else {
  2671. gotUp = 1;
  2672. rowsUp--;
  2673. spanInfo->y = rpyUp;
  2674. newy = rpyUp + zoomy;
  2675. inty = (GLint) rpyUp;
  2676. while (rowsUp && (GLint) newy == inty) {
  2677. spanInfo->y = newy;
  2678. newy += zoomy;
  2679. rowsUp--;
  2680. spanInfo->readY += ySign;
  2681. }
  2682. if (inty == (GLint) newy) break;
  2683. rpyUp = newy;
  2684. (*reader)(gc, spanInfo, spanData1);
  2685. spanInfo->readY += ySign;
  2686. }
  2687. if (startDown) {
  2688. startDown--;
  2689. } else {
  2690. gotDown = 1;
  2691. rowsDown--;
  2692. downSpanInfo.y = rpyDown;
  2693. newy = rpyDown - zoomy;
  2694. inty = (GLint) rpyDown;
  2695. while (rowsDown && (GLint) newy == inty) {
  2696. downSpanInfo.y = newy;
  2697. newy -= zoomy;
  2698. rowsDown--;
  2699. downSpanInfo.readY -= ySign;
  2700. }
  2701. if (inty == (GLint) newy) {
  2702. if (gotUp) {
  2703. for (i=0; i<modifiers; i++) {
  2704. if (i & 1) {
  2705. (*(spanInfo->spanModifier[i]))(gc, spanInfo,
  2706. spanData3, spanData1);
  2707. } else {
  2708. (*(spanInfo->spanModifier[i]))(gc, spanInfo,
  2709. spanData1, spanData3);
  2710. }
  2711. }
  2712. (*render)(gc, spanInfo, outSpan1);
  2713. }
  2714. break;
  2715. }
  2716. rpyDown = newy;
  2717. (*reader)(gc, &downSpanInfo, spanData2);
  2718. downSpanInfo.readY -= ySign;
  2719. }
  2720. if (gotUp) {
  2721. for (i=0; i<modifiers; i++) {
  2722. if (i & 1) {
  2723. (*(spanInfo->spanModifier[i]))(gc, spanInfo,
  2724. spanData3, spanData1);
  2725. } else {
  2726. (*(spanInfo->spanModifier[i]))(gc, spanInfo,
  2727. spanData1, spanData3);
  2728. }
  2729. }
  2730. (*render)(gc, spanInfo, outSpan1);
  2731. }
  2732. if (gotDown) {
  2733. for (i=0; i<modifiers; i++) {
  2734. if (i & 1) {
  2735. (*(spanInfo->spanModifier[i]))(gc, &downSpanInfo,
  2736. spanData3, spanData2);
  2737. } else {
  2738. (*(spanInfo->spanModifier[i]))(gc, &downSpanInfo,
  2739. spanData2, spanData3);
  2740. }
  2741. }
  2742. (*render)(gc, &downSpanInfo, outSpan2);
  2743. }
  2744. }
  2745. /*
  2746. ** Only one of the spanners is left to iterate.
  2747. */
  2748. while (rowsUp) {
  2749. /* Do what is left of up spans */
  2750. rowsUp--;
  2751. spanInfo->y = rpyUp;
  2752. newy = rpyUp + zoomy;
  2753. inty = (GLint) rpyUp;
  2754. while (rowsUp && (GLint) newy == inty) {
  2755. spanInfo->y = newy;
  2756. newy += zoomy;
  2757. rowsUp--;
  2758. spanInfo->readY += ySign;
  2759. }
  2760. if (inty == (GLint) newy) break;
  2761. rpyUp = newy;
  2762. (*reader)(gc, spanInfo, spanData1);
  2763. for (i=0; i<modifiers; i++) {
  2764. if (i & 1) {
  2765. (*(spanInfo->spanModifier[i]))(gc, spanInfo,
  2766. spanData3, spanData1);
  2767. } else {
  2768. (*(spanInfo->spanModifier[i]))(gc, spanInfo,
  2769. spanData1, spanData3);
  2770. }
  2771. }
  2772. (*render)(gc, spanInfo, outSpan1);
  2773. spanInfo->readY += ySign;
  2774. }
  2775. while (rowsDown) {
  2776. /* Do what is left of down spans */
  2777. rowsDown--;
  2778. downSpanInfo.y = rpyDown;
  2779. newy = rpyDown - zoomy;
  2780. inty = (GLint) rpyDown;
  2781. while (rowsDown && (GLint) newy == inty) {
  2782. downSpanInfo.y = newy;
  2783. newy -= zoomy;
  2784. rowsDown--;
  2785. downSpanInfo.readY -= ySign;
  2786. }
  2787. if (inty == (GLint) newy) break;
  2788. rpyDown = newy;
  2789. (*reader)(gc, &downSpanInfo, spanData2);
  2790. for (i=0; i<modifiers; i++) {
  2791. if (i & 1) {
  2792. (*(spanInfo->spanModifier[i]))(gc, &downSpanInfo,
  2793. spanData3, spanData2);
  2794. } else {
  2795. (*(spanInfo->spanModifier[i]))(gc, &downSpanInfo,
  2796. spanData2, spanData3);
  2797. }
  2798. }
  2799. (*render)(gc, &downSpanInfo, outSpan2);
  2800. downSpanInfo.readY -= ySign;
  2801. }
  2802. #ifdef NT
  2803. __glCopyPixelsOverlapping_exit:
  2804. if (spanData1) gcTempFree(gc, spanData1);
  2805. if (spanData2) gcTempFree(gc, spanData2);
  2806. if (spanData3) gcTempFree(gc, spanData3);
  2807. #endif
  2808. }
  2809. /*
  2810. ** Generic implementation of a CopyPixels picker. Any machine specific
  2811. ** implementation should provide their own.
  2812. */
  2813. void __glSlowPickCopyPixels(__GLcontext *gc, GLint x, GLint y, GLint width,
  2814. GLint height, GLenum type)
  2815. {
  2816. __GLpixelSpanInfo spanInfo;
  2817. __glInitCopyPixelsInfo(gc, &spanInfo, x, y, width, height, type);
  2818. if (!__glClipCopyPixels(gc, &spanInfo)) return;
  2819. __glGenericPickCopyPixels(gc, &spanInfo);
  2820. }
  2821. /*
  2822. ** Generic picker for CopyPixels. This should be called if no machine
  2823. ** specific path is provided for this specific version of CopyPixels.
  2824. */
  2825. void FASTCALL __glGenericPickCopyPixels(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  2826. {
  2827. __GLpixelMachine *pm;
  2828. void (FASTCALL *reader)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2829. GLvoid *outspan);
  2830. void (FASTCALL *render)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  2831. GLvoid *inspan);
  2832. void (FASTCALL *cpfn)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo);
  2833. GLint spanCount;
  2834. GLboolean zoomx1; /* -1 <= zoomx <= 1? */
  2835. GLboolean zoomx2; /* zoomx <= -1 || zoomx >= 1 */
  2836. __GLfloat zoomx;
  2837. GLenum format;
  2838. pm = &gc->pixel;
  2839. spanCount = 0;
  2840. zoomx = gc->state.pixel.transferMode.zoomX;
  2841. if (zoomx >= (__GLfloat) -1.0 && zoomx <= __glOne) {
  2842. zoomx1 = GL_TRUE;
  2843. } else {
  2844. zoomx1 = GL_FALSE;
  2845. }
  2846. if (zoomx <= (__GLfloat) -1.0 || zoomx >= __glOne) {
  2847. zoomx2 = GL_TRUE;
  2848. } else {
  2849. zoomx2 = GL_FALSE;
  2850. }
  2851. format = spanInfo->dstFormat;
  2852. #ifdef NT
  2853. // Special case RGB copying to use a DIB
  2854. // Also special case copying the Z buffer
  2855. if (format == GL_RGBA)
  2856. {
  2857. GLuint enables = gc->state.enables.general;
  2858. // Look to see if we're doing direct buffer-to-buffer copying
  2859. // Things that can't be allowed are depth testing,
  2860. // fogging, blending or anything that prevents the input data
  2861. // from going directly into the destination buffer
  2862. if (zoomx == __glOne &&
  2863. gc->state.pixel.transferMode.zoomY == __glOne &&
  2864. !pm->modifyRGBA &&
  2865. (enables & (__GL_DITHER_ENABLE |
  2866. __GL_ALPHA_TEST_ENABLE |
  2867. __GL_STENCIL_TEST_ENABLE |
  2868. __GL_DEPTH_TEST_ENABLE |
  2869. __GL_BLEND_ENABLE |
  2870. __GL_INDEX_LOGIC_OP_ENABLE |
  2871. __GL_COLOR_LOGIC_OP_ENABLE |
  2872. __GL_FOG_ENABLE)) == 0 &&
  2873. gc->state.raster.drawBuffer != GL_NONE &&
  2874. gc->state.raster.drawBuffer != GL_FRONT_AND_BACK &&
  2875. !gc->texture.textureEnabled &&
  2876. (gc->drawBuffer->buf.flags & COLORMASK_ON) == 0
  2877. #ifdef _MCD_
  2878. && ((__GLGENcontext *)gc)->pMcdState == NULL
  2879. #endif
  2880. )
  2881. {
  2882. if (CopyRgbPixels(gc, spanInfo))
  2883. {
  2884. return;
  2885. }
  2886. }
  2887. }
  2888. else if (format == GL_DEPTH_COMPONENT)
  2889. {
  2890. // If the Z test is GL_ALWAYS and there is no draw buffer
  2891. // then the application is simply copying Z values around
  2892. // the Z buffer.
  2893. if (zoomx == __glOne &&
  2894. gc->state.pixel.transferMode.zoomY == __glOne &&
  2895. !pm->modifyDepth &&
  2896. gc->state.raster.drawBuffer == GL_NONE &&
  2897. (gc->state.enables.general & __GL_DEPTH_TEST_ENABLE) &&
  2898. gc->state.depth.testFunc == GL_ALWAYS &&
  2899. gc->modes.haveDepthBuffer
  2900. #ifdef _MCD_
  2901. && ((__GLGENcontext *)gc)->pMcdState == NULL
  2902. #endif
  2903. )
  2904. {
  2905. if (CopyZPixels(gc, spanInfo))
  2906. {
  2907. return;
  2908. }
  2909. }
  2910. }
  2911. #endif
  2912. switch(format) {
  2913. case GL_RGBA:
  2914. if (zoomx2) {
  2915. reader = gc->procs.pixel.spanReadRGBA2;
  2916. } else {
  2917. reader = gc->procs.pixel.spanReadRGBA;
  2918. }
  2919. if (pm->modifyRGBA) {
  2920. spanInfo->spanModifier[spanCount++] = __glSpanUnscaleRGBA;
  2921. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGBA;
  2922. }
  2923. if (zoomx1) {
  2924. render = gc->procs.pixel.spanRenderRGBA2;
  2925. } else {
  2926. render = gc->procs.pixel.spanRenderRGBA;
  2927. }
  2928. break;
  2929. case GL_COLOR_INDEX:
  2930. if (zoomx2) {
  2931. reader = gc->procs.pixel.spanReadCI2;
  2932. } else {
  2933. reader = gc->procs.pixel.spanReadCI;
  2934. }
  2935. if (pm->modifyCI) {
  2936. spanInfo->spanModifier[spanCount++] = __glSpanModifyCI;
  2937. }
  2938. if (zoomx1) {
  2939. render = gc->procs.pixel.spanRenderCI2;
  2940. } else {
  2941. render = gc->procs.pixel.spanRenderCI;
  2942. }
  2943. break;
  2944. case GL_STENCIL_INDEX:
  2945. if (zoomx2) {
  2946. reader = gc->procs.pixel.spanReadStencil2;
  2947. } else {
  2948. reader = gc->procs.pixel.spanReadStencil;
  2949. }
  2950. if (pm->modifyStencil) {
  2951. spanInfo->spanModifier[spanCount++] = __glSpanModifyStencil;
  2952. }
  2953. if (zoomx1) {
  2954. render = gc->procs.pixel.spanRenderStencil2;
  2955. } else {
  2956. render = gc->procs.pixel.spanRenderStencil;
  2957. }
  2958. break;
  2959. case GL_DEPTH_COMPONENT:
  2960. if (zoomx2) {
  2961. reader = gc->procs.pixel.spanReadDepth2;
  2962. } else {
  2963. reader = gc->procs.pixel.spanReadDepth;
  2964. }
  2965. if (pm->modifyDepth) {
  2966. spanInfo->spanModifier[spanCount++] = __glSpanModifyDepth;
  2967. }
  2968. if (zoomx1) {
  2969. render = gc->procs.pixel.spanRenderDepth2;
  2970. } else {
  2971. render = gc->procs.pixel.spanRenderDepth;
  2972. }
  2973. break;
  2974. }
  2975. switch(spanCount) {
  2976. case 0:
  2977. cpfn = __glCopyPixels0;
  2978. break;
  2979. case 1:
  2980. cpfn = __glCopyPixels1;
  2981. break;
  2982. default:
  2983. ASSERTOPENGL(FALSE, "Default hit\n");
  2984. case 2:
  2985. cpfn = __glCopyPixels2;
  2986. break;
  2987. }
  2988. spanInfo->spanReader = reader;
  2989. spanInfo->spanRender = render;
  2990. (*cpfn)(gc, spanInfo);
  2991. }
  2992. /*
  2993. ** A simple image copying routine with one span modifier.
  2994. */
  2995. void FASTCALL __glCopyImage1(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  2996. {
  2997. GLint i;
  2998. GLint height;
  2999. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3000. GLvoid *inspan, GLvoid *outspan);
  3001. height = spanInfo->height;
  3002. span1 = spanInfo->spanModifier[0];
  3003. for (i=0; i<height; i++) {
  3004. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanInfo->dstCurrent);
  3005. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3006. spanInfo->srcRowIncrement;
  3007. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3008. spanInfo->dstRowIncrement;
  3009. }
  3010. }
  3011. /*
  3012. ** A simple image copying routine with two span modifiers.
  3013. */
  3014. void FASTCALL __glCopyImage2(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  3015. {
  3016. GLint i;
  3017. GLint height;
  3018. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3019. GLvoid *inspan, GLvoid *outspan);
  3020. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3021. GLvoid *inspan, GLvoid *outspan);
  3022. #ifdef NT
  3023. GLubyte *spanData1;
  3024. spanData1 = gcTempAlloc(gc, spanInfo->width * 4 * sizeof(GLfloat));
  3025. if (!spanData1)
  3026. return;
  3027. #else
  3028. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  3029. #endif
  3030. height = spanInfo->height;
  3031. span1 = spanInfo->spanModifier[0];
  3032. span2 = spanInfo->spanModifier[1];
  3033. for (i=0; i<height; i++) {
  3034. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  3035. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3036. spanInfo->srcRowIncrement;
  3037. (*span2)(gc, spanInfo, spanData1, spanInfo->dstCurrent);
  3038. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3039. spanInfo->dstRowIncrement;
  3040. }
  3041. #ifdef NT
  3042. gcTempFree(gc, spanData1);
  3043. #endif
  3044. }
  3045. /*
  3046. ** A simple image copying routine with three span modifiers.
  3047. */
  3048. void FASTCALL __glCopyImage3(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  3049. {
  3050. GLint i;
  3051. GLint height;
  3052. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3053. GLvoid *inspan, GLvoid *outspan);
  3054. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3055. GLvoid *inspan, GLvoid *outspan);
  3056. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3057. GLvoid *inspan, GLvoid *outspan);
  3058. #ifdef NT
  3059. GLubyte *spanData1, *spanData2;
  3060. i = spanInfo->width * 4 * sizeof(GLfloat);
  3061. spanData1 = gcTempAlloc(gc, i);
  3062. spanData2 = gcTempAlloc(gc, i);
  3063. if (!spanData1 || !spanData2)
  3064. goto __glCopyImage3_exit;
  3065. #else
  3066. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  3067. GLubyte spanData2[__GL_MAX_SPAN_SIZE];
  3068. #endif
  3069. height = spanInfo->height;
  3070. span1 = spanInfo->spanModifier[0];
  3071. span2 = spanInfo->spanModifier[1];
  3072. span3 = spanInfo->spanModifier[2];
  3073. for (i=0; i<height; i++) {
  3074. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  3075. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3076. spanInfo->srcRowIncrement;
  3077. (*span2)(gc, spanInfo, spanData1, spanData2);
  3078. (*span3)(gc, spanInfo, spanData2, spanInfo->dstCurrent);
  3079. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3080. spanInfo->dstRowIncrement;
  3081. }
  3082. #ifdef NT
  3083. __glCopyImage3_exit:
  3084. if (spanData1) gcTempFree(gc, spanData1);
  3085. if (spanData2) gcTempFree(gc, spanData2);
  3086. #endif
  3087. }
  3088. /*
  3089. ** A simple image copying routine with four span modifiers.
  3090. */
  3091. void FASTCALL __glCopyImage4(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  3092. {
  3093. GLint i;
  3094. GLint height;
  3095. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3096. GLvoid *inspan, GLvoid *outspan);
  3097. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3098. GLvoid *inspan, GLvoid *outspan);
  3099. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3100. GLvoid *inspan, GLvoid *outspan);
  3101. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3102. GLvoid *inspan, GLvoid *outspan);
  3103. #ifdef NT
  3104. GLubyte *spanData1, *spanData2;
  3105. i = spanInfo->width * 4 * sizeof(GLfloat);
  3106. spanData1 = gcTempAlloc(gc, i);
  3107. spanData2 = gcTempAlloc(gc, i);
  3108. if (!spanData1 || !spanData2)
  3109. goto __glCopyImage4_exit;
  3110. #else
  3111. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  3112. GLubyte spanData2[__GL_MAX_SPAN_SIZE];
  3113. #endif
  3114. height = spanInfo->height;
  3115. span1 = spanInfo->spanModifier[0];
  3116. span2 = spanInfo->spanModifier[1];
  3117. span3 = spanInfo->spanModifier[2];
  3118. span4 = spanInfo->spanModifier[3];
  3119. for (i=0; i<height; i++) {
  3120. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  3121. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3122. spanInfo->srcRowIncrement;
  3123. (*span2)(gc, spanInfo, spanData1, spanData2);
  3124. (*span3)(gc, spanInfo, spanData2, spanData1);
  3125. (*span4)(gc, spanInfo, spanData1, spanInfo->dstCurrent);
  3126. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3127. spanInfo->dstRowIncrement;
  3128. }
  3129. #ifdef NT
  3130. __glCopyImage4_exit:
  3131. if (spanData1) gcTempFree(gc, spanData1);
  3132. if (spanData2) gcTempFree(gc, spanData2);
  3133. #endif
  3134. }
  3135. /*
  3136. ** A simple image copying routine with five span modifiers.
  3137. */
  3138. void FASTCALL __glCopyImage5(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  3139. {
  3140. GLint i;
  3141. GLint height;
  3142. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3143. GLvoid *inspan, GLvoid *outspan);
  3144. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3145. GLvoid *inspan, GLvoid *outspan);
  3146. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3147. GLvoid *inspan, GLvoid *outspan);
  3148. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3149. GLvoid *inspan, GLvoid *outspan);
  3150. void (*span5)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3151. GLvoid *inspan, GLvoid *outspan);
  3152. #ifdef NT
  3153. GLubyte *spanData1, *spanData2;
  3154. i = spanInfo->width * 4 * sizeof(GLfloat);
  3155. spanData1 = gcTempAlloc(gc, i);
  3156. spanData2 = gcTempAlloc(gc, i);
  3157. if (!spanData1 || !spanData2)
  3158. goto __glCopyImage5_exit;
  3159. #else
  3160. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  3161. GLubyte spanData2[__GL_MAX_SPAN_SIZE];
  3162. #endif
  3163. height = spanInfo->height;
  3164. span1 = spanInfo->spanModifier[0];
  3165. span2 = spanInfo->spanModifier[1];
  3166. span3 = spanInfo->spanModifier[2];
  3167. span4 = spanInfo->spanModifier[3];
  3168. span5 = spanInfo->spanModifier[4];
  3169. for (i=0; i<height; i++) {
  3170. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  3171. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3172. spanInfo->srcRowIncrement;
  3173. (*span2)(gc, spanInfo, spanData1, spanData2);
  3174. (*span3)(gc, spanInfo, spanData2, spanData1);
  3175. (*span4)(gc, spanInfo, spanData1, spanData2);
  3176. (*span5)(gc, spanInfo, spanData2, spanInfo->dstCurrent);
  3177. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3178. spanInfo->dstRowIncrement;
  3179. }
  3180. #ifdef NT
  3181. __glCopyImage5_exit:
  3182. if (spanData1) gcTempFree(gc, spanData1);
  3183. if (spanData2) gcTempFree(gc, spanData2);
  3184. #endif
  3185. }
  3186. /*
  3187. ** A simple image copying routine with six span modifiers.
  3188. */
  3189. void FASTCALL __glCopyImage6(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  3190. {
  3191. GLint i;
  3192. GLint height;
  3193. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3194. GLvoid *inspan, GLvoid *outspan);
  3195. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3196. GLvoid *inspan, GLvoid *outspan);
  3197. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3198. GLvoid *inspan, GLvoid *outspan);
  3199. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3200. GLvoid *inspan, GLvoid *outspan);
  3201. void (*span5)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3202. GLvoid *inspan, GLvoid *outspan);
  3203. void (*span6)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3204. GLvoid *inspan, GLvoid *outspan);
  3205. #ifdef NT
  3206. GLubyte *spanData1, *spanData2;
  3207. i = spanInfo->width * 4 * sizeof(GLfloat);
  3208. spanData1 = gcTempAlloc(gc, i);
  3209. spanData2 = gcTempAlloc(gc, i);
  3210. if (!spanData1 || !spanData2)
  3211. goto __glCopyImage6_exit;
  3212. #else
  3213. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  3214. GLubyte spanData2[__GL_MAX_SPAN_SIZE];
  3215. #endif
  3216. height = spanInfo->height;
  3217. span1 = spanInfo->spanModifier[0];
  3218. span2 = spanInfo->spanModifier[1];
  3219. span3 = spanInfo->spanModifier[2];
  3220. span4 = spanInfo->spanModifier[3];
  3221. span5 = spanInfo->spanModifier[4];
  3222. span6 = spanInfo->spanModifier[5];
  3223. for (i=0; i<height; i++) {
  3224. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  3225. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3226. spanInfo->srcRowIncrement;
  3227. (*span2)(gc, spanInfo, spanData1, spanData2);
  3228. (*span3)(gc, spanInfo, spanData2, spanData1);
  3229. (*span4)(gc, spanInfo, spanData1, spanData2);
  3230. (*span5)(gc, spanInfo, spanData2, spanData1);
  3231. (*span6)(gc, spanInfo, spanData1, spanInfo->dstCurrent);
  3232. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3233. spanInfo->dstRowIncrement;
  3234. }
  3235. #ifdef NT
  3236. __glCopyImage6_exit:
  3237. if (spanData1) gcTempFree(gc, spanData1);
  3238. if (spanData2) gcTempFree(gc, spanData2);
  3239. #endif
  3240. }
  3241. /*
  3242. ** A simple image copying routine with seven span modifiers.
  3243. */
  3244. void FASTCALL __glCopyImage7(__GLcontext *gc, __GLpixelSpanInfo *spanInfo)
  3245. {
  3246. GLint i;
  3247. GLint height;
  3248. void (*span1)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3249. GLvoid *inspan, GLvoid *outspan);
  3250. void (*span2)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3251. GLvoid *inspan, GLvoid *outspan);
  3252. void (*span3)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3253. GLvoid *inspan, GLvoid *outspan);
  3254. void (*span4)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3255. GLvoid *inspan, GLvoid *outspan);
  3256. void (*span5)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3257. GLvoid *inspan, GLvoid *outspan);
  3258. void (*span6)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3259. GLvoid *inspan, GLvoid *outspan);
  3260. void (*span7)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3261. GLvoid *inspan, GLvoid *outspan);
  3262. #ifdef NT
  3263. GLubyte *spanData1, *spanData2;
  3264. i = spanInfo->width * 4 * sizeof(GLfloat);
  3265. spanData1 = gcTempAlloc(gc, i);
  3266. spanData2 = gcTempAlloc(gc, i);
  3267. if (!spanData1 || !spanData2)
  3268. goto __glCopyImage7_exit;
  3269. #else
  3270. GLubyte spanData1[__GL_MAX_SPAN_SIZE];
  3271. GLubyte spanData2[__GL_MAX_SPAN_SIZE];
  3272. #endif
  3273. height = spanInfo->height;
  3274. span1 = spanInfo->spanModifier[0];
  3275. span2 = spanInfo->spanModifier[1];
  3276. span3 = spanInfo->spanModifier[2];
  3277. span4 = spanInfo->spanModifier[3];
  3278. span5 = spanInfo->spanModifier[4];
  3279. span6 = spanInfo->spanModifier[5];
  3280. span7 = spanInfo->spanModifier[6];
  3281. for (i=0; i<height; i++) {
  3282. (*span1)(gc, spanInfo, spanInfo->srcCurrent, spanData1);
  3283. spanInfo->srcCurrent = (GLubyte *) spanInfo->srcCurrent +
  3284. spanInfo->srcRowIncrement;
  3285. (*span2)(gc, spanInfo, spanData1, spanData2);
  3286. (*span3)(gc, spanInfo, spanData2, spanData1);
  3287. (*span4)(gc, spanInfo, spanData1, spanData2);
  3288. (*span5)(gc, spanInfo, spanData2, spanData1);
  3289. (*span6)(gc, spanInfo, spanData1, spanData2);
  3290. (*span7)(gc, spanInfo, spanData2, spanInfo->dstCurrent);
  3291. spanInfo->dstCurrent = (GLubyte *) spanInfo->dstCurrent +
  3292. spanInfo->dstRowIncrement;
  3293. }
  3294. #ifdef NT
  3295. __glCopyImage7_exit:
  3296. if (spanData1) gcTempFree(gc, spanData1);
  3297. if (spanData2) gcTempFree(gc, spanData2);
  3298. #endif
  3299. }
  3300. /*
  3301. ** Internal image processing routine. Used by GetTexImage to transfer from
  3302. ** internal texture image to the user. Used by TexImage[12]D to transfer
  3303. ** from the user to internal texture. Used for display list optimization of
  3304. ** textures and DrawPixels.
  3305. **
  3306. ** This routine also supports the pixel format mode __GL_RED_ALPHA which is
  3307. ** basically a 2 component texture.
  3308. **
  3309. ** If applyPixelTransfer is set to GL_TRUE, pixel transfer modes will be
  3310. ** applied as necessary.
  3311. */
  3312. void FASTCALL __glGenericPickCopyImage(__GLcontext *gc, __GLpixelSpanInfo *spanInfo,
  3313. GLboolean applyPixelTransfer)
  3314. {
  3315. GLint spanCount;
  3316. GLboolean srcPackedData;
  3317. GLenum srcType, srcFormat;
  3318. GLboolean srcSwap;
  3319. GLboolean srcAlign;
  3320. GLboolean srcConvert;
  3321. GLboolean srcExpand;
  3322. GLboolean srcClamp;
  3323. GLenum dstType, dstFormat;
  3324. GLboolean dstSwap;
  3325. GLboolean dstAlign;
  3326. GLboolean dstConvert;
  3327. GLboolean dstReduce;
  3328. GLboolean modify;
  3329. __GLpixelMachine *pm;
  3330. void (FASTCALL *cpfn)(__GLcontext *gc, __GLpixelSpanInfo *spanInfo);
  3331. pm = &gc->pixel;
  3332. spanCount = 0;
  3333. srcPackedData = spanInfo->srcPackedData;
  3334. srcType = spanInfo->srcType;
  3335. srcFormat = spanInfo->srcFormat;
  3336. dstType = spanInfo->dstType;
  3337. dstFormat = spanInfo->dstFormat;
  3338. switch(srcFormat) {
  3339. case GL_RED:
  3340. case GL_GREEN:
  3341. case GL_BLUE:
  3342. case GL_ALPHA:
  3343. case GL_RGB:
  3344. case GL_LUMINANCE:
  3345. case GL_LUMINANCE_ALPHA:
  3346. case __GL_RED_ALPHA:
  3347. case GL_RGBA:
  3348. #ifdef GL_EXT_bgra
  3349. case GL_BGRA_EXT:
  3350. case GL_BGR_EXT:
  3351. #endif
  3352. #ifdef GL_EXT_paletted_texture
  3353. case __GL_PALETTE_INDEX:
  3354. #endif
  3355. modify = applyPixelTransfer && pm->modifyRGBA;
  3356. break;
  3357. case GL_DEPTH_COMPONENT:
  3358. modify = applyPixelTransfer && pm->modifyDepth;
  3359. break;
  3360. case GL_STENCIL_INDEX:
  3361. modify = applyPixelTransfer && pm->modifyStencil;
  3362. break;
  3363. case GL_COLOR_INDEX:
  3364. modify = applyPixelTransfer && pm->modifyCI;
  3365. break;
  3366. }
  3367. if ((srcFormat == dstFormat ||
  3368. (srcFormat == GL_LUMINANCE_ALPHA && dstFormat == __GL_RED_ALPHA) ||
  3369. (srcFormat == __GL_RED_ALPHA && dstFormat == GL_LUMINANCE_ALPHA) ||
  3370. (srcFormat == GL_LUMINANCE && dstFormat == GL_RED) ||
  3371. (srcFormat == GL_RED && dstFormat == GL_LUMINANCE)) && !modify) {
  3372. srcExpand = GL_FALSE;
  3373. dstReduce = GL_FALSE;
  3374. } else {
  3375. srcExpand = GL_TRUE;
  3376. dstReduce = GL_TRUE;
  3377. }
  3378. if (srcType == GL_FLOAT) {
  3379. srcConvert = GL_FALSE;
  3380. } else {
  3381. srcConvert = GL_TRUE;
  3382. }
  3383. if (dstType == GL_FLOAT) {
  3384. dstConvert = GL_FALSE;
  3385. } else {
  3386. dstConvert = GL_TRUE;
  3387. }
  3388. if (spanInfo->srcSwapBytes && spanInfo->srcElementSize > 1) {
  3389. srcSwap = GL_TRUE;
  3390. } else {
  3391. srcSwap = GL_FALSE;
  3392. }
  3393. if (spanInfo->dstSwapBytes && spanInfo->dstElementSize > 1) {
  3394. dstSwap = GL_TRUE;
  3395. } else {
  3396. dstSwap = GL_FALSE;
  3397. }
  3398. if (srcType != GL_BITMAP &&
  3399. (((INT_PTR) (spanInfo->srcImage)) & (spanInfo->srcElementSize - 1))) {
  3400. srcAlign = GL_TRUE;
  3401. } else {
  3402. srcAlign = GL_FALSE;
  3403. }
  3404. if (dstType != GL_BITMAP &&
  3405. (((INT_PTR) (spanInfo->dstImage)) & (spanInfo->dstElementSize - 1))) {
  3406. dstAlign = GL_TRUE;
  3407. } else {
  3408. dstAlign = GL_FALSE;
  3409. }
  3410. if (srcType == GL_BITMAP || srcType == GL_UNSIGNED_BYTE ||
  3411. srcType == GL_UNSIGNED_SHORT || srcType == GL_UNSIGNED_INT ||
  3412. srcFormat == GL_COLOR_INDEX || srcFormat == GL_STENCIL_INDEX ||
  3413. modify) {
  3414. srcClamp = GL_FALSE;
  3415. } else {
  3416. srcClamp = GL_TRUE;
  3417. }
  3418. if (srcType == dstType && srcType != GL_BITMAP && !srcExpand && !srcClamp) {
  3419. srcConvert = dstConvert = GL_FALSE;
  3420. }
  3421. #ifdef NT
  3422. // Special case copying where it's a straight data copy from
  3423. // the source to the destination
  3424. if (!srcSwap && !srcAlign && !srcConvert && !srcClamp && !srcExpand &&
  3425. !dstReduce && !dstConvert && !dstSwap && !dstAlign)
  3426. {
  3427. if (CopyAlignedImage(gc, spanInfo))
  3428. {
  3429. return;
  3430. }
  3431. }
  3432. else if (srcType == GL_UNSIGNED_BYTE && dstType == GL_UNSIGNED_BYTE &&
  3433. !srcAlign && !dstAlign)
  3434. {
  3435. // Special case expanding a 24-bit RGB texture into 32-bit BGRA
  3436. if (srcFormat == GL_RGB && dstFormat == GL_BGRA_EXT)
  3437. {
  3438. if (CopyRgbToBgraImage(gc, spanInfo))
  3439. {
  3440. return;
  3441. }
  3442. }
  3443. // Special case flipping a 32-bit RGBA texture into 32-bit BGRA
  3444. else if (srcFormat == GL_RGBA && dstFormat == GL_BGRA_EXT)
  3445. {
  3446. if (CopyRgbaToBgraImage(gc, spanInfo))
  3447. {
  3448. return;
  3449. }
  3450. }
  3451. // Special case expanding a 24-bit BGR texture into 32-bit BGRA
  3452. else if (srcFormat == GL_BGR_EXT && dstFormat == GL_BGRA_EXT)
  3453. {
  3454. if (CopyBgrToBgraImage(gc, spanInfo))
  3455. {
  3456. return;
  3457. }
  3458. }
  3459. }
  3460. #endif
  3461. /*
  3462. ** First step: Swap, align the data, etc.
  3463. */
  3464. if (srcSwap) {
  3465. if (spanInfo->srcElementSize == 2) {
  3466. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes2;
  3467. } else /* spanInfo->srcElementSize == 4 */ {
  3468. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes4;
  3469. }
  3470. } else if (srcAlign) {
  3471. if (spanInfo->srcElementSize == 2) {
  3472. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels2;
  3473. } else /* spanInfo->srcElementSize == 4 */ {
  3474. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels4;
  3475. }
  3476. }
  3477. /*
  3478. ** Second step: conversion to float
  3479. */
  3480. if (srcConvert) {
  3481. if (srcFormat == GL_COLOR_INDEX || srcFormat == GL_STENCIL_INDEX) {
  3482. /* Index conversion */
  3483. switch(srcType) {
  3484. case GL_BYTE:
  3485. spanInfo->spanModifier[spanCount++] = __glSpanUnpackByteI;
  3486. break;
  3487. case GL_UNSIGNED_BYTE:
  3488. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUbyteI;
  3489. break;
  3490. case GL_SHORT:
  3491. spanInfo->spanModifier[spanCount++] = __glSpanUnpackShortI;
  3492. break;
  3493. case GL_UNSIGNED_SHORT:
  3494. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUshortI;
  3495. break;
  3496. case GL_INT:
  3497. spanInfo->spanModifier[spanCount++] = __glSpanUnpackIntI;
  3498. break;
  3499. case GL_UNSIGNED_INT:
  3500. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUintI;
  3501. break;
  3502. case GL_BITMAP:
  3503. spanInfo->spanModifier[spanCount++] = __glSpanUnpackBitmap2;
  3504. break;
  3505. }
  3506. } else {
  3507. /* Component conversion */
  3508. switch(srcType) {
  3509. case GL_BYTE:
  3510. spanInfo->spanModifier[spanCount++] = __glSpanUnpackByte;
  3511. break;
  3512. case GL_UNSIGNED_BYTE:
  3513. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUbyte;
  3514. break;
  3515. case GL_SHORT:
  3516. spanInfo->spanModifier[spanCount++] = __glSpanUnpackShort;
  3517. break;
  3518. case GL_UNSIGNED_SHORT:
  3519. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUshort;
  3520. break;
  3521. case GL_INT:
  3522. spanInfo->spanModifier[spanCount++] = __glSpanUnpackInt;
  3523. break;
  3524. case GL_UNSIGNED_INT:
  3525. spanInfo->spanModifier[spanCount++] = __glSpanUnpackUint;
  3526. break;
  3527. case GL_BITMAP:
  3528. spanInfo->spanModifier[spanCount++] = __glSpanUnpackBitmap2;
  3529. break;
  3530. }
  3531. }
  3532. }
  3533. /*
  3534. ** Third step: Clamp if necessary.
  3535. */
  3536. if (srcClamp) {
  3537. switch(srcType) {
  3538. case GL_BYTE:
  3539. case GL_SHORT:
  3540. case GL_INT:
  3541. spanInfo->spanModifier[spanCount++] = __glSpanClampSigned;
  3542. break;
  3543. case GL_FLOAT:
  3544. spanInfo->spanModifier[spanCount++] = __glSpanClampFloat;
  3545. break;
  3546. }
  3547. }
  3548. /*
  3549. ** Fourth step: Expansion to RGBA, Modification and scale colors (sortof a
  3550. ** side effect).
  3551. */
  3552. if (srcExpand) {
  3553. switch(srcFormat) {
  3554. case GL_RED:
  3555. if (modify) {
  3556. spanInfo->spanModifier[spanCount++] = __glSpanModifyRed;
  3557. } else {
  3558. spanInfo->spanModifier[spanCount++] = __glSpanExpandRed;
  3559. }
  3560. break;
  3561. case GL_GREEN:
  3562. if (modify) {
  3563. spanInfo->spanModifier[spanCount++] = __glSpanModifyGreen;
  3564. } else {
  3565. spanInfo->spanModifier[spanCount++] = __glSpanExpandGreen;
  3566. }
  3567. break;
  3568. case GL_BLUE:
  3569. if (modify) {
  3570. spanInfo->spanModifier[spanCount++] = __glSpanModifyBlue;
  3571. } else {
  3572. spanInfo->spanModifier[spanCount++] = __glSpanExpandBlue;
  3573. }
  3574. break;
  3575. case GL_ALPHA:
  3576. if (modify) {
  3577. spanInfo->spanModifier[spanCount++] = __glSpanModifyAlpha;
  3578. } else {
  3579. spanInfo->spanModifier[spanCount++] = __glSpanExpandAlpha;
  3580. }
  3581. break;
  3582. case GL_RGB:
  3583. if (modify) {
  3584. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGB;
  3585. } else {
  3586. spanInfo->spanModifier[spanCount++] = __glSpanExpandRGB;
  3587. }
  3588. break;
  3589. #ifdef GL_EXT_bgra
  3590. case GL_BGR_EXT:
  3591. if (modify) {
  3592. // __glSpanModifyRGB handles both RGB and BGR
  3593. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGB;
  3594. } else {
  3595. spanInfo->spanModifier[spanCount++] = __glSpanExpandBGR;
  3596. }
  3597. break;
  3598. #endif
  3599. case GL_LUMINANCE:
  3600. if (modify) {
  3601. spanInfo->spanModifier[spanCount++] = __glSpanModifyLuminance;
  3602. } else {
  3603. spanInfo->spanModifier[spanCount++] = __glSpanExpandLuminance;
  3604. }
  3605. break;
  3606. case GL_LUMINANCE_ALPHA:
  3607. if (modify) {
  3608. spanInfo->spanModifier[spanCount++] =
  3609. __glSpanModifyLuminanceAlpha;
  3610. } else {
  3611. spanInfo->spanModifier[spanCount++] =
  3612. __glSpanExpandLuminanceAlpha;
  3613. }
  3614. break;
  3615. case __GL_RED_ALPHA:
  3616. if (modify) {
  3617. spanInfo->spanModifier[spanCount++] = __glSpanModifyRedAlpha;
  3618. } else {
  3619. spanInfo->spanModifier[spanCount++] = __glSpanExpandRedAlpha;
  3620. }
  3621. break;
  3622. case GL_RGBA:
  3623. if (modify) {
  3624. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGBA;
  3625. } else {
  3626. spanInfo->spanModifier[spanCount++] = __glSpanScaleRGBA;
  3627. }
  3628. break;
  3629. #ifdef GL_EXT_bgra
  3630. case GL_BGRA_EXT:
  3631. if (modify) {
  3632. // __glSpanModifyRGBA handles both RGBA and BGRA
  3633. spanInfo->spanModifier[spanCount++] = __glSpanModifyRGBA;
  3634. } else {
  3635. spanInfo->spanModifier[spanCount++] = __glSpanScaleBGRA;
  3636. }
  3637. break;
  3638. #endif
  3639. case GL_DEPTH_COMPONENT:
  3640. if (modify) {
  3641. spanInfo->spanModifier[spanCount++] = __glSpanModifyDepth;
  3642. }
  3643. break;
  3644. case GL_STENCIL_INDEX:
  3645. if (modify) {
  3646. spanInfo->spanModifier[spanCount++] = __glSpanModifyStencil;
  3647. }
  3648. break;
  3649. case GL_COLOR_INDEX:
  3650. if (modify) {
  3651. spanInfo->spanModifier[spanCount++] = __glSpanModifyCI;
  3652. }
  3653. break;
  3654. #ifdef GL_EXT_paletted_texture
  3655. case __GL_PALETTE_INDEX:
  3656. if (modify) {
  3657. spanInfo->spanModifier[spanCount++] = __glSpanModifyPI;
  3658. } else {
  3659. spanInfo->spanModifier[spanCount++] = __glSpanScalePI;
  3660. }
  3661. break;
  3662. #endif
  3663. }
  3664. }
  3665. /*
  3666. ** Fifth step: Reduce RGBA spans to appropriate derivative (RED,
  3667. ** LUMINANCE, ALPHA, etc.).
  3668. */
  3669. if (dstReduce) {
  3670. switch(dstFormat) {
  3671. case GL_RGB:
  3672. spanInfo->spanModifier[spanCount++] = __glSpanReduceRGB;
  3673. break;
  3674. #ifdef GL_EXT_bgra
  3675. case GL_BGR_EXT:
  3676. spanInfo->spanModifier[spanCount++] = __glSpanReduceBGR;
  3677. break;
  3678. #endif
  3679. case GL_RED:
  3680. spanInfo->spanModifier[spanCount++] = __glSpanReduceRed;
  3681. break;
  3682. case GL_GREEN:
  3683. spanInfo->spanModifier[spanCount++] = __glSpanReduceGreen;
  3684. break;
  3685. case GL_BLUE:
  3686. spanInfo->spanModifier[spanCount++] = __glSpanReduceBlue;
  3687. break;
  3688. case GL_LUMINANCE:
  3689. spanInfo->spanModifier[spanCount++] = __glSpanReduceLuminance;
  3690. break;
  3691. case GL_LUMINANCE_ALPHA:
  3692. spanInfo->spanModifier[spanCount++] = __glSpanReduceLuminanceAlpha;
  3693. break;
  3694. case __GL_RED_ALPHA:
  3695. spanInfo->spanModifier[spanCount++] = __glSpanReduceRedAlpha;
  3696. break;
  3697. case GL_ALPHA:
  3698. spanInfo->spanModifier[spanCount++] = __glSpanReduceAlpha;
  3699. break;
  3700. case GL_RGBA:
  3701. spanInfo->spanModifier[spanCount++] = __glSpanUnscaleRGBA;
  3702. break;
  3703. #ifdef GL_EXT_bgra
  3704. case GL_BGRA_EXT:
  3705. spanInfo->spanModifier[spanCount++] = __glSpanUnscaleBGRA;
  3706. break;
  3707. #endif
  3708. #ifdef NT
  3709. case GL_COLOR_INDEX:
  3710. break;
  3711. default:
  3712. // We should never be asked to reduce to palette indices
  3713. // so add this assert to catch such a request
  3714. ASSERTOPENGL(FALSE, "Unhandled copy_image reduction\n");
  3715. break;
  3716. #endif
  3717. }
  3718. }
  3719. /*
  3720. ** Sixth step: Conversion from FLOAT to requested type.
  3721. */
  3722. if (dstConvert) {
  3723. if (dstFormat == GL_COLOR_INDEX || dstFormat == GL_STENCIL_INDEX) {
  3724. switch(dstType) {
  3725. case GL_BYTE:
  3726. spanInfo->spanModifier[spanCount++] = __glSpanPackByteI;
  3727. break;
  3728. case GL_UNSIGNED_BYTE:
  3729. spanInfo->spanModifier[spanCount++] = __glSpanPackUbyteI;
  3730. break;
  3731. case GL_SHORT:
  3732. spanInfo->spanModifier[spanCount++] = __glSpanPackShortI;
  3733. break;
  3734. case GL_UNSIGNED_SHORT:
  3735. spanInfo->spanModifier[spanCount++] = __glSpanPackUshortI;
  3736. break;
  3737. case GL_INT:
  3738. spanInfo->spanModifier[spanCount++] = __glSpanPackIntI;
  3739. break;
  3740. case GL_UNSIGNED_INT:
  3741. spanInfo->spanModifier[spanCount++] = __glSpanPackUintI;
  3742. break;
  3743. case GL_BITMAP:
  3744. spanInfo->spanModifier[spanCount++] = __glSpanPackBitmap;
  3745. break;
  3746. }
  3747. } else {
  3748. switch(dstType) {
  3749. case GL_BYTE:
  3750. spanInfo->spanModifier[spanCount++] = __glSpanPackByte;
  3751. break;
  3752. case GL_UNSIGNED_BYTE:
  3753. spanInfo->spanModifier[spanCount++] = __glSpanPackUbyte;
  3754. break;
  3755. case GL_SHORT:
  3756. spanInfo->spanModifier[spanCount++] = __glSpanPackShort;
  3757. break;
  3758. case GL_UNSIGNED_SHORT:
  3759. spanInfo->spanModifier[spanCount++] = __glSpanPackUshort;
  3760. break;
  3761. case GL_INT:
  3762. spanInfo->spanModifier[spanCount++] = __glSpanPackInt;
  3763. break;
  3764. case GL_UNSIGNED_INT:
  3765. spanInfo->spanModifier[spanCount++] = __glSpanPackUint;
  3766. break;
  3767. }
  3768. }
  3769. }
  3770. /*
  3771. ** Seventh step: Mis-align data as needed, and perform byte swapping
  3772. ** if requested by the user.
  3773. */
  3774. if (dstSwap) {
  3775. if (spanInfo->dstElementSize == 2) {
  3776. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes2Dst;
  3777. } else /* if (spanInfo->dstElementSize == 4) */ {
  3778. spanInfo->spanModifier[spanCount++] = __glSpanSwapBytes4Dst;
  3779. }
  3780. } else if (dstAlign) {
  3781. if (spanInfo->dstElementSize == 2) {
  3782. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels2Dst;
  3783. } else /* if (spanInfo->dstElementSize == 4) */ {
  3784. spanInfo->spanModifier[spanCount++] = __glSpanAlignPixels4Dst;
  3785. }
  3786. }
  3787. /*
  3788. ** Sanity check: If we have zero span routines, then this simply
  3789. ** isn't going to work. We need to at least copy the data.
  3790. */
  3791. if (spanCount == 0) {
  3792. spanInfo->spanModifier[spanCount++] = __glSpanCopy;
  3793. }
  3794. /*
  3795. ** Final step: Pick a copying function.
  3796. */
  3797. switch(spanCount) {
  3798. case 1:
  3799. cpfn = __glCopyImage1;
  3800. break;
  3801. case 2:
  3802. cpfn = __glCopyImage2;
  3803. break;
  3804. case 3:
  3805. cpfn = __glCopyImage3;
  3806. break;
  3807. case 4:
  3808. cpfn = __glCopyImage4;
  3809. break;
  3810. case 5:
  3811. cpfn = __glCopyImage5;
  3812. break;
  3813. case 6:
  3814. cpfn = __glCopyImage6;
  3815. break;
  3816. default:
  3817. ASSERTOPENGL(FALSE, "Default hit\n");
  3818. case 7:
  3819. cpfn = __glCopyImage7;
  3820. break;
  3821. }
  3822. (*cpfn)(gc, spanInfo);
  3823. }