summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_gl.js157
1 files changed, 124 insertions, 33 deletions
diff --git a/src/library_gl.js b/src/library_gl.js
index f6e0f974..826eb904 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -54,6 +54,40 @@ var LibraryGL = {
return false;
},
+ getSource: function(shader, count, string, length) {
+ var source = '';
+ for (var i = 0; i < count; ++i) {
+ var frag;
+ if (length) {
+ var len = {{{ makeGetValue('length', 'i*4', 'i32') }}};
+ if (len < 0) {
+ frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}});
+ } else {
+ frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}}, len);
+ }
+ } else {
+ frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}});
+ }
+ source += frag;
+ }
+ // Let's see if we need to enable the standard derivatives extension
+ type = Module.ctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */);
+ if (type == 0x8B30 /* GL_FRAGMENT_SHADER */) {
+ if (GL.findToken(source, "dFdx") ||
+ GL.findToken(source, "dFdy") ||
+ GL.findToken(source, "fwidth")) {
+ source = "#extension GL_OES_standard_derivatives : enable\n" + source;
+ var extension = Module.ctx.getExtension("OES_standard_derivatives");
+#if GL_DEBUG
+ if (!extension) {
+ Module.printErr("Shader attempts to use the standard derivatives extension which is not available.");
+ }
+#endif
+ }
+ }
+ return source;
+ },
+
computeImageSize: function(width, height, sizePerPixel, alignment) {
function roundedToNextMultipleOf(x, y) {
return Math.floor((x + y - 1) / y) * y
@@ -681,36 +715,7 @@ var LibraryGL = {
},
glShaderSource: function(shader, count, string, length) {
- var source = "";
- for (var i = 0; i < count; ++i) {
- var frag;
- if (length) {
- var len = {{{ makeGetValue('length', 'i*4', 'i32') }}};
- if (len < 0) {
- frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}});
- } else {
- frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}}, len);
- }
- } else {
- frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}});
- }
- source += frag;
- }
- // Let's see if we need to enable the standard derivatives extension
- type = Module.ctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */);
- if (type == 0x8B30 /* GL_FRAGMENT_SHADER */) {
- if (GL.findToken(source, "dFdx") ||
- GL.findToken(source, "dFdy") ||
- GL.findToken(source, "fwidth")) {
- source = "#extension GL_OES_standard_derivatives : enable\n" + source;
- var extension = Module.ctx.getExtension("OES_standard_derivatives");
-#if GL_DEBUG
- if (!extension) {
- Module.printErr("Shader attempts to use the standard derivatives extension which is not available.");
- }
-#endif
- }
- }
+ var source = GL.getSource(shader, count, string, length);
Module.ctx.shaderSource(GL.shaders[shader], source);
},
@@ -862,7 +867,7 @@ var LibraryGL = {
// GL emulation: provides misc. functionality not present in OpenGL ES 2.0 or WebGL
- $GLEmulation__deps: ['glCreateShader', 'glShaderSource', 'glCompileShader', 'glCreateProgram', 'glDeleteShader', 'glDeleteProgram', 'glAttachShader', 'glActiveTexture', 'glGetShaderiv', 'glGetProgramiv', 'glLinkProgram'],
+ $GLEmulation__deps: ['glCreateShader', 'glShaderSource', 'glCompileShader', 'glCreateProgram', 'glDeleteShader', 'glDeleteProgram', 'glAttachShader', 'glActiveTexture', 'glGetShaderiv', 'glGetProgramiv', 'glLinkProgram', 'glGetProgramInfoLog', 'glGetShaderInfoLog'],
$GLEmulation__postset: 'GLEmulation.init();',
$GLEmulation: {
init: function() {
@@ -871,9 +876,12 @@ var LibraryGL = {
_glEnable = function(cap) {
if (cap == 0x0DE1) return; // GL_TEXTURE_2D
if (cap == 0x0B20) return; // GL_LINE_SMOOTH
+ if (cap == 0x0B60) return; // GL_FOG
Module.ctx.enable(cap);
};
_glDisable = function(cap) {
+ if (cap == 0x0DE1) return; // GL_TEXTURE_2D
+ if (cap == 0x0B20) return; // GL_LINE_SMOOTH
if (cap == 0x0B60) return; // GL_FOG
Module.ctx.disable(cap);
};
@@ -884,6 +892,70 @@ var LibraryGL = {
}
glGetIntegerv(pname, params);
};
+ // Do some automatic rewriting to work around GLSL differences. Note that this must be done in
+ // tandem with the rest of the program, by itself it cannot suffice.
+ // Note that we need to remember shader types for this rewriting, saving sources makes it easier to debug.
+ GL.shaderTypes = {};
+ GL.shaderSources = {};
+ GL.shaderOriginalSources = {};
+ var glCreateShader = _glCreateShader;
+ _glCreateShader = function(shaderType) {
+ var id = glCreateShader(shaderType);
+ GL.shaderTypes[id] = shaderType;
+ return id;
+ };
+ var glShaderSource = _glShaderSource;
+ _glShaderSource = function(shader, count, string, length) {
+ var source = GL.getSource(shader, count, string, length);
+ GL.shaderOriginalSources[shader] = source;
+ if (GL.shaderTypes[shader] == Module.ctx.VERTEX_SHADER) {
+ if (source.indexOf('ftransform()') >= 0) {
+ // Replace ftransform() with explicit project/modelview transforms, and add position and matrix info.
+ source = 'attribute vec3 a_position; \n\
+ uniform mat4 u_modelView; \n\
+ uniform mat4 u_projection; \n' +
+ source.replace(/ftransform\(\)/g, 'u_projection * u_modelView * vec4(a_position, 1.0)')
+ .replace(/gl_Vertex/g, 'a_position')
+ .replace(/gl_ModelViewMatrixTranspose\[2\]/g, 'vec3(u_modelView[0][0], u_modelView[1][0], u_modelView[2][0])'); // XXX extremely inefficient
+ }
+ if (source.indexOf('gl_TexCoord[0]') >= 0) {
+ // XXX To handle both regular texture mapping and cube mapping, we use vec3 for tex coordinates.
+ source = 'attribute vec3 a_texCoord; \n\
+ varying vec3 v_texCoord; \n' +
+ source.replace(/gl_TexCoord\[0\]/g, 'v_texCoord').replace(/gl_MultiTexCoord0/g, 'a_texCoord');
+ }
+ if (source.indexOf('gl_Color') >= 0) {
+ source = 'attribute vec4 a_color; \n\
+ varying vec4 v_color; \n' +
+ source.replace(/gl_Color/g, 'a_color').replace(/gl_FrontColor/g, 'v_color');
+ }
+ if (source.indexOf('gl_FogFragCoord') >= 0) {
+ source = 'varying float v_fogCoord; \n' +
+ source.replace(/gl_FogFragCoord/g, 'v_fogCoord');
+ }
+ } else { // Fragment shader
+ if (source.indexOf('gl_TexCoord[0]') >= 0) {
+ source = 'varying vec3 v_texCoord; \n' + source.replace(/gl_TexCoord\[0\]/g, 'v_texCoord');
+ }
+ if (source.indexOf('gl_Color') >= 0) {
+ source = 'varying vec4 v_color; \n' + source.replace(/gl_Color/g, 'v_color');
+ }
+ source = 'precision mediump float;\n' + source;
+ }
+ GL.shaderSources[shader] = source;
+ Module.ctx.shaderSource(GL.shaders[shader], source);
+ };
+ var glCompileShader = _glCompileShader;
+ _glCompileShader = function(shader) {
+ Module.ctx.compileShader(GL.shaders[shader]);
+ if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) {
+ console.log('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader]));
+ console.log('Type: ' + GL.shaderTypes[shader]);
+ console.log('Original source: ' + GL.shaderOriginalSources[shader]);
+ console.log('Source: ' + GL.shaderSources[shader]);
+ throw 'Shader compilation halt';
+ }
+ };
},
procReplacements: {
@@ -909,13 +981,31 @@ var LibraryGL = {
glGetObjectParameterivARB: function(id, type, result) {
if (GL.programs[id]) {
+ if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB
+ {{{ makeSetValue('result', '0', 'Module.ctx.getProgramInfoLog(GL.programs[id]).length', 'i32') }}};
+ return;
+ }
_glGetProgramiv(id, type, result);
} else if (GL.shaders[id]) {
+ if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB
+ {{{ makeSetValue('result', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[id]).length', 'i32') }}};
+ return;
+ }
_glGetShaderiv(id, type, result);
} else {
console.log('WARNING: getObjectParameterivARB received invalid id: ' + id);
}
},
+
+ glGetInfoLogARB: function(id, maxLength, length, infoLog) {
+ if (GL.programs[id]) {
+ _glGetProgramInfoLog(id, maxLength, length, infoLog);
+ } else if (GL.shaders[id]) {
+ _glGetShaderInfoLog(id, maxLength, length, infoLog);
+ } else {
+ console.log('WARNING: getObjectParameterivARB received invalid id: ' + id);
+ }
+ }
},
getProcAddress: function(name_) {
@@ -923,7 +1013,7 @@ var LibraryGL = {
var func = GLEmulation.procs[name_];
if (!func) {
try {
- func = eval('_' + name_);
+ func = eval('_' + name_); // XXX closure, need Module. and for them to be exported
} catch(e) {
console.log('WARNING: getProcAddress failed for ' + name_);
func = function() {
@@ -1070,6 +1160,7 @@ var LibraryGL = {
initted: false,
init: function() {
Module.printErr('WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports');
+ GL.immediate.initted = true;
// Buffers for data
this.tempData = new Float32Array(this.maxElements);
@@ -1291,7 +1382,7 @@ var LibraryGL = {
},
glPopMatrix: function() {
- GL.immediate.matrix[currentMatrix] = GL.immediate.matrixStack[GL.immediate.currentMatrix].pop();
+ GL.immediate.matrix[GL.immediate.currentMatrix] = GL.immediate.matrixStack[GL.immediate.currentMatrix].pop();
},
glLoadIdentity__deps: ['$GL', '$GLImmediateSetup'],