Leaked source code of windows server 2003
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.

1107 lines
28 KiB

  1. /*
  2. ** Copyright 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. ** $Revision: 1.4 $
  18. ** $Date: 1996/03/29 01:55:31 $
  19. */
  20. #ifdef NT
  21. #include <glos.h>
  22. #endif
  23. #include <assert.h>
  24. #include "gluint.h"
  25. #include <GL/glu.h>
  26. #include <stdio.h>
  27. #ifdef NT
  28. #include "winmem.h"
  29. #else
  30. #include <stdlib.h>
  31. #endif
  32. #include <string.h>
  33. #include <math.h>
  34. typedef union {
  35. unsigned char ub[4];
  36. unsigned short us[2];
  37. unsigned long ui;
  38. char b[4];
  39. short s[2];
  40. long i;
  41. float f;
  42. } Type_Widget;
  43. /* Pixel storage modes */
  44. typedef struct {
  45. GLint pack_alignment;
  46. GLint pack_row_length;
  47. GLint pack_skip_rows;
  48. GLint pack_skip_pixels;
  49. GLint pack_lsb_first;
  50. GLint pack_swap_bytes;
  51. GLint unpack_alignment;
  52. GLint unpack_row_length;
  53. GLint unpack_skip_rows;
  54. GLint unpack_skip_pixels;
  55. GLint unpack_lsb_first;
  56. GLint unpack_swap_bytes;
  57. } PixelStorageModes;
  58. /*
  59. * internal function declarations
  60. */
  61. static GLfloat bytes_per_element(GLenum type);
  62. static GLint elements_per_group(GLenum format);
  63. #ifdef NT
  64. static GLboolean is_index(GLenum format);
  65. #else
  66. static GLint is_index(GLenum format);
  67. #endif
  68. static GLint image_size(GLint width, GLint height, GLenum format, GLenum type);
  69. static void fill_image(const PixelStorageModes *,
  70. GLint width, GLint height, GLenum format,
  71. GLenum type, GLboolean index_format,
  72. const void *userdata, GLushort *newimage);
  73. static void empty_image(const PixelStorageModes *,
  74. GLint width, GLint height, GLenum format,
  75. GLenum type, GLboolean index_format,
  76. const GLushort *oldimage, void *userdata);
  77. static void scale_internal(GLint components, GLint widthin, GLint heightin,
  78. const GLushort *datain,
  79. GLint widthout, GLint heightout,
  80. GLushort *dataout);
  81. static GLint retrieveStoreModes(PixelStorageModes *psm)
  82. {
  83. glGetError();
  84. glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
  85. if (glGetError() != GL_NO_ERROR)
  86. {
  87. return 1;
  88. }
  89. glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
  90. if (glGetError() != GL_NO_ERROR)
  91. {
  92. return 1;
  93. }
  94. glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
  95. if (glGetError() != GL_NO_ERROR)
  96. {
  97. return 1;
  98. }
  99. glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
  100. if (glGetError() != GL_NO_ERROR)
  101. {
  102. return 1;
  103. }
  104. glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
  105. if (glGetError() != GL_NO_ERROR)
  106. {
  107. return 1;
  108. }
  109. glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
  110. if (glGetError() != GL_NO_ERROR)
  111. {
  112. return 1;
  113. }
  114. glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
  115. if (glGetError() != GL_NO_ERROR)
  116. {
  117. return 1;
  118. }
  119. glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
  120. if (glGetError() != GL_NO_ERROR)
  121. {
  122. return 1;
  123. }
  124. glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
  125. if (glGetError() != GL_NO_ERROR)
  126. {
  127. return 1;
  128. }
  129. glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
  130. if (glGetError() != GL_NO_ERROR)
  131. {
  132. return 1;
  133. }
  134. glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
  135. if (glGetError() != GL_NO_ERROR)
  136. {
  137. return 1;
  138. }
  139. glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
  140. if (glGetError() != GL_NO_ERROR)
  141. {
  142. return 1;
  143. }
  144. return 0;
  145. }
  146. static int computeLog(GLuint value)
  147. {
  148. int i;
  149. i = 0;
  150. /* Error! */
  151. if (value == 0) return -1;
  152. for (;;) {
  153. if (value & 1) {
  154. /* Error ! */
  155. if (value != 1) return -1;
  156. return i;
  157. }
  158. value = value >> 1;
  159. i++;
  160. }
  161. }
  162. /*
  163. ** Compute the nearest power of 2 number. This algorithm is a little
  164. ** strange, but it works quite well.
  165. */
  166. static int nearestPower(GLuint value)
  167. {
  168. int i;
  169. i = 1;
  170. /* Error! */
  171. if (value == 0) return -1;
  172. for (;;) {
  173. if (value == 1) {
  174. return i;
  175. } else if (value == 3) {
  176. return i*4;
  177. }
  178. value = value >> 1;
  179. i *= 2;
  180. }
  181. }
  182. static void halveImage(GLint components, GLuint width, GLuint height,
  183. const GLushort *datain, GLushort *dataout)
  184. {
  185. int i, j, k;
  186. int newwidth, newheight;
  187. int delta;
  188. GLushort *s;
  189. const GLushort *t;
  190. newwidth = width / 2;
  191. newheight = height / 2;
  192. delta = width * components;
  193. s = dataout;
  194. t = datain;
  195. /* Piece o' cake! */
  196. for (i = 0; i < newheight; i++) {
  197. for (j = 0; j < newwidth; j++) {
  198. for (k = 0; k < components; k++) {
  199. s[0] = (t[0] + t[components] + t[delta] +
  200. t[delta+components] + 2) / 4;
  201. s++; t++;
  202. }
  203. t += components;
  204. }
  205. t += delta;
  206. }
  207. }
  208. static void scale_internal(GLint components, GLint widthin, GLint heightin,
  209. const GLushort *datain,
  210. GLint widthout, GLint heightout,
  211. GLushort *dataout)
  212. {
  213. float x, lowx, highx, convx, halfconvx;
  214. float y, lowy, highy, convy, halfconvy;
  215. float xpercent,ypercent;
  216. float percent;
  217. /* Max components in a format is 4, so... */
  218. float totals[4];
  219. float area;
  220. int i,j,k,yint,xint,xindex,yindex;
  221. int temp;
  222. if (widthin == widthout*2 && heightin == heightout*2) {
  223. halveImage(components, widthin, heightin, datain, dataout);
  224. return;
  225. }
  226. convy = (float) heightin/heightout;
  227. convx = (float) widthin/widthout;
  228. halfconvx = convx/2;
  229. halfconvy = convy/2;
  230. for (i = 0; i < heightout; i++) {
  231. y = convy * (i+0.5);
  232. if (heightin > heightout) {
  233. highy = y + halfconvy;
  234. lowy = y - halfconvy;
  235. } else {
  236. highy = y + 0.5;
  237. lowy = y - 0.5;
  238. }
  239. for (j = 0; j < widthout; j++) {
  240. x = convx * (j+0.5);
  241. if (widthin > widthout) {
  242. highx = x + halfconvx;
  243. lowx = x - halfconvx;
  244. } else {
  245. highx = x + 0.5;
  246. lowx = x - 0.5;
  247. }
  248. /*
  249. ** Ok, now apply box filter to box that goes from (lowx, lowy)
  250. ** to (highx, highy) on input data into this pixel on output
  251. ** data.
  252. */
  253. totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
  254. area = 0.0;
  255. y = lowy;
  256. yint = floor(y);
  257. while (y < highy) {
  258. yindex = (yint + heightin) % heightin;
  259. if (highy < yint+1) {
  260. ypercent = highy - y;
  261. } else {
  262. ypercent = yint+1 - y;
  263. }
  264. x = lowx;
  265. xint = floor(x);
  266. while (x < highx) {
  267. xindex = (xint + widthin) % widthin;
  268. if (highx < xint+1) {
  269. xpercent = highx - x;
  270. } else {
  271. xpercent = xint+1 - x;
  272. }
  273. percent = xpercent * ypercent;
  274. area += percent;
  275. temp = (xindex + (yindex * widthin)) * components;
  276. for (k = 0; k < components; k++) {
  277. totals[k] += datain[temp + k] * percent;
  278. }
  279. xint++;
  280. x = xint;
  281. }
  282. yint++;
  283. y = yint;
  284. }
  285. temp = (j + (i * widthout)) * components;
  286. for (k = 0; k < components; k++) {
  287. dataout[temp + k] = totals[k]/area;
  288. }
  289. }
  290. }
  291. }
  292. static GLboolean legalFormat(GLenum format)
  293. {
  294. switch(format) {
  295. case GL_COLOR_INDEX:
  296. case GL_STENCIL_INDEX:
  297. case GL_DEPTH_COMPONENT:
  298. case GL_RED:
  299. case GL_GREEN:
  300. case GL_BLUE:
  301. case GL_ALPHA:
  302. case GL_RGB:
  303. case GL_RGBA:
  304. #ifdef GL_EXT_bgra
  305. case GL_BGR_EXT:
  306. case GL_BGRA_EXT:
  307. #endif
  308. case GL_LUMINANCE:
  309. case GL_LUMINANCE_ALPHA:
  310. return GL_TRUE;
  311. default:
  312. return GL_FALSE;
  313. }
  314. }
  315. static GLboolean legalType(GLenum type)
  316. {
  317. switch(type) {
  318. case GL_BITMAP:
  319. case GL_BYTE:
  320. case GL_UNSIGNED_BYTE:
  321. case GL_SHORT:
  322. case GL_UNSIGNED_SHORT:
  323. case GL_INT:
  324. case GL_UNSIGNED_INT:
  325. case GL_FLOAT:
  326. return GL_TRUE;
  327. default:
  328. return GL_FALSE;
  329. }
  330. }
  331. GLint gluScaleImage(GLenum format, GLint widthin, GLint heightin,
  332. GLenum typein, const void *datain,
  333. GLint widthout, GLint heightout, GLenum typeout,
  334. void *dataout)
  335. {
  336. int components;
  337. GLushort *beforeImage;
  338. GLushort *afterImage;
  339. PixelStorageModes psm;
  340. if (widthin == 0 || heightin == 0 || widthout == 0 || heightout == 0) {
  341. return 0;
  342. }
  343. if (widthin < 0 || heightin < 0 || widthout < 0 || heightout < 0) {
  344. return GLU_INVALID_VALUE;
  345. }
  346. if (!legalFormat(format) || !legalType(typein) || !legalType(typeout)) {
  347. return GLU_INVALID_ENUM;
  348. }
  349. if (retrieveStoreModes(&psm)) {
  350. return GL_OUT_OF_MEMORY;
  351. }
  352. beforeImage =
  353. malloc(image_size(widthin, heightin, format, GL_UNSIGNED_SHORT));
  354. afterImage =
  355. malloc(image_size(widthout, heightout, format, GL_UNSIGNED_SHORT));
  356. if (beforeImage == NULL || afterImage == NULL) {
  357. return GLU_OUT_OF_MEMORY;
  358. }
  359. fill_image(&psm,widthin, heightin, format, typein, is_index(format),
  360. datain, beforeImage);
  361. components = elements_per_group(format);
  362. scale_internal(components, widthin, heightin, beforeImage,
  363. widthout, heightout, afterImage);
  364. empty_image(&psm,widthout, heightout, format, typeout,
  365. is_index(format), afterImage, dataout);
  366. free((GLbyte *) beforeImage);
  367. free((GLbyte *) afterImage);
  368. return 0;
  369. }
  370. GLint gluBuild1DMipmaps(GLenum target, GLint components, GLint width,
  371. GLenum format, GLenum type, const void *data)
  372. {
  373. GLint newwidth;
  374. GLint level, levels;
  375. GLushort *newImage;
  376. GLint newImage_width;
  377. GLushort *otherImage;
  378. GLushort *imageTemp;
  379. GLint memreq;
  380. GLint maxsize;
  381. GLint cmpts;
  382. PixelStorageModes psm;
  383. GLboolean error = GL_FALSE;
  384. if (width < 1) {
  385. return GLU_INVALID_VALUE;
  386. }
  387. if (!legalFormat(format) || !legalType(type)) {
  388. return GLU_INVALID_ENUM;
  389. }
  390. if (format == GL_STENCIL_INDEX) {
  391. return GLU_INVALID_ENUM;
  392. }
  393. if (format == GL_DEPTH_COMPONENT) {
  394. return GLU_INVALID_ENUM;
  395. }
  396. if (retrieveStoreModes(&psm)) {
  397. return GL_OUT_OF_MEMORY;
  398. }
  399. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
  400. if (glGetError() != GL_NO_ERROR)
  401. {
  402. return GL_OUT_OF_MEMORY;
  403. }
  404. newwidth = nearestPower(width);
  405. if (newwidth > maxsize) newwidth = maxsize;
  406. levels = computeLog(newwidth);
  407. otherImage = NULL;
  408. newImage = (GLushort *)
  409. malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT));
  410. newImage_width = width;
  411. if (newImage == NULL) {
  412. return GLU_OUT_OF_MEMORY;
  413. }
  414. fill_image(&psm,width, 1, format, type, is_index(format),
  415. data, newImage);
  416. cmpts = elements_per_group(format);
  417. glGetError();
  418. glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  419. if (glGetError() != GL_NO_ERROR) {
  420. error = GL_TRUE;
  421. goto gluBuild1DMipmaps_cleanup;
  422. }
  423. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  424. if (glGetError() != GL_NO_ERROR) {
  425. error = GL_TRUE;
  426. goto gluBuild1DMipmaps_cleanup;
  427. }
  428. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  429. if (glGetError() != GL_NO_ERROR) {
  430. error = GL_TRUE;
  431. goto gluBuild1DMipmaps_cleanup;
  432. }
  433. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  434. if (glGetError() != GL_NO_ERROR) {
  435. error = GL_TRUE;
  436. goto gluBuild1DMipmaps_cleanup;
  437. }
  438. /*
  439. ** If swap_bytes was set, swapping occurred in fill_image.
  440. */
  441. glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
  442. if (glGetError() != GL_NO_ERROR) {
  443. error = GL_TRUE;
  444. goto gluBuild1DMipmaps_cleanup;
  445. }
  446. for (level = 0; level <= levels; level++) {
  447. if (newImage_width == newwidth) {
  448. /* Use newImage for this level */
  449. glTexImage1D(target, level, components, newImage_width,
  450. 0, format, GL_UNSIGNED_SHORT, (void *) newImage);
  451. } else {
  452. if (otherImage == NULL) {
  453. memreq = image_size(newwidth, 1, format, GL_UNSIGNED_SHORT);
  454. otherImage = (GLushort *) malloc(memreq);
  455. if (otherImage == NULL) {
  456. glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
  457. glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
  458. glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
  459. glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
  460. glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
  461. return GLU_OUT_OF_MEMORY;
  462. }
  463. }
  464. scale_internal(cmpts, newImage_width, 1, newImage,
  465. newwidth, 1, otherImage);
  466. /* Swap newImage and otherImage */
  467. imageTemp = otherImage;
  468. otherImage = newImage;
  469. newImage = imageTemp;
  470. newImage_width = newwidth;
  471. glTexImage1D(target, level, components, newImage_width,
  472. 0, format, GL_UNSIGNED_SHORT, (void *) newImage);
  473. }
  474. if (newwidth > 1) newwidth /= 2;
  475. }
  476. gluBuild1DMipmaps_cleanup:
  477. glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
  478. glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
  479. glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
  480. glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
  481. glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
  482. free((GLbyte *) newImage);
  483. if (otherImage) {
  484. free((GLbyte *) otherImage);
  485. }
  486. if (error == GL_TRUE)
  487. return GL_OUT_OF_MEMORY;
  488. else
  489. return 0;
  490. }
  491. GLint gluBuild2DMipmaps(GLenum target, GLint components, GLint width,
  492. GLint height, GLenum format,
  493. GLenum type, const void *data)
  494. {
  495. GLint newwidth, newheight;
  496. GLint level, levels;
  497. GLushort *newImage;
  498. GLint newImage_width;
  499. GLint newImage_height;
  500. GLushort *otherImage;
  501. GLushort *imageTemp;
  502. GLint memreq;
  503. GLint maxsize;
  504. GLint cmpts;
  505. GLboolean error = GL_FALSE;
  506. PixelStorageModes psm;
  507. if (width < 1 || height < 1) {
  508. return GLU_INVALID_VALUE;
  509. }
  510. if (!legalFormat(format) || !legalType(type)) {
  511. return GLU_INVALID_ENUM;
  512. }
  513. if (format == GL_STENCIL_INDEX) {
  514. return GLU_INVALID_ENUM;
  515. }
  516. if (format == GL_DEPTH_COMPONENT) {
  517. return GLU_INVALID_ENUM;
  518. }
  519. if (retrieveStoreModes(&psm)) {
  520. return GL_OUT_OF_MEMORY;
  521. }
  522. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
  523. if (glGetError() != GL_NO_ERROR)
  524. {
  525. return GL_OUT_OF_MEMORY;
  526. }
  527. newwidth = nearestPower(width);
  528. if (newwidth > maxsize) newwidth = maxsize;
  529. newheight = nearestPower(height);
  530. if (newheight > maxsize) newheight = maxsize;
  531. levels = computeLog(newwidth);
  532. level = computeLog(newheight);
  533. if (level > levels) levels=level;
  534. otherImage = NULL;
  535. newImage = (GLushort *)
  536. malloc(image_size(width, height, format, GL_UNSIGNED_SHORT));
  537. newImage_width = width;
  538. newImage_height = height;
  539. if (newImage == NULL) {
  540. return GLU_OUT_OF_MEMORY;
  541. }
  542. fill_image(&psm,width, height, format, type, is_index(format),
  543. data, newImage);
  544. cmpts = elements_per_group(format);
  545. glGetError();
  546. glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
  547. if (glGetError() != GL_NO_ERROR) {
  548. error = GL_TRUE;
  549. goto gluBuild2DMipmaps_cleanup;
  550. }
  551. glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  552. if (glGetError() != GL_NO_ERROR) {
  553. error = GL_TRUE;
  554. goto gluBuild2DMipmaps_cleanup;
  555. }
  556. glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  557. if (glGetError() != GL_NO_ERROR) {
  558. error = GL_TRUE;
  559. goto gluBuild2DMipmaps_cleanup;
  560. }
  561. glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  562. if (glGetError() != GL_NO_ERROR) {
  563. error = GL_TRUE;
  564. goto gluBuild2DMipmaps_cleanup;
  565. }
  566. /*
  567. ** If swap_bytes was set, swapping occurred in fill_image.
  568. */
  569. glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
  570. if (glGetError() != GL_NO_ERROR) {
  571. error = GL_TRUE;
  572. goto gluBuild2DMipmaps_cleanup;
  573. }
  574. for (level = 0; level <= levels; level++) {
  575. if (newImage_width == newwidth && newImage_height == newheight) {
  576. /* Use newImage for this level */
  577. glTexImage2D(target, level, components, newImage_width,
  578. newImage_height, 0, format, GL_UNSIGNED_SHORT,
  579. (void *) newImage);
  580. } else {
  581. if (otherImage == NULL) {
  582. memreq =
  583. image_size(newwidth, newheight, format, GL_UNSIGNED_SHORT);
  584. otherImage = (GLushort *) malloc(memreq);
  585. if (otherImage == NULL) {
  586. glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
  587. glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
  588. glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
  589. glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
  590. glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
  591. return GLU_OUT_OF_MEMORY;
  592. }
  593. }
  594. scale_internal(cmpts, newImage_width, newImage_height, newImage,
  595. newwidth, newheight, otherImage);
  596. /* Swap newImage and otherImage */
  597. imageTemp = otherImage;
  598. otherImage = newImage;
  599. newImage = imageTemp;
  600. newImage_width = newwidth;
  601. newImage_height = newheight;
  602. glTexImage2D(target, level, components, newImage_width,
  603. newImage_height, 0, format, GL_UNSIGNED_SHORT,
  604. (void *) newImage);
  605. }
  606. if (newwidth > 1) newwidth /= 2;
  607. if (newheight > 1) newheight /= 2;
  608. }
  609. gluBuild2DMipmaps_cleanup:
  610. glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
  611. glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
  612. glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
  613. glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
  614. glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
  615. free((GLbyte *) newImage);
  616. if (otherImage) {
  617. free((GLbyte *) otherImage);
  618. }
  619. if (error == GL_TRUE)
  620. return GL_OUT_OF_MEMORY;
  621. else
  622. return 0;
  623. }
  624. /*
  625. * Utility Routines
  626. */
  627. static GLint elements_per_group(GLenum format)
  628. {
  629. /*
  630. * Return the number of elements per group of a specified format
  631. */
  632. switch(format) {
  633. case GL_RGB:
  634. #ifdef GL_EXT_bgra
  635. case GL_BGR_EXT:
  636. #endif
  637. return 3;
  638. case GL_LUMINANCE_ALPHA:
  639. return 2;
  640. case GL_RGBA:
  641. #ifdef GL_EXT_bgra
  642. case GL_BGRA_EXT:
  643. #endif
  644. return 4;
  645. default:
  646. return 1;
  647. }
  648. }
  649. static GLfloat bytes_per_element(GLenum type)
  650. {
  651. /*
  652. * Return the number of bytes per element, based on the element type
  653. */
  654. switch(type) {
  655. case GL_BITMAP:
  656. return 1.0 / 8.0;
  657. case GL_UNSIGNED_SHORT:
  658. case GL_SHORT:
  659. return 2;
  660. case GL_UNSIGNED_BYTE:
  661. case GL_BYTE:
  662. return 1;
  663. case GL_INT:
  664. case GL_UNSIGNED_INT:
  665. case GL_FLOAT:
  666. default:
  667. return 4;
  668. }
  669. }
  670. #ifdef NT
  671. static GLboolean is_index(GLenum format)
  672. #else
  673. static GLint is_index(GLenum format)
  674. #endif
  675. {
  676. return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
  677. }
  678. /*
  679. ** Compute memory required for internal packed array of data of given type
  680. ** and format.
  681. */
  682. static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
  683. {
  684. int bytes_per_row;
  685. int components;
  686. assert(width > 0);
  687. assert(height > 0);
  688. components = elements_per_group(format);
  689. if (type == GL_BITMAP) {
  690. bytes_per_row = (width + 7) / 8;
  691. } else {
  692. bytes_per_row = bytes_per_element(type) * width;
  693. }
  694. return bytes_per_row * height * components;
  695. }
  696. /*
  697. ** Extract array from user's data applying all pixel store modes.
  698. ** The internal format used is an array of unsigned shorts.
  699. */
  700. static void fill_image(const PixelStorageModes *psm,
  701. GLint width, GLint height, GLenum format,
  702. GLenum type, GLboolean index_format,
  703. const void *userdata, GLushort *newimage)
  704. {
  705. GLint components;
  706. GLint element_size;
  707. GLint rowsize;
  708. GLint padding;
  709. GLint groups_per_line;
  710. GLint group_size;
  711. GLint elements_per_line;
  712. const GLubyte *start;
  713. const GLubyte *iter;
  714. GLushort *iter2;
  715. GLint i, j, k;
  716. GLint myswap_bytes;
  717. myswap_bytes = psm->unpack_swap_bytes;
  718. components = elements_per_group(format);
  719. if (psm->unpack_row_length > 0) {
  720. groups_per_line = psm->unpack_row_length;
  721. } else {
  722. groups_per_line = width;
  723. }
  724. /* All formats except GL_BITMAP fall out trivially */
  725. if (type == GL_BITMAP) {
  726. GLint bit_offset;
  727. GLint current_bit;
  728. rowsize = (groups_per_line * components + 7) / 8;
  729. padding = (rowsize % psm->unpack_alignment);
  730. if (padding) {
  731. rowsize += psm->unpack_alignment - padding;
  732. }
  733. start = (GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
  734. (psm->unpack_skip_pixels * components / 8);
  735. elements_per_line = width * components;
  736. iter2 = newimage;
  737. for (i = 0; i < height; i++) {
  738. iter = start;
  739. bit_offset = (psm->unpack_skip_pixels * components) % 8;
  740. for (j = 0; j < elements_per_line; j++) {
  741. /* Retrieve bit */
  742. if (psm->unpack_lsb_first) {
  743. current_bit = iter[0] & (1 << bit_offset);
  744. } else {
  745. current_bit = iter[0] & (1 << (7 - bit_offset));
  746. }
  747. if (current_bit) {
  748. if (index_format) {
  749. *iter2 = 1;
  750. } else {
  751. *iter2 = 65535;
  752. }
  753. } else {
  754. *iter2 = 0;
  755. }
  756. bit_offset++;
  757. if (bit_offset == 8) {
  758. bit_offset = 0;
  759. iter++;
  760. }
  761. iter2++;
  762. }
  763. start += rowsize;
  764. }
  765. } else {
  766. element_size = bytes_per_element(type);
  767. group_size = element_size * components;
  768. if (element_size == 1) myswap_bytes = 0;
  769. rowsize = groups_per_line * group_size;
  770. padding = (rowsize % psm->unpack_alignment);
  771. if (padding) {
  772. rowsize += psm->unpack_alignment - padding;
  773. }
  774. start = (GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
  775. psm->unpack_skip_pixels * group_size;
  776. elements_per_line = width * components;
  777. iter2 = newimage;
  778. for (i = 0; i < height; i++) {
  779. iter = start;
  780. for (j = 0; j < elements_per_line; j++) {
  781. Type_Widget widget;
  782. switch(type) {
  783. case GL_UNSIGNED_BYTE:
  784. if (index_format) {
  785. *iter2 = *iter;
  786. } else {
  787. *iter2 = (*iter) * 257;
  788. }
  789. break;
  790. case GL_BYTE:
  791. if (index_format) {
  792. *iter2 = *((GLbyte *) iter);
  793. } else {
  794. /* rough approx */
  795. *iter2 = (*((GLbyte *) iter)) * 516;
  796. }
  797. break;
  798. case GL_UNSIGNED_SHORT:
  799. case GL_SHORT:
  800. if (myswap_bytes) {
  801. widget.ub[0] = iter[1];
  802. widget.ub[1] = iter[0];
  803. } else {
  804. widget.ub[0] = iter[0];
  805. widget.ub[1] = iter[1];
  806. }
  807. if (type == GL_SHORT) {
  808. if (index_format) {
  809. *iter2 = widget.s[0];
  810. } else {
  811. /* rough approx */
  812. *iter2 = widget.s[0]*2;
  813. }
  814. } else {
  815. *iter2 = widget.us[0];
  816. }
  817. break;
  818. case GL_INT:
  819. case GL_UNSIGNED_INT:
  820. case GL_FLOAT:
  821. if (myswap_bytes) {
  822. widget.ub[0] = iter[3];
  823. widget.ub[1] = iter[2];
  824. widget.ub[2] = iter[1];
  825. widget.ub[3] = iter[0];
  826. } else {
  827. widget.ub[0] = iter[0];
  828. widget.ub[1] = iter[1];
  829. widget.ub[2] = iter[2];
  830. widget.ub[3] = iter[3];
  831. }
  832. if (type == GL_FLOAT) {
  833. if (index_format) {
  834. *iter2 = widget.f;
  835. } else {
  836. *iter2 = 65535 * widget.f;
  837. }
  838. } else if (type == GL_UNSIGNED_INT) {
  839. if (index_format) {
  840. *iter2 = (GLushort)widget.ui;
  841. } else {
  842. *iter2 = widget.ui >> 16;
  843. }
  844. } else {
  845. if (index_format) {
  846. *iter2 = (GLushort)widget.i;
  847. } else {
  848. *iter2 = widget.i >> 15;
  849. }
  850. }
  851. break;
  852. }
  853. iter += element_size;
  854. iter2++;
  855. }
  856. start += rowsize;
  857. }
  858. }
  859. }
  860. /*
  861. ** Insert array into user's data applying all pixel store modes.
  862. ** The internal format is an array of unsigned shorts.
  863. ** empty_image() because it is the opposite of fill_image().
  864. */
  865. static void empty_image(const PixelStorageModes *psm,
  866. GLint width, GLint height, GLenum format,
  867. GLenum type, GLboolean index_format,
  868. const GLushort *oldimage, void *userdata)
  869. {
  870. GLint components;
  871. GLint element_size;
  872. GLint rowsize;
  873. GLint padding;
  874. GLint groups_per_line;
  875. GLint group_size;
  876. GLint elements_per_line;
  877. GLubyte *start;
  878. GLubyte *iter;
  879. const GLushort *iter2;
  880. GLint i, j, k;
  881. GLint myswap_bytes;
  882. myswap_bytes = psm->pack_swap_bytes;
  883. components = elements_per_group(format);
  884. if (psm->pack_row_length > 0) {
  885. groups_per_line = psm->pack_row_length;
  886. } else {
  887. groups_per_line = width;
  888. }
  889. /* All formats except GL_BITMAP fall out trivially */
  890. if (type == GL_BITMAP) {
  891. GLint bit_offset;
  892. GLint current_bit;
  893. rowsize = (groups_per_line * components + 7) / 8;
  894. padding = (rowsize % psm->pack_alignment);
  895. if (padding) {
  896. rowsize += psm->pack_alignment - padding;
  897. }
  898. start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
  899. (psm->pack_skip_pixels * components / 8);
  900. elements_per_line = width * components;
  901. iter2 = oldimage;
  902. for (i = 0; i < height; i++) {
  903. iter = start;
  904. bit_offset = (psm->pack_skip_pixels * components) % 8;
  905. for (j = 0; j < elements_per_line; j++) {
  906. if (index_format) {
  907. current_bit = iter2[0] & 1;
  908. } else {
  909. if (iter2[0] > 32767) {
  910. current_bit = 1;
  911. } else {
  912. current_bit = 0;
  913. }
  914. }
  915. if (current_bit) {
  916. if (psm->pack_lsb_first) {
  917. *iter |= (1 << bit_offset);
  918. } else {
  919. *iter |= (1 << (7 - bit_offset));
  920. }
  921. } else {
  922. if (psm->pack_lsb_first) {
  923. *iter &= ~(1 << bit_offset);
  924. } else {
  925. *iter &= ~(1 << (7 - bit_offset));
  926. }
  927. }
  928. bit_offset++;
  929. if (bit_offset == 8) {
  930. bit_offset = 0;
  931. iter++;
  932. }
  933. iter2++;
  934. }
  935. start += rowsize;
  936. }
  937. } else {
  938. element_size = bytes_per_element(type);
  939. group_size = element_size * components;
  940. if (element_size == 1) myswap_bytes = 0;
  941. rowsize = groups_per_line * group_size;
  942. padding = (rowsize % psm->pack_alignment);
  943. if (padding) {
  944. rowsize += psm->pack_alignment - padding;
  945. }
  946. start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
  947. psm->pack_skip_pixels * group_size;
  948. elements_per_line = width * components;
  949. iter2 = oldimage;
  950. for (i = 0; i < height; i++) {
  951. iter = start;
  952. for (j = 0; j < elements_per_line; j++) {
  953. Type_Widget widget;
  954. switch(type) {
  955. case GL_UNSIGNED_BYTE:
  956. if (index_format) {
  957. *iter = (GLubyte)*iter2;
  958. } else {
  959. *iter = *iter2 >> 8;
  960. }
  961. break;
  962. case GL_BYTE:
  963. if (index_format) {
  964. *((GLbyte *) iter) = (GLbyte)*iter2;
  965. } else {
  966. *((GLbyte *) iter) = *iter2 >> 9;
  967. }
  968. break;
  969. case GL_UNSIGNED_SHORT:
  970. case GL_SHORT:
  971. if (type == GL_SHORT) {
  972. if (index_format) {
  973. widget.s[0] = *iter2;
  974. } else {
  975. widget.s[0] = *iter2 >> 1;
  976. }
  977. } else {
  978. widget.us[0] = *iter2;
  979. }
  980. if (myswap_bytes) {
  981. iter[0] = widget.ub[1];
  982. iter[1] = widget.ub[0];
  983. } else {
  984. iter[0] = widget.ub[0];
  985. iter[1] = widget.ub[1];
  986. }
  987. break;
  988. case GL_INT:
  989. case GL_UNSIGNED_INT:
  990. case GL_FLOAT:
  991. if (type == GL_FLOAT) {
  992. if (index_format) {
  993. widget.f = *iter2;
  994. } else {
  995. widget.f = *iter2 / (float) 65535.0;
  996. }
  997. } else if (type == GL_UNSIGNED_INT) {
  998. if (index_format) {
  999. widget.ui = *iter2;
  1000. } else {
  1001. widget.ui = (unsigned int) *iter2 * 65537;
  1002. }
  1003. } else {
  1004. if (index_format) {
  1005. widget.i = *iter2;
  1006. } else {
  1007. widget.i = ((unsigned int) *iter2 * 65537)/2;
  1008. }
  1009. }
  1010. if (myswap_bytes) {
  1011. iter[3] = widget.ub[0];
  1012. iter[2] = widget.ub[1];
  1013. iter[1] = widget.ub[2];
  1014. iter[0] = widget.ub[3];
  1015. } else {
  1016. iter[0] = widget.ub[0];
  1017. iter[1] = widget.ub[1];
  1018. iter[2] = widget.ub[2];
  1019. iter[3] = widget.ub[3];
  1020. }
  1021. break;
  1022. }
  1023. iter += element_size;
  1024. iter2++;
  1025. }
  1026. start += rowsize;
  1027. }
  1028. }
  1029. }