blob: 125b7dee7f63bfafd3ed61e9f9ff6e4ff74cbdcf [file] [log] [blame] [edit]
// Copyright 2021 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
// found in the LICENSE file.
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <emscripten.h>
#include <emscripten/html5.h>
#define GL_GLEXT_PROTOTYPES
#ifdef TEST_WEBGL2
#include <GLES3/gl3.h>
#include <GLES3/gl2ext.h>
#else
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif
int result = 0;
GLuint timerQuery = 0;
#define GL_CALL( x ) \
{ \
x; \
GLenum error = glGetError(); \
if( error != GL_NO_ERROR ) { \
printf( "GL ERROR: %d, %s\n", (int)error, #x ); \
result = 1; \
} \
} \
void getQueryResult()
{
/* Get the result. It should be nonzero. */
GLuint64 time = 0;
#ifdef TEST_WEBGL2
GL_CALL(glGetQueryObjectui64vEXT(timerQuery, GL_QUERY_RESULT, &time));
#else
GL_CALL(glGetQueryObjectui64vEXT(timerQuery, GL_QUERY_RESULT_EXT, &time));
#endif
if(!time) return;
printf("queried time: %llu\n", time);
emscripten_cancel_main_loop();
#ifdef TEST_WEBGL2
GL_CALL(glDeleteQueries(1, &timerQuery));
#else
GL_CALL(glDeleteQueriesEXT(1, &timerQuery));
#endif
exit(result);
}
int main()
{
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
#ifdef TEST_WEBGL2
printf("testing for WebGL 2\n");
#else
printf("testing for WebGL 1\n");
#endif
attrs.enableExtensionsByDefault = 1;
#ifdef TEST_WEBGL2
attrs.majorVersion = 2;
#else
attrs.majorVersion = 1;
#endif
attrs.minorVersion = 0;
/* Skip WebGL 2 tests if not supported */
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context( "#canvas", &attrs );
#ifdef TEST_WEBGL2
if (!context)
{
printf("Skipped: WebGL 2 is not supported.\n");
#ifdef REPORT_RESULT
REPORT_RESULT(result);
#endif
return 0;
}
#endif
emscripten_webgl_make_context_current(context);
/* Check if the extension is actually supported. Firefox reports
EXT_disjoint_timer_query on WebGL 2 as well. */
bool timerQuerySupported = true;
if (!std::strstr(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)), "EXT_disjoint_timer_query"))
{
timerQuerySupported = false;
printf("EXT_disjoint_timer_query[_webgl2] not supported\n");
#ifdef REPORT_RESULT
REPORT_RESULT(result);
#endif
return 0;
}
/* Generate a timer query */
#ifdef TEST_WEBGL2
GL_CALL(glGenQueries(2, &timerQuery));
#else
GL_CALL(glGenQueriesEXT(1, &timerQuery));
#endif
assert(timerQuery);
/* Test the glGetQuery function */
GLint bits = 0;
#ifdef TEST_WEBGL2
GL_CALL(glGetQueryiv(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &bits));
#else
GL_CALL(glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &bits));
#endif
printf("time query bits: %d\n", bits);
assert(bits);
/* Begin it */
#ifdef TEST_WEBGL2
GL_CALL(glBeginQuery(GL_TIME_ELAPSED_EXT, timerQuery));
#else
GL_CALL(glBeginQueryEXT(GL_TIME_ELAPSED_EXT, timerQuery));
#endif
/* Now, `timerQuery` should be a query */
bool isQuery = false;
#ifdef TEST_WEBGL2
GL_CALL(isQuery = glIsQuery(timerQuery));
#else
GL_CALL(isQuery = glIsQueryEXT(timerQuery));
#endif
assert(isQuery);
/* Do a clear to actually make the GPU busy for a bit */
glClearColor(0.5f, 0.7f, 0.9f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
/* End the query after the clear */
#ifdef TEST_WEBGL2
GL_CALL(glEndQuery(GL_TIME_ELAPSED_EXT));
#else
GL_CALL(glEndQueryEXT(GL_TIME_ELAPSED_EXT));
#endif
/* In WebGL, query results are available only in the next event loop
iteration, so this should return false */
GLuint isAvailable;
#ifdef TEST_WEBGL2
GL_CALL(glGetQueryObjectuiv(timerQuery, GL_QUERY_RESULT_AVAILABLE, &isAvailable));
#else
GL_CALL(glGetQueryObjectuivEXT(timerQuery, GL_QUERY_RESULT_AVAILABLE_EXT, &isAvailable));
#endif
assert(!isAvailable);
/* Run the main loop to get the result */
emscripten_set_main_loop(getQueryResult, 0, 0);
return 0;
}