1 #include "ABI47_0_0EXWebGLMethods.h"
2 #include "ABI47_0_0EXGLContextManager.h"
3 #include "ABI47_0_0EXGLImageUtils.h"
4 #include "ABI47_0_0EXJsiArgsTransform.h"
5 #include "ABI47_0_0EXWebGLMethodsHelpers.h"
6 #include "ABI47_0_0EXWebGLRenderer.h"
7
8 #include <algorithm>
9
10 #define ARG(index, type) \
11 (argc > index ? unpackArg<type>(runtime, jsArgv + index) \
12 : throw std::runtime_error("ABI47_0_0EXGL: Too few arguments"))
13
14 #define CTX() \
15 auto result = getContext(runtime, jsThis); \
16 auto ctx = result.first; \
17 if (ctx == nullptr) { \
18 return jsi::Value::undefined(); \
19 }
20
21 #define NATIVE_METHOD(name, ...) \
22 jsi::Value glNativeMethod_##name( \
23 jsi::Runtime &runtime, const jsi::Value &jsThis, const jsi::Value *jsArgv, size_t argc)
24
25 #define SIMPLE_NATIVE_METHOD(name, func) \
26 NATIVE_METHOD(name) { \
27 CTX(); \
28 ctx->addToNextBatch(generateNativeMethod(runtime, func, jsArgv, argc)); \
29 return nullptr; \
30 }
31
32 #define UNIMPL_NATIVE_METHOD(name) \
33 NATIVE_METHOD(name) { \
34 return exglUnimplemented(#name); \
35 }
36
37 namespace ABI47_0_0expo {
38 namespace gl_cpp {
39 namespace method {
40
getContext(jsi::Runtime & runtime,const jsi::Value & jsThis)41 ContextWithLock getContext(jsi::Runtime &runtime, const jsi::Value &jsThis) {
42 double exglCtxId = jsThis.asObject(runtime).getProperty(runtime, "contextId").asNumber();
43 return ContextGet(static_cast<ABI47_0_0EXGLContextId>(exglCtxId));
44 }
45
46 // This listing follows the order in
47 // https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext
48 // https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext
49
50 // The WebGL context
51 // -----------------
52
NATIVE_METHOD(getContextAttributes)53 NATIVE_METHOD(getContextAttributes) {
54 jsi::Object jsResult(runtime);
55 jsResult.setProperty(runtime, "alpha", true);
56 jsResult.setProperty(runtime, "depth", true);
57 jsResult.setProperty(runtime, "stencil", true);
58 jsResult.setProperty(runtime, "antialias", false);
59 jsResult.setProperty(runtime, "premultipliedAlpha", false);
60 return jsResult;
61 }
62
NATIVE_METHOD(isContextLost)63 NATIVE_METHOD(isContextLost) {
64 return false;
65 }
66
67 // Viewing and clipping
68 // --------------------
69
70 SIMPLE_NATIVE_METHOD(scissor, glScissor); // x, y, width, height
71
72 SIMPLE_NATIVE_METHOD(viewport, glViewport); // x, y, width, height
73
74 // State information
75 // -----------------
76
77 SIMPLE_NATIVE_METHOD(activeTexture, glActiveTexture); // texture
78
79 SIMPLE_NATIVE_METHOD(blendColor, glBlendColor); // red, green, blue, alpha
80
81 SIMPLE_NATIVE_METHOD(blendEquation, glBlendEquation); // mode
82
83 SIMPLE_NATIVE_METHOD(blendEquationSeparate, glBlendEquationSeparate); // modeRGB, modeAlpha
84
85 SIMPLE_NATIVE_METHOD(blendFunc, glBlendFunc); // sfactor, dfactor
86
87 SIMPLE_NATIVE_METHOD(blendFuncSeparate, glBlendFuncSeparate); // srcRGB, dstRGB, srcAlpha, dstAlpha
88
89 SIMPLE_NATIVE_METHOD(clearColor, glClearColor); // red, green, blue, alpha
90
91 SIMPLE_NATIVE_METHOD(clearDepth, glClearDepthf); // depth
92
93 SIMPLE_NATIVE_METHOD(clearStencil, glClearStencil); // s
94
95 SIMPLE_NATIVE_METHOD(colorMask, glColorMask); // red, green, blue, alpha
96
97 SIMPLE_NATIVE_METHOD(cullFace, glCullFace); // mode
98
99 SIMPLE_NATIVE_METHOD(depthFunc, glDepthFunc); // func
100
101 SIMPLE_NATIVE_METHOD(depthMask, glDepthMask); // flag
102
103 SIMPLE_NATIVE_METHOD(depthRange, glDepthRangef); // zNear, zFar
104
105 SIMPLE_NATIVE_METHOD(disable, glDisable); // cap
106
107 SIMPLE_NATIVE_METHOD(enable, glEnable); // cap
108
109 SIMPLE_NATIVE_METHOD(frontFace, glFrontFace); // mode
110
NATIVE_METHOD(getParameter)111 NATIVE_METHOD(getParameter) {
112 CTX();
113 auto pname = ARG(0, GLenum);
114
115 switch (pname) {
116 // Float32Array[0]
117 case GL_COMPRESSED_TEXTURE_FORMATS:
118 return TypedArray<TypedArrayKind::Float32Array>(runtime, {});
119
120 // FLoat32Array[2]
121 case GL_ALIASED_LINE_WIDTH_RANGE:
122 case GL_ALIASED_POINT_SIZE_RANGE:
123 case GL_DEPTH_RANGE: {
124 std::vector<TypedArrayBase::ContentType<TypedArrayKind::Float32Array>> glResults(2);
125 ctx->addBlockingToNextBatch([&] { glGetFloatv(pname, glResults.data()); });
126 return TypedArray<TypedArrayKind::Float32Array>(runtime, glResults);
127 }
128 // FLoat32Array[4]
129 case GL_BLEND_COLOR:
130 case GL_COLOR_CLEAR_VALUE: {
131 std::vector<TypedArrayBase::ContentType<TypedArrayKind::Float32Array>> glResults(4);
132 ctx->addBlockingToNextBatch([&] { glGetFloatv(pname, glResults.data()); });
133 return TypedArray<TypedArrayKind::Float32Array>(runtime, glResults);
134 }
135 // Int32Array[2]
136 case GL_MAX_VIEWPORT_DIMS: {
137 std::vector<TypedArrayBase::ContentType<TypedArrayKind::Int32Array>> glResults(2);
138 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, glResults.data()); });
139 return TypedArray<TypedArrayKind::Int32Array>(runtime, glResults);
140 }
141 // Int32Array[4]
142 case GL_SCISSOR_BOX:
143 case GL_VIEWPORT: {
144 std::vector<TypedArrayBase::ContentType<TypedArrayKind::Int32Array>> glResults(4);
145 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, glResults.data()); });
146 return TypedArray<TypedArrayKind::Int32Array>(runtime, glResults);
147 }
148 // boolean[4]
149 case GL_COLOR_WRITEMASK: {
150 GLint glResults[4];
151 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, glResults); });
152 return jsi::Array::createWithElements(
153 runtime,
154 {jsi::Value(glResults[0]),
155 jsi::Value(glResults[1]),
156 jsi::Value(glResults[2]),
157 jsi::Value(glResults[3])});
158 }
159
160 // boolean
161 case GL_UNPACK_FLIP_Y_WEBGL:
162 return ctx->unpackFLipY;
163 case GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL:
164 case GL_UNPACK_COLORSPACE_CONVERSION_WEBGL:
165 return false;
166 case GL_RASTERIZER_DISCARD:
167 case GL_SAMPLE_ALPHA_TO_COVERAGE:
168 case GL_SAMPLE_COVERAGE:
169 case GL_TRANSFORM_FEEDBACK_ACTIVE:
170 case GL_TRANSFORM_FEEDBACK_PAUSED: {
171 GLint glResult;
172 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glResult); });
173 return jsi::Value(glResult);
174 }
175
176 // string
177 case GL_RENDERER:
178 case GL_SHADING_LANGUAGE_VERSION:
179 case GL_VENDOR:
180 case GL_VERSION: {
181 const GLubyte *glStr;
182 ctx->addBlockingToNextBatch([&] { glStr = glGetString(pname); });
183 return jsi::String::createFromUtf8(
184 runtime, std::string(reinterpret_cast<const char *>(glStr)));
185 }
186
187 // float
188 case GL_DEPTH_CLEAR_VALUE:
189 case GL_LINE_WIDTH:
190 case GL_POLYGON_OFFSET_FACTOR:
191 case GL_POLYGON_OFFSET_UNITS:
192 case GL_SAMPLE_COVERAGE_VALUE:
193 case GL_MAX_TEXTURE_LOD_BIAS: {
194 GLfloat glFloat;
195 ctx->addBlockingToNextBatch([&] { glGetFloatv(pname, &glFloat); });
196 return static_cast<double>(glFloat);
197 }
198
199 // ABI47_0_0EXGLObjectId
200 case GL_ARRAY_BUFFER_BINDING:
201 case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
202 GLint glInt;
203 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glInt); });
204 for (const auto &pair : ctx->objects) {
205 if (static_cast<int>(pair.second) == glInt) {
206 return createWebGLObject(
207 runtime, ABI47_0_0EXWebGLClass::WebGLBuffer, {static_cast<double>(pair.first)});
208 }
209 }
210 return nullptr;
211 }
212
213 case GL_CURRENT_PROGRAM: {
214 GLint glInt;
215 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glInt); });
216 for (const auto &pair : ctx->objects) {
217 if (static_cast<int>(pair.second) == glInt) {
218 return createWebGLObject(
219 runtime, ABI47_0_0EXWebGLClass::WebGLProgram, {static_cast<double>(pair.first)});
220 }
221 }
222 return nullptr;
223 }
224
225 // Unimplemented...
226 case GL_COPY_READ_BUFFER_BINDING:
227 case GL_COPY_WRITE_BUFFER_BINDING:
228 case GL_DRAW_FRAMEBUFFER_BINDING:
229 case GL_READ_FRAMEBUFFER_BINDING:
230 case GL_RENDERBUFFER_BINDING:
231 case GL_SAMPLER_BINDING:
232 case GL_TEXTURE_BINDING_2D_ARRAY:
233 case GL_TEXTURE_BINDING_2D:
234 case GL_TEXTURE_BINDING_3D:
235 case GL_TEXTURE_BINDING_CUBE_MAP:
236 case GL_TRANSFORM_FEEDBACK_BINDING:
237 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
238 case GL_UNIFORM_BUFFER_BINDING:
239 case GL_VERTEX_ARRAY_BINDING:
240 throw std::runtime_error(
241 "ABI47_0_0EXGL: getParameter() doesn't support gl." + std::to_string(pname) + " yet!");
242
243 // int
244 default: {
245 GLint glInt;
246 ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glInt); });
247 return jsi::Value(glInt);
248 }
249 }
250 }
251
NATIVE_METHOD(getError)252 NATIVE_METHOD(getError) {
253 CTX();
254 GLenum glResult;
255 ctx->addBlockingToNextBatch([&] { glResult = glGetError(); });
256 return static_cast<double>(glResult);
257 }
258
259 SIMPLE_NATIVE_METHOD(hint, glHint); // target, mode
260
NATIVE_METHOD(isEnabled)261 NATIVE_METHOD(isEnabled) {
262 CTX();
263 auto cap = ARG(0, GLenum);
264 GLboolean glResult;
265 ctx->addBlockingToNextBatch([&] { glResult = glIsEnabled(cap); });
266 return glResult == GL_TRUE;
267 }
268
269 SIMPLE_NATIVE_METHOD(lineWidth, glLineWidth); // width
270
NATIVE_METHOD(pixelStorei)271 NATIVE_METHOD(pixelStorei) {
272 CTX();
273 auto pname = ARG(0, GLenum);
274 switch (pname) {
275 case GL_UNPACK_FLIP_Y_WEBGL: {
276 ctx->unpackFLipY = ARG(1, GLboolean);
277 break;
278 }
279 default:
280 jsConsoleLog(runtime, { jsi::String::createFromUtf8(runtime, "ABI47_0_0EXGL: gl.pixelStorei() doesn't support this parameter yet!") });
281 }
282 return nullptr;
283 }
284
285 SIMPLE_NATIVE_METHOD(polygonOffset, glPolygonOffset); // factor, units
286
287 SIMPLE_NATIVE_METHOD(sampleCoverage, glSampleCoverage); // value, invert
288
289 SIMPLE_NATIVE_METHOD(stencilFunc, glStencilFunc); // func, ref, mask
290
291 SIMPLE_NATIVE_METHOD(stencilFuncSeparate, glStencilFuncSeparate); // face, func, ref, mask
292
293 SIMPLE_NATIVE_METHOD(stencilMask, glStencilMask); // mask
294
295 SIMPLE_NATIVE_METHOD(stencilMaskSeparate, glStencilMaskSeparate); // face, mask
296
297 SIMPLE_NATIVE_METHOD(stencilOp, glStencilOp) // fail, zfail, zpass
298
299 SIMPLE_NATIVE_METHOD(stencilOpSeparate, glStencilOpSeparate); // face, fail, zfail, zpass
300
301 // Buffers
302 // -------
303
NATIVE_METHOD(bindBuffer)304 NATIVE_METHOD(bindBuffer) {
305 CTX();
306 auto target = ARG(0, GLenum);
307 auto buffer = ARG(1, ABI47_0_0EXWebGLClass);
308 ctx->addToNextBatch([=] { glBindBuffer(target, ctx->lookupObject(buffer)); });
309 return nullptr;
310 }
311
NATIVE_METHOD(bufferData)312 NATIVE_METHOD(bufferData) {
313 CTX();
314 auto target = ARG(0, GLenum);
315 auto &sizeOrData = ARG(1, const jsi::Value &);
316 auto usage = ARG(2, GLenum);
317
318 if (sizeOrData.isNumber()) {
319 GLsizeiptr length = sizeOrData.getNumber();
320 ctx->addToNextBatch([=] { glBufferData(target, length, nullptr, usage); });
321 } else if (sizeOrData.isNull() || sizeOrData.isUndefined()) {
322 ctx->addToNextBatch([=] { glBufferData(target, 0, nullptr, usage); });
323 } else if (sizeOrData.isObject()) {
324 auto data = rawTypedArray(runtime, sizeOrData.getObject(runtime));
325 ctx->addToNextBatch(
326 [=, data{std::move(data)}] { glBufferData(target, data.size(), data.data(), usage); });
327 }
328 return nullptr;
329 }
330
NATIVE_METHOD(bufferSubData)331 NATIVE_METHOD(bufferSubData) {
332 CTX();
333 auto target = ARG(0, GLenum);
334 auto offset = ARG(1, GLintptr);
335 if (ARG(2, const jsi::Value &).isNull()) {
336 ctx->addToNextBatch([=] { glBufferSubData(target, offset, 0, nullptr); });
337 } else {
338 auto data = rawTypedArray(runtime, ARG(2, jsi::Object));
339 ctx->addToNextBatch(
340 [=, data{std::move(data)}] { glBufferSubData(target, offset, data.size(), data.data()); });
341 }
342 return nullptr;
343 }
344
NATIVE_METHOD(createBuffer)345 NATIVE_METHOD(createBuffer) {
346 CTX();
347 return exglGenObject(ctx, runtime, glGenBuffers, ABI47_0_0EXWebGLClass::WebGLBuffer);
348 }
349
NATIVE_METHOD(deleteBuffer)350 NATIVE_METHOD(deleteBuffer) {
351 CTX();
352 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteBuffers);
353 }
354
NATIVE_METHOD(getBufferParameter)355 NATIVE_METHOD(getBufferParameter) {
356 CTX();
357 auto target = ARG(0, GLenum);
358 auto pname = ARG(1, GLenum);
359 GLint glResult;
360 ctx->addBlockingToNextBatch([&] { glGetBufferParameteriv(target, pname, &glResult); });
361 return jsi::Value(glResult);
362 }
363
NATIVE_METHOD(isBuffer)364 NATIVE_METHOD(isBuffer) {
365 CTX();
366 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsBuffer);
367 }
368
369 // Buffers (WebGL2)
370
371 SIMPLE_NATIVE_METHOD(
372 copyBufferSubData,
373 glCopyBufferSubData) // readTarget, writeTarget, readOffset, writeOffset, size
374
375 // glGetBufferSubData is not available in OpenGL ES
376 UNIMPL_NATIVE_METHOD(getBufferSubData);
377
378 // Framebuffers
379 // ------------
380
NATIVE_METHOD(bindFramebuffer)381 NATIVE_METHOD(bindFramebuffer) {
382 CTX();
383 auto target = ARG(0, GLenum);
384 auto framebuffer = ARG(1, ABI47_0_0EXWebGLClass);
385 ctx->addToNextBatch([=] {
386 glBindFramebuffer(
387 target, framebuffer == 0 ? ctx->defaultFramebuffer : ctx->lookupObject(framebuffer));
388 });
389 return nullptr;
390 }
391
NATIVE_METHOD(checkFramebufferStatus)392 NATIVE_METHOD(checkFramebufferStatus) {
393 CTX();
394 auto target = ARG(0, GLenum);
395 GLenum glResult;
396 ctx->addBlockingToNextBatch([&] { glResult = glCheckFramebufferStatus(target); });
397 return static_cast<double>(glResult);
398 }
399
NATIVE_METHOD(createFramebuffer)400 NATIVE_METHOD(createFramebuffer) {
401 CTX();
402 return exglGenObject(ctx, runtime, glGenFramebuffers, ABI47_0_0EXWebGLClass::WebGLFramebuffer);
403 }
404
NATIVE_METHOD(deleteFramebuffer)405 NATIVE_METHOD(deleteFramebuffer) {
406 CTX();
407 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteFramebuffers);
408 }
409
NATIVE_METHOD(framebufferRenderbuffer)410 NATIVE_METHOD(framebufferRenderbuffer) {
411 CTX();
412 auto target = ARG(0, GLenum);
413 auto attachment = ARG(1, GLenum);
414 auto renderbuffertarget = ARG(2, GLenum);
415 auto fRenderbuffer = ARG(3, ABI47_0_0EXWebGLClass);
416 ctx->addToNextBatch([=] {
417 GLuint renderbuffer = ctx->lookupObject(fRenderbuffer);
418 glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
419 });
420 return nullptr;
421 }
422
423 NATIVE_METHOD(framebufferTexture2D, 5) {
424 CTX();
425 auto target = ARG(0, GLenum);
426 auto attachment = ARG(1, GLenum);
427 auto textarget = ARG(2, GLenum);
428 auto fTexture = ARG(3, ABI47_0_0EXWebGLClass);
429 auto level = ARG(4, GLint);
__anon176ab9391802null430 ctx->addToNextBatch([=] {
431 glFramebufferTexture2D(target, attachment, textarget, ctx->lookupObject(fTexture), level);
432 });
433 return nullptr;
434 }
435
436 UNIMPL_NATIVE_METHOD(getFramebufferAttachmentParameter)
437
NATIVE_METHOD(isFramebuffer)438 NATIVE_METHOD(isFramebuffer) {
439 CTX();
440 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsFramebuffer);
441 }
442
NATIVE_METHOD(readPixels)443 NATIVE_METHOD(readPixels) {
444 CTX();
445 auto x = ARG(0, GLint);
446 auto y = ARG(1, GLint);
447 auto width = ARG(2, GLuint); // GLsizei allows negative values
448 auto height = ARG(3, GLuint);
449 auto format = ARG(4, GLenum);
450 auto type = ARG(5, GLenum);
451 size_t byteLength = width * height * bytesPerPixel(type, format);
452 std::vector<uint8_t> pixels(byteLength);
453 ctx->addBlockingToNextBatch(
454 [&] { glReadPixels(x, y, width, height, format, type, pixels.data()); });
455
456 TypedArrayBase arr = ARG(6, TypedArrayBase);
457 jsi::ArrayBuffer buffer = arr.getBuffer(runtime);
458 arrayBufferUpdate(runtime, buffer, pixels, arr.byteOffset(runtime));
459 return nullptr;
460 }
461
462 // Framebuffers (WebGL2)
463 // ---------------------
464
465 SIMPLE_NATIVE_METHOD(blitFramebuffer, glBlitFramebuffer);
466 // srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter
467
NATIVE_METHOD(framebufferTextureLayer)468 NATIVE_METHOD(framebufferTextureLayer) {
469 CTX();
470 auto target = ARG(0, GLenum);
471 auto attachment = ARG(1, GLenum);
472 auto texture = ARG(2, ABI47_0_0EXWebGLClass);
473 auto level = ARG(3, GLint);
474 auto layer = ARG(4, GLint);
475 ctx->addToNextBatch([=] {
476 glFramebufferTextureLayer(target, attachment, ctx->lookupObject(texture), level, layer);
477 });
478 return nullptr;
479 }
480
NATIVE_METHOD(invalidateFramebuffer)481 NATIVE_METHOD(invalidateFramebuffer) {
482 CTX();
483 auto target = ARG(0, GLenum);
484 auto jsAttachments = ARG(1, jsi::Array);
485
486 std::vector<GLenum> attachments(jsAttachments.size(runtime));
487 for (size_t i = 0; i < attachments.size(); i++) {
488 attachments[i] = jsAttachments.getValueAtIndex(runtime, i).asNumber();
489 }
490 ctx->addToNextBatch([=, attachaments{std::move(attachments)}] {
491 glInvalidateFramebuffer(target, static_cast<GLsizei>(attachments.size()), attachments.data());
492 });
493 return nullptr; // breaking change TypedArray -> Array (bug in previous implementation)
494 }
495
NATIVE_METHOD(invalidateSubFramebuffer)496 NATIVE_METHOD(invalidateSubFramebuffer) {
497 CTX();
498 auto target = ARG(0, GLenum);
499 auto jsAttachments = ARG(1, jsi::Array);
500 auto x = ARG(2, GLint);
501 auto y = ARG(3, GLint);
502 auto width = ARG(4, GLint);
503 auto height = ARG(5, GLint);
504 std::vector<GLenum> attachments(jsAttachments.size(runtime));
505 for (size_t i = 0; i < attachments.size(); i++) {
506 attachments[i] = jsAttachments.getValueAtIndex(runtime, i).asNumber();
507 }
508 ctx->addToNextBatch([=, attachments{std::move(attachments)}] {
509 glInvalidateSubFramebuffer(
510 target, static_cast<GLsizei>(attachments.size()), attachments.data(), x, y, width, height);
511 });
512 return nullptr;
513 }
514
515 SIMPLE_NATIVE_METHOD(readBuffer, glReadBuffer); // mode
516
517 // Renderbuffers
518 // -------------
519
NATIVE_METHOD(bindRenderbuffer)520 NATIVE_METHOD(bindRenderbuffer) {
521 CTX();
522 auto target = ARG(0, GLenum);
523 auto fRenderbuffer = ARG(1, ABI47_0_0EXWebGLClass);
524 ctx->addToNextBatch([=] { glBindRenderbuffer(target, ctx->lookupObject(fRenderbuffer)); });
525 return nullptr;
526 }
527
NATIVE_METHOD(createRenderbuffer)528 NATIVE_METHOD(createRenderbuffer) {
529 CTX();
530 return exglGenObject(ctx, runtime, glGenRenderbuffers, ABI47_0_0EXWebGLClass::WebGLRenderbuffer);
531 }
532
NATIVE_METHOD(deleteRenderbuffer)533 NATIVE_METHOD(deleteRenderbuffer) {
534 CTX();
535 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteRenderbuffers);
536 }
537
538 UNIMPL_NATIVE_METHOD(getRenderbufferParameter)
539
NATIVE_METHOD(isRenderbuffer)540 NATIVE_METHOD(isRenderbuffer) {
541 CTX();
542 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsRenderbuffer);
543 }
544
NATIVE_METHOD(renderbufferStorage)545 NATIVE_METHOD(renderbufferStorage) {
546 CTX();
547 auto target = ARG(0, GLenum);
548 auto internalformat = ARG(1, GLint);
549 auto width = ARG(2, GLsizei);
550 auto height = ARG(3, GLsizei);
551
552 // WebGL allows `GL_DEPTH_STENCIL` flag to be passed here,
553 // however OpenGL ES seems to require sized format, so we fall back to `GL_DEPTH24_STENCIL8`.
554 internalformat = internalformat == GL_DEPTH_STENCIL ? GL_DEPTH24_STENCIL8 : internalformat;
555
556 ctx->addToNextBatch([=] { glRenderbufferStorage(target, internalformat, width, height); });
557 return nullptr;
558 }
559
560 // Renderbuffers (WebGL2)
561 // ----------------------
562
NATIVE_METHOD(getInternalformatParameter)563 NATIVE_METHOD(getInternalformatParameter) {
564 CTX();
565 auto target = ARG(0, GLenum);
566 auto internalformat = ARG(1, GLenum);
567 auto pname = ARG(2, GLenum);
568
569 std::vector<TypedArrayBase::ContentType<TypedArrayKind::Int32Array>> glResults;
570 ctx->addBlockingToNextBatch([&] {
571 GLint count;
572 glGetInternalformativ(target, internalformat, GL_NUM_SAMPLE_COUNTS, 1, &count);
573 glResults.resize(count);
574 glGetInternalformativ(target, internalformat, pname, count, glResults.data());
575 });
576
577 return TypedArray<TypedArrayKind::Int32Array>(runtime, glResults);
578 }
579
580 UNIMPL_NATIVE_METHOD(renderbufferStorageMultisample)
581
582 // Textures
583 // --------
584
NATIVE_METHOD(bindTexture)585 NATIVE_METHOD(bindTexture) {
586 CTX();
587 auto target = ARG(0, GLenum);
588 auto texture = ARG(1, ABI47_0_0EXWebGLClass);
589 ctx->addToNextBatch([=] { glBindTexture(target, ctx->lookupObject(texture)); });
590 return nullptr;
591 }
592
593 UNIMPL_NATIVE_METHOD(compressedTexImage2D)
594
595 UNIMPL_NATIVE_METHOD(compressedTexSubImage2D)
596
597 SIMPLE_NATIVE_METHOD(
598 copyTexImage2D,
599 glCopyTexImage2D); // target, level, internalformat, x, y, width, height, border
600
SIMPLE_NATIVE_METHOD(copyTexSubImage2D,glCopyTexSubImage2D)601 SIMPLE_NATIVE_METHOD(
602 copyTexSubImage2D,
603 glCopyTexSubImage2D) // target, level, xoffset, yoffset, x, y, width, height
604
605 NATIVE_METHOD(createTexture) {
606 CTX();
607 return exglGenObject(ctx, runtime, glGenTextures, ABI47_0_0EXWebGLClass::WebGLTexture);
608 }
609
NATIVE_METHOD(deleteTexture)610 NATIVE_METHOD(deleteTexture) {
611 CTX();
612 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteTextures);
613 }
614
SIMPLE_NATIVE_METHOD(generateMipmap,glGenerateMipmap)615 SIMPLE_NATIVE_METHOD(generateMipmap, glGenerateMipmap) // target
616
617 UNIMPL_NATIVE_METHOD(getTexParameter)
618
619 NATIVE_METHOD(isTexture) {
620 CTX();
621 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsTexture);
622 }
623
624 NATIVE_METHOD(texImage2D, 6) {
625 CTX();
626 auto target = ARG(0, GLenum);
627 auto level = ARG(1, GLint);
628 auto internalformat = ARG(2, GLint);
629 if (argc == 9) {
630 auto width = ARG(3, GLsizei);
631 auto height = ARG(4, GLsizei);
632 auto border = ARG(5, GLsizei);
633 auto format = ARG(6, GLenum);
634 auto type = ARG(7, GLenum);
635 if (ARG(8, const jsi::Value &).isNull()) {
__anon176ab9392102null636 ctx->addToNextBatch([=] {
637 glTexImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
638 });
639 return nullptr;
640 }
641 auto data = ARG(8, jsi::Object);
642
643 if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
644 std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
645 if (ctx->unpackFLipY) {
646 flipPixels(vec.data(), width * bytesPerPixel(type, format), height);
647 }
__anon176ab9392202null648 ctx->addToNextBatch([=, vec{std::move(vec)}] {
649 glTexImage2D(
650 target, level, internalformat, width, height, border, format, type, vec.data());
651 });
652 } else {
653 auto image = loadImage(runtime, data, &width, &height, nullptr);
654 if (ctx->unpackFLipY) {
655 flipPixels(image.get(), width * bytesPerPixel(type, format), height);
656 }
__anon176ab9392302null657 ctx->addToNextBatch([=] {
658 glTexImage2D(
659 target, level, internalformat, width, height, border, format, type, image.get());
660 });
661 }
662 } else if (argc == 6) {
663 auto format = ARG(3, GLenum);
664 auto type = ARG(4, GLenum);
665 auto data = ARG(5, jsi::Object);
666 GLsizei width = 0, height = 0, border = 0;
667 auto image = loadImage(runtime, data, &width, &height, nullptr);
668 if (ctx->unpackFLipY) {
669 flipPixels(image.get(), width * bytesPerPixel(type, format), height);
670 }
__anon176ab9392402null671 ctx->addToNextBatch([=] {
672 glTexImage2D(target, level, internalformat, width, height, border, format, type, image.get());
673 });
674 } else {
675 throw std::runtime_error("ABI47_0_0EXGL: Invalid number of arguments to gl.texImage2D()!");
676 }
677 return nullptr;
678 }
679
680 NATIVE_METHOD(texSubImage2D, 6) {
681 CTX();
682 auto target = ARG(0, GLenum);
683 auto level = ARG(1, GLint);
684 auto xoffset = ARG(2, GLint);
685 auto yoffset = ARG(3, GLint);
686 if (argc == 9) {
687 auto width = ARG(4, GLsizei);
688 auto height = ARG(5, GLsizei);
689 auto format = ARG(6, GLenum);
690 auto type = ARG(7, GLenum);
691 if (ARG(8, const jsi::Value &).isNull()) {
__anon176ab9392502null692 ctx->addToNextBatch([=] {
693 auto empty = std::make_unique<uint8_t>(width * height * bytesPerPixel(type, format));
694 std::memset(empty.get(), 0, width * height * bytesPerPixel(type, format));
695 glTexImage2D(target, level, xoffset, yoffset, width, height, format, type, empty.get());
696 });
697 return nullptr;
698 }
699
700 auto data = ARG(8, jsi::Object);
701
702 if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
703 std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
704 if (ctx->unpackFLipY) {
705 flipPixels(vec.data(), width * bytesPerPixel(type, format), height);
706 }
__anon176ab9392602null707 ctx->addToNextBatch([=, vec{std::move(vec)}] {
708 glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, vec.data());
709 });
710 } else {
711 auto image = loadImage(runtime, data, &width, &height, nullptr);
712 if (ctx->unpackFLipY) {
713 flipPixels(image.get(), width * bytesPerPixel(type, format), height);
714 }
__anon176ab9392702null715 ctx->addToNextBatch([=] {
716 glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, image.get());
717 });
718 }
719 } else if (argc == 7) {
720 auto format = ARG(4, GLenum);
721 auto type = ARG(5, GLenum);
722 auto data = ARG(6, jsi::Object);
723 GLsizei width = 0, height = 0;
724 auto image = loadImage(runtime, data, &width, &height, nullptr);
725 if (ctx->unpackFLipY) {
726 flipPixels(image.get(), width * bytesPerPixel(type, format), height);
727 }
__anon176ab9392802null728 ctx->addToNextBatch([=] {
729 glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, image.get());
730 });
731 } else {
732 throw std::runtime_error("ABI47_0_0EXGL: Invalid number of arguments to gl.texSubImage2D()!");
733 }
734 return nullptr;
735 }
736
737 SIMPLE_NATIVE_METHOD(texParameterf, glTexParameterf); // target, pname, param
738
739 SIMPLE_NATIVE_METHOD(texParameteri, glTexParameteri); // target, pname, param
740
741 // Textures (WebGL2)
742 // -----------------
743
744 SIMPLE_NATIVE_METHOD(texStorage2D, glTexStorage2D); // target, levels, internalformat, width, height
745
746 SIMPLE_NATIVE_METHOD(
747 texStorage3D,
748 glTexStorage3D); // target, levels, internalformat, width, height, depth
749
NATIVE_METHOD(texImage3D)750 NATIVE_METHOD(texImage3D) {
751 CTX();
752 auto target = ARG(0, GLenum);
753 auto level = ARG(1, GLint);
754 auto internalformat = ARG(2, GLint);
755 auto width = ARG(3, GLsizei);
756 auto height = ARG(4, GLsizei);
757 auto depth = ARG(5, GLsizei);
758 auto border = ARG(6, GLsizei);
759 auto format = ARG(7, GLenum);
760 auto type = ARG(8, GLenum);
761
762 if (ARG(9, const jsi::Value &).isNull()) {
763 ctx->addToNextBatch([=] {
764 glTexImage3D(
765 target, level, internalformat, width, height, depth, border, format, type, nullptr);
766 });
767 return nullptr;
768 }
769 auto data = ARG(9, jsi::Object);
770 auto flip = [&](uint8_t *data) {
771 GLubyte *texelLayer = data;
772 for (int z = 0; z < depth; z++) {
773 flipPixels(texelLayer, width * bytesPerPixel(type, format), height);
774 texelLayer += bytesPerPixel(type, format) * width * height;
775 }
776 };
777
778 if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
779 std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
780 if (ctx->unpackFLipY) {
781 flip(vec.data());
782 }
783 ctx->addToNextBatch([=, vec{std::move(vec)}] {
784 glTexImage3D(
785 target, level, internalformat, width, height, depth, border, format, type, vec.data());
786 });
787 } else {
788 auto image = loadImage(runtime, data, &width, &height, nullptr);
789 if (ctx->unpackFLipY) {
790 flip(image.get());
791 }
792 ctx->addToNextBatch([=] {
793 glTexImage3D(
794 target, level, internalformat, width, height, depth, border, format, type, image.get());
795 });
796 }
797 return nullptr;
798 }
799
NATIVE_METHOD(texSubImage3D)800 NATIVE_METHOD(texSubImage3D) {
801 CTX();
802 auto target = ARG(0, GLenum);
803 auto level = ARG(1, GLint);
804 auto xoffset = ARG(2, GLint);
805 auto yoffset = ARG(3, GLint);
806 auto zoffset = ARG(4, GLint);
807 auto width = ARG(5, GLsizei);
808 auto height = ARG(6, GLsizei);
809 auto depth = ARG(7, GLsizei);
810 auto format = ARG(8, GLenum);
811 auto type = ARG(9, GLenum);
812
813 if (ARG(10, const jsi::Value &).isNull()) {
814 ctx->addToNextBatch([=] {
815 auto empty = std::make_unique<uint8_t>(width * height * depth * bytesPerPixel(type, format));
816 std::memset(empty.get(), 0, width * height * depth * bytesPerPixel(type, format));
817 auto ptr = empty.get();
818 glTexSubImage3D(
819 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, ptr);
820 });
821 return nullptr;
822 }
823 auto data = ARG(10, jsi::Object);
824 auto flip = [&](uint8_t *data) {
825 GLubyte *texelLayer = data;
826 for (int z = 0; z < depth; z++) {
827 flipPixels(texelLayer, width * bytesPerPixel(type, format), height);
828 texelLayer += bytesPerPixel(type, format) * width * height;
829 }
830 };
831
832 if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
833 std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
834 if (ctx->unpackFLipY) {
835 flip(vec.data());
836 }
837 ctx->addToNextBatch([=, vec{std::move(vec)}] {
838 glTexSubImage3D(
839 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, vec.data());
840 });
841 } else {
842 auto image = loadImage(runtime, data, &width, &height, nullptr);
843 if (ctx->unpackFLipY) {
844 flip(image.get());
845 }
846 ctx->addToNextBatch([=] {
847 glTexSubImage3D(
848 target,
849 level,
850 xoffset,
851 yoffset,
852 zoffset,
853 width,
854 height,
855 depth,
856 format,
857 type,
858 image.get());
859 });
860 }
861 return nullptr;
862 }
863
864 SIMPLE_NATIVE_METHOD(
865 copyTexSubImage3D,
866 glCopyTexSubImage3D); // target, level, xoffset, yoffset, zoffset, x, y, width, height
867
868 UNIMPL_NATIVE_METHOD(compressedTexImage3D)
869
UNIMPL_NATIVE_METHOD(compressedTexSubImage3D)870 UNIMPL_NATIVE_METHOD(compressedTexSubImage3D)
871
872 // Programs and shaders
873 // --------------------
874
875 NATIVE_METHOD(attachShader) {
876 CTX();
877 auto program = ARG(0, ABI47_0_0EXWebGLClass);
878 auto shader = ARG(1, ABI47_0_0EXWebGLClass);
879 ctx->addToNextBatch(
880 [=] { glAttachShader(ctx->lookupObject(program), ctx->lookupObject(shader)); });
881 return nullptr;
882 }
883
NATIVE_METHOD(bindAttribLocation)884 NATIVE_METHOD(bindAttribLocation) {
885 CTX();
886 auto program = ARG(0, ABI47_0_0EXWebGLClass);
887 auto index = ARG(1, GLuint);
888 auto name = ARG(2, std::string);
889 ctx->addToNextBatch([=, name{std::move(name)}] {
890 glBindAttribLocation(ctx->lookupObject(program), index, name.c_str());
891 });
892 return nullptr;
893 }
894
NATIVE_METHOD(compileShader)895 NATIVE_METHOD(compileShader) {
896 CTX();
897 auto shader = ARG(0, ABI47_0_0EXWebGLClass);
898 ctx->addToNextBatch([=] { glCompileShader(ctx->lookupObject(shader)); });
899 return nullptr;
900 }
901
NATIVE_METHOD(createProgram)902 NATIVE_METHOD(createProgram) {
903 CTX();
904 return exglCreateObject(ctx, runtime, glCreateProgram, ABI47_0_0EXWebGLClass::WebGLProgram);
905 }
906
NATIVE_METHOD(createShader)907 NATIVE_METHOD(createShader) {
908 CTX();
909 auto type = ARG(0, GLenum);
910 if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) {
911 return exglCreateObject(
912 ctx, runtime, std::bind(glCreateShader, type), ABI47_0_0EXWebGLClass::WebGLShader);
913 } else {
914 throw std::runtime_error("unknown shader type passed to function");
915 }
916 }
917
NATIVE_METHOD(deleteProgram)918 NATIVE_METHOD(deleteProgram) {
919 CTX();
920 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteProgram);
921 }
922
NATIVE_METHOD(deleteShader)923 NATIVE_METHOD(deleteShader) {
924 CTX();
925 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteShader);
926 }
927
NATIVE_METHOD(detachShader)928 NATIVE_METHOD(detachShader) {
929 CTX();
930 auto program = ARG(0, ABI47_0_0EXWebGLClass);
931 auto shader = ARG(1, ABI47_0_0EXWebGLClass);
932 ctx->addToNextBatch(
933 [=] { glDetachShader(ctx->lookupObject(program), ctx->lookupObject(shader)); });
934 return nullptr;
935 }
936
NATIVE_METHOD(getAttachedShaders)937 NATIVE_METHOD(getAttachedShaders) {
938 CTX();
939 auto fProgram = ARG(0, ABI47_0_0EXWebGLClass);
940
941 GLint count;
942 std::vector<GLuint> glResults;
943 ctx->addBlockingToNextBatch([&] {
944 GLuint program = ctx->lookupObject(fProgram);
945 glGetProgramiv(program, GL_ATTACHED_SHADERS, &count);
946 glResults.resize(count);
947 glGetAttachedShaders(program, count, nullptr, glResults.data());
948 });
949
950 jsi::Array jsResults(runtime, count);
951 for (auto i = 0; i < count; ++i) {
952 ABI47_0_0EXGLObjectId exglObjId = 0;
953 for (const auto &pair : ctx->objects) {
954 if (pair.second == glResults[i]) {
955 exglObjId = pair.first;
956 }
957 }
958 if (exglObjId == 0) {
959 throw std::runtime_error(
960 "ABI47_0_0EXGL: Internal error: couldn't find ABI47_0_0EXGLObjectId "
961 "associated with shader in getAttachedShaders()!");
962 }
963 jsResults.setValueAtIndex(
964 runtime,
965 i,
966 createWebGLObject(runtime, ABI47_0_0EXWebGLClass::WebGLShader, {static_cast<double>(exglObjId)}));
967 }
968 return jsResults;
969 }
970
NATIVE_METHOD(getProgramParameter)971 NATIVE_METHOD(getProgramParameter) {
972 CTX();
973 auto fProgram = ARG(0, ABI47_0_0EXWebGLClass);
974 auto pname = ARG(1, GLenum);
975 GLint glResult;
976 ctx->addBlockingToNextBatch(
977 [&] { glGetProgramiv(ctx->lookupObject(fProgram), pname, &glResult); });
978 if (pname == GL_DELETE_STATUS || pname == GL_LINK_STATUS || pname == GL_VALIDATE_STATUS) {
979 return glResult == GL_TRUE;
980 } else {
981 return glResult;
982 }
983 }
984
NATIVE_METHOD(getShaderParameter)985 NATIVE_METHOD(getShaderParameter) {
986 CTX();
987 auto fShader = ARG(0, ABI47_0_0EXWebGLClass);
988 auto pname = ARG(1, GLenum);
989 GLint glResult;
990 ctx->addBlockingToNextBatch([&] { glGetShaderiv(ctx->lookupObject(fShader), pname, &glResult); });
991 if (pname == GL_DELETE_STATUS || pname == GL_COMPILE_STATUS) {
992 return glResult == GL_TRUE;
993 } else {
994 return glResult;
995 }
996 }
997
NATIVE_METHOD(getShaderPrecisionFormat)998 NATIVE_METHOD(getShaderPrecisionFormat) {
999 CTX();
1000 auto shaderType = ARG(0, GLenum);
1001 auto precisionType = ARG(1, GLenum);
1002
1003 GLint range[2], precision;
1004 ctx->addBlockingToNextBatch(
1005 [&] { glGetShaderPrecisionFormat(shaderType, precisionType, range, &precision); });
1006
1007 jsi::Object jsResult =
1008 createWebGLObject(runtime, ABI47_0_0EXWebGLClass::WebGLShaderPrecisionFormat, {}).asObject(runtime);
1009 jsResult.setProperty(runtime, "rangeMin", jsi::Value(range[0]));
1010 jsResult.setProperty(runtime, "rangeMax", jsi::Value(range[1]));
1011 jsResult.setProperty(runtime, "precision", jsi::Value(precision));
1012 return jsResult;
1013 }
1014
NATIVE_METHOD(getProgramInfoLog)1015 NATIVE_METHOD(getProgramInfoLog) {
1016 CTX();
1017 auto fObj = ARG(0, ABI47_0_0EXWebGLClass);
1018 std::string str;
1019 ctx->addBlockingToNextBatch([&] {
1020 GLuint obj = ctx->lookupObject(fObj);
1021 GLint length;
1022 glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
1023 str.resize(length > 0 ? length - 1 : 0);
1024 glGetProgramInfoLog(obj, length, nullptr, &str[0]);
1025 });
1026 return jsi::String::createFromUtf8(runtime, str);
1027 }
1028
NATIVE_METHOD(getShaderInfoLog)1029 NATIVE_METHOD(getShaderInfoLog) {
1030 CTX();
1031 auto fObj = ARG(0, ABI47_0_0EXWebGLClass);
1032 std::string str;
1033 ctx->addBlockingToNextBatch([&] {
1034 GLuint obj = ctx->lookupObject(fObj);
1035 GLint length;
1036 glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
1037 str.resize(length > 0 ? length - 1 : 0);
1038 glGetShaderInfoLog(obj, length, nullptr, &str[0]);
1039 });
1040 return jsi::String::createFromUtf8(runtime, str);
1041 }
1042
NATIVE_METHOD(getShaderSource)1043 NATIVE_METHOD(getShaderSource) {
1044 CTX();
1045 auto fObj = ARG(0, ABI47_0_0EXWebGLClass);
1046 std::string str;
1047 ctx->addBlockingToNextBatch([&] {
1048 GLuint obj = ctx->lookupObject(fObj);
1049 GLint length;
1050 glGetShaderiv(obj, GL_SHADER_SOURCE_LENGTH, &length);
1051 str.resize(length > 0 ? length - 1 : 0);
1052 glGetShaderSource(obj, length, nullptr, &str[0]);
1053 });
1054 return jsi::String::createFromUtf8(runtime, str);
1055 }
1056
NATIVE_METHOD(isShader)1057 NATIVE_METHOD(isShader) {
1058 CTX();
1059 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsShader);
1060 }
1061
NATIVE_METHOD(isProgram)1062 NATIVE_METHOD(isProgram) {
1063 CTX();
1064 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsProgram);
1065 }
1066
NATIVE_METHOD(linkProgram)1067 NATIVE_METHOD(linkProgram) {
1068 CTX();
1069 auto fProgram = ARG(0, ABI47_0_0EXWebGLClass);
1070 ctx->addToNextBatch([=] { glLinkProgram(ctx->lookupObject(fProgram)); });
1071 return nullptr;
1072 }
1073
NATIVE_METHOD(shaderSource)1074 NATIVE_METHOD(shaderSource) {
1075 CTX();
1076 auto fShader = ARG(0, ABI47_0_0EXWebGLClass);
1077 auto str = ARG(1, std::string);
1078 ctx->addToNextBatch([=, str{std::move(str)}] {
1079 const char *cstr = str.c_str();
1080 glShaderSource(ctx->lookupObject(fShader), 1, &cstr, nullptr);
1081 });
1082 return nullptr;
1083 }
1084
NATIVE_METHOD(useProgram)1085 NATIVE_METHOD(useProgram) {
1086 CTX();
1087 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1088 ctx->addToNextBatch([=] { glUseProgram(ctx->lookupObject(program)); });
1089 return nullptr;
1090 }
1091
NATIVE_METHOD(validateProgram)1092 NATIVE_METHOD(validateProgram) {
1093 CTX();
1094 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1095 ctx->addToNextBatch([=] { glValidateProgram(ctx->lookupObject(program)); });
1096 return nullptr;
1097 }
1098
1099 // Programs and shaders (WebGL2)
1100
NATIVE_METHOD(getFragDataLocation)1101 NATIVE_METHOD(getFragDataLocation) {
1102 CTX();
1103 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1104 auto name = ARG(1, std::string);
1105 GLint location;
1106 ctx->addBlockingToNextBatch(
1107 [&] { location = glGetFragDataLocation(ctx->lookupObject(program), name.c_str()); });
1108 return location == -1 ? jsi::Value::null() : jsi::Value(location);
1109 }
1110
1111 // Uniforms and attributes
1112 // -----------------------
1113
1114 SIMPLE_NATIVE_METHOD(disableVertexAttribArray, glDisableVertexAttribArray); // index
1115
1116 SIMPLE_NATIVE_METHOD(enableVertexAttribArray, glEnableVertexAttribArray); // index
1117
NATIVE_METHOD(getActiveAttrib)1118 NATIVE_METHOD(getActiveAttrib) {
1119 CTX();
1120 return exglGetActiveInfo(
1121 ctx,
1122 runtime,
1123 ARG(0, ABI47_0_0EXWebGLClass),
1124 ARG(1, GLuint),
1125 GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
1126 glGetActiveAttrib);
1127 }
1128
NATIVE_METHOD(getActiveUniform)1129 NATIVE_METHOD(getActiveUniform) {
1130 CTX();
1131 return exglGetActiveInfo(
1132 ctx,
1133 runtime,
1134 ARG(0, ABI47_0_0EXWebGLClass),
1135 ARG(1, GLuint),
1136 GL_ACTIVE_UNIFORM_MAX_LENGTH,
1137 glGetActiveUniform);
1138 }
1139
NATIVE_METHOD(getAttribLocation)1140 NATIVE_METHOD(getAttribLocation) {
1141 CTX();
1142 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1143 auto name = ARG(1, std::string);
1144 GLint location;
1145 ctx->addBlockingToNextBatch(
1146 [&] { location = glGetAttribLocation(ctx->lookupObject(program), name.c_str()); });
1147 return jsi::Value(location);
1148 }
1149
1150 UNIMPL_NATIVE_METHOD(getUniform)
1151
NATIVE_METHOD(getUniformLocation)1152 NATIVE_METHOD(getUniformLocation) {
1153 CTX();
1154 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1155 auto name = ARG(1, std::string);
1156 GLint location;
1157 ctx->addBlockingToNextBatch(
1158 [&] { location = glGetUniformLocation(ctx->lookupObject(program), name.c_str()); });
1159 return location == -1
1160 ? jsi::Value::null()
1161 : createWebGLObject(runtime, ABI47_0_0EXWebGLClass::WebGLUniformLocation, {location});
1162 }
1163
1164 UNIMPL_NATIVE_METHOD(getVertexAttrib)
1165
UNIMPL_NATIVE_METHOD(getVertexAttribOffset)1166 UNIMPL_NATIVE_METHOD(getVertexAttribOffset)
1167
1168 NATIVE_METHOD(uniform1f) {
1169 CTX();
1170 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1171 auto x = ARG(1, GLfloat);
1172 ctx->addToNextBatch([uniform, x]() { glUniform1f(uniform, x); });
1173 return nullptr;
1174 }
1175
NATIVE_METHOD(uniform2f)1176 NATIVE_METHOD(uniform2f) {
1177 CTX();
1178 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1179 auto x = ARG(1, GLfloat);
1180 auto y = ARG(2, GLfloat);
1181 ctx->addToNextBatch([uniform, x, y]() { glUniform2f(uniform, x, y); });
1182 return nullptr;
1183 }
1184
NATIVE_METHOD(uniform3f)1185 NATIVE_METHOD(uniform3f) {
1186 CTX();
1187 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1188 auto x = ARG(1, GLfloat);
1189 auto y = ARG(2, GLfloat);
1190 auto z = ARG(3, GLfloat);
1191 ctx->addToNextBatch([uniform, x, y, z]() { glUniform3f(uniform, x, y, z); });
1192 return nullptr;
1193 }
1194
NATIVE_METHOD(uniform4f)1195 NATIVE_METHOD(uniform4f) {
1196 CTX();
1197 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1198 auto x = ARG(1, GLfloat);
1199 auto y = ARG(2, GLfloat);
1200 auto z = ARG(3, GLfloat);
1201 auto w = ARG(4, GLfloat);
1202 ctx->addToNextBatch([uniform, x, y, z, w]() { glUniform4f(uniform, x, y, z, w); });
1203 return nullptr;
1204 }
1205
NATIVE_METHOD(uniform1i)1206 NATIVE_METHOD(uniform1i) {
1207 CTX();
1208 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1209 auto x = ARG(1, GLint);
1210 ctx->addToNextBatch([uniform, x]() { glUniform1i(uniform, x); });
1211 return nullptr;
1212 }
1213
NATIVE_METHOD(uniform2i)1214 NATIVE_METHOD(uniform2i) {
1215 CTX();
1216 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1217 auto x = ARG(1, GLint);
1218 auto y = ARG(2, GLint);
1219 ctx->addToNextBatch([uniform, x, y]() { glUniform2i(uniform, x, y); });
1220 return nullptr;
1221 }
1222
NATIVE_METHOD(uniform3i)1223 NATIVE_METHOD(uniform3i) {
1224 CTX();
1225 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1226 auto x = ARG(1, GLint);
1227 auto y = ARG(2, GLint);
1228 auto z = ARG(3, GLint);
1229 ctx->addToNextBatch([uniform, x, y, z]() { glUniform3i(uniform, x, y, z); });
1230 return nullptr;
1231 }
1232
NATIVE_METHOD(uniform4i)1233 NATIVE_METHOD(uniform4i) {
1234 CTX();
1235 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1236 auto x = ARG(1, GLint);
1237 auto y = ARG(2, GLint);
1238 auto z = ARG(3, GLint);
1239 auto w = ARG(4, GLint);
1240 ctx->addToNextBatch([uniform, x, y, z, w]() { glUniform4i(uniform, x, y, z, w); });
1241 return nullptr;
1242 }
1243
NATIVE_METHOD(uniform1fv)1244 NATIVE_METHOD(uniform1fv) {
1245 CTX();
1246 return exglUniformv(ctx, glUniform1fv, ARG(0, ABI47_0_0EXWebGLClass), 1, ARG(1, std::vector<float>));
1247 };
1248
NATIVE_METHOD(uniform2fv)1249 NATIVE_METHOD(uniform2fv) {
1250 CTX();
1251 return exglUniformv(ctx, glUniform2fv, ARG(0, ABI47_0_0EXWebGLClass), 2, ARG(1, std::vector<float>));
1252 };
1253
NATIVE_METHOD(uniform3fv)1254 NATIVE_METHOD(uniform3fv) {
1255 CTX();
1256 return exglUniformv(ctx, glUniform3fv, ARG(0, ABI47_0_0EXWebGLClass), 3, ARG(1, std::vector<float>));
1257 };
1258
NATIVE_METHOD(uniform4fv)1259 NATIVE_METHOD(uniform4fv) {
1260 CTX();
1261 return exglUniformv(ctx, glUniform4fv, ARG(0, ABI47_0_0EXWebGLClass), 4, ARG(1, std::vector<float>));
1262 };
1263
NATIVE_METHOD(uniform1iv)1264 NATIVE_METHOD(uniform1iv) {
1265 CTX();
1266 return exglUniformv(ctx, glUniform1iv, ARG(0, ABI47_0_0EXWebGLClass), 1, ARG(1, std::vector<int32_t>));
1267 };
1268
NATIVE_METHOD(uniform2iv)1269 NATIVE_METHOD(uniform2iv) {
1270 CTX();
1271 return exglUniformv(ctx, glUniform2iv, ARG(0, ABI47_0_0EXWebGLClass), 2, ARG(1, std::vector<int32_t>));
1272 };
1273
NATIVE_METHOD(uniform3iv)1274 NATIVE_METHOD(uniform3iv) {
1275 CTX();
1276 return exglUniformv(ctx, glUniform3iv, ARG(0, ABI47_0_0EXWebGLClass), 3, ARG(1, std::vector<int32_t>));
1277 };
1278
NATIVE_METHOD(uniform4iv)1279 NATIVE_METHOD(uniform4iv) {
1280 CTX();
1281 return exglUniformv(ctx, glUniform4iv, ARG(0, ABI47_0_0EXWebGLClass), 4, ARG(1, std::vector<int32_t>));
1282 };
1283
NATIVE_METHOD(uniformMatrix2fv)1284 NATIVE_METHOD(uniformMatrix2fv) {
1285 CTX();
1286 return exglUniformMatrixv(
1287 ctx,
1288 glUniformMatrix2fv,
1289 ARG(0, ABI47_0_0EXWebGLClass),
1290 ARG(1, GLboolean),
1291 4,
1292 ARG(2, std::vector<float>));
1293 }
1294
NATIVE_METHOD(uniformMatrix3fv)1295 NATIVE_METHOD(uniformMatrix3fv) {
1296 CTX();
1297 return exglUniformMatrixv(
1298 ctx,
1299 glUniformMatrix3fv,
1300 ARG(0, ABI47_0_0EXWebGLClass),
1301 ARG(1, GLboolean),
1302 9,
1303 ARG(2, std::vector<float>));
1304 }
1305
NATIVE_METHOD(uniformMatrix4fv)1306 NATIVE_METHOD(uniformMatrix4fv) {
1307 CTX();
1308 return exglUniformMatrixv(
1309 ctx,
1310 glUniformMatrix4fv,
1311 ARG(0, ABI47_0_0EXWebGLClass),
1312 ARG(1, GLboolean),
1313 16,
1314 ARG(2, std::vector<float>));
1315 }
1316
NATIVE_METHOD(vertexAttrib1fv)1317 NATIVE_METHOD(vertexAttrib1fv) {
1318 CTX();
1319 return exglVertexAttribv(
1320 ctx, glVertexAttrib1fv, ARG(0, ABI47_0_0EXWebGLClass), ARG(1, std::vector<float>));
1321 }
1322
NATIVE_METHOD(vertexAttrib2fv)1323 NATIVE_METHOD(vertexAttrib2fv) {
1324 CTX();
1325 return exglVertexAttribv(
1326 ctx, glVertexAttrib2fv, ARG(0, ABI47_0_0EXWebGLClass), ARG(1, std::vector<float>));
1327 }
1328
NATIVE_METHOD(vertexAttrib3fv)1329 NATIVE_METHOD(vertexAttrib3fv) {
1330 CTX();
1331 return exglVertexAttribv(
1332 ctx, glVertexAttrib3fv, ARG(0, ABI47_0_0EXWebGLClass), ARG(1, std::vector<float>));
1333 }
1334
NATIVE_METHOD(vertexAttrib4fv)1335 NATIVE_METHOD(vertexAttrib4fv) {
1336 CTX();
1337 return exglVertexAttribv(
1338 ctx, glVertexAttrib4fv, ARG(0, ABI47_0_0EXWebGLClass), ARG(1, std::vector<float>));
1339 }
1340
1341 SIMPLE_NATIVE_METHOD(vertexAttrib1f, glVertexAttrib1f); // index, x
1342 SIMPLE_NATIVE_METHOD(vertexAttrib2f, glVertexAttrib2f); // index, x, y
1343 SIMPLE_NATIVE_METHOD(vertexAttrib3f, glVertexAttrib3f); // index, x, y, z
1344 SIMPLE_NATIVE_METHOD(vertexAttrib4f, glVertexAttrib4f); // index, x, y, z, w
1345
1346 SIMPLE_NATIVE_METHOD(
1347 vertexAttribPointer,
1348 glVertexAttribPointer); // index, itemSize, type, normalized, stride, const void *
1349
1350 // Uniforms and attributes (WebGL2)
1351 // --------------------------------
1352
NATIVE_METHOD(uniform1ui)1353 NATIVE_METHOD(uniform1ui) {
1354 CTX();
1355 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1356 auto x = ARG(1, GLuint);
1357 ctx->addToNextBatch([uniform, x]() { glUniform1ui(uniform, x); });
1358 return nullptr;
1359 }
1360
NATIVE_METHOD(uniform2ui)1361 NATIVE_METHOD(uniform2ui) {
1362 CTX();
1363 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1364 auto x = ARG(1, GLuint);
1365 auto y = ARG(2, GLuint);
1366 ctx->addToNextBatch([uniform, x, y]() { glUniform2ui(uniform, x, y); });
1367 return nullptr;
1368 }
1369
NATIVE_METHOD(uniform3ui)1370 NATIVE_METHOD(uniform3ui) {
1371 CTX();
1372 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1373 auto x = ARG(1, GLuint);
1374 auto y = ARG(2, GLuint);
1375 auto z = ARG(3, GLuint);
1376 ctx->addToNextBatch([uniform, x, y, z]() { glUniform3ui(uniform, x, y, z); });
1377 return nullptr;
1378 }
1379
NATIVE_METHOD(uniform4ui)1380 NATIVE_METHOD(uniform4ui) {
1381 CTX();
1382 auto uniform = ARG(0, ABI47_0_0EXWebGLClass);
1383 auto x = ARG(1, GLuint);
1384 auto y = ARG(2, GLuint);
1385 auto z = ARG(3, GLuint);
1386 auto w = ARG(4, GLuint);
1387 ctx->addToNextBatch([uniform, x, y, z, w]() { glUniform4ui(uniform, x, y, z, w); });
1388 return nullptr;
1389 }
1390
NATIVE_METHOD(uniform1uiv)1391 NATIVE_METHOD(uniform1uiv) {
1392 CTX();
1393 return exglUniformv(ctx, glUniform1uiv, ARG(0, ABI47_0_0EXWebGLClass), 1, ARG(1, std::vector<uint32_t>));
1394 };
1395
NATIVE_METHOD(uniform2uiv)1396 NATIVE_METHOD(uniform2uiv) {
1397 CTX();
1398 return exglUniformv(ctx, glUniform2uiv, ARG(0, ABI47_0_0EXWebGLClass), 2, ARG(1, std::vector<uint32_t>));
1399 };
1400
NATIVE_METHOD(uniform3uiv)1401 NATIVE_METHOD(uniform3uiv) {
1402 CTX();
1403 return exglUniformv(ctx, glUniform3uiv, ARG(0, ABI47_0_0EXWebGLClass), 3, ARG(1, std::vector<uint32_t>));
1404 };
1405
NATIVE_METHOD(uniform4uiv)1406 NATIVE_METHOD(uniform4uiv) {
1407 CTX();
1408 return exglUniformv(ctx, glUniform4uiv, ARG(0, ABI47_0_0EXWebGLClass), 4, ARG(1, std::vector<uint32_t>));
1409 };
1410
NATIVE_METHOD(uniformMatrix3x2fv)1411 NATIVE_METHOD(uniformMatrix3x2fv) {
1412 CTX();
1413 return exglUniformMatrixv(
1414 ctx,
1415 glUniformMatrix3x2fv,
1416 ARG(0, ABI47_0_0EXWebGLClass),
1417 ARG(1, GLboolean),
1418 6,
1419 ARG(2, std::vector<float>));
1420 }
1421
NATIVE_METHOD(uniformMatrix4x2fv)1422 NATIVE_METHOD(uniformMatrix4x2fv) {
1423 CTX();
1424 return exglUniformMatrixv(
1425 ctx,
1426 glUniformMatrix4x2fv,
1427 ARG(0, ABI47_0_0EXWebGLClass),
1428 ARG(1, GLboolean),
1429 8,
1430 ARG(2, std::vector<float>));
1431 }
1432
NATIVE_METHOD(uniformMatrix2x3fv)1433 NATIVE_METHOD(uniformMatrix2x3fv) {
1434 CTX();
1435 return exglUniformMatrixv(
1436 ctx,
1437 glUniformMatrix2x3fv,
1438 ARG(0, ABI47_0_0EXWebGLClass),
1439 ARG(1, GLboolean),
1440 6,
1441 ARG(2, std::vector<float>));
1442 }
1443
NATIVE_METHOD(uniformMatrix4x3fv)1444 NATIVE_METHOD(uniformMatrix4x3fv) {
1445 CTX();
1446 return exglUniformMatrixv(
1447 ctx,
1448 glUniformMatrix4x3fv,
1449 ARG(0, ABI47_0_0EXWebGLClass),
1450 ARG(1, GLboolean),
1451 12,
1452 ARG(2, std::vector<float>));
1453 }
1454
NATIVE_METHOD(uniformMatrix2x4fv)1455 NATIVE_METHOD(uniformMatrix2x4fv) {
1456 CTX();
1457 return exglUniformMatrixv(
1458 ctx,
1459 glUniformMatrix2x4fv,
1460 ARG(0, ABI47_0_0EXWebGLClass),
1461 ARG(1, GLboolean),
1462 8,
1463 ARG(2, std::vector<float>));
1464 }
1465
NATIVE_METHOD(uniformMatrix3x4fv)1466 NATIVE_METHOD(uniformMatrix3x4fv) {
1467 CTX();
1468 return exglUniformMatrixv(
1469 ctx,
1470 glUniformMatrix3x4fv,
1471 ARG(0, ABI47_0_0EXWebGLClass),
1472 ARG(1, GLboolean),
1473 12,
1474 ARG(2, std::vector<float>));
1475 }
1476
1477 SIMPLE_NATIVE_METHOD(vertexAttribI4i, glVertexAttribI4i); // index, x, y, z, w
1478 SIMPLE_NATIVE_METHOD(vertexAttribI4ui, glVertexAttribI4ui); // index, x, y, z, w
1479
NATIVE_METHOD(vertexAttribI4iv)1480 NATIVE_METHOD(vertexAttribI4iv) {
1481 CTX();
1482 return exglVertexAttribv(ctx, glVertexAttribI4iv, ARG(0, GLuint), ARG(1, std::vector<int32_t>));
1483 }
1484
NATIVE_METHOD(vertexAttribI4uiv)1485 NATIVE_METHOD(vertexAttribI4uiv) {
1486 CTX();
1487 return exglVertexAttribv(ctx, glVertexAttribI4uiv, ARG(0, GLuint), ARG(1, std::vector<uint32_t>));
1488 }
1489
1490 SIMPLE_NATIVE_METHOD(
1491 vertexAttribIPointer,
1492 glVertexAttribIPointer); // index, size, type, stride, offset
1493
1494 // Drawing buffers
1495 // ---------------
1496
1497 SIMPLE_NATIVE_METHOD(clear, glClear); // mask
1498
1499 SIMPLE_NATIVE_METHOD(drawArrays, glDrawArrays); // mode, first, count)
1500
1501 SIMPLE_NATIVE_METHOD(drawElements, glDrawElements); // mode, count, type, offset
1502
1503 SIMPLE_NATIVE_METHOD(finish, glFinish);
1504
1505 SIMPLE_NATIVE_METHOD(flush, glFlush);
1506
1507 // Drawing buffers (WebGL2)
1508 // ------------------------
1509
1510 SIMPLE_NATIVE_METHOD(vertexAttribDivisor, glVertexAttribDivisor); // index, divisor
1511
1512 SIMPLE_NATIVE_METHOD(
1513 drawArraysInstanced,
1514 glDrawArraysInstanced); // mode, first, count, instancecount
1515
1516 SIMPLE_NATIVE_METHOD(
1517 drawElementsInstanced,
1518 glDrawElementsInstanced); // mode, count, type, offset, instanceCount
1519
1520 SIMPLE_NATIVE_METHOD(
1521 drawRangeElements,
1522 glDrawRangeElements); // mode, start, end, count, type, offset
1523
NATIVE_METHOD(drawBuffers)1524 NATIVE_METHOD(drawBuffers) {
1525 CTX();
1526 auto data = jsArrayToVector<GLenum>(runtime, ARG(0, jsi::Array));
1527 ctx->addToNextBatch(
1528 [data{std::move(data)}] { glDrawBuffers(static_cast<GLsizei>(data.size()), data.data()); });
1529 return nullptr;
1530 }
1531
NATIVE_METHOD(clearBufferfv)1532 NATIVE_METHOD(clearBufferfv) {
1533 CTX();
1534 auto buffer = ARG(0, GLenum);
1535 auto drawbuffer = ARG(1, GLint);
1536 auto values = ARG(2, TypedArrayKind::Float32Array).toVector(runtime);
1537 ctx->addToNextBatch(
1538 [=, values{std::move(values)}] { glClearBufferfv(buffer, drawbuffer, values.data()); });
1539 return nullptr;
1540 }
1541
NATIVE_METHOD(clearBufferiv)1542 NATIVE_METHOD(clearBufferiv) {
1543 CTX();
1544 auto buffer = ARG(0, GLenum);
1545 auto drawbuffer = ARG(1, GLint);
1546 auto values = ARG(2, TypedArrayKind::Int32Array).toVector(runtime);
1547 ctx->addToNextBatch(
1548 [=, values{std::move(values)}] { glClearBufferiv(buffer, drawbuffer, values.data()); });
1549 return nullptr;
1550 }
1551
NATIVE_METHOD(clearBufferuiv)1552 NATIVE_METHOD(clearBufferuiv) {
1553 CTX();
1554 auto buffer = ARG(0, GLenum);
1555 auto drawbuffer = ARG(1, GLint);
1556 auto values = ARG(2, TypedArrayKind::Uint32Array).toVector(runtime);
1557 ctx->addToNextBatch(
1558 [=, values{std::move(values)}] { glClearBufferuiv(buffer, drawbuffer, values.data()); });
1559 return nullptr;
1560 }
1561
1562 SIMPLE_NATIVE_METHOD(clearBufferfi, glClearBufferfi); // buffer, drawbuffer, depth, stencil
1563
1564 // Query objects (WebGL2)
1565 // ----------------------
1566
NATIVE_METHOD(createQuery)1567 NATIVE_METHOD(createQuery) {
1568 CTX();
1569 return exglGenObject(ctx, runtime, glGenQueries, ABI47_0_0EXWebGLClass::WebGLQuery);
1570 }
1571
NATIVE_METHOD(deleteQuery)1572 NATIVE_METHOD(deleteQuery) {
1573 CTX();
1574 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteQueries);
1575 }
1576
NATIVE_METHOD(isQuery)1577 NATIVE_METHOD(isQuery) {
1578 CTX();
1579 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsQuery);
1580 }
1581
NATIVE_METHOD(beginQuery)1582 NATIVE_METHOD(beginQuery) {
1583 CTX();
1584 auto target = ARG(0, GLenum);
1585 auto query = ARG(1, ABI47_0_0EXWebGLClass);
1586 ctx->addToNextBatch([=] { glBeginQuery(target, ctx->lookupObject(query)); });
1587 return nullptr;
1588 }
1589
1590 SIMPLE_NATIVE_METHOD(endQuery, glEndQuery); // target
1591
NATIVE_METHOD(getQuery)1592 NATIVE_METHOD(getQuery) {
1593 CTX();
1594 auto target = ARG(0, GLenum);
1595 auto pname = ARG(1, GLenum);
1596 GLint params;
1597 ctx->addBlockingToNextBatch([&] { glGetQueryiv(target, pname, ¶ms); });
1598 return params == 0
1599 ? jsi::Value::null()
1600 : createWebGLObject(runtime, ABI47_0_0EXWebGLClass::WebGLQuery, {static_cast<double>(params)});
1601 }
1602
NATIVE_METHOD(getQueryParameter)1603 NATIVE_METHOD(getQueryParameter) {
1604 CTX();
1605 auto query = ARG(0, ABI47_0_0EXWebGLClass);
1606 auto pname = ARG(1, GLenum);
1607 GLuint params;
1608 ctx->addBlockingToNextBatch(
1609 [&] { glGetQueryObjectuiv(ctx->lookupObject(query), pname, ¶ms); });
1610 return params == 0 ? jsi::Value::null() : static_cast<double>(params);
1611 }
1612
1613 // Samplers (WebGL2)
1614 // -----------------
1615
NATIVE_METHOD(createSampler)1616 NATIVE_METHOD(createSampler) {
1617 CTX();
1618 return exglGenObject(ctx, runtime, glGenSamplers, ABI47_0_0EXWebGLClass::WebGLSampler);
1619 }
1620
NATIVE_METHOD(deleteSampler)1621 NATIVE_METHOD(deleteSampler) {
1622 CTX();
1623 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteSamplers);
1624 }
1625
NATIVE_METHOD(bindSampler)1626 NATIVE_METHOD(bindSampler) {
1627 CTX();
1628 auto unit = ARG(0, GLuint);
1629 auto sampler = ARG(1, ABI47_0_0EXWebGLClass);
1630 ctx->addToNextBatch([=] { glBindSampler(unit, ctx->lookupObject(sampler)); });
1631 return nullptr;
1632 }
1633
NATIVE_METHOD(isSampler)1634 NATIVE_METHOD(isSampler) {
1635 CTX();
1636 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsSampler);
1637 }
1638
NATIVE_METHOD(samplerParameteri)1639 NATIVE_METHOD(samplerParameteri) {
1640 CTX();
1641 auto sampler = ARG(0, ABI47_0_0EXWebGLClass);
1642 auto pname = ARG(1, GLenum);
1643 auto param = ARG(2, GLfloat);
1644 ctx->addToNextBatch([=] { glSamplerParameteri(ctx->lookupObject(sampler), pname, param); });
1645 return nullptr;
1646 }
1647
NATIVE_METHOD(samplerParameterf)1648 NATIVE_METHOD(samplerParameterf) {
1649 CTX();
1650 auto sampler = ARG(0, ABI47_0_0EXWebGLClass);
1651 auto pname = ARG(1, GLenum);
1652 auto param = ARG(2, GLfloat);
1653 ctx->addToNextBatch([=] { glSamplerParameterf(ctx->lookupObject(sampler), pname, param); });
1654 return nullptr;
1655 }
1656
NATIVE_METHOD(getSamplerParameter)1657 NATIVE_METHOD(getSamplerParameter) {
1658 CTX();
1659 auto sampler = ARG(0, ABI47_0_0EXWebGLClass);
1660 auto pname = ARG(1, GLenum);
1661 bool isFloatParam = pname == GL_TEXTURE_MAX_LOD || pname == GL_TEXTURE_MIN_LOD;
1662 union {
1663 GLfloat f;
1664 GLint i;
1665 } param;
1666
1667 ctx->addBlockingToNextBatch([&] {
1668 if (isFloatParam) {
1669 glGetSamplerParameterfv(ctx->lookupObject(sampler), pname, ¶m.f);
1670 } else {
1671 glGetSamplerParameteriv(ctx->lookupObject(sampler), pname, ¶m.i);
1672 }
1673 });
1674 return isFloatParam ? static_cast<double>(param.f) : static_cast<double>(param.i);
1675 }
1676
1677 // Sync objects (WebGL2)
1678 // ---------------------
1679
1680 UNIMPL_NATIVE_METHOD(fenceSync)
1681
UNIMPL_NATIVE_METHOD(isSync)1682 UNIMPL_NATIVE_METHOD(isSync)
1683
1684 UNIMPL_NATIVE_METHOD(deleteSync)
1685
1686 UNIMPL_NATIVE_METHOD(clientWaitSync)
1687
1688 UNIMPL_NATIVE_METHOD(waitSync)
1689
1690 UNIMPL_NATIVE_METHOD(getSyncParameter)
1691
1692 // Transform feedback (WebGL2)
1693 // ---------------------------
1694
1695 NATIVE_METHOD(createTransformFeedback) {
1696 CTX();
1697 return exglGenObject(ctx, runtime, glGenTransformFeedbacks, ABI47_0_0EXWebGLClass::WebGLTransformFeedback);
1698 }
1699
NATIVE_METHOD(deleteTransformFeedback)1700 NATIVE_METHOD(deleteTransformFeedback) {
1701 CTX();
1702 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteTransformFeedbacks);
1703 }
1704
NATIVE_METHOD(isTransformFeedback)1705 NATIVE_METHOD(isTransformFeedback) {
1706 CTX();
1707 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsTransformFeedback);
1708 }
1709
NATIVE_METHOD(bindTransformFeedback)1710 NATIVE_METHOD(bindTransformFeedback) {
1711 CTX();
1712 auto target = ARG(0, GLenum);
1713 auto transformFeedback = ARG(1, ABI47_0_0EXWebGLClass);
1714 ctx->addToNextBatch(
1715 [=] { glBindTransformFeedback(target, ctx->lookupObject(transformFeedback)); });
1716 return nullptr;
1717 }
1718
1719 SIMPLE_NATIVE_METHOD(beginTransformFeedback, glBeginTransformFeedback); // primitiveMode
1720
1721 SIMPLE_NATIVE_METHOD(endTransformFeedback, glEndTransformFeedback);
1722
NATIVE_METHOD(transformFeedbackVaryings)1723 NATIVE_METHOD(transformFeedbackVaryings) {
1724 CTX();
1725 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1726 std::vector<std::string> varyings = jsArrayToVector<std::string>(runtime, ARG(1, jsi::Array));
1727 auto bufferMode = ARG(2, GLenum);
1728
1729 ctx->addToNextBatch([=, varyings{std::move(varyings)}] {
1730 std::vector<const char *> varyingsRaw(varyings.size());
1731 std::transform(
1732 varyings.begin(), varyings.end(), varyingsRaw.begin(), [](const std::string &str) {
1733 return str.c_str();
1734 });
1735
1736 glTransformFeedbackVaryings(
1737 ctx->lookupObject(program),
1738 static_cast<GLsizei>(varyingsRaw.size()),
1739 varyingsRaw.data(),
1740 bufferMode);
1741 });
1742 return nullptr;
1743 }
1744
NATIVE_METHOD(getTransformFeedbackVarying)1745 NATIVE_METHOD(getTransformFeedbackVarying) {
1746 CTX();
1747 return exglGetActiveInfo(
1748 ctx,
1749 runtime,
1750 ARG(0, ABI47_0_0EXWebGLClass),
1751 ARG(1, GLuint),
1752 GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
1753 glGetTransformFeedbackVarying);
1754 }
1755
1756 SIMPLE_NATIVE_METHOD(pauseTransformFeedback, glPauseTransformFeedback);
1757
1758 SIMPLE_NATIVE_METHOD(resumeTransformFeedback, glResumeTransformFeedback);
1759
1760 // Uniform buffer objects (WebGL2)
1761 // -------------------------------
1762
NATIVE_METHOD(bindBufferBase)1763 NATIVE_METHOD(bindBufferBase) {
1764 CTX();
1765 auto target = ARG(0, GLenum);
1766 auto index = ARG(1, GLuint);
1767 auto buffer = ARG(2, ABI47_0_0EXWebGLClass);
1768 ctx->addToNextBatch([=] { glBindBufferBase(target, index, ctx->lookupObject(buffer)); });
1769 return nullptr;
1770 }
1771
NATIVE_METHOD(bindBufferRange)1772 NATIVE_METHOD(bindBufferRange) {
1773 CTX();
1774 auto target = ARG(0, GLenum);
1775 auto index = ARG(1, GLuint);
1776 auto buffer = ARG(2, ABI47_0_0EXWebGLClass);
1777 auto offset = ARG(3, GLint);
1778 auto size = ARG(4, GLsizei);
1779 ctx->addToNextBatch(
1780 [=] { glBindBufferRange(target, index, ctx->lookupObject(buffer), offset, size); });
1781 return nullptr;
1782 }
1783
NATIVE_METHOD(getUniformIndices)1784 NATIVE_METHOD(getUniformIndices) {
1785 CTX();
1786 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1787 std::vector<std::string> uniformNames = jsArrayToVector<std::string>(runtime, ARG(1, jsi::Array));
1788
1789 std::vector<const char *> uniformNamesRaw(uniformNames.size());
1790 std::transform(
1791 uniformNames.begin(),
1792 uniformNames.end(),
1793 uniformNamesRaw.begin(),
1794 [](const std::string &str) { return str.c_str(); });
1795
1796 std::vector<GLuint> indices(uniformNames.size());
1797 ctx->addBlockingToNextBatch([&] {
1798 glGetUniformIndices(
1799 ctx->lookupObject(program),
1800 static_cast<GLsizei>(uniformNames.size()),
1801 uniformNamesRaw.data(),
1802 &indices[0]);
1803 });
1804 jsi::Array jsResult(runtime, indices.size());
1805 for (unsigned int i = 0; i < indices.size(); i++) {
1806 jsResult.setValueAtIndex(runtime, i, static_cast<double>(indices[i]));
1807 }
1808 return jsResult;
1809 }
1810
NATIVE_METHOD(getActiveUniforms)1811 NATIVE_METHOD(getActiveUniforms) {
1812 CTX();
1813 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1814 auto uniformIndices = jsArrayToVector<GLuint>(runtime, ARG(1, jsi::Array));
1815 auto pname = ARG(2, GLenum);
1816 std::vector<GLint> params(uniformIndices.size());
1817
1818 ctx->addBlockingToNextBatch([&] {
1819 glGetActiveUniformsiv(
1820 ctx->lookupObject(program),
1821 static_cast<GLsizei>(uniformIndices.size()),
1822 uniformIndices.data(),
1823 pname,
1824 ¶ms[0]);
1825 });
1826 jsi::Array jsResult(runtime, params.size());
1827 for (unsigned int i = 0; i < params.size(); i++) {
1828 jsResult.setValueAtIndex(
1829 runtime,
1830 i,
1831 pname == GL_UNIFORM_IS_ROW_MAJOR ? params[i] != 0 : static_cast<double>(params[i]));
1832 }
1833 return jsResult;
1834 }
1835
NATIVE_METHOD(getUniformBlockIndex)1836 NATIVE_METHOD(getUniformBlockIndex) {
1837 CTX();
1838 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1839 auto uniformBlockName = ARG(1, std::string);
1840
1841 GLuint blockIndex;
1842 ctx->addBlockingToNextBatch([&] {
1843 blockIndex = glGetUniformBlockIndex(ctx->lookupObject(program), uniformBlockName.c_str());
1844 });
1845 return static_cast<double>(blockIndex);
1846 }
1847
1848 UNIMPL_NATIVE_METHOD(getActiveUniformBlockParameter)
1849
NATIVE_METHOD(getActiveUniformBlockName)1850 NATIVE_METHOD(getActiveUniformBlockName) {
1851 CTX();
1852 auto fProgram = ARG(0, ABI47_0_0EXWebGLClass);
1853 auto uniformBlockIndex = ARG(1, GLuint);
1854
1855 std::string blockName;
1856 ctx->addBlockingToNextBatch([&] {
1857 GLuint program = ctx->lookupObject(fProgram);
1858 GLint bufSize;
1859 glGetActiveUniformBlockiv(program, uniformBlockIndex, GL_UNIFORM_BLOCK_NAME_LENGTH, &bufSize);
1860 blockName.resize(bufSize > 0 ? bufSize - 1 : 0);
1861 glGetActiveUniformBlockName(program, uniformBlockIndex, bufSize, NULL, &blockName[0]);
1862 });
1863 return jsi::String::createFromUtf8(runtime, blockName);
1864 }
1865
NATIVE_METHOD(uniformBlockBinding)1866 NATIVE_METHOD(uniformBlockBinding) {
1867 CTX();
1868 auto program = ARG(0, ABI47_0_0EXWebGLClass);
1869 auto uniformBlockIndex = ARG(1, GLuint);
1870 auto uniformBlockBinding = ARG(2, GLuint);
1871 ctx->addToNextBatch([=] {
1872 glUniformBlockBinding(ctx->lookupObject(program), uniformBlockIndex, uniformBlockBinding);
1873 });
1874 return nullptr;
1875 }
1876
1877 // Vertex Array Object (WebGL2)
1878 // ----------------------------
1879
NATIVE_METHOD(createVertexArray)1880 NATIVE_METHOD(createVertexArray) {
1881 CTX();
1882 return exglGenObject(ctx, runtime, glGenVertexArrays, ABI47_0_0EXWebGLClass::WebGLVertexArrayObject);
1883 }
1884
NATIVE_METHOD(deleteVertexArray)1885 NATIVE_METHOD(deleteVertexArray) {
1886 CTX();
1887 return exglDeleteObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glDeleteVertexArrays);
1888 }
1889
NATIVE_METHOD(isVertexArray)1890 NATIVE_METHOD(isVertexArray) {
1891 CTX();
1892 return exglIsObject(ctx, ARG(0, ABI47_0_0EXWebGLClass), glIsVertexArray);
1893 }
1894
NATIVE_METHOD(bindVertexArray)1895 NATIVE_METHOD(bindVertexArray) {
1896 CTX();
1897 auto vertexArray = ARG(0, ABI47_0_0EXWebGLClass);
1898 ctx->addToNextBatch([=] { glBindVertexArray(ctx->lookupObject(vertexArray)); });
1899 return nullptr;
1900 }
1901
1902 // Extensions
1903 // ----------
1904
1905 // It may return some extensions that are not specified by WebGL specification nor drafts.
NATIVE_METHOD(getSupportedExtensions)1906 NATIVE_METHOD(getSupportedExtensions) {
1907 CTX();
1908 // Set with supported extensions is cached to make checks in `getExtension` faster.
1909 ctx->maybeReadAndCacheSupportedExtensions();
1910
1911 jsi::Array extensions(runtime, ctx->supportedExtensions.size());
1912 int i = 0;
1913 for (auto const &extensionName : ctx->supportedExtensions) {
1914 extensions.setValueAtIndex(runtime, i++, jsi::String::createFromUtf8(runtime, extensionName));
1915 }
1916 return extensions;
1917 }
1918
1919 #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
1920 #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
1921
NATIVE_METHOD(getExtension)1922 NATIVE_METHOD(getExtension) {
1923 CTX();
1924 auto name = ARG(0, std::string);
1925
1926 // There is no `getExtension` equivalent in OpenGL ES so return `null`
1927 // if requested extension is not returned by `getSupportedExtensions`.
1928 ctx->maybeReadAndCacheSupportedExtensions();
1929 if (ctx->supportedExtensions.find(name) == ctx->supportedExtensions.end()) {
1930 return nullptr;
1931 }
1932
1933 if (name == "ABI47_0_0EXT_texture_filter_anisotropic") {
1934 jsi::Object result(runtime);
1935 result.setProperty(
1936 runtime, "TEXTURE_MAX_ANISOTROPY_EXT", jsi::Value(GL_TEXTURE_MAX_ANISOTROPY_EXT));
1937 result.setProperty(
1938 runtime, "MAX_TEXTURE_MAX_ANISOTROPY_EXT", jsi::Value(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
1939 return result;
1940 }
1941 return jsi::Object(runtime);
1942 }
1943
1944 // Exponent extensions
1945 // -------------------
1946
NATIVE_METHOD(endFrameEXP)1947 NATIVE_METHOD(endFrameEXP) {
1948 CTX();
1949 ctx->addToNextBatch([=] { ctx->needsRedraw = true; });
1950 ctx->endNextBatch();
1951 ctx->flushOnGLThread();
1952 return nullptr;
1953 }
1954
NATIVE_METHOD(flushEXP)1955 NATIVE_METHOD(flushEXP) {
1956 CTX();
1957 // nothing, it's just a helper so that we can measure how much time some operations take
1958 ctx->addBlockingToNextBatch([&] {});
1959 return nullptr;
1960 }
1961
1962 } // namespace method
1963 } // namespace gl_cpp
1964 } // namespace ABI47_0_0expo
1965