| #include <emscripten/html5_webgl.h> |
| #include <emscripten/html5.h> |
| #include <webgl/webgl2.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| GLuint compile_shader(GLenum shaderType, const char *src) |
| { |
| GLuint shader = glCreateShader(shaderType); |
| glShaderSource(shader, 1, &src, NULL); |
| glCompileShader(shader); |
| return shader; |
| } |
| |
| GLuint create_program(GLuint vertexShader, GLuint fragmentShader) |
| { |
| GLuint program = glCreateProgram(); |
| glAttachShader(program, vertexShader); |
| glAttachShader(program, fragmentShader); |
| glBindAttribLocation(program, 0, "apos"); |
| glBindAttribLocation(program, 1, "acolor"); |
| glLinkProgram(program); |
| return program; |
| } |
| |
| int main() |
| { |
| EmscriptenWebGLContextAttributes attrs; |
| emscripten_webgl_init_context_attributes(&attrs); |
| attrs.majorVersion = 2; |
| attrs.proxyContextToMainThread = EMSCRIPTEN_WEBGL_CONTEXT_PROXY_FALLBACK; |
| attrs.renderViaOffscreenBackBuffer = EM_TRUE; |
| EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context("#canvas", &attrs); |
| emscripten_webgl_make_context_current(context); |
| |
| // Test emscripten_webgl_get_supported_extensions() API |
| char *extensions = emscripten_webgl_get_supported_extensions(); |
| assert(extensions); |
| assert(strlen(extensions) > 0); |
| assert(strstr(extensions, "WEBGL") != 0); |
| free(extensions); |
| |
| // Test emscripten_webgl_get_parameter_d() API |
| assert(emscripten_webgl_get_parameter_d(GL_BLUE_BITS) == 8); |
| |
| // Test emscripten_webgl_get_parameter_o() API |
| GLuint buf; |
| glGenBuffers(1, &buf); |
| assert(buf != 0); |
| glBindBuffer(GL_ARRAY_BUFFER, buf); |
| assert(emscripten_webgl_get_parameter_o(GL_ARRAY_BUFFER_BINDING) == buf); |
| |
| // Test emscripten_webgl_get_parameter_utf8() API |
| char *version = emscripten_webgl_get_parameter_utf8(GL_VERSION); |
| assert(version); |
| assert(strstr(version, "WebGL") != 0); |
| free(version); |
| |
| // Test emscripten_webgl_get_parameter_i64v API |
| int64_t components = 0; |
| emscripten_webgl_get_parameter_i64v(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, &components); |
| assert(components > 0); |
| |
| // Test emscripten_webgl_get_parameter_v API with truncated read length |
| glViewport(1, 2, 3, 4); |
| int viewport[4] = { 0, 0, 0, 0 }; |
| int numElements = emscripten_webgl_get_parameter_v(GL_VIEWPORT, viewport, 3, EMSCRIPTEN_WEBGL_PARAM_TYPE_INT); |
| assert(numElements == 4); |
| assert(viewport[0] == 1); |
| assert(viewport[1] == 2); |
| assert(viewport[2] == 3); |
| assert(viewport[3] == 0); |
| |
| // Test emscripten_webgl_get_parameter_v API with full read length |
| numElements = emscripten_webgl_get_parameter_v(GL_VIEWPORT, viewport, 4, EMSCRIPTEN_WEBGL_PARAM_TYPE_INT); |
| assert(numElements == 4); |
| assert(viewport[0] == 1); |
| assert(viewport[1] == 2); |
| assert(viewport[2] == 3); |
| assert(viewport[3] == 4); |
| |
| // Test emscripten_webgl_get_vertex_attrib_d() API |
| glEnableVertexAttribArray(0); |
| double enabled = emscripten_webgl_get_vertex_attrib_d(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED); |
| assert(enabled == 1.0); |
| |
| // Test emscripten_webgl_get_vertex_attrib_v() API with truncated read length |
| glVertexAttrib4f(0, 0.2f, 0.4f, 0.6f, 0.8f); |
| float data[4] = { 0, 0, 0, 0 }; |
| numElements = emscripten_webgl_get_vertex_attrib_v(0, GL_CURRENT_VERTEX_ATTRIB, data, 2, EMSCRIPTEN_WEBGL_PARAM_TYPE_FLOAT); |
| assert(numElements == 4); |
| assert(data[0] == 0.2f); |
| assert(data[1] == 0.4f); |
| assert(data[2] == 0.0f); |
| assert(data[3] == 0.0f); |
| |
| // Test emscripten_webgl_get_vertex_attrib_v() API with full read length |
| numElements = emscripten_webgl_get_vertex_attrib_v(0, GL_CURRENT_VERTEX_ATTRIB, data, 4, EMSCRIPTEN_WEBGL_PARAM_TYPE_FLOAT); |
| assert(numElements == 4); |
| assert(data[0] == 0.2f); |
| assert(data[1] == 0.4f); |
| assert(data[2] == 0.6f); |
| assert(data[3] == 0.8f); |
| |
| // Test emscripten_webgl_get_vertex_attrib_o() API |
| glBufferData(GL_ARRAY_BUFFER, 4, data, GL_STATIC_DRAW); |
| glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, 0); |
| assert(emscripten_webgl_get_vertex_attrib_o(0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) == buf); |
| |
| static const char vertex_shader[] = |
| "#version 100\n" |
| "attribute vec4 apos;" |
| "attribute vec4 acolor;" |
| "uniform float vsUniformFloat;" |
| "varying vec4 color;" |
| "void main() {" |
| "color = acolor * vsUniformFloat;" |
| "gl_Position = apos;" |
| "}"; |
| GLuint vs = compile_shader(GL_VERTEX_SHADER, vertex_shader); |
| |
| // Test emscripten_webgl_get_shader_parameter_d() API |
| assert(emscripten_webgl_get_shader_parameter_d(vs, GL_DELETE_STATUS) == 0); |
| assert(emscripten_webgl_get_shader_parameter_d(vs, GL_COMPILE_STATUS) == 1); |
| assert(emscripten_webgl_get_shader_parameter_d(vs, GL_SHADER_TYPE) == GL_VERTEX_SHADER); |
| |
| // Test emscripten_webgl_get_shader_source_utf8() API |
| char *src = emscripten_webgl_get_shader_source_utf8(vs); |
| assert(src); |
| assert(strstr(src, "attribute") != 0); |
| free(src); |
| |
| static const char failing_shader[] = |
| "#version 100\n" |
| "attribute vec4 apos;" |
| "attr_error_ibute vec4 acolor;" |
| "varying vec4 color;" |
| "void main() {" |
| "color = acolor;" |
| "gl_Position = apos;" |
| "}"; |
| GLuint vs2 = compile_shader(GL_VERTEX_SHADER, failing_shader); |
| |
| // Test emscripten_webgl_get_shader_info_log_utf8() API |
| src = emscripten_webgl_get_shader_info_log_utf8(vs2); |
| assert(src); |
| assert(strstr(src, "attr_error_ibute") != 0); |
| free(src); |
| |
| static const char fragment_shader[] = |
| "#version 100\n" |
| "precision lowp float;" |
| "varying vec4 color;" |
| "uniform vec4 psUniformVec;" |
| "void main() {" |
| "gl_FragColor = color + psUniformVec;" |
| "}"; |
| GLuint fs = compile_shader(GL_FRAGMENT_SHADER, fragment_shader); |
| |
| // Test emscripten_webgl_get_shader_parameter_d() API |
| assert(emscripten_webgl_get_shader_parameter_d(fs, GL_DELETE_STATUS) == 0); |
| assert(emscripten_webgl_get_shader_parameter_d(fs, GL_COMPILE_STATUS) == 1); |
| assert(emscripten_webgl_get_shader_parameter_d(fs, GL_SHADER_TYPE) == GL_FRAGMENT_SHADER); |
| |
| // Test emscripten_webgl_get_shader_source_utf8() API |
| src = emscripten_webgl_get_shader_source_utf8(fs); |
| assert(src); |
| assert(strstr(src, "varying") != 0); |
| free(src); |
| |
| GLuint program = create_program(vs, fs); |
| |
| // Test emscripten_webgl_get_program_parameter_d() API |
| assert(emscripten_webgl_get_program_parameter_d(program, GL_ACTIVE_ATTRIBUTES) == 2); |
| |
| // Test emscripten_webgl_get_program_info_log_utf8() API |
| GLuint program2 = create_program(vs2, fs); |
| char *programLog = emscripten_webgl_get_program_info_log_utf8(program2); |
| assert(programLog); |
| // Firefox says "Must have a compiled vertex shader attached." |
| // Chrome says "invalid shaders" |
| // -> test that word "shader" is present |
| assert(strstr(programLog, "shader") != 0); |
| free(programLog); |
| |
| glUseProgram(program); |
| glUniform1f(glGetUniformLocation(program, "vsUniformFloat"), 2.f); |
| glUniform4f(glGetUniformLocation(program, "psUniformVec"), 1.f, 2.f, 3.f, 4.f); |
| |
| // Test emscripten_webgl_get_uniform_d() API |
| double vsUniformFloat = emscripten_webgl_get_uniform_d(program, glGetUniformLocation(program, "vsUniformFloat")); |
| assert(vsUniformFloat == 2.f); |
| |
| float psUniformVec[4] = { 0, 0, 0, 0 }; |
| |
| // Test emscripten_webgl_get_uniform_v() API truncated read |
| numElements = emscripten_webgl_get_uniform_v(program, glGetUniformLocation(program, "psUniformVec"), psUniformVec, 3, EMSCRIPTEN_WEBGL_PARAM_TYPE_FLOAT); |
| assert(numElements == 4); |
| assert(psUniformVec[0] == 1.0f); |
| assert(psUniformVec[1] == 2.0f); |
| assert(psUniformVec[2] == 3.0f); |
| assert(psUniformVec[3] == 0.0f); |
| |
| // Test emscripten_webgl_get_uniform_v() API full read |
| numElements = emscripten_webgl_get_uniform_v(program, glGetUniformLocation(program, "psUniformVec"), psUniformVec, 4, EMSCRIPTEN_WEBGL_PARAM_TYPE_FLOAT); |
| assert(numElements == 4); |
| assert(psUniformVec[0] == 1.0f); |
| assert(psUniformVec[1] == 2.0f); |
| assert(psUniformVec[2] == 3.0f); |
| assert(psUniformVec[3] == 4.0f); |
| |
| #ifdef REPORT_RESULT |
| REPORT_RESULT(0); |
| #endif |
| } |