diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/aniso.c | 3 | ||||
-rw-r--r-- | tests/cases/caall.ll | 2 | ||||
-rw-r--r-- | tests/cubegeom.c | 6 | ||||
-rw-r--r-- | tests/mmap_file.c | 27 | ||||
-rw-r--r-- | tests/test_browser.py | 53 | ||||
-rw-r--r-- | tests/test_core.py | 178 | ||||
-rw-r--r-- | tests/test_other.py | 44 | ||||
-rw-r--r-- | tests/test_sanity.py | 6 | ||||
-rw-r--r-- | tests/test_webgl_context_attributes_common.c | 262 | ||||
-rw-r--r-- | tests/test_webgl_context_attributes_glfw.c | 47 | ||||
-rw-r--r-- | tests/test_webgl_context_attributes_glut.c | 42 | ||||
-rw-r--r-- | tests/test_webgl_context_attributes_sdl.c | 50 |
12 files changed, 651 insertions, 69 deletions
diff --git a/tests/aniso.c b/tests/aniso.c index e8d7bd3f..f1674cad 100644 --- a/tests/aniso.c +++ b/tests/aniso.c @@ -66,6 +66,9 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_EXT_texture_filter_anisotropic")); + const char *vendor = (const char *)glGetString(GL_VENDOR); + printf("vendor: %s\n", vendor); + GLint aniso; glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso); printf("Max anisotropy: %d (using that)\n", aniso); diff --git a/tests/cases/caall.ll b/tests/cases/caall.ll index 313116e6..5b8f7f29 100644 --- a/tests/cases/caall.ll +++ b/tests/cases/caall.ll @@ -18,7 +18,7 @@ entry: define (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 %x) { entry: %ret = inttoptr i32 0 to (i32*)** - ret %ret + ret (i32*)** %ret } ; [#uses=1] diff --git a/tests/cubegeom.c b/tests/cubegeom.c index fac0da2b..96d56339 100644 --- a/tests/cubegeom.c +++ b/tests/cubegeom.c @@ -194,8 +194,14 @@ int main(int argc, char *argv[]) // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound glTexCoordPointer(2, GL_FLOAT, 32, (void*)16); + glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build glTexCoordPointer(2, GL_SHORT, 32, (void*)24); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_SIZE, &tempInt); assert(tempInt == 2); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_TYPE, &tempInt); assert(tempInt == GL_SHORT); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_STRIDE, &tempInt); assert(tempInt == 32); + glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &tempPtr); assert(tempPtr == (void *)24); + glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup glNormalPointer(GL_BYTE, 32, (void*)12); glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28); diff --git a/tests/mmap_file.c b/tests/mmap_file.c new file mode 100644 index 00000000..6eed95e0 --- /dev/null +++ b/tests/mmap_file.c @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <sys/mman.h> +#include <emscripten.h> +#include <string.h> +#include <assert.h> + +int main() { + printf("*\n"); + FILE *f = fopen("data.dat", "r"); + char *m; + m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 0); + for (int i = 0; i < 20; i++) putchar(m[i]); + assert(!strncmp(m, "data from the file .", 20)); + munmap(m, 9000); + printf("\n"); + m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 5); + for (int i = 0; i < 20; i++) putchar(m[i]); + assert(!strncmp(m, "from the file ......", 20)); + munmap(m, 9000); + printf("\n*\n"); + +#ifdef REPORT_RESULT + int result = 1; + REPORT_RESULT(); +#endif + return 0; +} diff --git a/tests/test_browser.py b/tests/test_browser.py index be23074a..d52f109f 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -338,7 +338,7 @@ If manually bisecting: ("somefile.txt@/directory/file.txt", "/directory/file.txt"), ("somefile.txt@/directory/file.txt", "directory/file.txt"), (absolute_src_path + "@/directory/file.txt", "directory/file.txt")] - + for test in test_cases: (srcpath, dstpath) = test print 'Testing', srcpath, dstpath @@ -346,6 +346,11 @@ If manually bisecting: Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', srcpath, '-o', 'page.html']).communicate() self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1') + # Test that '--no-heap-copy' works. + make_main('somefile.txt') + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'somefile.txt', '--no-heap-copy', '-o', 'page.html']).communicate() + self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1') + # By absolute path make_main('somefile.txt') # absolute becomes relative @@ -869,6 +874,48 @@ keydown(100);keyup(100); // trigger the end def test_glut_wheelevents(self): self.btest('glut_wheelevents.c', '1') + def test_webgl_context_attributes(self): + # Javascript code to check the attributes support we want to test in the WebGL implementation + # (request the attribute, create a context and check its value afterwards in the context attributes). + # Tests will succeed when an attribute is not supported. + open(os.path.join(self.get_dir(), 'check_webgl_attributes_support.js'), 'w').write(''' + mergeInto(LibraryManager.library, { + webglAntialiasSupported: function() { + canvas = document.createElement('canvas'); + context = canvas.getContext('experimental-webgl', {antialias: true}); + attributes = context.getContextAttributes(); + return attributes.antialias; + }, + webglDepthSupported: function() { + canvas = document.createElement('canvas'); + context = canvas.getContext('experimental-webgl', {depth: true}); + attributes = context.getContextAttributes(); + return attributes.depth; + }, + webglStencilSupported: function() { + canvas = document.createElement('canvas'); + context = canvas.getContext('experimental-webgl', {stencil: true}); + attributes = context.getContextAttributes(); + return attributes.stencil; + } + }); + ''') + + # Copy common code file to temporary directory + filepath = path_from_root('tests/test_webgl_context_attributes_common.c') + temp_filepath = os.path.join(self.get_dir(), os.path.basename(filepath)) + shutil.copyfile(filepath, temp_filepath) + + # perform tests with attributes activated + self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED']) + self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED']) + self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED']) + + # perform tests with attributes desactivated + self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js']) + self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js']) + self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js']) + def test_emscripten_get_now(self): self.btest('emscripten_get_now.cpp', '1') @@ -1524,3 +1571,7 @@ keydown(100);keyup(100); // trigger the end Popen([PYTHON, EMCC, path_from_root('tests', 'browser_module.cpp'), '-o', 'module.js', '-O2', '-s', 'SIDE_MODULE=1', '-s', 'DLOPEN_SUPPORT=1', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two"]']).communicate() self.btest('browser_main.cpp', args=['-O2', '-s', 'MAIN_MODULE=1', '-s', 'DLOPEN_SUPPORT=1'], expected='8') + def test_mmap_file(self): + open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000)) + for extra_args in [[], ['--no-heap-copy']]: + self.btest(path_from_root('tests', 'mmap_file.c'), expected='1', args=['--preload-file', 'data.dat'] + extra_args) diff --git a/tests/test_core.py b/tests/test_core.py index ca81102d..a19cde10 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2975,6 +2975,23 @@ Exiting setjmp function, level: 0, prev_jmp: -1 ''' self.do_run(src, '3.14159') + def test_iswdigit(self): + if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc') + + src = ''' + #include <stdio.h> + #include <cctype> + #include <cwctype> + + int main() { + using namespace std; + printf("%d ", isdigit('0')); + printf("%d ", iswdigit(L'0')); + return 0; + } + ''' + self.do_run(src, '1 1') + def test_polymorph(self): if self.emcc_args is None: return self.skip('requires emcc') src = ''' @@ -7294,6 +7311,18 @@ date: 18.07.2013w; day 18, month 7, year 2013, extra: 201, 3 ''' self.do_run(src, '4779 4779') + def test_sscanf_float(self): + src = r''' + #include "stdio.h" + + int main(){ + float f1, f2, f3, f4, f5, f6, f7, f8, f9; + sscanf("0.512 0.250x5.129_-9.98 1.12*+54.32E3 +54.32E3^87.5E-3 87.5E-3$", "%f %fx%f_%f %f*%f %f^%f %f$", &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9); + printf("\n%f, %f, %f, %f, %f, %f, %f, %f, %f\n", f1, f2, f3, f4, f5, f6, f7, f8, f9); + } + ''' + self.do_run(src, '\n0.512000, 0.250000, 5.129000, -9.980000, 1.120000, 54320.000000, 54320.000000, 0.087500, 0.087500\n') + def test_langinfo(self): src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read() expected = open(path_from_root('tests', 'langinfo', 'output.txt'), 'r').read() @@ -8591,30 +8620,13 @@ void*:16 def test_mmap_file(self): if self.emcc_args is None: return self.skip('requires emcc') - self.emcc_args += ['--embed-file', 'data.dat'] + for extra_args in [[], ['--no-heap-copy']]: + self.emcc_args += ['--embed-file', 'data.dat'] + extra_args - open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000)) + open(self.in_dir('data.dat'), 'w').write('data from the file ' + ('.' * 9000)) - src = r''' - #include <stdio.h> - #include <sys/mman.h> - - int main() { - printf("*\n"); - FILE *f = fopen("data.dat", "r"); - char *m; - m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 0); - for (int i = 0; i < 20; i++) putchar(m[i]); - munmap(m, 9000); - printf("\n"); - m = (char*)mmap(NULL, 9000, PROT_READ, MAP_PRIVATE, fileno(f), 5); - for (int i = 0; i < 20; i++) putchar(m[i]); - munmap(m, 9000); - printf("\n*\n"); - return 0; - } - ''' - self.do_run(src, '*\ndata from the file .\nfrom the file ......\n*\n') + src = open(path_from_root('tests', 'mmap_file.c')).read() + self.do_run(src, '*\ndata from the file .\nfrom the file ......\n*\n') def test_cubescript(self): if self.emcc_args is None: return self.skip('requires emcc') @@ -8657,6 +8669,128 @@ void*:16 main = main[:main.find('\n}')] assert main.count('\n') == 7, 'must not emit too many postSets: %d' % main.count('\n') + def test_simd(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') + if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate + src = r''' +#include <stdio.h> + +#include <emscripten/vector.h> + +static inline float32x4 __attribute__((always_inline)) +_mm_set_ps(const float __Z, const float __Y, const float __X, const float __W) +{ + return (float32x4){ __W, __X, __Y, __Z }; +} + +static __inline__ float32x4 __attribute__((__always_inline__)) +_mm_setzero_ps(void) +{ + return (float32x4){ 0.0, 0.0, 0.0, 0.0 }; +} + +int main(int argc, char **argv) { + float data[8]; + for (int i = 0; i < 32; i++) data[i] = (1+i+argc)*(2+i+argc*argc); // confuse optimizer + { + float32x4 *a = (float32x4*)&data[0]; + float32x4 *b = (float32x4*)&data[4]; + float32x4 c, d; + c = *a; + d = *b; + printf("1floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); + c = c+d; + printf("2floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); + d = c*d; + printf("3floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); + c = _mm_setzero_ps(); + printf("zeros %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3]); + } + { + uint32x4 *a = (uint32x4*)&data[0]; + uint32x4 *b = (uint32x4*)&data[4]; + uint32x4 c, d, e, f; + c = *a; + d = *b; + printf("4uints! %d, %d, %d, %d %d, %d, %d, %d\n", c[0], c[1], c[2], c[3], d[0], d[1], d[2], d[3]); + e = c+d; + f = c-d; + printf("5uints! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]); + e = c&d; + f = c|d; + e = ~c&d; + f = c^d; + printf("5uintops! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]); + } + { + float32x4 c, d, e, f; + c = _mm_set_ps(9.0, 4.0, 0, -9.0); + d = _mm_set_ps(10.0, 14.0, -12, -2.0); + printf("6floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); + printf("7calcs: %d\n", emscripten_float32x4_signmask(c)); // TODO: just not just compilation but output as well + } + + return 0; +} + ''' + + self.do_run(src, '''1floats! 6, 12, 20, 30 42, 56, 72, 90 +2floats! 48, 68, 92, 120 42, 56, 72, 90 +3floats! 48, 68, 92, 120 2016, 3808, 6624, 10800 +zeros 0, 0, 0, 0 +4uints! 1086324736, 1094713344, 1101004800, 1106247680 1109917696, 1113587712, 1116733440, 1119092736 +5uints! -2098724864, -2086666240, -2077229056, -2069626880 -23592960, -18874368, -15728640, -12845056 +5uintops! 36175872, 35651584, 34603008, 33816576 48758784, 52428800, 53477376, 54788096 +6floats! -9, 0, 4, 9 -2, -12, 14, 10 +''') + + def test_simd2(self): + if Settings.ASM_JS: Settings.ASM_JS = 2 # does not validate + + self.do_run(r''' + #include <stdio.h> + + typedef float __m128 __attribute__ ((__vector_size__ (16))); + + static inline __m128 __attribute__((always_inline)) + _mm_set_ps(const float __Z, const float __Y, const float __X, const float __W) + { + return (__m128){ __W, __X, __Y, __Z }; + } + + static inline void __attribute__((always_inline)) + _mm_store_ps(float *__P, __m128 __A) + { + *(__m128 *)__P = __A; + } + + static inline __m128 __attribute__((always_inline)) + _mm_add_ps(__m128 __A, __m128 __B) + { + return __A + __B; + } + + using namespace std; + + int main(int argc, char ** argv) { + float __attribute__((__aligned__(16))) ar[4]; + __m128 v1 = _mm_set_ps(9.0, 4.0, 0, -9.0); + __m128 v2 = _mm_set_ps(7.0, 3.0, 2.5, 1.0); + __m128 v3 = _mm_add_ps(v1, v2); + _mm_store_ps(ar, v3); + + for (int i = 0; i < 4; i++) { + printf("%f\n", ar[i]); + } + + return 0; + } + ''', '''-8.000000 +2.500000 +7.000000 +16.000000 +''') + def test_gcc_unmangler(self): Settings.NAMED_GLOBALS = 1 # test coverage for this diff --git a/tests/test_other.py b/tests/test_other.py index e251da5d..86e0eadf 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2015,47 +2015,3 @@ a(int [32], char [5]*) Popen([PYTHON, EMCC, path_from_root('tests', 'linpack.c'), '-O2', '-DSP', '--llvm-opts', '''['-O3', '-vectorize', '-vectorize-loops', '-bb-vectorize-vector-bits=128', '-force-vector-width=4']''']).communicate() self.assertContained('Unrolled Single Precision', run_js('a.out.js')) - def test_simd2(self): - self.clear() - open('src.cpp', 'w').write(r''' -#include <stdio.h> - -#include <emscripten/vector.h> - -int main(int argc, char **argv) { - float data[8]; - for (int i = 0; i < 32; i++) data[i] = (1+i+argc)*(2+i+argc*argc); - { - float32x4 *a = (float32x4*)&data[0]; - float32x4 *b = (float32x4*)&data[4]; - float32x4 c, d; - c = *a; - d = *b; - printf("floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); - c = c+d; - printf("floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); - d = c*d; - printf("floats! %d, %d, %d, %d %d, %d, %d, %d\n", (int)c[0], (int)c[1], (int)c[2], (int)c[3], (int)d[0], (int)d[1], (int)d[2], (int)d[3]); - } - { - uint32x4 *a = (uint32x4*)&data[0]; - uint32x4 *b = (uint32x4*)&data[4]; - uint32x4 c, d, e, f; - c = *a; - d = *b; - printf("uints! %d, %d, %d, %d %d, %d, %d, %d\n", c[0], c[1], c[2], c[3], d[0], d[1], d[2], d[3]); - e = c+d; - f = c-d; - printf("uints! %d, %d, %d, %d %d, %d, %d, %d\n", e[0], e[1], e[2], e[3], f[0], f[1], f[2], f[3]); - } - return 0; -} - ''') - Popen([PYTHON, EMCC, 'src.cpp', '-O2']).communicate() - self.assertContained('''floats! 6, 12, 20, 30 42, 56, 72, 90 -floats! 48, 68, 92, 120 42, 56, 72, 90 -floats! 48, 68, 92, 120 2016, 3808, 6624, 10800 -uints! 1086324736, 1094713344, 1101004800, 1106247680 1109917696, 1113587712, 1116733440, 1119092736 -uints! -2098724864, -2086666240, -2077229056, -2069626880 -23592960, -18874368, -15728640, -12845056 -''', run_js('a.out.js')) - diff --git a/tests/test_sanity.py b/tests/test_sanity.py index a0fff252..a405c3a3 100644 --- a/tests/test_sanity.py +++ b/tests/test_sanity.py @@ -217,7 +217,11 @@ class sanity(RunnerCore): try: os.environ['EM_IGNORE_SANITY'] = '1' - for version, succeed in [('v0.7.9', False), ('v0.8.0', True), ('v0.8.1', True), ('cheez', False)]: + for version, succeed in [('v0.7.9', False), + ('v0.8.0', True), + ('v0.8.1', True), + ('v0.10.21-pre', True), + ('cheez', False)]: f = open(path_from_root('tests', 'fake', 'nodejs'), 'w') f.write('#!/bin/sh\n') f.write('''if [ $1 = "--version" ]; then diff --git a/tests/test_webgl_context_attributes_common.c b/tests/test_webgl_context_attributes_common.c new file mode 100644 index 00000000..7131203b --- /dev/null +++ b/tests/test_webgl_context_attributes_common.c @@ -0,0 +1,262 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#include <emscripten.h> + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +static const int WINDOWS_SIZE = 500; + +static GLfloat vertices[] = { 0.0f, 250.f, 0.0f, + -250.f, -250.f, 0.0f, + 250.f, -250.f, 0.0f }; + +static GLfloat vertices2[] = { 0.0f, 250.f, -1.0f, + -250.f, -250.f, -1.0f, + 250.f, -250.f, -1.0f }; + +static GLuint shaderProgram = 0; +static GLuint verticesVBO = 0; +static GLuint verticesVBO2 = 0; + +static unsigned char backgroundColor[4] = {255, 255, 255, 255}; +static unsigned char triangleColor[4] = {255, 0, 0, 255}; +static unsigned char triangleColor2[4] = {0, 255, 0, 255}; + +static char vertexShaderSrc[] = + "precision highp float;" + "precision highp int;" + + "uniform mat4 u_mvpMatrix;" + "uniform vec4 u_color;" + + "attribute vec3 a_position;" + + "varying vec4 v_color;" + + "void main() {" + " gl_Position = u_mvpMatrix * vec4(a_position, 1.0);" + " v_color = u_color;" + "}" + ; + +static char fragmentShaderSrc[] = + "precision highp float;" + "precision highp int;" + + "varying vec4 v_color;" + + "void main() {" + " gl_FragColor = v_color;" + "}" + ; + +static GLuint createShader(const char *source, int type) { + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, (const GLchar**)(&source), NULL); + glCompileShader(shader); + return shader; +} + +static GLuint createShaderProgram(const char *vertexShaderSrc, const char *fragmentShaderSrc) { + GLuint program = glCreateProgram(); + glAttachShader(program, createShader(vertexShaderSrc, GL_VERTEX_SHADER)); + glAttachShader(program, createShader(fragmentShaderSrc, GL_FRAGMENT_SHADER)); + glLinkProgram(program); + return program; +} + +void ortho(float left, float right, float bottom, float top, float nearVal, float farVal, GLfloat *projMatrix) { + float tx = -(right+left)/(right-left); + float ty = -(top+bottom)/(top-bottom); + float tz = -(farVal+nearVal)/(farVal-nearVal); + memset(projMatrix, 0, 16 * sizeof(GLfloat)); + projMatrix[0] = 2.0f / (right-left); + projMatrix[3] = tx; + projMatrix[1*4+1] = 2.0f / (top-bottom); + projMatrix[1*4+3] = ty; + projMatrix[2*4+2] = -2.0f / (farVal-nearVal); + projMatrix[2*4+3] = tz; + projMatrix[3*4+3] = 1.0f; +} + +static void initGlObjects() { + glGenBuffers(1, &verticesVBO); + glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); + glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenBuffers(1, &verticesVBO2); + glBindBuffer(GL_ARRAY_BUFFER, verticesVBO2); + glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), vertices2, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + shaderProgram = createShaderProgram(vertexShaderSrc, fragmentShaderSrc); +} + +static void drawTriangle(GLuint verticesVBO, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + glUseProgram(shaderProgram); + GLuint posLoc = glGetAttribLocation(shaderProgram, "a_position"); + GLuint mvpLoc = glGetUniformLocation(shaderProgram, "u_mvpMatrix"); + GLuint colorLoc = glGetUniformLocation(shaderProgram, "u_color"); + + GLfloat mvpMat[16]; + ortho(-WINDOWS_SIZE/2, WINDOWS_SIZE/2, -WINDOWS_SIZE/2, WINDOWS_SIZE/2, -100, 100, mvpMat); + + glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvpMat); + glUniform4f(colorLoc, r/255.f, g/255.f, b/255.f, a/255.f); + + glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), BUFFER_OFFSET(0)); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glUseProgram(0); +} + +// Draw a red triangle on a white background. If antialiasing is disabled, resulting pixels +// will only have white and red colors. If antialiasing is enabled, there will be pixels +// whose color is different from red and white. +static int testAntiAliasing(bool activated) { + glViewport(0, 0, WINDOWS_SIZE, WINDOWS_SIZE); + glClearColor(backgroundColor[0]/255.f, backgroundColor[1]/255.f, backgroundColor[2]/255.f, backgroundColor[3]/255.f); + glClear(GL_COLOR_BUFFER_BIT); + + drawTriangle(verticesVBO, triangleColor[0], triangleColor[1], triangleColor[2], triangleColor[3]); + + bool antialiased = false; + + unsigned char buffer[(WINDOWS_SIZE*WINDOWS_SIZE)*4]; + glReadPixels(0, 0, WINDOWS_SIZE, WINDOWS_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]); + glFinish(); + for (unsigned int i = 0 ; i < WINDOWS_SIZE ; ++i) { + for (unsigned int j = 0 ; j < WINDOWS_SIZE ; ++j) { + unsigned char r = buffer[4*(i*WINDOWS_SIZE+j)]; + unsigned char g = buffer[4*(i*WINDOWS_SIZE+j)+1]; + unsigned char b = buffer[4*(i*WINDOWS_SIZE+j)+2]; + unsigned char a = buffer[4*(i*WINDOWS_SIZE+j)+3]; + if ((r == backgroundColor[0] && g == backgroundColor[1] && b == backgroundColor[2] && a == backgroundColor[3]) || + (r == triangleColor[0] && g == triangleColor[1] && b == triangleColor[2] && a == triangleColor[3])) { + continue; + } else { + antialiased = true; + break; + } + } + } + + return (activated && antialiased) || (!activated && !antialiased); +} + +// Draw a red triangle with depth equals to 0 then a green triangle whose depth equals -1. +// If there is an attached depth buffer, the resulting image will be a red triangle. If not, +// the resulting image will be a green triangle. +static int testDepth(bool activated) { + glViewport(0, 0, WINDOWS_SIZE, WINDOWS_SIZE); + glClearColor(backgroundColor[0]/255.f, backgroundColor[1]/255.f, backgroundColor[2]/255.f, backgroundColor[3]/255.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + drawTriangle(verticesVBO, triangleColor[0], triangleColor[1], triangleColor[2], triangleColor[3]); + drawTriangle(verticesVBO2, triangleColor2[0], triangleColor2[1], triangleColor2[2], triangleColor2[3]); + + glDisable(GL_DEPTH_TEST); + + // read the pixel at the center of the resulting image. + unsigned char buffer[4]; + glReadPixels(WINDOWS_SIZE/2, WINDOWS_SIZE/2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]); + + bool frontTriangleColor = (buffer[0] == triangleColor[0] && buffer[1] == triangleColor[1] && + buffer[2] == triangleColor[2] && buffer[3] == triangleColor[3]); + + bool backTriangleColor = (buffer[0] == triangleColor2[0] && buffer[1] == triangleColor2[1] && + buffer[2] == triangleColor2[2] && buffer[3] == triangleColor2[3]); + + return (activated && frontTriangleColor) || (!activated && backTriangleColor); +} + +// The stencil function is set to GL_LEQUAL so fragments will be written to the +// back buffer only if the ref value is less or equal than the one in the stencil buffer. +// The content of the stencil buffer is initialized to 0xFF. +// First draw a red triangle whose stencil ref value is 0x1. +// Then draw a green triangle whose stencil ref value is 0xFF. +// If there is an attached stencil buffer, the resulting image will be a red triangle. If not, +// the resulting image will be a green triangle. +static int testStencil(bool activated) { + glViewport(0, 0, WINDOWS_SIZE, WINDOWS_SIZE); + glClearColor(backgroundColor[0]/255.f, backgroundColor[1]/255.f, backgroundColor[2]/255.f, backgroundColor[3]/255.f); + glClearStencil(0xFF); + glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + glEnable(GL_STENCIL_TEST); + + glStencilFunc(GL_LEQUAL, 0x1, 0xFF); + drawTriangle(verticesVBO, triangleColor[0], triangleColor[1], triangleColor[2], triangleColor[3]); + + glStencilFunc(GL_LEQUAL, 0xFF, 0xFF); + drawTriangle(verticesVBO, triangleColor2[0], triangleColor2[1], triangleColor2[2], triangleColor2[3]); + + glDisable(GL_STENCIL_TEST); + + unsigned char buffer[4]; + glReadPixels(WINDOWS_SIZE/2, WINDOWS_SIZE/2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]); + + bool firstTriangleColor = (buffer[0] == triangleColor[0] && buffer[1] == triangleColor[1] && + buffer[2] == triangleColor[2] && buffer[3] == triangleColor[3]); + + bool secondTriangleColor = (buffer[0] == triangleColor2[0] && buffer[1] == triangleColor2[1] && + buffer[2] == triangleColor2[2] && buffer[3] == triangleColor2[3]); + + return (activated && firstTriangleColor) || (!activated && secondTriangleColor); +} + +static bool antiAliasingActivated = false; +static bool depthActivated = false; +static bool stencilActivated = false; + +static int result = 0; +static int resultAA = 0; +static int resultDepth = 0; +static int resultStencil = 0; + +static void draw() { + + if (!resultAA) resultAA = testAntiAliasing(antiAliasingActivated); + + if (!resultDepth) resultDepth = testDepth(depthActivated); + + if (!resultStencil) resultStencil = testStencil(stencilActivated); + + result = resultAA && resultDepth && resultStencil; + +} + +extern int webglAntialiasSupported(); +extern int webglDepthSupported(); +extern int webglStencilSupported(); + +// Check attributes support in the WebGL implementation (see test_webgl_context_attributes function in test_browser.py) +// Tests will succeed if they are not. +static void checkContextAttributesSupport() { + if (!webglAntialiasSupported()) { + resultAA = 1; + EM_ASM(alert('warning: no antialiasing\n')); + } + if (!webglDepthSupported()) { + resultDepth = 1; + EM_ASM(alert('warning: no depth\n')); + } + if (!webglStencilSupported()) { + resultStencil = 1; + EM_ASM(alert('warning: no stencil\n')); + } +} + + diff --git a/tests/test_webgl_context_attributes_glfw.c b/tests/test_webgl_context_attributes_glfw.c new file mode 100644 index 00000000..694236d0 --- /dev/null +++ b/tests/test_webgl_context_attributes_glfw.c @@ -0,0 +1,47 @@ +#include <GL/glew.h> +#include <GL/glfw.h> +#include <emscripten.h> + +#include "test_webgl_context_attributes_common.c" + +int nbSamples = 0; +int nbDepthBits = 0; +int nbStencilBits = 0; + +int main() { + + checkContextAttributesSupport(); + + glfwInit(); + +#ifdef AA_ACTIVATED + antiAliasingActivated = true; + nbSamples = 4; +#endif + +#ifdef DEPTH_ACTIVATED + depthActivated = true; + nbDepthBits = 16; +#endif + +#ifdef STENCIL_ACTIVATED + stencilActivated = true; + nbStencilBits = 8; +#endif + + glfwOpenWindowHint(GLFW_FSAA_SAMPLES, nbSamples); + glfwOpenWindow(WINDOWS_SIZE, WINDOWS_SIZE, 8, 8, 8, 8, nbDepthBits, nbStencilBits, GLFW_WINDOW); + + glewInit(); + initGlObjects(); + + draw(); + + glfwTerminate(); + + REPORT_RESULT(); + + return 0; + +} +
\ No newline at end of file diff --git a/tests/test_webgl_context_attributes_glut.c b/tests/test_webgl_context_attributes_glut.c new file mode 100644 index 00000000..3255fc9a --- /dev/null +++ b/tests/test_webgl_context_attributes_glut.c @@ -0,0 +1,42 @@ +#include <GL/glew.h> +#include <GL/glut.h> +#include <emscripten.h> + +#include "test_webgl_context_attributes_common.c" + +int main(int argc, char *argv[]) { + + checkContextAttributesSupport(); + + unsigned int glutDisplayMode = GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA; + +#ifdef AA_ACTIVATED + antiAliasingActivated = true; + glutDisplayMode |= GLUT_MULTISAMPLE; +#endif + +#ifdef DEPTH_ACTIVATED + depthActivated = true; + glutDisplayMode |= GLUT_DEPTH; +#endif + +#ifdef STENCIL_ACTIVATED + stencilActivated = true; + glutDisplayMode |= GLUT_STENCIL; +#endif + + glutInit(&argc, argv); + glutInitWindowSize(WINDOWS_SIZE, WINDOWS_SIZE); + glutInitDisplayMode(glutDisplayMode); + glutCreateWindow("WebGL"); + glutDisplayFunc(draw); + + glewInit(); + initGlObjects(); + + draw(); + + REPORT_RESULT(); + + return 0; +} diff --git a/tests/test_webgl_context_attributes_sdl.c b/tests/test_webgl_context_attributes_sdl.c new file mode 100644 index 00000000..23ad4378 --- /dev/null +++ b/tests/test_webgl_context_attributes_sdl.c @@ -0,0 +1,50 @@ +#include <GL/glew.h> +#define NO_SDL_GLEXT +#include <SDL/SDL.h> +#include <SDL/SDL_opengl.h> +#include <emscripten.h> + +#include "test_webgl_context_attributes_common.c" + +int main(int argc, char *argv[]) { + + checkContextAttributesSupport(); + + SDL_Init(SDL_INIT_VIDEO); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + +#ifdef AA_ACTIVATED + antiAliasingActivated = true; + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); +#else + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); +#endif + +#ifdef DEPTH_ACTIVATED + depthActivated = true; + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); +#else + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); +#endif + +#ifdef STENCIL_ACTIVATED + stencilActivated = true; + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); +#else + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); +#endif + + SDL_Surface *screen = SDL_SetVideoMode(WINDOWS_SIZE, WINDOWS_SIZE, 32, SDL_OPENGL); + + glewInit(); + initGlObjects(); + + draw(); + + REPORT_RESULT(); + + return 0; +} |