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.

2013 lines
62 KiB

  1. /*
  2. ** Copyright 1991, 1922, 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. ** Display list table management routines.
  18. **
  19. ** $Revision: 1.3 $
  20. ** $Date: 1995/02/11 00:53:45 $
  21. */
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. #include <namesint.h>
  25. #include "..\..\dlist\dlistint.h"
  26. /************************************************************************/
  27. /*
  28. ** The Name Space Management code is used to store and retreive named
  29. ** data structures. The data being stored is referred to with void
  30. ** pointers to allow for the storage of any type of structure.
  31. **
  32. ** Note that this code was developed for dlist name management.
  33. ** The bulk of it remains the same, but the semaphores for locking
  34. ** dlist access have been moved up one level. The code that uses
  35. ** this module for name space management must enclose the calls
  36. ** to Names entry points with LOCK and UNLOCK statements.
  37. */
  38. /************************************************************************/
  39. /*----------------------------------------------------------------------*/
  40. /*
  41. ** Internal data structures. Not intended for consumption outside of
  42. ** this module.
  43. */
  44. /*----------------------------------------------------------------------*/
  45. /*
  46. ** The name space is implemented as a 2-3 tree.
  47. ** The depth of the tree is the same for
  48. ** the entire tree (so we always know once we reach that depth that the
  49. ** node found is a leaf).
  50. **
  51. ** A 2-3 tree in a nutshell goes like this:
  52. **
  53. ** Every node at the maximum depth is a leaf, all other nodes are branch
  54. ** nodes and have 2 or 3 children.
  55. **
  56. ** A new node can be inserted in O(depth) time and an old node can be deleted
  57. ** in O(depth) time. During this insertion or deletion, the tree is
  58. ** automatically rebalanced.
  59. **
  60. **
  61. ** Hmmm. Derrick Burns mentions splay trees. They would probably work
  62. ** as well if not better, and might be easier to code. Maybe later -- little
  63. ** point in re-writing working code.
  64. **
  65. ** Leaf nodes are arrays of sequential display lists. The typical tree will
  66. ** actually only be one node (since users will define a few sequential
  67. ** lists, all of which fit into one leaf node).
  68. **
  69. ** The range of display lists stored in a leaf is indicated by "start" and
  70. ** "end" (inclusive).
  71. **
  72. ** There are two varieties of leaves. There are leaves which contain unused
  73. ** (but reserved) display lists. They are unique in that "lists" will be
  74. ** NULL. The other type of leaf contains display lists currently in use.
  75. ** "lists" will not be NULL for these leaves, and will point to an array
  76. ** containing the actual display lists.
  77. **
  78. ** Leaves containing unused (but reserved) display lists are generated when
  79. ** the user calls glGenLists().
  80. **
  81. ** As the user starts using these reserved lists, the leaf containing unused
  82. ** (reserved) lists is split into two (or sometimes three) leaves. One of
  83. ** the leaves will contain the display list the user is currently using, and
  84. ** the other will contain the rest of the still unused display lists.
  85. **
  86. ** When this split takes place, the new leaf (containing the "now used" display
  87. ** lists) will be sized to __GL_DLIST_MIN_ARRAY_BLOCK entries if possible
  88. ** (with one of the array entries being the new display list, and the other
  89. ** entries pointing to a NOP dummy display list). As the user continues
  90. ** to define more and more display lists, the leaf containing a range
  91. ** of used display lists will continue to grow until it reaches a
  92. ** size of __GL_DLIST_MAX_ARRAY_BLOCK entries, at which point a new
  93. ** leaf will be created to hold additional lists.
  94. */
  95. /*
  96. ** A leaf node.
  97. ** The data pointers are void so diffent types of data structures can
  98. ** be managed. The dataInfo pointer points back to information needed
  99. ** to manage the specific data structure pointed to by a void pointer.
  100. */
  101. struct __GLnamesLeafRec {
  102. __GLnamesBranch *parent; /* parent node - must be first */
  103. GLuint start; /* start of range */
  104. GLuint end; /* end of range */
  105. void **dataList; /* array of ptrs to named data */
  106. __GLnamesArrayTypeInfo *dataInfo; /* ptr to data type info */
  107. };
  108. /*
  109. ** A branch node.
  110. ** The section of the tree in children[0] has name values all <= low.
  111. ** The section in children[1] has values: low < value <= medium.
  112. ** The section in children[2] (if not NULL) has values > medium.
  113. */
  114. struct __GLnamesBranchRec {
  115. __GLnamesBranch *parent; /* parent node - must be first */
  116. GLuint low; /* children[0] all <= low */
  117. GLuint medium; /* children[1] all <= medium & > low */
  118. __GLnamesBranch *children[3]; /* children[2] all > medium */
  119. };
  120. /*----------------------------------------------------------------------*/
  121. /*
  122. ** Name Space Manager internal routines.
  123. */
  124. /*----------------------------------------------------------------------*/
  125. /*
  126. ** Sets up a new names tree and returns a pointer to it.
  127. */
  128. __GLnamesArray * FASTCALL __glNamesNewArray(__GLcontext *gc, __GLnamesArrayTypeInfo *dataInfo)
  129. {
  130. __GLnamesArray *array;
  131. int i;
  132. array = (__GLnamesArray *) GCALLOC(gc, sizeof(__GLnamesArray));
  133. if (array == NULL) {
  134. __glSetError(GL_OUT_OF_MEMORY);
  135. return NULL;
  136. }
  137. #ifdef NT
  138. __try
  139. {
  140. InitializeCriticalSection(&array->critsec);
  141. }
  142. __except(EXCEPTION_EXECUTE_HANDLER)
  143. {
  144. GCFREE(gc, array);
  145. __glSetError(GL_OUT_OF_MEMORY);
  146. return NULL;
  147. }
  148. #endif
  149. array->refcount = 1;
  150. array->tree = NULL;
  151. array->depth = 0;
  152. array->dataInfo = dataInfo;
  153. /*
  154. ** Pre-allocate a few leaves and branches for paranoid OUT_OF_MEMORY
  155. ** reasons.
  156. */
  157. array->nbranches = __GL_DL_EXTRA_BRANCHES;
  158. array->nleaves = __GL_DL_EXTRA_LEAVES;
  159. for (i = 0; i < __GL_DL_EXTRA_BRANCHES; i++) {
  160. array->branches[i] = (__GLnamesBranch*)
  161. GCALLOC(gc, sizeof(__GLnamesBranch));
  162. if (array->branches[i] == NULL) {
  163. array->nbranches = i;
  164. break;
  165. }
  166. }
  167. for (i = 0; i < __GL_DL_EXTRA_LEAVES; i++) {
  168. array->leaves[i] = (__GLnamesLeaf*)
  169. GCALLOC(gc, sizeof(__GLnamesLeaf));
  170. if (array->leaves[i] == NULL) {
  171. array->nleaves = i;
  172. break;
  173. }
  174. }
  175. return array;
  176. }
  177. static void FASTCALL freeLeafData(__GLcontext *gc, void **dataList)
  178. {
  179. /*
  180. ** Note that the actual data pointed to by the elements of this list
  181. ** have already been freed with the callback.
  182. */
  183. GCFREE(gc, dataList);
  184. }
  185. static void FASTCALL freeLeaf(__GLcontext *gc, __GLnamesLeaf *leaf)
  186. {
  187. if (leaf->dataList) {
  188. freeLeafData(gc, leaf->dataList);
  189. }
  190. GCFREE(gc, leaf);
  191. }
  192. static void FASTCALL freeBranch(__GLcontext *gc, __GLnamesBranch *branch)
  193. {
  194. GCFREE(gc, branch);
  195. }
  196. /*
  197. ** Free an entire names tree.
  198. */
  199. void FASTCALL __glNamesFreeTree(__GLcontext *gc, __GLnamesArray *array,
  200. __GLnamesBranch *tree, GLint depth)
  201. {
  202. GLuint i;
  203. __GLnamesLeaf *leaf;
  204. void *empty;
  205. GLint maxdepth = array->depth;
  206. __GL_NAMES_ASSERT_LOCKED(array);
  207. if (tree == NULL) return;
  208. if (depth < maxdepth) {
  209. __glNamesFreeTree(gc, array, tree->children[2], depth+1);
  210. __glNamesFreeTree(gc, array, tree->children[1], depth+1);
  211. __glNamesFreeTree(gc, array, tree->children[0], depth+1);
  212. freeBranch(gc, tree);
  213. } else {
  214. leaf = (__GLnamesLeaf *) tree;
  215. empty = array->dataInfo->empty;
  216. if (leaf->dataList) {
  217. for (i=leaf->start; i<=leaf->end; i++) {
  218. if (leaf->dataList[i - leaf->start] != empty) {
  219. ASSERTOPENGL(leaf->dataInfo->free != NULL,
  220. "No free function\n");
  221. (*leaf->dataInfo->free)(gc,
  222. leaf->dataList[i - leaf->start]);
  223. leaf->dataList[i - leaf->start] = empty;
  224. }
  225. }
  226. }
  227. freeLeaf(gc, leaf);
  228. }
  229. }
  230. void FASTCALL __glNamesFreeArray(__GLcontext *gc, __GLnamesArray *array)
  231. {
  232. GLuint i;
  233. __GL_NAMES_ASSERT_LOCKED(array);
  234. for (i = 0; i < array->nbranches; i++) {
  235. GCFREE(gc, array->branches[i]);
  236. }
  237. for (i = 0; i < array->nleaves; i++) {
  238. GCFREE(gc, array->leaves[i]);
  239. }
  240. __glNamesFreeTree(gc, array, array->tree, 0);
  241. __GL_NAMES_UNLOCK(array);
  242. #ifdef NT
  243. DeleteCriticalSection(&array->critsec);
  244. #endif
  245. GCFREE(gc, array);
  246. }
  247. /*
  248. ** Find the leaf with the given name.
  249. ** If exact is TRUE, then only the leaf that contains this name will
  250. ** be returned (NULL, otherwise).
  251. ** If exact is FALSE, than the leaf containing the number will be returned
  252. ** if it exists, and otherwise the next highest leaf will be returned.
  253. ** A NULL value indicates that number is higher than any other leaves in
  254. ** the tree.
  255. ** This routine has been tuned for the case of finding the number in
  256. ** the tree, since this is the most likely case when dispatching a
  257. ** display list.
  258. */
  259. static __GLnamesLeaf * FASTCALL findLeaf(__GLnamesArray *array, GLuint number,
  260. GLint exact)
  261. {
  262. __GLnamesBranch *branch;
  263. __GLnamesLeaf *leaf;
  264. int depth = array->depth, r;
  265. __GL_NAMES_ASSERT_LOCKED(array);
  266. branch = array->tree;
  267. while (depth > 0 && branch) {
  268. /* rather than following if-then-else code
  269. * for correct branch, evaluate all conditions
  270. * quickly to compute correct branch.
  271. */
  272. int r = (number > branch->low) + (number > branch->medium);
  273. ASSERTOPENGL(branch->low <= branch->medium,
  274. "Branch ordering wrong\n");
  275. branch = branch->children[r];
  276. --depth;
  277. }
  278. if (!(leaf = (__GLnamesLeaf *) branch)) return NULL;
  279. /* the case we want to optimize is the one in which we
  280. * actually find the node, so evaluate both conditions
  281. * quickly, since both results are required in this case
  282. * and return appropriately. the choice of the final
  283. * if construct is to match the current vagaries of the
  284. * 3.19 compiler code generator (db)
  285. */
  286. r = (leaf->end < number) | (exact&(number<leaf->start));
  287. if (!r) return leaf;
  288. return NULL;
  289. }
  290. /*
  291. ** Copy data from leaf->lists into newleaf->lists.
  292. */
  293. static void FASTCALL copyLeafInfo(__GLnamesLeaf *leaf, __GLnamesLeaf *newleaf)
  294. {
  295. GLint offset;
  296. GLuint number;
  297. GLuint i;
  298. number = newleaf->end - newleaf->start + 1;
  299. offset = newleaf->start - leaf->start;
  300. for (i = 0; i < number; i++) {
  301. newleaf->dataList[i] = leaf->dataList[i+offset];
  302. }
  303. }
  304. /*
  305. ** Attempt to fix a possible situation caused by lack of memory.
  306. */
  307. static GLboolean FASTCALL fixMemoryProblem(__GLcontext *gc, __GLnamesArray *array)
  308. {
  309. GLuint i;
  310. __GL_NAMES_ASSERT_LOCKED(array);
  311. for (i = array->nbranches; i < __GL_DL_EXTRA_BRANCHES; i++) {
  312. array->branches[i] = (__GLnamesBranch*)
  313. GCALLOC(gc, sizeof(__GLnamesBranch));
  314. if (array->branches[i] == NULL) {
  315. array->nbranches = i;
  316. return GL_FALSE;
  317. }
  318. }
  319. array->nbranches = __GL_DL_EXTRA_BRANCHES;
  320. for (i = array->nleaves; i < __GL_DL_EXTRA_LEAVES; i++) {
  321. array->leaves[i] = (__GLnamesLeaf*) GCALLOC(gc, sizeof(__GLnamesLeaf));
  322. if (array->leaves[i] == NULL) {
  323. array->nleaves = i;
  324. return GL_FALSE;
  325. }
  326. }
  327. array->nleaves = __GL_DL_EXTRA_LEAVES;
  328. return GL_TRUE;
  329. }
  330. /*
  331. ** Compute the maximum value contained in the given tree. If
  332. ** curdepth == maxdepth, the tree is simply a leaf.
  333. */
  334. static GLuint FASTCALL computeMax(__GLnamesBranch *branch, GLint curdepth,
  335. GLint maxdepth)
  336. {
  337. __GLnamesLeaf *leaf;
  338. while (curdepth < maxdepth) {
  339. if (branch->children[2] != NULL) {
  340. branch = branch->children[2];
  341. } else if (branch->children[1] != NULL) {
  342. return branch->medium;
  343. } else {
  344. return branch->low;
  345. }
  346. curdepth++;
  347. }
  348. leaf = (__GLnamesLeaf *) branch;
  349. return leaf->end;
  350. }
  351. /*
  352. ** Make sure that all parents of this child know that maxval is the
  353. ** highest value that can be found in this child.
  354. */
  355. static void FASTCALL pushMaxVal(__GLnamesBranch *child, GLuint maxval)
  356. {
  357. __GLnamesBranch *parent;
  358. while (parent = child->parent) {
  359. if (parent->children[0] == child) {
  360. parent->low = maxval;
  361. if (parent->children[1] != NULL) {
  362. return;
  363. }
  364. } else if (parent->children[1] == child) {
  365. parent->medium = maxval;
  366. if (parent->children[2] != NULL) {
  367. return;
  368. }
  369. } else {
  370. ASSERTOPENGL(parent->children[2] == child,
  371. "Parent/child relationship incorrect\n");
  372. }
  373. child = parent;
  374. }
  375. }
  376. static GLboolean FASTCALL allocLeafData(__GLcontext *gc, __GLnamesLeaf *leaf)
  377. {
  378. GLint number;
  379. GLint i;
  380. number = leaf->end - leaf->start + 1;
  381. leaf->dataList = (void **) GCALLOC(gc, (size_t)(sizeof(void *)*number));
  382. if (!leaf->dataList) return GL_FALSE;
  383. for (i=0; i < number; i++) {
  384. leaf->dataList[i] = leaf->dataInfo->empty;
  385. }
  386. return GL_TRUE;
  387. }
  388. static GLboolean FASTCALL reallocLeafData(__GLcontext *gc, __GLnamesLeaf *leaf)
  389. {
  390. size_t number;
  391. void **answer;
  392. number = (size_t) (leaf->end - leaf->start + 1);
  393. answer = (void **) GCREALLOC(gc, leaf->dataList, sizeof(void *)*number);
  394. if (answer) {
  395. leaf->dataList = answer;
  396. return GL_TRUE;
  397. } else {
  398. /*
  399. ** Crud! Out of memory!
  400. */
  401. return GL_FALSE;
  402. }
  403. }
  404. static __GLnamesLeaf * FASTCALL allocLeaf(__GLcontext *gc, __GLnamesArray *array)
  405. {
  406. __GLnamesLeaf *leaf;
  407. leaf = (__GLnamesLeaf *) GCALLOC(gc, sizeof(__GLnamesLeaf));
  408. if (leaf == NULL) {
  409. /*
  410. ** Ouch! No memory? We had better use one of the preallocated
  411. ** leaves.
  412. */
  413. __GL_NAMES_ASSERT_LOCKED(array);
  414. ASSERTOPENGL(array->nleaves != 0,
  415. "No preallocated leaves\n");
  416. array->nleaves--;
  417. leaf = array->leaves[array->nleaves];
  418. }
  419. leaf->parent = NULL;
  420. leaf->dataList = NULL;
  421. leaf->dataInfo = array->dataInfo;
  422. return leaf;
  423. }
  424. /*
  425. ** Allocates a branch node.
  426. */
  427. static __GLnamesBranch * FASTCALL allocBranch(__GLcontext *gc, __GLnamesArray *array)
  428. {
  429. __GLnamesBranch *branch;
  430. branch = (__GLnamesBranch *) GCALLOC(gc, sizeof(__GLnamesBranch));
  431. if (branch == NULL) {
  432. /*
  433. ** Ouch! No memory? We had better use one of the preallocated
  434. ** branches.
  435. */
  436. __GL_NAMES_ASSERT_LOCKED(array);
  437. ASSERTOPENGL(array->nbranches != 0,
  438. "No preallocated branches\n");
  439. array->nbranches--;
  440. branch = array->branches[array->nbranches];
  441. }
  442. branch->children[0] = branch->children[1] = branch->children[2] = NULL;
  443. branch->parent = NULL;
  444. return branch;
  445. }
  446. /*
  447. ** Remove the child from the parent. depth refers to the parent.
  448. ** This deletion may delete a child from a parent with only two children.
  449. ** If so, the parent itself will soon be deleted, of course.
  450. */
  451. static void FASTCALL deleteChild(__GLnamesArray *array, __GLnamesBranch *parent,
  452. __GLnamesBranch *child, GLint depth)
  453. {
  454. GLuint maxval;
  455. GLint maxdepth;
  456. __GL_NAMES_ASSERT_LOCKED(array);
  457. maxdepth = array->depth;
  458. if (parent->children[0] == child) {
  459. parent->children[0] = parent->children[1];
  460. parent->children[1] = parent->children[2];
  461. parent->children[2] = NULL;
  462. parent->low = parent->medium;
  463. if (parent->children[1] != NULL) {
  464. maxval = computeMax(parent->children[1], depth+1, maxdepth);
  465. parent->medium = maxval;
  466. } else parent->medium = 0;
  467. } else if (parent->children[1] == child) {
  468. parent->children[1] = parent->children[2];
  469. parent->children[2] = NULL;
  470. if (parent->children[1] != NULL) {
  471. maxval = computeMax(parent->children[1], depth+1, maxdepth);
  472. parent->medium = maxval;
  473. } else parent->medium = 0;
  474. } else {
  475. ASSERTOPENGL(parent->children[2] == child,
  476. "Parent/child relationship wrong\n");
  477. parent->children[2] = NULL;
  478. pushMaxVal(parent, parent->medium);
  479. }
  480. }
  481. /*
  482. ** Add child to parent. child is a leaf if curdepth == maxdepth - 1
  483. ** (curdepth refers to the depth of the parent, not the child). Parent
  484. ** only has one or two children (thus has room for another child).
  485. */
  486. static void FASTCALL addChild(__GLnamesBranch *parent, __GLnamesBranch *child,
  487. GLint curdepth, GLint maxdepth)
  488. {
  489. GLuint maxval;
  490. maxval = computeMax(child, curdepth+1, maxdepth);
  491. child->parent = parent;
  492. if (maxval > parent->medium && parent->children[1] != NULL) {
  493. /* This becomes the third child */
  494. parent->children[2] = child;
  495. /* Propagate the maximum value for this child to its parents */
  496. pushMaxVal(parent, maxval);
  497. } else if (maxval > parent->low) {
  498. /* This becomes the second child */
  499. parent->children[2] = parent->children[1];
  500. parent->children[1] = child;
  501. parent->medium = maxval;
  502. if (parent->children[2] == NULL) {
  503. pushMaxVal(parent, maxval);
  504. }
  505. } else {
  506. parent->children[2] = parent->children[1];
  507. parent->children[1] = parent->children[0];
  508. parent->children[0] = child;
  509. parent->medium = parent->low;
  510. parent->low = maxval;
  511. }
  512. }
  513. /*
  514. ** From the three children in parent, and the extraChild, build two parents:
  515. ** parent and newParent. curdepth refers to the depth of parent. parent
  516. ** is part of the tree, so its maxval needs to be propagated up if it
  517. ** changes.
  518. */
  519. static void FASTCALL splitParent(__GLnamesBranch *parent,
  520. __GLnamesBranch *newParent,
  521. __GLnamesBranch *extraChild,
  522. GLint curdepth,
  523. GLint maxdepth)
  524. {
  525. __GLnamesBranch *children[4], *tempchild;
  526. GLuint maxvals[4], tempval;
  527. int i;
  528. /* Collect our four children */
  529. children[0] = parent->children[0];
  530. maxvals[0] = parent->low;
  531. children[1] = parent->children[1];
  532. maxvals[1] = parent->medium;
  533. children[2] = parent->children[2];
  534. maxvals[2] = computeMax(children[2], curdepth+1, maxdepth);
  535. children[3] = extraChild;
  536. maxvals[3] = computeMax(extraChild, curdepth+1, maxdepth);
  537. /* Children 0-2 are sorted. Sort child 3 too. */
  538. for (i = 3; i > 0; i--) {
  539. if (maxvals[i] < maxvals[i-1]) {
  540. tempval = maxvals[i];
  541. tempchild = children[i];
  542. maxvals[i] = maxvals[i-1];
  543. children[i] = children[i-1];
  544. maxvals[i-1] = tempval;
  545. children[i-1] = tempchild;
  546. }
  547. }
  548. /* Construct the two parents */
  549. parent->low = maxvals[0];
  550. parent->children[0] = children[0];
  551. parent->medium = maxvals[1];
  552. parent->children[1] = children[1];
  553. parent->children[2] = NULL;
  554. children[0]->parent = parent;
  555. children[1]->parent = parent;
  556. pushMaxVal(parent, maxvals[1]);
  557. newParent->low = maxvals[2];
  558. newParent->children[0] = children[2];
  559. newParent->medium = maxvals[3];
  560. newParent->children[1] = children[3];
  561. newParent->children[2] = NULL;
  562. children[2]->parent = newParent;
  563. children[3]->parent = newParent;
  564. }
  565. /*
  566. ** Build a parent from child1 and child2. depth tells the depth of
  567. ** the trees pointed to by child1 and child2.
  568. */
  569. static void FASTCALL buildParent(__GLnamesBranch *parent, __GLnamesBranch *child1,
  570. __GLnamesBranch *child2, GLint depth)
  571. {
  572. GLuint maxChild1, maxChild2;
  573. child1->parent = parent;
  574. child2->parent = parent;
  575. maxChild1 = computeMax(child1, 0, depth);
  576. maxChild2 = computeMax(child2, 0, depth);
  577. if (maxChild2 > maxChild1) {
  578. parent->children[0] = child1;
  579. parent->low = maxChild1;
  580. parent->children[1] = child2;
  581. parent->medium = maxChild2;
  582. } else {
  583. parent->children[0] = child2;
  584. parent->low = maxChild2;
  585. parent->children[1] = child1;
  586. parent->medium = maxChild1;
  587. }
  588. }
  589. /*
  590. ** Insert the new leaf into the tree.
  591. */
  592. static void FASTCALL insertLeaf(__GLcontext *gc, __GLnamesArray *array,
  593. __GLnamesLeaf *leaf)
  594. {
  595. __GLnamesBranch *extraChild;
  596. __GLnamesBranch *branch;
  597. __GLnamesBranch *parent;
  598. __GLnamesBranch *newParent;
  599. GLint maxdepth, curdepth;
  600. GLuint number;
  601. __GL_NAMES_ASSERT_LOCKED(array);
  602. number = leaf->end;
  603. maxdepth = array->depth;
  604. branch = array->tree;
  605. if (!branch) {
  606. /* No tree! Make a one leaf tree. */
  607. array->depth = 0;
  608. array->tree = (__GLnamesBranch *) leaf;
  609. return;
  610. }
  611. curdepth = 0;
  612. while (curdepth < maxdepth) {
  613. if (number <= branch->low) {
  614. branch = branch->children[0];
  615. } else if (number <= branch->medium) {
  616. branch = branch->children[1];
  617. } else {
  618. if (branch->children[2] != NULL) {
  619. branch = branch->children[2];
  620. } else {
  621. branch = branch->children[1];
  622. }
  623. }
  624. curdepth++;
  625. }
  626. /*
  627. ** Ok, we just managed to work our way to the bottom of the tree.
  628. ** 'leaf' becomes the extraChild, and we now try to insert it anywhere
  629. ** it will fit.
  630. */
  631. extraChild = (__GLnamesBranch *) leaf;
  632. parent = branch->parent;
  633. curdepth--;
  634. while (parent) {
  635. if (parent->children[2] == NULL) {
  636. /* We have room to squeeze this node in here! */
  637. addChild(parent, extraChild, curdepth, maxdepth);
  638. return;
  639. }
  640. /*
  641. ** We have one parent and four children. This simply
  642. ** won't do. We create a new parent, and end up with two
  643. ** parents with two children each. That works.
  644. */
  645. newParent = allocBranch(gc, array);
  646. splitParent(parent, newParent, extraChild, curdepth, maxdepth);
  647. /*
  648. ** Great. Now newParent becomes the orphan, and we try to
  649. ** trivially insert it up a level.
  650. */
  651. extraChild = newParent;
  652. branch = parent;
  653. parent = branch->parent;
  654. curdepth--;
  655. }
  656. /* We just reached the top node, and there is no parent, and we
  657. ** still haven't managed to rid ourselves of an extra child. So,
  658. ** we make a new parent to take branch and extraChild as it's two
  659. ** children. We have to increase the depth of the tree, of course.
  660. */
  661. ASSERTOPENGL(curdepth == -1, "Wrong depth at top\n");
  662. parent = allocBranch(gc, array);
  663. buildParent(parent, branch, extraChild, maxdepth);
  664. array->tree = parent;
  665. array->depth++;
  666. }
  667. /*
  668. ** Delete the given leaf from the tree. The leaf itself is not
  669. ** freed or anything, so the calling procedure needs to worry about it.
  670. */
  671. static void FASTCALL deleteLeaf(__GLcontext *gc, __GLnamesArray *array,
  672. __GLnamesLeaf *leaf)
  673. {
  674. __GLnamesBranch *orphan;
  675. __GLnamesBranch *parent, *newParent;
  676. __GLnamesBranch *grandparent;
  677. GLint depth, maxdepth;
  678. GLuint maxval;
  679. __GL_NAMES_ASSERT_LOCKED(array);
  680. maxdepth = depth = array->depth;
  681. parent = leaf->parent;
  682. if (parent == NULL) {
  683. /* Ack! We just nuked the only node! */
  684. array->tree = NULL;
  685. return;
  686. }
  687. deleteChild(array, parent, (__GLnamesBranch *) leaf, depth-1);
  688. /*
  689. ** depth is the depth of the child in this case.
  690. */
  691. depth--;
  692. while (parent->children[1] == NULL) {
  693. /* Crud. Need to do work. */
  694. orphan = parent->children[0];
  695. /* Ax the parent, insert child into grandparent. */
  696. grandparent = parent->parent;
  697. if (grandparent == NULL) {
  698. /*
  699. ** Hmmm. Parent was the root. Nuke it and make the orphan
  700. ** the new root.
  701. */
  702. freeBranch(gc, parent);
  703. array->tree = orphan;
  704. orphan->parent = NULL;
  705. array->depth--;
  706. return;
  707. }
  708. deleteChild(array, grandparent, parent, depth-1);
  709. freeBranch(gc, parent);
  710. /* The parent is dead. Find a new parent. */
  711. maxval = computeMax(orphan, depth+1, maxdepth);
  712. if (grandparent->children[1] == NULL ||
  713. maxval <= grandparent->low) {
  714. parent = grandparent->children[0];
  715. } else {
  716. parent = grandparent->children[1];
  717. }
  718. /* Insert orphan into new parent. */
  719. if (parent->children[2] != NULL) {
  720. newParent = allocBranch(gc, array);
  721. splitParent(parent, newParent, orphan, depth, maxdepth);
  722. /* We know there is room! */
  723. addChild(grandparent, newParent, depth-1, maxdepth);
  724. return;
  725. }
  726. /* The parent has room for the child */
  727. addChild(parent, orphan, depth, maxdepth);
  728. depth--;
  729. parent = grandparent;
  730. }
  731. }
  732. /*
  733. ** Shrink the leaf by adjusting start and end.
  734. ** If necessary, call pushMaxVal() to notify the database about the change.
  735. ** Also fix up the lists pointer if necessary.
  736. */
  737. static void FASTCALL resizeLeaf(__GLcontext *gc, __GLnamesLeaf *leaf,
  738. GLuint newstart, GLuint newend)
  739. {
  740. GLuint oldstart, oldend;
  741. GLuint newsize, offset, i;
  742. oldstart = leaf->start;
  743. oldend = leaf->end;
  744. leaf->start = newstart;
  745. if (newend != oldend) {
  746. leaf->end = newend;
  747. pushMaxVal((__GLnamesBranch *) leaf, newend);
  748. }
  749. if (leaf->dataList == NULL) return;
  750. /*
  751. ** Copy the appropriate pointers to the begining of the array, and
  752. ** realloc it.
  753. */
  754. offset = newstart - oldstart;
  755. newsize = newend - newstart + 1;
  756. if (offset) {
  757. for (i=0; i<newsize; i++) {
  758. /*
  759. ** Copy the whole structure with one line.
  760. */
  761. leaf->dataList[i] = leaf->dataList[i+offset];
  762. }
  763. }
  764. reallocLeafData(gc, leaf);
  765. }
  766. /*
  767. ** Find the previous leaf (before "leaf") in the tree.
  768. */
  769. static __GLnamesLeaf * FASTCALL prevLeaf(__GLnamesLeaf *leaf)
  770. {
  771. __GLnamesBranch *branch, *child;
  772. GLint reldepth;
  773. branch = leaf->parent;
  774. if (!branch) return NULL; /* A one leaf tree! */
  775. child = (__GLnamesBranch *) leaf;
  776. /* We start off at a relative depth of 1 above the child (-1) */
  777. reldepth = -1;
  778. while (branch) {
  779. /* If the child was the 3rd child, branch down to the second. */
  780. if (branch->children[2] == child) {
  781. branch = branch->children[1];
  782. reldepth++; /* One level lower */
  783. break;
  784. } else if (branch->children[1] == child) {
  785. /* If the child was the 2nd child, branch down to the first */
  786. branch = branch->children[0];
  787. reldepth++; /* One level lower */
  788. break;
  789. } else {
  790. /* Must have been 1st child */
  791. ASSERTOPENGL(branch->children[0] == child,
  792. "Parent/child relationship wrong\n");
  793. }
  794. /*
  795. ** Otherwise, we have already visited all of this branch's children,
  796. ** so we go up a level.
  797. */
  798. child = branch;
  799. branch = branch->parent;
  800. reldepth--; /* One level higher */
  801. }
  802. if (!branch) return NULL; /* All leaves visited! */
  803. /* Go down the 'right'most trail of this branch until we get to
  804. ** a child, then return it.
  805. */
  806. while (reldepth) {
  807. if (branch->children[2] != NULL) {
  808. branch = branch->children[2];
  809. } else if (branch->children[1] != NULL) {
  810. branch = branch->children[1];
  811. } else {
  812. branch = branch->children[0];
  813. }
  814. reldepth++; /* One level lower */
  815. }
  816. return (__GLnamesLeaf *) branch;
  817. }
  818. /*
  819. ** Find the first leaf in the tree.
  820. */
  821. static __GLnamesLeaf * FASTCALL firstLeaf(__GLnamesArray *array)
  822. {
  823. __GLnamesBranch *branch;
  824. GLint maxdepth, curdepth;
  825. __GL_NAMES_ASSERT_LOCKED(array);
  826. maxdepth = array->depth;
  827. curdepth = 0;
  828. branch = array->tree;
  829. /* No tree, no leaves! */
  830. if (!branch) return NULL;
  831. /* Take the 'left'most branch until we reach a leaf */
  832. while (curdepth != maxdepth) {
  833. branch = branch->children[0];
  834. curdepth++;
  835. }
  836. return (__GLnamesLeaf *) branch;
  837. }
  838. /*
  839. ** Find the next leaf (after "leaf") in the tree.
  840. */
  841. static __GLnamesLeaf * FASTCALL nextLeaf(__GLnamesLeaf *leaf)
  842. {
  843. __GLnamesBranch *branch, *child;
  844. GLint reldepth;
  845. branch = leaf->parent;
  846. if (!branch) return NULL; /* A one leaf tree! */
  847. child = (__GLnamesBranch *) leaf;
  848. /* We start off at a relative depth of 1 above the child (-1) */
  849. reldepth = -1;
  850. while (branch) {
  851. /* If the child was the 1st child, branch down to the second. */
  852. if (branch->children[0] == child) {
  853. branch = branch->children[1];
  854. reldepth++; /* One level lower */
  855. break;
  856. } else if (branch->children[1] == child) {
  857. /*
  858. ** If the child was the 2nd child, and there is a third, branch
  859. ** down to it.
  860. */
  861. if (branch->children[2] != NULL) {
  862. branch = branch->children[2];
  863. reldepth++; /* One level lower */
  864. break;
  865. }
  866. } else {
  867. /* Must have been 3rd child */
  868. ASSERTOPENGL(branch->children[2] == child,
  869. "Parent/child relationship wrong\n");
  870. }
  871. /*
  872. ** Otherwise, we have already visited all of this branch's children,
  873. ** so we go up a level.
  874. */
  875. child = branch;
  876. branch = branch->parent;
  877. reldepth--; /* One level higher */
  878. }
  879. if (!branch) return NULL; /* All leaves visited! */
  880. /* Go down the 'left'most trail of this branch until we get to
  881. ** a child, then return it.
  882. */
  883. while (reldepth) {
  884. branch = branch->children[0];
  885. reldepth++; /* One level lower */
  886. }
  887. return (__GLnamesLeaf *) branch;
  888. }
  889. /*
  890. ** Merge leaf2 into leaf1, and free leaf2.
  891. ** Need to pushMaxVal on the new leaf.
  892. ** We can assume that leaf1 and leaf2 are fit for merging.
  893. ** The return value is GL_TRUE if we did it.
  894. */
  895. static GLboolean FASTCALL mergeLeaves(__GLcontext *gc, __GLnamesLeaf *leaf1,
  896. __GLnamesLeaf *leaf2)
  897. {
  898. GLuint end;
  899. GLuint i;
  900. GLuint number, offset;
  901. /* If we don't have to merge lists, it is easy. */
  902. if (leaf1->dataList == NULL) {
  903. ASSERTOPENGL(leaf2->dataList == NULL, "Data already exists\n");
  904. if (leaf1->start < leaf2->start) {
  905. leaf1->end = leaf2->end;
  906. pushMaxVal((__GLnamesBranch *) leaf1, leaf1->end);
  907. } else {
  908. leaf1->start = leaf2->start;
  909. }
  910. freeLeaf(gc, leaf2);
  911. return GL_TRUE;
  912. }
  913. /*
  914. ** Yick! Need to merge lists.
  915. */
  916. ASSERTOPENGL(leaf2->dataList != NULL, "No data\n");
  917. if (leaf1->start < leaf2->start) {
  918. /*
  919. ** Expand size of leaf1's array, copy leaf2's array into it,
  920. ** free leaf2.
  921. */
  922. offset = leaf1->end - leaf1->start + 1;
  923. number = leaf2->end - leaf2->start + 1;
  924. end = leaf1->end;
  925. leaf1->end = leaf2->end;
  926. if (!reallocLeafData(gc, leaf1)) {
  927. /*
  928. ** Heavens! No memory? That sucks!
  929. ** We won't bother merging. It is never an absolutely critical
  930. ** operation.
  931. */
  932. leaf1->end = end;
  933. return GL_FALSE;
  934. }
  935. for (i = 0; i < number; i++) {
  936. leaf1->dataList[i+offset] = leaf2->dataList[i];
  937. }
  938. freeLeaf(gc, leaf2);
  939. pushMaxVal((__GLnamesBranch *) leaf1, leaf1->end);
  940. } else {
  941. /*
  942. ** Expand the size of leaf2's array, copy leaf1's array into it.
  943. ** Then free leaf1's array, copy leaf2's array to leaf1, and free
  944. ** leaf2.
  945. */
  946. offset = leaf2->end - leaf2->start + 1;
  947. number = leaf1->end - leaf1->start + 1;
  948. end = leaf2->end;
  949. leaf2->end = leaf1->end;
  950. if (!reallocLeafData(gc, leaf2)) {
  951. /*
  952. ** Heavens! No memory? That sucks!
  953. ** We won't bother merging. It is never an absolutely critical
  954. ** operation.
  955. */
  956. leaf2->end = end;
  957. return GL_FALSE;
  958. }
  959. for (i = 0; i < number; i++) {
  960. leaf2->dataList[i+offset] = leaf1->dataList[i];
  961. }
  962. freeLeafData(gc, leaf1->dataList);
  963. leaf1->start = leaf2->start;
  964. leaf1->dataList = leaf2->dataList;
  965. leaf2->dataList = NULL;
  966. freeLeaf(gc, leaf2);
  967. }
  968. return GL_TRUE;
  969. }
  970. /*
  971. ** Check if this leaf can merge with any neighbors, and if so, do it.
  972. */
  973. static void FASTCALL mergeLeaf(__GLcontext *gc, __GLnamesArray *array,
  974. __GLnamesLeaf *leaf)
  975. {
  976. __GLnamesLeaf *next, *prev;
  977. __GL_NAMES_ASSERT_LOCKED(array);
  978. next = nextLeaf(leaf);
  979. if (next) {
  980. /* Try to merge with next leaf */
  981. if (leaf->end + 1 == next->start) {
  982. if ((leaf->dataList == NULL && next->dataList == NULL) ||
  983. (next->dataList && leaf->dataList &&
  984. next->end - leaf->start < (GLuint) __GL_DLIST_MAX_ARRAY_BLOCK)) {
  985. /* It's legal to merge these leaves */
  986. deleteLeaf(gc, array, next);
  987. if (!mergeLeaves(gc, leaf, next)) {
  988. /*
  989. ** Ack! No memory? We bail on the merge.
  990. */
  991. insertLeaf(gc, array, next);
  992. return;
  993. }
  994. }
  995. }
  996. }
  997. prev = prevLeaf(leaf);
  998. if (prev) {
  999. /* Try to merge with prev leaf */
  1000. if (prev->end + 1 == leaf->start) {
  1001. if ((prev->dataList == NULL && leaf->dataList == NULL) ||
  1002. (leaf->dataList && prev->dataList &&
  1003. leaf->end - prev->start < (GLuint) __GL_DLIST_MAX_ARRAY_BLOCK)) {
  1004. /* It's legal to merge these leaves */
  1005. deleteLeaf(gc, array, prev);
  1006. if (!mergeLeaves(gc, leaf, prev)) {
  1007. /*
  1008. ** Ack! No memory? We bail on the merge.
  1009. */
  1010. insertLeaf(gc, array, prev);
  1011. return;
  1012. }
  1013. }
  1014. }
  1015. }
  1016. }
  1017. GLboolean FASTCALL __glNamesNewData(__GLcontext *gc, __GLnamesArray *array,
  1018. GLuint name, void *data)
  1019. {
  1020. __GLnamesLeaf *leaf, *newleaf;
  1021. GLint entry;
  1022. GLuint start, end;
  1023. __GL_NAMES_LOCK(array);
  1024. leaf = findLeaf(array, name, GL_TRUE);
  1025. /*
  1026. ** First we check for possible memory problems, since it will be
  1027. ** difficult to back out once we start.
  1028. */
  1029. if (leaf == NULL || leaf->dataList == NULL) {
  1030. /*
  1031. ** May need memory in these cases.
  1032. */
  1033. if (array->nbranches != __GL_DL_EXTRA_BRANCHES ||
  1034. array->nleaves != __GL_DL_EXTRA_LEAVES) {
  1035. if (!fixMemoryProblem(gc, array)) {
  1036. __GL_NAMES_UNLOCK(array);
  1037. __glSetError(GL_OUT_OF_MEMORY);
  1038. return GL_FALSE;
  1039. }
  1040. }
  1041. }
  1042. if (!leaf) {
  1043. /*
  1044. ** Make new leaf with just this display list
  1045. */
  1046. leaf = allocLeaf(gc, array);
  1047. leaf->start = leaf->end = name;
  1048. if (data) {
  1049. if (!allocLeafData(gc, leaf)) {
  1050. /*
  1051. ** Bummer. No new list for you!
  1052. */
  1053. freeLeaf(gc, leaf);
  1054. __GL_NAMES_UNLOCK(array);
  1055. __glSetError(GL_OUT_OF_MEMORY);
  1056. return GL_FALSE;
  1057. }
  1058. leaf->dataList[0] = data;
  1059. (*(GLint *)data) = 1; /* set the refcount */
  1060. }
  1061. insertLeaf(gc, array, leaf);
  1062. mergeLeaf(gc, array, leaf);
  1063. __GL_NAMES_UNLOCK(array);
  1064. return GL_TRUE;
  1065. } else if (leaf->dataList) {
  1066. /*
  1067. ** Simply update the appropriate entry in the lists array
  1068. */
  1069. entry = name - leaf->start;
  1070. if (leaf->dataList[entry] != leaf->dataInfo->empty) {
  1071. ASSERTOPENGL(leaf->dataInfo->free != NULL,
  1072. "No free function\n");
  1073. (*leaf->dataInfo->free)(gc, leaf->dataList[entry]);
  1074. leaf->dataList[entry] = leaf->dataInfo->empty;
  1075. }
  1076. if (data) {
  1077. leaf->dataList[entry] = data;
  1078. (*(GLint *)data) = 1; /* set the refcount */
  1079. }
  1080. __GL_NAMES_UNLOCK(array);
  1081. return GL_TRUE;
  1082. } else {
  1083. if (!data) {
  1084. /*
  1085. ** If there isn't really any list, we are done.
  1086. */
  1087. __GL_NAMES_UNLOCK(array);
  1088. return GL_TRUE;
  1089. }
  1090. /*
  1091. ** Allocate some or all of the lists in leaf. If only some, then
  1092. ** leaf needs to be split into two or three leaves.
  1093. **
  1094. ** First we decide what range of numbers to allocate an array for.
  1095. ** (be careful of possible word wrap error)
  1096. */
  1097. start = name - __GL_DLIST_MIN_ARRAY_BLOCK/2;
  1098. if (start < leaf->start || start > name) {
  1099. start = leaf->start;
  1100. }
  1101. end = start + __GL_DLIST_MIN_ARRAY_BLOCK - 1;
  1102. if (end > leaf->end || end < start) {
  1103. end = leaf->end;
  1104. }
  1105. if (start - leaf->start < (GLuint) __GL_DLIST_MIN_ARRAY_BLOCK) {
  1106. start = leaf->start;
  1107. }
  1108. if (leaf->end - end < (GLuint) __GL_DLIST_MIN_ARRAY_BLOCK) {
  1109. end = leaf->end;
  1110. }
  1111. if (start == leaf->start) {
  1112. if (end == leaf->end) {
  1113. /*
  1114. ** Simply allocate the entire array.
  1115. */
  1116. if (!allocLeafData(gc, leaf)) {
  1117. /*
  1118. ** Whoa! No memory! Never mind!
  1119. */
  1120. __glSetError(GL_OUT_OF_MEMORY);
  1121. __GL_NAMES_UNLOCK(array);
  1122. return GL_FALSE;
  1123. }
  1124. {
  1125. GLint entry = name - leaf->start;
  1126. leaf->dataList[entry] = data;
  1127. (*(GLint *)data) = 1; /* set the refcount */
  1128. }
  1129. mergeLeaf(gc, array, leaf);
  1130. __GL_NAMES_UNLOCK(array);
  1131. return GL_TRUE;
  1132. } else {
  1133. /*
  1134. ** Shrink the existing leaf, and create a new one to hold
  1135. ** the new arrays (done outside the "if" statement).
  1136. */
  1137. resizeLeaf(gc, leaf, end+1, leaf->end);
  1138. }
  1139. } else if (end == leaf->end) {
  1140. /*
  1141. ** Shrink the existing leaf, and create a new one to hold
  1142. ** the new arrays (done outside the "if" statement).
  1143. */
  1144. resizeLeaf(gc, leaf, leaf->start, start-1);
  1145. } else {
  1146. /*
  1147. ** Crud. The middle of the leaf was deleted. This is tough.
  1148. */
  1149. newleaf = allocLeaf(gc, array);
  1150. newleaf->start = end+1;
  1151. newleaf->end = leaf->end;
  1152. resizeLeaf(gc, leaf, leaf->start, start-1);
  1153. insertLeaf(gc, array, newleaf);
  1154. }
  1155. leaf = allocLeaf(gc, array);
  1156. leaf->start = start;
  1157. leaf->end = end;
  1158. if (!allocLeafData(gc, leaf)) {
  1159. /*
  1160. ** Whoa! No memory! Never mind!
  1161. */
  1162. insertLeaf(gc, array, leaf);
  1163. mergeLeaf(gc, array, leaf);
  1164. __glSetError(GL_OUT_OF_MEMORY);
  1165. __GL_NAMES_UNLOCK(array);
  1166. return GL_FALSE;
  1167. }
  1168. {
  1169. GLint entry = name - leaf->start;
  1170. leaf->dataList[entry] = data;
  1171. (*(GLint *)data) = 1; /* set the refcount */
  1172. }
  1173. insertLeaf(gc, array, leaf);
  1174. mergeLeaf(gc, array, leaf);
  1175. __GL_NAMES_UNLOCK(array);
  1176. return GL_TRUE;
  1177. }
  1178. }
  1179. /*
  1180. ** Lock the named data. Locking data both looks the data up,
  1181. ** and guarantees that another thread will not delete the data out from
  1182. ** under us. This data will be unlocked with __glNamesUnlockData().
  1183. **
  1184. ** A return value of NULL indicates that no data with the specified name
  1185. ** was found.
  1186. */
  1187. void * FASTCALL __glNamesLockData(__GLcontext *gc, __GLnamesArray *array,
  1188. GLuint name)
  1189. {
  1190. __GLnamesLeaf *leaf;
  1191. void *data;
  1192. GLint offset;
  1193. __GL_NAMES_LOCK(array);
  1194. /*
  1195. ** Lock access to data.
  1196. */
  1197. leaf = findLeaf(array, name, GL_TRUE);
  1198. if (leaf == NULL || leaf->dataList == NULL) {
  1199. __GL_NAMES_UNLOCK(array);
  1200. return NULL;
  1201. }
  1202. offset = name - leaf->start;
  1203. data = leaf->dataList[offset];
  1204. if (data) {
  1205. (*(GLint *)data)++; /* Increment the refcount. */
  1206. }
  1207. __GL_NAMES_UNLOCK(array);
  1208. return data;
  1209. }
  1210. /*
  1211. ** Lock all of the data in the user's names array. Locking data
  1212. ** both looks the data up, and guarantees that another thread will not
  1213. ** delete the data out from under us. These data structs will be unlocked
  1214. ** with __glNamesUnlockDataList().
  1215. **
  1216. ** All entries of the array are guaranteed to be non-NULL. This is
  1217. ** accomplished by sticking an empty data structure in those slots where
  1218. ** no data was set.
  1219. */
  1220. void FASTCALL __glNamesLockDataList(__GLcontext *gc, __GLnamesArray *array,
  1221. GLsizei n, GLenum type, GLuint base,
  1222. const GLvoid *names, void *dataPtrs[])
  1223. {
  1224. __GLnamesLeaf *leaf;
  1225. void **data;
  1226. void *tempData;
  1227. void *empty;
  1228. GLuint curName;
  1229. __GL_NAMES_LOCK(array);
  1230. empty = array->dataInfo->empty;
  1231. data = dataPtrs;
  1232. /*
  1233. ** Note that this code is designed to take advantage of coherence.
  1234. ** After looking up (and locking) a single display list in
  1235. ** listnums[], the next list is checked for in the same leaf that
  1236. ** contained the previous. This will make typical uses of CallLists()
  1237. ** quite fast (text, for example).
  1238. */
  1239. /*
  1240. ** Lock access to array.
  1241. */
  1242. switch(type) {
  1243. case GL_BYTE:
  1244. /*
  1245. ** Coded poorly for optimization purposes
  1246. */
  1247. {
  1248. const GLbyte *p = (const GLbyte *) names;
  1249. Bstart:
  1250. if (--n >= 0) {
  1251. /* Optimization for possibly common font case */
  1252. curName = base + *p++;
  1253. Bfind:
  1254. leaf = findLeaf(array, curName, GL_TRUE);
  1255. if (leaf && leaf->dataList) {
  1256. GLint reldiff;
  1257. GLuint relend;
  1258. void **leafData;
  1259. leafData = leaf->dataList;
  1260. tempData = leafData[curName - leaf->start];
  1261. /* All possible display lists can be found here */
  1262. reldiff = base - leaf->start;
  1263. relend = leaf->end - leaf->start;
  1264. Bsave:
  1265. (*(GLint *)tempData)++; /* increment the refcount */
  1266. *data++ = tempData;
  1267. if (--n >= 0) {
  1268. curName = *p++ + reldiff;
  1269. if (curName <= relend) {
  1270. tempData = leafData[curName];
  1271. goto Bsave;
  1272. }
  1273. curName = curName + leaf->start;
  1274. goto Bfind;
  1275. }
  1276. } else {
  1277. (*(GLint *)empty)++; /* increment refcount */
  1278. *data++ = empty;
  1279. goto Bstart;
  1280. }
  1281. }
  1282. }
  1283. break;
  1284. case GL_UNSIGNED_BYTE:
  1285. /*
  1286. ** Coded poorly for optimization purposes
  1287. */
  1288. {
  1289. const GLubyte *p = (const GLubyte *) names;
  1290. UBstart:
  1291. if (--n >= 0) {
  1292. /* Optimization for possibly common font case */
  1293. curName = base + *p++;
  1294. UBfind:
  1295. leaf = findLeaf(array, curName, GL_TRUE);
  1296. if (leaf && leaf->dataList) {
  1297. GLint reldiff;
  1298. GLuint relend;
  1299. void **leafData;
  1300. leafData = leaf->dataList;
  1301. tempData = leafData[curName - leaf->start];
  1302. /* All possible display lists can be found here */
  1303. reldiff = base - leaf->start;
  1304. relend = leaf->end - leaf->start;
  1305. UBsave:
  1306. (*(GLint *)tempData)++; /* increment the refcount */
  1307. *data++ = tempData;
  1308. if (--n >= 0) {
  1309. curName = *p++ + reldiff;
  1310. if (curName <= relend) {
  1311. tempData = leafData[curName];
  1312. goto UBsave;
  1313. }
  1314. curName = curName + leaf->start;
  1315. goto UBfind;
  1316. }
  1317. } else {
  1318. (*(GLint *)empty)++; /* increment refcount */
  1319. *data++ = empty;
  1320. goto UBstart;
  1321. }
  1322. }
  1323. }
  1324. break;
  1325. case GL_SHORT:
  1326. {
  1327. const GLshort *p = (const GLshort *) names;
  1328. leaf = NULL;
  1329. while (--n >= 0) {
  1330. curName = base + *p++;
  1331. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1332. leaf = findLeaf(array, curName, GL_TRUE);
  1333. }
  1334. if (leaf && leaf->dataList) {
  1335. tempData = leaf->dataList[curName - leaf->start];
  1336. (*(GLint *)tempData)++; /* increment the refcount */
  1337. *data++ = tempData;
  1338. } else {
  1339. (*(GLint *)empty)++; /* increment refcount */
  1340. *data++ = empty;
  1341. }
  1342. }
  1343. }
  1344. break;
  1345. case GL_UNSIGNED_SHORT:
  1346. {
  1347. const GLushort *p = (const GLushort *) names;
  1348. leaf = NULL;
  1349. while (--n >= 0) {
  1350. curName = base + *p++;
  1351. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1352. leaf = findLeaf(array, curName, GL_TRUE);
  1353. }
  1354. if (leaf && leaf->dataList) {
  1355. tempData = leaf->dataList[curName - leaf->start];
  1356. (*(GLint *)tempData)++; /* increment the refcount */
  1357. *data++ = tempData;
  1358. } else {
  1359. (*(GLint *)empty)++; /* increment refcount */
  1360. *data++ = empty;
  1361. }
  1362. }
  1363. }
  1364. break;
  1365. case GL_INT:
  1366. {
  1367. const GLint *p = (const GLint *) names;
  1368. leaf = NULL;
  1369. while (--n >= 0) {
  1370. curName = base + *p++;
  1371. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1372. leaf = findLeaf(array, curName, GL_TRUE);
  1373. }
  1374. if (leaf && leaf->dataList) {
  1375. tempData = leaf->dataList[curName - leaf->start];
  1376. (*(GLint *)tempData)++; /* increment the refcount */
  1377. *data++ = tempData;
  1378. } else {
  1379. (*(GLint *)empty)++; /* increment refcount */
  1380. *data++ = empty;
  1381. }
  1382. }
  1383. }
  1384. break;
  1385. case GL_UNSIGNED_INT:
  1386. {
  1387. const GLuint *p = (const GLuint *) names;
  1388. leaf = NULL;
  1389. while (--n >= 0) {
  1390. curName = base + *p++;
  1391. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1392. leaf = findLeaf(array, curName, GL_TRUE);
  1393. }
  1394. if (leaf && leaf->dataList) {
  1395. tempData = leaf->dataList[curName - leaf->start];
  1396. (*(GLint *)tempData)++; /* increment the refcount */
  1397. *data++ = tempData;
  1398. } else {
  1399. (*(GLint *)empty)++; /* increment refcount */
  1400. *data++ = empty;
  1401. }
  1402. }
  1403. }
  1404. break;
  1405. case GL_FLOAT:
  1406. {
  1407. const GLfloat *p = (const GLfloat *) names;
  1408. leaf = NULL;
  1409. while (--n >= 0) {
  1410. curName = base + *p++;
  1411. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1412. leaf = findLeaf(array, curName, GL_TRUE);
  1413. }
  1414. if (leaf && leaf->dataList) {
  1415. tempData = leaf->dataList[curName - leaf->start];
  1416. (*(GLint *)tempData)++; /* increment the refcount */
  1417. *data++ = tempData;
  1418. } else {
  1419. (*(GLint *)empty)++; /* increment refcount */
  1420. *data++ = empty;
  1421. }
  1422. }
  1423. }
  1424. break;
  1425. case GL_2_BYTES:
  1426. {
  1427. const GLubyte *p = (const GLubyte *) names;
  1428. leaf = NULL;
  1429. while (--n >= 0) {
  1430. curName = base + ((p[0] << 8) | p[1]);
  1431. p += 2;
  1432. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1433. leaf = findLeaf(array, curName, GL_TRUE);
  1434. }
  1435. if (leaf && leaf->dataList) {
  1436. tempData = leaf->dataList[curName - leaf->start];
  1437. (*(GLint *)tempData)++; /* increment the refcount */
  1438. *data++ = tempData;
  1439. } else {
  1440. (*(GLint *)empty)++; /* increment refcount */
  1441. *data++ = empty;
  1442. }
  1443. }
  1444. }
  1445. break;
  1446. case GL_3_BYTES:
  1447. {
  1448. const GLubyte *p = (const GLubyte *) names;
  1449. leaf = NULL;
  1450. while (--n >= 0) {
  1451. curName = base + ((p[0] << 16) | (p[1] << 8) | p[2]);
  1452. p += 3;
  1453. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1454. leaf = findLeaf(array, curName, GL_TRUE);
  1455. }
  1456. if (leaf && leaf->dataList) {
  1457. tempData = leaf->dataList[curName - leaf->start];
  1458. (*(GLint *)tempData)++; /* increment the refcount */
  1459. *data++ = tempData;
  1460. } else {
  1461. (*(GLint *)empty)++; /* increment refcount */
  1462. *data++ = empty;
  1463. }
  1464. }
  1465. }
  1466. break;
  1467. case GL_4_BYTES:
  1468. {
  1469. const GLubyte *p = (const GLubyte *) names;
  1470. leaf = NULL;
  1471. while (--n >= 0) {
  1472. curName = base + ((p[0] << 24) | (p[1] << 16) |
  1473. (p[2] << 8) | p[3]);
  1474. p += 4;
  1475. if (leaf==NULL || curName<leaf->start || curName>leaf->end) {
  1476. leaf = findLeaf(array, curName, GL_TRUE);
  1477. }
  1478. if (leaf && leaf->dataList) {
  1479. tempData = leaf->dataList[curName - leaf->start];
  1480. (*(GLint *)tempData)++; /* increment the refcount */
  1481. *data++ = tempData;
  1482. } else {
  1483. (*(GLint *)empty)++; /* increment refcount */
  1484. *data++ = empty;
  1485. }
  1486. }
  1487. }
  1488. break;
  1489. default:
  1490. /* This should be impossible */
  1491. ASSERTOPENGL(FALSE, "Default hit\n");
  1492. }
  1493. __GL_NAMES_UNLOCK(array);
  1494. }
  1495. /*
  1496. ** Unlocks data that was previously locked with __glNamesLockData().
  1497. */
  1498. void FASTCALL __glNamesUnlockData(__GLcontext *gc, void *data,
  1499. __GLnamesCleanupFunc cleanup)
  1500. {
  1501. GLint *pRefcount;
  1502. ASSERTOPENGL(data, "No data to unlock\n");
  1503. pRefcount = data;
  1504. (*pRefcount)--; /* decrement the refcount */
  1505. ASSERTOPENGL(*pRefcount >= 0, "Invalid refcount\n");
  1506. if (*pRefcount == 0) {
  1507. /*
  1508. ** We are the last person to see this list alive. Free it.
  1509. */
  1510. (*cleanup)(gc, data);
  1511. }
  1512. }
  1513. /*
  1514. ** Unlocks an array of named data that was previously locked with
  1515. ** __glNamesLockDataList().
  1516. */
  1517. void FASTCALL __glNamesUnlockDataList(__GLcontext *gc, GLsizei n,
  1518. void *dataList[],
  1519. __GLnamesCleanupFunc cleanup)
  1520. {
  1521. GLint i;
  1522. GLint *pRefcount;
  1523. /*
  1524. ** The refcount comes first in all data definitions, so the
  1525. ** data pointer also points to the refcount.
  1526. */
  1527. for (i = 0; i < n; i++) {
  1528. pRefcount = (GLint *)(dataList[i]);
  1529. (*pRefcount) --; /* decrement the refcount */
  1530. ASSERTOPENGL(*pRefcount >= 0, "Invalid refcount\n");
  1531. if (*pRefcount == 0) {
  1532. /*
  1533. ** We are the last person to see this list alive. Free it.
  1534. */
  1535. (*cleanup)(gc, (void *)pRefcount);
  1536. }
  1537. }
  1538. }
  1539. GLuint FASTCALL __glNamesGenRange(__GLcontext *gc, __GLnamesArray *array,
  1540. GLsizei range)
  1541. {
  1542. GLuint lastUsed;
  1543. GLuint nextUsed;
  1544. GLuint maxUsed;
  1545. __GLnamesLeaf *leaf;
  1546. __GLnamesLeaf *nextleaf;
  1547. __GLnamesLeaf *newleaf;
  1548. __GL_NAMES_LOCK(array);
  1549. /*
  1550. ** First we check for possible memory problems, since it will be
  1551. ** difficult to back out once we start.
  1552. */
  1553. if (array->nbranches != __GL_DL_EXTRA_BRANCHES ||
  1554. array->nleaves != __GL_DL_EXTRA_LEAVES) {
  1555. if (!fixMemoryProblem(gc, array)) {
  1556. __GL_NAMES_UNLOCK(array);
  1557. __glSetError(GL_OUT_OF_MEMORY);
  1558. return 0;
  1559. }
  1560. }
  1561. leaf = firstLeaf(array);
  1562. /*
  1563. ** Can we possibly allocate the appropriate number before the first leaf?
  1564. */
  1565. if (leaf && leaf->start > (GLuint)range) {
  1566. if (leaf->dataList == NULL) {
  1567. /*
  1568. ** Ha! We can trivially extend leaf!
  1569. */
  1570. leaf->start -= range;
  1571. __GL_NAMES_UNLOCK(array);
  1572. return leaf->start;
  1573. } else {
  1574. /*
  1575. ** Must make a new leaf
  1576. */
  1577. newleaf = allocLeaf(gc, array);
  1578. newleaf->start = 1;
  1579. newleaf->end = range;
  1580. insertLeaf(gc, array, newleaf);
  1581. __GL_NAMES_UNLOCK(array);
  1582. return 1;
  1583. }
  1584. }
  1585. while (leaf) {
  1586. nextleaf = nextLeaf(leaf);
  1587. if (!nextleaf) break;
  1588. lastUsed = leaf->end + 1;
  1589. nextUsed = nextleaf->start;
  1590. /* Room for (lastUsed) - (nextUsed-1) here */
  1591. if (nextUsed - lastUsed >= (GLuint)range) {
  1592. if (leaf->dataList == NULL) {
  1593. /* Trivial to expand 'leaf' */
  1594. leaf->end += range;
  1595. pushMaxVal((__GLnamesBranch *) leaf, leaf->end);
  1596. if (nextUsed - lastUsed == (GLuint)range && nextleaf->dataList == NULL) {
  1597. mergeLeaf(gc, array, leaf);
  1598. }
  1599. __GL_NAMES_UNLOCK(array);
  1600. return lastUsed;
  1601. } else if (nextleaf->dataList == NULL) {
  1602. /* Trivial to expand 'nextleaf' */
  1603. nextleaf->start -= range;
  1604. __GL_NAMES_UNLOCK(array);
  1605. return nextleaf->start;
  1606. } else {
  1607. newleaf = allocLeaf(gc, array);
  1608. newleaf->start = lastUsed;
  1609. newleaf->end = lastUsed + range - 1;
  1610. insertLeaf(gc, array, newleaf);
  1611. __GL_NAMES_UNLOCK(array);
  1612. return lastUsed;
  1613. }
  1614. }
  1615. leaf = nextleaf;
  1616. }
  1617. if (leaf == NULL) {
  1618. newleaf = allocLeaf(gc, array);
  1619. newleaf->start = 1;
  1620. newleaf->end = range;
  1621. insertLeaf(gc, array, newleaf);
  1622. __GL_NAMES_UNLOCK(array);
  1623. return 1;
  1624. } else {
  1625. lastUsed = leaf->end;
  1626. maxUsed = lastUsed + range;
  1627. if (maxUsed < lastUsed) {
  1628. /* Word wrap! Ack! */
  1629. __GL_NAMES_UNLOCK(array);
  1630. return 0;
  1631. }
  1632. if (leaf->dataList == NULL) {
  1633. /* Trivial to expand 'leaf' */
  1634. leaf->end += range;
  1635. pushMaxVal((__GLnamesBranch *) leaf, leaf->end);
  1636. __GL_NAMES_UNLOCK(array);
  1637. return lastUsed + 1;
  1638. } else {
  1639. /* Need to make new leaf */
  1640. newleaf = allocLeaf(gc, array);
  1641. newleaf->start = lastUsed + 1;
  1642. newleaf->end = maxUsed;
  1643. insertLeaf(gc, array, newleaf);
  1644. __GL_NAMES_UNLOCK(array);
  1645. return lastUsed + 1;
  1646. }
  1647. }
  1648. }
  1649. void FASTCALL __glNamesDeleteRange(__GLcontext *gc, __GLnamesArray *array,
  1650. GLuint name, GLsizei range)
  1651. {
  1652. __GLnamesLeaf *leaf;
  1653. /*LINTED nextleaf ok; lint doesn't understand for loops*/
  1654. __GLnamesLeaf *nextleaf;
  1655. __GLnamesLeaf *newleaf;
  1656. void *empty;
  1657. GLuint start, end, i;
  1658. GLuint firstdel, lastdel;
  1659. GLuint memoryProblem;
  1660. if (range == 0) return;
  1661. __GL_NAMES_LOCK(array);
  1662. /*
  1663. ** First we check for possible memory problems, since it will be
  1664. ** difficult to back out once we start. We note a possible problem,
  1665. ** and check for it before fragmenting a leaf.
  1666. */
  1667. memoryProblem = 0;
  1668. if (array->nbranches != __GL_DL_EXTRA_BRANCHES ||
  1669. array->nleaves != __GL_DL_EXTRA_LEAVES) {
  1670. memoryProblem = 1;
  1671. }
  1672. firstdel = name;
  1673. lastdel = name+range-1;
  1674. /*LINTED nextleaf ok; lint bug*/
  1675. for (leaf = findLeaf(array, name, GL_FALSE); leaf != NULL;
  1676. leaf = nextleaf) {
  1677. nextleaf = nextLeaf(leaf);
  1678. start = leaf->start;
  1679. end = leaf->end;
  1680. if (lastdel < start) break;
  1681. if (firstdel > end) continue;
  1682. if (firstdel > start) start = firstdel;
  1683. if (lastdel < end) end = lastdel;
  1684. /*
  1685. ** Need to delete the range of lists from start to end.
  1686. */
  1687. if (leaf->dataList) {
  1688. empty = array->dataInfo->empty;
  1689. for (i=start; i<=end; i++) {
  1690. if (leaf->dataList[i - leaf->start] != empty) {
  1691. (*leaf->dataInfo->free)(gc,
  1692. (void *)leaf->dataList[i - leaf->start]);
  1693. leaf->dataList[i - leaf->start] = empty;
  1694. }
  1695. }
  1696. }
  1697. if (start == leaf->start) {
  1698. if (end == leaf->end) {
  1699. /* Bye bye leaf! */
  1700. deleteLeaf(gc, array, leaf);
  1701. freeLeaf(gc, leaf);
  1702. } else {
  1703. /* Shrink leaf */
  1704. resizeLeaf(gc, leaf, end+1, leaf->end);
  1705. }
  1706. } else if (end == leaf->end) {
  1707. /* Shrink leaf */
  1708. resizeLeaf(gc, leaf, leaf->start, start-1);
  1709. } else {
  1710. if (memoryProblem) {
  1711. if (!fixMemoryProblem(gc, array)) {
  1712. __GL_NAMES_UNLOCK(array);
  1713. __glSetError(GL_OUT_OF_MEMORY);
  1714. return;
  1715. }
  1716. }
  1717. /* Crud. The middle of the leaf was deleted. This is tough. */
  1718. newleaf = allocLeaf(gc, array);
  1719. newleaf->start = end+1;
  1720. newleaf->end = leaf->end;
  1721. if (leaf->dataList) {
  1722. if (!allocLeafData(gc, newleaf)) {
  1723. /*
  1724. ** Darn! We are in trouble. This is a bad spot for an
  1725. ** out of memory error. It is also darn unlikely,
  1726. ** because we just freed up some memory.
  1727. */
  1728. freeLeaf(gc, newleaf);
  1729. __GL_NAMES_UNLOCK(array);
  1730. __glSetError(GL_OUT_OF_MEMORY);
  1731. return;
  1732. }
  1733. copyLeafInfo(leaf, newleaf);
  1734. }
  1735. resizeLeaf(gc, leaf, leaf->start, start-1);
  1736. insertLeaf(gc, array, newleaf);
  1737. break;
  1738. }
  1739. }
  1740. __GL_NAMES_UNLOCK(array);
  1741. }
  1742. GLboolean FASTCALL __glNamesIsName(__GLcontext *gc, __GLnamesArray *array,
  1743. GLuint name)
  1744. {
  1745. GLboolean isName;
  1746. __GL_NAMES_LOCK(array);
  1747. /*
  1748. ** If the name retrieves a leaf, it is in the current name space.
  1749. */
  1750. isName = findLeaf(array, name, GL_TRUE) != NULL;
  1751. __GL_NAMES_UNLOCK(array);
  1752. return isName;
  1753. }
  1754. /*
  1755. ** Generates a list of (not necessarily contiguous) names.
  1756. */
  1757. void FASTCALL __glNamesGenNames(__GLcontext *gc, __GLnamesArray *array,
  1758. GLsizei n, GLuint* names)
  1759. {
  1760. GLuint start, nameVal;
  1761. int i;
  1762. if (NULL == names) return;
  1763. start = __glNamesGenRange(gc, array, n);
  1764. for (i=0, nameVal=start; i < n; i++, nameVal++) {
  1765. names[i] = nameVal;
  1766. }
  1767. }
  1768. /*
  1769. ** Deletes a list of (not necessarily contiguous) names.
  1770. */
  1771. void FASTCALL __glNamesDeleteNames(__GLcontext *gc, __GLnamesArray *array,
  1772. GLsizei n, const GLuint* names)
  1773. {
  1774. GLuint start, rangeVal, i;
  1775. /*
  1776. ** Because of resizing leaves, etc, it is best to work in ranges
  1777. ** as much as possible. So break the list into ranges
  1778. ** and delete them that way. This degrades into deleting
  1779. ** them one at a time if the list is disjoint or non-ascending.
  1780. ** It also only calls DeleteRange once if the list is a
  1781. ** contiguous range of names.
  1782. */
  1783. start = rangeVal = names[0];
  1784. for (i=0; i < (GLuint)n; i++, rangeVal++) {
  1785. if (names[i] != rangeVal) {
  1786. __glNamesDeleteRange(gc,array,start,rangeVal-start);
  1787. start = rangeVal = names[i];
  1788. }
  1789. }
  1790. __glNamesDeleteRange(gc,array,start,rangeVal-start);
  1791. return;
  1792. }