TileReplacementQueue.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*global define*/
  2. define([
  3. '../Core/defined'
  4. ], function(
  5. defined) {
  6. "use strict";
  7. /**
  8. * A priority queue of tiles to be replaced, if necessary, to make room for new tiles. The queue
  9. * is implemented as a linked list.
  10. *
  11. * @alias TileReplacementQueue
  12. * @private
  13. */
  14. var TileReplacementQueue = function TileReplacementQueue() {
  15. this.head = undefined;
  16. this.tail = undefined;
  17. this.count = 0;
  18. this._lastBeforeStartOfFrame = undefined;
  19. };
  20. /**
  21. * Marks the start of the render frame. Tiles before (closer to the head) this tile in the
  22. * list were used last frame and must not be unloaded.
  23. */
  24. TileReplacementQueue.prototype.markStartOfRenderFrame = function() {
  25. this._lastBeforeStartOfFrame = this.head;
  26. };
  27. /**
  28. * Reduces the size of the queue to a specified size by unloading the least-recently used
  29. * tiles. Tiles that were used last frame will not be unloaded, even if that puts the number
  30. * of tiles above the specified maximum.
  31. *
  32. * @param {Number} maximumTiles The maximum number of tiles in the queue.
  33. */
  34. TileReplacementQueue.prototype.trimTiles = function(maximumTiles) {
  35. var tileToTrim = this.tail;
  36. var keepTrimming = true;
  37. while (keepTrimming &&
  38. defined(this._lastBeforeStartOfFrame) &&
  39. this.count > maximumTiles &&
  40. defined(tileToTrim)) {
  41. // Stop trimming after we process the last tile not used in the
  42. // current frame.
  43. keepTrimming = tileToTrim !== this._lastBeforeStartOfFrame;
  44. var previous = tileToTrim.replacementPrevious;
  45. if (tileToTrim.eligibleForUnloading) {
  46. tileToTrim.freeResources();
  47. remove(this, tileToTrim);
  48. }
  49. tileToTrim = previous;
  50. }
  51. };
  52. function remove(tileReplacementQueue, item) {
  53. var previous = item.replacementPrevious;
  54. var next = item.replacementNext;
  55. if (item === tileReplacementQueue._lastBeforeStartOfFrame) {
  56. tileReplacementQueue._lastBeforeStartOfFrame = next;
  57. }
  58. if (item === tileReplacementQueue.head) {
  59. tileReplacementQueue.head = next;
  60. } else {
  61. previous.replacementNext = next;
  62. }
  63. if (item === tileReplacementQueue.tail) {
  64. tileReplacementQueue.tail = previous;
  65. } else {
  66. next.replacementPrevious = previous;
  67. }
  68. item.replacementPrevious = undefined;
  69. item.replacementNext = undefined;
  70. --tileReplacementQueue.count;
  71. }
  72. /**
  73. * Marks a tile as rendered this frame and moves it before the first tile that was not rendered
  74. * this frame.
  75. *
  76. * @param {TileReplacementQueue} item The tile that was rendered.
  77. */
  78. TileReplacementQueue.prototype.markTileRendered = function(item) {
  79. var head = this.head;
  80. if (head === item) {
  81. if (item === this._lastBeforeStartOfFrame) {
  82. this._lastBeforeStartOfFrame = item.replacementNext;
  83. }
  84. return;
  85. }
  86. ++this.count;
  87. if (!defined(head)) {
  88. // no other tiles in the list
  89. item.replacementPrevious = undefined;
  90. item.replacementNext = undefined;
  91. this.head = item;
  92. this.tail = item;
  93. return;
  94. }
  95. if (defined(item.replacementPrevious) || defined(item.replacementNext)) {
  96. // tile already in the list, remove from its current location
  97. remove(this, item);
  98. }
  99. item.replacementPrevious = undefined;
  100. item.replacementNext = head;
  101. head.replacementPrevious = item;
  102. this.head = item;
  103. };
  104. return TileReplacementQueue;
  105. });