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.

264 lines
7.4 KiB

  1. /*
  2. ** Copyright 1991, 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: 1993/07/27 17:42:12 $
  19. */
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. /*
  23. ** A simple few routines which saves a cache for specular and spotlight
  24. ** computation (rather than recomputing the tables every time the user
  25. ** changes the specular or spotlight exponents).
  26. */
  27. /*
  28. ** Any more than TOO_MANY_LUT_ENTRIES entries, and we free any that
  29. ** become unreferenced.
  30. */
  31. #define TOO_MANY_LUT_ENTRIES 32
  32. typedef struct {
  33. __GLfloat exp;
  34. __GLspecLUTEntry *table;
  35. } __GLspecLUTEntryPtr;
  36. typedef struct __GLspecLUTCache_Rec {
  37. GLint nentries;
  38. GLint allocatedSize;
  39. __GLspecLUTEntryPtr entries[1];
  40. } __GLspecLUTCache;
  41. void FASTCALL __glInitLUTCache(__GLcontext *gc)
  42. {
  43. __GLspecLUTCache *lutCache;
  44. lutCache = gc->light.lutCache = (__GLspecLUTCache *)
  45. GCALLOC(gc, sizeof(__GLspecLUTCache));
  46. #ifdef NT
  47. if (!lutCache)
  48. return;
  49. #endif // NT
  50. lutCache->nentries = 0;
  51. lutCache->allocatedSize = 1;
  52. }
  53. void FASTCALL __glFreeLUTCache(__GLcontext *gc)
  54. {
  55. int i;
  56. GLint nentries;
  57. __GLspecLUTEntryPtr *entry;
  58. __GLspecLUTCache *lutCache;
  59. lutCache = gc->light.lutCache;
  60. #ifdef NT
  61. if (!lutCache)
  62. return;
  63. #endif // NT
  64. nentries = lutCache->nentries;
  65. for (i = 0; i < nentries; i++) {
  66. entry = &(lutCache->entries[i]);
  67. GCFREE(gc, entry->table);
  68. }
  69. GCFREE(gc, lutCache);
  70. }
  71. static __GLspecLUTEntry *findEntry(__GLspecLUTCache *lutCache, __GLfloat exp,
  72. GLint *location)
  73. {
  74. GLint nentries;
  75. GLint bottom, half, top;
  76. __GLspecLUTEntry *table;
  77. __GLspecLUTEntryPtr *entry;
  78. #ifdef NT
  79. ASSERTOPENGL(lutCache != NULL, "No LUT cache\n");
  80. #endif // NT
  81. nentries = lutCache->nentries;
  82. /* First attempt to find this entry in our cache */
  83. bottom = 0;
  84. top = nentries;
  85. while (top > bottom) {
  86. /* Entry might exist in the range [bottom, top-1] */
  87. half = (bottom+top)/2;
  88. entry = &(lutCache->entries[half]);
  89. if (entry->exp == exp) {
  90. /* Found the table already cached! */
  91. table = entry->table;
  92. *location = half;
  93. return table;
  94. }
  95. if (exp < entry->exp) {
  96. /* exp might exist somewhere earlier in the table */
  97. top = half;
  98. } else /* exp > entry->exp */ {
  99. /* exp might exist somewhere later in the table */
  100. bottom = half+1;
  101. }
  102. }
  103. *location = bottom;
  104. return NULL;
  105. }
  106. __GLspecLUTEntry *__glCreateSpecLUT(__GLcontext *gc, __GLfloat exp)
  107. {
  108. GLint nentries, allocatedSize;
  109. GLint location;
  110. __GLspecLUTCache *lutCache;
  111. __GLspecLUTEntryPtr *entry;
  112. __GLspecLUTEntry *table;
  113. __GLfloat *tableEntry;
  114. GLdouble threshold, scale, x, dx;
  115. GLint i;
  116. /* This code uses double-precision math, so make sure that the FPU */
  117. /* is set properly: */
  118. FPU_SAVE_MODE();
  119. FPU_CHOP_OFF_PREC_HI();
  120. lutCache = gc->light.lutCache;
  121. #ifdef NT
  122. if (!lutCache)
  123. return (__GLspecLUTEntry *)NULL;
  124. #endif // NT
  125. if (table = findEntry(lutCache, exp, &location)) {
  126. table->refcount++;
  127. return table;
  128. }
  129. /*
  130. ** We failed to find our entry in our cache anywhere, and have to compute
  131. ** it.
  132. */
  133. lutCache->nentries = nentries = 1 + lutCache->nentries;
  134. allocatedSize = lutCache->allocatedSize;
  135. if (nentries > allocatedSize) {
  136. /* Allocate space for another six entries (arbitrarily) */
  137. lutCache->allocatedSize = allocatedSize = allocatedSize + 6;
  138. if (!(lutCache = (__GLspecLUTCache *)
  139. GCREALLOC(gc, lutCache, sizeof(__GLspecLUTCache) +
  140. allocatedSize * sizeof(__GLspecLUTEntryPtr))))
  141. {
  142. gc->light.lutCache->allocatedSize -= 6;
  143. gc->light.lutCache->nentries -= 1;
  144. return (__GLspecLUTEntry *)NULL;
  145. }
  146. gc->light.lutCache = lutCache;
  147. }
  148. /*
  149. ** We have enough space now. So we stick the new entry in the array
  150. ** at entry 'location'. The rest of the entries need to be moved up
  151. ** (move [location, nentries-2] up to [location+1, nentries-1]).
  152. */
  153. if (nentries-location-1) {
  154. #ifdef NT
  155. __GL_MEMMOVE(&(lutCache->entries[location+1]),
  156. &(lutCache->entries[location]),
  157. (nentries-location-1) * sizeof(__GLspecLUTEntryPtr));
  158. #else
  159. __GL_MEMCOPY(&(lutCache->entries[location+1]),
  160. &(lutCache->entries[location]),
  161. (nentries-location-1) * sizeof(__GLspecLUTEntryPtr));
  162. #endif
  163. }
  164. entry = &(lutCache->entries[location]);
  165. entry->exp = exp;
  166. table = entry->table = (__GLspecLUTEntry *)
  167. GCALLOC(gc, sizeof(__GLspecLUTEntry));
  168. #ifdef NT
  169. if (!table)
  170. return (__GLspecLUTEntry *)NULL;
  171. #endif // NT
  172. /* Compute threshold */
  173. if (exp == (__GLfloat) 0.0) {
  174. threshold = (GLdouble) 0.0;
  175. } else {
  176. #ifdef NT
  177. // Changing this enabled conformance to pass for color index visuals
  178. // with 4096 colors, and did not seem to affect anything else.
  179. // What this does is sort of reduce the granularity at the beginning
  180. // of the table, because without it we were getting too big a jump
  181. // between 0 and the first entry in the table, causing l_sen.c to fail.
  182. threshold = (GLdouble) __GL_POWF((__GLfloat) 0.0005, (__GLfloat) 1.0 / exp);
  183. #else
  184. threshold = __GL_POWF(0.002, 1.0 / exp);
  185. #endif
  186. }
  187. scale = (GLdouble) (__GL_SPEC_LOOKUP_TABLE_SIZE - 1) / ((GLdouble) 1.0 - threshold);
  188. dx = (GLdouble) 1.0 / scale;
  189. x = threshold;
  190. tableEntry = table->table;
  191. for (i = __GL_SPEC_LOOKUP_TABLE_SIZE; --i >= 0; ) {
  192. *tableEntry++ = __GL_POWF(x, exp);
  193. x += dx;
  194. }
  195. table->threshold = threshold;
  196. table->scale = scale;
  197. table->refcount = 1;
  198. table->exp = exp;
  199. FPU_RESTORE_MODE();
  200. return table;
  201. }
  202. void FASTCALL __glFreeSpecLUT(__GLcontext *gc, __GLspecLUTEntry *lut)
  203. {
  204. __GLspecLUTCache *lutCache;
  205. GLint location, nentries;
  206. __GLspecLUTEntry *table;
  207. if (lut == NULL) return;
  208. ASSERTOPENGL(lut->refcount != 0, "Invalid refcount\n");
  209. lut->refcount--;
  210. if (lut->refcount > 0) return;
  211. lutCache = gc->light.lutCache;
  212. #ifdef NT
  213. ASSERTOPENGL(lutCache != NULL, "No LUT cache\n");
  214. #endif // NT
  215. table = findEntry(lutCache, lut->exp, &location);
  216. ASSERTOPENGL(table == lut, "Wrong LUT found\n");
  217. if (table->refcount == 0 && lutCache->nentries >= TOO_MANY_LUT_ENTRIES) {
  218. /*
  219. ** Free entry 'location'.
  220. ** This requires reducing lutCache->nentries by one, and copying
  221. ** entries [location+1, nentries] to [location, nentries-1].
  222. */
  223. lutCache->nentries = nentries = lutCache->nentries - 1;
  224. #ifdef NT
  225. __GL_MEMMOVE(&(lutCache->entries[location]),
  226. &(lutCache->entries[location+1]),
  227. (nentries-location) * sizeof(__GLspecLUTEntryPtr));
  228. #else
  229. __GL_MEMCOPY(&(lutCache->entries[location]),
  230. &(lutCache->entries[location+1]),
  231. (nentries-location) * sizeof(__GLspecLUTEntryPtr));
  232. #endif
  233. GCFREE(gc, table);
  234. }
  235. }