File: webgl_create_context.cpp

package info (click to toggle)
emscripten 3.1.6~dfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 114,112 kB
  • sloc: ansic: 583,052; cpp: 391,943; javascript: 79,361; python: 54,180; sh: 49,997; pascal: 4,658; makefile: 3,426; asm: 2,191; lisp: 1,869; ruby: 488; cs: 142
file content (200 lines) | stat: -rw-r--r-- 6,541 bytes parent folder | download
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// Copyright 2014 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 <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <emscripten.h>
#include <emscripten/html5.h>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

GLint GetInt(GLenum param)
{
  GLint value;
  glGetIntegerv(param, &value);
  return value;
}

void final(void*) {
  emscripten_force_exit(0);
}

EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;

void loop()
{
  EMSCRIPTEN_RESULT res;
  if (!context) {
    // new rendering frame started without a context
    EmscriptenWebGLContextAttributes attrs;
    emscripten_webgl_init_context_attributes(&attrs);
    EM_ASM(
      var canvas2 = Module['canvas'].cloneNode(true);
      Module['canvas'].parentElement.appendChild(canvas2);
      Module['canvas'] = canvas2;
    );
    assert(emscripten_webgl_get_current_context() == 0);
    context = emscripten_webgl_create_context("#canvas", &attrs);

    assert(context > 0); // Must have received a valid context.
    res = emscripten_webgl_make_context_current(context);
    assert(res == EMSCRIPTEN_RESULT_SUCCESS);
    assert(emscripten_webgl_get_current_context() == context);
  } else {
    res = emscripten_webgl_destroy_context(context);
    assert(res == EMSCRIPTEN_RESULT_SUCCESS);
    assert(emscripten_webgl_get_current_context() == 0);

    emscripten_cancel_main_loop();
    emscripten_async_call(final, (void*)0, 10);
  }
}

int main()
{
  bool first = true;
  EmscriptenWebGLContextAttributes attrs;
  int depth = 0;
  int stencil = 0;
  int antialias = 0;
#ifndef NO_DEPTH
  for(depth = 0; depth <= 1; ++depth)
#endif
#ifndef NO_STENCIL
  for(stencil = 0; stencil <= 1; ++stencil)
#endif
#ifndef NO_ANTIALIAS
  for(antialias = 0; antialias <= 1; ++antialias)
#endif
  {
    emscripten_webgl_init_context_attributes(&attrs);
    attrs.depth = depth;
    attrs.stencil = stencil;
    attrs.antialias = antialias;
    printf("Requesting depth: %d, stencil: %d, antialias: %d\n", depth, stencil, antialias);

    EM_ASM(
      var canvas2 = document.createElement('canvas');
      Module['canvas'].parentElement.appendChild(canvas2);
      canvas2.id = 'customCanvas';
    );

    assert(emscripten_webgl_get_current_context() == 0);
    EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context("#customCanvas", &attrs);
    assert(context > 0); // Must have received a valid context.
    EMSCRIPTEN_RESULT res = emscripten_webgl_make_context_current(context);
    assert(res == EMSCRIPTEN_RESULT_SUCCESS);
    assert(emscripten_webgl_get_current_context() == context);

    // Let's try enabling all extensions.
    const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
    std::vector<std::string> exts = split(extensions, ' ');
    for(size_t i = 0; i < exts.size(); ++i)
    {
      EM_BOOL supported = emscripten_webgl_enable_extension(context, exts[i].c_str());
      printf("%s\n", exts[i].c_str());
      assert(supported);
    }

    int drawingBufferWidth = -1;
    int drawingBufferHeight = -1;
    res = emscripten_webgl_get_drawing_buffer_size(context, &drawingBufferWidth, &drawingBufferHeight);
    assert(res == EMSCRIPTEN_RESULT_SUCCESS);
    printf("drawingBufferWidth x Height: %dx%d\n", drawingBufferWidth, drawingBufferHeight);
    assert(drawingBufferWidth == 300);
    assert(drawingBufferHeight == 150);

    // Try with a simple glClear() that we got a context.
    glClearColor(1.f, 0.f, 0.f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);
    unsigned char pixels[4];
    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    assert(pixels[0] == 0xFF);
    assert(pixels[1] == 0);
    assert(pixels[2] == 0);
    assert(pixels[3] == 0xFF);

    int numDepthBits = GetInt(GL_DEPTH_BITS);
    int numStencilBits = GetInt(GL_STENCIL_BITS);
    int numSamples = GetInt(GL_SAMPLES);
    printf("RGBA: %d%d%d%d, Depth: %d, Stencil: %d, Samples: %d\n",
      GetInt(GL_RED_BITS), GetInt(GL_GREEN_BITS), GetInt(GL_BLUE_BITS), GetInt(GL_ALPHA_BITS),
      numDepthBits, numStencilBits, numSamples);
    
    if (!depth && stencil && numDepthBits && numStencilBits && EM_ASM_INT(navigator.userAgent.toLowerCase().indexOf('firefox')) > -1)
    {
      numDepthBits = 0;
      printf("Applying workaround to ignore Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=982477\n");
    }
    assert(!!numDepthBits == !!depth);
    assert(!!numStencilBits == !!stencil);
    assert(!!numSamples == !!antialias);
    printf("\n");

    // Test bug https://github.com/emscripten-core/emscripten/issues/1330:
    unsigned vb;
    glGenBuffers(1, &vb);
    glBindBuffer(GL_ARRAY_BUFFER, vb);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    unsigned vb2;
    glGenBuffers(1, &vb2);
    glBindBuffer(GL_ARRAY_BUFFER, vb2);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);

    int vb3;
    glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vb3);
    if (vb != vb3) printf("Index 0: Generated VB: %d, read back VB: %d\n", vb, vb3);
    assert(vb == vb3);

    int vb4;
    glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vb4);
    if (vb2 != vb4) printf("Index 1: Generated VB: %d, read back VB: %d\n", vb2, vb4);
    assert(vb2 == vb4);

    // Test bug https://github.com/emscripten-core/emscripten/issues/7472:
    GLint enabled = 0;
    glGetVertexAttribiv(0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
    assert(enabled == 0);

    // Test that deleting the context works.
    res = emscripten_webgl_destroy_context(context);
    assert(res == 0);
    assert(emscripten_webgl_get_current_context() == 0);

    EM_ASM(
      var canvas2 = document.getElementById('customCanvas');
      canvas2.parentElement.removeChild(canvas2);
    );
  }

  // result will be reported when mainLoop completes
  emscripten_set_main_loop(loop, 0, 0);
  return 99;
}