智慧水务管理系统 - 精河县供水工程综合管理平台

SharedContext.js 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import clone from "../Core/clone.js";
  2. import destroyObject from "../Core/destroyObject.js";
  3. import DeveloperError from "../Core/DeveloperError.js";
  4. import Context from "./Context.js";
  5. /**
  6. * Enables a single WebGL context to be used by any number of {@link Scene}s.
  7. * You can pass a SharedContext in place of a {@link ContextOptions} to the constructors of {@link Scene}, {@link CesiumWidget}, and {@link Viewer}.
  8. * {@link Primitive}s associated with the shared WebGL context can be displayed in any Scene that uses the same context.
  9. * The context renders each Scene to an off-screen canvas, then blits the result to that Scene's on-screen canvas.
  10. *
  11. * @private
  12. * @alias SharedContext
  13. * @constructor
  14. *
  15. * @param {object} [options] Object with the following properties:
  16. * @param {ContextOptions} [options.contextOptions] Context and WebGL creation properties.
  17. * @param {boolean} [options.autoDestroy=true] Destroys this context and all of its WebGL resources after all Scenes using the context are destroyed.
  18. * @see {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}
  19. *
  20. * @example
  21. * // Create two Scenes sharing a single WebGL context
  22. * const context = new Cesium.SharedContext();
  23. * const scene1 = new Cesium.Scene({
  24. * canvas: canvas1,
  25. * contextOptions: context,
  26. * });
  27. * const scene2 = new Cesium.Scene({
  28. * canvas: canvas2,
  29. * contextOptions: context,
  30. * });
  31. */
  32. function SharedContext(options) {
  33. this._autoDestroy = options?.autoDestroy ?? true;
  34. this._canvas = document.createElement("canvas");
  35. this._context = new Context(this._canvas, clone(options?.contextOptions));
  36. this._canvases = [];
  37. }
  38. /**
  39. * Creates an instance of {@link Context} that manages the shared WebGL context for a specific canvas.
  40. * @param {HTMLCanvasElement} canvas The canvas element to which the context will be associated
  41. * @returns {Context} The created context instance
  42. * @private
  43. */
  44. SharedContext.prototype.createSceneContext = function (canvas) {
  45. const context2d = canvas.getContext("2d", { alpha: true });
  46. //>>includeStart('debug', pragmas.debug);
  47. if (!context2d) {
  48. throw new DeveloperError(
  49. "canvas used with SharedContext must provide a 2d context",
  50. );
  51. }
  52. if (this._canvases.includes(canvas)) {
  53. throw new DeveloperError("canvas is already associated with a scene");
  54. }
  55. //>>includeEnd('debug');
  56. const sharedContext = this;
  57. sharedContext._canvases.push(canvas);
  58. let isDestroyed = false;
  59. const destroy = function () {
  60. isDestroyed = true;
  61. const index = sharedContext._canvases.indexOf(canvas);
  62. if (-1 !== index) {
  63. sharedContext._canvases.splice(index, 1);
  64. if (sharedContext._autoDestroy && sharedContext._canvases.length === 0) {
  65. sharedContext.destroy();
  66. }
  67. }
  68. };
  69. const beginFrame = function () {
  70. // Ensure the off-screen canvas is at least as large as the on-screen canvas.
  71. const sharedCanvas = sharedContext._context.canvas;
  72. const width = this.drawingBufferWidth;
  73. if (sharedCanvas.width < width) {
  74. sharedCanvas.width = width;
  75. }
  76. const height = this.drawingBufferHeight;
  77. if (sharedCanvas.height < height) {
  78. sharedCanvas.height = height;
  79. }
  80. };
  81. const endFrame = function () {
  82. // Blit the image from the off-screen canvas to the on-screen canvas.
  83. const w = this.drawingBufferWidth;
  84. const h = this.drawingBufferHeight;
  85. const yOffset = sharedContext._context.canvas.height - h; // drawImage has top as Y=0, GL has bottom as Y=0
  86. context2d.drawImage(
  87. sharedContext._context.canvas,
  88. 0,
  89. yOffset,
  90. w,
  91. h,
  92. 0,
  93. 0,
  94. w,
  95. h,
  96. );
  97. // Do normal post-frame cleanup.
  98. sharedContext._context.endFrame();
  99. };
  100. const proxy = new Proxy(this._context, {
  101. get(target, prop, receiver) {
  102. if (prop === "isDestroyed") {
  103. return function () {
  104. return isDestroyed;
  105. };
  106. } else if (isDestroyed) {
  107. //>>includeStart('debug', pragmas.debug);
  108. throw new DeveloperError(
  109. "This object was destroyed, i.e., destroy() was called.",
  110. );
  111. //>>includeEnd('debug');
  112. }
  113. switch (prop) {
  114. case "_canvas":
  115. return canvas;
  116. case "destroy":
  117. return destroy;
  118. case "drawingBufferWidth":
  119. return canvas.width;
  120. case "drawingBufferHeight":
  121. return canvas.height;
  122. case "beginFrame":
  123. return beginFrame;
  124. case "endFrame":
  125. return endFrame;
  126. default:
  127. return Reflect.get(target, prop, receiver);
  128. }
  129. },
  130. });
  131. return proxy;
  132. };
  133. /**
  134. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  135. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  136. * <br /><br />
  137. * Once an object is destroyed, it should not be used; calling any function other than
  138. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  139. * assign the return value (<code>undefined</code>) to the object as done in the example.
  140. * <br /><br />
  141. * By default, a SharedContext is destroyed automatically once the last Scene using it is destroyed, in which case it
  142. * is not necessary to call this method directly.
  143. *
  144. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  145. *
  146. * @example
  147. * context = context && context.destroy();
  148. *
  149. * @see SharedContext#isDestroyed
  150. */
  151. SharedContext.prototype.destroy = function () {
  152. this._context.destroy();
  153. destroyObject(this);
  154. };
  155. /**
  156. * Returns true if this object was destroyed; otherwise, false.
  157. * <br /><br />
  158. * If this object was destroyed, it should not be used; calling any function other than
  159. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  160. *
  161. * @returns {boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  162. *
  163. * @see SharedContext#destroy
  164. */
  165. SharedContext.prototype.isDestroyed = function () {
  166. return false;
  167. };
  168. export default SharedContext;