|
138 | 138 | return value === undefined ? defaultValue : value;
|
139 | 139 | }
|
140 | 140 |
|
| 141 | + function errorDisposedContext(fnName) { |
| 142 | + return function() { |
| 143 | + throw new Error(`tried to call ${fnName} on disposed context`); |
| 144 | + }; |
| 145 | + } |
| 146 | + |
141 | 147 | class DefaultCompositor {
|
142 | 148 | constructor(canvas) {
|
143 | 149 | this._ctx = canvas.getContext('2d');
|
|
172 | 178 | 0, maxHeight - height, width, height, // src rect
|
173 | 179 | 0, 0, width, height); // dest rect
|
174 | 180 | }
|
| 181 | + dispose() { |
| 182 | + } |
175 | 183 | }
|
176 | 184 |
|
177 | 185 | class VirtualWebGLContext {
|
178 |
| - constructor(canvas, contextAttributes = {}, compositor) { |
| 186 | + constructor(canvas, contextAttributes = {}, compositor, disposeHelper) { |
179 | 187 | const gl = sharedWebGLContext;
|
180 | 188 | this.canvas = canvas;
|
181 | 189 | // Should use Symbols or someting to hide these variables from the outside.
|
182 | 190 |
|
183 | 191 | this._compositor = compositor;
|
| 192 | + this._disposeHelper = disposeHelper; |
184 | 193 | this._extensions = {};
|
185 | 194 | // based on context attributes and canvas.width, canvas.height
|
186 | 195 | // create a texture and framebuffer
|
|
233 | 242 | this._defaultVertexArray = this._state.vertexArray;
|
234 | 243 | }
|
235 | 244 | }
|
| 245 | + dispose() { |
| 246 | + this._disposeHelper(); |
| 247 | + const gl = sharedWebGLContext; |
| 248 | + gl.deleteFramebuffer(this._drawingbufferFramebuffer); |
| 249 | + gl.deleteTexture(this._drawingbufferTexture); |
| 250 | + if (this._depthRenderbuffer) { |
| 251 | + gl.deleteRenderbuffer(this._depthRenderbuffer); |
| 252 | + } |
| 253 | + if (this._compositor.dispose) { |
| 254 | + this._compositor.dispose(); |
| 255 | + } |
| 256 | + for (const [key, value] of Object.entries(this)) { |
| 257 | + if (typeof value === 'function') { |
| 258 | + this[key] = errorDisposedContext(key); |
| 259 | + } |
| 260 | + } |
| 261 | + for (const [key, value] of Object.entries(VirtualWebGLContext.prototype)) { |
| 262 | + if (typeof value === 'function') { |
| 263 | + this[key] = errorDisposedContext(key); |
| 264 | + } |
| 265 | + } |
| 266 | + } |
236 | 267 | get drawingBufferWidth() {
|
237 | 268 | return this.canvas.width;
|
238 | 269 | }
|
|
691 | 722 | }
|
692 | 723 |
|
693 | 724 | const compositor = settings.compositorCreator(canvas, type, contextAttributes) || new DefaultCompositor(canvas, type, contextAttributes);
|
694 |
| - const newVirtualCtx = new VirtualWebGLContext(canvas, contextAttributes, compositor); |
| 725 | + const newVirtualCtx = new VirtualWebGLContext(canvas, contextAttributes, compositor, () => { |
| 726 | + canvasToVirtualContextMap.delete(canvas); |
| 727 | + }); |
695 | 728 | canvasToVirtualContextMap.set(canvas, newVirtualCtx);
|
696 | 729 |
|
697 | 730 | return newVirtualCtx;
|
|
0 commit comments