File: webgl_timer_query.c

package info (click to toggle)
emscripten 3.1.69%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 121,872 kB
  • sloc: ansic: 636,110; cpp: 425,974; javascript: 78,401; python: 58,404; sh: 49,154; pascal: 5,237; makefile: 3,365; asm: 2,415; lisp: 1,869
file content (153 lines) | stat: -rw-r--r-- 4,360 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// 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 <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#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");
    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. */
  if (!strstr(glGetString(GL_EXTENSIONS), "EXT_disjoint_timer_query")) {
    printf("EXT_disjoint_timer_query[_webgl2] not supported\n");
    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;
}