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