• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "context/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 (!objQuery) {
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 (!objSampler) {
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 (!objVertexArrayObject) {
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 (!objSync) {
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}u %{public}u result %{public}u", syncId, returnValue, GetError_());
467     return NVal::CreateInt64(env, static_cast<int64_t>(returnValue)).val_;
468 }
469 
WaitSync(napi_env env,napi_value syncObj,GLbitfield flags,GLint64 timeout)470 napi_value WebGL2RenderingContextImpl::WaitSync(napi_env env, napi_value syncObj, GLbitfield flags, GLint64 timeout)
471 {
472     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
473     if (webGlSync == nullptr) {
474         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGlSync is nullptr");
475         return NVal::CreateNull(env).val_;
476     }
477     int64_t syncId = webGlSync->GetSync();
478     if (timeout < WebGL2RenderingContextBase::TIMEOUT_IGNORED) {
479         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "timeout %{pulic}" PRIi64, timeout);
480         return NVal::CreateNull(env).val_;
481     }
482     GLuint64 timeout64 = (timeout == -1) ? GL_TIMEOUT_IGNORED : static_cast<GLuint64>(timeout);
483     glWaitSync(reinterpret_cast<GLsync>(syncId), flags, timeout64);
484     LOGD("WebGL2 waitSync GL_TIMEOUT_IGNORED %{public}u", GL_TIMEOUT_IGNORED);
485     return NVal::CreateNull(env).val_;
486 }
487 
GetSyncParameter(napi_env env,napi_value syncObj,GLenum pname)488 napi_value WebGL2RenderingContextImpl::GetSyncParameter(napi_env env, napi_value syncObj, GLenum pname)
489 {
490     WebGLSync* webGlSync = WebGLObject::GetObjectInstance<WebGLSync>(env, syncObj);
491     if (webGlSync == nullptr) {
492         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
493         return NVal::CreateNull(env).val_;
494     }
495     int64_t syncId = webGlSync->GetSync();
496     LOGD("WebGL2 getSyncParameter syncId %{public}" PRIi64 " pname %{public}u ", syncId, pname);
497     if (CheckInList(pname, { GL_OBJECT_TYPE, GL_SYNC_STATUS, GL_SYNC_CONDITION, GL_SYNC_FLAGS })) {
498         GLint value = 0;
499         GLsizei length = -1;
500         glGetSynciv(reinterpret_cast<GLsync>(syncId), pname, 1, &length, &value);
501         LOGD("WebGL2 getSyncParameter value %{public}d ", value);
502         return NVal::CreateInt64(env, value).val_;
503     } else {
504         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
505         return NVal::CreateNull(env).val_;
506     }
507 }
508 
CreateTransformFeedback(napi_env env)509 napi_value WebGL2RenderingContextImpl::CreateTransformFeedback(napi_env env)
510 {
511     WebGLTransformFeedback* webGlTransformFeedback = nullptr;
512     napi_value objTransformFeedback = WebGLTransformFeedback::CreateObjectInstance(env, &webGlTransformFeedback).val_;
513     if (!objTransformFeedback || webGlTransformFeedback == nullptr) {
514         return NVal::CreateNull(env).val_;
515     }
516     GLuint transformFeedbackId = 0;
517     glGenTransformFeedbacks(1, &transformFeedbackId);
518     webGlTransformFeedback->SetTransformFeedback(transformFeedbackId);
519     LOGD("WebGL2 createTransformFeedback transformFeedbackId %{public}u", transformFeedbackId);
520     AddObject<WebGLTransformFeedback>(env, transformFeedbackId, objTransformFeedback);
521     return objTransformFeedback;
522 }
523 
DeleteTransformFeedback(napi_env env,napi_value obj)524 napi_value WebGL2RenderingContextImpl::DeleteTransformFeedback(napi_env env, napi_value obj)
525 {
526     uint32_t transformFeedbackId = WebGLTransformFeedback::DEFAULT_TRANSFORM_FEEDBACK;
527     WebGLTransformFeedback* webGlTransformFeedback = WebGLObject::GetObjectInstance<WebGLTransformFeedback>(env, obj);
528     if (webGlTransformFeedback == nullptr) {
529         return NVal::CreateNull(env).val_;
530     }
531     transformFeedbackId = webGlTransformFeedback->GetTransformFeedback();
532     DeleteObject<WebGLTransformFeedback>(env, transformFeedbackId);
533     glDeleteTransformFeedbacks(1, &transformFeedbackId);
534     LOGD("WebGL2 deleteTransformFeedback transformFeedbackId %{public}u", transformFeedbackId);
535     if (boundTransformFeedback_ != transformFeedbackId) {
536         LOGE("WebGL2 bindTransformFeedback bound %{public}u", boundTransformFeedback_);
537     }
538     boundTransformFeedback_ = 0;
539     return NVal::CreateNull(env).val_;
540 }
541 
IsTransformFeedback(napi_env env,napi_value obj)542 napi_value WebGL2RenderingContextImpl::IsTransformFeedback(napi_env env, napi_value obj)
543 {
544     WebGLTransformFeedback* webGlTransformFeedback = WebGLObject::GetObjectInstance<WebGLTransformFeedback>(env, obj);
545     if (webGlTransformFeedback == nullptr) {
546         return NVal::CreateBool(env, false).val_;
547     }
548     GLuint transformFeedbackId = webGlTransformFeedback->GetTransformFeedback();
549     LOGD("WebGL2 isTransformFeedback transformFeedbackId %{public}u bound %{public}u",
550         transformFeedbackId, boundTransformFeedback_);
551     if (GetObjectInstance<WebGLTransformFeedback>(env, transformFeedbackId) != nullptr &&
552         boundTransformFeedback_ == transformFeedbackId) {
553         return NVal::CreateBool(env, true).val_;
554     }
555     return NVal::CreateBool(env, false).val_;
556 }
557 
BindTransformFeedback(napi_env env,napi_value obj,GLenum target)558 napi_value WebGL2RenderingContextImpl::BindTransformFeedback(napi_env env, napi_value obj, GLenum target)
559 {
560     WebGLTransformFeedback* webGlTransformFeedback = WebGLObject::GetObjectInstance<WebGLTransformFeedback>(env, obj);
561     if (webGlTransformFeedback == nullptr) {
562         return NVal::CreateBool(env, false).val_;
563     }
564     GLuint transformFeedbackId = webGlTransformFeedback->GetTransformFeedback();
565     if (target != GL_TRANSFORM_FEEDBACK) {
566         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
567         return NVal::CreateNull(env).val_;
568     }
569     if (boundTransformFeedback_ && boundTransformFeedback_ != transformFeedbackId) {
570         LOGE("WebGL2 bindTransformFeedback has been bound %{public}u", boundTransformFeedback_);
571     }
572     boundTransformFeedback_ = transformFeedbackId;
573     glBindTransformFeedback(target, transformFeedbackId);
574     LOGD("WebGL2 bindTransformFeedback id %{public}u target %{public}u result %{public}u",
575         transformFeedbackId, target, GetError_());
576     if (webGlTransformFeedback) {
577         webGlTransformFeedback->SetTarget(target);
578     }
579     return NVal::CreateNull(env).val_;
580 }
581 
GetTransformFeedbackVaryingType(GLuint programId,GLint index)582 static GLint GetTransformFeedbackVaryingType(GLuint programId, GLint index)
583 {
584     GLint params = 0;
585     glGetProgramiv(programId, WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_VARYINGS, &params);
586     LOGD("WebGL2 GetTransformFeedbackVaryingType programId %{public}u params %{public}d", programId, params);
587     return params;
588 }
589 
BeginTransformFeedback(napi_env env,GLenum primitiveMode)590 napi_value WebGL2RenderingContextImpl::BeginTransformFeedback(napi_env env, GLenum primitiveMode)
591 {
592     if (!CheckInList(primitiveMode, { WebGLRenderingContextBase::POINTS, WebGLRenderingContextBase::LINES,
593         WebGLRenderingContextBase::TRIANGLES })) {
594         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
595         return NVal::CreateNull(env).val_;
596     }
597     if (GetTransformFeedbackVaryingType(currentProgramId_, boundTransformFeedback_) <= 0) {
598         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
599         return NVal::CreateNull(env).val_;
600     }
601     glBeginTransformFeedback(primitiveMode);
602     LOGD("WebGL2 beginTransformFeedback primitiveMode %{public}u result %{public}u", primitiveMode, GetError_());
603     return NVal::CreateNull(env).val_;
604 }
605 
EndTransformFeedback(napi_env env)606 napi_value WebGL2RenderingContextImpl::EndTransformFeedback(napi_env env)
607 {
608     LOGD("WebGL2 endTransformFeedback");
609     if (GetTransformFeedbackVaryingType(currentProgramId_, boundTransformFeedback_) <= 0) {
610         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
611         return NVal::CreateNull(env).val_;
612     }
613     glEndTransformFeedback();
614     return NVal::CreateNull(env).val_;
615 }
616 
GetTransformFeedbackVarying(napi_env env,napi_value programObj,GLuint index)617 napi_value WebGL2RenderingContextImpl::GetTransformFeedbackVarying(napi_env env, napi_value programObj, GLuint index)
618 {
619     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
620     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
621     if (webGLProgram == nullptr) {
622         return NVal::CreateNull(env).val_;
623     }
624     programId = webGLProgram->GetProgramId();
625 
626     WebGLActiveInfo* webGLActiveInfo = nullptr;
627     napi_value objActiveInfo = WebGLActiveInfo::CreateObjectInstance(env, &webGLActiveInfo).val_;
628     if (!objActiveInfo) {
629         return NVal::CreateNull(env).val_;
630     }
631 
632     GLsizei bufSize = WEBGL_ACTIVE_INFO_NAME_MAX_LENGTH;
633     GLsizei length = 0;
634     GLsizei size = 0;
635     GLenum type = 0;
636     GLchar name[WEBGL_ACTIVE_INFO_NAME_MAX_LENGTH] = { 0 };
637     glGetTransformFeedbackVarying(programId, index, bufSize, &length, &size, &type, name);
638     LOGD("WebGL2 getTransformFeedbackVarying: name '%{public}s' %{public}u length %{public}d %{public}d"
639         " index %{public}u", name, type, length, size, index);
640     if (type == 0) {
641         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
642         return NVal::CreateNull(env).val_;
643     }
644     webGLActiveInfo->SetActiveName(name, WEBGL_ACTIVE_INFO_NAME_MAX_LENGTH);
645     webGLActiveInfo->SetActiveSize(size);
646     webGLActiveInfo->SetActiveType(type);
647     return objActiveInfo;
648 }
649 
TexStorage2D(napi_env env,const TexStorageArg & arg)650 napi_value WebGL2RenderingContextImpl::TexStorage2D(napi_env env, const TexStorageArg& arg)
651 {
652     arg.Dump("WebGL2 texStorage2D");
653     if (arg.target != GL_TEXTURE_2D && arg.target != GL_TEXTURE_CUBE_MAP) {
654         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
655         return NVal::CreateNull(env).val_;
656     }
657     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
658     if (texture == nullptr) {
659         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
660         return NVal::CreateNull(env).val_;
661     }
662     GLenum result = CheckTexStorage(env, arg);
663     if (result != WebGLRenderingContextBase::NO_ERROR) {
664         SET_ERROR_WITH_LOG(result, "CheckTexStorage failed");
665         return NVal::CreateNull(env).val_;
666     }
667     glTexStorage2D(arg.target, arg.levels, arg.internalFormat, arg.width, arg.height);
668     texture->SetTexStorageInfo(&arg);
669     return NVal::CreateNull(env).val_;
670 }
671 
TexStorage3D(napi_env env,const TexStorageArg & arg)672 napi_value WebGL2RenderingContextImpl::TexStorage3D(napi_env env, const TexStorageArg& arg)
673 {
674     arg.Dump("WebGL texStorage3D");
675     if (arg.target != GL_TEXTURE_3D && arg.target != GL_TEXTURE_2D_ARRAY) {
676         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
677         return NVal::CreateNull(env).val_;
678     }
679     GLenum result = CheckTexStorage(env, arg);
680     if (result != WebGLRenderingContextBase::NO_ERROR) {
681         SET_ERROR_WITH_LOG(result, "CheckTexStorage failed");
682         return NVal::CreateNull(env).val_;
683     }
684     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
685     if (texture == nullptr) {
686         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
687         return NVal::CreateNull(env).val_;
688     }
689     glTexStorage3D(arg.target, arg.levels, arg.internalFormat, arg.width, arg.height, arg.depth);
690     texture->SetTexStorageInfo(&arg);
691     LOGD("WebGL texStorage3D result %{public}u", GetError_());
692     return NVal::CreateNull(env).val_;
693 }
694 
CheckTexImage3D(napi_env env,const TexImageArg & imgArg)695 GLenum WebGL2RenderingContextImpl::CheckTexImage3D(napi_env env, const TexImageArg& imgArg)
696 {
697     switch (imgArg.target) {
698         case GL_TEXTURE_3D:
699         case GL_TEXTURE_2D_ARRAY:
700             break;
701         default:
702             return WebGLRenderingContextBase::INVALID_ENUM;
703     }
704     GLenum result = CheckTextureLevel(imgArg.target, imgArg.level);
705     if (result != WebGLRenderingContextBase::NO_ERROR) {
706         return result;
707     }
708     return CheckTextureFormatAndType(env, imgArg.internalFormat, imgArg.format, imgArg.type, imgArg.level);
709 }
710 
TexImage3D(napi_env env,const TexImageArg & arg,napi_value source)711 napi_value WebGL2RenderingContextImpl::TexImage3D(napi_env env, const TexImageArg& arg, napi_value source)
712 {
713     TexImageArg imgArg(arg);
714     imgArg.Dump("WebGL2 texImage3D");
715     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
716     if (texture == nullptr) {
717         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
718         return NVal::CreateNull(env).val_;
719     }
720 
721     GLenum result = CheckTexImage3D(env, imgArg);
722     if (result != WebGLRenderingContextBase::NO_ERROR) {
723         SET_ERROR_WITH_LOG(result, "CheckTexImage3D failed");
724         return NVal::CreateNull(env).val_;
725     }
726     GLvoid* data = nullptr;
727     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
728     if (!NVal(env, source).IsNull()) {
729         result = imageSource.GenImageSource(
730             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, source);
731         if (result) {
732             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
733             return NVal::CreateNull(env).val_;
734         }
735         data = imageSource.GetImageSourceData();
736         imgArg.width = imageSource.GetWidth();
737         imgArg.height = imageSource.GetHeight();
738     }
739 
740     glTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth,
741         imgArg.border, imgArg.format, imgArg.type, data);
742     texture->SetTextureLevel({ imgArg.target, imgArg.level,
743         imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth, imgArg.type });
744     LOGD("WebGL2 texImage3D result %{public}u", GetError_());
745     return NVal::CreateNull(env).val_;
746 }
747 
TexImage3D(napi_env env,const TexImageArg & imgArg,napi_value dataObj,GLuint srcOffset)748 napi_value WebGL2RenderingContextImpl::TexImage3D(
749     napi_env env, const TexImageArg& imgArg, napi_value dataObj, GLuint srcOffset)
750 {
751     imgArg.Dump("WebGL2 texImage3D");
752     GLenum result = CheckTexImage3D(env, imgArg);
753     if (result != WebGLRenderingContextBase::NO_ERROR) {
754         SET_ERROR_WITH_LOG(result, "CheckTexImage3D failed");
755         return NVal::CreateNull(env).val_;
756     }
757 
758     GLvoid* data = nullptr;
759     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
760     if (!NVal(env, dataObj).IsNull()) {
761         result = imageSource.GenImageSource(
762             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, dataObj, srcOffset);
763         if (result) {
764             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
765             return NVal::CreateNull(env).val_;
766         }
767         data = imageSource.GetImageSourceData();
768     }
769     if (data != nullptr) {
770         GLenum result = CheckTextureDataBuffer(imgArg, imageSource.GetWebGLReadBuffer());
771         if (result) {
772             SET_ERROR_WITH_LOG(result, "CheckTextureDataBuffer failed");
773             return NVal::CreateNull(env).val_;
774         }
775     }
776     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
777     if (texture == nullptr) {
778         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "texture is nullptr");
779         return NVal::CreateNull(env).val_;
780     }
781     glTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth,
782         imgArg.border, imgArg.format, imgArg.type, data);
783     texture->SetTextureLevel(imgArg);
784     LOGD("WebGL2 texImage3D result %{public}u", GetError_());
785     return NVal::CreateNull(env).val_;
786 }
787 
TexImage3D(napi_env env,const TexImageArg & imgArg,GLintptr pboOffset)788 napi_value WebGL2RenderingContextImpl::TexImage3D(napi_env env, const TexImageArg& imgArg, GLintptr pboOffset)
789 {
790     imgArg.Dump("WebGL2 texImage3D");
791     GLenum result = CheckTexImage3D(env, imgArg);
792     if (result != WebGLRenderingContextBase::NO_ERROR) {
793         SET_ERROR(result);
794         return NVal::CreateNull(env).val_;
795     }
796     glTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height, imgArg.depth,
797         imgArg.border, imgArg.format, imgArg.type, reinterpret_cast<void*>(pboOffset));
798     LOGD("WebGL2 texImage3D result %{public}u", GetError_());
799     return NVal::CreateNull(env).val_;
800 }
801 
CheckTexSubImage3D(napi_env env,const TexSubImage3DArg & arg)802 GLenum WebGL2RenderingContextImpl::CheckTexSubImage3D(napi_env env, const TexSubImage3DArg& arg)
803 {
804     switch (arg.target) {
805         case GL_TEXTURE_3D:
806         case GL_TEXTURE_2D_ARRAY:
807             break;
808         default:
809             return WebGLRenderingContextBase::INVALID_ENUM;
810     }
811     GLenum result = CheckTextureLevel(arg.target, arg.level);
812     if (result != WebGLRenderingContextBase::NO_ERROR) {
813         return result;
814     }
815     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
816     if (texture == nullptr) {
817         return WebGLRenderingContextBase::INVALID_VALUE;
818     }
819 
820     if (!texture->CheckValid(arg.target, arg.level)) {
821         return WebGLRenderingContextBase::INVALID_OPERATION;
822     }
823 
824     if (!WebGLTexture::CheckTextureSize(arg.xOffset, arg.width, texture->GetWidth(arg.target, arg.level)) ||
825         !WebGLTexture::CheckTextureSize(arg.yOffset, arg.height, texture->GetHeight(arg.target, arg.level)) ||
826         !WebGLTexture::CheckTextureSize(arg.zOffset, arg.depth, texture->GetDepth(arg.target, arg.level))) {
827         return WebGLRenderingContextBase::INVALID_VALUE;
828     }
829     GLenum internalFormat = texture->GetInternalFormat(arg.target, arg.level);
830     return CheckTextureFormatAndType(env, internalFormat, arg.format, arg.type, arg.level);
831 }
832 
TexSubImage3D(napi_env env,const TexSubImage3DArg & arg,napi_value source)833 napi_value WebGL2RenderingContextImpl::TexSubImage3D(napi_env env, const TexSubImage3DArg& arg, napi_value source)
834 {
835     TexSubImage3DArg imgArg(arg);
836     imgArg.Dump("WebGL2 texSubImage3D source");
837     GLvoid* data = nullptr;
838     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
839     if (!NVal(env, source).IsNull()) {
840         GLenum result = imageSource.GenImageSource(
841             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, source);
842         if (result) {
843             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
844             return NVal::CreateNull(env).val_;
845         }
846         data = imageSource.GetImageSourceData();
847         imgArg.width = imageSource.GetWidth();
848         imgArg.height = imageSource.GetHeight();
849     } else {
850         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
851         return NVal::CreateNull(env).val_;
852     }
853     GLenum result = CheckTexSubImage3D(env, imgArg);
854     if (result != WebGLRenderingContextBase::NO_ERROR) {
855         SET_ERROR_WITH_LOG(result, "CheckTexSubImage3D failed");
856         return NVal::CreateNull(env).val_;
857     }
858     glTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
859         imgArg.height, imgArg.depth, imgArg.format, imgArg.type, data);
860     LOGD("WebGL2 texSubImage3D result %{public}u", GetError_());
861     return NVal::CreateNull(env).val_;
862 }
863 
TexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,napi_value dataObj,GLuint srcOffset)864 napi_value WebGL2RenderingContextImpl::TexSubImage3D(
865     napi_env env, const TexSubImage3DArg& imgArg, napi_value dataObj, GLuint srcOffset)
866 {
867     imgArg.Dump("WebGL2 texSubImage3D data buffer");
868 
869     WebGLImageSource imageSource(env, version_, unpackFlipY_, unpackPremultiplyAlpha_);
870     GLvoid* data = nullptr;
871     bool changeUnpackAlignment = false;
872     if (!NVal(env, dataObj).IsNull()) {
873         GLenum result = imageSource.GenImageSource(
874             { imgArg.format, imgArg.type, imgArg.width, imgArg.height, imgArg.depth }, dataObj, srcOffset);
875         if (result) {
876             SET_ERROR_WITH_LOG(result, "GenImageSource failed");
877             return NVal::CreateNull(env).val_;
878         }
879         data = imageSource.GetImageSourceData();
880         changeUnpackAlignment = unpackFlipY_ || unpackPremultiplyAlpha_;
881     } else {
882         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
883         return NVal::CreateNull(env).val_;
884     }
885 
886     GLenum result = CheckTexSubImage3D(env, imgArg);
887     if (result != WebGLRenderingContextBase::NO_ERROR) {
888         SET_ERROR_WITH_LOG(result, "CheckTexSubImage3D failed");
889         return NVal::CreateNull(env).val_;
890     }
891 
892     if (changeUnpackAlignment) {
893         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
894     }
895     glTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
896         imgArg.height, imgArg.depth, imgArg.format, imgArg.type, data);
897     if (changeUnpackAlignment) {
898         glPixelStorei(GL_UNPACK_ALIGNMENT, unpackAlignment_);
899     }
900     LOGD("WebGL2 texSubImage3D result %{public}u", GetError_());
901     return NVal::CreateNull(env).val_;
902 }
903 
TexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,GLintptr pboOffset)904 napi_value WebGL2RenderingContextImpl::TexSubImage3D(napi_env env, const TexSubImage3DArg& imgArg, GLintptr pboOffset)
905 {
906     imgArg.Dump("WebGL2 texSubImage3D pboOffset");
907     GLenum result = CheckTexSubImage3D(env, imgArg);
908     if (result != WebGLRenderingContextBase::NO_ERROR) {
909         SET_ERROR(result);
910         return NVal::CreateNull(env).val_;
911     }
912     glTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
913         imgArg.height, imgArg.depth, imgArg.format, imgArg.type, reinterpret_cast<void*>(pboOffset));
914     LOGD("WebGL2 texSubImage3D result %{public}u", GetError_());
915     return NVal::CreateNull(env).val_;
916 }
917 
CopyTexSubImage3D(napi_env env,const CopyTexSubImage3DArg & imgArg)918 napi_value WebGL2RenderingContextImpl::CopyTexSubImage3D(napi_env env, const CopyTexSubImage3DArg& imgArg)
919 {
920     imgArg.Dump("WebGL2 copyTexSubImage3D");
921     GLenum result = CheckCopyTexSubImage(env, imgArg);
922     if (result) {
923         SET_ERROR_WITH_LOG(result, "CheckCopyTexSubImage failed");
924         return NVal::CreateNull(env).val_;
925     }
926     GLuint frameBufferId = 0;
927     result = CheckReadBufferAndGetInfo(env, &frameBufferId, nullptr, nullptr);
928     if (result != WebGLRenderingContextBase::NO_ERROR) {
929         SET_ERROR_WITH_LOG(result, "CheckReadBufferAndGetInfo failed");
930         return NVal::CreateNull(env).val_;
931     }
932     glCopyTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.x, imgArg.y,
933         imgArg.width, imgArg.height);
934     LOGD("WebGL2 copyTexSubImage3D result %{public}u", GetError_());
935     return NVal::CreateNull(env).val_;
936 }
937 
CompressedTexImage3D(napi_env env,const TexImageArg & imgArg,GLsizei imageSize,GLintptr offset)938 napi_value WebGL2RenderingContextImpl::CompressedTexImage3D(
939     napi_env env, const TexImageArg& imgArg, GLsizei imageSize, GLintptr offset)
940 {
941     imgArg.Dump("WebGL2 compressedTexImage3D");
942     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
943     if (texture == nullptr) {
944         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
945         return NVal::CreateNull(env).val_;
946     }
947     if (texture->CheckImmutable()) {
948         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckImmutable failed");
949         return NVal::CreateNull(env).val_;
950     }
951 
952     glCompressedTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height,
953         imgArg.depth, imgArg.border, imageSize, reinterpret_cast<void*>(offset));
954     LOGD("WebGL2 copyTexSubImage3D result %{public}u", GetError_());
955     return NVal::CreateNull(env).val_;
956 }
957 
CompressedTexImage3D(napi_env env,const TexImageArg & imgArg,napi_value dataObj,GLuint srcOffset,GLuint srcLengthOverride)958 napi_value WebGL2RenderingContextImpl::CompressedTexImage3D(
959     napi_env env, const TexImageArg& imgArg, napi_value dataObj, GLuint srcOffset, GLuint srcLengthOverride)
960 {
961     imgArg.Dump("WebGL2 compressedTexImage3D");
962     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
963     if (texture == nullptr) {
964         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
965         return NVal::CreateNull(env).val_;
966     }
967     if (texture->CheckImmutable()) {
968         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckImmutable failed");
969         return NVal::CreateNull(env).val_;
970     }
971     WebGLReadBufferArg readData(env);
972     GLvoid* data = nullptr;
973     GLsizei length = 0;
974     if (NVal(env, dataObj).IsNull()) {
975         napi_status status = readData.GenBufferData(dataObj, BUFFER_DATA_FLOAT_32);
976         if (status != napi_ok) {
977             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GenBufferData failed");
978             return NVal::CreateNull(env).val_;
979         }
980         readData.DumpBuffer(readData.GetBufferDataType());
981         data = reinterpret_cast<void*>(readData.GetBuffer() + srcOffset);
982         length = static_cast<GLsizei>((srcLengthOverride == 0) ? readData.GetBufferLength() : srcLengthOverride);
983     }
984     glCompressedTexImage3D(imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height,
985         imgArg.depth, imgArg.border, length, data);
986     texture->SetTextureLevel({ imgArg.target, imgArg.level, imgArg.internalFormat, imgArg.width, imgArg.height,
987         imgArg.depth, GL_UNSIGNED_BYTE });
988     LOGD("WebGL2 compressedTexImage3D result %{public}u", GetError_());
989     return NVal::CreateNull(env).val_;
990 }
991 
CompressedTexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,GLsizei imageSize,GLintptr offset)992 napi_value WebGL2RenderingContextImpl::CompressedTexSubImage3D(
993     napi_env env, const TexSubImage3DArg& imgArg, GLsizei imageSize, GLintptr offset)
994 {
995     imgArg.Dump("WebGL2 compressedTexSubImage3D");
996     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
997     if (texture == nullptr) {
998         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
999         return NVal::CreateNull(env).val_;
1000     }
1001     if (imgArg.format != texture->GetInternalFormat(imgArg.target, imgArg.level)) {
1002         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1003         return NVal::CreateNull(env).val_;
1004     }
1005     glCompressedTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
1006         imgArg.height, imgArg.depth, imgArg.format, imageSize, reinterpret_cast<void*>(offset));
1007     LOGD("WebGL2 compressedTexSubImage3D result %{public}u", GetError_());
1008     return NVal::CreateNull(env).val_;
1009 }
1010 
CompressedTexSubImage3D(napi_env env,const TexSubImage3DArg & imgArg,napi_value dataObj,GLuint srcOffset,GLuint srcLengthOverride)1011 napi_value WebGL2RenderingContextImpl::CompressedTexSubImage3D(
1012     napi_env env, const TexSubImage3DArg& imgArg, napi_value dataObj, GLuint srcOffset, GLuint srcLengthOverride)
1013 {
1014     imgArg.Dump("WebGL2 compressedTexSubImage3D");
1015     WebGLTexture* texture = GetBoundTexture(env, imgArg.target, true);
1016     if (texture == nullptr) {
1017         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "texture is nullptr");
1018         return NVal::CreateNull(env).val_;
1019     }
1020     if (imgArg.format != texture->GetInternalFormat(imgArg.target, imgArg.level)) {
1021         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1022         return NVal::CreateNull(env).val_;
1023     }
1024 
1025     WebGLReadBufferArg readData(env);
1026     GLvoid* data = nullptr;
1027     GLsizei length = 0;
1028     if (NVal(env, dataObj).IsNull()) {
1029         napi_status status = readData.GenBufferData(dataObj, BUFFER_DATA_FLOAT_32);
1030         if (status != napi_ok) {
1031             SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1032             return NVal::CreateNull(env).val_;
1033         }
1034         readData.DumpBuffer(readData.GetBufferDataType());
1035         data = reinterpret_cast<void*>(readData.GetBuffer() + srcOffset);
1036         length = static_cast<GLsizei>((srcLengthOverride == 0) ? readData.GetBufferLength() : srcLengthOverride);
1037     }
1038 
1039     glCompressedTexSubImage3D(imgArg.target, imgArg.level, imgArg.xOffset, imgArg.yOffset, imgArg.zOffset, imgArg.width,
1040         imgArg.height, imgArg.depth, imgArg.format, length, data);
1041     LOGD("WebGL2 compressedTexSubImage3D result %{public}u", GetError_());
1042     return NVal::CreateNull(env).val_;
1043 }
1044 
ClearBufferV(napi_env env,GLenum buffer,GLint drawBuffer,napi_value value,int64_t srcOffset,BufferDataType type)1045 napi_value WebGL2RenderingContextImpl::ClearBufferV(
1046     napi_env env, GLenum buffer, GLint drawBuffer, napi_value value, int64_t srcOffset, BufferDataType type)
1047 {
1048     LOGD("WebGL2 clearBuffer buffer %{public}u %{public}d srcOffset %{public}" PRIi64, buffer, drawBuffer, srcOffset);
1049     WebGLReadBufferArg bufferData(env);
1050     napi_status status = bufferData.GenBufferData(value, type);
1051     if (status != 0) {
1052         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL2 clearBuffer failed to getbuffer data");
1053         return NVal::CreateNull(env).val_;
1054     }
1055     if (bufferData.GetBufferDataType() != type) {
1056         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1057             "WebGL2 clearBuffer invalid buffer data type %{public}d", bufferData.GetBufferDataType());
1058         return NVal::CreateNull(env).val_;
1059     }
1060 
1061     GLenum result = CheckClearBuffer(env, buffer, bufferData);
1062     if (result != WebGLRenderingContextBase::NO_ERROR) {
1063         SET_ERROR_WITH_LOG(result, "WebGL2 clearBuffer invalid clear buffer");
1064         return NVal::CreateNull(env).val_;
1065     }
1066 
1067     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1068     switch (type) {
1069         case BUFFER_DATA_FLOAT_32:
1070             glClearBufferfv(buffer, drawBuffer, reinterpret_cast<GLfloat*>(bufferData.GetBuffer() + srcOffset));
1071             break;
1072         case BUFFER_DATA_INT_32:
1073             glClearBufferiv(buffer, drawBuffer, reinterpret_cast<GLint*>(bufferData.GetBuffer() + srcOffset));
1074             break;
1075         case BUFFER_DATA_UINT_32:
1076             glClearBufferuiv(buffer, drawBuffer, reinterpret_cast<GLuint*>(bufferData.GetBuffer() + srcOffset));
1077             break;
1078         default:
1079             break;
1080     }
1081     LOGD("WebGL2 clearBuffer buffer %{public}u result %{public}u", buffer, GetError_());
1082     return NVal::CreateNull(env).val_;
1083 }
1084 
ClearBufferfi(napi_env env,GLenum buffer,GLint drawBuffer,GLfloat depth,GLint stencil)1085 napi_value WebGL2RenderingContextImpl::ClearBufferfi(
1086     napi_env env, GLenum buffer, GLint drawBuffer, GLfloat depth, GLint stencil)
1087 {
1088     if (buffer != WebGLRenderingContextBase::DEPTH_STENCIL) {
1089         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1090         return NVal::CreateNull(env).val_;
1091     }
1092     glClearBufferfi(buffer, drawBuffer, depth, stencil);
1093     LOGD("WebGL2 clearBufferfi buffer %{public}u %{public}d depth %{public}f %{public}d result %{public}u",
1094         buffer, drawBuffer, depth, stencil, GetError_());
1095     return NVal::CreateNull(env).val_;
1096 }
1097 
GetIndexedParameter(napi_env env,GLenum target,GLuint index)1098 napi_value WebGL2RenderingContextImpl::GetIndexedParameter(napi_env env, GLenum target, GLuint index)
1099 {
1100     LOGD("WebGL2 getIndexedParameter index %{public}u", index);
1101     switch (target) {
1102         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: {
1103             if (index >= maxBoundTransformFeedbackBufferIndex_) {
1104                 return NVal::CreateNull(env).val_;
1105             }
1106             return GetObject<WebGLBuffer>(env, boundIndexedTransformFeedbackBuffers_[index]);
1107         }
1108         case GL_UNIFORM_BUFFER_BINDING: {
1109             if (index >= maxBoundUniformBufferIndex_) {
1110                 return NVal::CreateNull(env).val_;
1111             }
1112             return GetObject<WebGLBuffer>(env, boundIndexedUniformBuffers_[index]);
1113         }
1114         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
1115         case GL_UNIFORM_BUFFER_SIZE:
1116         case GL_UNIFORM_BUFFER_START: {
1117             int64_t data;
1118             glGetInteger64i_v(target, index, &data);
1119             LOGD("WebGL getIndexedParameter end");
1120             return NVal::CreateInt64(env, data).val_;
1121         }
1122         default :
1123             LOGD("WebGL getIndexedParameter get nullptr");
1124             return NVal::CreateNull(env).val_;
1125     }
1126 }
1127 
GetFragDataLocation(napi_env env,napi_value programObj,const std::string & name)1128 napi_value WebGL2RenderingContextImpl::GetFragDataLocation(napi_env env, napi_value programObj, const std::string& name)
1129 {
1130     GLuint program = WebGLProgram::DEFAULT_PROGRAM_ID;
1131     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1132     if (webGLProgram == nullptr) {
1133         return NVal::CreateInt64(env, -1).val_;
1134     }
1135     program = webGLProgram->GetProgramId();
1136 
1137     GLint res = glGetFragDataLocation(program, const_cast<char*>(name.c_str()));
1138     LOGD("WebGL2 getFragDataLocation name %{public}s result %{public}d", name.c_str(), res);
1139     return NVal::CreateInt64(env, res).val_;
1140 }
1141 
VertexAttribI4i(napi_env env,GLuint index,GLint * data)1142 napi_value WebGL2RenderingContextImpl::VertexAttribI4i(napi_env env, GLuint index, GLint* data)
1143 {
1144     VertexAttribInfo* info = GetVertexAttribInfo(index);
1145     if (info == nullptr) {
1146         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1147         return NVal::CreateNull(env).val_;
1148     }
1149 
1150     glVertexAttribI4i(index, data[0], data[1], data[2], data[3]); // 2, 3 index for data
1151     info->type = BUFFER_DATA_INT_32;
1152     LOGD("WebGL2 vertexAttribI4i index %{public}u [%{public}d %{public}d %{public}d %{public}d] result %{public}u",
1153         index, data[0], data[1], data[2], data[3], GetError_()); // 2, 3 index for data
1154     return NVal::CreateNull(env).val_;
1155 }
1156 
VertexAttribI4ui(napi_env env,GLuint index,GLuint * data)1157 napi_value WebGL2RenderingContextImpl::VertexAttribI4ui(napi_env env, GLuint index, GLuint* data)
1158 {
1159     VertexAttribInfo* info = GetVertexAttribInfo(index);
1160     if (info == nullptr) {
1161         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1162         return NVal::CreateNull(env).val_;
1163     }
1164 
1165     glVertexAttribI4ui(index, data[0], data[1], data[2], data[3]); // 2, 3 index for data
1166     info->type = BUFFER_DATA_UINT_32;
1167     LOGD("WebGL2 vertexAttribI4ui index %{public}u [%{public}u %{public}u %{public}u %{public}u] result %{public}u",
1168         index, data[0], data[1], data[2], data[3], GetError_()); // 2, 3 index for data
1169     return NVal::CreateNull(env).val_;
1170 }
1171 
VertexAttribI4iv(napi_env env,GLuint index,napi_value data)1172 napi_value WebGL2RenderingContextImpl::VertexAttribI4iv(napi_env env, GLuint index, napi_value data)
1173 {
1174     VertexAttribInfo* info = GetVertexAttribInfo(index);
1175     if (info == nullptr) {
1176         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1177         return NVal::CreateNull(env).val_;
1178     }
1179 
1180     WebGLReadBufferArg bufferData(env);
1181     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_INT_32);
1182     if (status != 0) {
1183         LOGE("WebGL vertexAttribI4iv failed to getbuffer data");
1184         return NVal::CreateNull(env).val_;
1185     }
1186     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1187     if (bufferData.GetBufferDataType() != BUFFER_DATA_INT_32) {
1188         LOGE("WebGL vertexAttribI4iv invalid data type %{public}u", bufferData.GetBufferDataType());
1189         return NVal::CreateNull(env).val_;
1190     }
1191     glVertexAttribI4iv(index, reinterpret_cast<GLint*>(bufferData.GetBuffer()));
1192     info->type = BUFFER_DATA_INT_32;
1193     return NVal::CreateNull(env).val_;
1194 }
1195 
VertexAttribI4uiv(napi_env env,GLuint index,napi_value data)1196 napi_value WebGL2RenderingContextImpl::VertexAttribI4uiv(napi_env env, GLuint index, napi_value data)
1197 {
1198     VertexAttribInfo* info = GetVertexAttribInfo(index);
1199     if (info == nullptr) {
1200         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1201         return NVal::CreateNull(env).val_;
1202     }
1203     WebGLReadBufferArg bufferData(env);
1204     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_UINT_32);
1205     if (status != 0) {
1206         LOGE("WebGL vertexAttribI4uiv failed to getbuffer data");
1207         return NVal::CreateNull(env).val_;
1208     }
1209     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1210     if (bufferData.GetBufferDataType() != BUFFER_DATA_UINT_32) {
1211         LOGE("WebGL2 vertexAttribI4uiv invalid data type %{public}d", bufferData.GetBufferDataType());
1212         return NVal::CreateNull(env).val_;
1213     }
1214     glVertexAttribI4uiv(index, reinterpret_cast<const GLuint*>(bufferData.GetBuffer()));
1215     info->type = BUFFER_DATA_UINT_32;
1216     return NVal::CreateNull(env).val_;
1217 }
1218 
VertexAttribIPointer(napi_env env,const VertexAttribArg & vertexInfo)1219 napi_value WebGL2RenderingContextImpl::VertexAttribIPointer(napi_env env, const VertexAttribArg& vertexInfo)
1220 {
1221     vertexInfo.Dump("WebGL2 vertexAttribPointer");
1222     if (!CheckGLenum(vertexInfo.type,
1223         { GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT }, {})) {
1224         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1225             "WebGL vertexAttribPointer invalid type %{public}u", vertexInfo.type);
1226     }
1227 
1228     GLenum result = CheckVertexAttribPointer(env, vertexInfo);
1229     if (result) {
1230         SET_ERROR(result);
1231         return NVal::CreateNull(env).val_;
1232     }
1233 
1234     glVertexAttribIPointer(vertexInfo.index, vertexInfo.size, vertexInfo.type, vertexInfo.stride,
1235         reinterpret_cast<GLvoid*>(vertexInfo.offset));
1236     LOGD("WebGL vertexAttribPointer index %{public}u offset %{public}u", vertexInfo.index, vertexInfo.offset);
1237     return NVal::CreateNull(env).val_;
1238 }
1239 
VertexAttribDivisor(napi_env env,GLuint index,GLuint divisor)1240 napi_value WebGL2RenderingContextImpl::VertexAttribDivisor(napi_env env, GLuint index, GLuint divisor)
1241 {
1242     LOGD("WebGL2 vertexAttribDivisor index %{public}u divisor %{public}u", index, divisor);
1243     if (index >= GetMaxVertexAttribs()) {
1244         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1245             "WebGL2 vertexAttribDivisor invalid index %{public}u", index);
1246         return NVal::CreateNull(env).val_;
1247     }
1248     glVertexAttribDivisor(index, divisor);
1249     return NVal::CreateNull(env).val_;
1250 }
1251 
DrawBuffers(napi_env env,napi_value dataObj)1252 napi_value WebGL2RenderingContextImpl::DrawBuffers(napi_env env, napi_value dataObj)
1253 {
1254     WebGLReadBufferArg bufferData(env);
1255     napi_status status = bufferData.GenBufferData(dataObj, BUFFER_DATA_GLENUM);
1256     if (status != 0) {
1257         LOGE("WebGL glDrawBuffers failed to getbuffer data");
1258         return NVal::CreateNull(env).val_;
1259     }
1260     if (bufferData.GetBufferType() != BUFFER_ARRAY) {
1261         LOGE("WebGL glDrawBuffers invalid buffer type %d", bufferData.GetBufferType());
1262         return NVal::CreateNull(env).val_;
1263     }
1264     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1265     GLenum* data = reinterpret_cast<GLenum*>(bufferData.GetBuffer());
1266     GLsizei length = static_cast<GLsizei>(bufferData.GetBufferLength() / sizeof(GLenum));
1267     glDrawBuffers(length, data);
1268     return NVal::CreateNull(env).val_;
1269 }
1270 
DrawArraysInstanced(napi_env env,GLenum mode,GLint first,GLsizei count,GLsizei instanceCount)1271 napi_value WebGL2RenderingContextImpl::DrawArraysInstanced(
1272     napi_env env, GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1273 {
1274     LOGD("WebGL drawArraysInstanced mode %{public}u %{public}d %{public}d %{public}d",
1275         mode, first, count, instanceCount);
1276     GLenum result = CheckDrawArrays(env, mode, first, count);
1277     if (result != WebGLRenderingContextBase::NO_ERROR) {
1278         SET_ERROR_WITH_LOG(result, "CheckDrawArrays failed");
1279         return NVal::CreateNull(env).val_;
1280     }
1281     if (instanceCount < 0) {
1282         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "instanceCount < 0");
1283         return NVal::CreateNull(env).val_;
1284     }
1285     glDrawArraysInstanced(mode, first, count, instanceCount);
1286     return NVal::CreateNull(env).val_;
1287 }
1288 
DrawElementsInstanced(napi_env env,const DrawElementArg & arg,GLsizei instanceCount)1289 napi_value WebGL2RenderingContextImpl::DrawElementsInstanced(
1290     napi_env env, const DrawElementArg& arg, GLsizei instanceCount)
1291 {
1292     LOGD("WebGL2 drawElementsInstanced mode %{public}u %{public}d %{public}u", arg.mode, arg.count, arg.type);
1293     GLenum result = CheckDrawElements(env, arg.mode, arg.count, arg.type, arg.offset);
1294     if (result != WebGLRenderingContextBase::NO_ERROR) {
1295         SET_ERROR_WITH_LOG(result, "CheckDrawElements failed");
1296         return NVal::CreateNull(env).val_;
1297     }
1298     if (instanceCount < 0) {
1299         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "instanceCount < 0");
1300         return NVal::CreateNull(env).val_;
1301     }
1302     glDrawElementsInstanced(arg.mode, arg.count, arg.type, reinterpret_cast<GLvoid*>(arg.offset), instanceCount);
1303     return NVal::CreateNull(env).val_;
1304 }
1305 
DrawRangeElements(napi_env env,const DrawElementArg & arg,GLuint start,GLuint end)1306 napi_value WebGL2RenderingContextImpl::DrawRangeElements(
1307     napi_env env, const DrawElementArg& arg, GLuint start, GLuint end)
1308 {
1309     LOGD("WebGL2 drawRangeElements mode %{public}u %{public}d %{public}u start [%{public}u %{public}u]"
1310         "%{public}d" PRIi64, arg.mode, arg.count, arg.type, start, end, arg.offset);
1311     GLenum result = CheckDrawElements(env, arg.mode, arg.count, arg.type, arg.offset);
1312     if (result != WebGLRenderingContextBase::NO_ERROR) {
1313         SET_ERROR(result);
1314         return NVal::CreateNull(env).val_;
1315     }
1316     glDrawRangeElements(arg.mode, start, end, arg.count, arg.type, reinterpret_cast<GLvoid*>(arg.offset));
1317     return NVal::CreateNull(env).val_;
1318 }
1319 
CopyBufferSubData(napi_env env,GLenum targets[2],int64_t readOffset,int64_t writeOffset,int64_t size)1320 napi_value WebGL2RenderingContextImpl::CopyBufferSubData(
1321     napi_env env, GLenum targets[2], int64_t readOffset, int64_t writeOffset, int64_t size)
1322 {
1323     LOGD("WebGL2 copyBufferSubData targets [%{public}u %{public}u] offset"
1324         " [%{public}" PRIi64 " %{public}" PRIi64 "] %{public}" PRIi64,
1325         targets[0], targets[1], readOffset, writeOffset, size);
1326     if (!WebGLArg::CheckNoneNegInt<GLint>(readOffset) || !WebGLArg::CheckNoneNegInt<GLint>(writeOffset) ||
1327         !WebGLArg::CheckNoneNegInt<GLint>(size)) {
1328         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckNoneNegInt failed");
1329         return NVal::CreateNull(env).val_;
1330     }
1331     WebGLBuffer* readBuffer = GetBoundBuffer(env, targets[0]); // read
1332     if (readBuffer == nullptr || readBuffer->GetBufferSize() == 0) {
1333         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "readBuffer is nullptr or size is 0");
1334         return NVal::CreateNull(env).val_;
1335     }
1336     WebGLBuffer* writeBuffer = GetBoundBuffer(env, targets[1]); // write
1337     if (writeBuffer == nullptr || writeBuffer->GetBufferSize() == 0) {
1338         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "writeBuffer is nullptr or size is 0");
1339         return NVal::CreateNull(env).val_;
1340     }
1341     if (readOffset + size > static_cast<int64_t>(readBuffer->GetBufferSize()) ||
1342         writeOffset + size > static_cast<int64_t>(writeBuffer->GetBufferSize())) {
1343         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "readOffset or writeOffset size error");
1344         return NVal::CreateNull(env).val_;
1345     }
1346     if ((writeBuffer->GetTarget() == GL_ELEMENT_ARRAY_BUFFER && readBuffer->GetTarget() != GL_ELEMENT_ARRAY_BUFFER) ||
1347         (writeBuffer->GetTarget() != GL_ELEMENT_ARRAY_BUFFER && readBuffer->GetTarget() == GL_ELEMENT_ARRAY_BUFFER)) {
1348         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "readOffset or writeOffset GetTarget failed");
1349         return NVal::CreateNull(env).val_;
1350     }
1351     if (writeBuffer->GetTarget() == 0) {
1352         writeBuffer->SetTarget(readBuffer->GetTarget());
1353     }
1354     glCopyBufferSubData(targets[0], targets[1], static_cast<GLintptr>(readOffset), static_cast<GLintptr>(writeOffset),
1355         static_cast<GLsizeiptr>(size));
1356     LOGD("WebGL2 copyBufferSubData result %{public}u", GetError_());
1357     return NVal::CreateNull(env).val_;
1358 }
1359 
GetBufferSubData(napi_env env,GLenum target,int64_t offset,napi_value data,const BufferExt & ext)1360 napi_value WebGL2RenderingContextImpl::GetBufferSubData(
1361     napi_env env, GLenum target, int64_t offset, napi_value data, const BufferExt& ext)
1362 {
1363     LOGD("WebGL2 getBufferSubData target %{public}u %{public}" PRIi64, target, offset);
1364     WebGLReadBufferArg bufferData(env);
1365     napi_status status = bufferData.GenBufferData(data);
1366     if (status != 0 || bufferData.GetBufferType() == BUFFER_ARRAY) {
1367         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "check buffer failed");
1368         return NVal::CreateNull(env).val_;
1369     }
1370     if (!WebGLArg::CheckNoneNegInt<GLint>(offset)) {
1371         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckNoneNegInt failed");
1372         return NVal::CreateNull(env).val_;
1373     }
1374     WebGLBuffer* writeBuffer = GetBoundBuffer(env, target);
1375     if (writeBuffer == nullptr || writeBuffer->GetBufferSize() == 0) {
1376         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "no buffer");
1377         return NVal::CreateNull(env).val_;
1378     }
1379     if (static_cast<size_t>(offset) + bufferData.GetBufferLength() > writeBuffer->GetBufferSize()) {
1380         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "check buffer size failed");
1381         return NVal::CreateNull(env).val_;
1382     }
1383     GLsizeiptr dstSize = (ext.length == 0) ? static_cast<GLsizeiptr>(bufferData.GetBufferLength())
1384                                            : static_cast<GLsizeiptr>(ext.length * bufferData.GetBufferDataSize());
1385     GLuint dstOffset = static_cast<GLuint>(ext.offset * bufferData.GetBufferDataSize());
1386     LOGD("WebGL2 getBufferSubData dstSize %{public}u dstOffset %{public}p", dstSize, writeBuffer->bufferData_);
1387 
1388     void *mapBuffer = glMapBufferRange(target, static_cast<GLintptr>(offset), dstSize, GL_MAP_READ_BIT);
1389     if (mapBuffer == nullptr ||
1390         memcpy_s(bufferData.GetBuffer() + dstOffset, bufferData.GetBufferLength(), mapBuffer, dstSize) != 0) {
1391         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "mapBuffer is nullptr");
1392     }
1393     glUnmapBuffer(target);
1394     LOGD("WebGL2 getBufferSubData target %{public}u result %{public}u ", target, GetError_());
1395     return NVal::CreateNull(env).val_;
1396 }
1397 
BlitFrameBuffer(napi_env env,GLint data[8],GLbitfield mask,GLenum filter)1398 napi_value WebGL2RenderingContextImpl::BlitFrameBuffer(napi_env env, GLint data[8], GLbitfield mask, GLenum filter)
1399 {
1400     // 0,1,2,3,4,5,6,7 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1
1401     glBlitFramebuffer(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], mask, filter);
1402     LOGD("WebGL2 blitFrameBuffer filter %{public}u result %{public}u ", filter, GetError_());
1403     return NVal::CreateNull(env).val_;
1404 }
1405 
FrameBufferTextureLayer(napi_env env,GLenum target,GLenum attachment,napi_value textureObj,const TextureLayerArg & layer)1406 napi_value WebGL2RenderingContextImpl::FrameBufferTextureLayer(
1407     napi_env env, GLenum target, GLenum attachment, napi_value textureObj, const TextureLayerArg& layer)
1408 {
1409     int32_t textureId = WebGLTexture::DEFAULT_TEXTURE;
1410     WebGLTexture* webGlTexture = WebGLTexture::GetObjectInstance(env, textureObj);
1411     if (webGlTexture == nullptr) {
1412         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1413         return NVal::CreateNull(env).val_;
1414     }
1415     textureId = static_cast<int32_t>(webGlTexture->GetTexture());
1416     glFramebufferTextureLayer(target, attachment, textureId, layer.level, layer.layer);
1417     LOGD("WebGL frameBufferTextureLayer texture %{public}d result %{public}u", textureId, GetError_());
1418 
1419     WebGLFramebuffer* frameBuffer = GetBoundFrameBuffer(env, target);
1420     if (frameBuffer == nullptr) {
1421         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "can not find bind frame buffer");
1422         return NVal::CreateNull(env).val_;
1423     }
1424     frameBuffer->AddAttachment(
1425         target, attachment, static_cast<GLuint>(textureId), webGlTexture->GetTarget(), layer.level);
1426     return NVal::CreateNull(env).val_;
1427 }
1428 
ReadBuffer(napi_env env,GLenum mode)1429 napi_value WebGL2RenderingContextImpl::ReadBuffer(napi_env env, GLenum mode)
1430 {
1431     LOGD("WebGL2 readBuffer mode %{public}u", mode);
1432     if (!CheckReadBufferMode(mode)) {
1433         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckReadBufferMode failed");
1434         return NVal::CreateNull(env).val_;
1435     }
1436 
1437     WebGLFramebuffer* readFrameBuffer = GetBoundFrameBuffer(env, WebGL2RenderingContextBase::READ_FRAMEBUFFER);
1438     if (readFrameBuffer == nullptr) {
1439         if (mode != WebGLRenderingContextBase::BACK && mode != WebGLRenderingContextBase::NONE) {
1440             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
1441                 "readFrameBuffer is nullptr, mode %{public}u", mode);
1442             return NVal::CreateNull(env).val_;
1443         }
1444         defaultReadBufferMode_ = mode;
1445         if (mode == WebGLRenderingContextBase::BACK) {
1446             mode = WebGLRenderingContextBase::COLOR_ATTACHMENT0;
1447         }
1448     } else {
1449         if (mode == WebGLRenderingContextBase::BACK) {
1450             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "mode %{public}u", mode);
1451             return NVal::CreateNull(env).val_;
1452         }
1453         readFrameBuffer->SetReadBufferMode(mode);
1454     }
1455     glReadBuffer(mode);
1456     return NVal::CreateNull(env).val_;
1457 }
1458 
RenderBufferStorageMultiSample(napi_env env,const TexStorageArg & arg,GLsizei samples)1459 napi_value WebGL2RenderingContextImpl::RenderBufferStorageMultiSample(
1460     napi_env env, const TexStorageArg& arg, GLsizei samples)
1461 {
1462     arg.Dump("WebGL2 renderbufferStorageMultisample");
1463     LOGD("WebGL2 renderbufferStorageMultisample samples %{public}d", samples);
1464 
1465     WebGLRenderbuffer* renderBuffer = CheckRenderBufferStorage(env, arg);
1466     if (renderBuffer == nullptr) {
1467         return NVal::CreateNull(env).val_;
1468     }
1469     if (samples < 0) {
1470         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "samples < 0");
1471         return NVal::CreateNull(env).val_;
1472     }
1473     if (arg.internalFormat == GL_DEPTH_STENCIL) {
1474         if (samples > 0) {
1475             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "GL_DEPTH_STENCIL samples > 0");
1476             return NVal::CreateNull(env).val_;
1477         }
1478         glRenderbufferStorage(arg.target, GL_DEPTH24_STENCIL8, arg.width, arg.height);
1479     } else {
1480         if (CheckInList(arg.internalFormat, WebGLTexture::GetSupportInternalFormatGroup1())) {
1481             if (samples > 0) {
1482                 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckInList group1 failed");
1483                 return NVal::CreateNull(env).val_;
1484             }
1485         } else if (!CheckInList(arg.internalFormat, WebGLTexture::GetSupportInternalFormatGroup2())) {
1486             SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckInList group2 failed");
1487             return NVal::CreateNull(env).val_;
1488         }
1489         if (samples == 0) {
1490             glRenderbufferStorage(arg.target, arg.internalFormat, arg.width, arg.height);
1491         } else {
1492             glRenderbufferStorageMultisample(arg.target, samples, arg.internalFormat, arg.width, arg.height);
1493         }
1494     }
1495     renderBuffer->SetInternalFormat(arg.internalFormat);
1496     renderBuffer->SetSize(arg.width, arg.height);
1497     LOGD("WebGL2 renderbufferStorageMultisample result %{public}u", GetError_());
1498     return NVal::CreateNull(env).val_;
1499 }
1500 
BindBuffer(napi_env env,GLenum target,napi_value object)1501 napi_value WebGL2RenderingContextImpl::BindBuffer(napi_env env, GLenum target, napi_value object)
1502 {
1503     // support default value
1504     uint32_t bufferId = WebGLBuffer::DEFAULT_BUFFER;
1505     WebGLBuffer* webGlBuffer = GetValidBuffer(env, object);
1506     if (webGlBuffer != nullptr) {
1507         bufferId = webGlBuffer->GetBufferId();
1508     }
1509     uint32_t index = BoundBufferType::ARRAY_BUFFER;
1510     if (!CheckBufferTarget(env, target, index)) {
1511         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1512         return NVal::CreateNull(env).val_;
1513     }
1514     if (webGlBuffer != nullptr && !CheckBufferTargetCompatibility(env, target, webGlBuffer)) {
1515         SET_ERROR(WebGLRenderingContextBase::INVALID_OPERATION);
1516         return NVal::CreateNull(env).val_;
1517     }
1518     if (boundBufferIds_[index] && boundBufferIds_[index] != bufferId) {
1519         LOGD("WebGL2 bindBuffer has been bound bufferId %{public}u", boundBufferIds_[index]);
1520     }
1521     boundBufferIds_[index] = bufferId;
1522 
1523     glBindBuffer(target, static_cast<GLuint>(bufferId));
1524     if (webGlBuffer) {
1525         webGlBuffer->SetTarget(target);
1526     }
1527     LOGD("WebGL2 bindBuffer target %{public}u bufferId %{public}u result %{public}u",
1528         target, bufferId, GetError_());
1529     return NVal::CreateNull(env).val_;
1530 }
1531 
BindBufferBase(napi_env env,const BufferBaseArg & arg,napi_value bufferObj)1532 napi_value WebGL2RenderingContextImpl::BindBufferBase(napi_env env, const BufferBaseArg& arg, napi_value bufferObj)
1533 {
1534     GLuint bufferId = WebGLBuffer::DEFAULT_BUFFER;
1535     WebGLBuffer* webGlBuffer = GetValidBuffer(env, bufferObj);
1536     if (webGlBuffer != nullptr) {
1537         bufferId = webGlBuffer->GetBufferId();
1538     }
1539     if (!CheckBufferBindTarget(arg.target)) {
1540         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckBufferBindTarget failed");
1541         return NVal::CreateNull(env).val_;
1542     }
1543     if (webGlBuffer != nullptr && !CheckBufferTargetCompatibility(env, arg.target, webGlBuffer)) {
1544         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckBufferTargetCompatibility failed");
1545         return NVal::CreateNull(env).val_;
1546     }
1547     if (!UpdateBaseTargetBoundBuffer(env, arg.target, arg.index, bufferId)) {
1548         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "UpdateBaseTargetBoundBuffer failed");
1549         return NVal::CreateNull(env).val_;
1550     }
1551     if (webGlBuffer != nullptr && !webGlBuffer->GetTarget()) {
1552         webGlBuffer->SetTarget(arg.target);
1553     }
1554     glBindBufferBase(arg.target, arg.index, bufferId);
1555     LOGD("WebGL2 bindBufferBase target %{public}u %{public}u %{public}u result %{public}u ",
1556         arg.target, arg.index, bufferId, GetError_());
1557     return NVal::CreateNull(env).val_;
1558 }
1559 
BindBufferRange(napi_env env,const BufferBaseArg & arg,napi_value bufferObj,GLintptr offset,GLsizeiptr size)1560 napi_value WebGL2RenderingContextImpl::BindBufferRange(
1561     napi_env env, const BufferBaseArg& arg, napi_value bufferObj, GLintptr offset, GLsizeiptr size)
1562 {
1563     GLuint bufferId = WebGLBuffer::DEFAULT_BUFFER;
1564     WebGLBuffer* webGlBuffer = GetValidBuffer(env, bufferObj);
1565     if (webGlBuffer != nullptr) {
1566         bufferId = webGlBuffer->GetBufferId();
1567     }
1568     if (!CheckBufferBindTarget(arg.target)) {
1569         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckBufferBindTarget failed");
1570         return NVal::CreateNull(env).val_;
1571     }
1572     if (webGlBuffer != nullptr && !CheckBufferTargetCompatibility(env, arg.target, webGlBuffer)) {
1573         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckBufferTargetCompatibility failed");
1574         return NVal::CreateNull(env).val_;
1575     }
1576     if (!UpdateBaseTargetBoundBuffer(env, arg.target, arg.index, bufferId)) {
1577         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "UpdateBaseTargetBoundBuffer failed");
1578         return NVal::CreateNull(env).val_;
1579     }
1580     if (webGlBuffer != nullptr && !webGlBuffer->GetTarget()) {
1581         webGlBuffer->SetTarget(arg.target);
1582     }
1583     LOGD("WebGL2 bindBufferRange target %{public}u %{public}u %{public}u", arg.target, arg.index, bufferId);
1584     glBindBufferRange(arg.target, arg.index, bufferId, offset, size);
1585     return NVal::CreateNull(env).val_;
1586 }
1587 
DeleteBuffer(napi_env env,napi_value object)1588 napi_value WebGL2RenderingContextImpl::DeleteBuffer(napi_env env, napi_value object)
1589 {
1590     return WebGLRenderingContextBaseImpl::DeleteBuffer(env, object);
1591 }
1592 
GetUniformBlockIndex(napi_env env,napi_value programObj,const std::string & uniformBlockName)1593 napi_value WebGL2RenderingContextImpl::GetUniformBlockIndex(
1594     napi_env env, napi_value programObj, const std::string& uniformBlockName)
1595 {
1596     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1597     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1598     if (webGLProgram == nullptr) {
1599         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGLProgram is nullptr");
1600         return NVal::CreateInt64(env, -1).val_;
1601     }
1602     programId = webGLProgram->GetProgramId();
1603     if (!WebGLArg::CheckString(uniformBlockName)) {
1604         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckString failed");
1605         return NVal::CreateInt64(env, -1).val_;
1606     }
1607     GLuint returnValue = glGetUniformBlockIndex(programId, uniformBlockName.c_str());
1608     LOGD("WebGL2 getUniformBlockIndex name %{public}s programId %{public}u result %{public}u",
1609         uniformBlockName.c_str(), programId, returnValue);
1610     return NVal::CreateInt64(env, returnValue).val_;
1611 }
1612 
UniformBlockBinding(napi_env env,napi_value programObj,GLuint uniformBlockIndex,GLuint uniformBlockBinding)1613 napi_value WebGL2RenderingContextImpl::UniformBlockBinding(
1614     napi_env env, napi_value programObj, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
1615 {
1616     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1617     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1618     if (webGLProgram == nullptr) {
1619         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1620         return NVal::CreateNull(env).val_;
1621     }
1622     programId = webGLProgram->GetProgramId();
1623     glUniformBlockBinding(programId, uniformBlockIndex, uniformBlockBinding);
1624     LOGD("WebGL2 uniformBlockBinding programId %{public}u %{public}u %{public}u result %{public}u",
1625         programId, uniformBlockIndex, uniformBlockBinding, GetError_());
1626     return NVal::CreateNull(env).val_;
1627 }
1628 
InvalidateFrameBuffer(napi_env env,GLenum target,napi_value data)1629 napi_value WebGL2RenderingContextImpl::InvalidateFrameBuffer(napi_env env, GLenum target, napi_value data)
1630 {
1631     LOGD("WebGL2 invalidate Framebuffer target %{public}u", target);
1632     WebGLReadBufferArg bufferData(env);
1633     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_GLENUM);
1634     if (status != 0) {
1635         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1636             "WebGL2 invalidateFramebuffer failed to getbuffer data");
1637         return NVal::CreateNull(env).val_;
1638     }
1639     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1640     if (bufferData.GetBufferDataType() != BUFFER_DATA_GLENUM) {
1641         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1642             "WebGL2 invalidateFramebuffer invalid data type %{public}u", bufferData.GetBufferDataType());
1643         return NVal::CreateNull(env).val_;
1644     }
1645     if (bufferData.GetBufferType() != BUFFER_ARRAY) {
1646         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1647             "WebGL2 invalidateFramebuffer invalid type %{public}u", bufferData.GetBufferType());
1648         return NVal::CreateNull(env).val_;
1649     }
1650     glInvalidateFramebuffer(target, static_cast<GLsizei>(bufferData.GetBufferLength() / sizeof(GLenum)),
1651         reinterpret_cast<GLenum*>(bufferData.GetBuffer()));
1652     return NVal::CreateNull(env).val_;
1653 }
1654 
InvalidateSubFrameBuffer(napi_env env,GLenum target,napi_value data,const BufferPosition & position,const BufferSize & size)1655 napi_value WebGL2RenderingContextImpl::InvalidateSubFrameBuffer(
1656     napi_env env, GLenum target, napi_value data, const BufferPosition& position, const BufferSize& size)
1657 {
1658     WebGLReadBufferArg bufferData(env);
1659     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_GLENUM);
1660     if (status != 0) {
1661         LOGE("WebGL2 invalidateFramebuffer failed to getbuffer data");
1662         return NVal::CreateNull(env).val_;
1663     }
1664     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1665     if (bufferData.GetBufferDataType() != BUFFER_DATA_GLENUM) {
1666         LOGE("WebGL2 invalidateFramebuffer invalid data type %{public}d", bufferData.GetBufferDataType());
1667         return NVal::CreateNull(env).val_;
1668     }
1669     if (bufferData.GetBufferType() != BUFFER_ARRAY) {
1670         LOGE("WebGL2 invalidateFramebuffer invalid type %{public}d", bufferData.GetBufferType());
1671         return NVal::CreateNull(env).val_;
1672     }
1673 
1674     glInvalidateSubFramebuffer(target, static_cast<GLsizei>(bufferData.GetBufferLength() / sizeof(GLenum)),
1675         reinterpret_cast<GLenum*>(bufferData.GetBuffer()), position.x, position.y, size.width, size.height);
1676     return NVal::CreateNull(env).val_;
1677 }
1678 
GetInternalFormatParameter(napi_env env,GLenum target,GLenum internalFormat,GLenum pname)1679 napi_value WebGL2RenderingContextImpl::GetInternalFormatParameter(
1680     napi_env env, GLenum target, GLenum internalFormat, GLenum pname)
1681 {
1682     if (target != WebGLRenderingContextBase::RENDERBUFFER) {
1683         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "target %{publuc}u", target);
1684         return NVal::CreateNull(env).val_;
1685     }
1686     LOGD("WebGL2 getInternalformatParameter target %{public}u %{public}u %{public}u", target, internalFormat, pname);
1687     WebGLWriteBufferArg writeBuffer(env);
1688     if (CheckInList(internalFormat, WebGLTexture::GetSupportInternalFormatGroup1())) {
1689         return writeBuffer.ToExternalArray(BUFFER_DATA_INT_32);
1690     } else if (!CheckInList(internalFormat, WebGLTexture::GetSupportInternalFormatGroup2())) {
1691         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "CheckInList failed");
1692         return NVal::CreateNull(env).val_;
1693     }
1694 
1695     GLint length = -1;
1696     if (pname == GL_SAMPLES) {
1697         glGetInternalformativ(target, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &length);
1698         LOGD("WebGL2 getInternalformatParameter length %{public}u", length);
1699     } else {
1700         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "pname %{publuc}u", pname);
1701         return NVal::CreateNull(env).val_;
1702     }
1703     if (length > 0) {
1704         GLint* params = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(length * sizeof(GLint)));
1705         if (params == nullptr) {
1706             return NVal::CreateNull(env).val_;
1707         }
1708         glGetInternalformativ(target, internalFormat, pname, length, params);
1709         writeBuffer.DumpBuffer(BUFFER_DATA_INT_32);
1710     }
1711     return writeBuffer.ToExternalArray(BUFFER_DATA_INT_32);
1712 }
1713 
TransformFeedbackVaryings(napi_env env,napi_value programObj,napi_value data,GLenum bufferMode)1714 napi_value WebGL2RenderingContextImpl::TransformFeedbackVaryings(
1715     napi_env env, napi_value programObj, napi_value data, GLenum bufferMode)
1716 {
1717     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1718     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1719     if (webGLProgram == nullptr) {
1720         return NVal::CreateNull(env).val_;
1721     }
1722     programId = webGLProgram->GetProgramId();
1723     if (bufferMode != GL_INTERLEAVED_ATTRIBS && bufferMode != GL_SEPARATE_ATTRIBS) {
1724         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1725         return NVal::CreateNull(env).val_;
1726     }
1727     std::vector<char*> list = {};
1728     bool succ = WebGLArg::GetStringList(env, data, list);
1729     if (!succ) {
1730         WebGLArg::FreeStringList(list);
1731         return NVal::CreateNull(env).val_;
1732     }
1733     glTransformFeedbackVaryings(programId, static_cast<GLsizei>(list.size()), list.data(), bufferMode);
1734     WebGLArg::FreeStringList(list);
1735     return NVal::CreateNull(env).val_;
1736 }
1737 
GetUniformIndices(napi_env env,napi_value programObj,napi_value data)1738 napi_value WebGL2RenderingContextImpl::GetUniformIndices(napi_env env, napi_value programObj, napi_value data)
1739 {
1740     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1741     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1742     if (webGLProgram == nullptr) {
1743         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1744         return NVal::CreateNull(env).val_;
1745     }
1746     programId = webGLProgram->GetProgramId();
1747 
1748     std::vector<char*> list = {};
1749     bool succ = WebGLArg::GetStringList(env, data, list);
1750     if (!succ) {
1751         WebGLArg::FreeStringList(list);
1752         return NVal::CreateNull(env).val_;
1753     }
1754     LOGD("WebGL2 getUniformIndices uniformCount %{public}zu", list.size());
1755 
1756     WebGLWriteBufferArg writeBuffer(env);
1757     napi_value result = NVal::CreateNull(env).val_;
1758     GLuint* uniformIndices = reinterpret_cast<GLuint*>(writeBuffer.AllocBuffer(list.size() * sizeof(GLuint)));
1759     if (uniformIndices != nullptr) {
1760         glGetUniformIndices(programId, static_cast<GLsizei>(list.size()), const_cast<const GLchar**>(list.data()),
1761             static_cast<GLuint*>(uniformIndices));
1762         writeBuffer.DumpBuffer(BUFFER_DATA_UINT_32);
1763         result = writeBuffer.ToNormalArray(BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32);
1764     }
1765     WebGLArg::FreeStringList(list);
1766     return result;
1767 }
1768 
GetActiveUniforms(napi_env env,napi_value programObj,napi_value data,GLenum pname)1769 napi_value WebGL2RenderingContextImpl::GetActiveUniforms(
1770     napi_env env, napi_value programObj, napi_value data, GLenum pname)
1771 {
1772     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1773     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1774     if (webGLProgram == nullptr) {
1775         SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
1776         return NVal::CreateNull(env).val_;
1777     }
1778     if (pname == GL_UNIFORM_NAME_LENGTH) {
1779         SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1780         return NVal::CreateNull(env).val_;
1781     }
1782 
1783     programId = webGLProgram->GetProgramId();
1784     LOGD("WebGL2 getActiveUniforms programId %{public}u pname %{public}u", programId, pname);
1785     WebGLReadBufferArg bufferData(env);
1786     napi_status status = bufferData.GenBufferData(data, BUFFER_DATA_UINT_32);
1787     if (status != 0) {
1788         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1789             "WebGL2 invalidateFramebuffer failed to getbuffer data");
1790         return NVal::CreateNull(env).val_;
1791     }
1792     bufferData.DumpBuffer(bufferData.GetBufferDataType());
1793     GLsizei size = static_cast<GLsizei>(bufferData.GetBufferLength() / bufferData.GetBufferDataSize());
1794 
1795     WebGLWriteBufferArg writeBuffer(env);
1796     GLint* params = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(size * sizeof(GLint)));
1797     if (params == nullptr) {
1798         return NVal::CreateNull(env).val_;
1799     }
1800     glGetActiveUniformsiv(
1801         programId, size, reinterpret_cast<GLuint*>(bufferData.GetBuffer()), pname, reinterpret_cast<GLint*>(params));
1802     switch (pname) {
1803         case GL_UNIFORM_TYPE:
1804         case GL_UNIFORM_SIZE:
1805             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_BIGUINT_64);
1806         case GL_UNIFORM_BLOCK_INDEX:
1807         case GL_UNIFORM_OFFSET:
1808         case GL_UNIFORM_ARRAY_STRIDE:
1809         case GL_UNIFORM_MATRIX_STRIDE:
1810             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_INT_32);
1811         case GL_UNIFORM_IS_ROW_MAJOR:
1812             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN);
1813         default:
1814             break;
1815     }
1816     return NVal::CreateNull(env).val_;
1817 }
1818 
GetActiveUniformBlockParameter(napi_env env,napi_value programObj,GLuint uniformBlockIndex,GLenum pname)1819 napi_value WebGL2RenderingContextImpl::GetActiveUniformBlockParameter(
1820     napi_env env, napi_value programObj, GLuint uniformBlockIndex, GLenum pname)
1821 {
1822     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1823     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1824     if (webGLProgram == nullptr) {
1825         return NVal::CreateInt64(env, -1).val_;
1826     }
1827     programId = webGLProgram->GetProgramId();
1828     LOGD("WebGL2 getActiveUniformBlockParameter programId %{public}u %{public}u %{public}u",
1829         programId, uniformBlockIndex, pname);
1830     switch (pname) {
1831         case GL_UNIFORM_BLOCK_BINDING:
1832         case GL_UNIFORM_BLOCK_DATA_SIZE:
1833         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: {
1834             GLint params;
1835             glGetActiveUniformBlockiv(programId, uniformBlockIndex, pname, &params);
1836             return NVal::CreateInt64(env, params).val_;
1837         }
1838         case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1839         case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: {
1840             GLint params;
1841             glGetActiveUniformBlockiv(programId, uniformBlockIndex, pname, &params);
1842             return NVal::CreateBool(env, params != GL_FALSE).val_;
1843         }
1844         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: {
1845             WebGLWriteBufferArg writeBuffer(env);
1846             GLint uniformCount = 1;
1847             glGetActiveUniformBlockiv(programId, uniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformCount);
1848             LOGD("WebGL2 getActiveUniformBlockParameter uniformCount %{public}d", uniformCount);
1849             GLint* params = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(uniformCount * sizeof(GLint)));
1850             if (params == nullptr) {
1851                 return NVal::CreateNull(env).val_;
1852             }
1853             glGetActiveUniformBlockiv(programId, uniformBlockIndex, pname, params);
1854             return writeBuffer.ToNormalArray(BUFFER_DATA_INT_32, BUFFER_DATA_UINT_32);
1855         }
1856         default:
1857             SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1858             return NVal::CreateNull(env).val_;
1859     }
1860     return NVal::CreateInt64(env, -1).val_;
1861 }
1862 
GetActiveUniformBlockName(napi_env env,napi_value programObj,GLuint uniformBlockIndex)1863 napi_value WebGL2RenderingContextImpl::GetActiveUniformBlockName(
1864     napi_env env, napi_value programObj, GLuint uniformBlockIndex)
1865 {
1866     GLuint programId = WebGLProgram::DEFAULT_PROGRAM_ID;
1867     WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
1868     if (webGLProgram == nullptr) {
1869         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "webGLProgram is nullptr");
1870         return NVal::CreateUTF8String(env, "").val_;
1871     }
1872     programId = webGLProgram->GetProgramId();
1873 
1874     GLint length = 0;
1875     GLsizei size = 0;
1876     glGetProgramiv(programId, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &length);
1877     if (length <= 0) {
1878         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "length < 0");
1879         return NVal::CreateUTF8String(env, "").val_;
1880     }
1881     std::unique_ptr<char[]> buf = std::make_unique<char[]>(length + 1);
1882     if (buf == nullptr) {
1883         SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "buf is nullptr");
1884         return NVal::CreateNull(env).val_;
1885     }
1886     glGetActiveUniformBlockName(programId, uniformBlockIndex, length, &size, buf.get());
1887     LOGD("WebGL2 getActiveUniformBlockName programId %{public}u uniformBlockIndex  %{public}u name %{public}s",
1888         programId, uniformBlockIndex, buf.get());
1889     string str(buf.get(), size);
1890     return NVal::CreateUTF8String(env, str).val_;
1891 }
1892 
CheckClearBuffer(napi_env env,GLenum buffer,const WebGLReadBufferArg & bufferData)1893 GLenum WebGL2RenderingContextImpl::CheckClearBuffer(napi_env env, GLenum buffer, const WebGLReadBufferArg& bufferData)
1894 {
1895     size_t size = bufferData.GetBufferLength() / bufferData.GetBufferDataSize();
1896     switch (buffer) {
1897         case WebGL2RenderingContextBase::COLOR:
1898         case WebGLRenderingContextBase::FRONT:
1899         case WebGLRenderingContextBase::BACK:
1900         case WebGLRenderingContextBase::FRONT_AND_BACK:
1901             if (size < 4) { // 4 max element
1902                 return WebGLRenderingContextBase::INVALID_VALUE;
1903             }
1904             break;
1905         case WebGL2RenderingContextBase::DEPTH:
1906         case WebGL2RenderingContextBase::STENCIL:
1907         case WebGLRenderingContextBase::DEPTH_STENCIL:
1908             if (size < 1) {
1909                 return WebGLRenderingContextBase::INVALID_VALUE;
1910             }
1911             break;
1912         default:
1913             return WebGLRenderingContextBase::INVALID_ENUM;
1914     }
1915     return WebGLRenderingContextBase::NO_ERROR;
1916 }
1917 
CheckQueryTarget(napi_env env,GLenum target,uint32_t & index)1918 bool WebGL2RenderingContextImpl::CheckQueryTarget(napi_env env, GLenum target, uint32_t& index)
1919 {
1920     switch (target) {
1921         case WebGL2RenderingContextBase::ANY_SAMPLES_PASSED:
1922         case WebGL2RenderingContextBase::ANY_SAMPLES_PASSED_CONSERVATIVE:
1923             index = BoundQueryType::ANY_SAMPLES_PASSED;
1924             break;
1925         case WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1926             index = BoundQueryType::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
1927             break;
1928         default:
1929             return false;
1930     }
1931     return true;
1932 }
1933 
CheckTexStorage(napi_env env,const TexStorageArg & arg)1934 GLenum WebGL2RenderingContextImpl::CheckTexStorage(napi_env env, const TexStorageArg& arg)
1935 {
1936     WebGLTexture* texture = GetBoundTexture(env, arg.target, false);
1937     if (!texture) {
1938         LOGE("CheckTexStorage %{public}u", arg.target);
1939         return WebGLRenderingContextBase::INVALID_OPERATION;
1940     }
1941 
1942     if (!CheckStorageInternalFormat(env, arg.internalFormat)) {
1943         return WebGLRenderingContextBase::INVALID_ENUM;
1944     }
1945 
1946     if (arg.width <= 0 || arg.height <= 0 || arg.depth <= 0) {
1947         LOGE("CheckTexStorage invalid width %{public}d, height %{public}d, depth %{public}d",
1948             arg.width, arg.height, arg.depth);
1949         return WebGLRenderingContextBase::INVALID_VALUE;
1950     }
1951 
1952     if (arg.levels <= 0) {
1953         LOGE("CheckTexStorage invalid levels %{public}d", arg.levels);
1954         return WebGLRenderingContextBase::INVALID_VALUE;
1955     }
1956 
1957     if (arg.target == GL_TEXTURE_3D) {
1958         if (arg.levels > log2(std::max(std::max(arg.width, arg.height), arg.depth)) + 1) {
1959             LOGE("CheckTexStorage invalid levels %{public}d", arg.levels);
1960             return WebGLRenderingContextBase::INVALID_OPERATION;
1961         }
1962     } else {
1963         if (arg.levels > log2(std::max(arg.width, arg.height)) + 1) {
1964             LOGE("CheckTexStorage invalid %{public}d %{public}d",
1965                 arg.levels, log2(std::max(arg.width, arg.height)) + 1);
1966             return WebGLRenderingContextBase::INVALID_OPERATION;
1967         }
1968     }
1969     return WebGLRenderingContextBase::NO_ERROR;
1970 }
1971 
CheckBufferBindTarget(GLenum target)1972 bool WebGL2RenderingContextImpl::CheckBufferBindTarget(GLenum target)
1973 {
1974     if (target == GL_TRANSFORM_FEEDBACK_BUFFER || target == GL_UNIFORM_BUFFER) {
1975         return true;
1976     }
1977     return false;
1978 }
1979 
CheckTransformFeedbackBuffer(GLenum target,WebGLBuffer * buffer)1980 bool WebGL2RenderingContextImpl::CheckTransformFeedbackBuffer(GLenum target, WebGLBuffer* buffer)
1981 {
1982     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
1983         for (size_t i = 0; i < sizeof(boundBufferIds_) / boundBufferIds_[0]; i++) {
1984             if (i == BoundBufferType::TRANSFORM_FEEDBACK_BUFFER) {
1985                 continue;
1986             }
1987             if (boundBufferIds_[i] == buffer->GetBufferId()) {
1988                 LOGD("boundBufferIds_ %{public}u %{public}zu", boundBufferIds_[i], i);
1989                 return false;
1990             }
1991         }
1992         LOGD("boundIndexedUniformBuffers_ %{public}zu", boundIndexedUniformBuffers_.size());
1993         for (size_t i = 0; i < boundIndexedUniformBuffers_.size(); ++i) {
1994             if (boundIndexedUniformBuffers_[i] == buffer->GetBufferId()) {
1995                 return false;
1996             }
1997         }
1998     } else {
1999         LOGD("Get TRANSFORM_FEEDBACK_BUFFER id %{public}u ",
2000             boundBufferIds_[BoundBufferType::TRANSFORM_FEEDBACK_BUFFER]);
2001         if (boundBufferIds_[BoundBufferType::TRANSFORM_FEEDBACK_BUFFER] == buffer->GetBufferId()) {
2002             return false;
2003         }
2004         for (size_t i = 0; i < boundIndexedTransformFeedbackBuffers_.size(); ++i) {
2005             if (boundIndexedTransformFeedbackBuffers_[i] == buffer->GetBufferId()) {
2006                 return false;
2007             }
2008         }
2009     }
2010     return true;
2011 }
2012 
CheckBufferTargetCompatibility(napi_env env,GLenum target,WebGLBuffer * buffer)2013 bool WebGL2RenderingContextImpl::CheckBufferTargetCompatibility(napi_env env, GLenum target, WebGLBuffer* buffer)
2014 {
2015     LOGD("buffer target %{public}u %{public}u id %{public}u", buffer->GetTarget(), target, buffer->GetBufferId());
2016     switch (buffer->GetTarget()) {
2017         case GL_ELEMENT_ARRAY_BUFFER:
2018             switch (target) {
2019                 case GL_ARRAY_BUFFER:
2020                 case GL_PIXEL_PACK_BUFFER:
2021                 case GL_PIXEL_UNPACK_BUFFER:
2022                 case GL_TRANSFORM_FEEDBACK_BUFFER:
2023                 case GL_UNIFORM_BUFFER:
2024                     return false;
2025                 default:
2026                     break;
2027             }
2028             break;
2029         case GL_ARRAY_BUFFER:
2030         case GL_COPY_READ_BUFFER:
2031         case GL_COPY_WRITE_BUFFER:
2032         case GL_PIXEL_PACK_BUFFER:
2033         case GL_PIXEL_UNPACK_BUFFER:
2034         case GL_UNIFORM_BUFFER:
2035         case GL_TRANSFORM_FEEDBACK_BUFFER:
2036             if (target == GL_ELEMENT_ARRAY_BUFFER) {
2037                 return false;
2038             }
2039             break;
2040         default:
2041             break;
2042     }
2043     return CheckTransformFeedbackBuffer(target, buffer);
2044 }
2045 
UpdateBaseTargetBoundBuffer(napi_env env,GLenum target,GLuint index,GLuint bufferId)2046 bool WebGL2RenderingContextImpl::UpdateBaseTargetBoundBuffer(
2047     napi_env env, GLenum target, GLuint index, GLuint bufferId)
2048 {
2049     if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
2050         if (index >= maxBoundTransformFeedbackBufferIndex_) {
2051             LOGE("Out of bound indexed transform feedback buffer %{public}u", index);
2052             return false;
2053         }
2054         boundIndexedTransformFeedbackBuffers_[index] = bufferId;
2055         boundBufferIds_[BoundBufferType::TRANSFORM_FEEDBACK_BUFFER] = bufferId;
2056         if (!bufferId) { // for delete
2057             boundIndexedTransformFeedbackBuffers_.erase(index);
2058         }
2059         return true;
2060     }
2061     if (target == GL_UNIFORM_BUFFER) {
2062         if (index >= maxBoundUniformBufferIndex_) {
2063             LOGE("Out of bound indexed uniform buffer %{public}u", index);
2064             return false;
2065         }
2066         boundIndexedUniformBuffers_[index] = bufferId;
2067         boundBufferIds_[BoundBufferType::UNIFORM_BUFFER] = bufferId;
2068         if (!bufferId) { // for delete
2069             boundIndexedUniformBuffers_.erase(index);
2070         }
2071         return true;
2072     }
2073     return false;
2074 }
2075 
CheckStorageInternalFormat(napi_env env,GLenum internalFormat)2076 bool WebGL2RenderingContextImpl::CheckStorageInternalFormat(napi_env env, GLenum internalFormat)
2077 {
2078     return CheckInList(internalFormat, {
2079         GL_R8,
2080         GL_R8_SNORM,
2081         GL_R16F,
2082         GL_R32F,
2083         GL_R8UI,
2084         GL_R8I,
2085         GL_R16UI,
2086         GL_R16I,
2087         GL_R32UI,
2088         GL_R32I,
2089         GL_RG8,
2090         GL_RG8_SNORM,
2091         GL_RG16F,
2092         GL_RG32F,
2093         GL_RG8UI,
2094         GL_RG8I,
2095         GL_RG16UI,
2096         GL_RG16I,
2097         GL_RG32UI,
2098         GL_RG32I,
2099         GL_RGB8,
2100         GL_SRGB8,
2101         GL_RGB565,
2102         GL_RGB8_SNORM,
2103         GL_R11F_G11F_B10F,
2104         GL_RGB9_E5,
2105         GL_RGB16F,
2106         GL_RGB32F,
2107         GL_RGB8UI,
2108         GL_RGB8I,
2109         GL_RGB16UI,
2110         GL_RGB16I,
2111         GL_RGB32UI,
2112         GL_RGB32I,
2113         GL_RGBA8,
2114         GL_SRGB8_ALPHA8,
2115         GL_RGBA8_SNORM,
2116         GL_RGB5_A1,
2117         GL_RGBA4,
2118         GL_RGB10_A2,
2119         GL_RGBA16F,
2120         GL_RGBA32F,
2121         GL_RGBA8UI,
2122         GL_RGBA8I,
2123         GL_RGB10_A2UI,
2124         GL_RGBA16UI,
2125         GL_RGBA16I,
2126         GL_RGBA32UI,
2127         GL_RGBA32I,
2128         GL_DEPTH_COMPONENT16,
2129         GL_DEPTH_COMPONENT24,
2130         GL_DEPTH_COMPONENT32F,
2131         GL_DEPTH24_STENCIL8,
2132         GL_DEPTH32F_STENCIL8,
2133         GL_COMPRESSED_R11_EAC,
2134         GL_COMPRESSED_SIGNED_R11_EAC,
2135         GL_COMPRESSED_RG11_EAC,
2136         GL_COMPRESSED_SIGNED_RG11_EAC,
2137         GL_COMPRESSED_RGB8_ETC2,
2138         GL_COMPRESSED_SRGB8_ETC2,
2139         GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
2140         GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
2141         GL_COMPRESSED_RGBA8_ETC2_EAC,
2142         GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
2143     });
2144 }
2145 } // namespace Impl
2146 } // namespace Rosen
2147 } // namespace OHOS
2148