Skip to content

Commit 6f78cfb

Browse files
committed
Implement HTML5 WebGL context creation API. Add support to library_gl.js to manage multiple simultaneous GL contexts.
1 parent 64a2dea commit 6f78cfb

File tree

4 files changed

+313
-211
lines changed

4 files changed

+313
-211
lines changed

src/library_browser.js

+21-126
Original file line numberDiff line numberDiff line change
@@ -256,146 +256,41 @@ mergeInto(LibraryManager.library, {
256256
},
257257

258258
createContext: function(canvas, useWebGL, setInModule, webGLContextAttributes) {
259-
#if !USE_TYPED_ARRAYS
260-
if (useWebGL) {
261-
Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)');
262-
return null;
263-
}
264-
#endif
265-
if (useWebGL && Module.ctx) return Module.ctx; // no need to recreate singleton GL context
259+
if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
266260

267261
var ctx;
268-
var errorInfo = '?';
269-
function onContextCreationError(event) {
270-
errorInfo = event.statusMessage || errorInfo;
271-
}
272-
try {
273-
if (useWebGL) {
274-
var contextAttributes = {
275-
antialias: false,
276-
alpha: false
277-
};
278-
279-
if (webGLContextAttributes) {
280-
for (var attribute in webGLContextAttributes) {
281-
contextAttributes[attribute] = webGLContextAttributes[attribute];
282-
}
283-
}
284-
285-
#if GL_TESTING
286-
contextAttributes.preserveDrawingBuffer = true;
287-
#endif
288-
289-
canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false);
290-
try {
291-
['experimental-webgl', 'webgl'].some(function(webglId) {
292-
return ctx = canvas.getContext(webglId, contextAttributes);
293-
});
294-
} finally {
295-
canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false);
296-
}
297-
} else {
298-
ctx = canvas.getContext('2d');
299-
}
300-
if (!ctx) throw ':(';
301-
} catch (e) {
302-
Module.print('Could not create canvas: ' + [errorInfo, e]);
303-
return null;
304-
}
262+
var contextHandle;
305263
if (useWebGL) {
306-
#if GL_DEBUG
307-
function wrapDebugGL(ctx) {
308-
309-
var printObjectList = [];
310-
311-
function prettyPrint(arg) {
312-
if (typeof arg == 'undefined') return '!UNDEFINED!';
313-
if (typeof arg == 'boolean') arg = arg + 0;
314-
if (!arg) return arg;
315-
var index = printObjectList.indexOf(arg);
316-
if (index >= 0) return '<' + arg + '|'; // + index + '>';
317-
if (arg.toString() == '[object HTMLImageElement]') {
318-
return arg + '\n\n';
319-
}
320-
if (arg.byteLength) {
321-
return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 400)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that
322-
var buf = new ArrayBuffer(32);
323-
var i8buf = new Int8Array(buf);
324-
var i16buf = new Int16Array(buf);
325-
var f32buf = new Float32Array(buf);
326-
switch(arg.toString()) {
327-
case '[object Uint8Array]':
328-
i8buf.set(arg.subarray(0, 32));
329-
break;
330-
case '[object Float32Array]':
331-
f32buf.set(arg.subarray(0, 5));
332-
break;
333-
case '[object Uint16Array]':
334-
i16buf.set(arg.subarray(0, 16));
335-
break;
336-
default:
337-
alert('unknown array for debugging: ' + arg);
338-
throw 'see alert';
339-
}
340-
var ret = '{' + arg.byteLength + ':\n';
341-
var arr = Array.prototype.slice.call(i8buf);
342-
ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n';
343-
arr = Array.prototype.slice.call(f32buf, 0, 8);
344-
ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}';
345-
return ret;
346-
}
347-
if (typeof arg == 'object') {
348-
printObjectList.push(arg);
349-
return '<' + arg + '|'; // + (printObjectList.length-1) + '>';
350-
}
351-
if (typeof arg == 'number') {
352-
if (arg > 0) return '0x' + arg.toString(16) + ' (' + arg + ')';
353-
}
354-
return arg;
355-
}
264+
// For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
265+
var contextAttributes = {
266+
antialias: false,
267+
alpha: false
268+
};
356269

357-
var wrapper = {};
358-
for (var prop in ctx) {
359-
(function(prop) {
360-
switch (typeof ctx[prop]) {
361-
case 'function': {
362-
wrapper[prop] = function gl_wrapper() {
363-
var printArgs = Array.prototype.slice.call(arguments).map(prettyPrint);
364-
dump('[gl_f:' + prop + ':' + printArgs + ']\n');
365-
var ret = ctx[prop].apply(ctx, arguments);
366-
if (typeof ret != 'undefined') {
367-
dump('[ gl:' + prop + ':return:' + prettyPrint(ret) + ']\n');
368-
}
369-
return ret;
370-
}
371-
break;
372-
}
373-
case 'number': case 'string': {
374-
wrapper.__defineGetter__(prop, function() {
375-
//dump('[gl_g:' + prop + ':' + ctx[prop] + ']\n');
376-
return ctx[prop];
377-
});
378-
wrapper.__defineSetter__(prop, function(value) {
379-
dump('[gl_s:' + prop + ':' + value + ']\n');
380-
ctx[prop] = value;
381-
});
382-
break;
383-
}
384-
}
385-
})(prop);
270+
if (webGLContextAttributes) {
271+
for (var attribute in webGLContextAttributes) {
272+
contextAttributes[attribute] = webGLContextAttributes[attribute];
386273
}
387-
return wrapper;
388274
}
275+
#if GL_TESTING
276+
contextAttributes.preserveDrawingBuffer = true;
389277
#endif
390-
// possible GL_DEBUG entry point: ctx = wrapDebugGL(ctx);
391278

279+
contextHandle = GL.createContext(canvas, contextAttributes);
280+
ctx = GL.getContext(contextHandle).GLctx;
392281
// Set the background of the WebGL canvas to black
393282
canvas.style.backgroundColor = "black";
283+
} else {
284+
ctx = canvas.getContext('2d');
394285
}
286+
287+
if (!ctx) return null;
288+
395289
if (setInModule) {
396290
if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
291+
397292
Module.ctx = ctx;
398-
if (useWebGL) GLctx = ctx;
293+
if (useWebGL) GL.makeContextCurrent(contextHandle);
399294
Module.useWebGL = useWebGL;
400295
Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
401296
Browser.init();

0 commit comments

Comments
 (0)