1 #pragma once
2 // it should be included only in EXWebGLMethods.cpp
3 
4 #include "EXGLNativeContext.h"
5 #include "EXWebGLRenderer.h"
6 
7 #ifdef __ANDROID__
8 #include <GLES3/gl3.h>
9 #include <GLES3/gl3ext.h>
10 #endif
11 #ifdef __APPLE__
12 #include <OpenGLES/EAGL.h>
13 #include <OpenGLES/ES3/gl.h>
14 #include <OpenGLES/ES3/glext.h>
15 #endif
16 
17 namespace expo {
18 namespace gl_cpp {
19 
20 template <typename Func>
exglGetActiveInfo(EXGLContext * ctx,jsi::Runtime & runtime,EXGLObjectId fProgram,GLuint index,GLenum lengthParam,Func glFunc)21 inline jsi::Value exglGetActiveInfo(
22     EXGLContext *ctx,
23     jsi::Runtime &runtime,
24     EXGLObjectId fProgram,
25     GLuint index,
26     GLenum lengthParam,
27     Func glFunc) {
28   if (fProgram == 0) {
29     return nullptr;
30   }
31 
32   GLsizei length;
33   GLint size;
34   GLenum type;
35   std::string name;
36   GLint maxNameLength;
37 
38   ctx->addBlockingToNextBatch([&] {
39     GLuint program = ctx->lookupObject(fProgram);
40     glGetProgramiv(program, lengthParam, &maxNameLength);
41     name.resize(maxNameLength);
42 
43     glFunc(program, index, maxNameLength, &length, &size, &type, &name[0]);
44     name.resize(length);
45   });
46 
47   if (name.size() == 0) { // name.length() may be larger
48     return nullptr;
49   }
50 
51   jsi::Object jsResult =
52       createWebGLObject(runtime, EXWebGLClass::WebGLActiveInfo, {}).asObject(runtime);
53   jsResult.setProperty(runtime, "name", jsi::String::createFromUtf8(runtime, name));
54   jsResult.setProperty(runtime, "size", size);
55   jsResult.setProperty(runtime, "type", static_cast<double>(type));
56   return jsResult;
57 }
58 
59 template <typename Func, typename... T>
exglCall(EXGLContext * ctx,Func func,T &&...args)60 inline jsi::Value exglCall(EXGLContext *ctx, Func func, T &&... args) {
61   ctx->addToNextBatch([=, args = std::make_tuple(std::forward<T>(args)...)] {
62     return std::apply(func, std::move(args));
63   });
64 }
65 
66 template <typename Func, typename T>
67 inline jsi::Value
exglUniformv(EXGLContext * ctx,Func func,GLuint uniform,size_t dim,std::vector<T> && data)68 exglUniformv(EXGLContext *ctx, Func func, GLuint uniform, size_t dim, std::vector<T> &&data) {
69   ctx->addToNextBatch([=, data{std::move(data)}] {
70     func(uniform, static_cast<int>(data.size() / dim), data.data());
71   });
72   return nullptr;
73 }
74 
75 template <typename Func, typename T>
exglUniformMatrixv(EXGLContext * ctx,Func func,GLuint uniform,GLboolean transpose,size_t dim,std::vector<T> && data)76 inline jsi::Value exglUniformMatrixv(
77     EXGLContext *ctx,
78     Func func,
79     GLuint uniform,
80     GLboolean transpose,
81     size_t dim,
82     std::vector<T> &&data) {
83   ctx->addToNextBatch([=, data{std::move(data)}] {
84     func(uniform, static_cast<int>(data.size() / dim), transpose, data.data());
85   });
86   return nullptr;
87 }
88 
89 template <typename Func, typename T>
90 inline jsi::Value
exglVertexAttribv(EXGLContext * ctx,Func func,GLuint index,std::vector<T> && data)91 exglVertexAttribv(EXGLContext *ctx, Func func, GLuint index, std::vector<T> &&data) {
92   ctx->addToNextBatch([=, data{std::move(data)}] { func(index, data.data()); });
93   return nullptr;
94 }
95 
96 inline jsi::Value
exglIsObject(EXGLContext * ctx,EXGLObjectId id,std::function<GLboolean (GLuint)> func)97 exglIsObject(EXGLContext *ctx, EXGLObjectId id, std::function<GLboolean(GLuint)> func) {
98   GLboolean glResult;
99   ctx->addBlockingToNextBatch([&] { glResult = func(ctx->lookupObject(id)); });
100   return glResult == GL_TRUE;
101 }
102 
exglGenObject(EXGLContext * ctx,jsi::Runtime & runtime,std::function<void (GLsizei,EXGLObjectId *)> func,EXWebGLClass webglClass)103 inline jsi::Value exglGenObject(
104     EXGLContext *ctx,
105     jsi::Runtime &runtime,
106     std::function<void(GLsizei, EXGLObjectId *)> func,
107     EXWebGLClass webglClass) {
108   auto id = ctx->addFutureToNextBatch(runtime, [=] {
109     GLuint buffer;
110     func(1, &buffer);
111     return buffer;
112   });
113   return createWebGLObject(runtime, webglClass, {std::move(id)});
114 }
115 
exglCreateObject(EXGLContext * ctx,jsi::Runtime & runtime,std::function<GLuint ()> func,EXWebGLClass webglClass)116 inline jsi::Value exglCreateObject(
117     EXGLContext *ctx,
118     jsi::Runtime &runtime,
119     std::function<GLuint()> func,
120     EXWebGLClass webglClass) {
121   auto id = ctx->addFutureToNextBatch(runtime, [=] { return func(); });
122   return createWebGLObject(runtime, webglClass, {std::move(id)});
123 }
124 
125 inline jsi::Value
exglDeleteObject(EXGLContext * ctx,EXGLObjectId id,std::function<void (EXGLObjectId)> func)126 exglDeleteObject(EXGLContext *ctx, EXGLObjectId id, std::function<void(EXGLObjectId)> func) {
127   ctx->addToNextBatch([=] { func(ctx->lookupObject(id)); });
128   return nullptr;
129 }
130 
exglDeleteObject(EXGLContext * ctx,EXGLObjectId id,std::function<void (GLsizei,const EXGLObjectId *)> func)131 inline jsi::Value exglDeleteObject(
132     EXGLContext *ctx,
133     EXGLObjectId id,
134     std::function<void(GLsizei, const EXGLObjectId *)> func) {
135   ctx->addToNextBatch([=] {
136     GLuint buffer = ctx->lookupObject(id);
137     func(1, &buffer);
138   });
139   return nullptr;
140 }
141 
exglUnimplemented(std::string name)142 inline jsi::Value exglUnimplemented(std::string name) {
143   throw std::runtime_error("EXGL: " + name + "() isn't implemented yet!");
144 }
145 
146 } // namespace gl_cpp
147 } // namespace expo
148