• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "context/webgl_rendering_context_base_impl.h"
16 
17 #include "context/webgl2_rendering_context_base.h"
18 #include "context/webgl_rendering_context_base.h"
19 #include "napi/n_class.h"
20 #include "util/log.h"
21 #include "util/util.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 namespace Impl {
26 using namespace std;
~WebGLRenderingContextBaseImpl()27 WebGLRenderingContextBaseImpl::~WebGLRenderingContextBaseImpl() {}
28 
Init()29 void WebGLRenderingContextBaseImpl::Init()
30 {
31     if (maxTextureImageUnits_ != 0) {
32         return;
33     }
34 
35     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits_);
36     boundTexture_[BoundTextureType::TEXTURE_3D].resize(maxTextureImageUnits_);
37     boundTexture_[BoundTextureType::TEXTURE_2D_ARRAY].resize(maxTextureImageUnits_);
38 
39     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize_);
40     boundTexture_[BoundTextureType::TEXTURE_2D].resize(maxTextureSize_);
41 
42     glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize_);
43     boundTexture_[BoundTextureType::TEXTURE_CUBE_MAP].resize(maxCubeMapTextureSize_);
44 
45     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderBufferSize_);
46 
47     unpackColorspaceConversion_ = WebGLRenderingContextBase::BROWSER_DEFAULT_WEBGL;
48 
49     GLint max = 0;
50     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max);
51     maxVertexAttribs_ = static_cast<GLuint>(max);
52     arrayVertexAttribs_.resize(maxVertexAttribs_);
53 
54     stencilMask_[0] = 0xffffffff; // 0xffffffff: stencilMask_ max value
55     stencilMask_[1] = 0xffffffff; // 0xffffffff: stencilMask_ max value
56     stencilFuncMask_[0] = 0xffffffff; // 0xffffffff: stencilFuncMask_ max value
57     stencilFuncMask_[1] = 0xffffffff; // 0xffffffff: stencilFuncMask_ max value
58     stencilFuncRef_[0] = 0;
59     stencilFuncRef_[1] = 0;
60 
61     clearColor_[0] = 0; // 0: r
62     clearColor_[1] = 0; // 1: g
63     clearColor_[2] = 0; // 2: b
64     clearColor_[3] = 0; // 3: a
65 
66     colorMask_[0] = false; // 0: r
67     colorMask_[1] = false; // 1: g
68     colorMask_[2] = false; // 2: b
69     colorMask_[3] = false; // 3: a
70 
71     LOGD("WebGL Init maxTextureImageUnits %{public}d, maxTextureSize %{public}d, maxCubeMapTextureSize %{public}d, "
72         "maxRenderBufferSize %{public}d, maxVertexAttribs %{public}d", maxTextureImageUnits_,
73         maxTextureSize_, maxCubeMapTextureSize_, maxRenderBufferSize_, maxVertexAttribs_);
74 }
75 
GetContextAttributes(napi_env env)76 napi_value WebGLRenderingContextBaseImpl::GetContextAttributes(napi_env env)
77 {
78     auto webGlContextAttributes = webGLRenderingContext_->CreateWebGlContextAttributes();
79     if (webGlContextAttributes == nullptr) {
80         return NVal::CreateNull(env).val_;
81     }
82     NVal res = NVal::CreateObject(env);
83     napi_value alpha = NVal::CreateBool(env, webGlContextAttributes->alpha_).val_;
84     napi_value antialias = NVal::CreateBool(env, webGlContextAttributes->antialias_).val_;
85     napi_value depth = NVal::CreateBool(env, webGlContextAttributes->depth_).val_;
86     napi_value failIfMajorPerformanceCaveat =
87         NVal::CreateBool(env, webGlContextAttributes->failIfMajorPerformanceCaveat_).val_;
88     napi_value desynchronized = NVal::CreateBool(env, webGlContextAttributes->desynchronized_).val_;
89     napi_value premultipliedAlpha = NVal::CreateBool(env, webGlContextAttributes->premultipliedAlpha_).val_;
90     napi_value preserveDrawingBuffer = NVal::CreateBool(env, webGlContextAttributes->preserveDrawingBuffer_).val_;
91     napi_value stencil = NVal::CreateBool(env, webGlContextAttributes->stencil_).val_;
92     napi_value powerPreference = NVal::CreateUTF8String(env, webGlContextAttributes->powerPreference_).val_;
93     res.AddProp("alpha", alpha);
94     res.AddProp("antialias", antialias);
95     res.AddProp("depth", depth);
96     res.AddProp("failIfMajorPerformanceCaveat", failIfMajorPerformanceCaveat);
97     res.AddProp("desynchronized", desynchronized);
98     res.AddProp("premultipliedAlpha", premultipliedAlpha);
99     res.AddProp("preserveDrawingBuffer", preserveDrawingBuffer);
100     res.AddProp("stencil", stencil);
101     res.AddProp("powerPreference", powerPreference);
102     return res.val_;
103 }
104 
CreateTextureObject(napi_env env)105 napi_value WebGLRenderingContextBaseImpl::CreateTextureObject(napi_env env)
106 {
107     WebGLTexture* webGlTexture = nullptr;
108     napi_value objTexture = WebGLTexture::CreateObjectInstance(env, &webGlTexture).val_;
109     if (!webGlTexture) {
110         return NVal::CreateNull(env).val_;
111     }
112     GLuint textureId = 0;
113     glGenTextures(1, &textureId);
114     webGlTexture->SetTexture(textureId);
115     LOGD("WebGL createTexture textureId %{public}u", textureId);
116     AddObject<WebGLTexture>(env, textureId, objTexture);
117     return objTexture;
118 }
119 
ActiveTexture(napi_env env,GLenum texture)120 napi_value WebGLRenderingContextBaseImpl::ActiveTexture(napi_env env, GLenum texture)
121 {
122     if (texture < GL_TEXTURE0 || static_cast<GLint>(texture - GL_TEXTURE0) >= maxTextureImageUnits_) {
123         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
124             "WebGL activeTexture texture unit out of range %{public}u", texture);
125         return NVal::CreateNull(env).val_;
126     }
127     activeTextureIndex_ = texture - GL_TEXTURE0;
128     glActiveTexture(texture);
129     return NVal::CreateNull(env).val_;
130 }
131 
BindTexture(napi_env env,GLenum target,napi_value textureRef)132 napi_value WebGLRenderingContextBaseImpl::BindTexture(napi_env env, GLenum target, napi_value textureRef)
133 {
134     uint32_t texture = WebGLTexture::DEFAULT_TEXTURE;
135     WebGLTexture* webGlTexture = WebGLTexture::GetObjectInstance(env, textureRef);
136     if (webGlTexture != nullptr) {
137         texture = webGlTexture->GetTexture();
138         if (webGlTexture->GetTarget() && webGlTexture->GetTarget() != target) {
139             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
140                 "WebGL bindTexture textureId %{public}u has been bound", texture);
141             return NVal::CreateNull(env).val_;
142         }
143     }
144 
145     uint32_t index = 0;
146     if (!WebGLRenderingContextBaseImpl::CheckTextureTarget(env, target, index)) {
147         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
148         return NVal::CreateNull(env).val_;
149     }
150     if (activeTextureIndex_ >= boundTexture_[index].size()) {
151         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
152         return NVal::CreateNull(env).val_;
153     }
154     if (boundTexture_[index][activeTextureIndex_] && boundTexture_[index][activeTextureIndex_] !=
155         static_cast<uint32_t>(texture)) {
156         LOGD("WebGL bindTexture has been bound to textureId %{public}u", boundTexture_[index][activeTextureIndex_]);
157     }
158     boundTexture_[index][activeTextureIndex_] = texture;
159 
160     glBindTexture(target, texture);
161     if (webGlTexture) {
162         webGlTexture->SetTarget(target);
163     }
164     LOGD("WebGL bindTexture target %{public}u textureId %{public}u activeTextureIndex %{public}u result %{public}u ",
165         target, texture, activeTextureIndex_, GetError_());
166     return NVal::CreateNull(env).val_;
167 }
168 
IsBuffer(napi_env env,napi_value object)169 napi_value WebGLRenderingContextBaseImpl::IsBuffer(napi_env env, napi_value object)
170 {
171     WebGLBuffer* webGlBuffer = GetValidBuffer(env, object);
172     if (webGlBuffer == nullptr) {
173         return NVal::CreateBool(env, false).val_;
174     }
175     uint32_t buffer = webGlBuffer->GetBufferId();
176     bool result = static_cast<bool>(glIsBuffer(static_cast<GLuint>(buffer)));
177     LOGD("WebGL isBuffer %{public}u res %{public}d", buffer, result);
178     return NVal::CreateBool(env, result).val_;
179 }
180 
BindBuffer(napi_env env,GLenum target,napi_value object)181 napi_value WebGLRenderingContextBaseImpl::BindBuffer(napi_env env, GLenum target, napi_value object)
182 {
183     // support default value
184     uint32_t bufferId = WebGLBuffer::DEFAULT_BUFFER;
185     WebGLBuffer* webGlBuffer = GetValidBuffer(env, object);
186     if (webGlBuffer != nullptr) {
187         bufferId = webGlBuffer->GetBufferId();
188     }
189     LOGD("WebGL bindBuffer target %{public}u bufferId %{public}u", target, bufferId);
190     uint32_t index = BoundBufferType::ARRAY_BUFFER;
191     if (!CheckBufferTarget(env, target, index)) {
192         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
193         return NVal::CreateNull(env).val_;
194     }
195     if (webGlBuffer && webGlBuffer->GetTarget() && webGlBuffer->GetTarget() != target) {
196         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
197         return NVal::CreateNull(env).val_;
198     }
199     if (boundBufferIds_[index] && boundBufferIds_[index] != bufferId) {
200         LOGD("WebGL bindBuffer has been bound bufferId %{public}u", boundBufferIds_[index]);
201     }
202     boundBufferIds_[index] = bufferId;
203 
204     glBindBuffer(target, static_cast<GLuint>(bufferId));
205     if (webGlBuffer) {
206         webGlBuffer->SetTarget(target);
207     }
208     LOGD("WebGL bindBuffer bufferId %{public}u result %{public}u", bufferId, GetError_());
209     return NVal::CreateNull(env).val_;
210 }
211 
IsFrameBuffer(napi_env env,napi_value object)212 napi_value WebGLRenderingContextBaseImpl::IsFrameBuffer(napi_env env, napi_value object)
213 {
214     GLuint frameBufferId = WebGLFramebuffer::DEFAULT_FRAME_BUFFER;
215     WebGLFramebuffer* webGlFramebuffer = GetValidFrameBuffer(env, object);
216     if (webGlFramebuffer == nullptr) {
217         return NVal::CreateBool(env, false).val_;
218     }
219     frameBufferId = webGlFramebuffer->GetFramebuffer();
220     bool res = static_cast<bool>(glIsFramebuffer(frameBufferId));
221     LOGD("WebGL isFramebuffer framebuffer %{public}u result %{public}d", frameBufferId, res);
222     return NVal::CreateBool(env, res).val_;
223 }
224 
BindFrameBuffer(napi_env env,GLenum target,napi_value object)225 napi_value WebGLRenderingContextBaseImpl::BindFrameBuffer(napi_env env, GLenum target, napi_value object)
226 {
227     uint32_t index = 0;
228     if (!CheckFrameBufferTarget(env, target, index)) {
229         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "BindFrameBuffer Invalid target");
230         return NVal::CreateNull(env).val_;
231     }
232 
233     GLuint frameBufferId = WebGLFramebuffer::DEFAULT_FRAME_BUFFER;
234     WebGLFramebuffer* webGlFramebuffer = GetValidFrameBuffer(env, object);
235     if (webGlFramebuffer == nullptr) {
236         glBindFramebuffer(target, 0);
237         return NVal::CreateNull(env).val_;
238     }
239 
240     frameBufferId = webGlFramebuffer->GetFramebuffer();
241     if (boundFrameBufferIds_[index] && boundFrameBufferIds_[index] != frameBufferId) {
242         LOGD("WebGL bindFramebuffer has been bound %{public}u", boundFrameBufferIds_[index]);
243     }
244     glBindFramebuffer(target, frameBufferId);
245     boundFrameBufferIds_[index] = frameBufferId;
246     if (IsHighWebGL()) {
247         if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER) {
248             boundFrameBufferIds_[BoundFrameBufferType::READ_FRAMEBUFFER] = frameBufferId;
249         }
250     }
251     if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) {
252         boundFrameBufferIds_[BoundFrameBufferType::FRAMEBUFFER] = frameBufferId;
253     }
254 
255     if (webGlFramebuffer) {
256         webGlFramebuffer->SetTarget(target);
257     }
258     LOGD("WebGL bindFramebuffer target %{public}u frameBufferId %{public}u result %{public}u",
259         target, frameBufferId, GetError_());
260     return NVal::CreateNull(env).val_;
261 }
262 
BindRenderBuffer(napi_env env,GLenum target,napi_value object)263 napi_value WebGLRenderingContextBaseImpl::BindRenderBuffer(napi_env env, GLenum target, napi_value object)
264 {
265     uint32_t index = 0;
266     if (!CheckRenderBufferTarget(env, target, index)) {
267         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "BindRenderBuffer Invalid target");
268         return NVal::CreateNull(env).val_;
269     }
270 
271     GLuint renderBufferId = WebGLRenderbuffer::DEFAULT_RENDER_BUFFER;
272     WebGLRenderbuffer* renderBuffer = GetValidRenderBuffer(env, object);
273     if (renderBuffer != nullptr) {
274         renderBufferId = renderBuffer->GetRenderbuffer();
275     }
276 
277     glBindRenderbuffer(target, renderBufferId);
278 
279     // record render buffer
280     if (boundRenderBufferIds_[index] && boundRenderBufferIds_[index] != renderBufferId) {
281         LOGD("WebGL bindRenderbuffer has been bound %{public}u", boundRenderBufferIds_[index]);
282     }
283     boundRenderBufferIds_[index] = renderBufferId;
284 
285     if (renderBuffer) {
286         renderBuffer->SetTarget(target);
287     }
288     LOGD("WebGL bindRenderbuffer target %{public}u %{public}u", target, GetError_());
289     return NVal::CreateNull(env).val_;
290 }
291 
CreateBuffer(napi_env env)292 napi_value WebGLRenderingContextBaseImpl::CreateBuffer(napi_env env)
293 {
294     WebGLBuffer* webGlBuffer = nullptr;
295     napi_value objBuffer = WebGLBuffer::CreateObjectInstance(env, &webGlBuffer).val_;
296     if (webGlBuffer == nullptr) {
297         return NVal::CreateNull(env).val_;
298     }
299     uint32_t bufferId = 0;
300     glGenBuffers(1, &bufferId);
301     webGlBuffer->SetBufferId(bufferId);
302     bool ret = AddObject<WebGLBuffer>(env, bufferId, objBuffer);
303     LOGD("WebGL createBuffer bufferId %{public}u %{public}d", bufferId, ret);
304     return objBuffer;
305 }
306 
CreateFrameBuffer(napi_env env)307 napi_value WebGLRenderingContextBaseImpl::CreateFrameBuffer(napi_env env)
308 {
309     WebGLFramebuffer* webGlFramebuffer = nullptr;
310     napi_value objFramebuffer = WebGLFramebuffer::CreateObjectInstance(env, &webGlFramebuffer).val_;
311     if (!webGlFramebuffer) {
312         return NVal::CreateNull(env).val_;
313     }
314     uint32_t framebufferId = 0;
315     glGenFramebuffers(1, &framebufferId);
316     webGlFramebuffer->SetFramebuffer(framebufferId);
317     (void)AddObject<WebGLFramebuffer>(env, framebufferId, objFramebuffer);
318     LOGD("WebGL createFramebuffer framebufferId %{public}u", framebufferId);
319     return objFramebuffer;
320 }
321 
CreateProgram(napi_env env)322 napi_value WebGLRenderingContextBaseImpl::CreateProgram(napi_env env)
323 {
324     WebGLProgram* webGlProgram = nullptr;
325     napi_value objProgram = WebGLProgram::CreateObjectInstance(env, &webGlProgram).val_;
326     if (webGlProgram == nullptr) {
327         return NVal::CreateNull(env).val_;
328     }
329     GLuint programId = glCreateProgram();
330     if (programId == 0) {
331         LOGE("WebGL createProgram fail programId %{public}u", programId);
332         return NVal::CreateNull(env).val_;
333     }
334     webGlProgram->SetProgramId(programId);
335 
336     (void)AddObject<WebGLProgram>(env, programId, objProgram);
337     LOGD("WebGL createProgram programId %{public}u result %{public}u", programId, GetError_());
338     return objProgram;
339 }
340 
CreateRenderBuffer(napi_env env)341 napi_value WebGLRenderingContextBaseImpl::CreateRenderBuffer(napi_env env)
342 {
343     WebGLRenderbuffer* webGlRenderbuffer = nullptr;
344     napi_value objRenderbuffer = WebGLRenderbuffer::CreateObjectInstance(env, &webGlRenderbuffer).val_;
345     if (!webGlRenderbuffer) {
346         return NVal::CreateNull(env).val_;
347     }
348     GLuint renderbufferId = 0;
349     glGenRenderbuffers(1, &renderbufferId);
350     webGlRenderbuffer->SetRenderbuffer(renderbufferId);
351     (void)AddObject<WebGLRenderbuffer>(env, renderbufferId, objRenderbuffer);
352     LOGD("WebGL createRenderbuffer renderbufferId %{public}u result %{public}p", renderbufferId, objRenderbuffer);
353     return objRenderbuffer;
354 }
355 
CreateShader(napi_env env,GLenum type)356 napi_value WebGLRenderingContextBaseImpl::CreateShader(napi_env env, GLenum type)
357 {
358     if (type != WebGLRenderingContextBase::VERTEX_SHADER && type != WebGLRenderingContextBase::FRAGMENT_SHADER) {
359         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "createShader Invalid type");
360         return NVal::CreateNull(env).val_;
361     }
362     WebGLShader* webGlShader = nullptr;
363     napi_value objShader = WebGLShader::CreateObjectInstance(env, &webGlShader).val_;
364     if (!webGlShader) {
365         return NVal::CreateNull(env).val_;
366     }
367     GLuint shaderId = glCreateShader(type);
368     webGlShader->SetShaderId(shaderId);
369     LOGD("WebGL createShader shaderId = %{public}u type %{public}u", shaderId, type);
370     if (shaderId == 0) {
371         LOGE("WebGL create shader failed. type %40{public}x", type);
372         return NVal::CreateNull(env).val_;
373     }
374     (void)AddObject<WebGLShader>(env, shaderId, objShader);
375     webGlShader->SetShaderType(type);
376     return objShader;
377 }
378 
AttachShader(napi_env env,napi_value programObj,napi_value shaderObj)379 napi_value WebGLRenderingContextBaseImpl::AttachShader(napi_env env, napi_value programObj, napi_value shaderObj)
380 {
381     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
382     if (webGLProgram == nullptr) {
383         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL attach shader invalid program");
384         return NVal::CreateNull(env).val_;
385     }
386     WebGLShader* webGlShader = WebGLShader::GetObjectInstance(env, shaderObj);
387     if (webGlShader == nullptr) {
388         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL attach shader invalid shader");
389         return NVal::CreateNull(env).val_;
390     }
391     uint32_t shaderId = webGlShader->GetShaderId();
392     uint32_t programId = webGLProgram->GetProgramId();
393     LOGD("WebGL attach shader programId %{public}u, shaderId %{public}u", programId, shaderId);
394     uint32_t index = 0;
395     if (!CheckShaderType(env, webGlShader->GetShaderType(), index) || !webGLProgram->AttachShader(index, shaderId)) {
396         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "WebGL attach shader invalid shader");
397         return NVal::CreateNull(env).val_;
398     }
399     glAttachShader(static_cast<GLuint>(programId), static_cast<GLuint>(shaderId));
400     return NVal::CreateNull(env).val_;
401 }
402 
DetachShader(napi_env env,napi_value programObj,napi_value shaderObj)403 napi_value WebGLRenderingContextBaseImpl::DetachShader(napi_env env, napi_value programObj, napi_value shaderObj)
404 {
405     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
406     if (webGLProgram == nullptr) {
407         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "webGLProgram is nullptr.");
408         return NVal::CreateNull(env).val_;
409     }
410     WebGLShader* webGlShader = WebGLShader::GetObjectInstance(env, shaderObj);
411     if (webGlShader == nullptr) {
412         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "webGlShader is nullptr.");
413         return NVal::CreateNull(env).val_;
414     }
415     uint32_t shaderId = webGlShader->GetShaderId();
416     uint32_t programId = webGLProgram->GetProgramId();
417     LOGD("WebGL detach shader programId %{public}u, shaderId %{public}u", programId, shaderId);
418     uint32_t index = 0;
419     if (!CheckShaderType(env, webGlShader->GetShaderType(), index) || !webGLProgram->DetachShader(index, shaderId)) {
420         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "Invalid shader");
421         return NVal::CreateNull(env).val_;
422     }
423     glDetachShader(static_cast<GLuint>(programId), static_cast<GLuint>(shaderId));
424     return NVal::CreateNull(env).val_;
425 }
426 
CompileShader(napi_env env,napi_value object)427 napi_value WebGLRenderingContextBaseImpl::CompileShader(napi_env env, napi_value object)
428 {
429     WebGLShader* webGlShader = WebGLShader::GetObjectInstance(env, object);
430     if (webGlShader == nullptr) {
431         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
432         return NVal::CreateNull(env).val_;
433     }
434     uint32_t shaderId = webGlShader->GetShaderId();
435     glCompileShader(static_cast<GLuint>(shaderId));
436     LOGD("WebGL compile shader shaderId %{public}u result %{public}u", shaderId, GetError_());
437     return NVal::CreateNull(env).val_;
438 }
439 
ShaderSource(napi_env env,napi_value object,const std::string & source)440 napi_value WebGLRenderingContextBaseImpl::ShaderSource(napi_env env, napi_value object, const std::string& source)
441 {
442     WebGLShader* webGlShader = WebGLShader::GetObjectInstance(env, object);
443     if (webGlShader == nullptr) {
444         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGlShader is nullptr.");
445         return NVal::CreateNull(env).val_;
446     }
447     uint32_t shaderId = webGlShader->GetShaderId();
448     if (!WebGLArg::CheckString(source)) {
449         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "checkString failed.");
450         return NVal::CreateNull(env).val_;
451     }
452     GLint length = static_cast<GLint>(source.size());
453     GLchar* str = const_cast<GLchar*>(source.c_str());
454     glShaderSource(static_cast<GLuint>(shaderId), 1, &str, &length);
455     webGlShader->SetShaderRes(source);
456     LOGD("WebGL shaderSource shaderId %{public}u source: '%{public}s' result %{public}u",
457         shaderId, source.c_str(), GetError_());
458     return NVal::CreateNull(env).val_;
459 }
460 
DeleteBuffer(napi_env env,napi_value object)461 napi_value WebGLRenderingContextBaseImpl::DeleteBuffer(napi_env env, napi_value object)
462 {
463     LOGD("WebGL deleteBuffer ");
464     WebGLBuffer* webGlBuffer = GetValidBuffer(env, object);
465     if (webGlBuffer == nullptr) {
466         return NVal::CreateNull(env).val_;
467     }
468     GLuint buffer = webGlBuffer->GetBufferId();
469     DoObjectDelete(WebGLBuffer::objectType, webGlBuffer);
470     DeleteObject<WebGLBuffer>(env, buffer);
471     glDeleteBuffers(1, &buffer);
472     LOGD("WebGL deleteBuffer bufferId %{public}u %{public}p result %{public}u", buffer, webGlBuffer, GetError_());
473     for (uint32_t i = 0; i < BoundBufferType::BUFFER_MAX; i++) {
474         if (boundBufferIds_[i] == buffer) {
475             boundBufferIds_[i] = 0;
476         }
477     }
478     return NVal::CreateNull(env).val_;
479 }
480 
DeleteFrameBuffer(napi_env env,napi_value object)481 napi_value WebGLRenderingContextBaseImpl::DeleteFrameBuffer(napi_env env, napi_value object)
482 {
483     WebGLFramebuffer* webGlFramebuffer = WebGLObject::GetObjectInstance<WebGLFramebuffer>(env, object);
484     if (webGlFramebuffer == nullptr) {
485         return NVal::CreateNull(env).val_;
486     }
487     GLuint frameBufferId = webGlFramebuffer->GetFramebuffer();
488     DeleteObject<WebGLFramebuffer>(env, frameBufferId);
489     glDeleteFramebuffers(1, &frameBufferId);
490     GLenum target = 0;
491     if (!IsHighWebGL()) {
492         if (boundFrameBufferIds_[BoundFrameBufferType::FRAMEBUFFER] == frameBufferId) {
493             boundFrameBufferIds_[BoundFrameBufferType::FRAMEBUFFER] = 0;
494         }
495         target = webGlFramebuffer->GetTarget();
496     } else {
497         if (frameBufferId == boundFrameBufferIds_[BoundFrameBufferType::FRAMEBUFFER]) {
498             if (frameBufferId == boundFrameBufferIds_[BoundFrameBufferType::READ_FRAMEBUFFER]) {
499                 target = GL_FRAMEBUFFER;
500                 boundFrameBufferIds_[BoundFrameBufferType::FRAMEBUFFER] = 0;
501                 boundFrameBufferIds_[BoundFrameBufferType::READ_FRAMEBUFFER] = 0;
502             } else {
503                 target = GL_DRAW_FRAMEBUFFER;
504                 boundFrameBufferIds_[BoundFrameBufferType::FRAMEBUFFER] = 0;
505             }
506         } else if (frameBufferId == boundFrameBufferIds_[BoundFrameBufferType::READ_FRAMEBUFFER]) {
507             target = GL_READ_FRAMEBUFFER;
508             boundFrameBufferIds_[BoundFrameBufferType::READ_FRAMEBUFFER] = 0;
509         }
510     }
511     if (target) {
512         glBindFramebuffer(target, 0);
513     }
514     LOGD("WebGL deleteFramebuffer target %{public}u framebufferId %{public}u result %{public}u",
515         target, frameBufferId, GetError_());
516     return NVal::CreateNull(env).val_;
517 }
518 
GetBufferParameter(napi_env env,GLenum target,GLenum pname)519 napi_value WebGLRenderingContextBaseImpl::GetBufferParameter(napi_env env, GLenum target, GLenum pname)
520 {
521     LOGD("WebGL getBufferParameter target %{public}u %{public}u", target, pname);
522     uint32_t index = 0;
523     if (!CheckBufferTarget(env, target, index)) {
524         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckBufferTarget failed.");
525         return NVal::CreateNull(env).val_;
526     }
527     switch (pname) {
528         case WebGLRenderingContextBase::BUFFER_USAGE:
529         case WebGLRenderingContextBase::BUFFER_SIZE: {
530             GLint value = 0;
531             glGetBufferParameteriv(target, pname, &value);
532             return NVal::CreateInt64(env, value).val_;
533         }
534         default:
535             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
536             return NVal::CreateNull(env).val_;
537     }
538 }
539 
DeleteProgram(napi_env env,napi_value object)540 napi_value WebGLRenderingContextBaseImpl::DeleteProgram(napi_env env, napi_value object)
541 {
542     WebGLProgram* webGlProgram = WebGLObject::GetObjectInstance<WebGLProgram>(env, object);
543     if (webGlProgram == nullptr) {
544         return NVal::CreateNull(env).val_;
545     }
546     uint32_t programId = webGlProgram->GetProgramId();
547     DeleteObject<WebGLProgram>(env, programId);
548     glDeleteProgram(static_cast<GLuint>(programId));
549     if (currentProgramId_ == programId) {
550         currentProgramId_ = 0;
551     } else if (currentProgramId_ != 0) {
552         LOGD("WebGL deleteProgram current programId %{public}u", currentProgramId_);
553     }
554     LOGD("WebGL deleteProgram programId %{public}u result %{public}u", programId, GetError_());
555     return NVal::CreateNull(env).val_;
556 }
557 
DeleteRenderBuffer(napi_env env,napi_value object)558 napi_value WebGLRenderingContextBaseImpl::DeleteRenderBuffer(napi_env env, napi_value object)
559 {
560     WebGLRenderbuffer* webGlRenderbuffer = WebGLObject::GetObjectInstance<WebGLRenderbuffer>(env, object);
561     if (webGlRenderbuffer == nullptr) {
562         return NVal::CreateNull(env).val_;
563     }
564 
565     uint32_t renderbuffer = webGlRenderbuffer->GetRenderbuffer();
566     WebGLFramebuffer* framebufferBinding = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
567     if (framebufferBinding) {
568         framebufferBinding->RemoveAttachment(GL_FRAMEBUFFER, renderbuffer, AttachmentType::RENDER_BUFFER);
569     }
570     framebufferBinding = GetBoundFrameBuffer(env, WebGL2RenderingContextBase::READ_FRAMEBUFFER);
571     if (framebufferBinding != nullptr) {
572         framebufferBinding->RemoveAttachment(GL_READ_FRAMEBUFFER, renderbuffer, AttachmentType::RENDER_BUFFER);
573     }
574     DeleteObject<WebGLRenderbuffer>(env, renderbuffer);
575     glDeleteRenderbuffers(1, &renderbuffer);
576     LOGD("WebGL deleteRenderbuffer renderbuffer %{public}u", renderbuffer);
577     uint32_t index = 0;
578     if (!CheckRenderBufferTarget(env, webGlRenderbuffer->GetTarget(), index)) {
579         return NVal::CreateNull(env).val_;
580     }
581     boundRenderBufferIds_[index] = 0;
582     return NVal::CreateNull(env).val_;
583 }
584 
GetRenderBufferParameter(napi_env env,GLenum target,GLenum pname)585 napi_value WebGLRenderingContextBaseImpl::GetRenderBufferParameter(napi_env env, GLenum target, GLenum pname)
586 {
587     uint32_t index = 0;
588     LOGD("WebGL getRenderbufferParameter target %{public}u %{public}u", target, pname);
589     if (!CheckRenderBufferTarget(env, target, index)) {
590         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckRenderBufferTarget failed.");
591         return NVal::CreateNull(env).val_;
592     }
593     WebGLRenderbuffer* renderBuffer = GetObjectInstance<WebGLRenderbuffer>(env, boundRenderBufferIds_[index]);
594     if (renderBuffer == nullptr) {
595         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
596             "WebGL getRenderbufferParameter can not get bound render buffer Id %{public}u",
597             boundRenderBufferIds_[index]);
598         return NVal::CreateNull(env).val_;
599     }
600 
601     GLint params = 0;
602     switch (pname) {
603         case WebGL2RenderingContextBase::RENDERBUFFER_SAMPLES: {
604             if (!IsHighWebGL()) {
605                 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
606                 return NVal::CreateNull(env).val_;
607             }
608             [[fallthrough]];
609         }
610         case WebGLRenderingContextBase::RENDERBUFFER_WIDTH:
611         case WebGLRenderingContextBase::RENDERBUFFER_HEIGHT:
612         case WebGLRenderingContextBase::RENDERBUFFER_RED_SIZE:
613         case WebGLRenderingContextBase::RENDERBUFFER_GREEN_SIZE:
614         case WebGLRenderingContextBase::RENDERBUFFER_BLUE_SIZE:
615         case WebGLRenderingContextBase::RENDERBUFFER_ALPHA_SIZE:
616         case WebGLRenderingContextBase::RENDERBUFFER_DEPTH_SIZE:
617         case WebGLRenderingContextBase::RENDERBUFFER_STENCIL_SIZE: {
618             glGetRenderbufferParameteriv(target, pname, &params);
619             return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
620         }
621         case WebGLRenderingContextBase::RENDERBUFFER_INTERNAL_FORMAT:
622             return NVal::CreateInt64(env, static_cast<int64_t>(renderBuffer->GetInternalFormat())).val_;
623         default: {
624             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "invalud pname %{public}u", pname);
625             return NVal::CreateNull(env).val_;
626         }
627     }
628 }
629 
DeleteShader(napi_env env,napi_value object)630 napi_value WebGLRenderingContextBaseImpl::DeleteShader(napi_env env, napi_value object)
631 {
632     uint32_t shaderId = WebGLShader::DEFAULT_SHADER_ID;
633     WebGLShader* webGlShader = WebGLObject::GetObjectInstance<WebGLShader>(env, object);
634     if (webGlShader == nullptr) {
635         return NVal::CreateNull(env).val_;
636     }
637     shaderId = webGlShader->GetShaderId();
638     DeleteObject<WebGLShader>(env, shaderId);
639     glDeleteShader(static_cast<GLuint>(shaderId));
640     LOGD("WebGL deleteShader shaderId %{public}u", shaderId);
641     return NVal::CreateNull(env).val_;
642 }
643 
GetShaderParameter(napi_env env,napi_value object,GLenum pname)644 napi_value WebGLRenderingContextBaseImpl::GetShaderParameter(napi_env env, napi_value object, GLenum pname)
645 {
646     WebGLShader* webGlShader = WebGLShader::GetObjectInstance(env, object);
647     if (webGlShader == nullptr) {
648         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
649         return NVal::CreateNull(env).val_;
650     }
651     uint32_t shaderId = webGlShader->GetShaderId();
652     LOGD("WebGL getShaderParameter shaderId %{public}u", shaderId);
653 
654     GLint params = 0;
655     switch (pname) {
656         case WebGLRenderingContextBase::SHADER_TYPE: {
657             glGetShaderiv(static_cast<GLuint>(shaderId), pname, &params);
658             int64_t res = static_cast<int64_t>(params);
659             return NVal::CreateInt64(env, res).val_;
660         }
661         case WebGLRenderingContextBase::DELETE_STATUS:
662         case WebGLRenderingContextBase::COMPILE_STATUS: {
663             glGetShaderiv(static_cast<GLuint>(shaderId), pname, &params);
664             bool res = (params == GL_FALSE) ? false : true;
665             return NVal::CreateBool(env, res).val_;
666         }
667         default:
668             break;
669     }
670     SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
671     return NVal::CreateNull(env).val_;
672 }
673 
GetShaderPrecisionFormat(napi_env env,GLenum shaderType,GLenum precisionType)674 napi_value WebGLRenderingContextBaseImpl::GetShaderPrecisionFormat(
675     napi_env env, GLenum shaderType, GLenum precisionType)
676 {
677     LOGD("WebGL getShaderPrecisionFormat shaderType %{public}u precisionType %{public}u", shaderType, precisionType);
678     uint32_t index = 0;
679     if (!CheckShaderType(env, shaderType, index)) {
680         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckShaderType failed.");
681         return NVal::CreateNull(env).val_;
682     }
683     if (!CheckGLenum(precisionType,
684             { WebGLRenderingContextBase::LOW_FLOAT, WebGLRenderingContextBase::MEDIUM_FLOAT,
685             WebGLRenderingContextBase::HIGH_FLOAT, WebGLRenderingContextBase::LOW_INT,
686             WebGLRenderingContextBase::MEDIUM_INT, WebGLRenderingContextBase::HIGH_INT }, {})) {
687         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckGLenum failed.");
688         return NVal::CreateNull(env).val_;
689     }
690     WebGLShaderPrecisionFormat* webGLShaderPrecisionFormat = nullptr;
691     napi_value objShaderPrecisionFormat =
692         WebGLShaderPrecisionFormat::CreateObjectInstance(env, &webGLShaderPrecisionFormat).val_;
693     if (objShaderPrecisionFormat == nullptr) {
694         LOGE("WebGL getShaderPrecisionFormat fail oshaderType %{public}u", shaderType);
695         return NVal::CreateNull(env).val_;
696     }
697 
698     GLint range[2] = { 0 }; // 2 is glGetShaderPrecisionFormat default range array pointer.
699     GLint precision = 0;
700     glGetShaderPrecisionFormat(shaderType, precisionType, range, &precision);
701     LOGD("WebGL getShaderPrecisionFormat [%{public}d %{public}d] precision %{public}d", range[0], range[1], precision);
702     webGLShaderPrecisionFormat->SetShaderPrecisionFormatRangeMin(range[0]);
703     webGLShaderPrecisionFormat->SetShaderPrecisionFormatRangeMax(range[1]);
704     webGLShaderPrecisionFormat->SetShaderPrecisionFormatPrecision(precision);
705     return objShaderPrecisionFormat;
706 }
707 
DeleteTexture(napi_env env,napi_value object)708 napi_value WebGLRenderingContextBaseImpl::DeleteTexture(napi_env env, napi_value object)
709 {
710     WebGLTexture* webGlTexture = WebGLObject::GetObjectInstance<WebGLTexture>(env, object);
711     if (webGlTexture == nullptr) {
712         return NVal::CreateNull(env).val_;
713     }
714     uint32_t texture = webGlTexture->GetTexture();
715     LOGD("WebGL deleteTexture textureId %{public}u", texture);
716     WebGLFramebuffer* framebufferBinding = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
717     if (framebufferBinding) {
718         framebufferBinding->RemoveAttachment(GL_FRAMEBUFFER, texture, AttachmentType::TEXTURE);
719     }
720     framebufferBinding = GetBoundFrameBuffer(env, WebGL2RenderingContextBase::READ_FRAMEBUFFER);
721     if (framebufferBinding != nullptr) {
722         framebufferBinding->RemoveAttachment(GL_READ_FRAMEBUFFER, texture, AttachmentType::TEXTURE);
723     }
724     uint32_t index = 0;
725     if (webGlTexture->GetTarget() &&
726         !WebGLRenderingContextBaseImpl::CheckTextureTarget(env, webGlTexture->GetTarget(), index)) {
727         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
728         return NVal::CreateNull(env).val_;
729     }
730     for (size_t i = 0; i < boundTexture_[index].size(); i++) {
731         if (boundTexture_[index][i] == texture) {
732             boundTexture_[index][i] = 0;
733         }
734     }
735     DeleteObject<WebGLTexture>(env, texture);
736     glDeleteTextures(1, &texture);
737     return NVal::CreateNull(env).val_;
738 }
739 
HandleFrameBufferAttachmentPname(napi_env env,GLenum target,GLenum attachment,GLenum pname,GLint type)740 napi_value WebGLRenderingContextBaseImpl::HandleFrameBufferAttachmentPname(
741     napi_env env, GLenum target, GLenum attachment, GLenum pname, GLint type)
742 {
743     GLint params = 0;
744     switch (pname) {
745         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
746             return NVal::CreateInt64(env, static_cast<int64_t>(type)).val_;
747         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: {
748             glGetFramebufferAttachmentParameteriv(target, attachment, pname, &params);
749             LOGD("WebGL getFramebufferAttachmentParameter objectId %{public}d", params);
750             return (type == WebGLRenderingContextBase::RENDERBUFFER) ? GetObject<WebGLRenderbuffer>(env, params) :
751                 GetObject<WebGLTexture>(env, params);
752         }
753         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: {
754             if (!IsHighWebGL()) {
755                 break;
756             }
757             [[fallthrough]];
758         }
759         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
760         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: {
761             if (type == WebGLRenderingContextBase::RENDERBUFFER) {
762                 break;
763             }
764             glGetFramebufferAttachmentParameteriv(target, attachment, pname, &params);
765             return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
766         }
767         case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: {
768             if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
769                 SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
770                 return NVal::CreateNull(env).val_;
771             }
772             [[fallthrough]];
773         }
774         case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
775         case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
776         case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
777         case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
778         case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
779         case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
780         case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: {
781             if (!IsHighWebGL()) {
782                 break;
783             }
784             glGetFramebufferAttachmentParameteriv(target, attachment, pname, &params);
785             return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
786         }
787         default:
788             break;
789     }
790     SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
791     LOGE("WebGL getFramebufferAttachmentParameter : no image is attached pname %{public}u %{public}d", pname, type);
792     return NVal::CreateNull(env).val_;
793 }
794 
GetFrameBufferAttachmentParameter(napi_env env,GLenum target,GLenum attachment,GLenum pname)795 napi_value WebGLRenderingContextBaseImpl::GetFrameBufferAttachmentParameter(
796     napi_env env, GLenum target, GLenum attachment, GLenum pname)
797 {
798     uint32_t index = 0;
799     if (!CheckFrameBufferTarget(env, target, index)) {
800         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "getFramebufferAttachmentParameter Invalid target");
801         return NVal::CreateNull(env).val_;
802     }
803     if (!CheckAttachment(env, attachment)) {
804         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckAttachment failed.");
805         return NVal::CreateNull(env).val_;
806     }
807 
808     WebGLFramebuffer* frameBuffer = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
809     if (frameBuffer == nullptr) {
810         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "frameBuffer is nullptr");
811         return NVal::CreateNull(env).val_;
812     }
813     GLint type = 0;
814     glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
815     LOGD("WebGL getFramebufferAttachmentParameter target %{public}u %{public}u %{public}u %{public}d",
816         target, attachment, pname, type);
817     if ((type != WebGLRenderingContextBase::RENDERBUFFER) && (type != WebGLRenderingContextBase::TEXTURE)) {
818         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
819         return NVal::CreateNull(env).val_;
820     }
821 
822     return HandleFrameBufferAttachmentPname(env, target, attachment, pname, type);
823 }
824 
FrameBufferRenderBuffer(napi_env env,GLenum target,GLenum attachment,GLenum renderBufferTarget,napi_value object)825 napi_value WebGLRenderingContextBaseImpl::FrameBufferRenderBuffer(
826     napi_env env, GLenum target, GLenum attachment, GLenum renderBufferTarget, napi_value object)
827 {
828     LOGD("WebGL framebufferRenderbuffer target %{public}u %{public}u %{public}u",
829         target, attachment, renderBufferTarget);
830     uint32_t frameBufferTargetIdx = 0;
831     if (!CheckFrameBufferTarget(env, target, frameBufferTargetIdx)) {
832         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
833             "WebGL framebufferRenderbuffer invalid target %{public}u", target);
834         return NVal::CreateNull(env).val_;
835     }
836     if (!CheckAttachment(env, attachment)) {
837         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
838             "WebGL framebufferRenderbuffer invalid attachment %{public}u", attachment);
839         return NVal::CreateNull(env).val_;
840     }
841     uint32_t renderBufferTargetIdx = 0;
842     if (!CheckRenderBufferTarget(env, renderBufferTarget, renderBufferTargetIdx)) {
843         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
844             "WebGL framebufferRenderbuffer invalid renderBufferTarget %{public}u", renderBufferTarget);
845         return NVal::CreateNull(env).val_;
846     }
847     WebGLFramebuffer* frameBuffer =
848         GetObjectInstance<WebGLFramebuffer>(env, boundFrameBufferIds_[frameBufferTargetIdx]);
849     if (frameBuffer == nullptr) {
850         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
851             "WebGL framebufferRenderbuffer can not find bind frame buffer");
852         return NVal::CreateNull(env).val_;
853     }
854 
855     GLuint renderbuffer = WebGLRenderbuffer::DEFAULT_RENDER_BUFFER;
856     WebGLRenderbuffer* webGlRenderbuffer = GetValidRenderBuffer(env, object);
857     if (webGlRenderbuffer != nullptr) {
858         renderbuffer = webGlRenderbuffer->GetRenderbuffer();
859     }
860 
861     if (attachment == WebGLRenderingContextBase::DEPTH_STENCIL_ATTACHMENT) {
862         if (IsHighWebGL()) {
863             frameBuffer->AddAttachment(target, WebGLRenderingContextBase::DEPTH_ATTACHMENT, renderbuffer);
864             frameBuffer->AddAttachment(target, WebGLRenderingContextBase::STENCIL_ATTACHMENT, renderbuffer);
865         } else {
866             frameBuffer->AddAttachment(target, attachment, renderbuffer);
867         }
868         glFramebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderBufferTarget, renderbuffer);
869         glFramebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderBufferTarget, renderbuffer);
870     } else {
871         frameBuffer->AddAttachment(target, attachment, renderbuffer);
872         glFramebufferRenderbuffer(target, attachment, renderBufferTarget, renderbuffer);
873     }
874     LOGD("WebGL framebufferRenderbuffer renderbuffer %{public}u error %{public}u", renderbuffer, GetError_());
875     return NVal::CreateNull(env).val_;
876 }
877 
FrameBufferTexture2D(napi_env env,GLenum target,GLenum attachment,GLenum textureTarget,napi_value texture,GLint level)878 napi_value WebGLRenderingContextBaseImpl::FrameBufferTexture2D(
879     napi_env env, GLenum target, GLenum attachment, GLenum textureTarget, napi_value texture, GLint level)
880 {
881     LOGD("WebGL framebufferTexture2D target %{public}u %{public}u %{public}u", target, attachment, textureTarget);
882     if (!CheckAttachment(env, attachment)) {
883         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "invalid attachment");
884         return NVal::CreateNull(env).val_;
885     }
886     if (IsHighWebGL()) {
887         if (CheckTextureLevel(textureTarget, level)) {
888             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "Invalid texture level");
889             return NVal::CreateNull(env).val_;
890         }
891     } else if (level) {
892         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "Invalid texture level");
893         return NVal::CreateNull(env).val_;
894     }
895     if (!CheckTexture2DTarget(env, textureTarget)) {
896         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "invalid textureTarget");
897         return NVal::CreateNull(env).val_;
898     }
899     WebGLFramebuffer* frameBuffer = GetBoundFrameBuffer(env, target);
900     if (frameBuffer == nullptr) {
901         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "can not find bind frame buffer");
902         return NVal::CreateNull(env).val_;
903     }
904 
905     int32_t textureId = WebGLTexture::DEFAULT_TEXTURE;
906     WebGLTexture* webGlTexture = WebGLTexture::GetObjectInstance(env, texture);
907     if (webGlTexture != nullptr) {
908         textureId = static_cast<int32_t>(webGlTexture->GetTexture());
909     }
910     frameBuffer->AddAttachment(target, attachment, static_cast<GLuint>(textureId), textureTarget, level);
911 
912     if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
913         glFramebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textureTarget, static_cast<GLuint>(textureId), level);
914         glFramebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textureTarget, static_cast<GLuint>(textureId), level);
915     } else {
916         glFramebufferTexture2D(target, attachment, textureTarget, static_cast<GLuint>(textureId), level);
917     }
918     LOGD("WebGL framebufferTexture2D texture %{public}u result %{public}u", textureId, GetError_());
919     return NVal::CreateNull(env).val_;
920 }
921 
GetProgramParameter(napi_env env,napi_value object,GLenum pname)922 napi_value WebGLRenderingContextBaseImpl::GetProgramParameter(napi_env env, napi_value object, GLenum pname)
923 {
924     uint32_t programId = WebGLProgram::DEFAULT_PROGRAM_ID;
925     WebGLProgram* webGlProgram = WebGLObject::GetObjectInstance<WebGLProgram>(env, object);
926     if (webGlProgram == nullptr) {
927         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
928         return NVal::CreateNull(env).val_;
929     }
930     programId = webGlProgram->GetProgramId();
931     LOGD("WebGL getProgramParameter programId %{public}u pname %{public}u", programId, pname);
932     switch (pname) {
933         case WebGLRenderingContextBase::DELETE_STATUS:
934         case WebGLRenderingContextBase::LINK_STATUS:
935         case WebGLRenderingContextBase::VALIDATE_STATUS: {
936             GLint params = 0;
937             glGetProgramiv(static_cast<GLuint>(programId), pname, &params);
938             LOGD("WebGL getProgramParameter params %{public}d", params);
939             return NVal::CreateBool(env, params ? true : false).val_;
940         }
941         case WebGLRenderingContextBase::ATTACHED_SHADERS:
942         case WebGLRenderingContextBase::ACTIVE_ATTRIBUTES:
943         case WebGLRenderingContextBase::ACTIVE_UNIFORMS: {
944             GLint params = 0;
945             glGetProgramiv(static_cast<GLuint>(programId), pname, &params);
946             LOGD("WebGL getProgramParameter params %{public}d", params);
947             return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
948         }
949         case WebGL2RenderingContextBase::ACTIVE_UNIFORM_BLOCKS:
950         case WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_VARYINGS:
951         case WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_BUFFER_MODE: {
952             if (!IsHighWebGL()) {
953                 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
954                 return NVal::CreateNull(env).val_;
955             }
956             GLint params = 0;
957             glGetProgramiv(static_cast<GLuint>(programId), pname, &params);
958             LOGD("WebGL getProgramParameter params %{public}d", params);
959             return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
960         }
961         default:
962             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "invalid pname %{public}u", pname);
963             break;
964     }
965     return NVal::CreateNull(env).val_;
966 }
967 
GetAttachedShaders(napi_env env,napi_value object)968 napi_value WebGLRenderingContextBaseImpl::GetAttachedShaders(napi_env env, napi_value object)
969 {
970     uint32_t programId = WebGLProgram::DEFAULT_PROGRAM_ID;
971     WebGLProgram* webGlProgram = WebGLObject::GetObjectInstance<WebGLProgram>(env, object);
972     if (webGlProgram != nullptr) {
973         programId = webGlProgram->GetProgramId();
974     }
975 
976     GLsizei count = 1;
977     std::vector<GLuint> shaderId(MAX_COUNT_ATTACHED_SHADER);
978     glGetAttachedShaders(
979         static_cast<GLuint>(programId), MAX_COUNT_ATTACHED_SHADER, &count, static_cast<GLuint*>(shaderId.data()));
980     LOGD("WebGL getAttachedShaders programId %{public}u count %{public}d", programId, count);
981     napi_value shaderArr = nullptr;
982     napi_create_array(env, &shaderArr);
983     for (GLsizei i = 0; i < count; i++) {
984         napi_value objShader = GetObject<WebGLShader>(env, shaderId[i]);
985         (void)napi_set_element(env, shaderArr, i, objShader);
986     }
987     return shaderArr;
988 }
989 
GetUniformLocation(napi_env env,napi_value object,const std::string & name)990 napi_value WebGLRenderingContextBaseImpl::GetUniformLocation(napi_env env, napi_value object, const std::string& name)
991 {
992     WebGLProgram* webGlProgram = WebGLObject::GetObjectInstance<WebGLProgram>(env, object);
993     if (webGlProgram == nullptr) {
994         return NVal::CreateNull(env).val_;
995     }
996     GLuint programId = webGlProgram->GetProgramId();
997     if (!CheckLocationName(name)) {
998         return NVal::CreateNull(env).val_;
999     }
1000 
1001     GLint locationId = glGetUniformLocation(programId, name.c_str());
1002     LOGD("WebGL getUniformLocation locationId programId %{public}u name '%{public}s' %{public}d",
1003         programId, name.c_str(), locationId);
1004     if (locationId == -1) {
1005         return NVal::CreateNull(env).val_;
1006     }
1007     // check if exit
1008     WebGLUniformLocation* webGLUniformLocation = GetObjectInstance<WebGLUniformLocation>(env, locationId);
1009     napi_value objUniformLocation = GetNapiValue<WebGLUniformLocation>(env, locationId);
1010     if (webGLUniformLocation == nullptr) { // create new
1011         objUniformLocation = WebGLUniformLocation::CreateObjectInstance(env, &webGLUniformLocation).val_;
1012         if (!objUniformLocation) {
1013             return NVal::CreateNull(env).val_;
1014         }
1015         webGLUniformLocation->SetUniformLocationId(locationId);
1016         AddObject<WebGLUniformLocation>(env, locationId, objUniformLocation);
1017     } else {
1018         webGLUniformLocation->SetUniformLocationName(name);
1019     }
1020     return objUniformLocation;
1021 }
1022 
GetAttribLocation(napi_env env,napi_value object,const std::string & name)1023 napi_value WebGLRenderingContextBaseImpl::GetAttribLocation(napi_env env, napi_value object, const std::string& name)
1024 {
1025     WebGLProgram* webGlProgram = WebGLObject::GetObjectInstance<WebGLProgram>(env, object);
1026     if (webGlProgram == nullptr) {
1027         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGlProgram is nullptr.");
1028         return NVal::CreateInt64(env, -1).val_;
1029     }
1030 
1031     if (!CheckLocationName(name)) {
1032         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckLocationName failed.");
1033         return NVal::CreateInt64(env, -1).val_;
1034     }
1035 
1036     if (!CheckProgramLinkStatus(webGlProgram)) {
1037         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckProgramLinkStatus failed.");
1038         return NVal::CreateInt64(env, -1).val_;
1039     }
1040     GLuint programId = webGlProgram->GetProgramId();
1041     GLint returnValue = glGetAttribLocation(programId, const_cast<char*>(name.c_str()));
1042     LOGD("WebGL getAttribLocation programId %{public}u name %{public}s, location %{public}d",
1043         programId, name.c_str(), returnValue);
1044     return NVal::CreateInt64(env, static_cast<int64_t>(returnValue)).val_;
1045 }
1046 
GetVertexAttrib(napi_env env,GLenum pname,GLuint index,VertexAttribInfo * info)1047 napi_value WebGLRenderingContextBaseImpl::GetVertexAttrib(napi_env env, GLenum pname, GLuint index,
1048     VertexAttribInfo* info)
1049 {
1050     if (info == nullptr) {
1051         return NVal::CreateNull(env).val_;
1052     }
1053     WebGLWriteBufferArg writeBuffer(env);
1054     void* result = reinterpret_cast<void*>(writeBuffer.AllocBuffer(4 * sizeof(GLfloat))); // 4 args
1055     if (result == nullptr) {
1056         return NVal::CreateNull(env).val_;
1057     }
1058     switch (info->type) {
1059         case BUFFER_DATA_FLOAT_32:
1060             glGetVertexAttribfv(index, pname, reinterpret_cast<GLfloat*>(result));
1061             return writeBuffer.ToNormalArray(BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32);
1062         case BUFFER_DATA_INT_32:
1063             glGetVertexAttribIuiv(index, pname, reinterpret_cast<GLuint*>(result));
1064             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_INT_32);
1065         case BUFFER_DATA_UINT_32:
1066             glGetVertexAttribIuiv(index, pname, reinterpret_cast<GLuint*>(result));
1067             return writeBuffer.ToNormalArray(BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32);
1068         default:
1069             break;
1070     }
1071     return NVal::CreateNull(env).val_;
1072 }
1073 
GetVertexAttrib(napi_env env,GLenum pname,GLuint index)1074 napi_value WebGLRenderingContextBaseImpl::GetVertexAttrib(napi_env env, GLenum pname, GLuint index)
1075 {
1076     LOGD("WebGL getVertexAttrib index %{public}u %{public}u", index, pname);
1077     VertexAttribInfo* info = GetVertexAttribInfo(index);
1078     if (info == nullptr) {
1079         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1080         return NVal::CreateNull(env).val_;
1081     }
1082     int32_t params = -1;
1083     switch (pname) {
1084         case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
1085             glGetVertexAttribiv(index, pname, &params);
1086             LOGD("WebGL getVertexAttrib %{public}d", params);
1087             return GetObject<WebGLBuffer>(env, params);
1088         }
1089         case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1090         case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1091         case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1092             glGetVertexAttribiv(index, pname, &params);
1093             return NVal::CreateBool(env, static_cast<bool>(params)).val_;
1094         case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1095         case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1096         case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:
1097         case GL_VERTEX_ATTRIB_ARRAY_TYPE: {
1098             glGetVertexAttribiv(index, pname, &params);
1099             LOGD("WebGL getVertexAttrib %{public}d", params);
1100             return NVal::CreateInt64(env, params).val_;
1101         }
1102         case GL_CURRENT_VERTEX_ATTRIB:
1103             break;
1104         default:
1105             glGetVertexAttribiv(index, pname, &params);
1106             LOGD("WebGL getVertexAttrib getVertexAttrib end");
1107             return NVal::CreateNull(env).val_;
1108     }
1109     return GetVertexAttrib(env, pname, index, info);
1110 }
1111 
GetExtensionsParameter(napi_env env,GLenum pname)1112 static napi_value GetExtensionsParameter(napi_env env, GLenum pname)
1113 {
1114     const unsigned char* extensions = glGetString(pname);
1115     if (extensions == nullptr) {
1116         return NVal::CreateNull(env).val_;
1117     }
1118     std::string str = const_cast<char*>(reinterpret_cast<const char*>(extensions));
1119     vector<std::string> vec {};
1120     Util::SplitString(str, vec, " ");
1121     LOGD("WebGL GetExtensionsParameter  %{public}s %{public}s %{public}zu", extensions, str.c_str(), vec.size());
1122     napi_value result = nullptr;
1123     napi_create_array_with_length(env, vec.size(), &result);
1124     for (vector<std::string>::size_type i = 0; i != vec.size(); ++i) {
1125         napi_set_element(env, result, i, NVal::CreateUTF8String(env, vec[i]).val_);
1126     }
1127     return result;
1128 }
1129 
1130 template<class T>
GetObjectParameter(napi_env env,GLenum pname)1131 napi_value WebGLRenderingContextBaseImpl::GetObjectParameter(napi_env env, GLenum pname)
1132 {
1133     GLint params = 0;
1134     glGetIntegerv(pname, &params);
1135     LOGD("WebGL getParameter %{public}s params %{public}d", T::className.c_str(), params);
1136     return GetObject<T>(env, params);
1137 }
1138 
1139 template<class T>
GetIntegerVectorParameter(napi_env env,GLenum pname,GLuint count,BufferDataType dstDataType)1140 napi_value WebGLRenderingContextBaseImpl::GetIntegerVectorParameter(
1141     napi_env env, GLenum pname, GLuint count, BufferDataType dstDataType)
1142 {
1143     LOGD("get integer parameter pname %{public}u count %{public}u", pname, count);
1144     WebGLWriteBufferArg writeBuffer(env);
1145     T* params = reinterpret_cast<T*>(writeBuffer.AllocBuffer(count * sizeof(T))); // 2 args
1146     if (params == nullptr) {
1147         return writeBuffer.ToExternalArray(dstDataType);
1148     }
1149     glGetIntegerv(pname, params);
1150     return writeBuffer.ToExternalArray(dstDataType);
1151 }
1152 
GetFloatVectorParameter(napi_env env,GLenum pname,GLuint count,BufferDataType dstDataType)1153 napi_value WebGLRenderingContextBaseImpl::GetFloatVectorParameter(
1154     napi_env env, GLenum pname, GLuint count, BufferDataType dstDataType)
1155 {
1156     LOGD("get float parameter pname %{public}u count %{public}u", pname, count);
1157     WebGLWriteBufferArg writeBuffer(env);
1158     GLfloat* params = reinterpret_cast<GLfloat*>(writeBuffer.AllocBuffer(count * sizeof(GLfloat)));
1159     if (params == nullptr) {
1160         return writeBuffer.ToExternalArray(dstDataType);
1161     }
1162     glGetFloatv(pname, params);
1163     return writeBuffer.ToExternalArray(dstDataType);
1164 }
1165 
GetBoolVectorParameter(napi_env env,GLenum pname,GLuint count,BufferDataType dstDataType)1166 napi_value WebGLRenderingContextBaseImpl::GetBoolVectorParameter(
1167     napi_env env, GLenum pname, GLuint count, BufferDataType dstDataType)
1168 {
1169     WebGLWriteBufferArg writeBuffer(env);
1170     GLboolean* params = reinterpret_cast<GLboolean*>(writeBuffer.AllocBuffer(count * sizeof(GLboolean)));
1171     if (params == nullptr) {
1172         return writeBuffer.ToExternalArray(dstDataType);
1173     }
1174     glGetBooleanv(pname, static_cast<GLboolean*>(params));
1175     return writeBuffer.ToNormalArray(BUFFER_DATA_BOOLEAN, dstDataType);
1176 }
1177 
GetParameter(napi_env env,GLenum pname)1178 napi_value WebGLRenderingContextBaseImpl::GetParameter(napi_env env, GLenum pname)
1179 {
1180     LOGD("WebGL getParameter pname %{public}u", pname);
1181     switch (pname) {
1182         case GL_DEPTH_CLEAR_VALUE:
1183         case GL_LINE_WIDTH:
1184         case GL_POLYGON_OFFSET_FACTOR:
1185         case GL_POLYGON_OFFSET_UNITS:
1186         case GL_SAMPLE_COVERAGE_VALUE:
1187             return WebGLArg::GetFloatParameter(env, pname);
1188         case GL_TEXTURE_BINDING_2D:
1189         case GL_TEXTURE_BINDING_CUBE_MAP:
1190             return GetObjectParameter<WebGLTexture>(env, pname);
1191         case GL_RENDERER:
1192         case GL_SHADING_LANGUAGE_VERSION:
1193         case GL_VENDOR:
1194         case GL_VERSION:
1195             return GetExtensionsParameter(env, pname);
1196         case GL_ARRAY_BUFFER_BINDING:
1197         case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1198             return GetObjectParameter<WebGLBuffer>(env, pname);
1199         case GL_FRAMEBUFFER_BINDING:
1200             return GetObjectParameter<WebGLFramebuffer>(env, pname);
1201         case GL_CURRENT_PROGRAM:
1202             return GetObjectParameter<WebGLProgram>(env, pname);
1203         case GL_RENDERBUFFER_BINDING:
1204             return GetObjectParameter<WebGLRenderbuffer>(env, pname);
1205         case GL_ALIASED_LINE_WIDTH_RANGE:
1206         case GL_ALIASED_POINT_SIZE_RANGE:
1207         case GL_DEPTH_RANGE:
1208             return GetFloatVectorParameter(env, pname, 2, BUFFER_DATA_FLOAT_32); //  2 args
1209         case GL_COLOR_CLEAR_VALUE:
1210         case GL_BLEND_COLOR:
1211             return GetFloatVectorParameter(env, pname, 4, BUFFER_DATA_FLOAT_32); //  4 args
1212         case GL_COMPRESSED_TEXTURE_FORMATS: {
1213             GLint count = 0;
1214             glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &count);
1215             return GetIntegerVectorParameter<GLint>(env, pname, count, BUFFER_DATA_INT_32);
1216         }
1217         case GL_MAX_VIEWPORT_DIMS:
1218             return GetIntegerVectorParameter<GLint>(env, pname, 2, BUFFER_DATA_INT_32); // 2 args
1219         case GL_SCISSOR_BOX:
1220         case WebGLRenderingContextBase::VIEWPORT:
1221             return GetIntegerVectorParameter<GLint>(env, pname, 4, BUFFER_DATA_INT_32); // 4 args
1222         case GL_COLOR_WRITEMASK:
1223             return GetBoolVectorParameter(env, pname, 4, BUFFER_DATA_BOOLEAN); // 4 args
1224         case WebGLRenderingContextBase::UNPACK_COLORSPACE_CONVERSION_WEBGL:
1225             return NVal::CreateInt64(env, unpackColorspaceConversion_).val_;
1226         case WebGLRenderingContextBase::UNPACK_FLIP_Y_WEBGL:
1227             return NVal::CreateBool(env, unpackFlipY_).val_;
1228         case WebGLRenderingContextBase::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
1229             return NVal::CreateBool(env, unpackPremultiplyAlpha_).val_;
1230         default: {
1231             if (CheckInList(pname, GetBoolParaName())) {
1232                 return WebGLArg::GetBoolParameter(env, pname);
1233             }
1234             if (CheckInList(pname, GetIntegerParaName())) {
1235                 return WebGLArg::GetInt32Parameter(env, pname);
1236             }
1237             break;
1238         }
1239     }
1240     SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "WebGL getParameter invalid pname %{public}u", pname);
1241     return NVal::CreateNull(env).val_;
1242 }
1243 
ClearColor(napi_env env,GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)1244 napi_value WebGLRenderingContextBaseImpl::ClearColor(
1245     napi_env env, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
1246 {
1247     LOGD("WebGL clearColor [%{public}f, %{public}f, %{public}f, %{public}f]", red, green, blue, alpha);
1248     clearColor_[0] = red; // 0:red
1249     clearColor_[1] = green; // 1:green
1250     clearColor_[2] = blue; // 2:blue
1251     clearColor_[3] = alpha; // 3:alpha
1252     glClearColor(red, green, blue, alpha);
1253     return NVal::CreateNull(env).val_;
1254 }
1255 
ColorMask(napi_env env,GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)1256 napi_value WebGLRenderingContextBaseImpl::ColorMask(
1257     napi_env env, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
1258 {
1259     colorMask_[0] = red; // 0:red
1260     colorMask_[1] = green; // 1:green
1261     colorMask_[2] = blue; // 2:blue
1262     colorMask_[3] = alpha; // 3:alpha
1263     glColorMask(static_cast<GLboolean>(red), static_cast<GLboolean>(green), static_cast<GLboolean>(blue),
1264         static_cast<GLboolean>(alpha));
1265     return NVal::CreateNull(env).val_;
1266 }
1267 
Clear(napi_env env,GLbitfield mask)1268 napi_value WebGLRenderingContextBaseImpl::Clear(napi_env env, GLbitfield mask)
1269 {
1270     if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
1271         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1272             "WebGL clear mask %{public}x failed.", mask);
1273         return NVal::CreateNull(env).val_;
1274     }
1275     GLenum result = CheckFrameBufferBoundComplete(env);
1276     if (result) {
1277         SET_ERROR_WITH_LOG(result, "WebGL clear mask %{public}x CheckFrameBufferBoundComplete failed.", mask);
1278         return NVal::CreateNull(env).val_;
1279     }
1280     glClear(mask);
1281     LOGD("WebGL clear mask %{public}x result %{public}u", mask, GetError_());
1282     return NVal::CreateNull(env).val_;
1283 }
1284 
ClearDepth(napi_env env,GLclampf depth)1285 napi_value WebGLRenderingContextBaseImpl::ClearDepth(napi_env env, GLclampf depth)
1286 {
1287     LOGD("WebGL clearDepth %{public}f", depth);
1288     clearDepth_ = depth;
1289     glClearDepthf(depth);
1290     return NVal::CreateNull(env).val_;
1291 }
1292 
ClearStencil(napi_env env,GLint s)1293 napi_value WebGLRenderingContextBaseImpl::ClearStencil(napi_env env, GLint s)
1294 {
1295     LOGD("WebGL clearStencil s %{public}d", s);
1296     clearStencil_ = static_cast<GLint>(s);
1297     glClearStencil(static_cast<GLint>(s));
1298     return NVal::CreateNull(env).val_;
1299 }
1300 
UseProgram(napi_env env,napi_value object)1301 napi_value WebGLRenderingContextBaseImpl::UseProgram(napi_env env, napi_value object)
1302 {
1303     uint32_t program = WebGLProgram::DEFAULT_PROGRAM_ID;
1304     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, object);
1305     if (webGLProgram != nullptr) {
1306         program = webGLProgram->GetProgramId();
1307     }
1308     if ((currentProgramId_ != program) && (currentProgramId_ != 0)) {
1309         glUseProgram(static_cast<GLuint>(0));
1310     }
1311     currentProgramId_ = program;
1312     glUseProgram(static_cast<GLuint>(program));
1313     LOGD("WebGL useProgram programId %{public}u %{public}u result %{public}u",
1314         program, currentProgramId_, GetError_());
1315     return NVal::CreateNull(env).val_;
1316 }
1317 
ValidateProgram(napi_env env,napi_value object)1318 napi_value WebGLRenderingContextBaseImpl::ValidateProgram(napi_env env, napi_value object)
1319 {
1320     uint32_t program = WebGLProgram::DEFAULT_PROGRAM_ID;
1321     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, object);
1322     if (webGLProgram != nullptr) {
1323         program = webGLProgram->GetProgramId();
1324     }
1325     LOGD("WebGL validateProgram program %{public}u", program);
1326     glValidateProgram(static_cast<GLuint>(program));
1327     return NVal::CreateNull(env).val_;
1328 }
1329 
LinkProgram(napi_env env,napi_value object)1330 napi_value WebGLRenderingContextBaseImpl::LinkProgram(napi_env env, napi_value object)
1331 {
1332     uint32_t program = WebGLProgram::DEFAULT_PROGRAM_ID;
1333     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, object);
1334     if (webGLProgram != nullptr) {
1335         program = webGLProgram->GetProgramId();
1336     }
1337     glLinkProgram(static_cast<GLuint>(program));
1338     LOGD("WebGL linkProgram program %{public}u result %{public}u", program, GetError_());
1339     return NVal::CreateNull(env).val_;
1340 }
1341 
RenderBufferStorage(napi_env env,const TexStorageArg & arg)1342 napi_value WebGLRenderingContextBaseImpl::RenderBufferStorage(napi_env env, const TexStorageArg& arg)
1343 {
1344     LOGD("WebGL renderbufferStorage target %{public}u %{public}u %{public}d %{public}d",
1345         arg.target, arg.internalFormat, arg.width, arg.height);
1346     WebGLRenderbuffer* renderBuffer = CheckRenderBufferStorage(env, arg);
1347     if (renderBuffer == nullptr) {
1348         return NVal::CreateNull(env).val_;
1349     }
1350 
1351     switch (arg.internalFormat) {
1352         case WebGLRenderingContextBase::DEPTH_COMPONENT16:
1353         case WebGLRenderingContextBase::RGBA4:
1354         case WebGLRenderingContextBase::RGB5_A1:
1355         case WebGLRenderingContextBase::RGB565:
1356         case WebGLRenderingContextBase::STENCIL_INDEX8: {
1357             glRenderbufferStorage(arg.target, arg.internalFormat, arg.width, arg.height);
1358             renderBuffer->SetInternalFormat(arg.internalFormat);
1359             renderBuffer->SetSize(arg.width, arg.height);
1360             break;
1361         }
1362         case WebGLRenderingContextBase::DEPTH_STENCIL: {
1363             glRenderbufferStorage(arg.target, GL_DEPTH_COMPONENT16, arg.width, arg.height);
1364             glRenderbufferStorage(arg.target, GL_STENCIL_INDEX8, arg.width, arg.height);
1365             renderBuffer->SetInternalFormat(arg.internalFormat);
1366             renderBuffer->SetSize(arg.width, arg.height);
1367             break;
1368         }
1369         default:
1370             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1371             return NVal::CreateNull(env).val_;
1372     }
1373     LOGD("WebGL renderbufferStorage result %{public}u", GetError_());
1374     return NVal::CreateNull(env).val_;
1375 }
1376 
VertexAttribPointer(napi_env env,const VertexAttribArg & vertexInfo)1377 napi_value WebGLRenderingContextBaseImpl::VertexAttribPointer(napi_env env, const VertexAttribArg& vertexInfo)
1378 {
1379     vertexInfo.Dump("WebGL vertexAttribPointer");
1380     if (!CheckGLenum(vertexInfo.type, { GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT }, {})) {
1381         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1382             "WebGL vertexAttribPointer invalid type %{public}u", vertexInfo.type);
1383     }
1384     GLenum result = CheckVertexAttribPointer(env, vertexInfo);
1385     if (result) {
1386         SET_ERROR(result);
1387         return NVal::CreateNull(env).val_;
1388     }
1389     glVertexAttribPointer(vertexInfo.index, vertexInfo.size, vertexInfo.type, vertexInfo.normalized,
1390         vertexInfo.stride, reinterpret_cast<GLvoid*>(vertexInfo.offset));
1391     LOGD("WebGL vertexAttribPointer index %{public}u result %{public}u", vertexInfo.index, GetError_());
1392     return NVal::CreateNull(env).val_;
1393 }
1394 
GetVertexAttribOffset(napi_env env,GLuint index,GLenum pname)1395 napi_value WebGLRenderingContextBaseImpl::GetVertexAttribOffset(napi_env env, GLuint index, GLenum pname)
1396 {
1397     LOGD("WebGL getVertexAttribOffset index %{public}u %{public}u", index, pname);
1398     if (pname != WebGLRenderingContextBase::VERTEX_ATTRIB_ARRAY_POINTER) {
1399         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1400         return NVal::CreateInt64(env, 0).val_;
1401     }
1402     GLvoid* point = nullptr;
1403     glGetVertexAttribPointerv(index, pname, &point);
1404     return NVal::CreateInt64(env, reinterpret_cast<int64_t>(point)).val_;
1405 }
1406 
EnableVertexAttribArray(napi_env env,int64_t index)1407 napi_value WebGLRenderingContextBaseImpl::EnableVertexAttribArray(napi_env env, int64_t index)
1408 {
1409     if (index < 0 || index >= GetMaxVertexAttribs()) {
1410         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1411             "WebGL enableVertexAttribArray invalid index %{public}" PRIi64, index);
1412         return NVal::CreateNull(env).val_;
1413     }
1414     LOGD("WebGL enableVertexAttribArray index %{public}" PRIi64, index);
1415     glEnableVertexAttribArray(static_cast<GLuint>(index));
1416     return NVal::CreateNull(env).val_;
1417 }
1418 
DisableVertexAttribArray(napi_env env,int64_t index)1419 napi_value WebGLRenderingContextBaseImpl::DisableVertexAttribArray(napi_env env, int64_t index)
1420 {
1421     if (index < 0 || index >= GetMaxVertexAttribs()) {
1422         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1423             "WebGL disableVertexAttribArray invalid index %{public}" PRIi64, index);
1424         return NVal::CreateNull(env).val_;
1425     }
1426     LOGD("WebGL disableVertexAttribArray index %{public}" PRIi64, index);
1427     glDisableVertexAttribArray(index);
1428     return NVal::CreateNull(env).val_;
1429 }
1430 
IsEnabled(napi_env env,GLenum cap)1431 napi_value WebGLRenderingContextBaseImpl::IsEnabled(napi_env env, GLenum cap)
1432 {
1433     bool result = false;
1434     if (!CheckCap(env, cap)) {
1435         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1436         return NVal::CreateBool(env, result).val_;
1437     }
1438     result = static_cast<bool>(glIsEnabled(cap));
1439     LOGD("WebGL isEnabled cap %{public}u result %{public}d", cap, result);
1440     return NVal::CreateBool(env, result).val_;
1441 }
1442 
Disable(napi_env env,GLenum cap)1443 napi_value WebGLRenderingContextBaseImpl::Disable(napi_env env, GLenum cap)
1444 {
1445     LOGD("WebGL disable cap %{public}u", cap);
1446     if (!CheckCap(env, cap)) {
1447         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1448         return NVal::CreateNull(env).val_;
1449     }
1450     glDisable(cap);
1451     return NVal::CreateNull(env).val_;
1452 }
1453 
Enable(napi_env env,GLenum cap)1454 napi_value WebGLRenderingContextBaseImpl::Enable(napi_env env, GLenum cap)
1455 {
1456     LOGD("WebGL enable cap %{public}u", cap);
1457     if (!CheckCap(env, cap)) {
1458         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1459         return NVal::CreateNull(env).val_;
1460     }
1461     if (cap == WebGLRenderingContextBase::STENCIL_TEST) {
1462         stencilEnabled_ = true;
1463     }
1464     if (cap == WebGLRenderingContextBase::SCISSOR_TEST) {
1465         scissorEnabled_ = true;
1466     }
1467     glEnable(cap);
1468     return NVal::CreateNull(env).val_;
1469 }
1470 
BindAttribLocation(napi_env env,napi_value program,GLuint index,const std::string & name)1471 napi_value WebGLRenderingContextBaseImpl::BindAttribLocation(
1472     napi_env env, napi_value program, GLuint index, const std::string& name)
1473 {
1474     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, program);
1475     if (webGLProgram == nullptr) {
1476         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL bindAttribLocation invalid object");
1477         return NVal::CreateNull(env).val_;
1478     }
1479     GLuint programId = webGLProgram->GetProgramId();
1480 
1481     if (index >= GetMaxVertexAttribs()) {
1482         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1483             "WebGL bindAttribLocation invalid index %{public}u", index);
1484         return NVal::CreateNull(env).val_;
1485     }
1486 
1487     if (!CheckLocationName(name)) {
1488         return NVal::CreateNull(env).val_;
1489     }
1490     LOGD("WebGL bindAttribLocation programId %{public}u index %{public}u name %{public}s",
1491         programId, index, name.c_str());
1492     glBindAttribLocation(programId, index, const_cast<char*>(name.c_str()));
1493     return NVal::CreateNull(env).val_;
1494 }
1495 
GenerateMipmap(napi_env env,GLenum target)1496 napi_value WebGLRenderingContextBaseImpl::GenerateMipmap(napi_env env, GLenum target)
1497 {
1498     if (!CheckGLenum(target,
1499         { WebGLRenderingContextBase::TEXTURE_2D, WebGLRenderingContextBase::TEXTURE_CUBE_MAP },
1500         { WebGL2RenderingContextBase::TEXTURE_3D, WebGL2RenderingContextBase::TEXTURE_2D_ARRAY })) {
1501         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1502         return NVal::CreateNull(env).val_;
1503     }
1504 
1505     WebGLTexture* webGLTexture = GetBoundTexture(env, target, false);
1506     if (webGLTexture == nullptr) {
1507         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1508         return NVal::CreateNull(env).val_;
1509     }
1510     glGenerateMipmap(target);
1511     LOGD("WebGL generateMipmap target %{public}u %{public}u", target, GetError_());
1512     return NVal::CreateNull(env).val_;
1513 }
1514 
GetError_()1515 GLenum WebGLRenderingContextBaseImpl::GetError_()
1516 {
1517     GLenum err = glGetError();
1518     if (err != GL_NO_ERROR) {
1519         lastError_ = err;
1520     }
1521     return lastError_;
1522 }
1523 
GetError(napi_env env)1524 napi_value WebGLRenderingContextBaseImpl::GetError(napi_env env)
1525 {
1526     GLenum err = GetError_();
1527     LOGD("getError result %{public}u", err);
1528     lastError_ = GL_NO_ERROR;
1529     return NVal::CreateInt64(env, static_cast<int64_t>(err)).val_;
1530 }
1531 
UniformF(napi_env env,napi_value locationObj,uint32_t count,const GLfloat * data)1532 napi_value WebGLRenderingContextBaseImpl::UniformF(
1533     napi_env env, napi_value locationObj, uint32_t count, const GLfloat* data)
1534 {
1535     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1536     if (webGLUniformLocation == nullptr) {
1537         LOGE("WebGL uniform_f can not find uniform");
1538         return NVal::CreateNull(env).val_;
1539     }
1540     GLint location = webGLUniformLocation->GetUniformLocationId();
1541 
1542     // 0,1,2,3 index for data
1543     LOGD("WebGL uniform location %{public}d [%{public}f %{public}f %{public}f %{public}f]",
1544         location, data[0], data[1], data[2], data[3]);
1545     switch (count) {
1546         case PARAMETERS_NUM_1:
1547             glUniform1f(location, data[0]);
1548             break;
1549         case PARAMETERS_NUM_2:
1550             glUniform2f(location, data[0], data[1]);
1551             break;
1552         case PARAMETERS_NUM_3:
1553             glUniform3f(location, data[0], data[1], data[2]); // 0,1,2,3 index for data
1554             break;
1555         case PARAMETERS_NUM_4:
1556             glUniform4f(location, data[0], data[1], data[2], data[3]); // 0,1,2,3 index for data
1557             break;
1558         default:
1559             break;;
1560     }
1561     return NVal::CreateNull(env).val_;
1562 }
1563 
UniformI(napi_env env,napi_value locationObj,uint32_t count,const GLint * data)1564 napi_value WebGLRenderingContextBaseImpl::UniformI(
1565     napi_env env, napi_value locationObj, uint32_t count, const GLint* data)
1566 {
1567     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1568     if (webGLUniformLocation == nullptr) {
1569         LOGE("WebGL uniform_i can not find uniform");
1570         return NVal::CreateNull(env).val_;
1571     }
1572     GLint location = webGLUniformLocation->GetUniformLocationId();
1573     // 0,1,2,3 index for data
1574     LOGD("WebGL uniform location %{public}d [%{public}d %{public}d %{public}d %{public}d]",
1575         location, data[0], data[1], data[2], data[3]);
1576     switch (count) {
1577         case PARAMETERS_NUM_1:
1578             glUniform1i(location, data[0]);
1579             break;
1580         case PARAMETERS_NUM_2:
1581             glUniform2i(location, data[0], data[1]);
1582             break;
1583         case PARAMETERS_NUM_3:
1584             glUniform3i(location, data[0], data[1], data[2]); // 0, 1, 2 are array index
1585             break;
1586         case PARAMETERS_NUM_4:
1587             glUniform4i(location, data[0], data[1], data[2], data[3]); // 0, 1, 2, 3 are array index
1588             break;
1589         default:
1590             break;
1591     }
1592     return NVal::CreateNull(env).val_;
1593 }
1594 
UniformUi(napi_env env,napi_value locationObj,uint32_t count,const GLuint * data)1595 napi_value WebGLRenderingContextBaseImpl::UniformUi(
1596     napi_env env, napi_value locationObj, uint32_t count, const GLuint* data)
1597 {
1598     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1599     if (webGLUniformLocation == nullptr) {
1600         LOGE("WebGL uniform_ui can not find uniform");
1601         return NVal::CreateNull(env).val_;
1602     }
1603     GLint location = webGLUniformLocation->GetUniformLocationId();
1604     LOGD("WebGL uniformXui location %{public}d [%{public}u %{public}u %{public}u %{public}u]",
1605         location, data[0], data[1], data[2], data[3]); // 0,1,2,3 index for data
1606     switch (count) {
1607         case PARAMETERS_NUM_1:
1608             glUniform1ui(location, data[0]);
1609             break;
1610         case PARAMETERS_NUM_2:
1611             glUniform2ui(location, data[0], data[1]);
1612             break;
1613         case PARAMETERS_NUM_3:
1614             glUniform3ui(location, data[0], data[1], data[2]); // 0, 1, 2 are array index
1615             break;
1616         case PARAMETERS_NUM_4:
1617             glUniform4ui(location, data[0], data[1], data[2], data[3]); // 0, 1, 2, 3 are array index
1618             break;
1619         default:
1620             break;
1621     }
1622     LOGD("WebGL uniformXui result %{public}u", GetError_());
1623     return NVal::CreateNull(env).val_;
1624 }
1625 
1626 template<class T>
CheckUniformDataInfo(bool isHighWebGL,const WebGLReadBufferArg & readData,const UniformExtInfo * info)1627 static std::tuple<GLenum, GLsizei, T*> CheckUniformDataInfo(
1628     bool isHighWebGL, const WebGLReadBufferArg& readData, const UniformExtInfo* info)
1629 {
1630     GLuint count = static_cast<GLuint>(readData.GetBufferLength() / sizeof(T));
1631     T* srcData = reinterpret_cast<T*>(readData.GetBuffer());
1632     LOGD("WebGL CheckUniformDataInfo count %{public}u length %{public}zu %{public}zu Offset %{public}zu %{public}zu",
1633         count, readData.GetBufferLength(), info->elemCount, info->srcOffset, info->srcLength);
1634     if (isHighWebGL) {
1635         if (count <= info->srcOffset || count < info->srcLength) {
1636             return make_tuple(WebGLRenderingContextBase::INVALID_VALUE, 0, nullptr);
1637         }
1638         count = info->srcLength != 0 ? info->srcLength : count - info->srcOffset;
1639         srcData = srcData + info->srcOffset;
1640     }
1641     if (count % info->elemCount) {
1642         return make_tuple(WebGLRenderingContextBase::INVALID_VALUE, 0, nullptr);
1643     }
1644     if (count != info->elemCount) {
1645         return make_tuple(WebGLRenderingContextBase::INVALID_OPERATION, 0, nullptr);
1646     }
1647     return make_tuple(WebGLRenderingContextBase::NO_ERROR, count, srcData);
1648 }
1649 
UniformFv(napi_env env,napi_value locationObj,napi_value data,const UniformExtInfo * info)1650 napi_value WebGLRenderingContextBaseImpl::UniformFv(
1651     napi_env env, napi_value locationObj, napi_value data, const UniformExtInfo* info)
1652 {
1653     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1654     if (webGLUniformLocation == nullptr) {
1655         LOGE("WebGL uniform_fv can not find uniform");
1656         return NVal::CreateNull(env).val_;
1657     }
1658     GLint location = webGLUniformLocation->GetUniformLocationId();
1659 
1660     WebGLReadBufferArg readData(env);
1661     napi_status status = readData.GenBufferData(data, BUFFER_DATA_FLOAT_32);
1662     if (status != napi_ok) {
1663         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GenBufferData failed.");
1664         return NVal::CreateNull(env).val_;
1665     }
1666     readData.DumpBuffer(readData.GetBufferDataType());
1667     if (readData.GetBufferDataType() != BUFFER_DATA_FLOAT_32) {
1668         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GetBufferDataType failed. %{public}d",
1669             readData.GetBufferDataType());
1670         return NVal::CreateNull(env).val_;
1671     }
1672     GLenum result = 0;
1673     GLsizei count = 0;
1674     GLfloat* srcData = nullptr;
1675     std::tie(result, count, srcData) = CheckUniformDataInfo<GLfloat>(IsHighWebGL(), readData, info);
1676     if (result) {
1677         SET_ERROR(result);
1678         return NVal::CreateNull(env).val_;
1679     }
1680 
1681     switch (info->dimension) {
1682         case PARAMETERS_NUM_1:
1683             glUniform1fv(location, 1, srcData);
1684             break;
1685         case PARAMETERS_NUM_2:
1686             glUniform2fv(location, count / 2, srcData); // 2 array size
1687             break;
1688         case PARAMETERS_NUM_3:
1689             glUniform3fv(location, count / 3, srcData); // 3 array size
1690             break;
1691         case PARAMETERS_NUM_4:
1692             glUniform4fv(location, count / 4, srcData); // 4 array size
1693             break;
1694         default:
1695             break;
1696     }
1697     return NVal::CreateNull(env).val_;
1698 }
1699 
UniformIv(napi_env env,napi_value locationObj,napi_value data,const UniformExtInfo * info)1700 napi_value WebGLRenderingContextBaseImpl::UniformIv(
1701     napi_env env, napi_value locationObj, napi_value data, const UniformExtInfo* info)
1702 {
1703     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1704     if (webGLUniformLocation == nullptr) {
1705         LOGE("WebGL UniformIv can not find uniform");
1706         return NVal::CreateNull(env).val_;
1707     }
1708     GLint location = webGLUniformLocation->GetUniformLocationId();
1709 
1710     WebGLReadBufferArg readData(env);
1711     napi_status status = readData.GenBufferData(data, BUFFER_DATA_INT_32);
1712     if (status != napi_ok) {
1713         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL UniformIv failed to getbuffer data");
1714         return NVal::CreateNull(env).val_;
1715     }
1716     readData.DumpBuffer(readData.GetBufferDataType());
1717     if (readData.GetBufferDataType() != BUFFER_DATA_INT_32) {
1718         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1719             "WebGL UniformIv not support data type %{public}d", readData.GetBufferDataType());
1720         return NVal::CreateNull(env).val_;
1721     }
1722     GLenum result = 0;
1723     GLsizei count = 0;
1724     GLint* srcData = nullptr;
1725     std::tie(result, count, srcData) = CheckUniformDataInfo<GLint>(IsHighWebGL(), readData, info);
1726     if (result) {
1727         SET_ERROR(result);
1728         return NVal::CreateNull(env).val_;
1729     }
1730     switch (info->dimension) {
1731         case PARAMETERS_NUM_1:
1732             glUniform1iv(location, 1, srcData);
1733             break;
1734         case PARAMETERS_NUM_2:
1735             glUniform2iv(location, count / 2, srcData); // 2 array size
1736             break;
1737         case PARAMETERS_NUM_3:
1738             glUniform3iv(location, count / 3, srcData); // 3 array size
1739             break;
1740         case PARAMETERS_NUM_4:
1741             glUniform4iv(location, count / 4, srcData); // 4 array size
1742             break;
1743         default:
1744             break;
1745     }
1746     return NVal::CreateNull(env).val_;
1747 }
1748 
UniformUiv(napi_env env,napi_value locationObj,napi_value dataObj,const UniformExtInfo * info)1749 napi_value WebGLRenderingContextBaseImpl::UniformUiv(
1750     napi_env env, napi_value locationObj, napi_value dataObj, const UniformExtInfo* info)
1751 {
1752     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1753     if (webGLUniformLocation == nullptr) {
1754         LOGE("WebGL uniform_uiv can not find uniform");
1755         return NVal::CreateNull(env).val_;
1756     }
1757     GLint location = webGLUniformLocation->GetUniformLocationId();
1758 
1759     WebGLReadBufferArg readData(env);
1760     napi_status status = readData.GenBufferData(dataObj, BUFFER_DATA_UINT_32);
1761     if (status != napi_ok) {
1762         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GenBufferData failed.");
1763         return NVal::CreateNull(env).val_;
1764     }
1765     readData.DumpBuffer(readData.GetBufferDataType());
1766     if (readData.GetBufferDataType() != BUFFER_DATA_UINT_32) {
1767         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GetBufferDataType failed. %{public}d",
1768             readData.GetBufferDataType());
1769         return NVal::CreateNull(env).val_;
1770     }
1771     GLenum result = 0;
1772     GLsizei count = 0;
1773     GLuint* srcData = nullptr;
1774     std::tie(result, count, srcData) = CheckUniformDataInfo<GLuint>(IsHighWebGL(), readData, info);
1775     if (result) {
1776         SET_ERROR(result);
1777         return NVal::CreateNull(env).val_;
1778     }
1779     switch (info->dimension) {
1780         case PARAMETERS_NUM_1:
1781             glUniform1uiv(location, 1, srcData);
1782             break;
1783         case PARAMETERS_NUM_2:
1784             glUniform2uiv(location, count / PARAMETERS_NUM_2, srcData);
1785             break;;
1786         case PARAMETERS_NUM_3:
1787             glUniform3uiv(location, count / PARAMETERS_NUM_3, srcData);
1788             break;
1789         case PARAMETERS_NUM_4:
1790             glUniform4uiv(location, count / PARAMETERS_NUM_4, srcData);
1791             break;
1792         default:
1793             break;
1794     }
1795     return NVal::CreateNull(env).val_;
1796 }
1797 
HandleUniformMatrixInfo(GLboolean transpose,const UniformExtInfo * info,GLint location,GLsizei count,GLfloat * srcData)1798 void WebGLRenderingContextBaseImpl::HandleUniformMatrixInfo(
1799     GLboolean transpose, const UniformExtInfo* info, GLint location, GLsizei count, GLfloat* srcData)
1800 {
1801     switch (info->dimension) {
1802         case WebGLArg::MATRIX_2X2_REQUIRE_MIN_SIZE:
1803             glUniformMatrix2fv(location, count / 4, transpose, srcData); // 4 is 2x2
1804             break;
1805         case WebGLArg::MATRIX_3X3_REQUIRE_MIN_SIZE:
1806             glUniformMatrix3fv(location, count / 8, transpose, srcData); // 8 is 2x2x2
1807             break;
1808         case WebGLArg::MATRIX_4X4_REQUIRE_MIN_SIZE:
1809             glUniformMatrix4fv(location, count / 16, transpose, srcData); // 16 is 2x2x2x2
1810             break;
1811         case WebGLArg::MATRIX_3X2_REQUIRE_MIN_SIZE:
1812             glUniformMatrix3x2fv(location, count / 6, transpose, srcData); // 6 matrix
1813             break;
1814         case WebGLArg::MATRIX_4X2_REQUIRE_MIN_SIZE:
1815             glUniformMatrix4x2fv(location, count / 8, transpose, srcData); // 8 matrix
1816             break;
1817         case WebGLArg::MATRIX_2X3_REQUIRE_MIN_SIZE:
1818             glUniformMatrix2x3fv(location, count / 6, transpose, srcData); // 6 matrix
1819             break;
1820         case WebGLArg::MATRIX_4X3_REQUIRE_MIN_SIZE:
1821             glUniformMatrix4x3fv(location, count / 12, transpose, srcData); // 12 matrix
1822             break;
1823         case WebGLArg::MATRIX_2X4_REQUIRE_MIN_SIZE:
1824             glUniformMatrix2x4fv(location, count / 8, transpose, srcData); // 8 matrix
1825             break;
1826         case WebGLArg::MATRIX_3X4_REQUIRE_MIN_SIZE:
1827             glUniformMatrix3x4fv(location, count / 12, transpose, srcData); // 12 matrix
1828             break;
1829         default:
1830             break;
1831     }
1832 }
1833 
UniformMatrixFv(napi_env env,napi_value locationObj,napi_value data,GLboolean transpose,const UniformExtInfo * info)1834 napi_value WebGLRenderingContextBaseImpl::UniformMatrixFv(
1835     napi_env env, napi_value locationObj, napi_value data, GLboolean transpose, const UniformExtInfo* info)
1836 {
1837     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1838     if (webGLUniformLocation == nullptr) {
1839         LOGE("WebGL uniformMatrix_fv can not find uniform");
1840         return NVal::CreateNull(env).val_;
1841     }
1842     GLint location = webGLUniformLocation->GetUniformLocationId();
1843 
1844     WebGLReadBufferArg readData(env);
1845     napi_status status = readData.GenBufferData(data, BUFFER_DATA_FLOAT_32);
1846     if (status != napi_ok) {
1847         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1848             "WebGL uniformMatrix_fv failed to getbuffer data");
1849         return NVal::CreateNull(env).val_;
1850     }
1851     readData.DumpBuffer(readData.GetBufferDataType());
1852 
1853     if (readData.GetBufferDataType() != BUFFER_DATA_FLOAT_32) {
1854         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1855             "WebGL uniformMatrix_fv not support data type %{public}d", readData.GetBufferDataType());
1856         return NVal::CreateNull(env).val_;
1857     }
1858     GLenum result = 0;
1859     GLsizei count = 0;
1860     GLfloat* srcData = nullptr;
1861     std::tie(result, count, srcData) = CheckUniformDataInfo<GLfloat>(IsHighWebGL(), readData, info);
1862     if (result) {
1863         SET_ERROR(result);
1864         return NVal::CreateNull(env).val_;
1865     }
1866     HandleUniformMatrixInfo(transpose, info, location, count, srcData);
1867     LOGD("WebGL uniformMatrix_fv location %{public}d result %{public}u", location, GetError_());
1868     return NVal::CreateNull(env).val_;
1869 }
1870 
CheckFrameBufferStatus(napi_env env,GLenum target)1871 napi_value WebGLRenderingContextBaseImpl::CheckFrameBufferStatus(napi_env env, GLenum target)
1872 {
1873     uint32_t index = 0;
1874     if (!CheckFrameBufferTarget(env, target, index)) {
1875         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1876         return NVal::CreateInt64(env, 0).val_;
1877     }
1878     WebGLFramebuffer* framebufferBinding = GetBoundFrameBuffer(env, target);
1879     if (!framebufferBinding) {
1880         return NVal::CreateInt64(env, WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE).val_;
1881     }
1882     GLenum result = framebufferBinding->CheckStatus(env, this);
1883     if (result != WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE) {
1884         return NVal::CreateInt64(env, static_cast<int64_t>(result)).val_;
1885     }
1886     result = glCheckFramebufferStatus(target);
1887     LOGD("WebGL checkFramebufferStatus target %{public}u result %{public}u", target, result);
1888     return NVal::CreateInt64(env, static_cast<int64_t>(result)).val_;
1889 }
1890 
DepthMask(napi_env env,bool flag)1891 napi_value WebGLRenderingContextBaseImpl::DepthMask(napi_env env, bool flag)
1892 {
1893     LOGD("WebGL depthMask flag %{public}d", flag);
1894     depthMask_ = flag;
1895     glDepthMask(static_cast<GLboolean>(flag));
1896     return NVal::CreateNull(env).val_;
1897 }
1898 
StencilMask(napi_env env,GLuint mask)1899 napi_value WebGLRenderingContextBaseImpl::StencilMask(napi_env env, GLuint mask)
1900 {
1901     LOGD("WebGL stencilMask mask %{public}u", mask);
1902     stencilMask_[0] = mask;
1903     stencilMask_[1] = mask;
1904     glStencilMask(mask);
1905     return NVal::CreateNull(env).val_;
1906 }
1907 
StencilMaskSeparate(napi_env env,GLenum face,GLuint mask)1908 napi_value WebGLRenderingContextBaseImpl::StencilMaskSeparate(napi_env env, GLenum face, GLuint mask)
1909 {
1910     LOGD("WebGL stencilMaskSeparate face %{public}u mask %{public}u", face, mask);
1911     switch (face) {
1912         case WebGLRenderingContextBase::FRONT_AND_BACK: {
1913             stencilMask_[0] = mask;
1914             stencilMask_[1] = mask;
1915             break;
1916         }
1917         case WebGLRenderingContextBase::FRONT:
1918             stencilMask_[0] = mask;
1919             break;
1920         case WebGLRenderingContextBase::BACK:
1921             stencilMask_[1] = mask;
1922             break;
1923         default:
1924             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1925             return NVal::CreateNull(env).val_;
1926     }
1927     glStencilMaskSeparate(face, mask);
1928     return NVal::CreateNull(env).val_;
1929 }
1930 
StencilFunc(napi_env env,GLenum func,GLint ref,GLuint mask)1931 napi_value WebGLRenderingContextBaseImpl::StencilFunc(napi_env env, GLenum func, GLint ref, GLuint mask)
1932 {
1933     LOGD("WebGL stencilFunc func %{public}u %{public}d %{public}u", func, ref, mask);
1934     if (!CheckGLenum(func,
1935         { WebGLRenderingContextBase::NEVER, WebGLRenderingContextBase::LESS, WebGLRenderingContextBase::EQUAL,
1936             WebGLRenderingContextBase::LEQUAL, WebGLRenderingContextBase::GREATER,
1937             WebGLRenderingContextBase::NOTEQUAL, WebGLRenderingContextBase::GEQUAL,
1938             WebGLRenderingContextBase::ALWAYS }, {})) {
1939         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1940         return NVal::CreateNull(env).val_;
1941     }
1942     stencilFuncRef_[0] = ref;
1943     stencilFuncRef_[1] = ref;
1944     stencilFuncMask_[0] = mask;
1945     stencilFuncMask_[1] = mask;
1946     glStencilFunc(func, ref, mask);
1947     return NVal::CreateNull(env).val_;
1948 }
1949 
StencilFuncSeparate(napi_env env,GLenum face,GLenum func,GLint ref,GLuint mask)1950 napi_value WebGLRenderingContextBaseImpl::StencilFuncSeparate(
1951     napi_env env, GLenum face, GLenum func, GLint ref, GLuint mask)
1952 {
1953     LOGD("WebGL stencilFuncSeparate face %{public}u func %{public}u %{public}d %{public}u", face, func, ref, mask);
1954     switch (face) {
1955         case WebGLRenderingContextBase::FRONT_AND_BACK: {
1956             stencilFuncRef_[0] = ref;
1957             stencilFuncRef_[1] = ref;
1958             stencilFuncMask_[0] = mask;
1959             stencilFuncMask_[1] = mask;
1960             break;
1961         }
1962         case WebGLRenderingContextBase::FRONT: {
1963             stencilFuncRef_[0] = ref;
1964             stencilFuncMask_[0] = mask;
1965             break;
1966         }
1967         case WebGLRenderingContextBase::BACK: {
1968             stencilFuncRef_[1] = ref;
1969             stencilFuncMask_[1] = mask;
1970             break;
1971         }
1972         default:
1973             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "invalid face %{public}u", face);
1974             return NVal::CreateNull(env).val_;
1975     }
1976     if (!CheckGLenum(func,
1977         { WebGLRenderingContextBase::NEVER, WebGLRenderingContextBase::LESS, WebGLRenderingContextBase::EQUAL,
1978             WebGLRenderingContextBase::LEQUAL, WebGLRenderingContextBase::GREATER,
1979             WebGLRenderingContextBase::NOTEQUAL, WebGLRenderingContextBase::GEQUAL,
1980             WebGLRenderingContextBase::ALWAYS }, {})) {
1981         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1982         return NVal::CreateNull(env).val_;
1983     }
1984     glStencilFuncSeparate(face, func, ref, mask);
1985     return NVal::CreateNull(env).val_;
1986 }
1987 
1988 template<class T>
CheckTexParameter(napi_env env,GLenum target,GLenum pname,T param,bool isFloat)1989 GLenum WebGLRenderingContextBaseImpl::CheckTexParameter(
1990     napi_env env, GLenum target, GLenum pname, T param, bool isFloat)
1991 {
1992     WebGLTexture* textuer = GetBoundTexture(env, target, false);
1993     if (textuer == nullptr) {
1994         return WebGLRenderingContextBase::INVALID_VALUE;
1995     }
1996 
1997     switch (pname) {
1998         case WebGLRenderingContextBase::TEXTURE_MIN_FILTER:
1999         case WebGLRenderingContextBase::TEXTURE_MAG_FILTER:
2000             break;
2001         case WebGL2RenderingContextBase::TEXTURE_WRAP_R: {
2002             if (!IsHighWebGL()) {
2003                 return WebGLRenderingContextBase::INVALID_ENUM;
2004             }
2005             [[fallthrough]];
2006         }
2007         case WebGLRenderingContextBase::TEXTURE_WRAP_S:
2008         case WebGLRenderingContextBase::TEXTURE_WRAP_T: {
2009             if (param == WebGLRenderingContextBase::CLAMP_TO_EDGE ||
2010                 param == WebGLRenderingContextBase::MIRRORED_REPEAT || param == WebGLRenderingContextBase::REPEAT) {
2011                 break;
2012             }
2013             return WebGLRenderingContextBase::INVALID_ENUM;
2014         }
2015         case WebGL2RenderingContextBase::TEXTURE_COMPARE_FUNC:
2016         case WebGL2RenderingContextBase::TEXTURE_COMPARE_MODE:
2017         case WebGL2RenderingContextBase::TEXTURE_BASE_LEVEL:
2018         case WebGL2RenderingContextBase::TEXTURE_MAX_LEVEL:
2019         case WebGL2RenderingContextBase::TEXTURE_MAX_LOD:
2020         case WebGL2RenderingContextBase::TEXTURE_MIN_LOD: {
2021             if (!IsHighWebGL()) {
2022                 return WebGLRenderingContextBase::INVALID_ENUM;
2023             }
2024             break;
2025         }
2026         default:
2027             return WebGLRenderingContextBase::INVALID_ENUM;
2028     }
2029     return WebGLRenderingContextBase::NO_ERROR;
2030 }
2031 
TexParameteri(napi_env env,GLenum target,GLenum pname,GLint param)2032 napi_value WebGLRenderingContextBaseImpl::TexParameteri(napi_env env, GLenum target, GLenum pname, GLint param)
2033 {
2034     GLenum result = CheckTexParameter<GLint>(env, target, pname, param, false);
2035     if (result != WebGLRenderingContextBase::NO_ERROR) {
2036         SET_ERROR(result);
2037         return NVal::CreateNull(env).val_;
2038     }
2039     glTexParameteri(target, pname, static_cast<GLint>(param));
2040     LOGD("WebGL texParameteri target %{public}u %{public}u %{public}d result %{public}u ",
2041         target, pname, param, GetError_());
2042     return NVal::CreateNull(env).val_;
2043 }
2044 
TexParameterf(napi_env env,GLenum target,GLenum pname,GLfloat param)2045 napi_value WebGLRenderingContextBaseImpl::TexParameterf(napi_env env, GLenum target, GLenum pname, GLfloat param)
2046 {
2047     GLenum result = CheckTexParameter<GLfloat>(env, target, pname, param, false);
2048     if (result != WebGLRenderingContextBase::NO_ERROR) {
2049         SET_ERROR(result);
2050         return NVal::CreateNull(env).val_;
2051     }
2052     glTexParameterf(target, pname, static_cast<GLfloat>(param));
2053     LOGD("WebGL texParameterf target %{public}u %{public}u %{public}f result %{public}u ",
2054         target, pname, param, GetError_());
2055     return NVal::CreateNull(env).val_;
2056 }
2057 
GetTexParameter(napi_env env,GLenum target,GLenum pname)2058 napi_value WebGLRenderingContextBaseImpl::GetTexParameter(napi_env env, GLenum target, GLenum pname)
2059 {
2060     WebGLTexture* texture = GetBoundTexture(env, target, false);
2061     if (!texture) {
2062         return NVal::CreateNull(env).val_;
2063     }
2064     if (IsHighWebGL()) {
2065         switch (pname) {
2066             case GL_TEXTURE_WRAP_R:
2067             case GL_TEXTURE_COMPARE_FUNC:
2068             case GL_TEXTURE_COMPARE_MODE:
2069             case GL_TEXTURE_BASE_LEVEL:
2070             case GL_TEXTURE_MAX_LEVEL:
2071             case GL_TEXTURE_IMMUTABLE_LEVELS: {
2072                 GLint params = 0;
2073                 glGetTexParameteriv(target, pname, &params);
2074                 return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
2075             }
2076             case GL_TEXTURE_IMMUTABLE_FORMAT: {
2077                 GLint params = 0;
2078                 glGetTexParameteriv(target, pname, &params);
2079                 return NVal::CreateBool(env, params == 1).val_;
2080             }
2081             case GL_TEXTURE_MAX_LOD:
2082             case GL_TEXTURE_MIN_LOD: {
2083                 GLfloat params = 0.f;
2084                 glGetTexParameterfv(target, pname, &params);
2085                 return NVal::CreateDouble(env, static_cast<double>(params)).val_;
2086             }
2087             default:
2088                 break;
2089         }
2090     }
2091 
2092     switch (pname) {
2093         case WebGLRenderingContextBase::TEXTURE_MAG_FILTER:
2094         case WebGLRenderingContextBase::TEXTURE_MIN_FILTER:
2095         case WebGLRenderingContextBase::TEXTURE_WRAP_S:
2096         case WebGLRenderingContextBase::TEXTURE_WRAP_T: {
2097             GLint params = 0;
2098             glGetTexParameteriv(target, pname, &params);
2099             LOGD("WebGL getTexParameter params %{public}d", params);
2100             return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
2101         }
2102         default:
2103             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
2104             return NVal::CreateNull(env).val_;
2105     }
2106 }
2107 
VertexAttribfv(napi_env env,GLuint index,int32_t count,napi_value dataObj)2108 napi_value WebGLRenderingContextBaseImpl::VertexAttribfv(napi_env env, GLuint index, int32_t count, napi_value dataObj)
2109 {
2110     LOGD("WebGL vertexAttribfv index %{public}u %{public}d", index, count);
2111     WebGLReadBufferArg bufferData(env);
2112     napi_status status = bufferData.GenBufferData(dataObj, BUFFER_DATA_FLOAT_32);
2113     if (status != 0) {
2114         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL vertexAttribfv failed to getbuffer data");
2115         return NVal::CreateNull(env).val_;
2116     }
2117     bufferData.DumpBuffer(bufferData.GetBufferDataType());
2118     if (bufferData.GetBufferDataType() != BUFFER_DATA_FLOAT_32) {
2119         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2120             "WebGL :vertexAttribfv invalid buffer data type = %{public}d",
2121             static_cast<uint32_t>(bufferData.GetBufferDataType()));
2122         return NVal::CreateNull(env).val_;
2123     }
2124 
2125     if (static_cast<int32_t>(bufferData.GetBufferLength() / sizeof(float)) < count) {
2126         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2127             "WebGL vertexAttribfv invalid data length %{public}zu", bufferData.GetBufferLength());
2128         return NVal::CreateNull(env).val_;
2129     }
2130     VertexAttribInfo* info = GetVertexAttribInfo(index);
2131     if (info == nullptr) {
2132         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
2133         return NVal::CreateNull(env).val_;
2134     }
2135 
2136     switch (count) {
2137         case PARAMETERS_NUM_1:
2138             glVertexAttrib1fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2139             break;
2140         case PARAMETERS_NUM_2:
2141             glVertexAttrib2fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2142             break;
2143         case PARAMETERS_NUM_3:
2144             glVertexAttrib3fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2145             break;
2146         case PARAMETERS_NUM_4:
2147             glVertexAttrib4fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2148             break;
2149         default:
2150             break;
2151     }
2152     info->type = BUFFER_DATA_FLOAT_32;
2153     return NVal::CreateNull(env).val_;
2154 }
2155 
VertexAttribf(napi_env env,GLuint index,int32_t count,GLfloat * data)2156 napi_value WebGLRenderingContextBaseImpl::VertexAttribf(napi_env env, GLuint index, int32_t count, GLfloat* data)
2157 {
2158     VertexAttribInfo* info = GetVertexAttribInfo(index);
2159     if (info == nullptr) {
2160         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
2161         return NVal::CreateNull(env).val_;
2162     }
2163     // In GL, we skip setting vertexAttrib0 values.
2164     switch (count) {
2165         case PARAMETERS_NUM_1:
2166             glVertexAttrib1f(index, data[0]);
2167             break;
2168         case PARAMETERS_NUM_2:
2169             glVertexAttrib2f(index, data[0], data[1]);
2170             break;
2171         case PARAMETERS_NUM_3:
2172             glVertexAttrib3f(index, data[0], data[1], data[2]); // 1, 2 index
2173             break;
2174         case PARAMETERS_NUM_4:
2175             glVertexAttrib4f(index, data[0], data[1], data[2], data[3]); // 1, 2, 3 index
2176             break;
2177         default:
2178             break;
2179     }
2180     LOGD("WebGL vertexAttribf index %{public}u count %{public}d result %{public}u", index, count, GetError_());
2181     info->type = BUFFER_DATA_FLOAT_32;
2182     return NVal::CreateNull(env).val_;
2183 }
2184 
GetUniformType(napi_env env,GLuint programId,GLint locationId)2185 GLenum WebGLRenderingContextBaseImpl::GetUniformType(napi_env env, GLuint programId, GLint locationId)
2186 {
2187     GLint maxNameLength = -1;
2188     glGetProgramiv(programId, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
2189     if (maxNameLength <= 0) {
2190         return 0;
2191     }
2192 
2193     GLint activeUniforms = 0;
2194     glGetProgramiv(programId, GL_ACTIVE_UNIFORMS, &activeUniforms);
2195     LOGD("WebGL getUniform maxNameLength %{public}d activeUniforms %{public}d", maxNameLength, activeUniforms);
2196     if (locationId >= activeUniforms) {
2197         return 0;
2198     }
2199     GLenum type = 0;
2200     std::vector<GLchar> name(maxNameLength + 1);
2201     name[maxNameLength] = '\0';
2202     for (int32_t i = 0; i < activeUniforms; i++) {
2203         GLsizei nameLength = 0;
2204         GLint size = -1;
2205         glGetActiveUniform(programId, i, maxNameLength, &nameLength, &size, &type, name.data());
2206         LOGD("WebGL getUniform index %{public}d type 0x%{public}x name %{public}s ", i, type, name.data());
2207         if (locationId == i) {
2208             break;
2209         }
2210     }
2211     return type;
2212 }
2213 
GetUniform(napi_env env,napi_value programObj,napi_value uniformObj)2214 napi_value WebGLRenderingContextBaseImpl::GetUniform(napi_env env, napi_value programObj, napi_value uniformObj)
2215 {
2216     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
2217     WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, uniformObj);
2218     if (webGLUniformLocation == nullptr || webGLProgram == nullptr) {
2219         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2220             "webGLUniformLocation or webGLProgram is nullptr.");
2221         return NVal::CreateNull(env).val_;
2222     }
2223     GLuint programId = webGLProgram->GetProgramId();
2224     GLint locationId = webGLUniformLocation->GetUniformLocationId();
2225     const UniformTypeMap* typeMap = GetUniformTypeMap(GetUniformType(env, programId, locationId));
2226     if (typeMap == nullptr) {
2227         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "typeMap is nullptr.");
2228         return NVal::CreateNull(env).val_;
2229     }
2230     WebGLWriteBufferArg writeBuffer(env);
2231     GLint* data = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(typeMap->length * sizeof(GLfloat)));
2232     if (data == nullptr) {
2233         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "data is nullptr.");
2234         return NVal::CreateNull(env).val_;
2235     }
2236     switch (typeMap->baseType) {
2237         case GL_FLOAT: {
2238             GLfloat* params = reinterpret_cast<GLfloat*>(data);
2239             glGetUniformfv(programId, locationId, params);
2240             if (typeMap->length == 1) {
2241                 return NVal::CreateDouble(env, params[0]).val_;
2242             }
2243             break;
2244         }
2245         case GL_INT: {
2246             glGetUniformiv(programId, locationId, data);
2247             if (typeMap->length == 1) {
2248                 return NVal::CreateInt64(env, data[0]).val_;
2249             }
2250             break;
2251         }
2252         case GL_BOOL: {
2253             glGetUniformiv(programId, locationId, data);
2254             if (typeMap->length == 1) {
2255                 return NVal::CreateBool(env, data[0]).val_;
2256             }
2257             break;
2258         }
2259         case GL_UNSIGNED_INT: {
2260             GLuint* params = reinterpret_cast<GLuint*>(data);
2261             glGetUniformuiv(programId, locationId, params);
2262             if (typeMap->length == 1) {
2263                 return NVal::CreateInt64(env, params[0]).val_;
2264             }
2265             break;
2266         }
2267         default:
2268             break;
2269     }
2270     writeBuffer.DumpBuffer(typeMap->dstType);
2271     return writeBuffer.ToNormalArray(typeMap->srcType, typeMap->dstType);
2272 }
2273 
CheckGLenum(GLenum type,const std::vector<GLenum> & glSupport,const std::vector<GLenum> & g2Support)2274 bool WebGLRenderingContextBaseImpl::CheckGLenum(
2275     GLenum type, const std::vector<GLenum>& glSupport, const std::vector<GLenum>& g2Support)
2276 {
2277     auto it = std::find(glSupport.begin(), glSupport.end(), type);
2278     if (it != glSupport.end()) {
2279         return true;
2280     }
2281     if (!IsHighWebGL()) {
2282         return false;
2283     }
2284     auto it2 = std::find(g2Support.begin(), g2Support.end(), type);
2285     if (it2 != g2Support.end()) {
2286         return true;
2287     }
2288     return false;
2289 }
2290 
CheckInList(GLenum type,const std::vector<GLenum> & glSupport)2291 bool WebGLRenderingContextBaseImpl::CheckInList(GLenum type, const std::vector<GLenum>& glSupport)
2292 {
2293     auto it = std::find(glSupport.begin(), glSupport.end(), type);
2294     if (it != glSupport.end()) {
2295         return true;
2296     }
2297     return false;
2298 }
2299 
CheckCap(napi_env env,GLenum cap)2300 bool WebGLRenderingContextBaseImpl::CheckCap(napi_env env, GLenum cap)
2301 {
2302     return CheckGLenum(cap,
2303         { WebGLRenderingContextBase::BLEND, WebGLRenderingContextBase::CULL_FACE, WebGLRenderingContextBase::DEPTH_TEST,
2304             WebGLRenderingContextBase::DITHER, WebGLRenderingContextBase::POLYGON_OFFSET_FILL,
2305             WebGLRenderingContextBase::SAMPLE_ALPHA_TO_COVERAGE, WebGLRenderingContextBase::SAMPLE_COVERAGE,
2306             WebGLRenderingContextBase::SCISSOR_TEST, WebGLRenderingContextBase::STENCIL_TEST },
2307         { WebGL2RenderingContextBase::RASTERIZER_DISCARD });
2308 }
2309 
CheckInternalFormat(napi_env env,GLenum internalFormat)2310 bool WebGLRenderingContextBaseImpl::CheckInternalFormat(napi_env env, GLenum internalFormat)
2311 {
2312     static const std::vector<GLenum> glSupport = { WebGLRenderingContextBase::RGBA4, WebGLRenderingContextBase::RGB565,
2313         WebGLRenderingContextBase::RGB5_A1, WebGLRenderingContextBase::DEPTH_COMPONENT16,
2314         WebGLRenderingContextBase::STENCIL_INDEX8, WebGLRenderingContextBase::DEPTH_STENCIL };
2315     static const std::vector<GLenum> gl2Support = { WebGL2RenderingContextBase::R8, WebGL2RenderingContextBase::R8UI,
2316         WebGL2RenderingContextBase::R8I, WebGL2RenderingContextBase::R16UI, WebGL2RenderingContextBase::R16I,
2317         WebGL2RenderingContextBase::R32UI, WebGL2RenderingContextBase::R32I,
2318 
2319         WebGL2RenderingContextBase::RG8, WebGL2RenderingContextBase::RG8UI, WebGL2RenderingContextBase::RG8I,
2320         WebGL2RenderingContextBase::RG16UI, WebGL2RenderingContextBase::RG16I, WebGL2RenderingContextBase::RG32UI,
2321         WebGL2RenderingContextBase::RG32I,
2322 
2323         WebGL2RenderingContextBase::RGB8, WebGL2RenderingContextBase::RGBA8, WebGL2RenderingContextBase::SRGB8_ALPHA8,
2324         WebGL2RenderingContextBase::RGB10_A2, WebGL2RenderingContextBase::RGBA8UI, WebGL2RenderingContextBase::RGBA8I,
2325         WebGL2RenderingContextBase::RGB10_A2UI,
2326 
2327         WebGL2RenderingContextBase::RGBA16UI, WebGL2RenderingContextBase::RGBA16I, WebGL2RenderingContextBase::RGBA32I,
2328         WebGL2RenderingContextBase::RGBA32UI, WebGL2RenderingContextBase::DEPTH_COMPONENT24,
2329         WebGL2RenderingContextBase::DEPTH_COMPONENT32F, WebGL2RenderingContextBase::DEPTH24_STENCIL8,
2330         WebGL2RenderingContextBase::DEPTH32F_STENCIL8 };
2331     return CheckGLenum(internalFormat, glSupport, gl2Support);
2332 }
2333 
CheckAttachment(napi_env env,GLenum attachment)2334 bool WebGLRenderingContextBaseImpl::CheckAttachment(napi_env env, GLenum attachment)
2335 {
2336     static const std::vector<GLenum> glSupport = { WebGLRenderingContextBase::COLOR_ATTACHMENT0,
2337         WebGLRenderingContextBase::DEPTH_ATTACHMENT, WebGLRenderingContextBase::STENCIL_ATTACHMENT,
2338         WebGLRenderingContextBase::DEPTH_STENCIL_ATTACHMENT };
2339 
2340     if (!CheckGLenum(attachment, glSupport, {})) {
2341         if (IsHighWebGL()) {
2342             if (attachment < WebGLRenderingContextBase::COLOR_ATTACHMENT0 ||
2343                 attachment > WebGLRenderingContextBase::COLOR_ATTACHMENT0 +
2344                 static_cast<GLenum>(GetMaxColorAttachments())) {
2345                 return false;
2346             }
2347         }
2348     }
2349     return true;
2350 }
2351 
GetBoundTexture(napi_env env,GLenum target,bool cubeMapExt)2352 WebGLTexture* WebGLRenderingContextBaseImpl::GetBoundTexture(napi_env env, GLenum target, bool cubeMapExt)
2353 {
2354     uint32_t index = 0;
2355     switch (target) {
2356         case WebGLRenderingContextBase::TEXTURE_2D:
2357             index = BoundTextureType::TEXTURE_2D;
2358             break;
2359         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_X:
2360         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_X:
2361         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Y:
2362         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Y:
2363         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Z:
2364         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Z: {
2365             if (!cubeMapExt) {
2366                 return nullptr;
2367             }
2368             index = BoundTextureType::TEXTURE_CUBE_MAP;
2369             break;
2370         }
2371         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP: {
2372             if (cubeMapExt) {
2373                 return nullptr;
2374             }
2375             index = BoundTextureType::TEXTURE_CUBE_MAP;
2376             break;
2377         }
2378         case WebGL2RenderingContextBase::TEXTURE_2D_ARRAY: {
2379             if (!IsHighWebGL()) {
2380                 return nullptr;
2381             }
2382             index = BoundTextureType::TEXTURE_2D_ARRAY;
2383             break;
2384         }
2385         case WebGL2RenderingContextBase::TEXTURE_3D: {
2386             if (!IsHighWebGL()) {
2387                 return nullptr;
2388             }
2389             index = BoundTextureType::TEXTURE_3D;
2390             break;
2391         }
2392         default:
2393             return nullptr;
2394     }
2395     if (activeTextureIndex_ >= boundTexture_[index].size()) {
2396         return nullptr;
2397     }
2398 
2399     return GetObjectInstance<WebGLTexture>(env, boundTexture_[index][activeTextureIndex_]);
2400 }
2401 
GetBoundFrameBuffer(napi_env env,GLenum target)2402 WebGLFramebuffer* WebGLRenderingContextBaseImpl::GetBoundFrameBuffer(napi_env env, GLenum target)
2403 {
2404     uint32_t index = 0;
2405     if (!CheckFrameBufferTarget(env, target, index)) {
2406         return nullptr;
2407     }
2408     LOGD("Get bound Frame buffer target %{public}u id %{public}u ", target, boundFrameBufferIds_[index]);
2409     return GetObjectInstance<WebGLFramebuffer>(env, boundFrameBufferIds_[index]);
2410 }
2411 
GetBoundRenderBuffer(napi_env env,GLenum target)2412 WebGLRenderbuffer* WebGLRenderingContextBaseImpl::GetBoundRenderBuffer(napi_env env, GLenum target)
2413 {
2414     uint32_t index = 0;
2415     if (!CheckRenderBufferTarget(env, target, index)) {
2416         return nullptr;
2417     }
2418     LOGD("Get bound render buffer target %{public}u id %{public}u ", target, boundRenderBufferIds_[index]);
2419     return GetObjectInstance<WebGLRenderbuffer>(env, boundRenderBufferIds_[index]);
2420 }
2421 
GetBoundBuffer(napi_env env,GLenum target)2422 WebGLBuffer* WebGLRenderingContextBaseImpl::GetBoundBuffer(napi_env env, GLenum target)
2423 {
2424     uint32_t index = BoundBufferType::ARRAY_BUFFER;
2425     if (!CheckBufferTarget(env, target, index)) {
2426         return nullptr;
2427     }
2428     LOGD("Get bound buffer target %{public}u id %{public}u ", target, boundBufferIds_[index]);
2429     return GetObjectInstance<WebGLBuffer>(env, boundBufferIds_[index]);
2430 }
2431 
CheckDrawMode(napi_env env,GLenum mode)2432 bool WebGLRenderingContextBaseImpl::CheckDrawMode(napi_env env, GLenum mode)
2433 {
2434     return CheckGLenum(mode,
2435         {
2436             WebGLRenderingContextBase::POINTS,
2437             WebGLRenderingContextBase::LINE_STRIP,
2438             WebGLRenderingContextBase::LINE_LOOP,
2439             WebGLRenderingContextBase::LINES,
2440             WebGLRenderingContextBase::TRIANGLE_STRIP,
2441             WebGLRenderingContextBase::TRIANGLE_FAN,
2442             WebGLRenderingContextBase::TRIANGLES
2443         },
2444         {});
2445 }
2446 
CheckFrameBufferTarget(napi_env env,GLenum target,uint32_t & index)2447 bool WebGLRenderingContextBaseImpl::CheckFrameBufferTarget(napi_env env, GLenum target, uint32_t& index)
2448 {
2449     switch (target) {
2450         case WebGLRenderingContextBase::FRAMEBUFFER:
2451             index = BoundFrameBufferType::FRAMEBUFFER;
2452             return true;
2453         default:
2454             break;
2455     }
2456     if (!IsHighWebGL()) {
2457         return false;
2458     }
2459     switch (target) {
2460         case WebGL2RenderingContextBase::DRAW_FRAMEBUFFER:
2461             index = BoundFrameBufferType::DRAW_FRAMEBUFFER;
2462             return true;
2463         case WebGL2RenderingContextBase::READ_FRAMEBUFFER:
2464             index = BoundFrameBufferType::READ_FRAMEBUFFER;
2465             return true;
2466         default:
2467             break;
2468     }
2469     return false;
2470 }
2471 
CheckRenderBufferTarget(napi_env env,GLenum target,uint32_t & index)2472 bool WebGLRenderingContextBaseImpl::CheckRenderBufferTarget(napi_env env, GLenum target, uint32_t& index)
2473 {
2474     switch (target) {
2475         case WebGLRenderingContextBase::RENDERBUFFER:
2476             index = BoundRenderBufferType::RENDERBUFFER;
2477             return true;
2478         default:
2479             break;
2480     }
2481     return false;
2482 }
2483 
CheckTextureTarget(napi_env env,GLenum target,uint32_t & index)2484 bool WebGLRenderingContextBaseImpl::CheckTextureTarget(napi_env env, GLenum target, uint32_t& index)
2485 {
2486     switch (target) {
2487         case WebGLRenderingContextBase::TEXTURE_2D:
2488             index = BoundTextureType::TEXTURE_2D;
2489             break;
2490         case WebGLRenderingContextBase::TEXTURE_CUBE_MAP:
2491             index = BoundTextureType::TEXTURE_CUBE_MAP;
2492             break;
2493         case WebGL2RenderingContextBase::TEXTURE_3D:
2494             index = BoundTextureType::TEXTURE_3D;
2495             break;
2496         case WebGL2RenderingContextBase::TEXTURE_2D_ARRAY:
2497             index = BoundTextureType::TEXTURE_2D_ARRAY;
2498             break;
2499         default:
2500             if (IsHighWebGL()) {
2501                 break;
2502             }
2503             return false;
2504     }
2505     return true;
2506 }
2507 
CheckShaderType(napi_env env,GLenum type,uint32_t & index)2508 bool WebGLRenderingContextBaseImpl::CheckShaderType(napi_env env, GLenum type, uint32_t& index)
2509 {
2510     switch (type) {
2511         case WebGLRenderingContextBase::VERTEX_SHADER:
2512             index = BoundShaderType::VERTEX_SHADER;
2513             break;
2514         case WebGLRenderingContextBase::FRAGMENT_SHADER:
2515             index = BoundShaderType::FRAGMENT_SHADER;
2516             break;
2517         default:
2518             return false;
2519     }
2520     return true;
2521 }
2522 
CheckTexture2DTarget(napi_env env,GLenum target)2523 bool WebGLRenderingContextBaseImpl::CheckTexture2DTarget(napi_env env, GLenum target)
2524 {
2525     return CheckGLenum(target,
2526         { WebGLRenderingContextBase::TEXTURE_2D, WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_X,
2527             WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_X,
2528             WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Y,
2529             WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Y,
2530             WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Z,
2531             WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Z },
2532         {});
2533 }
2534 
CheckBufferTarget(napi_env env,GLenum target,uint32_t & index)2535 bool WebGLRenderingContextBaseImpl::CheckBufferTarget(napi_env env, GLenum target, uint32_t& index)
2536 {
2537     switch (target) {
2538         case WebGLRenderingContextBase::ARRAY_BUFFER:
2539             index = BoundBufferType::ARRAY_BUFFER;
2540             break;
2541         case WebGLRenderingContextBase::ELEMENT_ARRAY_BUFFER:
2542             index = BoundBufferType::ELEMENT_ARRAY_BUFFER;
2543             break;
2544         case WebGL2RenderingContextBase::COPY_READ_BUFFER:
2545             index = BoundBufferType::COPY_READ_BUFFER;
2546             break;
2547         case WebGL2RenderingContextBase::COPY_WRITE_BUFFER:
2548             index = BoundBufferType::COPY_WRITE_BUFFER;
2549             break;
2550         case WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_BUFFER:
2551             index = BoundBufferType::TRANSFORM_FEEDBACK_BUFFER;
2552             break;
2553         case WebGL2RenderingContextBase::UNIFORM_BUFFER:
2554             index = BoundBufferType::UNIFORM_BUFFER;
2555             break;
2556         case WebGL2RenderingContextBase::PIXEL_PACK_BUFFER:
2557             index = BoundBufferType::PIXEL_PACK_BUFFER;
2558             break;
2559         case WebGL2RenderingContextBase::PIXEL_UNPACK_BUFFER:
2560             index = BoundBufferType::PIXEL_UNPACK_BUFFER;
2561             break;
2562         default:
2563             if (IsHighWebGL()) {
2564                 break;
2565             }
2566             return false;
2567     }
2568     return true;
2569 }
2570 
CheckBufferDataUsage(napi_env env,GLenum usage)2571 bool WebGLRenderingContextBaseImpl::CheckBufferDataUsage(napi_env env, GLenum usage)
2572 {
2573     return CheckGLenum(usage, { GL_STREAM_DRAW, GL_STATIC_DRAW, GL_DYNAMIC_DRAW },
2574         { GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_READ, GL_DYNAMIC_COPY });
2575 }
2576 
CheckPixelsFormat(napi_env env,GLenum format)2577 bool WebGLRenderingContextBaseImpl::CheckPixelsFormat(napi_env env, GLenum format)
2578 {
2579     return CheckGLenum(format, { GL_ALPHA, GL_RGB, GL_RGBA },
2580         {
2581             GL_RED,
2582             GL_RED_INTEGER,
2583             GL_RG,
2584             GL_RG_INTEGER,
2585             GL_RGBA,
2586             GL_RGBA_INTEGER,
2587             GL_LUMINANCE_ALPHA,
2588             GL_LUMINANCE,
2589             GL_ALPHA,
2590             GL_RGB,
2591             GL_RGB_INTEGER,
2592         });
2593 }
2594 
CheckPixelsType(napi_env env,GLenum type)2595 bool WebGLRenderingContextBaseImpl::CheckPixelsType(napi_env env, GLenum type)
2596 {
2597     return CheckGLenum(type,
2598         { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, GL_FLOAT,
2599             GL_HALF_FLOAT_OES },
2600         { GL_UNSIGNED_BYTE, GL_BYTE, GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT_5_6_5,
2601             GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, GL_SHORT, GL_UNSIGNED_INT,
2602             GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV, GL_INT
2603         });
2604 }
2605 
CheckStencil(napi_env env)2606 bool WebGLRenderingContextBaseImpl::CheckStencil(napi_env env)
2607 {
2608     if (stencilMask_[0] != stencilMask_[1] || stencilFuncRef_[0] != stencilFuncRef_[1] ||
2609         stencilFuncMask_[0] != stencilFuncMask_[1]) {
2610         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
2611             "front and back stencils settings do not match");
2612         return false;
2613     }
2614     return true;
2615 }
2616 
CheckLocationName(const std::string & name)2617 bool WebGLRenderingContextBaseImpl::CheckLocationName(const std::string& name)
2618 {
2619     if (name.size() > MAX_LOCATION_LENGTH) {
2620         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "check name size failed.%{public}zu",
2621             name.size());
2622         return false;
2623     }
2624     if (!WebGLArg::CheckString(name)) {
2625         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckString failed.");
2626         return false;
2627     }
2628     if (WebGLArg::CheckReservedPrefix(name)) {
2629         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckReservedPrefix failed.");
2630         return false;
2631     }
2632     return true;
2633 }
2634 
CheckRenderBufferStorage(napi_env env,const TexStorageArg & arg)2635 WebGLRenderbuffer* WebGLRenderingContextBaseImpl::CheckRenderBufferStorage(napi_env env, const TexStorageArg& arg)
2636 {
2637     uint32_t index = 0;
2638     if (!CheckRenderBufferTarget(env, arg.target, index)) {
2639         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
2640             "WebGL renderbufferStorage invalid target %{public}u", arg.target);
2641         return nullptr;
2642     }
2643     if (!CheckInternalFormat(env, arg.internalFormat)) {
2644         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
2645             "WebGL renderbufferStorage invalid internalFormat %{public}u", arg.internalFormat);
2646         return nullptr;
2647     }
2648     if (arg.width < 0 || arg.height < 0) {
2649         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2650             "WebGL renderbufferStorage invalid size %{public}d %{public}d", arg.width, arg.height);
2651         return nullptr;
2652     }
2653     WebGLRenderbuffer* renderBuffer = GetObjectInstance<WebGLRenderbuffer>(env, boundRenderBufferIds_[index]);
2654     if (renderBuffer == nullptr) {
2655         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
2656             "WebGL renderbufferStorage can not get bound render buffer Id %{public}u", boundRenderBufferIds_[index]);
2657         return nullptr;
2658     }
2659     return renderBuffer;
2660 }
2661 
CheckProgramLinkStatus(WebGLProgram * program)2662 bool WebGLRenderingContextBaseImpl::CheckProgramLinkStatus(WebGLProgram* program)
2663 {
2664     if (program == nullptr) {
2665         return false;
2666     }
2667     GLint params = 0;
2668     glGetProgramiv(static_cast<GLuint>(program->GetProgramId()), WebGLRenderingContextBase::LINK_STATUS, &params);
2669     if (params) {
2670         return true;
2671     }
2672     return false;
2673 }
2674 
GetUniformTypeMap(GLenum type)2675 const UniformTypeMap* WebGLRenderingContextBaseImpl::GetUniformTypeMap(GLenum type)
2676 {
2677     const static UniformTypeMap baseTypeMap[] = {
2678         { GL_FLOAT, GL_FLOAT, 1, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2679         { GL_FLOAT_VEC2, GL_FLOAT, 2, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2680         { GL_FLOAT_VEC3, GL_FLOAT, 3, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2681         { GL_FLOAT_VEC4, GL_FLOAT, 4, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2682         { GL_FLOAT_MAT2, GL_FLOAT, 4, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2683         { GL_FLOAT_MAT3, GL_FLOAT, 9, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2684         { GL_FLOAT_MAT4, GL_FLOAT, 16, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2685 
2686         { GL_INT, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2687         { GL_INT_VEC2, GL_INT, 2, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2688         { GL_INT_VEC3, GL_INT, 3, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2689         { GL_INT_VEC4, GL_INT, 4, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2690 
2691         { GL_BOOL, GL_BOOL, 1, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2692         { GL_BOOL_VEC2, GL_BOOL, 2, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2693         { GL_BOOL_VEC3, GL_BOOL, 3, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2694         { GL_BOOL_VEC4, GL_BOOL, 4, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2695 
2696         { GL_SAMPLER_2D, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2697         { GL_SAMPLER_CUBE, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2698     };
2699 
2700     const static UniformTypeMap webgl2BaseTypeMap[] = {
2701         { GL_UNSIGNED_INT, GL_UNSIGNED_INT, 1, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2702         { GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT, 2, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2703         { GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT, 3, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2704         { GL_UNSIGNED_INT_VEC4, GL_UNSIGNED_INT, 4, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2705 
2706         { GL_FLOAT_MAT2x3, GL_FLOAT, 6, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2707         { GL_FLOAT_MAT2x4, GL_FLOAT, 8, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2708         { GL_FLOAT_MAT3x2, GL_FLOAT, 6, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2709         { GL_FLOAT_MAT3x4, GL_FLOAT, 12, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2710         { GL_FLOAT_MAT4x2, GL_FLOAT, 8, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2711         { GL_FLOAT_MAT4x3, GL_FLOAT, 12, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2712 
2713         { GL_SAMPLER_3D, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2714         { GL_SAMPLER_2D_ARRAY, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2715     };
2716     for (size_t i = 0; i < sizeof(baseTypeMap) / sizeof(baseTypeMap[0]); i++) {
2717         if (baseTypeMap[i].type == type) {
2718             return &baseTypeMap[i];
2719         }
2720     }
2721     if (!IsHighWebGL()) {
2722         return nullptr;
2723     }
2724     for (size_t i = 0; i < sizeof(webgl2BaseTypeMap) / sizeof(webgl2BaseTypeMap[0]); i++) {
2725         if (webgl2BaseTypeMap[i].type == type) {
2726             return &webgl2BaseTypeMap[i];
2727         }
2728     }
2729     return nullptr;
2730 }
2731 
CheckFrameBufferBoundComplete(napi_env env)2732 GLenum WebGLRenderingContextBaseImpl::CheckFrameBufferBoundComplete(napi_env env)
2733 {
2734     WebGLFramebuffer* framebufferBinding = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
2735     if (framebufferBinding &&
2736         framebufferBinding->CheckStatus(env, this) != WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE) {
2737         return WebGLRenderingContextBase::INVALID_FRAMEBUFFER_OPERATION;
2738     }
2739     GLenum complete = glCheckFramebufferStatus(WebGLRenderingContextBase::FRAMEBUFFER);
2740     LOGD("CheckFrameBufferBoundComplete complete %{public}u", complete);
2741     if (complete != WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE) {
2742         return WebGLRenderingContextBase::INVALID_FRAMEBUFFER_OPERATION;
2743     }
2744     return WebGLRenderingContextBase::NO_ERROR;
2745 }
2746 
CheckReadPixelsArg(napi_env env,const PixelsArg & arg,uint64_t bufferSize)2747 GLenum WebGLRenderingContextBaseImpl::CheckReadPixelsArg(napi_env env, const PixelsArg& arg, uint64_t bufferSize)
2748 {
2749     if (!CheckPixelsFormat(env, arg.format) || !CheckPixelsType(env, arg.type)) {
2750         return WebGLRenderingContextBase::INVALID_ENUM;
2751     }
2752     return 0;
2753 }
2754 
CheckVertexAttribPointer(napi_env env,const VertexAttribArg & vertexInfo)2755 GLenum WebGLRenderingContextBaseImpl::CheckVertexAttribPointer(napi_env env, const VertexAttribArg& vertexInfo)
2756 {
2757     if (vertexInfo.index >= GetMaxVertexAttribs()) {
2758         LOGE("WebGL vertexAttribPointer invalid index %{public}u", vertexInfo.index);
2759         return WebGLRenderingContextBase::INVALID_VALUE;
2760     }
2761     // check size,  4 is max vertexInfo size, 255 is max vertexInfo stride
2762     if (vertexInfo.size < 1 || vertexInfo.size > 4 || vertexInfo.stride < 0 || vertexInfo.stride > 255) {
2763         LOGE("WebGL vertexAttribPointer invalid size %{public}d %{public}d", vertexInfo.size, vertexInfo.stride);
2764         return WebGLRenderingContextBase::INVALID_VALUE;
2765     }
2766     // check offset
2767     WebGLBuffer* webGLBuffer = GetBoundBuffer(env, WebGLRenderingContextBase::ARRAY_BUFFER);
2768     if (webGLBuffer == nullptr || webGLBuffer->GetBufferSize() == 0) {
2769         LOGE("WebGL vertexAttribPointer can not bind buffer %{public}p ", webGLBuffer);
2770         return WebGLRenderingContextBase::INVALID_OPERATION;
2771     }
2772 
2773     // check offset
2774     if (vertexInfo.offset >= static_cast<GLintptr>(webGLBuffer->GetBufferSize())) {
2775         LOGE("WebGL vertexAttribPointer invalid offset %{public}u", vertexInfo.offset);
2776         return WebGLRenderingContextBase::INVALID_VALUE;
2777     }
2778 
2779     uint32_t typeSize = WebGLArg::GetWebGLDataSize(vertexInfo.type);
2780     if ((static_cast<uint32_t>(vertexInfo.stride) & static_cast<uint32_t>(typeSize - 1)) ||
2781         (static_cast<uint32_t>(vertexInfo.offset) & static_cast<uint32_t>(typeSize - 1))) {
2782         return WebGLRenderingContextBase::INVALID_OPERATION;
2783     }
2784     return WebGLRenderingContextBase::NO_ERROR;
2785 }
2786 
GetBoundFrameBufferColorFormat(napi_env env)2787 GLenum WebGLRenderingContextBaseImpl::GetBoundFrameBufferColorFormat(napi_env env)
2788 {
2789     WebGLFramebuffer* frameBuffer = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
2790     if (frameBuffer != nullptr) {
2791         WebGLAttachmentInfo info = {};
2792         if (frameBuffer->GetWebGLAttachmentInfo(env, this, frameBuffer->GetAttachment(GL_COLOR_ATTACHMENT0), info)) {
2793             return info.format;
2794         }
2795     }
2796     auto webGlContextAttributes = webGLRenderingContext_->CreateWebGlContextAttributes();
2797     if (webGlContextAttributes != nullptr && webGlContextAttributes->alpha_) {
2798         return GL_RGBA;
2799     }
2800     return GL_RGB;
2801 }
2802 
GetVertexAttribInfo(GLint index)2803 VertexAttribInfo* WebGLRenderingContextBaseImpl::GetVertexAttribInfo(GLint index)
2804 {
2805     if (index >= static_cast<GLint>(arrayVertexAttribs_.size())) {
2806         LOGE("Invalid index for VertexAttrib %{public}d, max %{public}zu",
2807             index, arrayVertexAttribs_.size());
2808         return nullptr;
2809     }
2810     return &arrayVertexAttribs_[index];
2811 }
2812 
CheckReadBufferMode(GLenum mode)2813 bool WebGLRenderingContextBaseImpl::CheckReadBufferMode(GLenum mode)
2814 {
2815     switch (mode) {
2816         case WebGLRenderingContextBase::BACK:
2817         case WebGLRenderingContextBase::NONE:
2818         case WebGLRenderingContextBase::COLOR_ATTACHMENT0:
2819             return true;
2820         default: {
2821             if (mode < WebGLRenderingContextBase::COLOR_ATTACHMENT0) {
2822                 return false;
2823             }
2824             if (mode > static_cast<GLenum>(WebGLRenderingContextBase::COLOR_ATTACHMENT0 + GetMaxColorAttachments())) {
2825                 return false;
2826             }
2827             break;
2828         }
2829     }
2830     return true;
2831 }
2832 
GetMaxColorAttachments()2833 GLint WebGLRenderingContextBaseImpl::GetMaxColorAttachments()
2834 {
2835     if (!maxColorAttachments_) {
2836         glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments_);
2837     }
2838     LOGD("maxColorAttachments %{public}d", maxColorAttachments_);
2839     return maxColorAttachments_;
2840 }
2841 
GetValidFrameBuffer(napi_env env,napi_value object)2842 WebGLFramebuffer* WebGLRenderingContextBaseImpl::GetValidFrameBuffer(napi_env env, napi_value object)
2843 {
2844     WebGLFramebuffer* webGlFramebuffer = WebGLObject::GetObjectInstance<WebGLFramebuffer>(env, object);
2845     if (webGlFramebuffer == nullptr) {
2846         return nullptr;
2847     }
2848     return GetObjectInstance<WebGLFramebuffer>(env, webGlFramebuffer->GetFramebuffer());
2849 }
2850 
GetValidBuffer(napi_env env,napi_value object)2851 WebGLBuffer* WebGLRenderingContextBaseImpl::GetValidBuffer(napi_env env, napi_value object)
2852 {
2853     WebGLBuffer* buffer = WebGLObject::GetObjectInstance<WebGLBuffer>(env, object);
2854     if (buffer == nullptr) {
2855         return nullptr;
2856     }
2857     return GetObjectInstance<WebGLBuffer>(env, buffer->GetBufferId());
2858 }
2859 
GetValidRenderBuffer(napi_env env,napi_value object)2860 WebGLRenderbuffer* WebGLRenderingContextBaseImpl::GetValidRenderBuffer(napi_env env, napi_value object)
2861 {
2862     WebGLRenderbuffer* renderBuffer = WebGLObject::GetObjectInstance<WebGLRenderbuffer>(env, object);
2863     if (renderBuffer == nullptr) {
2864         return nullptr;
2865     }
2866     return GetObjectInstance<WebGLRenderbuffer>(env, renderBuffer->GetRenderbuffer());
2867 }
2868 } // namespace Impl
2869 } // namespace Rosen
2870 } // namespace OHOS
2871