All files / engine/Source/Scene TileReplacementQueue.js

100% Statements 48/48
100% Branches 22/22
100% Functions 5/5
100% Lines 48/48

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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