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/webgl2_rendering_context_impl.h"
16 
17 #include "context/webgl2_rendering_context_base.h"
18 #include "context/webgl_context_attributes.h"
19 #include "context/webgl_rendering_context.h"
20 #include "context/webgl_rendering_context_base.h"
21 #include "context/webgl_rendering_context_basic_base.h"
22 #include "napi/n_class.h"
23 #include "napi/n_func_arg.h"
24 #include "util/egl_manager.h"
25 #include "util/log.h"
26 #include "util/util.h"
27 #include "webgl/webgl_query.h"
28 #include "webgl/webgl_sampler.h"
29 #include "webgl/webgl_shader.h"
30 #include "webgl/webgl_sync.h"
31 #include "webgl/webgl_transform_feedback.h"
32 #include "webgl/webgl_vertex_array_object.h"
33 
34 namespace OHOS {
35 namespace Rosen {
36 namespace Impl {
37 using namespace std;
Init()38 void WebGL2RenderingContextImpl::Init()
39 {
40     WebGLRenderingContextBaseImpl::Init();
41     if (maxSamplerUnit_) {
42         return;
43     }
44     GLint max = 0;
45     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max);
46     maxSamplerUnit_ = static_cast<GLuint>(max);
47     samplerUnits_.resize(max);
48 
49     glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max);
50     maxBoundTransformFeedbackBufferIndex_ = static_cast<GLuint>(max);
51     glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max);
52     maxBoundUniformBufferIndex_ = static_cast<GLuint>(max);
53     LOGD("WebGL2 Init maxBoundTransformFeedbackBufferIndex_ %{public}u, maxBoundUniformBufferIndex_ %{public}u"
54         "maxSamplerUnit_ %{public}d",
55         maxBoundTransformFeedbackBufferIndex_, maxBoundUniformBufferIndex_, max);
56 }
57 
CreateQuery(napi_env env)58 napi_value WebGL2RenderingContextImpl::CreateQuery(napi_env env)
59 {
60     WebGLQuery* webGlQuery = nullptr;
61     napi_value objQuery = WebGLQuery::CreateObjectInstance(env, &webGlQuery).val_;
62     if (webGlQuery == nullptr) {
63         return NVal::CreateNull(env).val_;
64     }
65 
66     uint32_t queryId = 0;
67     glGenQueries(1, &queryId);
68     webGlQuery->SetQuery(queryId);
69     AddObject<WebGLQuery>(env, queryId, objQuery);
70     LOGD("WebGL2 createQuery queryId = %{public}u", queryId);
71     return objQuery;
72 }
73 
DeleteQuery(napi_env env,napi_value object)74 napi_value WebGL2RenderingContextImpl::DeleteQuery(napi_env env, napi_value object)
75 {
76     uint32_t queryId = 0;
77     WebGLQuery* webGlQuery = WebGLObject::GetObjectInstance<WebGLQuery>(env, object);
78     if (webGlQuery == nullptr) {
79         return NVal::CreateNull(env).val_;
80     }
81     queryId = webGlQuery->GetQuery();
82     glDeleteQueries(1, &queryId);
83     DeleteObject<WebGLQuery>(env, queryId);
84     uint32_t index = 0;
85     LOGD("WebGL2 deleteQuery target %{public}u, queryId %{public}u", webGlQuery->GetTarget(), queryId);
86     if (CheckQueryTarget(env, webGlQuery->GetTarget(), index)) {
87         LOGD("WebGL2 deleteQuery currentQuery_ %{public}u", currentQuery_[index]);
88         if (currentQuery_[index] == queryId) {
89             currentQuery_[index] = 0;
90             glEndQuery(webGlQuery->GetTarget());
91         }
92     }
93     return NVal::CreateNull(env).val_;
94 }
95 
IsQuery(napi_env env,napi_value object)96 napi_value WebGL2RenderingContextImpl::IsQuery(napi_env env, napi_value object)
97 {
98     GLuint queryId = 0;
99     WebGLQuery* webGlQuery = WebGLObject::GetObjectInstance<WebGLQuery>(env, object);
100     if (webGlQuery == nullptr) {
101         return NVal::CreateBool(env, false).val_;
102     }
103     queryId = webGlQuery->GetQuery();
104 
105     GLboolean returnValue = glIsQuery(queryId);
106     bool res = static_cast<bool>(returnValue);
107     LOGD("WebGL2 isQuery query %{public}u result %{public}d ", queryId, res);
108     return NVal::CreateBool(env, res).val_;
109 }
110 
GetQuery(napi_env env,GLenum target,GLenum pName)111 napi_value WebGL2RenderingContextImpl::GetQuery(napi_env env, GLenum target, GLenum pName)
112 {
113     LOGD("WebGL2 getQuery target %{public}u %{public}u", target, pName);
114     if (pName != WebGL2RenderingContextBase::CURRENT_QUERY) {
115         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "pName %{public}u", pName);
116         return NVal::CreateNull(env).val_;
117     }
118     uint32_t index = 0;
119     if (!CheckQueryTarget(env, target, index)) {
120         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckQueryTarget failed");
121         return NVal::CreateNull(env).val_;
122     }
123 
124     GLint params = 0;
125     glGetQueryiv(target, pName, &params);
126     LOGD("WebGL2 getQuery params = %{public}d %{public}u", params, currentQuery_[index]);
127     return GetObject<WebGLQuery>(env, params);
128 }
129 
BeginQuery(napi_env env,GLenum target,napi_value object)130 napi_value WebGL2RenderingContextImpl::BeginQuery(napi_env env, GLenum target, napi_value object)
131 {
132     LOGD("WebGL2 beginQuery target %{public}u", target);
133     GLuint queryId = 0;
134     WebGLQuery* webGlQuery = WebGLObject::GetObjectInstance<WebGLQuery>(env, object);
135     if (webGlQuery == nullptr) {
136         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "webGlQuery is nullptr");
137         return NVal::CreateNull(env).val_;
138     }
139     queryId = webGlQuery->GetQuery();
140 
141     if (webGlQuery->GetTarget() && webGlQuery->GetTarget() != target) {
142         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
143             "webGlQuery->GetTarget %{public}u target %{public}u", webGlQuery->GetTarget(), target);
144         return NVal::CreateNull(env).val_;
145     }
146     uint32_t index = 0;
147     if (!CheckQueryTarget(env, target, index)) {
148         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckQueryTarget failed");
149         return NVal::CreateNull(env).val_;
150     }
151 
152     if (currentQuery_[index] && currentQuery_[index] != queryId) {
153         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
154             "currentQuery_[index] %{public}u queryId %{public}u", currentQuery_[index], queryId);
155         return NVal::CreateNull(env).val_;
156     }
157     currentQuery_[index] = queryId;
158     webGlQuery->SetTarget(target);
159 
160     glBeginQuery(target, queryId);
161     LOGD("WebGL2 beginQuery queryId %{public}u result %{public}u", queryId, GetError_());
162     return NVal::CreateNull(env).val_;
163 }
164 
EndQuery(napi_env env,GLenum target)165 napi_value WebGL2RenderingContextImpl::EndQuery(napi_env env, GLenum target)
166 {
167     LOGD("WebGL2 endQuery target %{public}u", target);
168     uint32_t index = 0;
169     if (!CheckQueryTarget(env, target, index)) {
170         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
171         return NVal::CreateNull(env).val_;
172     }
173     if (!currentQuery_[index]) {
174         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
175         return NVal::CreateNull(env).val_;
176     }
177     currentQuery_[index] = 0;
178     glEndQuery(target);
179     return NVal::CreateNull(env).val_;
180 }
181 
GetQueryParameter(napi_env env,napi_value queryObj,GLenum pName)182 napi_value WebGL2RenderingContextImpl::GetQueryParameter(napi_env env, napi_value queryObj, GLenum pName)
183 {
184     GLuint queryId = 0;
185     WebGLQuery* webGlQuery = WebGLObject::GetObjectInstance<WebGLQuery>(env, queryObj);
186     if (webGlQuery == nullptr) {
187         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
188         return NVal::CreateNull(env).val_;
189     }
190     queryId = webGlQuery->GetQuery();
191 
192     GLuint params = 0;
193     switch (pName) {
194         case GL_QUERY_RESULT: {
195             glGetQueryObjectuiv(queryId, pName, &params);
196             int64_t res = static_cast<int64_t>(params);
197             LOGD("WebGL2 getQueryParameter params %{public}u", params);
198             return NVal::CreateInt64(env, res).val_;
199         }
200         case GL_QUERY_RESULT_AVAILABLE: {
201             glGetQueryObjectuiv(queryId, pName, &params);
202             bool res = (params == GL_FALSE) ? false : true;
203             LOGD("WebGL2 getQueryParameter params %{public}u", params);
204             return NVal::CreateBool(env, res).val_;
205         }
206         default : {
207             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
208             return NVal::CreateNull(env).val_;
209         }
210     }
211 }
212 
CreateSampler(napi_env env)213 napi_value WebGL2RenderingContextImpl::CreateSampler(napi_env env)
214 {
215     WebGLSampler* webGlSampler = nullptr;
216     napi_value objSampler = WebGLSampler::CreateObjectInstance(env, &webGlSampler).val_;
217     if (webGlSampler == nullptr) {
218         return NVal::CreateNull(env).val_;
219     }
220     GLuint samplerId = 0;
221     glGenSamplers(1, &samplerId);
222     webGlSampler->SetSampler(samplerId);
223     LOGD("WebGL2 createSampler samplerId = %{public}u", samplerId);
224     AddObject<WebGLSampler>(env, samplerId, objSampler);
225     return objSampler;
226 }
227 
DeleteSampler(napi_env env,napi_value samplerObj)228 napi_value WebGL2RenderingContextImpl::DeleteSampler(napi_env env, napi_value samplerObj)
229 {
230     WebGLSampler* sampler = WebGLObject::GetObjectInstance<WebGLSampler>(env, samplerObj);
231     if (sampler == nullptr) {
232         return NVal::CreateNull(env).val_;
233     }
234     GLuint samplerId = sampler->GetSampler();
235     LOGD("WebGL2 deleteSampler samplerId = %{public}u", samplerId);
236     // delete
237     glBindSampler(sampler->GetSampleUnit(), 0);
238 
239     samplerUnits_[sampler->GetSampleUnit()] = 0;
240     glDeleteSamplers(1, &samplerId);
241     sampler->SetSampleUnit(0);
242     DeleteObject<WebGLSampler>(env, samplerId);
243     return NVal::CreateNull(env).val_;
244 }
245 
IsSampler(napi_env env,napi_value samplerObj)246 napi_value WebGL2RenderingContextImpl::IsSampler(napi_env env, napi_value samplerObj)
247 {
248     WebGLSampler* sampler = WebGLObject::GetObjectInstance<WebGLSampler>(env, samplerObj);
249     if (sampler == nullptr) {
250         return NVal::CreateBool(env, false).val_;
251     }
252     GLuint samplerId = sampler->GetSampler();
253 
254     GLboolean returnValue = glIsSampler(samplerId);
255     bool res = static_cast<bool>(returnValue);
256     LOGD("WebGL2 IsSampler samplerId = %{public}u res %{public}d", samplerId, res);
257     return NVal::CreateBool(env, res).val_;
258 }
259 
BindSampler(napi_env env,GLuint unit,napi_value samplerObj)260 napi_value WebGL2RenderingContextImpl::BindSampler(napi_env env, GLuint unit, napi_value samplerObj)
261 {
262     WebGLSampler* sampler = WebGLObject::GetObjectInstance<WebGLSampler>(env, samplerObj);
263     if (sampler == nullptr) {
264         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
265         return NVal::CreateNull(env).val_;
266     }
267     GLuint samplerId = sampler->GetSampler();
268     if (unit >= samplerUnits_.size()) {
269         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
270         return NVal::CreateNull(env).val_;
271     }
272     sampler->SetSampleUnit(unit);
273     glBindSampler(unit, samplerId);
274     samplerUnits_[unit] = samplerId;
275     LOGD("WebGL2 bindSampler unit = %{public}u samplerId = %{public}u", unit, samplerId);
276     return NVal::CreateNull(env).val_;
277 }
278 
SamplerParameter(napi_env env,napi_value samplerObj,GLenum pName,bool isFloat,void * param)279 napi_value WebGL2RenderingContextImpl::SamplerParameter(
280     napi_env env, napi_value samplerObj, GLenum pName, bool isFloat, void* param)
281 {
282     LOGD("WebGL2 samplerParameteri pname %{public}u", pName);
283     WebGLSampler* sampler = WebGLObject::GetObjectInstance<WebGLSampler>(env, samplerObj);
284     if (sampler == nullptr) {
285         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
286         return NVal::CreateNull(env).val_;
287     }
288     GLuint samplerId = sampler->GetSampler();
289     switch (pName) {
290         case GL_TEXTURE_COMPARE_FUNC:
291         case GL_TEXTURE_COMPARE_MODE:
292         case GL_TEXTURE_MAG_FILTER:
293         case GL_TEXTURE_MIN_FILTER:
294         case GL_TEXTURE_WRAP_R:
295         case GL_TEXTURE_WRAP_S:
296         case GL_TEXTURE_WRAP_T:
297         case GL_TEXTURE_MAX_LOD:
298         case GL_TEXTURE_MIN_LOD:
299             break;
300         default:
301             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
302             return NVal::CreateNull(env).val_;
303     }
304     if (isFloat) {
305         GLfloat v = *static_cast<GLfloat*>(param);
306         glSamplerParameterf(samplerId, pName, v);
307     } else {
308         GLint v = *static_cast<GLint*>(param);
309         glSamplerParameteri(samplerId, pName, v);
310     }
311     return NVal::CreateNull(env).val_;
312 }
313 
GetSamplerParameter(napi_env env,napi_value samplerObj,GLenum pName)314 napi_value WebGL2RenderingContextImpl::GetSamplerParameter(napi_env env, napi_value samplerObj, GLenum pName)
315 {
316     WebGLSampler* sampler = WebGLObject::GetObjectInstance<WebGLSampler>(env, samplerObj);
317     if (sampler == nullptr) {
318         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
319         return NVal::CreateNull(env).val_;
320     }
321     GLuint samplerId = sampler->GetSampler();
322     switch (pName) {
323         case GL_TEXTURE_COMPARE_FUNC:
324         case GL_TEXTURE_COMPARE_MODE:
325         case GL_TEXTURE_MAG_FILTER:
326         case GL_TEXTURE_MIN_FILTER:
327         case GL_TEXTURE_WRAP_R:
328         case GL_TEXTURE_WRAP_S:
329         case GL_TEXTURE_WRAP_T: {
330             GLint params;
331             glGetSamplerParameteriv(static_cast<GLuint>(samplerId), static_cast<GLenum>(pName), &params);
332             int64_t res = static_cast<int64_t>(params);
333             LOGD("WebGL2 getSamplerParameter samplerId %{public}u params %{public}d", samplerId, params);
334             return NVal::CreateInt64(env, res).val_;
335         }
336         case GL_TEXTURE_MAX_LOD:
337         case GL_TEXTURE_MIN_LOD: {
338             GLfloat params;
339             glGetSamplerParameterfv(static_cast<GLuint>(samplerId), static_cast<GLenum>(pName), &params);
340             float res = static_cast<float>(params);
341             LOGD("WebGL2 getSamplerParameter samplerId %{public}u params %{public}f", samplerId, params);
342             return NVal::CreateDouble(env, (double)res).val_;
343         }
344         default:
345             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
346             return NVal::CreateNull(env).val_;
347     }
348 }
349 
CreateVertexArray(napi_env env)350 napi_value WebGL2RenderingContextImpl::CreateVertexArray(napi_env env)
351 {
352     WebGLVertexArrayObject* webGLVertexArrayObject = nullptr;
353     napi_value objVertexArrayObject = WebGLVertexArrayObject::CreateObjectInstance(env, &webGLVertexArrayObject).val_;
354     if (webGLVertexArrayObject == nullptr) {
355         return NVal::CreateNull(env).val_;
356     }
357     uint32_t vertexArraysId = 0;
358     glGenVertexArrays(1, &vertexArraysId);
359 
360     webGLVertexArrayObject->SetVertexArrays(vertexArraysId);
361     LOGD("WebGL2 createVertexArray vertexArraysId = %{public}u", vertexArraysId);
362     AddObject<WebGLVertexArrayObject>(env, vertexArraysId, objVertexArrayObject);
363     return objVertexArrayObject;
364 }
365 
DeleteVertexArray(napi_env env,napi_value object)366 napi_value WebGL2RenderingContextImpl::DeleteVertexArray(napi_env env, napi_value object)
367 {
368     uint32_t vertexArrays = WebGLVertexArrayObject::DEFAULT_VERTEX_ARRAY_OBJECT;
369     WebGLVertexArrayObject* webGLVertexArrayObject =
370         WebGLObject::GetObjectInstance<WebGLVertexArrayObject>(env, object);
371     if (webGLVertexArrayObject == nullptr) {
372         return NVal::CreateNull(env).val_;
373     }
374     vertexArrays = webGLVertexArrayObject->GetVertexArrays();
375     if (boundVertexArrayId_ && boundVertexArrayId_ == vertexArrays) {
376         boundVertexArrayId_ = 0;
377     }
378     glDeleteVertexArrays(1, &vertexArrays);
379     LOGD("WebGL2 deleteVertexArrays vertexArrays %{public}u", vertexArrays);
380     DeleteObject<WebGLVertexArrayObject>(env, vertexArrays);
381     return NVal::CreateNull(env).val_;
382 }
383 
IsVertexArray(napi_env env,napi_value object)384 napi_value WebGL2RenderingContextImpl::IsVertexArray(napi_env env, napi_value object)
385 {
386     GLuint vertexArrayId = WebGLVertexArrayObject::DEFAULT_VERTEX_ARRAY_OBJECT;
387     WebGLVertexArrayObject* webGLVertexArrayObject =
388         WebGLObject::GetObjectInstance<WebGLVertexArrayObject>(env, object);
389     if (webGLVertexArrayObject == nullptr) {
390         return NVal::CreateBool(env, false).val_;
391     }
392     vertexArrayId = webGLVertexArrayObject->GetVertexArrays();
393     GLboolean returnValue = glIsVertexArray(vertexArrayId);
394     LOGD("WebGL2 isVertexArray %{public}u %{public}d", vertexArrayId, returnValue);
395     return NVal::CreateBool(env, returnValue).val_;
396 }
397 
BindVertexArray(napi_env env,napi_value object)398 napi_value WebGL2RenderingContextImpl::BindVertexArray(napi_env env, napi_value object)
399 {
400     GLuint vertexArrayId = WebGLVertexArrayObject::DEFAULT_VERTEX_ARRAY_OBJECT;
401     WebGLVertexArrayObject* webGLVertexArrayObject =
402         WebGLObject::GetObjectInstance<WebGLVertexArrayObject>(env, object);
403     if (webGLVertexArrayObject == nullptr) {
404         return NVal::CreateNull(env).val_;
405     }
406     vertexArrayId = webGLVertexArrayObject->GetVertexArrays();
407     glBindVertexArray(vertexArrayId);
408     boundVertexArrayId_ = vertexArrayId;
409     LOGD("WebGL2 bindVertexArray %{public}u ", vertexArrayId);
410     return NVal::CreateNull(env).val_;
411 }
412 
FenceSync(napi_env env,GLenum condition,GLbitfield flags)413 napi_value WebGL2RenderingContextImpl::FenceSync(napi_env env, GLenum condition, GLbitfield flags)
414 {
415     WebGLSync* webGlSync = nullptr;
416     napi_value objSync = WebGLSync::CreateObjectInstance(env, &webGlSync).val_;
417     if (webGlSync == nullptr) {
418         return NVal::CreateNull(env).val_;
419     }
420     GLsync returnValue = glFenceSync(condition, flags);
421     webGlSync->SetSync(reinterpret_cast<int64_t>(returnValue));
422     LOGD("WebGL2 fenceSync syncId %{public}" PRIi64 " result %{public}u condition %{public}u flags %{public}u",
423         reinterpret_cast<int64_t>(returnValue), GetError_(), condition, flags);
424     return objSync;
425 }
426 
IsSync(napi_env env,napi_value syncObj)427 napi_value WebGL2RenderingContextImpl::IsSync(napi_env env, napi_value syncObj)
428 {
429     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
430     if (webGlSync == nullptr) {
431         return NVal::CreateBool(env, false).val_;
432     }
433     int64_t syncId = webGlSync->GetSync();
434     GLboolean returnValue = glIsSync(reinterpret_cast<GLsync>(syncId));
435     LOGD("WebGL2 isSync syncId %{public}" PRIi64 " result %{public}d", syncId, returnValue);
436     return NVal::CreateBool(env, static_cast<bool>(returnValue)).val_;
437 }
438 
DeleteSync(napi_env env,napi_value syncObj)439 napi_value WebGL2RenderingContextImpl::DeleteSync(napi_env env, napi_value syncObj)
440 {
441     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
442     if (webGlSync == nullptr) {
443         return NVal::CreateNull(env).val_;
444     }
445     int64_t syncId = webGlSync->GetSync();
446     glDeleteSync(reinterpret_cast<GLsync>(syncId));
447     LOGD("WebGL2 deleteSync syncId %{public}" PRIi64, syncId);
448     return NVal::CreateNull(env).val_;
449 }
450 
ClientWaitSync(napi_env env,napi_value syncObj,GLbitfield flags,GLint64 timeout)451 napi_value WebGL2RenderingContextImpl::ClientWaitSync(
452     napi_env env, napi_value syncObj, GLbitfield flags, GLint64 timeout)
453 {
454     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
455     if (webGlSync == nullptr) {
456         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGlSync is nullptr");
457         return NVal::CreateInt64(env, WebGL2RenderingContextBase::WAIT_FAILED).val_;
458     }
459     int64_t syncId = webGlSync->GetSync();
460     if (timeout < WebGL2RenderingContextBase::TIMEOUT_IGNORED) {
461         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "timeout %{pulic}" PRIi64, timeout);
462         return NVal::CreateInt64(env, WebGL2RenderingContextBase::WAIT_FAILED).val_;
463     }
464     GLuint64 timeout64 = (timeout == -1) ? GL_TIMEOUT_IGNORED : static_cast<GLuint64>(timeout);
465     GLenum returnValue = glClientWaitSync(reinterpret_cast<GLsync>(syncId), flags, timeout64);
466     LOGD("WebGL2 clientWaitSync syncId = %{public}d %{public}u result %{public}u",
467          static_cast<int>(syncId), returnValue, GetError_());
468     return NVal::CreateInt64(env, static_cast<int64_t>(returnValue)).val_;
469 }
470 
WaitSync(napi_env env,napi_value syncObj,GLbitfield flags,GLint64 timeout)471 napi_value WebGL2RenderingContextImpl::WaitSync(napi_env env, napi_value syncObj, GLbitfield flags, GLint64 timeout)
472 {
473     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
474     if (webGlSync == nullptr) {
475         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGlSync is nullptr");
476         return NVal::CreateNull(env).val_;
477     }
478     int64_t syncId = webGlSync->GetSync();
479     if (timeout < WebGL2RenderingContextBase::TIMEOUT_IGNORED) {
480         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "timeout %{pulic}" PRIi64, timeout);
481         return NVal::CreateNull(env).val_;
482     }
483     GLuint64 timeout64 = (timeout == -1) ? GL_TIMEOUT_IGNORED : static_cast<GLuint64>(timeout);
484     glWaitSync(reinterpret_cast<GLsync>(syncId), flags, timeout64);
485     LOGD("WebGL2 waitSync GL_TIMEOUT_IGNORED %{public}u", static_cast<unsigned int>(GL_TIMEOUT_IGNORED));
486     return NVal::CreateNull(env).val_;
487 }
488 
GetSyncParameter(napi_env env,napi_value syncObj,GLenum pname)489 napi_value WebGL2RenderingContextImpl::GetSyncParameter(napi_env env, napi_value syncObj, GLenum pname)
490 {
491     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
492     if (webGlSync == nullptr) {
493         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
494         return NVal::CreateNull(env).val_;
495     }
496     int64_t syncId = webGlSync->GetSync();
497     LOGD("WebGL2 getSyncParameter syncId %{public}" PRIi64 " pname %{public}u ", syncId, pname);
498     if (CheckInList(pname, { GL_OBJECT_TYPE, GL_SYNC_STATUS, GL_SYNC_CONDITION, GL_SYNC_FLAGS })) {
499         GLint value = 0;
500         GLsizei length = -1;
501         glGetSynciv(reinterpret_cast<GLsync>(syncId), pname, 1, &length, &value);
502         LOGD("WebGL2 getSyncParameter value %{public}d ", value);
503         return NVal::CreateInt64(env, value).val_;
504     } else {
505         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
506         return NVal::CreateNull(env).val_;
507     }
508 }
509 
CreateTransformFeedback(napi_env env)510 napi_value WebGL2RenderingContextImpl::CreateTransformFeedback(napi_env env)
511 {
512     WebGLTransformFeedback* webGlTransformFeedback = nullptr;
513     napi_value objTransformFeedback = WebGLTransformFeedback::CreateObjectInstance(env, &webGlTransformFeedback).val_;
514     if (webGlTransformFeedback == nullptr) {
515         return NVal::CreateNull(env).val_;
516     }
517     GLuint transformFeedbackId = 0;
518     glGenTransformFeedbacks(1, &transformFeedbackId);
519     webGlTransformFeedback->SetTransformFeedback(transformFeedbackId);
520     LOGD("WebGL2 createTransformFeedback transformFeedbackId %{public}u", transformFeedbackId);
521     AddObject<WebGLTransformFeedback>(env, transformFeedbackId, objTransformFeedback);
522     return objTransformFeedback;
523 }
524 
DeleteTransformFeedback(napi_env env,napi_value obj)525 napi_value WebGL2RenderingContextImpl::DeleteTransformFeedback(napi_env env, napi_value obj)
526 {
527     uint32_t transformFeedbackId = WebGLTransformFeedback::DEFAULT_TRANSFORM_FEEDBACK;
528     WebGLTransformFeedback* webGlTransformFeedback = WebGLObject::GetObjectInstance<WebGLTransformFeedback>(env, obj);
529     if (webGlTransformFeedback == nullptr) {
530         return NVal::CreateNull(env).val_;
531     }
532     transformFeedbackId = webGlTransformFeedback->GetTransformFeedback();
533     DeleteObject<WebGLTransformFeedback>(env, transformFeedbackId);
534     glDeleteTransformFeedbacks(1, &transformFeedbackId);
535     LOGD("WebGL2 deleteTransformFeedback transformFeedbackId %{public}u", transformFeedbackId);
536     if (boundTransformFeedback_ != transformFeedbackId) {
537         LOGE("WebGL2 bindTransformFeedback bound %{public}u", boundTransformFeedback_);
538     }
539     boundTransformFeedback_ = 0;
540     return NVal::CreateNull(env).val_;
541 }
542 
IsTransformFeedback(napi_env env,napi_value obj)543 napi_value WebGL2RenderingContextImpl::IsTransformFeedback(napi_env env, napi_value obj)
544 {
545     WebGLTransformFeedback* webGlTransformFeedback = WebGLObject::GetObjectInstance<WebGLTransformFeedback>(env, obj);
546     if (webGlTransformFeedback == nullptr) {
547         return NVal::CreateBool(env, false).val_;
548     }
549     GLuint transformFeedbackId = webGlTransformFeedback->GetTransformFeedback();
550     LOGD("WebGL2 isTransformFeedback transformFeedbackId %{public}u bound %{public}u",
551         transformFeedbackId, boundTransformFeedback_);
552     if (GetObjectInstance<WebGLTransformFeedback>(env, transformFeedbackId) != nullptr &&
553         boundTransformFeedback_ == transformFeedbackId) {
554         return NVal::CreateBool(env, true).val_;
555     }
556     return NVal::CreateBool(env, false).val_;
557 }
558 
BindTransformFeedback(napi_env env,napi_value obj,GLenum target)559 napi_value WebGL2RenderingContextImpl::BindTransformFeedback(napi_env env, napi_value obj, GLenum target)
560 {
561     WebGLTransformFeedback* webGlTransformFeedback = WebGLObject::GetObjectInstance<WebGLTransformFeedback>(env, obj);
562     if (webGlTransformFeedback == nullptr) {
563         return NVal::CreateBool(env, false).val_;
564     }
565     GLuint transformFeedbackId = webGlTransformFeedback->GetTransformFeedback();
566     if (target != GL_TRANSFORM_FEEDBACK) {
567         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
568         return NVal::CreateNull(env).val_;
569     }
570     if (boundTransformFeedback_ && boundTransformFeedback_ != transformFeedbackId) {
571         LOGE("WebGL2 bindTransformFeedback has been bound %{public}u", boundTransformFeedback_);
572     }
573     boundTransformFeedback_ = transformFeedbackId;
574     glBindTransformFeedback(target, transformFeedbackId);
575     LOGD("WebGL2 bindTransformFeedback id %{public}u target %{public}u result %{public}u",
576         transformFeedbackId, target, GetError_());
577     if (webGlTransformFeedback) {
578         webGlTransformFeedback->SetTarget(target);
579     }
580     return NVal::CreateNull(env).val_;
581 }
582 
GetTransformFeedbackVaryingType(GLuint programId,GLint index)583 static GLint GetTransformFeedbackVaryingType(GLuint programId, GLint index)
584 {
585     GLint params = 0;
586     glGetProgramiv(programId, WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_VARYINGS, &params);
587     LOGD("WebGL2 GetTransformFeedbackVaryingType programId %{public}u params %{public}d", programId, params);
588     return params;
589 }
590 
BeginTransformFeedback(napi_env env,GLenum primitiveMode)591 napi_value WebGL2RenderingContextImpl::BeginTransformFeedback(napi_env env, GLenum primitiveMode)
592 {
593     if (!CheckInList(primitiveMode, { WebGLRenderingContextBase::POINTS, WebGLRenderingContextBase::LINES,
594         WebGLRenderingContextBase::TRIANGLES })) {
595         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
596         return NVal::CreateNull(env).val_;
597     }
598     if (GetTransformFeedbackVaryingType(currentProgramId_, boundTransformFeedback_) <= 0) {
599         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
600         return NVal::CreateNull(env).val_;
601     }
602     glBeginTransformFeedback(primitiveMode);
603     LOGD("WebGL2 beginTransformFeedback primitiveMode %{public}u result %{public}u", primitiveMode, GetError_());
604     return NVal::CreateNull(env).val_;
605 }
606 
EndTransformFeedback(napi_env env)607 napi_value WebGL2RenderingContextImpl::EndTransformFeedback(napi_env env)
608 {
609     LOGD("WebGL2 endTransformFeedback");
610     if (GetTransformFeedbackVaryingType(currentProgramId_, boundTransformFeedback_) <= 0) {
611         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
612         return NVal::CreateNull(env).val_;
613     }
614     glEndTransformFeedback();
615     return NVal::CreateNull(env).val_;
616 }
617 
GetTransformFeedbackVarying(napi_env env,napi_value programObj,GLuint index)618 napi_value WebGL2RenderingContextImpl::GetTransformFeedbackVarying(napi_env env, napi_value programObj, GLuint index)
619 {
620     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
621     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
622     if (webGLProgram == nullptr) {
623         return NVal::CreateNull(env).val_;
624     }
625     programId = webGLProgram->GetProgramId();
626 
627     WebGLActiveInfo* webGLActiveInfo = nullptr;
628     napi_value objActiveInfo = WebGLActiveInfo::CreateObjectInstance(env, &webGLActiveInfo).val_;
629     if (webGLActiveInfo == nullptr) {
630         return NVal::CreateNull(env).val_;
631     }
632 
633     GLsizei bufSize = WEBGL_ACTIVE_INFO_NAME_MAX_LENGTH;
634     GLsizei length = 0;
635     GLsizei size = 0;
636     GLenum type = 0;
637     GLchar name[WEBGL_ACTIVE_INFO_NAME_MAX_LENGTH] = { 0 };
638     glGetTransformFeedbackVarying(programId, index, bufSize, &length, &size, &type, name);
639     LOGD("WebGL2 getTransformFeedbackVarying: name '%{public}s' %{public}u length %{public}d %{public}d"
640         " index %{public}u", name, type, length, size, index);
641     if (type == 0) {
642         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
643         return NVal::CreateNull(env).val_;
644     }
645     webGLActiveInfo->SetActiveName(name, WEBGL_ACTIVE_INFO_NAME_MAX_LENGTH);
646     webGLActiveInfo->SetActiveSize(size);
647     webGLActiveInfo->SetActiveType(type);
648     return objActiveInfo;
649 }
650 
TexStorage2D(napi_env env,const TexStorageArg & arg)651 napi_value WebGL2RenderingContextImpl::TexStorage2D(napi_env env, const TexStorageArg& arg)
652 {
653     arg.Dump("WebGL2 texStorage2D");
654     if (arg.target != GL_TEXTURE_2D && arg.target != GL_TEXTURE_CUBE_MAP) {
655         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
656         return NVal::CreateNull(env).val_;
657     }
658     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
659     if (texture == nullptr) {
660         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
661         return NVal::CreateNull(env).val_;
662     }
663     GLenum result = CheckTexStorage(env, arg);
664     if (result != WebGLRenderingContextBase::NO_ERROR) {
665         SET_ERROR_WITH_LOG(result, "CheckTexStorage failed");
666         return NVal::CreateNull(env).val_;
667     }
668     glTexStorage2D(arg.target, arg.levels, arg.internalFormat, arg.width, arg.height);
669     texture->SetTexStorageInfo(&arg);
670     return NVal::CreateNull(env).val_;
671 }
672 
TexStorage3D(napi_env env,const TexStorageArg & arg)673 napi_value WebGL2RenderingContextImpl::TexStorage3D(napi_env env, const TexStorageArg& arg)
674 {
675     arg.Dump("WebGL texStorage3D");
676     if (arg.target != GL_TEXTURE_3D && arg.target != GL_TEXTURE_2D_ARRAY) {
677         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
678         return NVal::CreateNull(env).val_;
679     }
680     GLenum result = CheckTexStorage(env, arg);
681     if (result != WebGLRenderingContextBase::NO_ERROR) {
682         SET_ERROR_WITH_LOG(result, "CheckTexStorage failed");
683         return NVal::CreateNull(env).val_;
684     }
685     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
686     if (texture == nullptr) {
687         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
688         return NVal::CreateNull(env).val_;
689     }
690     glTexStorage3D(arg.target, arg.levels, arg.internalFormat, arg.width, arg.height, arg.depth);
691     texture->SetTexStorageInfo(&arg);
692     LOGD("WebGL texStorage3D result %{public}u", GetError_());
693     return NVal::CreateNull(env).val_;
694 }
695 
CheckTexImage3D(napi_env env,const TexImageArg & imgArg)696 GLenum WebGL2RenderingContextImpl::CheckTexImage3D(napi_env env, const TexImageArg& imgArg)
697 {
698     switch (imgArg.target) {
699         case GL_TEXTURE_3D:
700         case GL_TEXTURE_2D_ARRAY:
701             break;
702         default:
703             return WebGLRenderingContextBase::INVALID_ENUM;
704     }
705     GLenum result = CheckTextureLevel(imgArg.target, imgArg.level);
706     if (result != WebGLRenderingContextBase::NO_ERROR) {
707         return result;
708     }
709     return CheckTextureFormatAndType(env, imgArg.internalFormat, imgArg.format, imgArg.type, imgArg.level);
710 }
711 
TexImage3D(napi_env env,const TexImageArg & arg,napi_value source)712 napi_value WebGL2RenderingContextImpl::TexImage3D(napi_env env, const TexImageArg& arg, napi_value source)
713 {
714     TexImageArg imgArg(arg);
715     imgArg.Dump("WebGL2 texImage3D");
716     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
717     if (texture == nullptr) {
718         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
719         return NVal::CreateNull(env).val_;
720     }
721 
722     GLenum result = CheckTexImage3D(env, imgArg);
723     if (result != WebGLRenderingContextBase::NO_ERROR) {
724         SET_ERROR_WITH_LOG(result, "CheckTexImage3D failed");
725         return NVal::CreateNull(env).val_;
726     }
727     GLvoid* data = nullptr;
728     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
729     if (!NVal(env, source).IsNull()) {
730         result = imageSource.GenImageSource(
731             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, source);
732         if (result) {
733             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
734             return NVal::CreateNull(env).val_;
735         }
736         data = imageSource.GetImageSourceData();
737         imgArg.width = imageSource.GetWidth();
738         imgArg.height = imageSource.GetHeight();
739     }
740 
741     glTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth,
742         imgArg.border, imgArg.format, imgArg.type, data);
743     texture->SetTextureLevel({ imgArg.target, imgArg.level,
744         imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth, imgArg.type });
745     LOGD("WebGL2 texImage3D result %{public}u", GetError_());
746     return NVal::CreateNull(env).val_;
747 }
748 
TexImage3D(napi_env env,const TexImageArg & imgArg,napi_value dataObj,GLuint srcOffset)749 napi_value WebGL2RenderingContextImpl::TexImage3D(
750     napi_env env, const TexImageArg& imgArg, napi_value dataObj, GLuint srcOffset)
751 {
752     imgArg.Dump("WebGL2 texImage3D");
753     GLenum result = CheckTexImage3D(env, imgArg);
754     if (result != WebGLRenderingContextBase::NO_ERROR) {
755         SET_ERROR_WITH_LOG(result, "CheckTexImage3D failed");
756         return NVal::CreateNull(env).val_;
757     }
758 
759     GLvoid* data = nullptr;
760     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
761     if (!NVal(env, dataObj).IsNull()) {
762         result = imageSource.GenImageSource(
763             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, dataObj, srcOffset);
764         if (result) {
765             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
766             return NVal::CreateNull(env).val_;
767         }
768         data = imageSource.GetImageSourceData();
769     }
770     if (data != nullptr) {
771         GLenum result = CheckTextureDataBuffer(imgArg, imageSource.GetWebGLReadBuffer());
772         if (result) {
773             SET_ERROR_WITH_LOG(result, "CheckTextureDataBuffer failed");
774             return NVal::CreateNull(env).val_;
775         }
776     }
777     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
778     if (texture == nullptr) {
779         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "texture is nullptr");
780         return NVal::CreateNull(env).val_;
781     }
782     glTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth,
783         imgArg.border, imgArg.format, imgArg.type, data);
784     texture->SetTextureLevel(imgArg);
785     LOGD("WebGL2 texImage3D result %{public}u", GetError_());
786     return NVal::CreateNull(env).val_;
787 }
788 
TexImage3D(napi_env env,const TexImageArg & imgArg,GLintptr pboOffset)789 napi_value WebGL2RenderingContextImpl::TexImage3D(napi_env env, const TexImageArg& imgArg, GLintptr pboOffset)
790 {
791     imgArg.Dump("WebGL2 texImage3D");
792     GLenum result = CheckTexImage3D(env, imgArg);
793     if (result != WebGLRenderingContextBase::NO_ERROR) {
794         SET_ERROR(result);
795         return NVal::CreateNull(env).val_;
796     }
797     glTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth,
798         imgArg.border, imgArg.format, imgArg.type, reinterpret_cast<void*>(pboOffset));
799     LOGD("WebGL2 texImage3D result %{public}u", GetError_());
800     return NVal::CreateNull(env).val_;
801 }
802 
CheckTexSubImage3D(napi_env env,const TexSubImage3DArg & arg)803 GLenum WebGL2RenderingContextImpl::CheckTexSubImage3D(napi_env env, const TexSubImage3DArg& arg)
804 {
805     switch (arg.target) {
806         case GL_TEXTURE_3D:
807         case GL_TEXTURE_2D_ARRAY:
808             break;
809         default:
810             return WebGLRenderingContextBase::INVALID_ENUM;
811     }
812     GLenum result = CheckTextureLevel(arg.target, arg.level);
813     if (result != WebGLRenderingContextBase::NO_ERROR) {
814         return result;
815     }
816     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
817     if (texture == nullptr) {
818         return WebGLRenderingContextBase::INVALID_VALUE;
819     }
820 
821     if (!texture->CheckValid(arg.target, arg.level)) {
822         return WebGLRenderingContextBase::INVALID_OPERATION;
823     }
824 
825     if (!WebGLTexture::CheckTextureSize(arg.xOffset, arg.width, texture->GetWidth(arg.target, arg.level)) ||
826         !WebGLTexture::CheckTextureSize(arg.yOffset, arg.height, texture->GetHeight(arg.target, arg.level)) ||
827         !WebGLTexture::CheckTextureSize(arg.zOffset, arg.depth, texture->GetDepth(arg.target, arg.level))) {
828         return WebGLRenderingContextBase::INVALID_VALUE;
829     }
830     GLenum internalFormat = texture->GetInternalFormat(arg.target, arg.level);
831     return CheckTextureFormatAndType(env, internalFormat, arg.format, arg.type, arg.level);
832 }
833 
TexSubImage3D(napi_env env,const TexSubImage3DArg & arg,napi_value source)834 napi_value WebGL2RenderingContextImpl::TexSubImage3D(napi_env env, const TexSubImage3DArg& arg, napi_value source)
835 {
836     TexSubImage3DArg imgArg(arg);
837     imgArg.Dump("WebGL2 texSubImage3D source");
838     GLvoid* data = nullptr;
839     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
840     if (!NVal(env, source).IsNull()) {
841         GLenum result = imageSource.GenImageSource(
842             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, source);
843         if (result) {
844             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
845             return NVal::CreateNull(env).val_;
846         }
847         data = imageSource.GetImageSourceData();
848         imgArg.width = imageSource.GetWidth();
849         imgArg.height = imageSource.GetHeight();
850     } else {
851         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
852         return NVal::CreateNull(env).val_;
853     }
854     GLenum result = CheckTexSubImage3D(env, imgArg);
855     if (result != WebGLRenderingContextBase::NO_ERROR) {
856         SET_ERROR_WITH_LOG(result, "CheckTexSubImage3D failed");
857         return NVal::CreateNull(env).val_;
858     }
859     glTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
860         imgArg.height, imgArg.depth, imgArg.format, imgArg.type, data);
861     LOGD("WebGL2 texSubImage3D result %{public}u", GetError_());
862     return NVal::CreateNull(env).val_;
863 }
864 
TexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,napi_value dataObj,GLuint srcOffset)865 napi_value WebGL2RenderingContextImpl::TexSubImage3D(
866     napi_env env, const TexSubImage3DArg& imgArg, napi_value dataObj, GLuint srcOffset)
867 {
868     imgArg.Dump("WebGL2 texSubImage3D data buffer");
869 
870     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
871     GLvoid* data = nullptr;
872     bool changeUnpackAlignment = false;
873     if (!NVal(env, dataObj).IsNull()) {
874         GLenum result = imageSource.GenImageSource(
875             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, dataObj, srcOffset);
876         if (result) {
877             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
878             return NVal::CreateNull(env).val_;
879         }
880         data = imageSource.GetImageSourceData();
881         changeUnpackAlignment = unpackFlipY_ || unpackPremultiplyAlpha_;
882     } else {
883         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
884         return NVal::CreateNull(env).val_;
885     }
886 
887     GLenum result = CheckTexSubImage3D(env, imgArg);
888     if (result != WebGLRenderingContextBase::NO_ERROR) {
889         SET_ERROR_WITH_LOG(result, "CheckTexSubImage3D failed");
890         return NVal::CreateNull(env).val_;
891     }
892 
893     if (changeUnpackAlignment) {
894         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
895     }
896     glTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
897         imgArg.height, imgArg.depth, imgArg.format, imgArg.type, data);
898     if (changeUnpackAlignment) {
899         glPixelStorei(GL_UNPACK_ALIGNMENT, unpackAlignment_);
900     }
901     LOGD("WebGL2 texSubImage3D result %{public}u", GetError_());
902     return NVal::CreateNull(env).val_;
903 }
904 
TexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,GLintptr pboOffset)905 napi_value WebGL2RenderingContextImpl::TexSubImage3D(napi_env env, const TexSubImage3DArg& imgArg, GLintptr pboOffset)
906 {
907     imgArg.Dump("WebGL2 texSubImage3D pboOffset");
908     GLenum result = CheckTexSubImage3D(env, imgArg);
909     if (result != WebGLRenderingContextBase::NO_ERROR) {
910         SET_ERROR(result);
911         return NVal::CreateNull(env).val_;
912     }
913     glTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
914         imgArg.height, imgArg.depth, imgArg.format, imgArg.type, reinterpret_cast<void*>(pboOffset));
915     LOGD("WebGL2 texSubImage3D result %{public}u", GetError_());
916     return NVal::CreateNull(env).val_;
917 }
918 
CopyTexSubImage3D(napi_env env,const CopyTexSubImage3DArg & imgArg)919 napi_value WebGL2RenderingContextImpl::CopyTexSubImage3D(napi_env env, const CopyTexSubImage3DArg& imgArg)
920 {
921     imgArg.Dump("WebGL2 copyTexSubImage3D");
922     GLenum result = CheckCopyTexSubImage(env, imgArg);
923     if (result) {
924         SET_ERROR_WITH_LOG(result, "CheckCopyTexSubImage failed");
925         return NVal::CreateNull(env).val_;
926     }
927     GLuint frameBufferId = 0;
928     result = CheckReadBufferAndGetInfo(env, &frameBufferId, nullptr, nullptr);
929     if (result != WebGLRenderingContextBase::NO_ERROR) {
930         SET_ERROR_WITH_LOG(result, "CheckReadBufferAndGetInfo failed");
931         return NVal::CreateNull(env).val_;
932     }
933     glCopyTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.x, imgArg.y,
934         imgArg.width, imgArg.height);
935     LOGD("WebGL2 copyTexSubImage3D result %{public}u", GetError_());
936     return NVal::CreateNull(env).val_;
937 }
938 
CompressedTexImage3D(napi_env env,const TexImageArg & imgArg,GLsizei imageSize,GLintptr offset)939 napi_value WebGL2RenderingContextImpl::CompressedTexImage3D(
940     napi_env env, const TexImageArg& imgArg, GLsizei imageSize, GLintptr offset)
941 {
942     imgArg.Dump("WebGL2 compressedTexImage3D");
943     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
944     if (texture == nullptr) {
945         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
946         return NVal::CreateNull(env).val_;
947     }
948     if (texture->CheckImmutable()) {
949         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckImmutable failed");
950         return NVal::CreateNull(env).val_;
951     }
952 
953     glCompressedTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height,
954         imgArg.depth, imgArg.border, imageSize, reinterpret_cast<void*>(offset));
955     LOGD("WebGL2 copyTexSubImage3D result %{public}u", GetError_());
956     return NVal::CreateNull(env).val_;
957 }
958 
CompressedTexImage3D(napi_env env,const TexImageArg & imgArg,napi_value dataObj,GLuint srcOffset,GLuint srcLengthOverride)959 napi_value WebGL2RenderingContextImpl::CompressedTexImage3D(
960     napi_env env, const TexImageArg& imgArg, napi_value dataObj, GLuint srcOffset, GLuint srcLengthOverride)
961 {
962     imgArg.Dump("WebGL2 compressedTexImage3D");
963     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
964     if (texture == nullptr) {
965         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
966         return NVal::CreateNull(env).val_;
967     }
968     if (texture->CheckImmutable()) {
969         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckImmutable failed");
970         return NVal::CreateNull(env).val_;
971     }
972     WebGLReadBufferArg readData(env);
973     GLvoid* data = nullptr;
974     GLsizei length = 0;
975     if (NVal(env, dataObj).IsNull()) {
976         napi_status status = readData.GenBufferData(dataObj, BUFFER_DATA_FLOAT_32);
977         if (status != napi_ok) {
978             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GenBufferData failed");
979             return NVal::CreateNull(env).val_;
980         }
981         readData.DumpBuffer(readData.GetBufferDataType());
982         data = reinterpret_cast<void*>(readData.GetBuffer() + srcOffset);
983         length = static_cast<GLsizei>((srcLengthOverride == 0) ? readData.GetBufferLength() : srcLengthOverride);
984     }
985     glCompressedTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height,
986         imgArg.depth, imgArg.border, length, data);
987     texture->SetTextureLevel({ imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height,
988         imgArg.depth, GL_UNSIGNED_BYTE });
989     LOGD("WebGL2 compressedTexImage3D result %{public}u", GetError_());
990     return NVal::CreateNull(env).val_;
991 }
992 
CompressedTexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,GLsizei imageSize,GLintptr offset)993 napi_value WebGL2RenderingContextImpl::CompressedTexSubImage3D(
994     napi_env env, const TexSubImage3DArg& imgArg, GLsizei imageSize, GLintptr offset)
995 {
996     imgArg.Dump("WebGL2 compressedTexSubImage3D");
997     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
998     if (texture == nullptr) {
999         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
1000         return NVal::CreateNull(env).val_;
1001     }
1002     if (imgArg.format != texture->GetInternalFormat(imgArg.target, imgArg.level)) {
1003         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1004         return NVal::CreateNull(env).val_;
1005     }
1006     glCompressedTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
1007         imgArg.height, imgArg.depth, imgArg.format, imageSize, reinterpret_cast<void*>(offset));
1008     LOGD("WebGL2 compressedTexSubImage3D result %{public}u", GetError_());
1009     return NVal::CreateNull(env).val_;
1010 }
1011 
CompressedTexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,napi_value dataObj,GLuint srcOffset,GLuint srcLengthOverride)1012 napi_value WebGL2RenderingContextImpl::CompressedTexSubImage3D(
1013     napi_env env, const TexSubImage3DArg& imgArg, napi_value dataObj, GLuint srcOffset, GLuint srcLengthOverride)
1014 {
1015     imgArg.Dump("WebGL2 compressedTexSubImage3D");
1016     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
1017     if (texture == nullptr) {
1018         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
1019         return NVal::CreateNull(env).val_;
1020     }
1021     if (imgArg.format != texture->GetInternalFormat(imgArg.target, imgArg.level)) {
1022         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1023         return NVal::CreateNull(env).val_;
1024     }
1025 
1026     WebGLReadBufferArg readData(env);
1027     GLvoid* data = nullptr;
1028     GLsizei length = 0;
1029     if (NVal(env, dataObj).IsNull()) {
1030         napi_status status = readData.GenBufferData(dataObj, BUFFER_DATA_FLOAT_32);
1031         if (status != napi_ok) {
1032             SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1033             return NVal::CreateNull(env).val_;
1034         }
1035         readData.DumpBuffer(readData.GetBufferDataType());
1036         data = reinterpret_cast<void*>(readData.GetBuffer() + srcOffset);
1037         length = static_cast<GLsizei>((srcLengthOverride == 0) ? readData.GetBufferLength() : srcLengthOverride);
1038     }
1039 
1040     glCompressedTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
1041         imgArg.height, imgArg.depth, imgArg.format, length, data);
1042     LOGD("WebGL2 compressedTexSubImage3D result %{public}u", GetError_());
1043     return NVal::CreateNull(env).val_;
1044 }
1045 
ClearBufferV(napi_env env,GLenum buffer,GLint drawBuffer,napi_value value,int64_t srcOffset,BufferDataType type)1046 napi_value WebGL2RenderingContextImpl::ClearBufferV(
1047     napi_env env, GLenum buffer, GLint drawBuffer, napi_value value, int64_t srcOffset, BufferDataType type)
1048 {
1049     LOGD("WebGL2 clearBuffer buffer %{public}u %{public}d srcOffset %{public}" PRIi64, buffer, drawBuffer, srcOffset);
1050     WebGLReadBufferArg bufferData(env);
1051     napi_status status = bufferData.GenBufferData(value, type);
1052     if (status != 0) {
1053         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL2 clearBuffer failed to getbuffer data");
1054         return NVal::CreateNull(env).val_;
1055     }
1056     if (bufferData.GetBufferDataType() != type) {
1057         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1058             "WebGL2 clearBuffer invalid buffer data type %{public}d", bufferData.GetBufferDataType());
1059         return NVal::CreateNull(env).val_;
1060     }
1061 
1062     GLenum result = CheckClearBuffer(env, buffer, bufferData);
1063     if (result != WebGLRenderingContextBase::NO_ERROR) {
1064         SET_ERROR_WITH_LOG(result, "WebGL2 clearBuffer invalid clear buffer");
1065         return NVal::CreateNull(env).val_;
1066     }
1067 
1068     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1069     switch (type) {
1070         case BUFFER_DATA_FLOAT_32:
1071             glClearBufferfv(buffer, drawBuffer, reinterpret_cast<GLfloat*>(bufferData.GetBuffer() + srcOffset));
1072             break;
1073         case BUFFER_DATA_INT_32:
1074             glClearBufferiv(buffer, drawBuffer, reinterpret_cast<GLint*>(bufferData.GetBuffer() + srcOffset));
1075             break;
1076         case BUFFER_DATA_UINT_32:
1077             glClearBufferuiv(buffer, drawBuffer, reinterpret_cast<GLuint*>(bufferData.GetBuffer() + srcOffset));
1078             break;
1079         default:
1080             break;
1081     }
1082     LOGD("WebGL2 clearBuffer buffer %{public}u result %{public}u", buffer, GetError_());
1083     return NVal::CreateNull(env).val_;
1084 }
1085 
ClearBufferfi(napi_env env,GLenum buffer,GLint drawBuffer,GLfloat depth,GLint stencil)1086 napi_value WebGL2RenderingContextImpl::ClearBufferfi(
1087     napi_env env, GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil)
1088 {
1089     if (buffer != WebGLRenderingContextBase::DEPTH_STENCIL) {
1090         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1091         return NVal::CreateNull(env).val_;
1092     }
1093     glClearBufferfi(buffer, drawBuffer, depth, stencil);
1094     LOGD("WebGL2 clearBufferfi buffer %{public}u %{public}d depth %{public}f %{public}d result %{public}u",
1095         buffer, drawBuffer, depth, stencil, GetError_());
1096     return NVal::CreateNull(env).val_;
1097 }
1098 
GetIndexedParameter(napi_env env,GLenum target,GLuint index)1099 napi_value WebGL2RenderingContextImpl::GetIndexedParameter(napi_env env, GLenum target, GLuint index)
1100 {
1101     LOGD("WebGL2 getIndexedParameter index %{public}u", index);
1102     switch (target) {
1103         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: {
1104             if (index >= maxBoundTransformFeedbackBufferIndex_) {
1105                 return NVal::CreateNull(env).val_;
1106             }
1107             return GetObject<WebGLBuffer>(env, boundIndexedTransformFeedbackBuffers_[index]);
1108         }
1109         case GL_UNIFORM_BUFFER_BINDING: {
1110             if (index >= maxBoundUniformBufferIndex_) {
1111                 return NVal::CreateNull(env).val_;
1112             }
1113             return GetObject<WebGLBuffer>(env, boundIndexedUniformBuffers_[index]);
1114         }
1115         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1116         case GL_UNIFORM_BUFFER_SIZE:
1117         case GL_UNIFORM_BUFFER_START: {
1118             int64_t data;
1119             glGetInteger64i_v(target, index, &data);
1120             LOGD("WebGL getIndexedParameter end");
1121             return NVal::CreateInt64(env, data).val_;
1122         }
1123         default :
1124             LOGD("WebGL getIndexedParameter get nullptr");
1125             return NVal::CreateNull(env).val_;
1126     }
1127 }
1128 
GetFragDataLocation(napi_env env,napi_value programObj,const std::string & name)1129 napi_value WebGL2RenderingContextImpl::GetFragDataLocation(napi_env env, napi_value programObj, const std::string& name)
1130 {
1131     GLuint program = WebGLProgram::DEFAULT_PROGRAM_ID;
1132     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1133     if (webGLProgram == nullptr) {
1134         return NVal::CreateInt64(env, -1).val_;
1135     }
1136     program = webGLProgram->GetProgramId();
1137 
1138     GLint res = glGetFragDataLocation(program, const_cast<char*>(name.c_str()));
1139     LOGD("WebGL2 getFragDataLocation name %{public}s result %{public}d", name.c_str(), res);
1140     return NVal::CreateInt64(env, res).val_;
1141 }
1142 
VertexAttribI4i(napi_env env,GLuint index,GLint * data)1143 napi_value WebGL2RenderingContextImpl::VertexAttribI4i(napi_env env, GLuint index, GLint* data)
1144 {
1145     VertexAttribInfo* info = GetVertexAttribInfo(index);
1146     if (info == nullptr) {
1147         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1148         return NVal::CreateNull(env).val_;
1149     }
1150 
1151     glVertexAttribI4i(index, data[0], data[1], data[2], data[3]); // 2, 3 index for data
1152     info->type = BUFFER_DATA_INT_32;
1153     LOGD("WebGL2 vertexAttribI4i index %{public}u [%{public}d %{public}d %{public}d %{public}d] result %{public}u",
1154         index, data[0], data[1], data[2], data[3], GetError_()); // 2, 3 index for data
1155     return NVal::CreateNull(env).val_;
1156 }
1157 
VertexAttribI4ui(napi_env env,GLuint index,GLuint * data)1158 napi_value WebGL2RenderingContextImpl::VertexAttribI4ui(napi_env env, GLuint index, GLuint* data)
1159 {
1160     VertexAttribInfo* info = GetVertexAttribInfo(index);
1161     if (info == nullptr) {
1162         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1163         return NVal::CreateNull(env).val_;
1164     }
1165 
1166     glVertexAttribI4ui(index, data[0], data[1], data[2], data[3]); // 2, 3 index for data
1167     info->type = BUFFER_DATA_UINT_32;
1168     LOGD("WebGL2 vertexAttribI4ui index %{public}u [%{public}u %{public}u %{public}u %{public}u] result %{public}u",
1169         index, data[0], data[1], data[2], data[3], GetError_()); // 2, 3 index for data
1170     return NVal::CreateNull(env).val_;
1171 }
1172 
VertexAttribI4iv(napi_env env,GLuint index,napi_value data)1173 napi_value WebGL2RenderingContextImpl::VertexAttribI4iv(napi_env env, GLuint index, napi_value data)
1174 {
1175     VertexAttribInfo* info = GetVertexAttribInfo(index);
1176     if (info == nullptr) {
1177         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1178         return NVal::CreateNull(env).val_;
1179     }
1180 
1181     WebGLReadBufferArg bufferData(env);
1182     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_INT_32);
1183     if (status != 0) {
1184         LOGE("WebGL vertexAttribI4iv failed to getbuffer data");
1185         return NVal::CreateNull(env).val_;
1186     }
1187     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1188     if (bufferData.GetBufferDataType() != BUFFER_DATA_INT_32) {
1189         LOGE("WebGL vertexAttribI4iv invalid data type %{public}u", bufferData.GetBufferDataType());
1190         return NVal::CreateNull(env).val_;
1191     }
1192     glVertexAttribI4iv(index, reinterpret_cast<GLint*>(bufferData.GetBuffer()));
1193     info->type = BUFFER_DATA_INT_32;
1194     return NVal::CreateNull(env).val_;
1195 }
1196 
VertexAttribI4uiv(napi_env env,GLuint index,napi_value data)1197 napi_value WebGL2RenderingContextImpl::VertexAttribI4uiv(napi_env env, GLuint index, napi_value data)
1198 {
1199     VertexAttribInfo* info = GetVertexAttribInfo(index);
1200     if (info == nullptr) {
1201         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1202         return NVal::CreateNull(env).val_;
1203     }
1204     WebGLReadBufferArg bufferData(env);
1205     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_UINT_32);
1206     if (status != 0) {
1207         LOGE("WebGL vertexAttribI4uiv failed to getbuffer data");
1208         return NVal::CreateNull(env).val_;
1209     }
1210     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1211     if (bufferData.GetBufferDataType() != BUFFER_DATA_UINT_32) {
1212         LOGE("WebGL2 vertexAttribI4uiv invalid data type %{public}d", bufferData.GetBufferDataType());
1213         return NVal::CreateNull(env).val_;
1214     }
1215     glVertexAttribI4uiv(index, reinterpret_cast<const GLuint*>(bufferData.GetBuffer()));
1216     info->type = BUFFER_DATA_UINT_32;
1217     return NVal::CreateNull(env).val_;
1218 }
1219 
VertexAttribIPointer(napi_env env,const VertexAttribArg & vertexInfo)1220 napi_value WebGL2RenderingContextImpl::VertexAttribIPointer(napi_env env, const VertexAttribArg& vertexInfo)
1221 {
1222     vertexInfo.Dump("WebGL2 vertexAttribPointer");
1223     if (!CheckGLenum(vertexInfo.type,
1224         { GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT }, {})) {
1225         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1226             "WebGL vertexAttribPointer invalid type %{public}u", vertexInfo.type);
1227     }
1228 
1229     GLenum result = CheckVertexAttribPointer(env, vertexInfo);
1230     if (result) {
1231         SET_ERROR(result);
1232         return NVal::CreateNull(env).val_;
1233     }
1234 
1235     glVertexAttribIPointer(vertexInfo.index, vertexInfo.size, vertexInfo.type, vertexInfo.stride,
1236         reinterpret_cast<GLvoid*>(vertexInfo.offset));
1237     LOGD("WebGL vertexAttribPointer index %{public}u offset %{public}u",
1238          static_cast<unsigned int>(vertexInfo.index), static_cast<unsigned int>(vertexInfo.offset));
1239     return NVal::CreateNull(env).val_;
1240 }
1241 
VertexAttribDivisor(napi_env env,GLuint index,GLuint divisor)1242 napi_value WebGL2RenderingContextImpl::VertexAttribDivisor(napi_env env, GLuint index, GLuint divisor)
1243 {
1244     LOGD("WebGL2 vertexAttribDivisor index %{public}u divisor %{public}u", index, divisor);
1245     if (index >= GetMaxVertexAttribs()) {
1246         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1247             "WebGL2 vertexAttribDivisor invalid index %{public}u", index);
1248         return NVal::CreateNull(env).val_;
1249     }
1250     glVertexAttribDivisor(index, divisor);
1251     return NVal::CreateNull(env).val_;
1252 }
1253 
DrawBuffers(napi_env env,napi_value dataObj)1254 napi_value WebGL2RenderingContextImpl::DrawBuffers(napi_env env, napi_value dataObj)
1255 {
1256     WebGLReadBufferArg bufferData(env);
1257     napi_status status = bufferData.GenBufferData(dataObj, BUFFER_DATA_GLENUM);
1258     if (status != 0) {
1259         LOGE("WebGL glDrawBuffers failed to getbuffer data");
1260         return NVal::CreateNull(env).val_;
1261     }
1262     if (bufferData.GetBufferType() != BUFFER_ARRAY) {
1263         LOGE("WebGL glDrawBuffers invalid buffer type %d", bufferData.GetBufferType());
1264         return NVal::CreateNull(env).val_;
1265     }
1266     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1267     GLenum* data = reinterpret_cast<GLenum*>(bufferData.GetBuffer());
1268     GLsizei length = static_cast<GLsizei>(bufferData.GetBufferLength() / sizeof(GLenum));
1269     glDrawBuffers(length, data);
1270     return NVal::CreateNull(env).val_;
1271 }
1272 
DrawArraysInstanced(napi_env env,GLenum mode,GLint first,GLsizei count,GLsizei instanceCount)1273 napi_value WebGL2RenderingContextImpl::DrawArraysInstanced(
1274     napi_env env, GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1275 {
1276     LOGD("WebGL drawArraysInstanced mode %{public}u %{public}d %{public}d %{public}d",
1277         mode, first, count, instanceCount);
1278     GLenum result = CheckDrawArrays(env, mode, first, count);
1279     if (result != WebGLRenderingContextBase::NO_ERROR) {
1280         SET_ERROR_WITH_LOG(result, "CheckDrawArrays failed");
1281         return NVal::CreateNull(env).val_;
1282     }
1283     if (instanceCount < 0) {
1284         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "instanceCount < 0");
1285         return NVal::CreateNull(env).val_;
1286     }
1287     glDrawArraysInstanced(mode, first, count, instanceCount);
1288     return NVal::CreateNull(env).val_;
1289 }
1290 
DrawElementsInstanced(napi_env env,const DrawElementArg & arg,GLsizei instanceCount)1291 napi_value WebGL2RenderingContextImpl::DrawElementsInstanced(
1292     napi_env env, const DrawElementArg& arg, GLsizei instanceCount)
1293 {
1294     LOGD("WebGL2 drawElementsInstanced mode %{public}u %{public}d %{public}u", arg.mode, arg.count, arg.type);
1295     GLenum result = CheckDrawElements(env, arg.mode, arg.count, arg.type, arg.offset);
1296     if (result != WebGLRenderingContextBase::NO_ERROR) {
1297         SET_ERROR_WITH_LOG(result, "CheckDrawElements failed");
1298         return NVal::CreateNull(env).val_;
1299     }
1300     if (instanceCount < 0) {
1301         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "instanceCount < 0");
1302         return NVal::CreateNull(env).val_;
1303     }
1304     glDrawElementsInstanced(arg.mode, arg.count, arg.type, reinterpret_cast<GLvoid*>(arg.offset), instanceCount);
1305     return NVal::CreateNull(env).val_;
1306 }
1307 
DrawRangeElements(napi_env env,const DrawElementArg & arg,GLuint start,GLuint end)1308 napi_value WebGL2RenderingContextImpl::DrawRangeElements(
1309     napi_env env, const DrawElementArg& arg, GLuint start, GLuint end)
1310 {
1311     LOGD("WebGL2 drawRangeElements mode %{public}u %{public}d %{public}u start [%{public}u %{public}u]"
1312         "%{public}d" PRIi64, arg.mode, arg.count, arg.type, start, end, static_cast<int>(arg.offset));
1313     GLenum result = CheckDrawElements(env, arg.mode, arg.count, arg.type, arg.offset);
1314     if (result != WebGLRenderingContextBase::NO_ERROR) {
1315         SET_ERROR(result);
1316         return NVal::CreateNull(env).val_;
1317     }
1318     glDrawRangeElements(arg.mode, start, end, arg.count, arg.type, reinterpret_cast<GLvoid*>(arg.offset));
1319     return NVal::CreateNull(env).val_;
1320 }
1321 
CopyBufferSubData(napi_env env,GLenum targets[2],int64_t readOffset,int64_t writeOffset,int64_t size)1322 napi_value WebGL2RenderingContextImpl::CopyBufferSubData(
1323     napi_env env, GLenum targets[2], int64_t readOffset, int64_t writeOffset, int64_t size)
1324 {
1325     LOGD("WebGL2 copyBufferSubData targets [%{public}u %{public}u] offset"
1326         " [%{public}" PRIi64 " %{public}" PRIi64 "] %{public}" PRIi64,
1327         targets[0], targets[1], readOffset, writeOffset, size);
1328     if (!WebGLArg::CheckNoneNegInt<GLint>(readOffset) || !WebGLArg::CheckNoneNegInt<GLint>(writeOffset) ||
1329         !WebGLArg::CheckNoneNegInt<GLint>(size)) {
1330         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckNoneNegInt failed");
1331         return NVal::CreateNull(env).val_;
1332     }
1333     WebGLBuffer* readBuffer = GetBoundBuffer(env, targets[0]); // read
1334     if (readBuffer == nullptr || readBuffer->GetBufferSize() == 0) {
1335         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "readBuffer is nullptr or size is 0");
1336         return NVal::CreateNull(env).val_;
1337     }
1338     WebGLBuffer* writeBuffer = GetBoundBuffer(env, targets[1]); // write
1339     if (writeBuffer == nullptr || writeBuffer->GetBufferSize() == 0) {
1340         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "writeBuffer is nullptr or size is 0");
1341         return NVal::CreateNull(env).val_;
1342     }
1343     if (readOffset + size > static_cast<int64_t>(readBuffer->GetBufferSize()) ||
1344         writeOffset + size > static_cast<int64_t>(writeBuffer->GetBufferSize())) {
1345         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "readOffset or writeOffset size error");
1346         return NVal::CreateNull(env).val_;
1347     }
1348     if ((writeBuffer->GetTarget() == GL_ELEMENT_ARRAY_BUFFER && readBuffer->GetTarget() != GL_ELEMENT_ARRAY_BUFFER) ||
1349         (writeBuffer->GetTarget() != GL_ELEMENT_ARRAY_BUFFER && readBuffer->GetTarget() == GL_ELEMENT_ARRAY_BUFFER)) {
1350         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "readOffset or writeOffset GetTarget failed");
1351         return NVal::CreateNull(env).val_;
1352     }
1353     if (writeBuffer->GetTarget() == 0) {
1354         writeBuffer->SetTarget(readBuffer->GetTarget());
1355     }
1356     glCopyBufferSubData(targets[0], targets[1], static_cast<GLintptr>(readOffset), static_cast<GLintptr>(writeOffset),
1357         static_cast<GLsizeiptr>(size));
1358     LOGD("WebGL2 copyBufferSubData result %{public}u", GetError_());
1359     return NVal::CreateNull(env).val_;
1360 }
1361 
GetBufferSubData(napi_env env,GLenum target,int64_t offset,napi_value data,const BufferExt & ext)1362 napi_value WebGL2RenderingContextImpl::GetBufferSubData(
1363     napi_env env, GLenum target, int64_t offset, napi_value data, const BufferExt& ext)
1364 {
1365     LOGD("WebGL2 getBufferSubData target %{public}u %{public}" PRIi64, target, offset);
1366     WebGLReadBufferArg bufferData(env);
1367     napi_status status = bufferData.GenBufferData(data);
1368     if (status != 0 || bufferData.GetBufferType() == BUFFER_ARRAY) {
1369         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "check buffer failed");
1370         return NVal::CreateNull(env).val_;
1371     }
1372     if (!WebGLArg::CheckNoneNegInt<GLint>(offset)) {
1373         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckNoneNegInt failed");
1374         return NVal::CreateNull(env).val_;
1375     }
1376     WebGLBuffer* writeBuffer = GetBoundBuffer(env, target);
1377     if (writeBuffer == nullptr || writeBuffer->GetBufferSize() == 0) {
1378         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "no buffer");
1379         return NVal::CreateNull(env).val_;
1380     }
1381     if (static_cast<size_t>(offset) + bufferData.GetBufferLength() > writeBuffer->GetBufferSize()) {
1382         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "check buffer size failed");
1383         return NVal::CreateNull(env).val_;
1384     }
1385     GLsizeiptr dstSize = (ext.length == 0) ? static_cast<GLsizeiptr>(bufferData.GetBufferLength())
1386                                            : static_cast<GLsizeiptr>(ext.length * bufferData.GetBufferDataSize());
1387     GLuint dstOffset = static_cast<GLuint>(ext.offset * bufferData.GetBufferDataSize());
1388     LOGD("WebGL2 getBufferSubData dstSize %{public}u dstOffset %{public}p",
1389          static_cast<unsigned int>(dstSize), writeBuffer->bufferData_);
1390 
1391     void *mapBuffer = glMapBufferRange(target, static_cast<GLintptr>(offset), dstSize, GL_MAP_READ_BIT);
1392     if (mapBuffer == nullptr ||
1393         memcpy_s(bufferData.GetBuffer() + dstOffset, bufferData.GetBufferLength(), mapBuffer, dstSize) != 0) {
1394         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "mapBuffer is nullptr");
1395     }
1396     glUnmapBuffer(target);
1397     LOGD("WebGL2 getBufferSubData target %{public}u result %{public}u ", target, GetError_());
1398     return NVal::CreateNull(env).val_;
1399 }
1400 
BlitFrameBuffer(napi_env env,GLint data[8],GLbitfield mask,GLenum filter)1401 napi_value WebGL2RenderingContextImpl::BlitFrameBuffer(napi_env env, GLint data[8], GLbitfield mask, GLenum filter)
1402 {
1403     // 0,1,2,3,4,5,6,7 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1
1404     glBlitFramebuffer(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], mask, filter);
1405     LOGD("WebGL2 blitFrameBuffer filter %{public}u result %{public}u ", filter, GetError_());
1406     return NVal::CreateNull(env).val_;
1407 }
1408 
FrameBufferTextureLayer(napi_env env,GLenum target,GLenum attachment,napi_value textureObj,const TextureLayerArg & layer)1409 napi_value WebGL2RenderingContextImpl::FrameBufferTextureLayer(
1410     napi_env env, GLenum target, GLenum attachment, napi_value textureObj, const TextureLayerArg& layer)
1411 {
1412     int32_t textureId = WebGLTexture::DEFAULT_TEXTURE;
1413     WebGLTexture* webGlTexture = WebGLTexture::GetObjectInstance(env, textureObj);
1414     if (webGlTexture == nullptr) {
1415         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1416         return NVal::CreateNull(env).val_;
1417     }
1418     textureId = static_cast<int32_t>(webGlTexture->GetTexture());
1419     glFramebufferTextureLayer(target, attachment, textureId, layer.level, layer.layer);
1420     LOGD("WebGL frameBufferTextureLayer texture %{public}d result %{public}u", textureId, GetError_());
1421 
1422     WebGLFramebuffer* frameBuffer = GetBoundFrameBuffer(env, target);
1423     if (frameBuffer == nullptr) {
1424         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "can not find bind frame buffer");
1425         return NVal::CreateNull(env).val_;
1426     }
1427     frameBuffer->AddAttachment(
1428         target, attachment, static_cast<GLuint>(textureId), webGlTexture->GetTarget(), layer.level);
1429     return NVal::CreateNull(env).val_;
1430 }
1431 
ReadBuffer(napi_env env,GLenum mode)1432 napi_value WebGL2RenderingContextImpl::ReadBuffer(napi_env env, GLenum mode)
1433 {
1434     LOGD("WebGL2 readBuffer mode %{public}u", mode);
1435     if (!CheckReadBufferMode(mode)) {
1436         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckReadBufferMode failed");
1437         return NVal::CreateNull(env).val_;
1438     }
1439 
1440     WebGLFramebuffer* readFrameBuffer = GetBoundFrameBuffer(env, WebGL2RenderingContextBase::READ_FRAMEBUFFER);
1441     if (readFrameBuffer == nullptr) {
1442         if (mode != WebGLRenderingContextBase::BACK && mode != WebGLRenderingContextBase::NONE) {
1443             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
1444                 "readFrameBuffer is nullptr, mode %{public}u", mode);
1445             return NVal::CreateNull(env).val_;
1446         }
1447         defaultReadBufferMode_ = mode;
1448         if (mode == WebGLRenderingContextBase::BACK) {
1449             mode = WebGLRenderingContextBase::COLOR_ATTACHMENT0;
1450         }
1451     } else {
1452         if (mode == WebGLRenderingContextBase::BACK) {
1453             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "mode %{public}u", mode);
1454             return NVal::CreateNull(env).val_;
1455         }
1456         readFrameBuffer->SetReadBufferMode(mode);
1457     }
1458     glReadBuffer(mode);
1459     return NVal::CreateNull(env).val_;
1460 }
1461 
RenderBufferStorageMultiSample(napi_env env,const TexStorageArg & arg,GLsizei samples)1462 napi_value WebGL2RenderingContextImpl::RenderBufferStorageMultiSample(
1463     napi_env env, const TexStorageArg& arg, GLsizei samples)
1464 {
1465     arg.Dump("WebGL2 renderbufferStorageMultisample");
1466     LOGD("WebGL2 renderbufferStorageMultisample samples %{public}d", samples);
1467 
1468     WebGLRenderbuffer* renderBuffer = CheckRenderBufferStorage(env, arg);
1469     if (renderBuffer == nullptr) {
1470         return NVal::CreateNull(env).val_;
1471     }
1472     if (samples < 0) {
1473         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "samples < 0");
1474         return NVal::CreateNull(env).val_;
1475     }
1476     if (arg.internalFormat == GL_DEPTH_STENCIL) {
1477         if (samples > 0) {
1478             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "GL_DEPTH_STENCIL samples > 0");
1479             return NVal::CreateNull(env).val_;
1480         }
1481         glRenderbufferStorage(arg.target, GL_DEPTH24_STENCIL8, arg.width, arg.height);
1482     } else {
1483         if (CheckInList(arg.internalFormat, WebGLTexture::GetSupportInternalFormatGroup1())) {
1484             if (samples > 0) {
1485                 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckInList group1 failed");
1486                 return NVal::CreateNull(env).val_;
1487             }
1488         } else if (!CheckInList(arg.internalFormat, WebGLTexture::GetSupportInternalFormatGroup2())) {
1489             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckInList group2 failed");
1490             return NVal::CreateNull(env).val_;
1491         }
1492         if (samples == 0) {
1493             glRenderbufferStorage(arg.target, arg.internalFormat, arg.width, arg.height);
1494         } else {
1495             glRenderbufferStorageMultisample(arg.target, samples, arg.internalFormat, arg.width, arg.height);
1496         }
1497     }
1498     renderBuffer->SetInternalFormat(arg.internalFormat);
1499     renderBuffer->SetSize(arg.width, arg.height);
1500     LOGD("WebGL2 renderbufferStorageMultisample result %{public}u", GetError_());
1501     return NVal::CreateNull(env).val_;
1502 }
1503 
BindBuffer(napi_env env,GLenum target,napi_value object)1504 napi_value WebGL2RenderingContextImpl::BindBuffer(napi_env env, GLenum target, napi_value object)
1505 {
1506     // support default value
1507     uint32_t bufferId = WebGLBuffer::DEFAULT_BUFFER;
1508     WebGLBuffer* webGlBuffer = GetValidBuffer(env, object);
1509     if (webGlBuffer != nullptr) {
1510         bufferId = webGlBuffer->GetBufferId();
1511     }
1512     uint32_t index = BoundBufferType::ARRAY_BUFFER;
1513     if (!CheckBufferTarget(env, target, index)) {
1514         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1515         return NVal::CreateNull(env).val_;
1516     }
1517     if (webGlBuffer != nullptr && !CheckBufferTargetCompatibility(env, target, webGlBuffer)) {
1518         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1519         return NVal::CreateNull(env).val_;
1520     }
1521     if (boundBufferIds_[index] && boundBufferIds_[index] != bufferId) {
1522         LOGD("WebGL2 bindBuffer has been bound bufferId %{public}u", boundBufferIds_[index]);
1523     }
1524     boundBufferIds_[index] = bufferId;
1525 
1526     glBindBuffer(target, static_cast<GLuint>(bufferId));
1527     if (webGlBuffer) {
1528         webGlBuffer->SetTarget(target);
1529     }
1530     LOGD("WebGL2 bindBuffer target %{public}u bufferId %{public}u result %{public}u",
1531         target, bufferId, GetError_());
1532     return NVal::CreateNull(env).val_;
1533 }
1534 
BindBufferBase(napi_env env,const BufferBaseArg & arg,napi_value bufferObj)1535 napi_value WebGL2RenderingContextImpl::BindBufferBase(napi_env env, const BufferBaseArg& arg, napi_value bufferObj)
1536 {
1537     GLuint bufferId = WebGLBuffer::DEFAULT_BUFFER;
1538     WebGLBuffer* webGlBuffer = GetValidBuffer(env, bufferObj);
1539     if (webGlBuffer != nullptr) {
1540         bufferId = webGlBuffer->GetBufferId();
1541     }
1542     if (!CheckBufferBindTarget(arg.target)) {
1543         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckBufferBindTarget failed");
1544         return NVal::CreateNull(env).val_;
1545     }
1546     if (webGlBuffer != nullptr && !CheckBufferTargetCompatibility(env, arg.target, webGlBuffer)) {
1547         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckBufferTargetCompatibility failed");
1548         return NVal::CreateNull(env).val_;
1549     }
1550     if (!UpdateBaseTargetBoundBuffer(env, arg.target, arg.index, bufferId)) {
1551         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "UpdateBaseTargetBoundBuffer failed");
1552         return NVal::CreateNull(env).val_;
1553     }
1554     if (webGlBuffer != nullptr && !webGlBuffer->GetTarget()) {
1555         webGlBuffer->SetTarget(arg.target);
1556     }
1557     glBindBufferBase(arg.target, arg.index, bufferId);
1558     LOGD("WebGL2 bindBufferBase target %{public}u %{public}u %{public}u result %{public}u ",
1559         arg.target, arg.index, bufferId, GetError_());
1560     return NVal::CreateNull(env).val_;
1561 }
1562 
BindBufferRange(napi_env env,const BufferBaseArg & arg,napi_value bufferObj,GLintptr offset,GLsizeiptr size)1563 napi_value WebGL2RenderingContextImpl::BindBufferRange(
1564     napi_env env, const BufferBaseArg& arg, napi_value bufferObj, GLintptr offset, GLsizeiptr size)
1565 {
1566     GLuint bufferId = WebGLBuffer::DEFAULT_BUFFER;
1567     WebGLBuffer* webGlBuffer = GetValidBuffer(env, bufferObj);
1568     if (webGlBuffer != nullptr) {
1569         bufferId = webGlBuffer->GetBufferId();
1570     }
1571     if (!CheckBufferBindTarget(arg.target)) {
1572         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckBufferBindTarget failed");
1573         return NVal::CreateNull(env).val_;
1574     }
1575     if (webGlBuffer != nullptr && !CheckBufferTargetCompatibility(env, arg.target, webGlBuffer)) {
1576         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckBufferTargetCompatibility failed");
1577         return NVal::CreateNull(env).val_;
1578     }
1579     if (!UpdateBaseTargetBoundBuffer(env, arg.target, arg.index, bufferId)) {
1580         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "UpdateBaseTargetBoundBuffer failed");
1581         return NVal::CreateNull(env).val_;
1582     }
1583     if (webGlBuffer != nullptr && !webGlBuffer->GetTarget()) {
1584         webGlBuffer->SetTarget(arg.target);
1585     }
1586     LOGD("WebGL2 bindBufferRange target %{public}u %{public}u %{public}u", arg.target, arg.index, bufferId);
1587     glBindBufferRange(arg.target, arg.index, bufferId, offset, size);
1588     return NVal::CreateNull(env).val_;
1589 }
1590 
DeleteBuffer(napi_env env,napi_value object)1591 napi_value WebGL2RenderingContextImpl::DeleteBuffer(napi_env env, napi_value object)
1592 {
1593     return WebGLRenderingContextBaseImpl::DeleteBuffer(env, object);
1594 }
1595 
GetUniformBlockIndex(napi_env env,napi_value programObj,const std::string & uniformBlockName)1596 napi_value WebGL2RenderingContextImpl::GetUniformBlockIndex(
1597     napi_env env, napi_value programObj, const std::string& uniformBlockName)
1598 {
1599     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1600     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1601     if (webGLProgram == nullptr) {
1602         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGLProgram is nullptr");
1603         return NVal::CreateInt64(env, -1).val_;
1604     }
1605     programId = webGLProgram->GetProgramId();
1606     if (!WebGLArg::CheckString(uniformBlockName)) {
1607         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckString failed");
1608         return NVal::CreateInt64(env, -1).val_;
1609     }
1610     GLuint returnValue = glGetUniformBlockIndex(programId, uniformBlockName.c_str());
1611     LOGD("WebGL2 getUniformBlockIndex name %{public}s programId %{public}u result %{public}u",
1612         uniformBlockName.c_str(), programId, returnValue);
1613     return NVal::CreateInt64(env, returnValue).val_;
1614 }
1615 
UniformBlockBinding(napi_env env,napi_value programObj,GLuint uniformBlockIndex,GLuint uniformBlockBinding)1616 napi_value WebGL2RenderingContextImpl::UniformBlockBinding(
1617     napi_env env, napi_value programObj, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
1618 {
1619     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1620     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1621     if (webGLProgram == nullptr) {
1622         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1623         return NVal::CreateNull(env).val_;
1624     }
1625     programId = webGLProgram->GetProgramId();
1626     glUniformBlockBinding(programId, uniformBlockIndex, uniformBlockBinding);
1627     LOGD("WebGL2 uniformBlockBinding programId %{public}u %{public}u %{public}u result %{public}u",
1628         programId, uniformBlockIndex, uniformBlockBinding, GetError_());
1629     return NVal::CreateNull(env).val_;
1630 }
1631 
InvalidateFrameBuffer(napi_env env,GLenum target,napi_value data)1632 napi_value WebGL2RenderingContextImpl::InvalidateFrameBuffer(napi_env env, GLenum target, napi_value data)
1633 {
1634     LOGD("WebGL2 invalidate Framebuffer target %{public}u", target);
1635     WebGLReadBufferArg bufferData(env);
1636     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_GLENUM);
1637     if (status != 0) {
1638         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1639             "WebGL2 invalidateFramebuffer failed to getbuffer data");
1640         return NVal::CreateNull(env).val_;
1641     }
1642     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1643     if (bufferData.GetBufferDataType() != BUFFER_DATA_GLENUM) {
1644         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1645             "WebGL2 invalidateFramebuffer invalid data type %{public}u", bufferData.GetBufferDataType());
1646         return NVal::CreateNull(env).val_;
1647     }
1648     if (bufferData.GetBufferType() != BUFFER_ARRAY) {
1649         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1650             "WebGL2 invalidateFramebuffer invalid type %{public}u", bufferData.GetBufferType());
1651         return NVal::CreateNull(env).val_;
1652     }
1653     glInvalidateFramebuffer(target, static_cast<GLsizei>(bufferData.GetBufferLength() / sizeof(GLenum)),
1654         reinterpret_cast<GLenum*>(bufferData.GetBuffer()));
1655     return NVal::CreateNull(env).val_;
1656 }
1657 
InvalidateSubFrameBuffer(napi_env env,GLenum target,napi_value data,const BufferPosition & position,const BufferSize & size)1658 napi_value WebGL2RenderingContextImpl::InvalidateSubFrameBuffer(
1659     napi_env env, GLenum target, napi_value data, const BufferPosition& position, const BufferSize& size)
1660 {
1661     WebGLReadBufferArg bufferData(env);
1662     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_GLENUM);
1663     if (status != 0) {
1664         LOGE("WebGL2 invalidateFramebuffer failed to getbuffer data");
1665         return NVal::CreateNull(env).val_;
1666     }
1667     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1668     if (bufferData.GetBufferDataType() != BUFFER_DATA_GLENUM) {
1669         LOGE("WebGL2 invalidateFramebuffer invalid data type %{public}d", bufferData.GetBufferDataType());
1670         return NVal::CreateNull(env).val_;
1671     }
1672     if (bufferData.GetBufferType() != BUFFER_ARRAY) {
1673         LOGE("WebGL2 invalidateFramebuffer invalid type %{public}d", bufferData.GetBufferType());
1674         return NVal::CreateNull(env).val_;
1675     }
1676 
1677     glInvalidateSubFramebuffer(target, static_cast<GLsizei>(bufferData.GetBufferLength() / sizeof(GLenum)),
1678         reinterpret_cast<GLenum*>(bufferData.GetBuffer()), position.x, position.y, size.width, size.height);
1679     return NVal::CreateNull(env).val_;
1680 }
1681 
GetInternalFormatParameter(napi_env env,GLenum target,GLenum internalFormat,GLenum pname)1682 napi_value WebGL2RenderingContextImpl::GetInternalFormatParameter(
1683     napi_env env, GLenum target, GLenum internalFormat, GLenum pname)
1684 {
1685     if (target != WebGLRenderingContextBase::RENDERBUFFER) {
1686         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "target %{publuc}u", target);
1687         return NVal::CreateNull(env).val_;
1688     }
1689     LOGD("WebGL2 getInternalformatParameter target %{public}u %{public}u %{public}u", target, internalFormat, pname);
1690     WebGLWriteBufferArg writeBuffer(env);
1691     if (CheckInList(internalFormat, WebGLTexture::GetSupportInternalFormatGroup1())) {
1692         return writeBuffer.ToExternalArray(BUFFER_DATA_INT_32);
1693     } else if (!CheckInList(internalFormat, WebGLTexture::GetSupportInternalFormatGroup2())) {
1694         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckInList failed");
1695         return NVal::CreateNull(env).val_;
1696     }
1697 
1698     GLint length = -1;
1699     if (pname == GL_SAMPLES) {
1700         glGetInternalformativ(target, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &length);
1701         LOGD("WebGL2 getInternalformatParameter length %{public}u", length);
1702     } else {
1703         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "pname %{publuc}u", pname);
1704         return NVal::CreateNull(env).val_;
1705     }
1706     if (length > 0) {
1707         GLint* params = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(length * sizeof(GLint)));
1708         if (params == nullptr) {
1709             return NVal::CreateNull(env).val_;
1710         }
1711         glGetInternalformativ(target, internalFormat, pname, length, params);
1712         writeBuffer.DumpBuffer(BUFFER_DATA_INT_32);
1713     }
1714     return writeBuffer.ToExternalArray(BUFFER_DATA_INT_32);
1715 }
1716 
TransformFeedbackVaryings(napi_env env,napi_value programObj,napi_value data,GLenum bufferMode)1717 napi_value WebGL2RenderingContextImpl::TransformFeedbackVaryings(
1718     napi_env env, napi_value programObj, napi_value data, GLenum bufferMode)
1719 {
1720     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1721     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1722     if (webGLProgram == nullptr) {
1723         return NVal::CreateNull(env).val_;
1724     }
1725     programId = webGLProgram->GetProgramId();
1726     if (bufferMode != GL_INTERLEAVED_ATTRIBS && bufferMode != GL_SEPARATE_ATTRIBS) {
1727         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1728         return NVal::CreateNull(env).val_;
1729     }
1730     std::vector<char*> list = {};
1731     bool succ = WebGLArg::GetStringList(env, data, list);
1732     if (!succ) {
1733         WebGLArg::FreeStringList(list);
1734         return NVal::CreateNull(env).val_;
1735     }
1736     glTransformFeedbackVaryings(programId, static_cast<GLsizei>(list.size()), list.data(), bufferMode);
1737     WebGLArg::FreeStringList(list);
1738     return NVal::CreateNull(env).val_;
1739 }
1740 
GetUniformIndices(napi_env env,napi_value programObj,napi_value data)1741 napi_value WebGL2RenderingContextImpl::GetUniformIndices(napi_env env, napi_value programObj, napi_value data)
1742 {
1743     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1744     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1745     if (webGLProgram == nullptr) {
1746         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1747         return NVal::CreateNull(env).val_;
1748     }
1749     programId = webGLProgram->GetProgramId();
1750 
1751     std::vector<char*> list = {};
1752     bool succ = WebGLArg::GetStringList(env, data, list);
1753     if (!succ) {
1754         WebGLArg::FreeStringList(list);
1755         return NVal::CreateNull(env).val_;
1756     }
1757     LOGD("WebGL2 getUniformIndices uniformCount %{public}zu", list.size());
1758 
1759     WebGLWriteBufferArg writeBuffer(env);
1760     napi_value result = NVal::CreateNull(env).val_;
1761     GLuint* uniformIndices = reinterpret_cast<GLuint*>(writeBuffer.AllocBuffer(list.size() * sizeof(GLuint)));
1762     if (uniformIndices != nullptr) {
1763         glGetUniformIndices(programId, static_cast<GLsizei>(list.size()), const_cast<const GLchar**>(list.data()),
1764             static_cast<GLuint*>(uniformIndices));
1765         writeBuffer.DumpBuffer(BUFFER_DATA_UINT_32);
1766         result = writeBuffer.ToNormalArray(BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32);
1767     }
1768     WebGLArg::FreeStringList(list);
1769     return result;
1770 }
1771 
GetActiveUniforms(napi_env env,napi_value programObj,napi_value data,GLenum pname)1772 napi_value WebGL2RenderingContextImpl::GetActiveUniforms(
1773     napi_env env, napi_value programObj, napi_value data, GLenum pname)
1774 {
1775     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1776     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1777     if (webGLProgram == nullptr) {
1778         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1779         return NVal::CreateNull(env).val_;
1780     }
1781     if (pname == GL_UNIFORM_NAME_LENGTH) {
1782         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1783         return NVal::CreateNull(env).val_;
1784     }
1785 
1786     programId = webGLProgram->GetProgramId();
1787     LOGD("WebGL2 getActiveUniforms programId %{public}u pname %{public}u", programId, pname);
1788     WebGLReadBufferArg bufferData(env);
1789     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_UINT_32);
1790     if (status != 0) {
1791         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1792             "WebGL2 invalidateFramebuffer failed to getbuffer data");
1793         return NVal::CreateNull(env).val_;
1794     }
1795     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1796     GLsizei size = static_cast<GLsizei>(bufferData.GetBufferLength() / bufferData.GetBufferDataSize());
1797 
1798     WebGLWriteBufferArg writeBuffer(env);
1799     GLint* params = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(size * sizeof(GLint)));
1800     if (params == nullptr) {
1801         return NVal::CreateNull(env).val_;
1802     }
1803     glGetActiveUniformsiv(
1804         programId, size, reinterpret_cast<GLuint*>(bufferData.GetBuffer()), pname, reinterpret_cast<GLint*>(params));
1805     switch (pname) {
1806         case GL_UNIFORM_TYPE:
1807         case GL_UNIFORM_SIZE:
1808             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_BIGUINT_64);
1809         case GL_UNIFORM_BLOCK_INDEX:
1810         case GL_UNIFORM_OFFSET:
1811         case GL_UNIFORM_ARRAY_STRIDE:
1812         case GL_UNIFORM_MATRIX_STRIDE:
1813             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_INT_32);
1814         case GL_UNIFORM_IS_ROW_MAJOR:
1815             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN);
1816         default:
1817             break;
1818     }
1819     return NVal::CreateNull(env).val_;
1820 }
1821 
GetActiveUniformBlockParameter(napi_env env,napi_value programObj,GLuint uniformBlockIndex,GLenum pname)1822 napi_value WebGL2RenderingContextImpl::GetActiveUniformBlockParameter(
1823     napi_env env, napi_value programObj, GLuint uniformBlockIndex, GLenum pname)
1824 {
1825     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1826     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1827     if (webGLProgram == nullptr) {
1828         return NVal::CreateInt64(env, -1).val_;
1829     }
1830     programId = webGLProgram->GetProgramId();
1831     LOGD("WebGL2 getActiveUniformBlockParameter programId %{public}u %{public}u %{public}u",
1832         programId, uniformBlockIndex, pname);
1833     switch (pname) {
1834         case GL_UNIFORM_BLOCK_BINDING:
1835         case GL_UNIFORM_BLOCK_DATA_SIZE:
1836         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: {
1837             GLint params;
1838             glGetActiveUniformBlockiv(programId, uniformBlockIndex, pname, &params);
1839             return NVal::CreateInt64(env, params).val_;
1840         }
1841         case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1842         case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: {
1843             GLint params;
1844             glGetActiveUniformBlockiv(programId, uniformBlockIndex, pname, &params);
1845             return NVal::CreateBool(env, params != GL_FALSE).val_;
1846         }
1847         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: {
1848             WebGLWriteBufferArg writeBuffer(env);
1849             GLint uniformCount = 1;
1850             glGetActiveUniformBlockiv(programId, uniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformCount);
1851             LOGD("WebGL2 getActiveUniformBlockParameter uniformCount %{public}d", uniformCount);
1852             GLint* params = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(uniformCount * sizeof(GLint)));
1853             if (params == nullptr) {
1854                 return NVal::CreateNull(env).val_;
1855             }
1856             glGetActiveUniformBlockiv(programId, uniformBlockIndex, pname, params);
1857             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_UINT_32);
1858         }
1859         default:
1860             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1861             return NVal::CreateNull(env).val_;
1862     }
1863     return NVal::CreateInt64(env, -1).val_;
1864 }
1865 
GetActiveUniformBlockName(napi_env env,napi_value programObj,GLuint uniformBlockIndex)1866 napi_value WebGL2RenderingContextImpl::GetActiveUniformBlockName(
1867     napi_env env, napi_value programObj, GLuint uniformBlockIndex)
1868 {
1869     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1870     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1871     if (webGLProgram == nullptr) {
1872         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGLProgram is nullptr");
1873         return NVal::CreateUTF8String(env, "").val_;
1874     }
1875     programId = webGLProgram->GetProgramId();
1876 
1877     GLint length = 0;
1878     GLsizei size = 0;
1879     glGetProgramiv(programId, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &length);
1880     if (length <= 0) {
1881         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "length < 0");
1882         return NVal::CreateUTF8String(env, "").val_;
1883     }
1884     std::unique_ptr<char[]> buf = std::make_unique<char[]>(length + 1);
1885     if (buf == nullptr) {
1886         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "buf is nullptr");
1887         return NVal::CreateNull(env).val_;
1888     }
1889     glGetActiveUniformBlockName(programId, uniformBlockIndex, length, &size, buf.get());
1890     LOGD("WebGL2 getActiveUniformBlockName programId %{public}u uniformBlockIndex  %{public}u name %{public}s",
1891         programId, uniformBlockIndex, buf.get());
1892     string str(buf.get(), size);
1893     return NVal::CreateUTF8String(env, str).val_;
1894 }
1895 
CheckClearBuffer(napi_env env,GLenum buffer,const WebGLReadBufferArg & bufferData)1896 GLenum WebGL2RenderingContextImpl::CheckClearBuffer(napi_env env, GLenum buffer, const WebGLReadBufferArg& bufferData)
1897 {
1898     size_t size = bufferData.GetBufferLength() / bufferData.GetBufferDataSize();
1899     switch (buffer) {
1900         case WebGL2RenderingContextBase::COLOR:
1901         case WebGLRenderingContextBase::FRONT:
1902         case WebGLRenderingContextBase::BACK:
1903         case WebGLRenderingContextBase::FRONT_AND_BACK:
1904             if (size < 4) { // 4 max element
1905                 return WebGLRenderingContextBase::INVALID_VALUE;
1906             }
1907             break;
1908         case WebGL2RenderingContextBase::DEPTH:
1909         case WebGL2RenderingContextBase::STENCIL:
1910         case WebGLRenderingContextBase::DEPTH_STENCIL:
1911             if (size < 1) {
1912                 return WebGLRenderingContextBase::INVALID_VALUE;
1913             }
1914             break;
1915         default:
1916             return WebGLRenderingContextBase::INVALID_ENUM;
1917     }
1918     return WebGLRenderingContextBase::NO_ERROR;
1919 }
1920 
CheckQueryTarget(napi_env env,GLenum target,uint32_t & index)1921 bool WebGL2RenderingContextImpl::CheckQueryTarget(napi_env env, GLenum target, uint32_t& index)
1922 {
1923     switch (target) {
1924         case WebGL2RenderingContextBase::ANY_SAMPLES_PASSED:
1925         case WebGL2RenderingContextBase::ANY_SAMPLES_PASSED_CONSERVATIVE:
1926             index = BoundQueryType::ANY_SAMPLES_PASSED;
1927             break;
1928         case WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1929             index = BoundQueryType::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
1930             break;
1931         default:
1932             return false;
1933     }
1934     return true;
1935 }
1936 
CheckTexStorage(napi_env env,const TexStorageArg & arg)1937 GLenum WebGL2RenderingContextImpl::CheckTexStorage(napi_env env, const TexStorageArg& arg)
1938 {
1939     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
1940     if (!texture) {
1941         LOGE("CheckTexStorage %{public}u", arg.target);
1942         return WebGLRenderingContextBase::INVALID_OPERATION;
1943     }
1944 
1945     if (!CheckStorageInternalFormat(env, arg.internalFormat)) {
1946         return WebGLRenderingContextBase::INVALID_ENUM;
1947     }
1948 
1949     if (arg.width <= 0 || arg.height <= 0 || arg.depth <= 0) {
1950         LOGE("CheckTexStorage invalid width %{public}d, height %{public}d, depth %{public}d",
1951             arg.width, arg.height, arg.depth);
1952         return WebGLRenderingContextBase::INVALID_VALUE;
1953     }
1954 
1955     if (arg.levels <= 0) {
1956         LOGE("CheckTexStorage invalid levels %{public}d", arg.levels);
1957         return WebGLRenderingContextBase::INVALID_VALUE;
1958     }
1959 
1960     if (arg.target == GL_TEXTURE_3D) {
1961         if (arg.levels > log2(std::max(std::max(arg.width, arg.height), arg.depth)) + 1) {
1962             LOGE("CheckTexStorage invalid levels %{public}d", arg.levels);
1963             return WebGLRenderingContextBase::INVALID_OPERATION;
1964         }
1965     } else {
1966         if (arg.levels > log2(std::max(arg.width, arg.height)) + 1) {
1967             LOGE("CheckTexStorage invalid %{public}d %{public}d",
1968                 arg.levels, static_cast<int>(log2(std::max(arg.width, arg.height)) + 1));
1969             return WebGLRenderingContextBase::INVALID_OPERATION;
1970         }
1971     }
1972     return WebGLRenderingContextBase::NO_ERROR;
1973 }
1974 
CheckBufferBindTarget(GLenum target)1975 bool WebGL2RenderingContextImpl::CheckBufferBindTarget(GLenum target)
1976 {
1977     if (target == GL_TRANSFORM_FEEDBACK_BUFFER || target == GL_UNIFORM_BUFFER) {
1978         return true;
1979     }
1980     return false;
1981 }
1982 
CheckTransformFeedbackBuffer(GLenum target,WebGLBuffer * buffer)1983 bool WebGL2RenderingContextImpl::CheckTransformFeedbackBuffer(GLenum target, WebGLBuffer* buffer)
1984 {
1985     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
1986         for (size_t i = 0; i < sizeof(boundBufferIds_) / boundBufferIds_[0]; i++) {
1987             if (i == BoundBufferType::TRANSFORM_FEEDBACK_BUFFER) {
1988                 continue;
1989             }
1990             if (boundBufferIds_[i] == buffer->GetBufferId()) {
1991                 LOGD("boundBufferIds_ %{public}u %{public}zu", boundBufferIds_[i], i);
1992                 return false;
1993             }
1994         }
1995         LOGD("boundIndexedUniformBuffers_ %{public}zu", boundIndexedUniformBuffers_.size());
1996         for (size_t i = 0; i < boundIndexedUniformBuffers_.size(); ++i) {
1997             if (boundIndexedUniformBuffers_[i] == buffer->GetBufferId()) {
1998                 return false;
1999             }
2000         }
2001     } else {
2002         LOGD("Get TRANSFORM_FEEDBACK_BUFFER id %{public}u ",
2003             boundBufferIds_[BoundBufferType::TRANSFORM_FEEDBACK_BUFFER]);
2004         if (boundBufferIds_[BoundBufferType::TRANSFORM_FEEDBACK_BUFFER] == buffer->GetBufferId()) {
2005             return false;
2006         }
2007         for (size_t i = 0; i < boundIndexedTransformFeedbackBuffers_.size(); ++i) {
2008             if (boundIndexedTransformFeedbackBuffers_[i] == buffer->GetBufferId()) {
2009                 return false;
2010             }
2011         }
2012     }
2013     return true;
2014 }
2015 
CheckBufferTargetCompatibility(napi_env env,GLenum target,WebGLBuffer * buffer)2016 bool WebGL2RenderingContextImpl::CheckBufferTargetCompatibility(napi_env env, GLenum target, WebGLBuffer* buffer)
2017 {
2018     LOGD("buffer target %{public}u %{public}u id %{public}u", buffer->GetTarget(), target, buffer->GetBufferId());
2019     switch (buffer->GetTarget()) {
2020         case GL_ELEMENT_ARRAY_BUFFER:
2021             switch (target) {
2022                 case GL_ARRAY_BUFFER:
2023                 case GL_PIXEL_PACK_BUFFER:
2024                 case GL_PIXEL_UNPACK_BUFFER:
2025                 case GL_TRANSFORM_FEEDBACK_BUFFER:
2026                 case GL_UNIFORM_BUFFER:
2027                     return false;
2028                 default:
2029                     break;
2030             }
2031             break;
2032         case GL_ARRAY_BUFFER:
2033         case GL_COPY_READ_BUFFER:
2034         case GL_COPY_WRITE_BUFFER:
2035         case GL_PIXEL_PACK_BUFFER:
2036         case GL_PIXEL_UNPACK_BUFFER:
2037         case GL_UNIFORM_BUFFER:
2038         case GL_TRANSFORM_FEEDBACK_BUFFER:
2039             if (target == GL_ELEMENT_ARRAY_BUFFER) {
2040                 return false;
2041             }
2042             break;
2043         default:
2044             break;
2045     }
2046     return CheckTransformFeedbackBuffer(target, buffer);
2047 }
2048 
UpdateBaseTargetBoundBuffer(napi_env env,GLenum target,GLuint index,GLuint bufferId)2049 bool WebGL2RenderingContextImpl::UpdateBaseTargetBoundBuffer(
2050     napi_env env, GLenum target, GLuint index, GLuint bufferId)
2051 {
2052     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
2053         if (index >= maxBoundTransformFeedbackBufferIndex_) {
2054             LOGE("Out of bound indexed transform feedback buffer %{public}u", index);
2055             return false;
2056         }
2057         boundIndexedTransformFeedbackBuffers_[index] = bufferId;
2058         boundBufferIds_[BoundBufferType::TRANSFORM_FEEDBACK_BUFFER] = bufferId;
2059         if (!bufferId) { // for delete
2060             boundIndexedTransformFeedbackBuffers_.erase(index);
2061         }
2062         return true;
2063     }
2064     if (target == GL_UNIFORM_BUFFER) {
2065         if (index >= maxBoundUniformBufferIndex_) {
2066             LOGE("Out of bound indexed uniform buffer %{public}u", index);
2067             return false;
2068         }
2069         boundIndexedUniformBuffers_[index] = bufferId;
2070         boundBufferIds_[BoundBufferType::UNIFORM_BUFFER] = bufferId;
2071         if (!bufferId) { // for delete
2072             boundIndexedUniformBuffers_.erase(index);
2073         }
2074         return true;
2075     }
2076     return false;
2077 }
2078 
CheckStorageInternalFormat(napi_env env,GLenum internalFormat)2079 bool WebGL2RenderingContextImpl::CheckStorageInternalFormat(napi_env env, GLenum internalFormat)
2080 {
2081     return CheckInList(internalFormat, {
2082         GL_R8,
2083         GL_R8_SNORM,
2084         GL_R16F,
2085         GL_R32F,
2086         GL_R8UI,
2087         GL_R8I,
2088         GL_R16UI,
2089         GL_R16I,
2090         GL_R32UI,
2091         GL_R32I,
2092         GL_RG8,
2093         GL_RG8_SNORM,
2094         GL_RG16F,
2095         GL_RG32F,
2096         GL_RG8UI,
2097         GL_RG8I,
2098         GL_RG16UI,
2099         GL_RG16I,
2100         GL_RG32UI,
2101         GL_RG32I,
2102         GL_RGB8,
2103         GL_SRGB8,
2104         GL_RGB565,
2105         GL_RGB8_SNORM,
2106         GL_R11F_G11F_B10F,
2107         GL_RGB9_E5,
2108         GL_RGB16F,
2109         GL_RGB32F,
2110         GL_RGB8UI,
2111         GL_RGB8I,
2112         GL_RGB16UI,
2113         GL_RGB16I,
2114         GL_RGB32UI,
2115         GL_RGB32I,
2116         GL_RGBA8,
2117         GL_SRGB8_ALPHA8,
2118         GL_RGBA8_SNORM,
2119         GL_RGB5_A1,
2120         GL_RGBA4,
2121         GL_RGB10_A2,
2122         GL_RGBA16F,
2123         GL_RGBA32F,
2124         GL_RGBA8UI,
2125         GL_RGBA8I,
2126         GL_RGB10_A2UI,
2127         GL_RGBA16UI,
2128         GL_RGBA16I,
2129         GL_RGBA32UI,
2130         GL_RGBA32I,
2131         GL_DEPTH_COMPONENT16,
2132         GL_DEPTH_COMPONENT24,
2133         GL_DEPTH_COMPONENT32F,
2134         GL_DEPTH24_STENCIL8,
2135         GL_DEPTH32F_STENCIL8,
2136         GL_COMPRESSED_R11_EAC,
2137         GL_COMPRESSED_SIGNED_R11_EAC,
2138         GL_COMPRESSED_RG11_EAC,
2139         GL_COMPRESSED_SIGNED_RG11_EAC,
2140         GL_COMPRESSED_RGB8_ETC2,
2141         GL_COMPRESSED_SRGB8_ETC2,
2142         GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
2143         GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
2144         GL_COMPRESSED_RGBA8_ETC2_EAC,
2145         GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
2146     });
2147 }
2148 } // namespace Impl
2149 } // namespace Rosen
2150 } // namespace OHOS
2151