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