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.

285 lines
7.3 KiB

  1. /**************************************************************************
  2. * *
  3. * Copyright (C) 1989, Silicon Graphics, Inc. *
  4. * *
  5. * These coded instructions, statements, and computer programs contain *
  6. * unpublished proprietary information of Silicon Graphics, Inc., and *
  7. * are protected by Federal copyright law. They may not be disclosed *
  8. * to third parties or copied or duplicated in any form, in whole or *
  9. * in part, without the prior written consent of Silicon Graphics, Inc. *
  10. * *
  11. **************************************************************************/
  12. /* msort.c */
  13. /*
  14. Tom Davis - 1988
  15. Derrick Burns - 1989
  16. */
  17. #include <glos.h>
  18. #include <GL/gl.h>
  19. #include <GL/glu.h>
  20. #ifndef NT
  21. #include <assert.h>
  22. #include <stdlib.h>
  23. #else
  24. #include "winmem.h"
  25. #endif
  26. #include "monotone.h"
  27. #include "msort.h"
  28. /* code to do a merge sort where we assume that the initial data tends
  29. * to make long runs, either up or down.
  30. */
  31. #define INITSORT 50
  32. /*---------------------------------------------------------------------------
  33. * init_sort - initialize merge sort data structures
  34. *---------------------------------------------------------------------------
  35. */
  36. void
  37. __gl_init_sort( GLUtriangulatorObj *tobj, long n )
  38. {
  39. if( n == 0 ) return;
  40. if( tobj->minit ) {
  41. if( n > tobj->size ) {
  42. free( tobj->ptrlist );
  43. free( tobj->limits );
  44. free( tobj->dirs );
  45. tobj->size = n * 2;
  46. tobj->ptrlist = (void **)
  47. malloc((unsigned int)tobj->size*sizeof(void *) );
  48. tobj->limits = (long *)
  49. malloc((unsigned int)(tobj->size+1)*sizeof(long) );
  50. tobj->dirs = (enum updown *)
  51. malloc((unsigned int)tobj->size*sizeof(enum updown) );
  52. }
  53. } else {
  54. tobj->size = n;
  55. tobj->ptrlist = (void **)
  56. malloc((unsigned int)tobj->size*sizeof(void *) );
  57. tobj->limits = (long *)
  58. malloc((unsigned int)(tobj->size+1)*sizeof(long) );
  59. tobj->dirs = (enum updown *)
  60. malloc((unsigned int)tobj->size*sizeof(enum updown) );
  61. tobj->minit = 1;
  62. }
  63. }
  64. /*---------------------------------------------------------------------------
  65. * clear_sort - free merge sort data structures
  66. *---------------------------------------------------------------------------
  67. */
  68. void
  69. __gl_clear_sort( GLUtriangulatorObj *tobj )
  70. {
  71. if( tobj->minit ) {
  72. free( tobj->ptrlist );
  73. free( tobj->limits );
  74. free( tobj->dirs );
  75. tobj->minit = 0;
  76. }
  77. }
  78. /*---------------------------------------------------------------------------
  79. * msort - perform a merge sort on the data
  80. *---------------------------------------------------------------------------
  81. */
  82. void
  83. __gl_msort( GLUtriangulatorObj *tobj,
  84. void **curptrlist, long count, long width, SortFunc comp )
  85. {
  86. long i;
  87. long p1s, p1e, p2s, p2e, d1, d2;
  88. long q;
  89. int result;
  90. void *tmp;
  91. void **temp;
  92. void **newptrlist, **saveptrlist;
  93. void **c1s, **c1e, **c2s, **c2e, **np;
  94. /* XXX
  95. ** if comp() returns 0, then vertices are coincident. That is illegal,
  96. ** call error.
  97. */
  98. if( count <= 1) return;
  99. if( count == 2) {
  100. result = comp( &curptrlist[0], &curptrlist[1] );
  101. if( result < 0 ) {
  102. tmp = curptrlist[0];
  103. curptrlist[0] = curptrlist[1];
  104. curptrlist[1] = tmp;
  105. } else if (result == 0) {
  106. __gl_in_error( tobj, 6 );
  107. }
  108. return;
  109. }
  110. __gl_init_sort( tobj, count );
  111. saveptrlist = curptrlist;
  112. newptrlist = tobj->ptrlist;
  113. tobj->limitcount = 0;
  114. tobj->limits[0] = 0;
  115. i=0;
  116. while( 1 ) {
  117. do {
  118. i++;
  119. if( i == count ) break;
  120. result = comp(&curptrlist[i-1], &curptrlist[i]);
  121. if (result == 0) {
  122. __gl_in_error( tobj, 6 );
  123. }
  124. } while( result > 0 );
  125. tobj->dirs[tobj->limitcount] = down;
  126. tobj->limits[++tobj->limitcount] = i;
  127. if( i == count ) break;
  128. do {
  129. i++;
  130. if( i == count ) break;
  131. result = comp(&curptrlist[i-1], &curptrlist[i]);
  132. if (result == 0) {
  133. __gl_in_error( tobj, 6 );
  134. }
  135. } while( result <= 0 );
  136. tobj->dirs[tobj->limitcount] = up;
  137. tobj->limits[++tobj->limitcount] = i;
  138. if( i == count ) break;
  139. }
  140. q = tobj->newlimitcount = 0;
  141. for (i = 0; i < tobj->limitcount-1; i += 2) {
  142. if (tobj->dirs[i] == up) {
  143. p1s = tobj->limits[i];
  144. p1e = tobj->limits[i+1];
  145. d1 = 1;
  146. } else {
  147. p1s = tobj->limits[i+1]-1;
  148. p1e = tobj->limits[i]-1;
  149. d1 = -1;
  150. }
  151. if (tobj->dirs[i+1] == up) {
  152. p2s = tobj->limits[i+1];
  153. p2e = tobj->limits[i+2];
  154. d2 = 1;
  155. } else {
  156. p2s = tobj->limits[i+2]-1;
  157. p2e = tobj->limits[i+1]-1;
  158. d2 = -1;
  159. }
  160. while ((p1s != p1e) && (p2s != p2e)) {
  161. result = comp(&curptrlist[p1s], &curptrlist[p2s]);
  162. if (result == 0) {
  163. __gl_in_error( tobj, 6 );
  164. }
  165. if (result > 0) {
  166. newptrlist[q++] = curptrlist[p2s];
  167. p2s += d2;
  168. if (p2s == p2e) do {
  169. newptrlist[q++] = curptrlist[p1s];
  170. p1s += d1;
  171. } while (p1s != p1e);
  172. } else {
  173. newptrlist[q++] = curptrlist[p1s];
  174. p1s += d1;
  175. if (p1s == p1e) do {
  176. newptrlist[q++] = curptrlist[p2s];
  177. p2s += d2;
  178. } while (p2s != p2e);
  179. }
  180. }
  181. tobj->limits[++tobj->newlimitcount] = q;
  182. }
  183. if (tobj->limitcount & 1) {
  184. if (tobj->dirs[tobj->limitcount-1] == up) {
  185. p1s = tobj->limits[tobj->limitcount-1];
  186. p1e = tobj->limits[tobj->limitcount];
  187. d1 = 1;
  188. } else {
  189. p1s = tobj->limits[tobj->limitcount] - 1;
  190. p1e = tobj->limits[tobj->limitcount-1] - 1;
  191. d1 = -1;
  192. }
  193. do {
  194. newptrlist[q++] = curptrlist[p1s];
  195. p1s += d1;
  196. } while (p1s != p1e);
  197. tobj->limits[++tobj->newlimitcount] = q;
  198. }
  199. tobj->limitcount = tobj->newlimitcount;
  200. // The x86 compiler does not deal with this swap properly (though it does
  201. // it fine in the while loop below). Luckily, at this point saveptrlist
  202. // has the data we want, so do the assignment to newptrlist using it instead.
  203. //
  204. // Meanwhile, lets keep the old code around so we can verify the compiler
  205. // fix when it rolls out.
  206. //!!!XXX -- compiler bug
  207. #ifdef COMPILER_FIXED
  208. temp = curptrlist;
  209. curptrlist = newptrlist;
  210. newptrlist = temp;
  211. #else
  212. curptrlist = newptrlist;
  213. newptrlist = saveptrlist;
  214. #endif
  215. while (tobj->limitcount > 1) {
  216. np = newptrlist;
  217. q = tobj->newlimitcount = 0;
  218. for (i = 0; i < tobj->limitcount-1; i += 2) {
  219. c1s = curptrlist + tobj->limits[i];
  220. c1e = curptrlist + tobj->limits[i+1];
  221. c2s = curptrlist + tobj->limits[i+1];
  222. c2e = curptrlist + tobj->limits[i+2];
  223. while ((c1s != c1e) && (c2s != c2e)) {
  224. result = comp(c1s, c2s);
  225. if (result == 0) {
  226. __gl_in_error( tobj, 6 );
  227. }
  228. if (result > 0) {
  229. *np++ = *c2s++;
  230. if (c2s == c2e) do {
  231. *np++ = *c1s++;
  232. } while (c1s != c1e);
  233. } else {
  234. *np++ = *c1s++;
  235. if (c1s == c1e) do {
  236. *np++ = *c2s++;
  237. } while (c2s != c2e);
  238. }
  239. }
  240. tobj->limits[++tobj->newlimitcount] = np - newptrlist;
  241. }
  242. if( tobj->limitcount & 1 ) {
  243. p1s = tobj->limits[tobj->limitcount-1];
  244. p1e = tobj->limits[tobj->limitcount];
  245. do {
  246. *np++ = curptrlist[p1s++];
  247. } while (p1s != p1e);
  248. tobj->limits[++tobj->newlimitcount] = np - newptrlist;
  249. }
  250. tobj->limitcount = tobj->newlimitcount;
  251. temp = curptrlist;
  252. curptrlist = newptrlist;
  253. newptrlist = temp;
  254. }
  255. if (curptrlist != saveptrlist)
  256. for (i = 0; i < count; i++)
  257. saveptrlist[i] = curptrlist[i];
  258. }