16297d8c7SWojciech Kozyra #include "EXWebGLMethods.h"
26297d8c7SWojciech Kozyra #include "EXGLContextManager.h"
36297d8c7SWojciech Kozyra #include "EXGLImageUtils.h"
46297d8c7SWojciech Kozyra #include "EXJsiArgsTransform.h"
56297d8c7SWojciech Kozyra #include "EXWebGLMethodsHelpers.h"
66297d8c7SWojciech Kozyra #include "EXWebGLRenderer.h"
76297d8c7SWojciech Kozyra 
86297d8c7SWojciech Kozyra #include <algorithm>
96297d8c7SWojciech Kozyra 
106297d8c7SWojciech Kozyra #define ARG(index, type)                                   \
116297d8c7SWojciech Kozyra   (argc > index ? unpackArg<type>(runtime, jsArgv + index) \
126297d8c7SWojciech Kozyra                 : throw std::runtime_error("EXGL: Too few arguments"))
136297d8c7SWojciech Kozyra 
146297d8c7SWojciech Kozyra #define CTX()                                \
156297d8c7SWojciech Kozyra   auto result = getContext(runtime, jsThis); \
166297d8c7SWojciech Kozyra   auto ctx = result.first;                   \
176297d8c7SWojciech Kozyra   if (ctx == nullptr) {                      \
186297d8c7SWojciech Kozyra     return jsi::Value::undefined();          \
196297d8c7SWojciech Kozyra   }
206297d8c7SWojciech Kozyra 
216297d8c7SWojciech Kozyra #define NATIVE_METHOD(name, ...)    \
226297d8c7SWojciech Kozyra   jsi::Value glNativeMethod_##name( \
236297d8c7SWojciech Kozyra       jsi::Runtime &runtime, const jsi::Value &jsThis, const jsi::Value *jsArgv, size_t argc)
246297d8c7SWojciech Kozyra 
256297d8c7SWojciech Kozyra #define SIMPLE_NATIVE_METHOD(name, func)                                    \
266297d8c7SWojciech Kozyra   NATIVE_METHOD(name) {                                                     \
276297d8c7SWojciech Kozyra     CTX();                                                                  \
286297d8c7SWojciech Kozyra     ctx->addToNextBatch(generateNativeMethod(runtime, func, jsArgv, argc)); \
296297d8c7SWojciech Kozyra     return nullptr;                                                         \
306297d8c7SWojciech Kozyra   }
316297d8c7SWojciech Kozyra 
326297d8c7SWojciech Kozyra #define UNIMPL_NATIVE_METHOD(name)   \
336297d8c7SWojciech Kozyra   NATIVE_METHOD(name) {              \
346297d8c7SWojciech Kozyra     return exglUnimplemented(#name); \
356297d8c7SWojciech Kozyra   }
366297d8c7SWojciech Kozyra 
376297d8c7SWojciech Kozyra namespace expo {
386297d8c7SWojciech Kozyra namespace gl_cpp {
396297d8c7SWojciech Kozyra namespace method {
406297d8c7SWojciech Kozyra 
getContext(jsi::Runtime & runtime,const jsi::Value & jsThis)416297d8c7SWojciech Kozyra ContextWithLock getContext(jsi::Runtime &runtime, const jsi::Value &jsThis) {
426297d8c7SWojciech Kozyra   double exglCtxId = jsThis.asObject(runtime).getProperty(runtime, "contextId").asNumber();
436297d8c7SWojciech Kozyra   return ContextGet(static_cast<EXGLContextId>(exglCtxId));
446297d8c7SWojciech Kozyra }
456297d8c7SWojciech Kozyra 
466297d8c7SWojciech Kozyra // This listing follows the order in
476297d8c7SWojciech Kozyra // https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext
486297d8c7SWojciech Kozyra // https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext
496297d8c7SWojciech Kozyra 
506297d8c7SWojciech Kozyra // The WebGL context
516297d8c7SWojciech Kozyra // -----------------
526297d8c7SWojciech Kozyra 
NATIVE_METHOD(getContextAttributes)536297d8c7SWojciech Kozyra NATIVE_METHOD(getContextAttributes) {
546297d8c7SWojciech Kozyra   jsi::Object jsResult(runtime);
556297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "alpha", true);
566297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "depth", true);
576297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "stencil", true);
586297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "antialias", false);
596297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "premultipliedAlpha", false);
606297d8c7SWojciech Kozyra   return jsResult;
616297d8c7SWojciech Kozyra }
626297d8c7SWojciech Kozyra 
NATIVE_METHOD(isContextLost)636297d8c7SWojciech Kozyra NATIVE_METHOD(isContextLost) {
646297d8c7SWojciech Kozyra   return false;
656297d8c7SWojciech Kozyra }
666297d8c7SWojciech Kozyra 
676297d8c7SWojciech Kozyra // Viewing and clipping
686297d8c7SWojciech Kozyra // --------------------
696297d8c7SWojciech Kozyra 
706297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(scissor, glScissor); // x, y, width, height
716297d8c7SWojciech Kozyra 
726297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(viewport, glViewport); // x, y, width, height
736297d8c7SWojciech Kozyra 
746297d8c7SWojciech Kozyra // State information
756297d8c7SWojciech Kozyra // -----------------
766297d8c7SWojciech Kozyra 
776297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(activeTexture, glActiveTexture); // texture
786297d8c7SWojciech Kozyra 
796297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(blendColor, glBlendColor); // red, green, blue, alpha
806297d8c7SWojciech Kozyra 
816297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(blendEquation, glBlendEquation); // mode
826297d8c7SWojciech Kozyra 
836297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(blendEquationSeparate, glBlendEquationSeparate); // modeRGB, modeAlpha
846297d8c7SWojciech Kozyra 
856297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(blendFunc, glBlendFunc); // sfactor, dfactor
866297d8c7SWojciech Kozyra 
876297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(blendFuncSeparate, glBlendFuncSeparate); // srcRGB, dstRGB, srcAlpha, dstAlpha
886297d8c7SWojciech Kozyra 
896297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(clearColor, glClearColor); // red, green, blue, alpha
906297d8c7SWojciech Kozyra 
916297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(clearDepth, glClearDepthf); // depth
926297d8c7SWojciech Kozyra 
936297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(clearStencil, glClearStencil); // s
946297d8c7SWojciech Kozyra 
956297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(colorMask, glColorMask); // red, green, blue, alpha
966297d8c7SWojciech Kozyra 
976297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(cullFace, glCullFace); // mode
986297d8c7SWojciech Kozyra 
996297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(depthFunc, glDepthFunc); // func
1006297d8c7SWojciech Kozyra 
1016297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(depthMask, glDepthMask); // flag
1026297d8c7SWojciech Kozyra 
1036297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(depthRange, glDepthRangef); // zNear, zFar
1046297d8c7SWojciech Kozyra 
1056297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(disable, glDisable); // cap
1066297d8c7SWojciech Kozyra 
1076297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(enable, glEnable); // cap
1086297d8c7SWojciech Kozyra 
1096297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(frontFace, glFrontFace); // mode
1106297d8c7SWojciech Kozyra 
NATIVE_METHOD(getParameter)1116297d8c7SWojciech Kozyra NATIVE_METHOD(getParameter) {
1126297d8c7SWojciech Kozyra   CTX();
1136297d8c7SWojciech Kozyra   auto pname = ARG(0, GLenum);
1146297d8c7SWojciech Kozyra 
1156297d8c7SWojciech Kozyra   switch (pname) {
1166297d8c7SWojciech Kozyra       // Float32Array[0]
1176297d8c7SWojciech Kozyra     case GL_COMPRESSED_TEXTURE_FORMATS:
1186297d8c7SWojciech Kozyra       return TypedArray<TypedArrayKind::Float32Array>(runtime, {});
1196297d8c7SWojciech Kozyra 
1206297d8c7SWojciech Kozyra       // FLoat32Array[2]
1216297d8c7SWojciech Kozyra     case GL_ALIASED_LINE_WIDTH_RANGE:
1226297d8c7SWojciech Kozyra     case GL_ALIASED_POINT_SIZE_RANGE:
1236297d8c7SWojciech Kozyra     case GL_DEPTH_RANGE: {
1246297d8c7SWojciech Kozyra       std::vector<TypedArrayBase::ContentType<TypedArrayKind::Float32Array>> glResults(2);
1256297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetFloatv(pname, glResults.data()); });
1266297d8c7SWojciech Kozyra       return TypedArray<TypedArrayKind::Float32Array>(runtime, glResults);
1276297d8c7SWojciech Kozyra     }
1286297d8c7SWojciech Kozyra       // FLoat32Array[4]
1296297d8c7SWojciech Kozyra     case GL_BLEND_COLOR:
1306297d8c7SWojciech Kozyra     case GL_COLOR_CLEAR_VALUE: {
1316297d8c7SWojciech Kozyra       std::vector<TypedArrayBase::ContentType<TypedArrayKind::Float32Array>> glResults(4);
1326297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetFloatv(pname, glResults.data()); });
1336297d8c7SWojciech Kozyra       return TypedArray<TypedArrayKind::Float32Array>(runtime, glResults);
1346297d8c7SWojciech Kozyra     }
1356297d8c7SWojciech Kozyra       // Int32Array[2]
1366297d8c7SWojciech Kozyra     case GL_MAX_VIEWPORT_DIMS: {
1376297d8c7SWojciech Kozyra       std::vector<TypedArrayBase::ContentType<TypedArrayKind::Int32Array>> glResults(2);
1386297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, glResults.data()); });
1396297d8c7SWojciech Kozyra       return TypedArray<TypedArrayKind::Int32Array>(runtime, glResults);
1406297d8c7SWojciech Kozyra     }
1416297d8c7SWojciech Kozyra       // Int32Array[4]
1426297d8c7SWojciech Kozyra     case GL_SCISSOR_BOX:
1436297d8c7SWojciech Kozyra     case GL_VIEWPORT: {
1446297d8c7SWojciech Kozyra       std::vector<TypedArrayBase::ContentType<TypedArrayKind::Int32Array>> glResults(4);
1456297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, glResults.data()); });
1466297d8c7SWojciech Kozyra       return TypedArray<TypedArrayKind::Int32Array>(runtime, glResults);
1476297d8c7SWojciech Kozyra     }
1486297d8c7SWojciech Kozyra       // boolean[4]
1496297d8c7SWojciech Kozyra     case GL_COLOR_WRITEMASK: {
1506297d8c7SWojciech Kozyra       GLint glResults[4];
1516297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, glResults); });
1526297d8c7SWojciech Kozyra       return jsi::Array::createWithElements(
1536297d8c7SWojciech Kozyra           runtime,
1546297d8c7SWojciech Kozyra           {jsi::Value(glResults[0]),
1556297d8c7SWojciech Kozyra            jsi::Value(glResults[1]),
1566297d8c7SWojciech Kozyra            jsi::Value(glResults[2]),
1576297d8c7SWojciech Kozyra            jsi::Value(glResults[3])});
1586297d8c7SWojciech Kozyra     }
1596297d8c7SWojciech Kozyra 
1606297d8c7SWojciech Kozyra       // boolean
1616297d8c7SWojciech Kozyra     case GL_UNPACK_FLIP_Y_WEBGL:
1626297d8c7SWojciech Kozyra       return ctx->unpackFLipY;
1636297d8c7SWojciech Kozyra     case GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL:
1646297d8c7SWojciech Kozyra     case GL_UNPACK_COLORSPACE_CONVERSION_WEBGL:
1656297d8c7SWojciech Kozyra       return false;
1666297d8c7SWojciech Kozyra     case GL_RASTERIZER_DISCARD:
1676297d8c7SWojciech Kozyra     case GL_SAMPLE_ALPHA_TO_COVERAGE:
1686297d8c7SWojciech Kozyra     case GL_SAMPLE_COVERAGE:
1696297d8c7SWojciech Kozyra     case GL_TRANSFORM_FEEDBACK_ACTIVE:
1706297d8c7SWojciech Kozyra     case GL_TRANSFORM_FEEDBACK_PAUSED: {
1716297d8c7SWojciech Kozyra       GLint glResult;
1726297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glResult); });
1736297d8c7SWojciech Kozyra       return jsi::Value(glResult);
1746297d8c7SWojciech Kozyra     }
1756297d8c7SWojciech Kozyra 
1766297d8c7SWojciech Kozyra       // string
1776297d8c7SWojciech Kozyra     case GL_RENDERER:
1786297d8c7SWojciech Kozyra     case GL_SHADING_LANGUAGE_VERSION:
1796297d8c7SWojciech Kozyra     case GL_VENDOR:
1806297d8c7SWojciech Kozyra     case GL_VERSION: {
1816297d8c7SWojciech Kozyra       const GLubyte *glStr;
1826297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glStr = glGetString(pname); });
1836297d8c7SWojciech Kozyra       return jsi::String::createFromUtf8(
1846297d8c7SWojciech Kozyra           runtime, std::string(reinterpret_cast<const char *>(glStr)));
1856297d8c7SWojciech Kozyra     }
1866297d8c7SWojciech Kozyra 
1876297d8c7SWojciech Kozyra       // float
1886297d8c7SWojciech Kozyra     case GL_DEPTH_CLEAR_VALUE:
1896297d8c7SWojciech Kozyra     case GL_LINE_WIDTH:
1906297d8c7SWojciech Kozyra     case GL_POLYGON_OFFSET_FACTOR:
1916297d8c7SWojciech Kozyra     case GL_POLYGON_OFFSET_UNITS:
1926297d8c7SWojciech Kozyra     case GL_SAMPLE_COVERAGE_VALUE:
1936297d8c7SWojciech Kozyra     case GL_MAX_TEXTURE_LOD_BIAS: {
1946297d8c7SWojciech Kozyra       GLfloat glFloat;
1956297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetFloatv(pname, &glFloat); });
1966297d8c7SWojciech Kozyra       return static_cast<double>(glFloat);
1976297d8c7SWojciech Kozyra     }
1986297d8c7SWojciech Kozyra 
1996297d8c7SWojciech Kozyra       // EXGLObjectId
2006297d8c7SWojciech Kozyra     case GL_ARRAY_BUFFER_BINDING:
2016297d8c7SWojciech Kozyra     case GL_ELEMENT_ARRAY_BUFFER_BINDING: {
2026297d8c7SWojciech Kozyra       GLint glInt;
2036297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glInt); });
2046297d8c7SWojciech Kozyra       for (const auto &pair : ctx->objects) {
2056297d8c7SWojciech Kozyra         if (static_cast<int>(pair.second) == glInt) {
2066297d8c7SWojciech Kozyra           return createWebGLObject(
2076297d8c7SWojciech Kozyra               runtime, EXWebGLClass::WebGLBuffer, {static_cast<double>(pair.first)});
2086297d8c7SWojciech Kozyra         }
2096297d8c7SWojciech Kozyra       }
2106297d8c7SWojciech Kozyra       return nullptr;
2116297d8c7SWojciech Kozyra     }
2126297d8c7SWojciech Kozyra 
2136297d8c7SWojciech Kozyra     case GL_CURRENT_PROGRAM: {
2146297d8c7SWojciech Kozyra       GLint glInt;
2156297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glInt); });
2166297d8c7SWojciech Kozyra       for (const auto &pair : ctx->objects) {
2176297d8c7SWojciech Kozyra         if (static_cast<int>(pair.second) == glInt) {
2186297d8c7SWojciech Kozyra           return createWebGLObject(
2196297d8c7SWojciech Kozyra               runtime, EXWebGLClass::WebGLProgram, {static_cast<double>(pair.first)});
2206297d8c7SWojciech Kozyra         }
2216297d8c7SWojciech Kozyra       }
2226297d8c7SWojciech Kozyra       return nullptr;
2236297d8c7SWojciech Kozyra     }
2246297d8c7SWojciech Kozyra 
2256297d8c7SWojciech Kozyra       // Unimplemented...
2266297d8c7SWojciech Kozyra     case GL_COPY_READ_BUFFER_BINDING:
2276297d8c7SWojciech Kozyra     case GL_COPY_WRITE_BUFFER_BINDING:
2286297d8c7SWojciech Kozyra     case GL_DRAW_FRAMEBUFFER_BINDING:
2296297d8c7SWojciech Kozyra     case GL_READ_FRAMEBUFFER_BINDING:
2306297d8c7SWojciech Kozyra     case GL_RENDERBUFFER_BINDING:
2316297d8c7SWojciech Kozyra     case GL_SAMPLER_BINDING:
2326297d8c7SWojciech Kozyra     case GL_TEXTURE_BINDING_2D_ARRAY:
2336297d8c7SWojciech Kozyra     case GL_TEXTURE_BINDING_2D:
2346297d8c7SWojciech Kozyra     case GL_TEXTURE_BINDING_3D:
2356297d8c7SWojciech Kozyra     case GL_TEXTURE_BINDING_CUBE_MAP:
2366297d8c7SWojciech Kozyra     case GL_TRANSFORM_FEEDBACK_BINDING:
2376297d8c7SWojciech Kozyra     case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2386297d8c7SWojciech Kozyra     case GL_UNIFORM_BUFFER_BINDING:
2396297d8c7SWojciech Kozyra     case GL_VERTEX_ARRAY_BINDING:
2406297d8c7SWojciech Kozyra       throw std::runtime_error(
2416297d8c7SWojciech Kozyra           "EXGL: getParameter() doesn't support gl." + std::to_string(pname) + " yet!");
2426297d8c7SWojciech Kozyra 
2436297d8c7SWojciech Kozyra       // int
2446297d8c7SWojciech Kozyra     default: {
2456297d8c7SWojciech Kozyra       GLint glInt;
2466297d8c7SWojciech Kozyra       ctx->addBlockingToNextBatch([&] { glGetIntegerv(pname, &glInt); });
2476297d8c7SWojciech Kozyra       return jsi::Value(glInt);
2486297d8c7SWojciech Kozyra     }
2496297d8c7SWojciech Kozyra   }
2506297d8c7SWojciech Kozyra }
2516297d8c7SWojciech Kozyra 
NATIVE_METHOD(getError)2526297d8c7SWojciech Kozyra NATIVE_METHOD(getError) {
2536297d8c7SWojciech Kozyra   CTX();
2546297d8c7SWojciech Kozyra   GLenum glResult;
2556297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] { glResult = glGetError(); });
2566297d8c7SWojciech Kozyra   return static_cast<double>(glResult);
2576297d8c7SWojciech Kozyra }
2586297d8c7SWojciech Kozyra 
2596297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(hint, glHint); // target, mode
2606297d8c7SWojciech Kozyra 
NATIVE_METHOD(isEnabled)2616297d8c7SWojciech Kozyra NATIVE_METHOD(isEnabled) {
2626297d8c7SWojciech Kozyra   CTX();
2636297d8c7SWojciech Kozyra   auto cap = ARG(0, GLenum);
2646297d8c7SWojciech Kozyra   GLboolean glResult;
2656297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] { glResult = glIsEnabled(cap); });
2666297d8c7SWojciech Kozyra   return glResult == GL_TRUE;
2676297d8c7SWojciech Kozyra }
2686297d8c7SWojciech Kozyra 
2696297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(lineWidth, glLineWidth); // width
2706297d8c7SWojciech Kozyra 
NATIVE_METHOD(pixelStorei)2716297d8c7SWojciech Kozyra NATIVE_METHOD(pixelStorei) {
2726297d8c7SWojciech Kozyra   CTX();
2736297d8c7SWojciech Kozyra   auto pname = ARG(0, GLenum);
2746297d8c7SWojciech Kozyra   switch (pname) {
2756297d8c7SWojciech Kozyra     case GL_UNPACK_FLIP_Y_WEBGL: {
2766297d8c7SWojciech Kozyra       ctx->unpackFLipY = ARG(1, GLboolean);
2776297d8c7SWojciech Kozyra       break;
2786297d8c7SWojciech Kozyra     }
279*97fb1ba6SBartłomiej Banasik     case GL_UNPACK_ALIGNMENT: {
280*97fb1ba6SBartłomiej Banasik       auto param = ARG(1, GLint);
281*97fb1ba6SBartłomiej Banasik       ctx->addToNextBatch([=] {
282*97fb1ba6SBartłomiej Banasik         glPixelStorei(GL_UNPACK_ALIGNMENT, param);
283*97fb1ba6SBartłomiej Banasik       });
284*97fb1ba6SBartłomiej Banasik       break;
285*97fb1ba6SBartłomiej Banasik     }
2866297d8c7SWojciech Kozyra     default:
2876297d8c7SWojciech Kozyra       jsConsoleLog(runtime, { jsi::String::createFromUtf8(runtime, "EXGL: gl.pixelStorei() doesn't support this parameter yet!") });
2886297d8c7SWojciech Kozyra   }
2896297d8c7SWojciech Kozyra   return nullptr;
2906297d8c7SWojciech Kozyra }
2916297d8c7SWojciech Kozyra 
2926297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(polygonOffset, glPolygonOffset); // factor, units
2936297d8c7SWojciech Kozyra 
2946297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(sampleCoverage, glSampleCoverage); // value, invert
2956297d8c7SWojciech Kozyra 
2966297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(stencilFunc, glStencilFunc); // func, ref, mask
2976297d8c7SWojciech Kozyra 
2986297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(stencilFuncSeparate, glStencilFuncSeparate); // face, func, ref, mask
2996297d8c7SWojciech Kozyra 
3006297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(stencilMask, glStencilMask); // mask
3016297d8c7SWojciech Kozyra 
3026297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(stencilMaskSeparate, glStencilMaskSeparate); // face, mask
3036297d8c7SWojciech Kozyra 
3046297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(stencilOp, glStencilOp) // fail, zfail, zpass
3056297d8c7SWojciech Kozyra 
3066297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(stencilOpSeparate, glStencilOpSeparate); // face, fail, zfail, zpass
3076297d8c7SWojciech Kozyra 
3086297d8c7SWojciech Kozyra // Buffers
3096297d8c7SWojciech Kozyra // -------
3106297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindBuffer)3116297d8c7SWojciech Kozyra NATIVE_METHOD(bindBuffer) {
3126297d8c7SWojciech Kozyra   CTX();
3136297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
3146297d8c7SWojciech Kozyra   auto buffer = ARG(1, EXWebGLClass);
3156297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBindBuffer(target, ctx->lookupObject(buffer)); });
3166297d8c7SWojciech Kozyra   return nullptr;
3176297d8c7SWojciech Kozyra }
3186297d8c7SWojciech Kozyra 
NATIVE_METHOD(bufferData)3196297d8c7SWojciech Kozyra NATIVE_METHOD(bufferData) {
3206297d8c7SWojciech Kozyra   CTX();
3216297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
3226297d8c7SWojciech Kozyra   auto &sizeOrData = ARG(1, const jsi::Value &);
3236297d8c7SWojciech Kozyra   auto usage = ARG(2, GLenum);
3246297d8c7SWojciech Kozyra 
3256297d8c7SWojciech Kozyra   if (sizeOrData.isNumber()) {
3266297d8c7SWojciech Kozyra     GLsizeiptr length = sizeOrData.getNumber();
3276297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] { glBufferData(target, length, nullptr, usage); });
3286297d8c7SWojciech Kozyra   } else if (sizeOrData.isNull() || sizeOrData.isUndefined()) {
3296297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] { glBufferData(target, 0, nullptr, usage); });
3306297d8c7SWojciech Kozyra   } else if (sizeOrData.isObject()) {
3316297d8c7SWojciech Kozyra     auto data = rawTypedArray(runtime, sizeOrData.getObject(runtime));
3326297d8c7SWojciech Kozyra     ctx->addToNextBatch(
3336297d8c7SWojciech Kozyra         [=, data{std::move(data)}] { glBufferData(target, data.size(), data.data(), usage); });
3346297d8c7SWojciech Kozyra   }
3356297d8c7SWojciech Kozyra   return nullptr;
3366297d8c7SWojciech Kozyra }
3376297d8c7SWojciech Kozyra 
NATIVE_METHOD(bufferSubData)3386297d8c7SWojciech Kozyra NATIVE_METHOD(bufferSubData) {
3396297d8c7SWojciech Kozyra   CTX();
3406297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
3416297d8c7SWojciech Kozyra   auto offset = ARG(1, GLintptr);
3426297d8c7SWojciech Kozyra   if (ARG(2, const jsi::Value &).isNull()) {
3436297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] { glBufferSubData(target, offset, 0, nullptr); });
3446297d8c7SWojciech Kozyra   } else {
3456297d8c7SWojciech Kozyra     auto data = rawTypedArray(runtime, ARG(2, jsi::Object));
3466297d8c7SWojciech Kozyra     ctx->addToNextBatch(
3476297d8c7SWojciech Kozyra         [=, data{std::move(data)}] { glBufferSubData(target, offset, data.size(), data.data()); });
3486297d8c7SWojciech Kozyra   }
3496297d8c7SWojciech Kozyra   return nullptr;
3506297d8c7SWojciech Kozyra }
3516297d8c7SWojciech Kozyra 
NATIVE_METHOD(createBuffer)3526297d8c7SWojciech Kozyra NATIVE_METHOD(createBuffer) {
3536297d8c7SWojciech Kozyra   CTX();
3546297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenBuffers, EXWebGLClass::WebGLBuffer);
3556297d8c7SWojciech Kozyra }
3566297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteBuffer)3576297d8c7SWojciech Kozyra NATIVE_METHOD(deleteBuffer) {
3586297d8c7SWojciech Kozyra   CTX();
3596297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteBuffers);
3606297d8c7SWojciech Kozyra }
3616297d8c7SWojciech Kozyra 
NATIVE_METHOD(getBufferParameter)3626297d8c7SWojciech Kozyra NATIVE_METHOD(getBufferParameter) {
3636297d8c7SWojciech Kozyra   CTX();
3646297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
3656297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
3666297d8c7SWojciech Kozyra   GLint glResult;
3676297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] { glGetBufferParameteriv(target, pname, &glResult); });
3686297d8c7SWojciech Kozyra   return jsi::Value(glResult);
3696297d8c7SWojciech Kozyra }
3706297d8c7SWojciech Kozyra 
NATIVE_METHOD(isBuffer)3716297d8c7SWojciech Kozyra NATIVE_METHOD(isBuffer) {
3726297d8c7SWojciech Kozyra   CTX();
3736297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsBuffer);
3746297d8c7SWojciech Kozyra }
3756297d8c7SWojciech Kozyra 
3766297d8c7SWojciech Kozyra // Buffers (WebGL2)
3776297d8c7SWojciech Kozyra 
3786297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
3796297d8c7SWojciech Kozyra     copyBufferSubData,
3806297d8c7SWojciech Kozyra     glCopyBufferSubData) // readTarget, writeTarget, readOffset, writeOffset, size
3816297d8c7SWojciech Kozyra 
3826297d8c7SWojciech Kozyra // glGetBufferSubData is not available in OpenGL ES
3836297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getBufferSubData);
3846297d8c7SWojciech Kozyra 
3856297d8c7SWojciech Kozyra // Framebuffers
3866297d8c7SWojciech Kozyra // ------------
3876297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindFramebuffer)3886297d8c7SWojciech Kozyra NATIVE_METHOD(bindFramebuffer) {
3896297d8c7SWojciech Kozyra   CTX();
3906297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
3916297d8c7SWojciech Kozyra   auto framebuffer = ARG(1, EXWebGLClass);
3926297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] {
3936297d8c7SWojciech Kozyra     glBindFramebuffer(
3946297d8c7SWojciech Kozyra         target, framebuffer == 0 ? ctx->defaultFramebuffer : ctx->lookupObject(framebuffer));
3956297d8c7SWojciech Kozyra   });
3966297d8c7SWojciech Kozyra   return nullptr;
3976297d8c7SWojciech Kozyra }
3986297d8c7SWojciech Kozyra 
NATIVE_METHOD(checkFramebufferStatus)3996297d8c7SWojciech Kozyra NATIVE_METHOD(checkFramebufferStatus) {
4006297d8c7SWojciech Kozyra   CTX();
4016297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
4026297d8c7SWojciech Kozyra   GLenum glResult;
4036297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] { glResult = glCheckFramebufferStatus(target); });
4046297d8c7SWojciech Kozyra   return static_cast<double>(glResult);
4056297d8c7SWojciech Kozyra }
4066297d8c7SWojciech Kozyra 
NATIVE_METHOD(createFramebuffer)4076297d8c7SWojciech Kozyra NATIVE_METHOD(createFramebuffer) {
4086297d8c7SWojciech Kozyra   CTX();
4096297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenFramebuffers, EXWebGLClass::WebGLFramebuffer);
4106297d8c7SWojciech Kozyra }
4116297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteFramebuffer)4126297d8c7SWojciech Kozyra NATIVE_METHOD(deleteFramebuffer) {
4136297d8c7SWojciech Kozyra   CTX();
4146297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteFramebuffers);
4156297d8c7SWojciech Kozyra }
4166297d8c7SWojciech Kozyra 
NATIVE_METHOD(framebufferRenderbuffer)4176297d8c7SWojciech Kozyra NATIVE_METHOD(framebufferRenderbuffer) {
4186297d8c7SWojciech Kozyra   CTX();
4196297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
4206297d8c7SWojciech Kozyra   auto attachment = ARG(1, GLenum);
4216297d8c7SWojciech Kozyra   auto renderbuffertarget = ARG(2, GLenum);
4226297d8c7SWojciech Kozyra   auto fRenderbuffer = ARG(3, EXWebGLClass);
4236297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] {
4246297d8c7SWojciech Kozyra     GLuint renderbuffer = ctx->lookupObject(fRenderbuffer);
4256297d8c7SWojciech Kozyra     glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
4266297d8c7SWojciech Kozyra   });
4276297d8c7SWojciech Kozyra   return nullptr;
4286297d8c7SWojciech Kozyra }
4296297d8c7SWojciech Kozyra 
4306297d8c7SWojciech Kozyra NATIVE_METHOD(framebufferTexture2D, 5) {
4316297d8c7SWojciech Kozyra   CTX();
4326297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
4336297d8c7SWojciech Kozyra   auto attachment = ARG(1, GLenum);
4346297d8c7SWojciech Kozyra   auto textarget = ARG(2, GLenum);
4356297d8c7SWojciech Kozyra   auto fTexture = ARG(3, EXWebGLClass);
4366297d8c7SWojciech Kozyra   auto level = ARG(4, GLint);
__anon33f747aa1902null4376297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] {
4386297d8c7SWojciech Kozyra     glFramebufferTexture2D(target, attachment, textarget, ctx->lookupObject(fTexture), level);
4396297d8c7SWojciech Kozyra   });
4406297d8c7SWojciech Kozyra   return nullptr;
4416297d8c7SWojciech Kozyra }
4426297d8c7SWojciech Kozyra 
4436297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getFramebufferAttachmentParameter)
4446297d8c7SWojciech Kozyra 
NATIVE_METHOD(isFramebuffer)4456297d8c7SWojciech Kozyra NATIVE_METHOD(isFramebuffer) {
4466297d8c7SWojciech Kozyra   CTX();
4476297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsFramebuffer);
4486297d8c7SWojciech Kozyra }
4496297d8c7SWojciech Kozyra 
NATIVE_METHOD(readPixels)4506297d8c7SWojciech Kozyra NATIVE_METHOD(readPixels) {
4516297d8c7SWojciech Kozyra   CTX();
4526297d8c7SWojciech Kozyra   auto x = ARG(0, GLint);
4536297d8c7SWojciech Kozyra   auto y = ARG(1, GLint);
4546297d8c7SWojciech Kozyra   auto width = ARG(2, GLuint); // GLsizei allows negative values
4556297d8c7SWojciech Kozyra   auto height = ARG(3, GLuint);
4566297d8c7SWojciech Kozyra   auto format = ARG(4, GLenum);
4576297d8c7SWojciech Kozyra   auto type = ARG(5, GLenum);
4586297d8c7SWojciech Kozyra   size_t byteLength = width * height * bytesPerPixel(type, format);
4596297d8c7SWojciech Kozyra   std::vector<uint8_t> pixels(byteLength);
4606297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
4616297d8c7SWojciech Kozyra       [&] { glReadPixels(x, y, width, height, format, type, pixels.data()); });
4626297d8c7SWojciech Kozyra 
4636297d8c7SWojciech Kozyra   TypedArrayBase arr = ARG(6, TypedArrayBase);
4646297d8c7SWojciech Kozyra   jsi::ArrayBuffer buffer = arr.getBuffer(runtime);
4656297d8c7SWojciech Kozyra   arrayBufferUpdate(runtime, buffer, pixels, arr.byteOffset(runtime));
4666297d8c7SWojciech Kozyra   return nullptr;
4676297d8c7SWojciech Kozyra }
4686297d8c7SWojciech Kozyra 
4696297d8c7SWojciech Kozyra // Framebuffers (WebGL2)
4706297d8c7SWojciech Kozyra // ---------------------
4716297d8c7SWojciech Kozyra 
4726297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(blitFramebuffer, glBlitFramebuffer);
4736297d8c7SWojciech Kozyra // srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter
4746297d8c7SWojciech Kozyra 
NATIVE_METHOD(framebufferTextureLayer)4756297d8c7SWojciech Kozyra NATIVE_METHOD(framebufferTextureLayer) {
4766297d8c7SWojciech Kozyra   CTX();
4776297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
4786297d8c7SWojciech Kozyra   auto attachment = ARG(1, GLenum);
4796297d8c7SWojciech Kozyra   auto texture = ARG(2, EXWebGLClass);
4806297d8c7SWojciech Kozyra   auto level = ARG(3, GLint);
4816297d8c7SWojciech Kozyra   auto layer = ARG(4, GLint);
4826297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] {
4836297d8c7SWojciech Kozyra     glFramebufferTextureLayer(target, attachment, ctx->lookupObject(texture), level, layer);
4846297d8c7SWojciech Kozyra   });
4856297d8c7SWojciech Kozyra   return nullptr;
4866297d8c7SWojciech Kozyra }
4876297d8c7SWojciech Kozyra 
NATIVE_METHOD(invalidateFramebuffer)4886297d8c7SWojciech Kozyra NATIVE_METHOD(invalidateFramebuffer) {
4896297d8c7SWojciech Kozyra   CTX();
4906297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
4916297d8c7SWojciech Kozyra   auto jsAttachments = ARG(1, jsi::Array);
4926297d8c7SWojciech Kozyra 
4936297d8c7SWojciech Kozyra   std::vector<GLenum> attachments(jsAttachments.size(runtime));
4946297d8c7SWojciech Kozyra   for (size_t i = 0; i < attachments.size(); i++) {
4956297d8c7SWojciech Kozyra     attachments[i] = jsAttachments.getValueAtIndex(runtime, i).asNumber();
4966297d8c7SWojciech Kozyra   }
4976297d8c7SWojciech Kozyra   ctx->addToNextBatch([=, attachaments{std::move(attachments)}] {
4986297d8c7SWojciech Kozyra     glInvalidateFramebuffer(target, static_cast<GLsizei>(attachments.size()), attachments.data());
4996297d8c7SWojciech Kozyra   });
5006297d8c7SWojciech Kozyra   return nullptr; // breaking change TypedArray -> Array (bug in previous implementation)
5016297d8c7SWojciech Kozyra }
5026297d8c7SWojciech Kozyra 
NATIVE_METHOD(invalidateSubFramebuffer)5036297d8c7SWojciech Kozyra NATIVE_METHOD(invalidateSubFramebuffer) {
5046297d8c7SWojciech Kozyra   CTX();
5056297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
5066297d8c7SWojciech Kozyra   auto jsAttachments = ARG(1, jsi::Array);
5076297d8c7SWojciech Kozyra   auto x = ARG(2, GLint);
5086297d8c7SWojciech Kozyra   auto y = ARG(3, GLint);
5096297d8c7SWojciech Kozyra   auto width = ARG(4, GLint);
5106297d8c7SWojciech Kozyra   auto height = ARG(5, GLint);
5116297d8c7SWojciech Kozyra   std::vector<GLenum> attachments(jsAttachments.size(runtime));
5126297d8c7SWojciech Kozyra   for (size_t i = 0; i < attachments.size(); i++) {
5136297d8c7SWojciech Kozyra     attachments[i] = jsAttachments.getValueAtIndex(runtime, i).asNumber();
5146297d8c7SWojciech Kozyra   }
5156297d8c7SWojciech Kozyra   ctx->addToNextBatch([=, attachments{std::move(attachments)}] {
5166297d8c7SWojciech Kozyra     glInvalidateSubFramebuffer(
5176297d8c7SWojciech Kozyra         target, static_cast<GLsizei>(attachments.size()), attachments.data(), x, y, width, height);
5186297d8c7SWojciech Kozyra   });
5196297d8c7SWojciech Kozyra   return nullptr;
5206297d8c7SWojciech Kozyra }
5216297d8c7SWojciech Kozyra 
5226297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(readBuffer, glReadBuffer); // mode
5236297d8c7SWojciech Kozyra 
5246297d8c7SWojciech Kozyra // Renderbuffers
5256297d8c7SWojciech Kozyra // -------------
5266297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindRenderbuffer)5276297d8c7SWojciech Kozyra NATIVE_METHOD(bindRenderbuffer) {
5286297d8c7SWojciech Kozyra   CTX();
5296297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
5306297d8c7SWojciech Kozyra   auto fRenderbuffer = ARG(1, EXWebGLClass);
5316297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBindRenderbuffer(target, ctx->lookupObject(fRenderbuffer)); });
5326297d8c7SWojciech Kozyra   return nullptr;
5336297d8c7SWojciech Kozyra }
5346297d8c7SWojciech Kozyra 
NATIVE_METHOD(createRenderbuffer)5356297d8c7SWojciech Kozyra NATIVE_METHOD(createRenderbuffer) {
5366297d8c7SWojciech Kozyra   CTX();
5376297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenRenderbuffers, EXWebGLClass::WebGLRenderbuffer);
5386297d8c7SWojciech Kozyra }
5396297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteRenderbuffer)5406297d8c7SWojciech Kozyra NATIVE_METHOD(deleteRenderbuffer) {
5416297d8c7SWojciech Kozyra   CTX();
5426297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteRenderbuffers);
5436297d8c7SWojciech Kozyra }
5446297d8c7SWojciech Kozyra 
5456297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getRenderbufferParameter)
5466297d8c7SWojciech Kozyra 
NATIVE_METHOD(isRenderbuffer)5476297d8c7SWojciech Kozyra NATIVE_METHOD(isRenderbuffer) {
5486297d8c7SWojciech Kozyra   CTX();
5496297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsRenderbuffer);
5506297d8c7SWojciech Kozyra }
5516297d8c7SWojciech Kozyra 
NATIVE_METHOD(renderbufferStorage)5526297d8c7SWojciech Kozyra NATIVE_METHOD(renderbufferStorage) {
5536297d8c7SWojciech Kozyra   CTX();
5546297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
5556297d8c7SWojciech Kozyra   auto internalformat = ARG(1, GLint);
5566297d8c7SWojciech Kozyra   auto width = ARG(2, GLsizei);
5576297d8c7SWojciech Kozyra   auto height = ARG(3, GLsizei);
5586297d8c7SWojciech Kozyra 
5596297d8c7SWojciech Kozyra   // WebGL allows `GL_DEPTH_STENCIL` flag to be passed here,
5606297d8c7SWojciech Kozyra   // however OpenGL ES seems to require sized format, so we fall back to `GL_DEPTH24_STENCIL8`.
5616297d8c7SWojciech Kozyra   internalformat = internalformat == GL_DEPTH_STENCIL ? GL_DEPTH24_STENCIL8 : internalformat;
5626297d8c7SWojciech Kozyra 
5636297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glRenderbufferStorage(target, internalformat, width, height); });
5646297d8c7SWojciech Kozyra   return nullptr;
5656297d8c7SWojciech Kozyra }
5666297d8c7SWojciech Kozyra 
5676297d8c7SWojciech Kozyra // Renderbuffers (WebGL2)
5686297d8c7SWojciech Kozyra // ----------------------
5696297d8c7SWojciech Kozyra 
NATIVE_METHOD(getInternalformatParameter)5706297d8c7SWojciech Kozyra NATIVE_METHOD(getInternalformatParameter) {
5716297d8c7SWojciech Kozyra   CTX();
5726297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
5736297d8c7SWojciech Kozyra   auto internalformat = ARG(1, GLenum);
5746297d8c7SWojciech Kozyra   auto pname = ARG(2, GLenum);
5756297d8c7SWojciech Kozyra 
5766297d8c7SWojciech Kozyra   std::vector<TypedArrayBase::ContentType<TypedArrayKind::Int32Array>> glResults;
5776297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
5786297d8c7SWojciech Kozyra     GLint count;
5796297d8c7SWojciech Kozyra     glGetInternalformativ(target, internalformat, GL_NUM_SAMPLE_COUNTS, 1, &count);
5806297d8c7SWojciech Kozyra     glResults.resize(count);
5816297d8c7SWojciech Kozyra     glGetInternalformativ(target, internalformat, pname, count, glResults.data());
5826297d8c7SWojciech Kozyra   });
5836297d8c7SWojciech Kozyra 
5846297d8c7SWojciech Kozyra   return TypedArray<TypedArrayKind::Int32Array>(runtime, glResults);
5856297d8c7SWojciech Kozyra }
5866297d8c7SWojciech Kozyra 
5876297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(renderbufferStorageMultisample)
5886297d8c7SWojciech Kozyra 
5896297d8c7SWojciech Kozyra // Textures
5906297d8c7SWojciech Kozyra // --------
5916297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindTexture)5926297d8c7SWojciech Kozyra NATIVE_METHOD(bindTexture) {
5936297d8c7SWojciech Kozyra   CTX();
5946297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
5956297d8c7SWojciech Kozyra   auto texture = ARG(1, EXWebGLClass);
5966297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBindTexture(target, ctx->lookupObject(texture)); });
5976297d8c7SWojciech Kozyra   return nullptr;
5986297d8c7SWojciech Kozyra }
5996297d8c7SWojciech Kozyra 
6006297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(compressedTexImage2D)
6016297d8c7SWojciech Kozyra 
6026297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(compressedTexSubImage2D)
6036297d8c7SWojciech Kozyra 
6046297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
6056297d8c7SWojciech Kozyra     copyTexImage2D,
6066297d8c7SWojciech Kozyra     glCopyTexImage2D); // target, level, internalformat, x, y, width, height, border
6076297d8c7SWojciech Kozyra 
SIMPLE_NATIVE_METHOD(copyTexSubImage2D,glCopyTexSubImage2D)6086297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
6096297d8c7SWojciech Kozyra     copyTexSubImage2D,
6106297d8c7SWojciech Kozyra     glCopyTexSubImage2D) // target, level, xoffset, yoffset, x, y, width, height
6116297d8c7SWojciech Kozyra 
6126297d8c7SWojciech Kozyra NATIVE_METHOD(createTexture) {
6136297d8c7SWojciech Kozyra   CTX();
6146297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenTextures, EXWebGLClass::WebGLTexture);
6156297d8c7SWojciech Kozyra }
6166297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteTexture)6176297d8c7SWojciech Kozyra NATIVE_METHOD(deleteTexture) {
6186297d8c7SWojciech Kozyra   CTX();
6196297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteTextures);
6206297d8c7SWojciech Kozyra }
6216297d8c7SWojciech Kozyra 
SIMPLE_NATIVE_METHOD(generateMipmap,glGenerateMipmap)6226297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(generateMipmap, glGenerateMipmap) // target
6236297d8c7SWojciech Kozyra 
6246297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getTexParameter)
6256297d8c7SWojciech Kozyra 
6266297d8c7SWojciech Kozyra NATIVE_METHOD(isTexture) {
6276297d8c7SWojciech Kozyra   CTX();
6286297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsTexture);
6296297d8c7SWojciech Kozyra }
6306297d8c7SWojciech Kozyra 
6316297d8c7SWojciech Kozyra NATIVE_METHOD(texImage2D, 6) {
6326297d8c7SWojciech Kozyra   CTX();
6336297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
6346297d8c7SWojciech Kozyra   auto level = ARG(1, GLint);
6356297d8c7SWojciech Kozyra   auto internalformat = ARG(2, GLint);
6366297d8c7SWojciech Kozyra   if (argc == 9) {
6376297d8c7SWojciech Kozyra     auto width = ARG(3, GLsizei);
6386297d8c7SWojciech Kozyra     auto height = ARG(4, GLsizei);
6396297d8c7SWojciech Kozyra     auto border = ARG(5, GLsizei);
6406297d8c7SWojciech Kozyra     auto format = ARG(6, GLenum);
6416297d8c7SWojciech Kozyra     auto type = ARG(7, GLenum);
6426297d8c7SWojciech Kozyra     if (ARG(8, const jsi::Value &).isNull()) {
__anon33f747aa2202null6436297d8c7SWojciech Kozyra       ctx->addToNextBatch([=] {
6446297d8c7SWojciech Kozyra         glTexImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
6456297d8c7SWojciech Kozyra       });
6466297d8c7SWojciech Kozyra       return nullptr;
6476297d8c7SWojciech Kozyra     }
6486297d8c7SWojciech Kozyra     auto data = ARG(8, jsi::Object);
6496297d8c7SWojciech Kozyra 
6506297d8c7SWojciech Kozyra     if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
6516297d8c7SWojciech Kozyra       std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
6526297d8c7SWojciech Kozyra       if (ctx->unpackFLipY) {
6536297d8c7SWojciech Kozyra         flipPixels(vec.data(), width * bytesPerPixel(type, format), height);
6546297d8c7SWojciech Kozyra       }
__anon33f747aa2302null6556297d8c7SWojciech Kozyra       ctx->addToNextBatch([=, vec{std::move(vec)}] {
6566297d8c7SWojciech Kozyra         glTexImage2D(
6576297d8c7SWojciech Kozyra             target, level, internalformat, width, height, border, format, type, vec.data());
6586297d8c7SWojciech Kozyra       });
6596297d8c7SWojciech Kozyra     } else {
6606297d8c7SWojciech Kozyra       auto image = loadImage(runtime, data, &width, &height, nullptr);
6616297d8c7SWojciech Kozyra       if (ctx->unpackFLipY) {
6626297d8c7SWojciech Kozyra         flipPixels(image.get(), width * bytesPerPixel(type, format), height);
6636297d8c7SWojciech Kozyra       }
__anon33f747aa2402null6646297d8c7SWojciech Kozyra       ctx->addToNextBatch([=] {
6656297d8c7SWojciech Kozyra         glTexImage2D(
6666297d8c7SWojciech Kozyra             target, level, internalformat, width, height, border, format, type, image.get());
6676297d8c7SWojciech Kozyra       });
6686297d8c7SWojciech Kozyra     }
6696297d8c7SWojciech Kozyra   } else if (argc == 6) {
6706297d8c7SWojciech Kozyra     auto format = ARG(3, GLenum);
6716297d8c7SWojciech Kozyra     auto type = ARG(4, GLenum);
6726297d8c7SWojciech Kozyra     auto data = ARG(5, jsi::Object);
6736297d8c7SWojciech Kozyra     GLsizei width = 0, height = 0, border = 0;
6746297d8c7SWojciech Kozyra     auto image = loadImage(runtime, data, &width, &height, nullptr);
6756297d8c7SWojciech Kozyra     if (ctx->unpackFLipY) {
6766297d8c7SWojciech Kozyra       flipPixels(image.get(), width * bytesPerPixel(type, format), height);
6776297d8c7SWojciech Kozyra     }
__anon33f747aa2502null6786297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] {
6796297d8c7SWojciech Kozyra       glTexImage2D(target, level, internalformat, width, height, border, format, type, image.get());
6806297d8c7SWojciech Kozyra     });
6816297d8c7SWojciech Kozyra   } else {
6826297d8c7SWojciech Kozyra     throw std::runtime_error("EXGL: Invalid number of arguments to gl.texImage2D()!");
6836297d8c7SWojciech Kozyra   }
6846297d8c7SWojciech Kozyra   return nullptr;
6856297d8c7SWojciech Kozyra }
6866297d8c7SWojciech Kozyra 
6876297d8c7SWojciech Kozyra NATIVE_METHOD(texSubImage2D, 6) {
6886297d8c7SWojciech Kozyra   CTX();
6896297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
6906297d8c7SWojciech Kozyra   auto level = ARG(1, GLint);
6916297d8c7SWojciech Kozyra   auto xoffset = ARG(2, GLint);
6926297d8c7SWojciech Kozyra   auto yoffset = ARG(3, GLint);
6936297d8c7SWojciech Kozyra   if (argc == 9) {
6946297d8c7SWojciech Kozyra     auto width = ARG(4, GLsizei);
6956297d8c7SWojciech Kozyra     auto height = ARG(5, GLsizei);
6966297d8c7SWojciech Kozyra     auto format = ARG(6, GLenum);
6976297d8c7SWojciech Kozyra     auto type = ARG(7, GLenum);
6986297d8c7SWojciech Kozyra     if (ARG(8, const jsi::Value &).isNull()) {
__anon33f747aa2602null6996297d8c7SWojciech Kozyra       ctx->addToNextBatch([=] {
7006297d8c7SWojciech Kozyra         auto empty = std::make_unique<uint8_t>(width * height * bytesPerPixel(type, format));
7016297d8c7SWojciech Kozyra         std::memset(empty.get(), 0, width * height * bytesPerPixel(type, format));
7026297d8c7SWojciech Kozyra         glTexImage2D(target, level, xoffset, yoffset, width, height, format, type, empty.get());
7036297d8c7SWojciech Kozyra       });
7046297d8c7SWojciech Kozyra       return nullptr;
7056297d8c7SWojciech Kozyra     }
7066297d8c7SWojciech Kozyra 
7076297d8c7SWojciech Kozyra     auto data = ARG(8, jsi::Object);
7086297d8c7SWojciech Kozyra 
7096297d8c7SWojciech Kozyra     if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
7106297d8c7SWojciech Kozyra       std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
7116297d8c7SWojciech Kozyra       if (ctx->unpackFLipY) {
7126297d8c7SWojciech Kozyra         flipPixels(vec.data(), width * bytesPerPixel(type, format), height);
7136297d8c7SWojciech Kozyra       }
__anon33f747aa2702null7146297d8c7SWojciech Kozyra       ctx->addToNextBatch([=, vec{std::move(vec)}] {
7156297d8c7SWojciech Kozyra         glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, vec.data());
7166297d8c7SWojciech Kozyra       });
7176297d8c7SWojciech Kozyra     } else {
7186297d8c7SWojciech Kozyra       auto image = loadImage(runtime, data, &width, &height, nullptr);
7196297d8c7SWojciech Kozyra       if (ctx->unpackFLipY) {
7206297d8c7SWojciech Kozyra         flipPixels(image.get(), width * bytesPerPixel(type, format), height);
7216297d8c7SWojciech Kozyra       }
__anon33f747aa2802null7226297d8c7SWojciech Kozyra       ctx->addToNextBatch([=] {
7236297d8c7SWojciech Kozyra         glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, image.get());
7246297d8c7SWojciech Kozyra       });
7256297d8c7SWojciech Kozyra     }
7266297d8c7SWojciech Kozyra   } else if (argc == 7) {
7276297d8c7SWojciech Kozyra     auto format = ARG(4, GLenum);
7286297d8c7SWojciech Kozyra     auto type = ARG(5, GLenum);
7296297d8c7SWojciech Kozyra     auto data = ARG(6, jsi::Object);
7306297d8c7SWojciech Kozyra     GLsizei width = 0, height = 0;
7316297d8c7SWojciech Kozyra     auto image = loadImage(runtime, data, &width, &height, nullptr);
7326297d8c7SWojciech Kozyra     if (ctx->unpackFLipY) {
7336297d8c7SWojciech Kozyra       flipPixels(image.get(), width * bytesPerPixel(type, format), height);
7346297d8c7SWojciech Kozyra     }
__anon33f747aa2902null7356297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] {
7366297d8c7SWojciech Kozyra       glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, image.get());
7376297d8c7SWojciech Kozyra     });
7386297d8c7SWojciech Kozyra   } else {
7396297d8c7SWojciech Kozyra     throw std::runtime_error("EXGL: Invalid number of arguments to gl.texSubImage2D()!");
7406297d8c7SWojciech Kozyra   }
7416297d8c7SWojciech Kozyra   return nullptr;
7426297d8c7SWojciech Kozyra }
7436297d8c7SWojciech Kozyra 
7446297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(texParameterf, glTexParameterf); // target, pname, param
7456297d8c7SWojciech Kozyra 
7466297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(texParameteri, glTexParameteri); // target, pname, param
7476297d8c7SWojciech Kozyra 
7486297d8c7SWojciech Kozyra // Textures (WebGL2)
7496297d8c7SWojciech Kozyra // -----------------
7506297d8c7SWojciech Kozyra 
7516297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(texStorage2D, glTexStorage2D); // target, levels, internalformat, width, height
7526297d8c7SWojciech Kozyra 
7536297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
7546297d8c7SWojciech Kozyra     texStorage3D,
7556297d8c7SWojciech Kozyra     glTexStorage3D); // target, levels, internalformat, width, height, depth
7566297d8c7SWojciech Kozyra 
NATIVE_METHOD(texImage3D)7576297d8c7SWojciech Kozyra NATIVE_METHOD(texImage3D) {
7586297d8c7SWojciech Kozyra   CTX();
7596297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
7606297d8c7SWojciech Kozyra   auto level = ARG(1, GLint);
7616297d8c7SWojciech Kozyra   auto internalformat = ARG(2, GLint);
7626297d8c7SWojciech Kozyra   auto width = ARG(3, GLsizei);
7636297d8c7SWojciech Kozyra   auto height = ARG(4, GLsizei);
7646297d8c7SWojciech Kozyra   auto depth = ARG(5, GLsizei);
7656297d8c7SWojciech Kozyra   auto border = ARG(6, GLsizei);
7666297d8c7SWojciech Kozyra   auto format = ARG(7, GLenum);
7676297d8c7SWojciech Kozyra   auto type = ARG(8, GLenum);
7686297d8c7SWojciech Kozyra 
7696297d8c7SWojciech Kozyra   if (ARG(9, const jsi::Value &).isNull()) {
7706297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] {
7716297d8c7SWojciech Kozyra       glTexImage3D(
7726297d8c7SWojciech Kozyra           target, level, internalformat, width, height, depth, border, format, type, nullptr);
7736297d8c7SWojciech Kozyra     });
7746297d8c7SWojciech Kozyra     return nullptr;
7756297d8c7SWojciech Kozyra   }
7766297d8c7SWojciech Kozyra   auto data = ARG(9, jsi::Object);
7776297d8c7SWojciech Kozyra   auto flip = [&](uint8_t *data) {
7786297d8c7SWojciech Kozyra     GLubyte *texelLayer = data;
7796297d8c7SWojciech Kozyra     for (int z = 0; z < depth; z++) {
7806297d8c7SWojciech Kozyra       flipPixels(texelLayer, width * bytesPerPixel(type, format), height);
7816297d8c7SWojciech Kozyra       texelLayer += bytesPerPixel(type, format) * width * height;
7826297d8c7SWojciech Kozyra     }
7836297d8c7SWojciech Kozyra   };
7846297d8c7SWojciech Kozyra 
7856297d8c7SWojciech Kozyra   if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
7866297d8c7SWojciech Kozyra     std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
7876297d8c7SWojciech Kozyra     if (ctx->unpackFLipY) {
7886297d8c7SWojciech Kozyra       flip(vec.data());
7896297d8c7SWojciech Kozyra     }
7906297d8c7SWojciech Kozyra     ctx->addToNextBatch([=, vec{std::move(vec)}] {
7916297d8c7SWojciech Kozyra       glTexImage3D(
7926297d8c7SWojciech Kozyra           target, level, internalformat, width, height, depth, border, format, type, vec.data());
7936297d8c7SWojciech Kozyra     });
7946297d8c7SWojciech Kozyra   } else {
7956297d8c7SWojciech Kozyra     auto image = loadImage(runtime, data, &width, &height, nullptr);
7966297d8c7SWojciech Kozyra     if (ctx->unpackFLipY) {
7976297d8c7SWojciech Kozyra       flip(image.get());
7986297d8c7SWojciech Kozyra     }
7996297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] {
8006297d8c7SWojciech Kozyra       glTexImage3D(
8016297d8c7SWojciech Kozyra           target, level, internalformat, width, height, depth, border, format, type, image.get());
8026297d8c7SWojciech Kozyra     });
8036297d8c7SWojciech Kozyra   }
8046297d8c7SWojciech Kozyra   return nullptr;
8056297d8c7SWojciech Kozyra }
8066297d8c7SWojciech Kozyra 
NATIVE_METHOD(texSubImage3D)8076297d8c7SWojciech Kozyra NATIVE_METHOD(texSubImage3D) {
8086297d8c7SWojciech Kozyra   CTX();
8096297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
8106297d8c7SWojciech Kozyra   auto level = ARG(1, GLint);
8116297d8c7SWojciech Kozyra   auto xoffset = ARG(2, GLint);
8126297d8c7SWojciech Kozyra   auto yoffset = ARG(3, GLint);
8136297d8c7SWojciech Kozyra   auto zoffset = ARG(4, GLint);
8146297d8c7SWojciech Kozyra   auto width = ARG(5, GLsizei);
8156297d8c7SWojciech Kozyra   auto height = ARG(6, GLsizei);
8166297d8c7SWojciech Kozyra   auto depth = ARG(7, GLsizei);
8176297d8c7SWojciech Kozyra   auto format = ARG(8, GLenum);
8186297d8c7SWojciech Kozyra   auto type = ARG(9, GLenum);
8196297d8c7SWojciech Kozyra 
8206297d8c7SWojciech Kozyra   if (ARG(10, const jsi::Value &).isNull()) {
8216297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] {
8226297d8c7SWojciech Kozyra       auto empty = std::make_unique<uint8_t>(width * height * depth * bytesPerPixel(type, format));
8236297d8c7SWojciech Kozyra       std::memset(empty.get(), 0, width * height * depth * bytesPerPixel(type, format));
8246297d8c7SWojciech Kozyra       auto ptr = empty.get();
8256297d8c7SWojciech Kozyra       glTexSubImage3D(
8266297d8c7SWojciech Kozyra           target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, ptr);
8276297d8c7SWojciech Kozyra     });
8286297d8c7SWojciech Kozyra     return nullptr;
8296297d8c7SWojciech Kozyra   }
8306297d8c7SWojciech Kozyra   auto data = ARG(10, jsi::Object);
8316297d8c7SWojciech Kozyra   auto flip = [&](uint8_t *data) {
8326297d8c7SWojciech Kozyra     GLubyte *texelLayer = data;
8336297d8c7SWojciech Kozyra     for (int z = 0; z < depth; z++) {
8346297d8c7SWojciech Kozyra       flipPixels(texelLayer, width * bytesPerPixel(type, format), height);
8356297d8c7SWojciech Kozyra       texelLayer += bytesPerPixel(type, format) * width * height;
8366297d8c7SWojciech Kozyra     }
8376297d8c7SWojciech Kozyra   };
8386297d8c7SWojciech Kozyra 
8396297d8c7SWojciech Kozyra   if (data.isArrayBuffer(runtime) || isTypedArray(runtime, data)) {
8406297d8c7SWojciech Kozyra     std::vector<uint8_t> vec = rawTypedArray(runtime, std::move(data));
8416297d8c7SWojciech Kozyra     if (ctx->unpackFLipY) {
8426297d8c7SWojciech Kozyra       flip(vec.data());
8436297d8c7SWojciech Kozyra     }
8446297d8c7SWojciech Kozyra     ctx->addToNextBatch([=, vec{std::move(vec)}] {
8456297d8c7SWojciech Kozyra       glTexSubImage3D(
8466297d8c7SWojciech Kozyra           target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, vec.data());
8476297d8c7SWojciech Kozyra     });
8486297d8c7SWojciech Kozyra   } else {
8496297d8c7SWojciech Kozyra     auto image = loadImage(runtime, data, &width, &height, nullptr);
8506297d8c7SWojciech Kozyra     if (ctx->unpackFLipY) {
8516297d8c7SWojciech Kozyra       flip(image.get());
8526297d8c7SWojciech Kozyra     }
8536297d8c7SWojciech Kozyra     ctx->addToNextBatch([=] {
8546297d8c7SWojciech Kozyra       glTexSubImage3D(
8556297d8c7SWojciech Kozyra           target,
8566297d8c7SWojciech Kozyra           level,
8576297d8c7SWojciech Kozyra           xoffset,
8586297d8c7SWojciech Kozyra           yoffset,
8596297d8c7SWojciech Kozyra           zoffset,
8606297d8c7SWojciech Kozyra           width,
8616297d8c7SWojciech Kozyra           height,
8626297d8c7SWojciech Kozyra           depth,
8636297d8c7SWojciech Kozyra           format,
8646297d8c7SWojciech Kozyra           type,
8656297d8c7SWojciech Kozyra           image.get());
8666297d8c7SWojciech Kozyra     });
8676297d8c7SWojciech Kozyra   }
8686297d8c7SWojciech Kozyra   return nullptr;
8696297d8c7SWojciech Kozyra }
8706297d8c7SWojciech Kozyra 
8716297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
8726297d8c7SWojciech Kozyra     copyTexSubImage3D,
8736297d8c7SWojciech Kozyra     glCopyTexSubImage3D); // target, level, xoffset, yoffset, zoffset, x, y, width, height
8746297d8c7SWojciech Kozyra 
8756297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(compressedTexImage3D)
8766297d8c7SWojciech Kozyra 
UNIMPL_NATIVE_METHOD(compressedTexSubImage3D)8776297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(compressedTexSubImage3D)
8786297d8c7SWojciech Kozyra 
8796297d8c7SWojciech Kozyra // Programs and shaders
8806297d8c7SWojciech Kozyra // --------------------
8816297d8c7SWojciech Kozyra 
8826297d8c7SWojciech Kozyra NATIVE_METHOD(attachShader) {
8836297d8c7SWojciech Kozyra   CTX();
8846297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
8856297d8c7SWojciech Kozyra   auto shader = ARG(1, EXWebGLClass);
8866297d8c7SWojciech Kozyra   ctx->addToNextBatch(
8876297d8c7SWojciech Kozyra       [=] { glAttachShader(ctx->lookupObject(program), ctx->lookupObject(shader)); });
8886297d8c7SWojciech Kozyra   return nullptr;
8896297d8c7SWojciech Kozyra }
8906297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindAttribLocation)8916297d8c7SWojciech Kozyra NATIVE_METHOD(bindAttribLocation) {
8926297d8c7SWojciech Kozyra   CTX();
8936297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
8946297d8c7SWojciech Kozyra   auto index = ARG(1, GLuint);
8956297d8c7SWojciech Kozyra   auto name = ARG(2, std::string);
8966297d8c7SWojciech Kozyra   ctx->addToNextBatch([=, name{std::move(name)}] {
8976297d8c7SWojciech Kozyra     glBindAttribLocation(ctx->lookupObject(program), index, name.c_str());
8986297d8c7SWojciech Kozyra   });
8996297d8c7SWojciech Kozyra   return nullptr;
9006297d8c7SWojciech Kozyra }
9016297d8c7SWojciech Kozyra 
NATIVE_METHOD(compileShader)9026297d8c7SWojciech Kozyra NATIVE_METHOD(compileShader) {
9036297d8c7SWojciech Kozyra   CTX();
9046297d8c7SWojciech Kozyra   auto shader = ARG(0, EXWebGLClass);
9056297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glCompileShader(ctx->lookupObject(shader)); });
9066297d8c7SWojciech Kozyra   return nullptr;
9076297d8c7SWojciech Kozyra }
9086297d8c7SWojciech Kozyra 
NATIVE_METHOD(createProgram)9096297d8c7SWojciech Kozyra NATIVE_METHOD(createProgram) {
9106297d8c7SWojciech Kozyra   CTX();
9116297d8c7SWojciech Kozyra   return exglCreateObject(ctx, runtime, glCreateProgram, EXWebGLClass::WebGLProgram);
9126297d8c7SWojciech Kozyra }
9136297d8c7SWojciech Kozyra 
NATIVE_METHOD(createShader)9146297d8c7SWojciech Kozyra NATIVE_METHOD(createShader) {
9156297d8c7SWojciech Kozyra   CTX();
9166297d8c7SWojciech Kozyra   auto type = ARG(0, GLenum);
9176297d8c7SWojciech Kozyra   if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) {
9186297d8c7SWojciech Kozyra     return exglCreateObject(
9196297d8c7SWojciech Kozyra         ctx, runtime, std::bind(glCreateShader, type), EXWebGLClass::WebGLShader);
9206297d8c7SWojciech Kozyra   } else {
9216297d8c7SWojciech Kozyra     throw std::runtime_error("unknown shader type passed to function");
9226297d8c7SWojciech Kozyra   }
9236297d8c7SWojciech Kozyra }
9246297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteProgram)9256297d8c7SWojciech Kozyra NATIVE_METHOD(deleteProgram) {
9266297d8c7SWojciech Kozyra   CTX();
9276297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteProgram);
9286297d8c7SWojciech Kozyra }
9296297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteShader)9306297d8c7SWojciech Kozyra NATIVE_METHOD(deleteShader) {
9316297d8c7SWojciech Kozyra   CTX();
9326297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteShader);
9336297d8c7SWojciech Kozyra }
9346297d8c7SWojciech Kozyra 
NATIVE_METHOD(detachShader)9356297d8c7SWojciech Kozyra NATIVE_METHOD(detachShader) {
9366297d8c7SWojciech Kozyra   CTX();
9376297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
9386297d8c7SWojciech Kozyra   auto shader = ARG(1, EXWebGLClass);
9396297d8c7SWojciech Kozyra   ctx->addToNextBatch(
9406297d8c7SWojciech Kozyra       [=] { glDetachShader(ctx->lookupObject(program), ctx->lookupObject(shader)); });
9416297d8c7SWojciech Kozyra   return nullptr;
9426297d8c7SWojciech Kozyra }
9436297d8c7SWojciech Kozyra 
NATIVE_METHOD(getAttachedShaders)9446297d8c7SWojciech Kozyra NATIVE_METHOD(getAttachedShaders) {
9456297d8c7SWojciech Kozyra   CTX();
9466297d8c7SWojciech Kozyra   auto fProgram = ARG(0, EXWebGLClass);
9476297d8c7SWojciech Kozyra 
9486297d8c7SWojciech Kozyra   GLint count;
9496297d8c7SWojciech Kozyra   std::vector<GLuint> glResults;
9506297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
9516297d8c7SWojciech Kozyra     GLuint program = ctx->lookupObject(fProgram);
9526297d8c7SWojciech Kozyra     glGetProgramiv(program, GL_ATTACHED_SHADERS, &count);
9536297d8c7SWojciech Kozyra     glResults.resize(count);
9546297d8c7SWojciech Kozyra     glGetAttachedShaders(program, count, nullptr, glResults.data());
9556297d8c7SWojciech Kozyra   });
9566297d8c7SWojciech Kozyra 
9576297d8c7SWojciech Kozyra   jsi::Array jsResults(runtime, count);
9586297d8c7SWojciech Kozyra   for (auto i = 0; i < count; ++i) {
9596297d8c7SWojciech Kozyra     EXGLObjectId exglObjId = 0;
9606297d8c7SWojciech Kozyra     for (const auto &pair : ctx->objects) {
9616297d8c7SWojciech Kozyra       if (pair.second == glResults[i]) {
9626297d8c7SWojciech Kozyra         exglObjId = pair.first;
9636297d8c7SWojciech Kozyra       }
9646297d8c7SWojciech Kozyra     }
9656297d8c7SWojciech Kozyra     if (exglObjId == 0) {
9666297d8c7SWojciech Kozyra       throw std::runtime_error(
9676297d8c7SWojciech Kozyra           "EXGL: Internal error: couldn't find EXGLObjectId "
9686297d8c7SWojciech Kozyra           "associated with shader in getAttachedShaders()!");
9696297d8c7SWojciech Kozyra     }
9706297d8c7SWojciech Kozyra     jsResults.setValueAtIndex(
9716297d8c7SWojciech Kozyra         runtime,
9726297d8c7SWojciech Kozyra         i,
9736297d8c7SWojciech Kozyra         createWebGLObject(runtime, EXWebGLClass::WebGLShader, {static_cast<double>(exglObjId)}));
9746297d8c7SWojciech Kozyra   }
9756297d8c7SWojciech Kozyra   return jsResults;
9766297d8c7SWojciech Kozyra }
9776297d8c7SWojciech Kozyra 
NATIVE_METHOD(getProgramParameter)9786297d8c7SWojciech Kozyra NATIVE_METHOD(getProgramParameter) {
9796297d8c7SWojciech Kozyra   CTX();
9806297d8c7SWojciech Kozyra   auto fProgram = ARG(0, EXWebGLClass);
9816297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
9826297d8c7SWojciech Kozyra   GLint glResult;
9836297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
9846297d8c7SWojciech Kozyra       [&] { glGetProgramiv(ctx->lookupObject(fProgram), pname, &glResult); });
9856297d8c7SWojciech Kozyra   if (pname == GL_DELETE_STATUS || pname == GL_LINK_STATUS || pname == GL_VALIDATE_STATUS) {
9866297d8c7SWojciech Kozyra     return glResult == GL_TRUE;
9876297d8c7SWojciech Kozyra   } else {
9886297d8c7SWojciech Kozyra     return glResult;
9896297d8c7SWojciech Kozyra   }
9906297d8c7SWojciech Kozyra }
9916297d8c7SWojciech Kozyra 
NATIVE_METHOD(getShaderParameter)9926297d8c7SWojciech Kozyra NATIVE_METHOD(getShaderParameter) {
9936297d8c7SWojciech Kozyra   CTX();
9946297d8c7SWojciech Kozyra   auto fShader = ARG(0, EXWebGLClass);
9956297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
9966297d8c7SWojciech Kozyra   GLint glResult;
9976297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] { glGetShaderiv(ctx->lookupObject(fShader), pname, &glResult); });
9986297d8c7SWojciech Kozyra   if (pname == GL_DELETE_STATUS || pname == GL_COMPILE_STATUS) {
9996297d8c7SWojciech Kozyra     return glResult == GL_TRUE;
10006297d8c7SWojciech Kozyra   } else {
10016297d8c7SWojciech Kozyra     return glResult;
10026297d8c7SWojciech Kozyra   }
10036297d8c7SWojciech Kozyra }
10046297d8c7SWojciech Kozyra 
NATIVE_METHOD(getShaderPrecisionFormat)10056297d8c7SWojciech Kozyra NATIVE_METHOD(getShaderPrecisionFormat) {
10066297d8c7SWojciech Kozyra   CTX();
10076297d8c7SWojciech Kozyra   auto shaderType = ARG(0, GLenum);
10086297d8c7SWojciech Kozyra   auto precisionType = ARG(1, GLenum);
10096297d8c7SWojciech Kozyra 
10106297d8c7SWojciech Kozyra   GLint range[2], precision;
10116297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
10126297d8c7SWojciech Kozyra       [&] { glGetShaderPrecisionFormat(shaderType, precisionType, range, &precision); });
10136297d8c7SWojciech Kozyra 
10146297d8c7SWojciech Kozyra   jsi::Object jsResult =
10156297d8c7SWojciech Kozyra       createWebGLObject(runtime, EXWebGLClass::WebGLShaderPrecisionFormat, {}).asObject(runtime);
10166297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "rangeMin", jsi::Value(range[0]));
10176297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "rangeMax", jsi::Value(range[1]));
10186297d8c7SWojciech Kozyra   jsResult.setProperty(runtime, "precision", jsi::Value(precision));
10196297d8c7SWojciech Kozyra   return jsResult;
10206297d8c7SWojciech Kozyra }
10216297d8c7SWojciech Kozyra 
NATIVE_METHOD(getProgramInfoLog)10226297d8c7SWojciech Kozyra NATIVE_METHOD(getProgramInfoLog) {
10236297d8c7SWojciech Kozyra   CTX();
10246297d8c7SWojciech Kozyra   auto fObj = ARG(0, EXWebGLClass);
10256297d8c7SWojciech Kozyra   std::string str;
10266297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
10276297d8c7SWojciech Kozyra     GLuint obj = ctx->lookupObject(fObj);
10286297d8c7SWojciech Kozyra     GLint length;
10296297d8c7SWojciech Kozyra     glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
10306297d8c7SWojciech Kozyra     str.resize(length > 0 ? length - 1 : 0);
10316297d8c7SWojciech Kozyra     glGetProgramInfoLog(obj, length, nullptr, &str[0]);
10326297d8c7SWojciech Kozyra   });
10336297d8c7SWojciech Kozyra   return jsi::String::createFromUtf8(runtime, str);
10346297d8c7SWojciech Kozyra }
10356297d8c7SWojciech Kozyra 
NATIVE_METHOD(getShaderInfoLog)10366297d8c7SWojciech Kozyra NATIVE_METHOD(getShaderInfoLog) {
10376297d8c7SWojciech Kozyra   CTX();
10386297d8c7SWojciech Kozyra   auto fObj = ARG(0, EXWebGLClass);
10396297d8c7SWojciech Kozyra   std::string str;
10406297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
10416297d8c7SWojciech Kozyra     GLuint obj = ctx->lookupObject(fObj);
10426297d8c7SWojciech Kozyra     GLint length;
10436297d8c7SWojciech Kozyra     glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
10446297d8c7SWojciech Kozyra     str.resize(length > 0 ? length - 1 : 0);
10456297d8c7SWojciech Kozyra     glGetShaderInfoLog(obj, length, nullptr, &str[0]);
10466297d8c7SWojciech Kozyra   });
10476297d8c7SWojciech Kozyra   return jsi::String::createFromUtf8(runtime, str);
10486297d8c7SWojciech Kozyra }
10496297d8c7SWojciech Kozyra 
NATIVE_METHOD(getShaderSource)10506297d8c7SWojciech Kozyra NATIVE_METHOD(getShaderSource) {
10516297d8c7SWojciech Kozyra   CTX();
10526297d8c7SWojciech Kozyra   auto fObj = ARG(0, EXWebGLClass);
10536297d8c7SWojciech Kozyra   std::string str;
10546297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
10556297d8c7SWojciech Kozyra     GLuint obj = ctx->lookupObject(fObj);
10566297d8c7SWojciech Kozyra     GLint length;
10576297d8c7SWojciech Kozyra     glGetShaderiv(obj, GL_SHADER_SOURCE_LENGTH, &length);
10586297d8c7SWojciech Kozyra     str.resize(length > 0 ? length - 1 : 0);
10596297d8c7SWojciech Kozyra     glGetShaderSource(obj, length, nullptr, &str[0]);
10606297d8c7SWojciech Kozyra   });
10616297d8c7SWojciech Kozyra   return jsi::String::createFromUtf8(runtime, str);
10626297d8c7SWojciech Kozyra }
10636297d8c7SWojciech Kozyra 
NATIVE_METHOD(isShader)10646297d8c7SWojciech Kozyra NATIVE_METHOD(isShader) {
10656297d8c7SWojciech Kozyra   CTX();
10666297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsShader);
10676297d8c7SWojciech Kozyra }
10686297d8c7SWojciech Kozyra 
NATIVE_METHOD(isProgram)10696297d8c7SWojciech Kozyra NATIVE_METHOD(isProgram) {
10706297d8c7SWojciech Kozyra   CTX();
10716297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsProgram);
10726297d8c7SWojciech Kozyra }
10736297d8c7SWojciech Kozyra 
NATIVE_METHOD(linkProgram)10746297d8c7SWojciech Kozyra NATIVE_METHOD(linkProgram) {
10756297d8c7SWojciech Kozyra   CTX();
10766297d8c7SWojciech Kozyra   auto fProgram = ARG(0, EXWebGLClass);
10776297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glLinkProgram(ctx->lookupObject(fProgram)); });
10786297d8c7SWojciech Kozyra   return nullptr;
10796297d8c7SWojciech Kozyra }
10806297d8c7SWojciech Kozyra 
NATIVE_METHOD(shaderSource)10816297d8c7SWojciech Kozyra NATIVE_METHOD(shaderSource) {
10826297d8c7SWojciech Kozyra   CTX();
10836297d8c7SWojciech Kozyra   auto fShader = ARG(0, EXWebGLClass);
10846297d8c7SWojciech Kozyra   auto str = ARG(1, std::string);
10856297d8c7SWojciech Kozyra   ctx->addToNextBatch([=, str{std::move(str)}] {
10866297d8c7SWojciech Kozyra     const char *cstr = str.c_str();
10876297d8c7SWojciech Kozyra     glShaderSource(ctx->lookupObject(fShader), 1, &cstr, nullptr);
10886297d8c7SWojciech Kozyra   });
10896297d8c7SWojciech Kozyra   return nullptr;
10906297d8c7SWojciech Kozyra }
10916297d8c7SWojciech Kozyra 
NATIVE_METHOD(useProgram)10926297d8c7SWojciech Kozyra NATIVE_METHOD(useProgram) {
10936297d8c7SWojciech Kozyra   CTX();
10946297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
10956297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glUseProgram(ctx->lookupObject(program)); });
10966297d8c7SWojciech Kozyra   return nullptr;
10976297d8c7SWojciech Kozyra }
10986297d8c7SWojciech Kozyra 
NATIVE_METHOD(validateProgram)10996297d8c7SWojciech Kozyra NATIVE_METHOD(validateProgram) {
11006297d8c7SWojciech Kozyra   CTX();
11016297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
11026297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glValidateProgram(ctx->lookupObject(program)); });
11036297d8c7SWojciech Kozyra   return nullptr;
11046297d8c7SWojciech Kozyra }
11056297d8c7SWojciech Kozyra 
11066297d8c7SWojciech Kozyra // Programs and shaders (WebGL2)
11076297d8c7SWojciech Kozyra 
NATIVE_METHOD(getFragDataLocation)11086297d8c7SWojciech Kozyra NATIVE_METHOD(getFragDataLocation) {
11096297d8c7SWojciech Kozyra   CTX();
11106297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
11116297d8c7SWojciech Kozyra   auto name = ARG(1, std::string);
11126297d8c7SWojciech Kozyra   GLint location;
11136297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
11146297d8c7SWojciech Kozyra       [&] { location = glGetFragDataLocation(ctx->lookupObject(program), name.c_str()); });
11156297d8c7SWojciech Kozyra   return location == -1 ? jsi::Value::null() : jsi::Value(location);
11166297d8c7SWojciech Kozyra }
11176297d8c7SWojciech Kozyra 
11186297d8c7SWojciech Kozyra // Uniforms and attributes
11196297d8c7SWojciech Kozyra // -----------------------
11206297d8c7SWojciech Kozyra 
11216297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(disableVertexAttribArray, glDisableVertexAttribArray); // index
11226297d8c7SWojciech Kozyra 
11236297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(enableVertexAttribArray, glEnableVertexAttribArray); // index
11246297d8c7SWojciech Kozyra 
NATIVE_METHOD(getActiveAttrib)11256297d8c7SWojciech Kozyra NATIVE_METHOD(getActiveAttrib) {
11266297d8c7SWojciech Kozyra   CTX();
11276297d8c7SWojciech Kozyra   return exglGetActiveInfo(
11286297d8c7SWojciech Kozyra       ctx,
11296297d8c7SWojciech Kozyra       runtime,
11306297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
11316297d8c7SWojciech Kozyra       ARG(1, GLuint),
11326297d8c7SWojciech Kozyra       GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
11336297d8c7SWojciech Kozyra       glGetActiveAttrib);
11346297d8c7SWojciech Kozyra }
11356297d8c7SWojciech Kozyra 
NATIVE_METHOD(getActiveUniform)11366297d8c7SWojciech Kozyra NATIVE_METHOD(getActiveUniform) {
11376297d8c7SWojciech Kozyra   CTX();
11386297d8c7SWojciech Kozyra   return exglGetActiveInfo(
11396297d8c7SWojciech Kozyra       ctx,
11406297d8c7SWojciech Kozyra       runtime,
11416297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
11426297d8c7SWojciech Kozyra       ARG(1, GLuint),
11436297d8c7SWojciech Kozyra       GL_ACTIVE_UNIFORM_MAX_LENGTH,
11446297d8c7SWojciech Kozyra       glGetActiveUniform);
11456297d8c7SWojciech Kozyra }
11466297d8c7SWojciech Kozyra 
NATIVE_METHOD(getAttribLocation)11476297d8c7SWojciech Kozyra NATIVE_METHOD(getAttribLocation) {
11486297d8c7SWojciech Kozyra   CTX();
11496297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
11506297d8c7SWojciech Kozyra   auto name = ARG(1, std::string);
11516297d8c7SWojciech Kozyra   GLint location;
11526297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
11536297d8c7SWojciech Kozyra       [&] { location = glGetAttribLocation(ctx->lookupObject(program), name.c_str()); });
11546297d8c7SWojciech Kozyra   return jsi::Value(location);
11556297d8c7SWojciech Kozyra }
11566297d8c7SWojciech Kozyra 
11576297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getUniform)
11586297d8c7SWojciech Kozyra 
NATIVE_METHOD(getUniformLocation)11596297d8c7SWojciech Kozyra NATIVE_METHOD(getUniformLocation) {
11606297d8c7SWojciech Kozyra   CTX();
11616297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
11626297d8c7SWojciech Kozyra   auto name = ARG(1, std::string);
11636297d8c7SWojciech Kozyra   GLint location;
11646297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
11656297d8c7SWojciech Kozyra       [&] { location = glGetUniformLocation(ctx->lookupObject(program), name.c_str()); });
11666297d8c7SWojciech Kozyra   return location == -1
11676297d8c7SWojciech Kozyra       ? jsi::Value::null()
11686297d8c7SWojciech Kozyra       : createWebGLObject(runtime, EXWebGLClass::WebGLUniformLocation, {location});
11696297d8c7SWojciech Kozyra }
11706297d8c7SWojciech Kozyra 
11716297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getVertexAttrib)
11726297d8c7SWojciech Kozyra 
UNIMPL_NATIVE_METHOD(getVertexAttribOffset)11736297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getVertexAttribOffset)
11746297d8c7SWojciech Kozyra 
11756297d8c7SWojciech Kozyra NATIVE_METHOD(uniform1f) {
11766297d8c7SWojciech Kozyra   CTX();
11776297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
11786297d8c7SWojciech Kozyra   auto x = ARG(1, GLfloat);
11796297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x]() { glUniform1f(uniform, x); });
11806297d8c7SWojciech Kozyra   return nullptr;
11816297d8c7SWojciech Kozyra }
11826297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform2f)11836297d8c7SWojciech Kozyra NATIVE_METHOD(uniform2f) {
11846297d8c7SWojciech Kozyra   CTX();
11856297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
11866297d8c7SWojciech Kozyra   auto x = ARG(1, GLfloat);
11876297d8c7SWojciech Kozyra   auto y = ARG(2, GLfloat);
11886297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y]() { glUniform2f(uniform, x, y); });
11896297d8c7SWojciech Kozyra   return nullptr;
11906297d8c7SWojciech Kozyra }
11916297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform3f)11926297d8c7SWojciech Kozyra NATIVE_METHOD(uniform3f) {
11936297d8c7SWojciech Kozyra   CTX();
11946297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
11956297d8c7SWojciech Kozyra   auto x = ARG(1, GLfloat);
11966297d8c7SWojciech Kozyra   auto y = ARG(2, GLfloat);
11976297d8c7SWojciech Kozyra   auto z = ARG(3, GLfloat);
11986297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y, z]() { glUniform3f(uniform, x, y, z); });
11996297d8c7SWojciech Kozyra   return nullptr;
12006297d8c7SWojciech Kozyra }
12016297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform4f)12026297d8c7SWojciech Kozyra NATIVE_METHOD(uniform4f) {
12036297d8c7SWojciech Kozyra   CTX();
12046297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
12056297d8c7SWojciech Kozyra   auto x = ARG(1, GLfloat);
12066297d8c7SWojciech Kozyra   auto y = ARG(2, GLfloat);
12076297d8c7SWojciech Kozyra   auto z = ARG(3, GLfloat);
12086297d8c7SWojciech Kozyra   auto w = ARG(4, GLfloat);
12096297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y, z, w]() { glUniform4f(uniform, x, y, z, w); });
12106297d8c7SWojciech Kozyra   return nullptr;
12116297d8c7SWojciech Kozyra }
12126297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform1i)12136297d8c7SWojciech Kozyra NATIVE_METHOD(uniform1i) {
12146297d8c7SWojciech Kozyra   CTX();
12156297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
12166297d8c7SWojciech Kozyra   auto x = ARG(1, GLint);
12176297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x]() { glUniform1i(uniform, x); });
12186297d8c7SWojciech Kozyra   return nullptr;
12196297d8c7SWojciech Kozyra }
12206297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform2i)12216297d8c7SWojciech Kozyra NATIVE_METHOD(uniform2i) {
12226297d8c7SWojciech Kozyra   CTX();
12236297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
12246297d8c7SWojciech Kozyra   auto x = ARG(1, GLint);
12256297d8c7SWojciech Kozyra   auto y = ARG(2, GLint);
12266297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y]() { glUniform2i(uniform, x, y); });
12276297d8c7SWojciech Kozyra   return nullptr;
12286297d8c7SWojciech Kozyra }
12296297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform3i)12306297d8c7SWojciech Kozyra NATIVE_METHOD(uniform3i) {
12316297d8c7SWojciech Kozyra   CTX();
12326297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
12336297d8c7SWojciech Kozyra   auto x = ARG(1, GLint);
12346297d8c7SWojciech Kozyra   auto y = ARG(2, GLint);
12356297d8c7SWojciech Kozyra   auto z = ARG(3, GLint);
12366297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y, z]() { glUniform3i(uniform, x, y, z); });
12376297d8c7SWojciech Kozyra   return nullptr;
12386297d8c7SWojciech Kozyra }
12396297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform4i)12406297d8c7SWojciech Kozyra NATIVE_METHOD(uniform4i) {
12416297d8c7SWojciech Kozyra   CTX();
12426297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
12436297d8c7SWojciech Kozyra   auto x = ARG(1, GLint);
12446297d8c7SWojciech Kozyra   auto y = ARG(2, GLint);
12456297d8c7SWojciech Kozyra   auto z = ARG(3, GLint);
12466297d8c7SWojciech Kozyra   auto w = ARG(4, GLint);
12476297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y, z, w]() { glUniform4i(uniform, x, y, z, w); });
12486297d8c7SWojciech Kozyra   return nullptr;
12496297d8c7SWojciech Kozyra }
12506297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform1fv)12516297d8c7SWojciech Kozyra NATIVE_METHOD(uniform1fv) {
12526297d8c7SWojciech Kozyra   CTX();
12536297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform1fv, ARG(0, EXWebGLClass), 1, ARG(1, std::vector<float>));
12546297d8c7SWojciech Kozyra };
12556297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform2fv)12566297d8c7SWojciech Kozyra NATIVE_METHOD(uniform2fv) {
12576297d8c7SWojciech Kozyra   CTX();
12586297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform2fv, ARG(0, EXWebGLClass), 2, ARG(1, std::vector<float>));
12596297d8c7SWojciech Kozyra };
12606297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform3fv)12616297d8c7SWojciech Kozyra NATIVE_METHOD(uniform3fv) {
12626297d8c7SWojciech Kozyra   CTX();
12636297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform3fv, ARG(0, EXWebGLClass), 3, ARG(1, std::vector<float>));
12646297d8c7SWojciech Kozyra };
12656297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform4fv)12666297d8c7SWojciech Kozyra NATIVE_METHOD(uniform4fv) {
12676297d8c7SWojciech Kozyra   CTX();
12686297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform4fv, ARG(0, EXWebGLClass), 4, ARG(1, std::vector<float>));
12696297d8c7SWojciech Kozyra };
12706297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform1iv)12716297d8c7SWojciech Kozyra NATIVE_METHOD(uniform1iv) {
12726297d8c7SWojciech Kozyra   CTX();
12736297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform1iv, ARG(0, EXWebGLClass), 1, ARG(1, std::vector<int32_t>));
12746297d8c7SWojciech Kozyra };
12756297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform2iv)12766297d8c7SWojciech Kozyra NATIVE_METHOD(uniform2iv) {
12776297d8c7SWojciech Kozyra   CTX();
12786297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform2iv, ARG(0, EXWebGLClass), 2, ARG(1, std::vector<int32_t>));
12796297d8c7SWojciech Kozyra };
12806297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform3iv)12816297d8c7SWojciech Kozyra NATIVE_METHOD(uniform3iv) {
12826297d8c7SWojciech Kozyra   CTX();
12836297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform3iv, ARG(0, EXWebGLClass), 3, ARG(1, std::vector<int32_t>));
12846297d8c7SWojciech Kozyra };
12856297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform4iv)12866297d8c7SWojciech Kozyra NATIVE_METHOD(uniform4iv) {
12876297d8c7SWojciech Kozyra   CTX();
12886297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform4iv, ARG(0, EXWebGLClass), 4, ARG(1, std::vector<int32_t>));
12896297d8c7SWojciech Kozyra };
12906297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix2fv)12916297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix2fv) {
12926297d8c7SWojciech Kozyra   CTX();
12936297d8c7SWojciech Kozyra   return exglUniformMatrixv(
12946297d8c7SWojciech Kozyra       ctx,
12956297d8c7SWojciech Kozyra       glUniformMatrix2fv,
12966297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
12976297d8c7SWojciech Kozyra       ARG(1, GLboolean),
12986297d8c7SWojciech Kozyra       4,
12996297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
13006297d8c7SWojciech Kozyra }
13016297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix3fv)13026297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix3fv) {
13036297d8c7SWojciech Kozyra   CTX();
13046297d8c7SWojciech Kozyra   return exglUniformMatrixv(
13056297d8c7SWojciech Kozyra       ctx,
13066297d8c7SWojciech Kozyra       glUniformMatrix3fv,
13076297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
13086297d8c7SWojciech Kozyra       ARG(1, GLboolean),
13096297d8c7SWojciech Kozyra       9,
13106297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
13116297d8c7SWojciech Kozyra }
13126297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix4fv)13136297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix4fv) {
13146297d8c7SWojciech Kozyra   CTX();
13156297d8c7SWojciech Kozyra   return exglUniformMatrixv(
13166297d8c7SWojciech Kozyra       ctx,
13176297d8c7SWojciech Kozyra       glUniformMatrix4fv,
13186297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
13196297d8c7SWojciech Kozyra       ARG(1, GLboolean),
13206297d8c7SWojciech Kozyra       16,
13216297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
13226297d8c7SWojciech Kozyra }
13236297d8c7SWojciech Kozyra 
NATIVE_METHOD(vertexAttrib1fv)13246297d8c7SWojciech Kozyra NATIVE_METHOD(vertexAttrib1fv) {
13256297d8c7SWojciech Kozyra   CTX();
13266297d8c7SWojciech Kozyra   return exglVertexAttribv(
13276297d8c7SWojciech Kozyra       ctx, glVertexAttrib1fv, ARG(0, EXWebGLClass), ARG(1, std::vector<float>));
13286297d8c7SWojciech Kozyra }
13296297d8c7SWojciech Kozyra 
NATIVE_METHOD(vertexAttrib2fv)13306297d8c7SWojciech Kozyra NATIVE_METHOD(vertexAttrib2fv) {
13316297d8c7SWojciech Kozyra   CTX();
13326297d8c7SWojciech Kozyra   return exglVertexAttribv(
13336297d8c7SWojciech Kozyra       ctx, glVertexAttrib2fv, ARG(0, EXWebGLClass), ARG(1, std::vector<float>));
13346297d8c7SWojciech Kozyra }
13356297d8c7SWojciech Kozyra 
NATIVE_METHOD(vertexAttrib3fv)13366297d8c7SWojciech Kozyra NATIVE_METHOD(vertexAttrib3fv) {
13376297d8c7SWojciech Kozyra   CTX();
13386297d8c7SWojciech Kozyra   return exglVertexAttribv(
13396297d8c7SWojciech Kozyra       ctx, glVertexAttrib3fv, ARG(0, EXWebGLClass), ARG(1, std::vector<float>));
13406297d8c7SWojciech Kozyra }
13416297d8c7SWojciech Kozyra 
NATIVE_METHOD(vertexAttrib4fv)13426297d8c7SWojciech Kozyra NATIVE_METHOD(vertexAttrib4fv) {
13436297d8c7SWojciech Kozyra   CTX();
13446297d8c7SWojciech Kozyra   return exglVertexAttribv(
13456297d8c7SWojciech Kozyra       ctx, glVertexAttrib4fv, ARG(0, EXWebGLClass), ARG(1, std::vector<float>));
13466297d8c7SWojciech Kozyra }
13476297d8c7SWojciech Kozyra 
13486297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttrib1f, glVertexAttrib1f); // index, x
13496297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttrib2f, glVertexAttrib2f); // index, x, y
13506297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttrib3f, glVertexAttrib3f); // index, x, y, z
13516297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttrib4f, glVertexAttrib4f); // index, x, y, z, w
13526297d8c7SWojciech Kozyra 
13536297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
13546297d8c7SWojciech Kozyra     vertexAttribPointer,
13556297d8c7SWojciech Kozyra     glVertexAttribPointer); // index, itemSize, type, normalized, stride, const void *
13566297d8c7SWojciech Kozyra 
13576297d8c7SWojciech Kozyra // Uniforms and attributes (WebGL2)
13586297d8c7SWojciech Kozyra // --------------------------------
13596297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform1ui)13606297d8c7SWojciech Kozyra NATIVE_METHOD(uniform1ui) {
13616297d8c7SWojciech Kozyra   CTX();
13626297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
13636297d8c7SWojciech Kozyra   auto x = ARG(1, GLuint);
13646297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x]() { glUniform1ui(uniform, x); });
13656297d8c7SWojciech Kozyra   return nullptr;
13666297d8c7SWojciech Kozyra }
13676297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform2ui)13686297d8c7SWojciech Kozyra NATIVE_METHOD(uniform2ui) {
13696297d8c7SWojciech Kozyra   CTX();
13706297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
13716297d8c7SWojciech Kozyra   auto x = ARG(1, GLuint);
13726297d8c7SWojciech Kozyra   auto y = ARG(2, GLuint);
13736297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y]() { glUniform2ui(uniform, x, y); });
13746297d8c7SWojciech Kozyra   return nullptr;
13756297d8c7SWojciech Kozyra }
13766297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform3ui)13776297d8c7SWojciech Kozyra NATIVE_METHOD(uniform3ui) {
13786297d8c7SWojciech Kozyra   CTX();
13796297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
13806297d8c7SWojciech Kozyra   auto x = ARG(1, GLuint);
13816297d8c7SWojciech Kozyra   auto y = ARG(2, GLuint);
13826297d8c7SWojciech Kozyra   auto z = ARG(3, GLuint);
13836297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y, z]() { glUniform3ui(uniform, x, y, z); });
13846297d8c7SWojciech Kozyra   return nullptr;
13856297d8c7SWojciech Kozyra }
13866297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform4ui)13876297d8c7SWojciech Kozyra NATIVE_METHOD(uniform4ui) {
13886297d8c7SWojciech Kozyra   CTX();
13896297d8c7SWojciech Kozyra   auto uniform = ARG(0, EXWebGLClass);
13906297d8c7SWojciech Kozyra   auto x = ARG(1, GLuint);
13916297d8c7SWojciech Kozyra   auto y = ARG(2, GLuint);
13926297d8c7SWojciech Kozyra   auto z = ARG(3, GLuint);
13936297d8c7SWojciech Kozyra   auto w = ARG(4, GLuint);
13946297d8c7SWojciech Kozyra   ctx->addToNextBatch([uniform, x, y, z, w]() { glUniform4ui(uniform, x, y, z, w); });
13956297d8c7SWojciech Kozyra   return nullptr;
13966297d8c7SWojciech Kozyra }
13976297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform1uiv)13986297d8c7SWojciech Kozyra NATIVE_METHOD(uniform1uiv) {
13996297d8c7SWojciech Kozyra   CTX();
14006297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform1uiv, ARG(0, EXWebGLClass), 1, ARG(1, std::vector<uint32_t>));
14016297d8c7SWojciech Kozyra };
14026297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform2uiv)14036297d8c7SWojciech Kozyra NATIVE_METHOD(uniform2uiv) {
14046297d8c7SWojciech Kozyra   CTX();
14056297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform2uiv, ARG(0, EXWebGLClass), 2, ARG(1, std::vector<uint32_t>));
14066297d8c7SWojciech Kozyra };
14076297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform3uiv)14086297d8c7SWojciech Kozyra NATIVE_METHOD(uniform3uiv) {
14096297d8c7SWojciech Kozyra   CTX();
14106297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform3uiv, ARG(0, EXWebGLClass), 3, ARG(1, std::vector<uint32_t>));
14116297d8c7SWojciech Kozyra };
14126297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniform4uiv)14136297d8c7SWojciech Kozyra NATIVE_METHOD(uniform4uiv) {
14146297d8c7SWojciech Kozyra   CTX();
14156297d8c7SWojciech Kozyra   return exglUniformv(ctx, glUniform4uiv, ARG(0, EXWebGLClass), 4, ARG(1, std::vector<uint32_t>));
14166297d8c7SWojciech Kozyra };
14176297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix3x2fv)14186297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix3x2fv) {
14196297d8c7SWojciech Kozyra   CTX();
14206297d8c7SWojciech Kozyra   return exglUniformMatrixv(
14216297d8c7SWojciech Kozyra       ctx,
14226297d8c7SWojciech Kozyra       glUniformMatrix3x2fv,
14236297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
14246297d8c7SWojciech Kozyra       ARG(1, GLboolean),
14256297d8c7SWojciech Kozyra       6,
14266297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
14276297d8c7SWojciech Kozyra }
14286297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix4x2fv)14296297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix4x2fv) {
14306297d8c7SWojciech Kozyra   CTX();
14316297d8c7SWojciech Kozyra   return exglUniformMatrixv(
14326297d8c7SWojciech Kozyra       ctx,
14336297d8c7SWojciech Kozyra       glUniformMatrix4x2fv,
14346297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
14356297d8c7SWojciech Kozyra       ARG(1, GLboolean),
14366297d8c7SWojciech Kozyra       8,
14376297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
14386297d8c7SWojciech Kozyra }
14396297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix2x3fv)14406297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix2x3fv) {
14416297d8c7SWojciech Kozyra   CTX();
14426297d8c7SWojciech Kozyra   return exglUniformMatrixv(
14436297d8c7SWojciech Kozyra       ctx,
14446297d8c7SWojciech Kozyra       glUniformMatrix2x3fv,
14456297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
14466297d8c7SWojciech Kozyra       ARG(1, GLboolean),
14476297d8c7SWojciech Kozyra       6,
14486297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
14496297d8c7SWojciech Kozyra }
14506297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix4x3fv)14516297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix4x3fv) {
14526297d8c7SWojciech Kozyra   CTX();
14536297d8c7SWojciech Kozyra   return exglUniformMatrixv(
14546297d8c7SWojciech Kozyra       ctx,
14556297d8c7SWojciech Kozyra       glUniformMatrix4x3fv,
14566297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
14576297d8c7SWojciech Kozyra       ARG(1, GLboolean),
14586297d8c7SWojciech Kozyra       12,
14596297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
14606297d8c7SWojciech Kozyra }
14616297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix2x4fv)14626297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix2x4fv) {
14636297d8c7SWojciech Kozyra   CTX();
14646297d8c7SWojciech Kozyra   return exglUniformMatrixv(
14656297d8c7SWojciech Kozyra       ctx,
14666297d8c7SWojciech Kozyra       glUniformMatrix2x4fv,
14676297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
14686297d8c7SWojciech Kozyra       ARG(1, GLboolean),
14696297d8c7SWojciech Kozyra       8,
14706297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
14716297d8c7SWojciech Kozyra }
14726297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformMatrix3x4fv)14736297d8c7SWojciech Kozyra NATIVE_METHOD(uniformMatrix3x4fv) {
14746297d8c7SWojciech Kozyra   CTX();
14756297d8c7SWojciech Kozyra   return exglUniformMatrixv(
14766297d8c7SWojciech Kozyra       ctx,
14776297d8c7SWojciech Kozyra       glUniformMatrix3x4fv,
14786297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
14796297d8c7SWojciech Kozyra       ARG(1, GLboolean),
14806297d8c7SWojciech Kozyra       12,
14816297d8c7SWojciech Kozyra       ARG(2, std::vector<float>));
14826297d8c7SWojciech Kozyra }
14836297d8c7SWojciech Kozyra 
14846297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttribI4i, glVertexAttribI4i); // index, x, y, z, w
14856297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttribI4ui, glVertexAttribI4ui); // index, x, y, z, w
14866297d8c7SWojciech Kozyra 
NATIVE_METHOD(vertexAttribI4iv)14876297d8c7SWojciech Kozyra NATIVE_METHOD(vertexAttribI4iv) {
14886297d8c7SWojciech Kozyra   CTX();
14896297d8c7SWojciech Kozyra   return exglVertexAttribv(ctx, glVertexAttribI4iv, ARG(0, GLuint), ARG(1, std::vector<int32_t>));
14906297d8c7SWojciech Kozyra }
14916297d8c7SWojciech Kozyra 
NATIVE_METHOD(vertexAttribI4uiv)14926297d8c7SWojciech Kozyra NATIVE_METHOD(vertexAttribI4uiv) {
14936297d8c7SWojciech Kozyra   CTX();
14946297d8c7SWojciech Kozyra   return exglVertexAttribv(ctx, glVertexAttribI4uiv, ARG(0, GLuint), ARG(1, std::vector<uint32_t>));
14956297d8c7SWojciech Kozyra }
14966297d8c7SWojciech Kozyra 
14976297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
14986297d8c7SWojciech Kozyra     vertexAttribIPointer,
14996297d8c7SWojciech Kozyra     glVertexAttribIPointer); // index, size, type, stride, offset
15006297d8c7SWojciech Kozyra 
15016297d8c7SWojciech Kozyra // Drawing buffers
15026297d8c7SWojciech Kozyra // ---------------
15036297d8c7SWojciech Kozyra 
15046297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(clear, glClear); // mask
15056297d8c7SWojciech Kozyra 
15066297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(drawArrays, glDrawArrays); // mode, first, count)
15076297d8c7SWojciech Kozyra 
15086297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(drawElements, glDrawElements); // mode, count, type, offset
15096297d8c7SWojciech Kozyra 
15106297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(finish, glFinish);
15116297d8c7SWojciech Kozyra 
15126297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(flush, glFlush);
15136297d8c7SWojciech Kozyra 
15146297d8c7SWojciech Kozyra // Drawing buffers (WebGL2)
15156297d8c7SWojciech Kozyra // ------------------------
15166297d8c7SWojciech Kozyra 
15176297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(vertexAttribDivisor, glVertexAttribDivisor); // index, divisor
15186297d8c7SWojciech Kozyra 
15196297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
15206297d8c7SWojciech Kozyra     drawArraysInstanced,
15216297d8c7SWojciech Kozyra     glDrawArraysInstanced); // mode, first, count, instancecount
15226297d8c7SWojciech Kozyra 
15236297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
15246297d8c7SWojciech Kozyra     drawElementsInstanced,
15256297d8c7SWojciech Kozyra     glDrawElementsInstanced); // mode, count, type, offset, instanceCount
15266297d8c7SWojciech Kozyra 
15276297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(
15286297d8c7SWojciech Kozyra     drawRangeElements,
15296297d8c7SWojciech Kozyra     glDrawRangeElements); // mode, start, end, count, type, offset
15306297d8c7SWojciech Kozyra 
NATIVE_METHOD(drawBuffers)15316297d8c7SWojciech Kozyra NATIVE_METHOD(drawBuffers) {
15326297d8c7SWojciech Kozyra   CTX();
15336297d8c7SWojciech Kozyra   auto data = jsArrayToVector<GLenum>(runtime, ARG(0, jsi::Array));
15346297d8c7SWojciech Kozyra   ctx->addToNextBatch(
15356297d8c7SWojciech Kozyra       [data{std::move(data)}] { glDrawBuffers(static_cast<GLsizei>(data.size()), data.data()); });
15366297d8c7SWojciech Kozyra   return nullptr;
15376297d8c7SWojciech Kozyra }
15386297d8c7SWojciech Kozyra 
NATIVE_METHOD(clearBufferfv)15396297d8c7SWojciech Kozyra NATIVE_METHOD(clearBufferfv) {
15406297d8c7SWojciech Kozyra   CTX();
15416297d8c7SWojciech Kozyra   auto buffer = ARG(0, GLenum);
15426297d8c7SWojciech Kozyra   auto drawbuffer = ARG(1, GLint);
15436297d8c7SWojciech Kozyra   auto values = ARG(2, TypedArrayKind::Float32Array).toVector(runtime);
15446297d8c7SWojciech Kozyra   ctx->addToNextBatch(
15456297d8c7SWojciech Kozyra       [=, values{std::move(values)}] { glClearBufferfv(buffer, drawbuffer, values.data()); });
15466297d8c7SWojciech Kozyra   return nullptr;
15476297d8c7SWojciech Kozyra }
15486297d8c7SWojciech Kozyra 
NATIVE_METHOD(clearBufferiv)15496297d8c7SWojciech Kozyra NATIVE_METHOD(clearBufferiv) {
15506297d8c7SWojciech Kozyra   CTX();
15516297d8c7SWojciech Kozyra   auto buffer = ARG(0, GLenum);
15526297d8c7SWojciech Kozyra   auto drawbuffer = ARG(1, GLint);
15536297d8c7SWojciech Kozyra   auto values = ARG(2, TypedArrayKind::Int32Array).toVector(runtime);
15546297d8c7SWojciech Kozyra   ctx->addToNextBatch(
15556297d8c7SWojciech Kozyra       [=, values{std::move(values)}] { glClearBufferiv(buffer, drawbuffer, values.data()); });
15566297d8c7SWojciech Kozyra   return nullptr;
15576297d8c7SWojciech Kozyra }
15586297d8c7SWojciech Kozyra 
NATIVE_METHOD(clearBufferuiv)15596297d8c7SWojciech Kozyra NATIVE_METHOD(clearBufferuiv) {
15606297d8c7SWojciech Kozyra   CTX();
15616297d8c7SWojciech Kozyra   auto buffer = ARG(0, GLenum);
15626297d8c7SWojciech Kozyra   auto drawbuffer = ARG(1, GLint);
15636297d8c7SWojciech Kozyra   auto values = ARG(2, TypedArrayKind::Uint32Array).toVector(runtime);
15646297d8c7SWojciech Kozyra   ctx->addToNextBatch(
15656297d8c7SWojciech Kozyra       [=, values{std::move(values)}] { glClearBufferuiv(buffer, drawbuffer, values.data()); });
15666297d8c7SWojciech Kozyra   return nullptr;
15676297d8c7SWojciech Kozyra }
15686297d8c7SWojciech Kozyra 
15696297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(clearBufferfi, glClearBufferfi); // buffer, drawbuffer, depth, stencil
15706297d8c7SWojciech Kozyra 
15716297d8c7SWojciech Kozyra // Query objects (WebGL2)
15726297d8c7SWojciech Kozyra // ----------------------
15736297d8c7SWojciech Kozyra 
NATIVE_METHOD(createQuery)15746297d8c7SWojciech Kozyra NATIVE_METHOD(createQuery) {
15756297d8c7SWojciech Kozyra   CTX();
15766297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenQueries, EXWebGLClass::WebGLQuery);
15776297d8c7SWojciech Kozyra }
15786297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteQuery)15796297d8c7SWojciech Kozyra NATIVE_METHOD(deleteQuery) {
15806297d8c7SWojciech Kozyra   CTX();
15816297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteQueries);
15826297d8c7SWojciech Kozyra }
15836297d8c7SWojciech Kozyra 
NATIVE_METHOD(isQuery)15846297d8c7SWojciech Kozyra NATIVE_METHOD(isQuery) {
15856297d8c7SWojciech Kozyra   CTX();
15866297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsQuery);
15876297d8c7SWojciech Kozyra }
15886297d8c7SWojciech Kozyra 
NATIVE_METHOD(beginQuery)15896297d8c7SWojciech Kozyra NATIVE_METHOD(beginQuery) {
15906297d8c7SWojciech Kozyra   CTX();
15916297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
15926297d8c7SWojciech Kozyra   auto query = ARG(1, EXWebGLClass);
15936297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBeginQuery(target, ctx->lookupObject(query)); });
15946297d8c7SWojciech Kozyra   return nullptr;
15956297d8c7SWojciech Kozyra }
15966297d8c7SWojciech Kozyra 
15976297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(endQuery, glEndQuery); // target
15986297d8c7SWojciech Kozyra 
NATIVE_METHOD(getQuery)15996297d8c7SWojciech Kozyra NATIVE_METHOD(getQuery) {
16006297d8c7SWojciech Kozyra   CTX();
16016297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
16026297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
16036297d8c7SWojciech Kozyra   GLint params;
16046297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] { glGetQueryiv(target, pname, &params); });
16056297d8c7SWojciech Kozyra   return params == 0
16066297d8c7SWojciech Kozyra       ? jsi::Value::null()
16076297d8c7SWojciech Kozyra       : createWebGLObject(runtime, EXWebGLClass::WebGLQuery, {static_cast<double>(params)});
16086297d8c7SWojciech Kozyra }
16096297d8c7SWojciech Kozyra 
NATIVE_METHOD(getQueryParameter)16106297d8c7SWojciech Kozyra NATIVE_METHOD(getQueryParameter) {
16116297d8c7SWojciech Kozyra   CTX();
16126297d8c7SWojciech Kozyra   auto query = ARG(0, EXWebGLClass);
16136297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
16146297d8c7SWojciech Kozyra   GLuint params;
16156297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch(
16166297d8c7SWojciech Kozyra       [&] { glGetQueryObjectuiv(ctx->lookupObject(query), pname, &params); });
16176297d8c7SWojciech Kozyra   return params == 0 ? jsi::Value::null() : static_cast<double>(params);
16186297d8c7SWojciech Kozyra }
16196297d8c7SWojciech Kozyra 
16206297d8c7SWojciech Kozyra // Samplers (WebGL2)
16216297d8c7SWojciech Kozyra // -----------------
16226297d8c7SWojciech Kozyra 
NATIVE_METHOD(createSampler)16236297d8c7SWojciech Kozyra NATIVE_METHOD(createSampler) {
16246297d8c7SWojciech Kozyra   CTX();
16256297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenSamplers, EXWebGLClass::WebGLSampler);
16266297d8c7SWojciech Kozyra }
16276297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteSampler)16286297d8c7SWojciech Kozyra NATIVE_METHOD(deleteSampler) {
16296297d8c7SWojciech Kozyra   CTX();
16306297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteSamplers);
16316297d8c7SWojciech Kozyra }
16326297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindSampler)16336297d8c7SWojciech Kozyra NATIVE_METHOD(bindSampler) {
16346297d8c7SWojciech Kozyra   CTX();
16356297d8c7SWojciech Kozyra   auto unit = ARG(0, GLuint);
16366297d8c7SWojciech Kozyra   auto sampler = ARG(1, EXWebGLClass);
16376297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBindSampler(unit, ctx->lookupObject(sampler)); });
16386297d8c7SWojciech Kozyra   return nullptr;
16396297d8c7SWojciech Kozyra }
16406297d8c7SWojciech Kozyra 
NATIVE_METHOD(isSampler)16416297d8c7SWojciech Kozyra NATIVE_METHOD(isSampler) {
16426297d8c7SWojciech Kozyra   CTX();
16436297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsSampler);
16446297d8c7SWojciech Kozyra }
16456297d8c7SWojciech Kozyra 
NATIVE_METHOD(samplerParameteri)16466297d8c7SWojciech Kozyra NATIVE_METHOD(samplerParameteri) {
16476297d8c7SWojciech Kozyra   CTX();
16486297d8c7SWojciech Kozyra   auto sampler = ARG(0, EXWebGLClass);
16496297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
16506297d8c7SWojciech Kozyra   auto param = ARG(2, GLfloat);
16516297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glSamplerParameteri(ctx->lookupObject(sampler), pname, param); });
16526297d8c7SWojciech Kozyra   return nullptr;
16536297d8c7SWojciech Kozyra }
16546297d8c7SWojciech Kozyra 
NATIVE_METHOD(samplerParameterf)16556297d8c7SWojciech Kozyra NATIVE_METHOD(samplerParameterf) {
16566297d8c7SWojciech Kozyra   CTX();
16576297d8c7SWojciech Kozyra   auto sampler = ARG(0, EXWebGLClass);
16586297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
16596297d8c7SWojciech Kozyra   auto param = ARG(2, GLfloat);
16606297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glSamplerParameterf(ctx->lookupObject(sampler), pname, param); });
16616297d8c7SWojciech Kozyra   return nullptr;
16626297d8c7SWojciech Kozyra }
16636297d8c7SWojciech Kozyra 
NATIVE_METHOD(getSamplerParameter)16646297d8c7SWojciech Kozyra NATIVE_METHOD(getSamplerParameter) {
16656297d8c7SWojciech Kozyra   CTX();
16666297d8c7SWojciech Kozyra   auto sampler = ARG(0, EXWebGLClass);
16676297d8c7SWojciech Kozyra   auto pname = ARG(1, GLenum);
16686297d8c7SWojciech Kozyra   bool isFloatParam = pname == GL_TEXTURE_MAX_LOD || pname == GL_TEXTURE_MIN_LOD;
16696297d8c7SWojciech Kozyra   union {
16706297d8c7SWojciech Kozyra     GLfloat f;
16716297d8c7SWojciech Kozyra     GLint i;
16726297d8c7SWojciech Kozyra   } param;
16736297d8c7SWojciech Kozyra 
16746297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
16756297d8c7SWojciech Kozyra     if (isFloatParam) {
16766297d8c7SWojciech Kozyra       glGetSamplerParameterfv(ctx->lookupObject(sampler), pname, &param.f);
16776297d8c7SWojciech Kozyra     } else {
16786297d8c7SWojciech Kozyra       glGetSamplerParameteriv(ctx->lookupObject(sampler), pname, &param.i);
16796297d8c7SWojciech Kozyra     }
16806297d8c7SWojciech Kozyra   });
16816297d8c7SWojciech Kozyra   return isFloatParam ? static_cast<double>(param.f) : static_cast<double>(param.i);
16826297d8c7SWojciech Kozyra }
16836297d8c7SWojciech Kozyra 
16846297d8c7SWojciech Kozyra // Sync objects (WebGL2)
16856297d8c7SWojciech Kozyra // ---------------------
16866297d8c7SWojciech Kozyra 
16876297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(fenceSync)
16886297d8c7SWojciech Kozyra 
UNIMPL_NATIVE_METHOD(isSync)16896297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(isSync)
16906297d8c7SWojciech Kozyra 
16916297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(deleteSync)
16926297d8c7SWojciech Kozyra 
16936297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(clientWaitSync)
16946297d8c7SWojciech Kozyra 
16956297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(waitSync)
16966297d8c7SWojciech Kozyra 
16976297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getSyncParameter)
16986297d8c7SWojciech Kozyra 
16996297d8c7SWojciech Kozyra // Transform feedback (WebGL2)
17006297d8c7SWojciech Kozyra // ---------------------------
17016297d8c7SWojciech Kozyra 
17026297d8c7SWojciech Kozyra NATIVE_METHOD(createTransformFeedback) {
17036297d8c7SWojciech Kozyra   CTX();
17046297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenTransformFeedbacks, EXWebGLClass::WebGLTransformFeedback);
17056297d8c7SWojciech Kozyra }
17066297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteTransformFeedback)17076297d8c7SWojciech Kozyra NATIVE_METHOD(deleteTransformFeedback) {
17086297d8c7SWojciech Kozyra   CTX();
17096297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteTransformFeedbacks);
17106297d8c7SWojciech Kozyra }
17116297d8c7SWojciech Kozyra 
NATIVE_METHOD(isTransformFeedback)17126297d8c7SWojciech Kozyra NATIVE_METHOD(isTransformFeedback) {
17136297d8c7SWojciech Kozyra   CTX();
17146297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsTransformFeedback);
17156297d8c7SWojciech Kozyra }
17166297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindTransformFeedback)17176297d8c7SWojciech Kozyra NATIVE_METHOD(bindTransformFeedback) {
17186297d8c7SWojciech Kozyra   CTX();
17196297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
17206297d8c7SWojciech Kozyra   auto transformFeedback = ARG(1, EXWebGLClass);
17216297d8c7SWojciech Kozyra   ctx->addToNextBatch(
17226297d8c7SWojciech Kozyra       [=] { glBindTransformFeedback(target, ctx->lookupObject(transformFeedback)); });
17236297d8c7SWojciech Kozyra   return nullptr;
17246297d8c7SWojciech Kozyra }
17256297d8c7SWojciech Kozyra 
17266297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(beginTransformFeedback, glBeginTransformFeedback); // primitiveMode
17276297d8c7SWojciech Kozyra 
17286297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(endTransformFeedback, glEndTransformFeedback);
17296297d8c7SWojciech Kozyra 
NATIVE_METHOD(transformFeedbackVaryings)17306297d8c7SWojciech Kozyra NATIVE_METHOD(transformFeedbackVaryings) {
17316297d8c7SWojciech Kozyra   CTX();
17326297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
17336297d8c7SWojciech Kozyra   std::vector<std::string> varyings = jsArrayToVector<std::string>(runtime, ARG(1, jsi::Array));
17346297d8c7SWojciech Kozyra   auto bufferMode = ARG(2, GLenum);
17356297d8c7SWojciech Kozyra 
17366297d8c7SWojciech Kozyra   ctx->addToNextBatch([=, varyings{std::move(varyings)}] {
17376297d8c7SWojciech Kozyra     std::vector<const char *> varyingsRaw(varyings.size());
17386297d8c7SWojciech Kozyra     std::transform(
17396297d8c7SWojciech Kozyra         varyings.begin(), varyings.end(), varyingsRaw.begin(), [](const std::string &str) {
17406297d8c7SWojciech Kozyra           return str.c_str();
17416297d8c7SWojciech Kozyra         });
17426297d8c7SWojciech Kozyra 
17436297d8c7SWojciech Kozyra     glTransformFeedbackVaryings(
17446297d8c7SWojciech Kozyra         ctx->lookupObject(program),
17456297d8c7SWojciech Kozyra         static_cast<GLsizei>(varyingsRaw.size()),
17466297d8c7SWojciech Kozyra         varyingsRaw.data(),
17476297d8c7SWojciech Kozyra         bufferMode);
17486297d8c7SWojciech Kozyra   });
17496297d8c7SWojciech Kozyra   return nullptr;
17506297d8c7SWojciech Kozyra }
17516297d8c7SWojciech Kozyra 
NATIVE_METHOD(getTransformFeedbackVarying)17526297d8c7SWojciech Kozyra NATIVE_METHOD(getTransformFeedbackVarying) {
17536297d8c7SWojciech Kozyra   CTX();
17546297d8c7SWojciech Kozyra   return exglGetActiveInfo(
17556297d8c7SWojciech Kozyra       ctx,
17566297d8c7SWojciech Kozyra       runtime,
17576297d8c7SWojciech Kozyra       ARG(0, EXWebGLClass),
17586297d8c7SWojciech Kozyra       ARG(1, GLuint),
17596297d8c7SWojciech Kozyra       GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
17606297d8c7SWojciech Kozyra       glGetTransformFeedbackVarying);
17616297d8c7SWojciech Kozyra }
17626297d8c7SWojciech Kozyra 
17636297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(pauseTransformFeedback, glPauseTransformFeedback);
17646297d8c7SWojciech Kozyra 
17656297d8c7SWojciech Kozyra SIMPLE_NATIVE_METHOD(resumeTransformFeedback, glResumeTransformFeedback);
17666297d8c7SWojciech Kozyra 
17676297d8c7SWojciech Kozyra // Uniform buffer objects (WebGL2)
17686297d8c7SWojciech Kozyra // -------------------------------
17696297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindBufferBase)17706297d8c7SWojciech Kozyra NATIVE_METHOD(bindBufferBase) {
17716297d8c7SWojciech Kozyra   CTX();
17726297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
17736297d8c7SWojciech Kozyra   auto index = ARG(1, GLuint);
17746297d8c7SWojciech Kozyra   auto buffer = ARG(2, EXWebGLClass);
17756297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBindBufferBase(target, index, ctx->lookupObject(buffer)); });
17766297d8c7SWojciech Kozyra   return nullptr;
17776297d8c7SWojciech Kozyra }
17786297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindBufferRange)17796297d8c7SWojciech Kozyra NATIVE_METHOD(bindBufferRange) {
17806297d8c7SWojciech Kozyra   CTX();
17816297d8c7SWojciech Kozyra   auto target = ARG(0, GLenum);
17826297d8c7SWojciech Kozyra   auto index = ARG(1, GLuint);
17836297d8c7SWojciech Kozyra   auto buffer = ARG(2, EXWebGLClass);
17846297d8c7SWojciech Kozyra   auto offset = ARG(3, GLint);
17856297d8c7SWojciech Kozyra   auto size = ARG(4, GLsizei);
17866297d8c7SWojciech Kozyra   ctx->addToNextBatch(
17876297d8c7SWojciech Kozyra       [=] { glBindBufferRange(target, index, ctx->lookupObject(buffer), offset, size); });
17886297d8c7SWojciech Kozyra   return nullptr;
17896297d8c7SWojciech Kozyra }
17906297d8c7SWojciech Kozyra 
NATIVE_METHOD(getUniformIndices)17916297d8c7SWojciech Kozyra NATIVE_METHOD(getUniformIndices) {
17926297d8c7SWojciech Kozyra   CTX();
17936297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
17946297d8c7SWojciech Kozyra   std::vector<std::string> uniformNames = jsArrayToVector<std::string>(runtime, ARG(1, jsi::Array));
17956297d8c7SWojciech Kozyra 
17966297d8c7SWojciech Kozyra   std::vector<const char *> uniformNamesRaw(uniformNames.size());
17976297d8c7SWojciech Kozyra   std::transform(
17986297d8c7SWojciech Kozyra       uniformNames.begin(),
17996297d8c7SWojciech Kozyra       uniformNames.end(),
18006297d8c7SWojciech Kozyra       uniformNamesRaw.begin(),
18016297d8c7SWojciech Kozyra       [](const std::string &str) { return str.c_str(); });
18026297d8c7SWojciech Kozyra 
18036297d8c7SWojciech Kozyra   std::vector<GLuint> indices(uniformNames.size());
18046297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
18056297d8c7SWojciech Kozyra     glGetUniformIndices(
18066297d8c7SWojciech Kozyra         ctx->lookupObject(program),
18076297d8c7SWojciech Kozyra         static_cast<GLsizei>(uniformNames.size()),
18086297d8c7SWojciech Kozyra         uniformNamesRaw.data(),
18096297d8c7SWojciech Kozyra         &indices[0]);
18106297d8c7SWojciech Kozyra   });
18116297d8c7SWojciech Kozyra   jsi::Array jsResult(runtime, indices.size());
18126297d8c7SWojciech Kozyra   for (unsigned int i = 0; i < indices.size(); i++) {
18136297d8c7SWojciech Kozyra     jsResult.setValueAtIndex(runtime, i, static_cast<double>(indices[i]));
18146297d8c7SWojciech Kozyra   }
18156297d8c7SWojciech Kozyra   return jsResult;
18166297d8c7SWojciech Kozyra }
18176297d8c7SWojciech Kozyra 
NATIVE_METHOD(getActiveUniforms)18186297d8c7SWojciech Kozyra NATIVE_METHOD(getActiveUniforms) {
18196297d8c7SWojciech Kozyra   CTX();
18206297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
18216297d8c7SWojciech Kozyra   auto uniformIndices = jsArrayToVector<GLuint>(runtime, ARG(1, jsi::Array));
18226297d8c7SWojciech Kozyra   auto pname = ARG(2, GLenum);
18236297d8c7SWojciech Kozyra   std::vector<GLint> params(uniformIndices.size());
18246297d8c7SWojciech Kozyra 
18256297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
18266297d8c7SWojciech Kozyra     glGetActiveUniformsiv(
18276297d8c7SWojciech Kozyra         ctx->lookupObject(program),
18286297d8c7SWojciech Kozyra         static_cast<GLsizei>(uniformIndices.size()),
18296297d8c7SWojciech Kozyra         uniformIndices.data(),
18306297d8c7SWojciech Kozyra         pname,
18316297d8c7SWojciech Kozyra         &params[0]);
18326297d8c7SWojciech Kozyra   });
18336297d8c7SWojciech Kozyra   jsi::Array jsResult(runtime, params.size());
18346297d8c7SWojciech Kozyra   for (unsigned int i = 0; i < params.size(); i++) {
18356297d8c7SWojciech Kozyra     jsResult.setValueAtIndex(
18366297d8c7SWojciech Kozyra         runtime,
18376297d8c7SWojciech Kozyra         i,
18386297d8c7SWojciech Kozyra         pname == GL_UNIFORM_IS_ROW_MAJOR ? params[i] != 0 : static_cast<double>(params[i]));
18396297d8c7SWojciech Kozyra   }
18406297d8c7SWojciech Kozyra   return jsResult;
18416297d8c7SWojciech Kozyra }
18426297d8c7SWojciech Kozyra 
NATIVE_METHOD(getUniformBlockIndex)18436297d8c7SWojciech Kozyra NATIVE_METHOD(getUniformBlockIndex) {
18446297d8c7SWojciech Kozyra   CTX();
18456297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
18466297d8c7SWojciech Kozyra   auto uniformBlockName = ARG(1, std::string);
18476297d8c7SWojciech Kozyra 
18486297d8c7SWojciech Kozyra   GLuint blockIndex;
18496297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
18506297d8c7SWojciech Kozyra     blockIndex = glGetUniformBlockIndex(ctx->lookupObject(program), uniformBlockName.c_str());
18516297d8c7SWojciech Kozyra   });
18526297d8c7SWojciech Kozyra   return static_cast<double>(blockIndex);
18536297d8c7SWojciech Kozyra }
18546297d8c7SWojciech Kozyra 
18556297d8c7SWojciech Kozyra UNIMPL_NATIVE_METHOD(getActiveUniformBlockParameter)
18566297d8c7SWojciech Kozyra 
NATIVE_METHOD(getActiveUniformBlockName)18576297d8c7SWojciech Kozyra NATIVE_METHOD(getActiveUniformBlockName) {
18586297d8c7SWojciech Kozyra   CTX();
18596297d8c7SWojciech Kozyra   auto fProgram = ARG(0, EXWebGLClass);
18606297d8c7SWojciech Kozyra   auto uniformBlockIndex = ARG(1, GLuint);
18616297d8c7SWojciech Kozyra 
18626297d8c7SWojciech Kozyra   std::string blockName;
18636297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {
18646297d8c7SWojciech Kozyra     GLuint program = ctx->lookupObject(fProgram);
18656297d8c7SWojciech Kozyra     GLint bufSize;
18666297d8c7SWojciech Kozyra     glGetActiveUniformBlockiv(program, uniformBlockIndex, GL_UNIFORM_BLOCK_NAME_LENGTH, &bufSize);
18676297d8c7SWojciech Kozyra     blockName.resize(bufSize > 0 ? bufSize - 1 : 0);
18686297d8c7SWojciech Kozyra     glGetActiveUniformBlockName(program, uniformBlockIndex, bufSize, NULL, &blockName[0]);
18696297d8c7SWojciech Kozyra   });
18706297d8c7SWojciech Kozyra   return jsi::String::createFromUtf8(runtime, blockName);
18716297d8c7SWojciech Kozyra }
18726297d8c7SWojciech Kozyra 
NATIVE_METHOD(uniformBlockBinding)18736297d8c7SWojciech Kozyra NATIVE_METHOD(uniformBlockBinding) {
18746297d8c7SWojciech Kozyra   CTX();
18756297d8c7SWojciech Kozyra   auto program = ARG(0, EXWebGLClass);
18766297d8c7SWojciech Kozyra   auto uniformBlockIndex = ARG(1, GLuint);
18776297d8c7SWojciech Kozyra   auto uniformBlockBinding = ARG(2, GLuint);
18786297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] {
18796297d8c7SWojciech Kozyra     glUniformBlockBinding(ctx->lookupObject(program), uniformBlockIndex, uniformBlockBinding);
18806297d8c7SWojciech Kozyra   });
18816297d8c7SWojciech Kozyra   return nullptr;
18826297d8c7SWojciech Kozyra }
18836297d8c7SWojciech Kozyra 
18846297d8c7SWojciech Kozyra // Vertex Array Object (WebGL2)
18856297d8c7SWojciech Kozyra // ----------------------------
18866297d8c7SWojciech Kozyra 
NATIVE_METHOD(createVertexArray)18876297d8c7SWojciech Kozyra NATIVE_METHOD(createVertexArray) {
18886297d8c7SWojciech Kozyra   CTX();
18896297d8c7SWojciech Kozyra   return exglGenObject(ctx, runtime, glGenVertexArrays, EXWebGLClass::WebGLVertexArrayObject);
18906297d8c7SWojciech Kozyra }
18916297d8c7SWojciech Kozyra 
NATIVE_METHOD(deleteVertexArray)18926297d8c7SWojciech Kozyra NATIVE_METHOD(deleteVertexArray) {
18936297d8c7SWojciech Kozyra   CTX();
18946297d8c7SWojciech Kozyra   return exglDeleteObject(ctx, ARG(0, EXWebGLClass), glDeleteVertexArrays);
18956297d8c7SWojciech Kozyra }
18966297d8c7SWojciech Kozyra 
NATIVE_METHOD(isVertexArray)18976297d8c7SWojciech Kozyra NATIVE_METHOD(isVertexArray) {
18986297d8c7SWojciech Kozyra   CTX();
18996297d8c7SWojciech Kozyra   return exglIsObject(ctx, ARG(0, EXWebGLClass), glIsVertexArray);
19006297d8c7SWojciech Kozyra }
19016297d8c7SWojciech Kozyra 
NATIVE_METHOD(bindVertexArray)19026297d8c7SWojciech Kozyra NATIVE_METHOD(bindVertexArray) {
19036297d8c7SWojciech Kozyra   CTX();
19046297d8c7SWojciech Kozyra   auto vertexArray = ARG(0, EXWebGLClass);
19056297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { glBindVertexArray(ctx->lookupObject(vertexArray)); });
19066297d8c7SWojciech Kozyra   return nullptr;
19076297d8c7SWojciech Kozyra }
19086297d8c7SWojciech Kozyra 
19096297d8c7SWojciech Kozyra // Extensions
19106297d8c7SWojciech Kozyra // ----------
19116297d8c7SWojciech Kozyra 
19126297d8c7SWojciech Kozyra // It may return some extensions that are not specified by WebGL specification nor drafts.
NATIVE_METHOD(getSupportedExtensions)19136297d8c7SWojciech Kozyra NATIVE_METHOD(getSupportedExtensions) {
19146297d8c7SWojciech Kozyra   CTX();
19156297d8c7SWojciech Kozyra   // Set with supported extensions is cached to make checks in `getExtension` faster.
19166297d8c7SWojciech Kozyra   ctx->maybeReadAndCacheSupportedExtensions();
19176297d8c7SWojciech Kozyra 
19186297d8c7SWojciech Kozyra   jsi::Array extensions(runtime, ctx->supportedExtensions.size());
19196297d8c7SWojciech Kozyra   int i = 0;
19206297d8c7SWojciech Kozyra   for (auto const &extensionName : ctx->supportedExtensions) {
19216297d8c7SWojciech Kozyra     extensions.setValueAtIndex(runtime, i++, jsi::String::createFromUtf8(runtime, extensionName));
19226297d8c7SWojciech Kozyra   }
19236297d8c7SWojciech Kozyra   return extensions;
19246297d8c7SWojciech Kozyra }
19256297d8c7SWojciech Kozyra 
19266297d8c7SWojciech Kozyra #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
19276297d8c7SWojciech Kozyra #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
19286297d8c7SWojciech Kozyra 
NATIVE_METHOD(getExtension)19296297d8c7SWojciech Kozyra NATIVE_METHOD(getExtension) {
19306297d8c7SWojciech Kozyra   CTX();
19316297d8c7SWojciech Kozyra   auto name = ARG(0, std::string);
19326297d8c7SWojciech Kozyra 
19336297d8c7SWojciech Kozyra   // There is no `getExtension` equivalent in OpenGL ES so return `null`
19346297d8c7SWojciech Kozyra   // if requested extension is not returned by `getSupportedExtensions`.
19356297d8c7SWojciech Kozyra   ctx->maybeReadAndCacheSupportedExtensions();
19366297d8c7SWojciech Kozyra   if (ctx->supportedExtensions.find(name) == ctx->supportedExtensions.end()) {
19376297d8c7SWojciech Kozyra     return nullptr;
19386297d8c7SWojciech Kozyra   }
19396297d8c7SWojciech Kozyra 
19406297d8c7SWojciech Kozyra   if (name == "EXT_texture_filter_anisotropic") {
19416297d8c7SWojciech Kozyra     jsi::Object result(runtime);
19426297d8c7SWojciech Kozyra     result.setProperty(
19436297d8c7SWojciech Kozyra         runtime, "TEXTURE_MAX_ANISOTROPY_EXT", jsi::Value(GL_TEXTURE_MAX_ANISOTROPY_EXT));
19446297d8c7SWojciech Kozyra     result.setProperty(
19456297d8c7SWojciech Kozyra         runtime, "MAX_TEXTURE_MAX_ANISOTROPY_EXT", jsi::Value(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
19466297d8c7SWojciech Kozyra     return result;
19476297d8c7SWojciech Kozyra   }
19486297d8c7SWojciech Kozyra   return jsi::Object(runtime);
19496297d8c7SWojciech Kozyra }
19506297d8c7SWojciech Kozyra 
19516297d8c7SWojciech Kozyra // Exponent extensions
19526297d8c7SWojciech Kozyra // -------------------
19536297d8c7SWojciech Kozyra 
NATIVE_METHOD(endFrameEXP)19546297d8c7SWojciech Kozyra NATIVE_METHOD(endFrameEXP) {
19556297d8c7SWojciech Kozyra   CTX();
19566297d8c7SWojciech Kozyra   ctx->addToNextBatch([=] { ctx->needsRedraw = true; });
19576297d8c7SWojciech Kozyra   ctx->endNextBatch();
19586297d8c7SWojciech Kozyra   ctx->flushOnGLThread();
19596297d8c7SWojciech Kozyra   return nullptr;
19606297d8c7SWojciech Kozyra }
19616297d8c7SWojciech Kozyra 
NATIVE_METHOD(flushEXP)19626297d8c7SWojciech Kozyra NATIVE_METHOD(flushEXP) {
19636297d8c7SWojciech Kozyra   CTX();
19646297d8c7SWojciech Kozyra   // nothing, it's just a helper so that we can measure how much time some operations take
19656297d8c7SWojciech Kozyra   ctx->addBlockingToNextBatch([&] {});
19666297d8c7SWojciech Kozyra   return nullptr;
19676297d8c7SWojciech Kozyra }
19686297d8c7SWojciech Kozyra 
19696297d8c7SWojciech Kozyra } // namespace method
19706297d8c7SWojciech Kozyra } // namespace gl_cpp
19716297d8c7SWojciech Kozyra } // namespace expo
1972