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 %{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 (webGLShaderPrecisionFormat == 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 (webGLUniformLocation == nullptr) {
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 static_cast<unsigned int>(count), static_cast<size_t>(readData.GetBufferLength()),
1634 static_cast<size_t>(info->elemCount), static_cast<size_t>(info->srcOffset),
1635 static_cast<size_t>(info->srcLength));
1636 if (isHighWebGL) {
1637 if (count <= info->srcOffset || count < info->srcLength) {
1638 return make_tuple(WebGLRenderingContextBase::INVALID_VALUE, 0, nullptr);
1639 }
1640 count = info->srcLength != 0 ? info->srcLength : count - info->srcOffset;
1641 srcData = srcData + info->srcOffset;
1642 }
1643 if (count % info->elemCount) {
1644 return make_tuple(WebGLRenderingContextBase::INVALID_VALUE, 0, nullptr);
1645 }
1646 if (count != info->elemCount) {
1647 return make_tuple(WebGLRenderingContextBase::INVALID_OPERATION, 0, nullptr);
1648 }
1649 return make_tuple(WebGLRenderingContextBase::NO_ERROR, count, srcData);
1650 }
1651
UniformFv(napi_env env,napi_value locationObj,napi_value data,const UniformExtInfo * info)1652 napi_value WebGLRenderingContextBaseImpl::UniformFv(
1653 napi_env env, napi_value locationObj, napi_value data, const UniformExtInfo* info)
1654 {
1655 WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1656 if (webGLUniformLocation == nullptr) {
1657 LOGE("WebGL uniform_fv can not find uniform");
1658 return NVal::CreateNull(env).val_;
1659 }
1660 GLint location = webGLUniformLocation->GetUniformLocationId();
1661
1662 WebGLReadBufferArg readData(env);
1663 napi_status status = readData.GenBufferData(data, BUFFER_DATA_FLOAT_32);
1664 if (status != napi_ok) {
1665 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GenBufferData failed.");
1666 return NVal::CreateNull(env).val_;
1667 }
1668 readData.DumpBuffer(readData.GetBufferDataType());
1669 if (readData.GetBufferDataType() != BUFFER_DATA_FLOAT_32) {
1670 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GetBufferDataType failed. %{public}d",
1671 readData.GetBufferDataType());
1672 return NVal::CreateNull(env).val_;
1673 }
1674 GLenum result = 0;
1675 GLsizei count = 0;
1676 GLfloat* srcData = nullptr;
1677 std::tie(result, count, srcData) = CheckUniformDataInfo<GLfloat>(IsHighWebGL(), readData, info);
1678 if (result) {
1679 SET_ERROR(result);
1680 return NVal::CreateNull(env).val_;
1681 }
1682
1683 switch (info->dimension) {
1684 case PARAMETERS_NUM_1:
1685 glUniform1fv(location, 1, srcData);
1686 break;
1687 case PARAMETERS_NUM_2:
1688 glUniform2fv(location, count / 2, srcData); // 2 array size
1689 break;
1690 case PARAMETERS_NUM_3:
1691 glUniform3fv(location, count / 3, srcData); // 3 array size
1692 break;
1693 case PARAMETERS_NUM_4:
1694 glUniform4fv(location, count / 4, srcData); // 4 array size
1695 break;
1696 default:
1697 break;
1698 }
1699 return NVal::CreateNull(env).val_;
1700 }
1701
UniformIv(napi_env env,napi_value locationObj,napi_value data,const UniformExtInfo * info)1702 napi_value WebGLRenderingContextBaseImpl::UniformIv(
1703 napi_env env, napi_value locationObj, napi_value data, const UniformExtInfo* info)
1704 {
1705 WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1706 if (webGLUniformLocation == nullptr) {
1707 LOGE("WebGL UniformIv can not find uniform");
1708 return NVal::CreateNull(env).val_;
1709 }
1710 GLint location = webGLUniformLocation->GetUniformLocationId();
1711
1712 WebGLReadBufferArg readData(env);
1713 napi_status status = readData.GenBufferData(data, BUFFER_DATA_INT_32);
1714 if (status != napi_ok) {
1715 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL UniformIv failed to getbuffer data");
1716 return NVal::CreateNull(env).val_;
1717 }
1718 readData.DumpBuffer(readData.GetBufferDataType());
1719 if (readData.GetBufferDataType() != BUFFER_DATA_INT_32) {
1720 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1721 "WebGL UniformIv not support data type %{public}d", readData.GetBufferDataType());
1722 return NVal::CreateNull(env).val_;
1723 }
1724 GLenum result = 0;
1725 GLsizei count = 0;
1726 GLint* srcData = nullptr;
1727 std::tie(result, count, srcData) = CheckUniformDataInfo<GLint>(IsHighWebGL(), readData, info);
1728 if (result) {
1729 SET_ERROR(result);
1730 return NVal::CreateNull(env).val_;
1731 }
1732 switch (info->dimension) {
1733 case PARAMETERS_NUM_1:
1734 glUniform1iv(location, 1, srcData);
1735 break;
1736 case PARAMETERS_NUM_2:
1737 glUniform2iv(location, count / 2, srcData); // 2 array size
1738 break;
1739 case PARAMETERS_NUM_3:
1740 glUniform3iv(location, count / 3, srcData); // 3 array size
1741 break;
1742 case PARAMETERS_NUM_4:
1743 glUniform4iv(location, count / 4, srcData); // 4 array size
1744 break;
1745 default:
1746 break;
1747 }
1748 return NVal::CreateNull(env).val_;
1749 }
1750
UniformUiv(napi_env env,napi_value locationObj,napi_value dataObj,const UniformExtInfo * info)1751 napi_value WebGLRenderingContextBaseImpl::UniformUiv(
1752 napi_env env, napi_value locationObj, napi_value dataObj, const UniformExtInfo* info)
1753 {
1754 WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1755 if (webGLUniformLocation == nullptr) {
1756 LOGE("WebGL uniform_uiv can not find uniform");
1757 return NVal::CreateNull(env).val_;
1758 }
1759 GLint location = webGLUniformLocation->GetUniformLocationId();
1760
1761 WebGLReadBufferArg readData(env);
1762 napi_status status = readData.GenBufferData(dataObj, BUFFER_DATA_UINT_32);
1763 if (status != napi_ok) {
1764 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GenBufferData failed.");
1765 return NVal::CreateNull(env).val_;
1766 }
1767 readData.DumpBuffer(readData.GetBufferDataType());
1768 if (readData.GetBufferDataType() != BUFFER_DATA_UINT_32) {
1769 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "GetBufferDataType failed. %{public}d",
1770 readData.GetBufferDataType());
1771 return NVal::CreateNull(env).val_;
1772 }
1773 GLenum result = 0;
1774 GLsizei count = 0;
1775 GLuint* srcData = nullptr;
1776 std::tie(result, count, srcData) = CheckUniformDataInfo<GLuint>(IsHighWebGL(), readData, info);
1777 if (result) {
1778 SET_ERROR(result);
1779 return NVal::CreateNull(env).val_;
1780 }
1781 switch (info->dimension) {
1782 case PARAMETERS_NUM_1:
1783 glUniform1uiv(location, 1, srcData);
1784 break;
1785 case PARAMETERS_NUM_2:
1786 glUniform2uiv(location, count / PARAMETERS_NUM_2, srcData);
1787 break;;
1788 case PARAMETERS_NUM_3:
1789 glUniform3uiv(location, count / PARAMETERS_NUM_3, srcData);
1790 break;
1791 case PARAMETERS_NUM_4:
1792 glUniform4uiv(location, count / PARAMETERS_NUM_4, srcData);
1793 break;
1794 default:
1795 break;
1796 }
1797 return NVal::CreateNull(env).val_;
1798 }
1799
HandleUniformMatrixInfo(GLboolean transpose,const UniformExtInfo * info,GLint location,GLsizei count,GLfloat * srcData)1800 void WebGLRenderingContextBaseImpl::HandleUniformMatrixInfo(
1801 GLboolean transpose, const UniformExtInfo* info, GLint location, GLsizei count, GLfloat* srcData)
1802 {
1803 switch (info->dimension) {
1804 case WebGLArg::MATRIX_2X2_REQUIRE_MIN_SIZE:
1805 glUniformMatrix2fv(location, count / 4, transpose, srcData); // 4 is 2x2
1806 break;
1807 case WebGLArg::MATRIX_3X3_REQUIRE_MIN_SIZE:
1808 glUniformMatrix3fv(location, count / 8, transpose, srcData); // 8 is 2x2x2
1809 break;
1810 case WebGLArg::MATRIX_4X4_REQUIRE_MIN_SIZE:
1811 glUniformMatrix4fv(location, count / 16, transpose, srcData); // 16 is 2x2x2x2
1812 break;
1813 case WebGLArg::MATRIX_3X2_REQUIRE_MIN_SIZE:
1814 glUniformMatrix3x2fv(location, count / 6, transpose, srcData); // 6 matrix
1815 break;
1816 case WebGLArg::MATRIX_4X2_REQUIRE_MIN_SIZE:
1817 glUniformMatrix4x2fv(location, count / 8, transpose, srcData); // 8 matrix
1818 break;
1819 case WebGLArg::MATRIX_2X3_REQUIRE_MIN_SIZE:
1820 glUniformMatrix2x3fv(location, count / 6, transpose, srcData); // 6 matrix
1821 break;
1822 case WebGLArg::MATRIX_4X3_REQUIRE_MIN_SIZE:
1823 glUniformMatrix4x3fv(location, count / 12, transpose, srcData); // 12 matrix
1824 break;
1825 case WebGLArg::MATRIX_2X4_REQUIRE_MIN_SIZE:
1826 glUniformMatrix2x4fv(location, count / 8, transpose, srcData); // 8 matrix
1827 break;
1828 case WebGLArg::MATRIX_3X4_REQUIRE_MIN_SIZE:
1829 glUniformMatrix3x4fv(location, count / 12, transpose, srcData); // 12 matrix
1830 break;
1831 default:
1832 break;
1833 }
1834 }
1835
UniformMatrixFv(napi_env env,napi_value locationObj,napi_value data,GLboolean transpose,const UniformExtInfo * info)1836 napi_value WebGLRenderingContextBaseImpl::UniformMatrixFv(
1837 napi_env env, napi_value locationObj, napi_value data, GLboolean transpose, const UniformExtInfo* info)
1838 {
1839 WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, locationObj);
1840 if (webGLUniformLocation == nullptr) {
1841 LOGE("WebGL uniformMatrix_fv can not find uniform");
1842 return NVal::CreateNull(env).val_;
1843 }
1844 GLint location = webGLUniformLocation->GetUniformLocationId();
1845
1846 WebGLReadBufferArg readData(env);
1847 napi_status status = readData.GenBufferData(data, BUFFER_DATA_FLOAT_32);
1848 if (status != napi_ok) {
1849 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1850 "WebGL uniformMatrix_fv failed to getbuffer data");
1851 return NVal::CreateNull(env).val_;
1852 }
1853 readData.DumpBuffer(readData.GetBufferDataType());
1854
1855 if (readData.GetBufferDataType() != BUFFER_DATA_FLOAT_32) {
1856 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
1857 "WebGL uniformMatrix_fv not support data type %{public}d", readData.GetBufferDataType());
1858 return NVal::CreateNull(env).val_;
1859 }
1860 GLenum result = 0;
1861 GLsizei count = 0;
1862 GLfloat* srcData = nullptr;
1863 std::tie(result, count, srcData) = CheckUniformDataInfo<GLfloat>(IsHighWebGL(), readData, info);
1864 if (result) {
1865 SET_ERROR(result);
1866 return NVal::CreateNull(env).val_;
1867 }
1868 HandleUniformMatrixInfo(transpose, info, location, count, srcData);
1869 LOGD("WebGL uniformMatrix_fv location %{public}d result %{public}u", location, GetError_());
1870 return NVal::CreateNull(env).val_;
1871 }
1872
CheckFrameBufferStatus(napi_env env,GLenum target)1873 napi_value WebGLRenderingContextBaseImpl::CheckFrameBufferStatus(napi_env env, GLenum target)
1874 {
1875 uint32_t index = 0;
1876 if (!CheckFrameBufferTarget(env, target, index)) {
1877 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1878 return NVal::CreateInt64(env, 0).val_;
1879 }
1880 WebGLFramebuffer* framebufferBinding = GetBoundFrameBuffer(env, target);
1881 if (!framebufferBinding) {
1882 return NVal::CreateInt64(env, WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE).val_;
1883 }
1884 GLenum result = framebufferBinding->CheckStatus(env, this);
1885 if (result != WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE) {
1886 return NVal::CreateInt64(env, static_cast<int64_t>(result)).val_;
1887 }
1888 result = glCheckFramebufferStatus(target);
1889 LOGD("WebGL checkFramebufferStatus target %{public}u result %{public}u", target, result);
1890 return NVal::CreateInt64(env, static_cast<int64_t>(result)).val_;
1891 }
1892
DepthMask(napi_env env,bool flag)1893 napi_value WebGLRenderingContextBaseImpl::DepthMask(napi_env env, bool flag)
1894 {
1895 LOGD("WebGL depthMask flag %{public}d", flag);
1896 depthMask_ = flag;
1897 glDepthMask(static_cast<GLboolean>(flag));
1898 return NVal::CreateNull(env).val_;
1899 }
1900
StencilMask(napi_env env,GLuint mask)1901 napi_value WebGLRenderingContextBaseImpl::StencilMask(napi_env env, GLuint mask)
1902 {
1903 LOGD("WebGL stencilMask mask %{public}u", mask);
1904 stencilMask_[0] = mask;
1905 stencilMask_[1] = mask;
1906 glStencilMask(mask);
1907 return NVal::CreateNull(env).val_;
1908 }
1909
StencilMaskSeparate(napi_env env,GLenum face,GLuint mask)1910 napi_value WebGLRenderingContextBaseImpl::StencilMaskSeparate(napi_env env, GLenum face, GLuint mask)
1911 {
1912 LOGD("WebGL stencilMaskSeparate face %{public}u mask %{public}u", face, mask);
1913 switch (face) {
1914 case WebGLRenderingContextBase::FRONT_AND_BACK: {
1915 stencilMask_[0] = mask;
1916 stencilMask_[1] = mask;
1917 break;
1918 }
1919 case WebGLRenderingContextBase::FRONT:
1920 stencilMask_[0] = mask;
1921 break;
1922 case WebGLRenderingContextBase::BACK:
1923 stencilMask_[1] = mask;
1924 break;
1925 default:
1926 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1927 return NVal::CreateNull(env).val_;
1928 }
1929 glStencilMaskSeparate(face, mask);
1930 return NVal::CreateNull(env).val_;
1931 }
1932
StencilFunc(napi_env env,GLenum func,GLint ref,GLuint mask)1933 napi_value WebGLRenderingContextBaseImpl::StencilFunc(napi_env env, GLenum func, GLint ref, GLuint mask)
1934 {
1935 LOGD("WebGL stencilFunc func %{public}u %{public}d %{public}u", func, ref, mask);
1936 if (!CheckGLenum(func,
1937 { WebGLRenderingContextBase::NEVER, WebGLRenderingContextBase::LESS, WebGLRenderingContextBase::EQUAL,
1938 WebGLRenderingContextBase::LEQUAL, WebGLRenderingContextBase::GREATER,
1939 WebGLRenderingContextBase::NOTEQUAL, WebGLRenderingContextBase::GEQUAL,
1940 WebGLRenderingContextBase::ALWAYS }, {})) {
1941 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1942 return NVal::CreateNull(env).val_;
1943 }
1944 stencilFuncRef_[0] = ref;
1945 stencilFuncRef_[1] = ref;
1946 stencilFuncMask_[0] = mask;
1947 stencilFuncMask_[1] = mask;
1948 glStencilFunc(func, ref, mask);
1949 return NVal::CreateNull(env).val_;
1950 }
1951
StencilFuncSeparate(napi_env env,GLenum face,GLenum func,GLint ref,GLuint mask)1952 napi_value WebGLRenderingContextBaseImpl::StencilFuncSeparate(
1953 napi_env env, GLenum face, GLenum func, GLint ref, GLuint mask)
1954 {
1955 LOGD("WebGL stencilFuncSeparate face %{public}u func %{public}u %{public}d %{public}u", face, func, ref, mask);
1956 switch (face) {
1957 case WebGLRenderingContextBase::FRONT_AND_BACK: {
1958 stencilFuncRef_[0] = ref;
1959 stencilFuncRef_[1] = ref;
1960 stencilFuncMask_[0] = mask;
1961 stencilFuncMask_[1] = mask;
1962 break;
1963 }
1964 case WebGLRenderingContextBase::FRONT: {
1965 stencilFuncRef_[0] = ref;
1966 stencilFuncMask_[0] = mask;
1967 break;
1968 }
1969 case WebGLRenderingContextBase::BACK: {
1970 stencilFuncRef_[1] = ref;
1971 stencilFuncMask_[1] = mask;
1972 break;
1973 }
1974 default:
1975 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM, "invalid face %{public}u", face);
1976 return NVal::CreateNull(env).val_;
1977 }
1978 if (!CheckGLenum(func,
1979 { WebGLRenderingContextBase::NEVER, WebGLRenderingContextBase::LESS, WebGLRenderingContextBase::EQUAL,
1980 WebGLRenderingContextBase::LEQUAL, WebGLRenderingContextBase::GREATER,
1981 WebGLRenderingContextBase::NOTEQUAL, WebGLRenderingContextBase::GEQUAL,
1982 WebGLRenderingContextBase::ALWAYS }, {})) {
1983 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
1984 return NVal::CreateNull(env).val_;
1985 }
1986 glStencilFuncSeparate(face, func, ref, mask);
1987 return NVal::CreateNull(env).val_;
1988 }
1989
1990 template<class T>
CheckTexParameter(napi_env env,GLenum target,GLenum pname,T param,bool isFloat)1991 GLenum WebGLRenderingContextBaseImpl::CheckTexParameter(
1992 napi_env env, GLenum target, GLenum pname, T param, bool isFloat)
1993 {
1994 WebGLTexture* textuer = GetBoundTexture(env, target, false);
1995 if (textuer == nullptr) {
1996 return WebGLRenderingContextBase::INVALID_VALUE;
1997 }
1998
1999 switch (pname) {
2000 case WebGLRenderingContextBase::TEXTURE_MIN_FILTER:
2001 case WebGLRenderingContextBase::TEXTURE_MAG_FILTER:
2002 break;
2003 case WebGL2RenderingContextBase::TEXTURE_WRAP_R: {
2004 if (!IsHighWebGL()) {
2005 return WebGLRenderingContextBase::INVALID_ENUM;
2006 }
2007 [[fallthrough]];
2008 }
2009 case WebGLRenderingContextBase::TEXTURE_WRAP_S:
2010 case WebGLRenderingContextBase::TEXTURE_WRAP_T: {
2011 if (param == WebGLRenderingContextBase::CLAMP_TO_EDGE ||
2012 param == WebGLRenderingContextBase::MIRRORED_REPEAT || param == WebGLRenderingContextBase::REPEAT) {
2013 break;
2014 }
2015 return WebGLRenderingContextBase::INVALID_ENUM;
2016 }
2017 case WebGL2RenderingContextBase::TEXTURE_COMPARE_FUNC:
2018 case WebGL2RenderingContextBase::TEXTURE_COMPARE_MODE:
2019 case WebGL2RenderingContextBase::TEXTURE_BASE_LEVEL:
2020 case WebGL2RenderingContextBase::TEXTURE_MAX_LEVEL:
2021 case WebGL2RenderingContextBase::TEXTURE_MAX_LOD:
2022 case WebGL2RenderingContextBase::TEXTURE_MIN_LOD: {
2023 if (!IsHighWebGL()) {
2024 return WebGLRenderingContextBase::INVALID_ENUM;
2025 }
2026 break;
2027 }
2028 default:
2029 return WebGLRenderingContextBase::INVALID_ENUM;
2030 }
2031 return WebGLRenderingContextBase::NO_ERROR;
2032 }
2033
TexParameteri(napi_env env,GLenum target,GLenum pname,GLint param)2034 napi_value WebGLRenderingContextBaseImpl::TexParameteri(napi_env env, GLenum target, GLenum pname, GLint param)
2035 {
2036 GLenum result = CheckTexParameter<GLint>(env, target, pname, param, false);
2037 if (result != WebGLRenderingContextBase::NO_ERROR) {
2038 SET_ERROR(result);
2039 return NVal::CreateNull(env).val_;
2040 }
2041 glTexParameteri(target, pname, static_cast<GLint>(param));
2042 LOGD("WebGL texParameteri target %{public}u %{public}u %{public}d result %{public}u ",
2043 target, pname, param, GetError_());
2044 return NVal::CreateNull(env).val_;
2045 }
2046
TexParameterf(napi_env env,GLenum target,GLenum pname,GLfloat param)2047 napi_value WebGLRenderingContextBaseImpl::TexParameterf(napi_env env, GLenum target, GLenum pname, GLfloat param)
2048 {
2049 GLenum result = CheckTexParameter<GLfloat>(env, target, pname, param, false);
2050 if (result != WebGLRenderingContextBase::NO_ERROR) {
2051 SET_ERROR(result);
2052 return NVal::CreateNull(env).val_;
2053 }
2054 glTexParameterf(target, pname, static_cast<GLfloat>(param));
2055 LOGD("WebGL texParameterf target %{public}u %{public}u %{public}f result %{public}u ",
2056 target, pname, param, GetError_());
2057 return NVal::CreateNull(env).val_;
2058 }
2059
GetTexParameter(napi_env env,GLenum target,GLenum pname)2060 napi_value WebGLRenderingContextBaseImpl::GetTexParameter(napi_env env, GLenum target, GLenum pname)
2061 {
2062 WebGLTexture* texture = GetBoundTexture(env, target, false);
2063 if (!texture) {
2064 return NVal::CreateNull(env).val_;
2065 }
2066 if (IsHighWebGL()) {
2067 switch (pname) {
2068 case GL_TEXTURE_WRAP_R:
2069 case GL_TEXTURE_COMPARE_FUNC:
2070 case GL_TEXTURE_COMPARE_MODE:
2071 case GL_TEXTURE_BASE_LEVEL:
2072 case GL_TEXTURE_MAX_LEVEL:
2073 case GL_TEXTURE_IMMUTABLE_LEVELS: {
2074 GLint params = 0;
2075 glGetTexParameteriv(target, pname, ¶ms);
2076 return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
2077 }
2078 case GL_TEXTURE_IMMUTABLE_FORMAT: {
2079 GLint params = 0;
2080 glGetTexParameteriv(target, pname, ¶ms);
2081 return NVal::CreateBool(env, params == 1).val_;
2082 }
2083 case GL_TEXTURE_MAX_LOD:
2084 case GL_TEXTURE_MIN_LOD: {
2085 GLfloat params = 0.f;
2086 glGetTexParameterfv(target, pname, ¶ms);
2087 return NVal::CreateDouble(env, static_cast<double>(params)).val_;
2088 }
2089 default:
2090 break;
2091 }
2092 }
2093
2094 switch (pname) {
2095 case WebGLRenderingContextBase::TEXTURE_MAG_FILTER:
2096 case WebGLRenderingContextBase::TEXTURE_MIN_FILTER:
2097 case WebGLRenderingContextBase::TEXTURE_WRAP_S:
2098 case WebGLRenderingContextBase::TEXTURE_WRAP_T: {
2099 GLint params = 0;
2100 glGetTexParameteriv(target, pname, ¶ms);
2101 LOGD("WebGL getTexParameter params %{public}d", params);
2102 return NVal::CreateInt64(env, static_cast<int64_t>(params)).val_;
2103 }
2104 default:
2105 SET_ERROR(WebGLRenderingContextBase::INVALID_ENUM);
2106 return NVal::CreateNull(env).val_;
2107 }
2108 }
2109
VertexAttribfv(napi_env env,GLuint index,int32_t count,napi_value dataObj)2110 napi_value WebGLRenderingContextBaseImpl::VertexAttribfv(napi_env env, GLuint index, int32_t count, napi_value dataObj)
2111 {
2112 LOGD("WebGL vertexAttribfv index %{public}u %{public}d", index, count);
2113 WebGLReadBufferArg bufferData(env);
2114 napi_status status = bufferData.GenBufferData(dataObj, BUFFER_DATA_FLOAT_32);
2115 if (status != 0) {
2116 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "WebGL vertexAttribfv failed to getbuffer data");
2117 return NVal::CreateNull(env).val_;
2118 }
2119 bufferData.DumpBuffer(bufferData.GetBufferDataType());
2120 if (bufferData.GetBufferDataType() != BUFFER_DATA_FLOAT_32) {
2121 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2122 "WebGL :vertexAttribfv invalid buffer data type = %{public}d",
2123 static_cast<uint32_t>(bufferData.GetBufferDataType()));
2124 return NVal::CreateNull(env).val_;
2125 }
2126
2127 if (static_cast<int32_t>(bufferData.GetBufferLength() / sizeof(float)) < count) {
2128 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2129 "WebGL vertexAttribfv invalid data length %{public}zu", bufferData.GetBufferLength());
2130 return NVal::CreateNull(env).val_;
2131 }
2132 VertexAttribInfo* info = GetVertexAttribInfo(index);
2133 if (info == nullptr) {
2134 SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
2135 return NVal::CreateNull(env).val_;
2136 }
2137
2138 switch (count) {
2139 case PARAMETERS_NUM_1:
2140 glVertexAttrib1fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2141 break;
2142 case PARAMETERS_NUM_2:
2143 glVertexAttrib2fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2144 break;
2145 case PARAMETERS_NUM_3:
2146 glVertexAttrib3fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2147 break;
2148 case PARAMETERS_NUM_4:
2149 glVertexAttrib4fv(index, reinterpret_cast<GLfloat*>(bufferData.GetBuffer()));
2150 break;
2151 default:
2152 break;
2153 }
2154 info->type = BUFFER_DATA_FLOAT_32;
2155 return NVal::CreateNull(env).val_;
2156 }
2157
VertexAttribf(napi_env env,GLuint index,int32_t count,GLfloat * data)2158 napi_value WebGLRenderingContextBaseImpl::VertexAttribf(napi_env env, GLuint index, int32_t count, GLfloat* data)
2159 {
2160 VertexAttribInfo* info = GetVertexAttribInfo(index);
2161 if (info == nullptr) {
2162 SET_ERROR(WebGLRenderingContextBase::INVALID_VALUE);
2163 return NVal::CreateNull(env).val_;
2164 }
2165 // In GL, we skip setting vertexAttrib0 values.
2166 switch (count) {
2167 case PARAMETERS_NUM_1:
2168 glVertexAttrib1f(index, data[0]);
2169 break;
2170 case PARAMETERS_NUM_2:
2171 glVertexAttrib2f(index, data[0], data[1]);
2172 break;
2173 case PARAMETERS_NUM_3:
2174 glVertexAttrib3f(index, data[0], data[1], data[2]); // 1, 2 index
2175 break;
2176 case PARAMETERS_NUM_4:
2177 glVertexAttrib4f(index, data[0], data[1], data[2], data[3]); // 1, 2, 3 index
2178 break;
2179 default:
2180 break;
2181 }
2182 LOGD("WebGL vertexAttribf index %{public}u count %{public}d result %{public}u", index, count, GetError_());
2183 info->type = BUFFER_DATA_FLOAT_32;
2184 return NVal::CreateNull(env).val_;
2185 }
2186
GetUniformType(napi_env env,GLuint programId,GLint locationId)2187 GLenum WebGLRenderingContextBaseImpl::GetUniformType(napi_env env, GLuint programId, GLint locationId)
2188 {
2189 GLint maxNameLength = -1;
2190 glGetProgramiv(programId, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
2191 if (maxNameLength <= 0) {
2192 return 0;
2193 }
2194
2195 GLint activeUniforms = 0;
2196 glGetProgramiv(programId, GL_ACTIVE_UNIFORMS, &activeUniforms);
2197 LOGD("WebGL getUniform maxNameLength %{public}d activeUniforms %{public}d", maxNameLength, activeUniforms);
2198 if (locationId >= activeUniforms) {
2199 return 0;
2200 }
2201 GLenum type = 0;
2202 std::vector<GLchar> name(maxNameLength + 1);
2203 name[maxNameLength] = '\0';
2204 for (int32_t i = 0; i < activeUniforms; i++) {
2205 GLsizei nameLength = 0;
2206 GLint size = -1;
2207 glGetActiveUniform(programId, i, maxNameLength, &nameLength, &size, &type, name.data());
2208 LOGD("WebGL getUniform index %{public}d type 0x%{public}x name %{public}s ", i, type, name.data());
2209 if (locationId == i) {
2210 break;
2211 }
2212 }
2213 return type;
2214 }
2215
GetUniform(napi_env env,napi_value programObj,napi_value uniformObj)2216 napi_value WebGLRenderingContextBaseImpl::GetUniform(napi_env env, napi_value programObj, napi_value uniformObj)
2217 {
2218 WebGLProgram* webGLProgram = WebGLProgram::GetObjectInstance(env, programObj);
2219 WebGLUniformLocation* webGLUniformLocation = WebGLUniformLocation::GetObjectInstance(env, uniformObj);
2220 if (webGLUniformLocation == nullptr || webGLProgram == nullptr) {
2221 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2222 "webGLUniformLocation or webGLProgram is nullptr.");
2223 return NVal::CreateNull(env).val_;
2224 }
2225 GLuint programId = webGLProgram->GetProgramId();
2226 GLint locationId = webGLUniformLocation->GetUniformLocationId();
2227 const UniformTypeMap* typeMap = GetUniformTypeMap(GetUniformType(env, programId, locationId));
2228 if (typeMap == nullptr) {
2229 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "typeMap is nullptr.");
2230 return NVal::CreateNull(env).val_;
2231 }
2232 WebGLWriteBufferArg writeBuffer(env);
2233 GLint* data = reinterpret_cast<GLint*>(writeBuffer.AllocBuffer(typeMap->length * sizeof(GLfloat)));
2234 if (data == nullptr) {
2235 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "data is nullptr.");
2236 return NVal::CreateNull(env).val_;
2237 }
2238 switch (typeMap->baseType) {
2239 case GL_FLOAT: {
2240 GLfloat* params = reinterpret_cast<GLfloat*>(data);
2241 glGetUniformfv(programId, locationId, params);
2242 if (typeMap->length == 1) {
2243 return NVal::CreateDouble(env, params[0]).val_;
2244 }
2245 break;
2246 }
2247 case GL_INT: {
2248 glGetUniformiv(programId, locationId, data);
2249 if (typeMap->length == 1) {
2250 return NVal::CreateInt64(env, data[0]).val_;
2251 }
2252 break;
2253 }
2254 case GL_BOOL: {
2255 glGetUniformiv(programId, locationId, data);
2256 if (typeMap->length == 1) {
2257 return NVal::CreateBool(env, data[0]).val_;
2258 }
2259 break;
2260 }
2261 case GL_UNSIGNED_INT: {
2262 GLuint* params = reinterpret_cast<GLuint*>(data);
2263 glGetUniformuiv(programId, locationId, params);
2264 if (typeMap->length == 1) {
2265 return NVal::CreateInt64(env, params[0]).val_;
2266 }
2267 break;
2268 }
2269 default:
2270 break;
2271 }
2272 writeBuffer.DumpBuffer(typeMap->dstType);
2273 return writeBuffer.ToNormalArray(typeMap->srcType, typeMap->dstType);
2274 }
2275
CheckGLenum(GLenum type,const std::vector<GLenum> & glSupport,const std::vector<GLenum> & g2Support)2276 bool WebGLRenderingContextBaseImpl::CheckGLenum(
2277 GLenum type, const std::vector<GLenum>& glSupport, const std::vector<GLenum>& g2Support)
2278 {
2279 auto it = std::find(glSupport.begin(), glSupport.end(), type);
2280 if (it != glSupport.end()) {
2281 return true;
2282 }
2283 if (!IsHighWebGL()) {
2284 return false;
2285 }
2286 auto it2 = std::find(g2Support.begin(), g2Support.end(), type);
2287 if (it2 != g2Support.end()) {
2288 return true;
2289 }
2290 return false;
2291 }
2292
CheckInList(GLenum type,const std::vector<GLenum> & glSupport)2293 bool WebGLRenderingContextBaseImpl::CheckInList(GLenum type, const std::vector<GLenum>& glSupport)
2294 {
2295 auto it = std::find(glSupport.begin(), glSupport.end(), type);
2296 if (it != glSupport.end()) {
2297 return true;
2298 }
2299 return false;
2300 }
2301
CheckCap(napi_env env,GLenum cap)2302 bool WebGLRenderingContextBaseImpl::CheckCap(napi_env env, GLenum cap)
2303 {
2304 return CheckGLenum(cap,
2305 { WebGLRenderingContextBase::BLEND, WebGLRenderingContextBase::CULL_FACE, WebGLRenderingContextBase::DEPTH_TEST,
2306 WebGLRenderingContextBase::DITHER, WebGLRenderingContextBase::POLYGON_OFFSET_FILL,
2307 WebGLRenderingContextBase::SAMPLE_ALPHA_TO_COVERAGE, WebGLRenderingContextBase::SAMPLE_COVERAGE,
2308 WebGLRenderingContextBase::SCISSOR_TEST, WebGLRenderingContextBase::STENCIL_TEST },
2309 { WebGL2RenderingContextBase::RASTERIZER_DISCARD });
2310 }
2311
CheckInternalFormat(napi_env env,GLenum internalFormat)2312 bool WebGLRenderingContextBaseImpl::CheckInternalFormat(napi_env env, GLenum internalFormat)
2313 {
2314 static const std::vector<GLenum> glSupport = { WebGLRenderingContextBase::RGBA4, WebGLRenderingContextBase::RGB565,
2315 WebGLRenderingContextBase::RGB5_A1, WebGLRenderingContextBase::DEPTH_COMPONENT16,
2316 WebGLRenderingContextBase::STENCIL_INDEX8, WebGLRenderingContextBase::DEPTH_STENCIL };
2317 static const std::vector<GLenum> gl2Support = { WebGL2RenderingContextBase::R8, WebGL2RenderingContextBase::R8UI,
2318 WebGL2RenderingContextBase::R8I, WebGL2RenderingContextBase::R16UI, WebGL2RenderingContextBase::R16I,
2319 WebGL2RenderingContextBase::R32UI, WebGL2RenderingContextBase::R32I,
2320
2321 WebGL2RenderingContextBase::RG8, WebGL2RenderingContextBase::RG8UI, WebGL2RenderingContextBase::RG8I,
2322 WebGL2RenderingContextBase::RG16UI, WebGL2RenderingContextBase::RG16I, WebGL2RenderingContextBase::RG32UI,
2323 WebGL2RenderingContextBase::RG32I,
2324
2325 WebGL2RenderingContextBase::RGB8, WebGL2RenderingContextBase::RGBA8, WebGL2RenderingContextBase::SRGB8_ALPHA8,
2326 WebGL2RenderingContextBase::RGB10_A2, WebGL2RenderingContextBase::RGBA8UI, WebGL2RenderingContextBase::RGBA8I,
2327 WebGL2RenderingContextBase::RGB10_A2UI,
2328
2329 WebGL2RenderingContextBase::RGBA16UI, WebGL2RenderingContextBase::RGBA16I, WebGL2RenderingContextBase::RGBA32I,
2330 WebGL2RenderingContextBase::RGBA32UI, WebGL2RenderingContextBase::DEPTH_COMPONENT24,
2331 WebGL2RenderingContextBase::DEPTH_COMPONENT32F, WebGL2RenderingContextBase::DEPTH24_STENCIL8,
2332 WebGL2RenderingContextBase::DEPTH32F_STENCIL8 };
2333 return CheckGLenum(internalFormat, glSupport, gl2Support);
2334 }
2335
CheckAttachment(napi_env env,GLenum attachment)2336 bool WebGLRenderingContextBaseImpl::CheckAttachment(napi_env env, GLenum attachment)
2337 {
2338 static const std::vector<GLenum> glSupport = { WebGLRenderingContextBase::COLOR_ATTACHMENT0,
2339 WebGLRenderingContextBase::DEPTH_ATTACHMENT, WebGLRenderingContextBase::STENCIL_ATTACHMENT,
2340 WebGLRenderingContextBase::DEPTH_STENCIL_ATTACHMENT };
2341
2342 if (!CheckGLenum(attachment, glSupport, {})) {
2343 if (IsHighWebGL()) {
2344 if (attachment < WebGLRenderingContextBase::COLOR_ATTACHMENT0 ||
2345 attachment > WebGLRenderingContextBase::COLOR_ATTACHMENT0 +
2346 static_cast<GLenum>(GetMaxColorAttachments())) {
2347 return false;
2348 }
2349 }
2350 }
2351 return true;
2352 }
2353
GetBoundTexture(napi_env env,GLenum target,bool cubeMapExt)2354 WebGLTexture* WebGLRenderingContextBaseImpl::GetBoundTexture(napi_env env, GLenum target, bool cubeMapExt)
2355 {
2356 uint32_t index = 0;
2357 switch (target) {
2358 case WebGLRenderingContextBase::TEXTURE_2D:
2359 index = BoundTextureType::TEXTURE_2D;
2360 break;
2361 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_X:
2362 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_X:
2363 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Y:
2364 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Y:
2365 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Z:
2366 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Z: {
2367 if (!cubeMapExt) {
2368 return nullptr;
2369 }
2370 index = BoundTextureType::TEXTURE_CUBE_MAP;
2371 break;
2372 }
2373 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP: {
2374 if (cubeMapExt) {
2375 return nullptr;
2376 }
2377 index = BoundTextureType::TEXTURE_CUBE_MAP;
2378 break;
2379 }
2380 case WebGL2RenderingContextBase::TEXTURE_2D_ARRAY: {
2381 if (!IsHighWebGL()) {
2382 return nullptr;
2383 }
2384 index = BoundTextureType::TEXTURE_2D_ARRAY;
2385 break;
2386 }
2387 case WebGL2RenderingContextBase::TEXTURE_3D: {
2388 if (!IsHighWebGL()) {
2389 return nullptr;
2390 }
2391 index = BoundTextureType::TEXTURE_3D;
2392 break;
2393 }
2394 default:
2395 return nullptr;
2396 }
2397 if (activeTextureIndex_ >= boundTexture_[index].size()) {
2398 return nullptr;
2399 }
2400
2401 return GetObjectInstance<WebGLTexture>(env, boundTexture_[index][activeTextureIndex_]);
2402 }
2403
GetBoundFrameBuffer(napi_env env,GLenum target)2404 WebGLFramebuffer* WebGLRenderingContextBaseImpl::GetBoundFrameBuffer(napi_env env, GLenum target)
2405 {
2406 uint32_t index = 0;
2407 if (!CheckFrameBufferTarget(env, target, index)) {
2408 return nullptr;
2409 }
2410 LOGD("Get bound Frame buffer target %{public}u id %{public}u ", target, boundFrameBufferIds_[index]);
2411 return GetObjectInstance<WebGLFramebuffer>(env, boundFrameBufferIds_[index]);
2412 }
2413
GetBoundRenderBuffer(napi_env env,GLenum target)2414 WebGLRenderbuffer* WebGLRenderingContextBaseImpl::GetBoundRenderBuffer(napi_env env, GLenum target)
2415 {
2416 uint32_t index = 0;
2417 if (!CheckRenderBufferTarget(env, target, index)) {
2418 return nullptr;
2419 }
2420 LOGD("Get bound render buffer target %{public}u id %{public}u ", target, boundRenderBufferIds_[index]);
2421 return GetObjectInstance<WebGLRenderbuffer>(env, boundRenderBufferIds_[index]);
2422 }
2423
GetBoundBuffer(napi_env env,GLenum target)2424 WebGLBuffer* WebGLRenderingContextBaseImpl::GetBoundBuffer(napi_env env, GLenum target)
2425 {
2426 uint32_t index = BoundBufferType::ARRAY_BUFFER;
2427 if (!CheckBufferTarget(env, target, index)) {
2428 return nullptr;
2429 }
2430 LOGD("Get bound buffer target %{public}u id %{public}u ", target, boundBufferIds_[index]);
2431 return GetObjectInstance<WebGLBuffer>(env, boundBufferIds_[index]);
2432 }
2433
CheckDrawMode(napi_env env,GLenum mode)2434 bool WebGLRenderingContextBaseImpl::CheckDrawMode(napi_env env, GLenum mode)
2435 {
2436 return CheckGLenum(mode,
2437 {
2438 WebGLRenderingContextBase::POINTS,
2439 WebGLRenderingContextBase::LINE_STRIP,
2440 WebGLRenderingContextBase::LINE_LOOP,
2441 WebGLRenderingContextBase::LINES,
2442 WebGLRenderingContextBase::TRIANGLE_STRIP,
2443 WebGLRenderingContextBase::TRIANGLE_FAN,
2444 WebGLRenderingContextBase::TRIANGLES
2445 },
2446 {});
2447 }
2448
CheckFrameBufferTarget(napi_env env,GLenum target,uint32_t & index)2449 bool WebGLRenderingContextBaseImpl::CheckFrameBufferTarget(napi_env env, GLenum target, uint32_t& index)
2450 {
2451 switch (target) {
2452 case WebGLRenderingContextBase::FRAMEBUFFER:
2453 index = BoundFrameBufferType::FRAMEBUFFER;
2454 return true;
2455 default:
2456 break;
2457 }
2458 if (!IsHighWebGL()) {
2459 return false;
2460 }
2461 switch (target) {
2462 case WebGL2RenderingContextBase::DRAW_FRAMEBUFFER:
2463 index = BoundFrameBufferType::DRAW_FRAMEBUFFER;
2464 return true;
2465 case WebGL2RenderingContextBase::READ_FRAMEBUFFER:
2466 index = BoundFrameBufferType::READ_FRAMEBUFFER;
2467 return true;
2468 default:
2469 break;
2470 }
2471 return false;
2472 }
2473
CheckRenderBufferTarget(napi_env env,GLenum target,uint32_t & index)2474 bool WebGLRenderingContextBaseImpl::CheckRenderBufferTarget(napi_env env, GLenum target, uint32_t& index)
2475 {
2476 switch (target) {
2477 case WebGLRenderingContextBase::RENDERBUFFER:
2478 index = BoundRenderBufferType::RENDERBUFFER;
2479 return true;
2480 default:
2481 break;
2482 }
2483 return false;
2484 }
2485
CheckTextureTarget(napi_env env,GLenum target,uint32_t & index)2486 bool WebGLRenderingContextBaseImpl::CheckTextureTarget(napi_env env, GLenum target, uint32_t& index)
2487 {
2488 switch (target) {
2489 case WebGLRenderingContextBase::TEXTURE_2D:
2490 index = BoundTextureType::TEXTURE_2D;
2491 break;
2492 case WebGLRenderingContextBase::TEXTURE_CUBE_MAP:
2493 index = BoundTextureType::TEXTURE_CUBE_MAP;
2494 break;
2495 case WebGL2RenderingContextBase::TEXTURE_3D:
2496 index = BoundTextureType::TEXTURE_3D;
2497 break;
2498 case WebGL2RenderingContextBase::TEXTURE_2D_ARRAY:
2499 index = BoundTextureType::TEXTURE_2D_ARRAY;
2500 break;
2501 default:
2502 if (IsHighWebGL()) {
2503 break;
2504 }
2505 return false;
2506 }
2507 return true;
2508 }
2509
CheckShaderType(napi_env env,GLenum type,uint32_t & index)2510 bool WebGLRenderingContextBaseImpl::CheckShaderType(napi_env env, GLenum type, uint32_t& index)
2511 {
2512 switch (type) {
2513 case WebGLRenderingContextBase::VERTEX_SHADER:
2514 index = BoundShaderType::VERTEX_SHADER;
2515 break;
2516 case WebGLRenderingContextBase::FRAGMENT_SHADER:
2517 index = BoundShaderType::FRAGMENT_SHADER;
2518 break;
2519 default:
2520 return false;
2521 }
2522 return true;
2523 }
2524
CheckTexture2DTarget(napi_env env,GLenum target)2525 bool WebGLRenderingContextBaseImpl::CheckTexture2DTarget(napi_env env, GLenum target)
2526 {
2527 return CheckGLenum(target,
2528 { WebGLRenderingContextBase::TEXTURE_2D, WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_X,
2529 WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_X,
2530 WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Y,
2531 WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Y,
2532 WebGLRenderingContextBase::TEXTURE_CUBE_MAP_POSITIVE_Z,
2533 WebGLRenderingContextBase::TEXTURE_CUBE_MAP_NEGATIVE_Z },
2534 {});
2535 }
2536
CheckBufferTarget(napi_env env,GLenum target,uint32_t & index)2537 bool WebGLRenderingContextBaseImpl::CheckBufferTarget(napi_env env, GLenum target, uint32_t& index)
2538 {
2539 switch (target) {
2540 case WebGLRenderingContextBase::ARRAY_BUFFER:
2541 index = BoundBufferType::ARRAY_BUFFER;
2542 break;
2543 case WebGLRenderingContextBase::ELEMENT_ARRAY_BUFFER:
2544 index = BoundBufferType::ELEMENT_ARRAY_BUFFER;
2545 break;
2546 case WebGL2RenderingContextBase::COPY_READ_BUFFER:
2547 index = BoundBufferType::COPY_READ_BUFFER;
2548 break;
2549 case WebGL2RenderingContextBase::COPY_WRITE_BUFFER:
2550 index = BoundBufferType::COPY_WRITE_BUFFER;
2551 break;
2552 case WebGL2RenderingContextBase::TRANSFORM_FEEDBACK_BUFFER:
2553 index = BoundBufferType::TRANSFORM_FEEDBACK_BUFFER;
2554 break;
2555 case WebGL2RenderingContextBase::UNIFORM_BUFFER:
2556 index = BoundBufferType::UNIFORM_BUFFER;
2557 break;
2558 case WebGL2RenderingContextBase::PIXEL_PACK_BUFFER:
2559 index = BoundBufferType::PIXEL_PACK_BUFFER;
2560 break;
2561 case WebGL2RenderingContextBase::PIXEL_UNPACK_BUFFER:
2562 index = BoundBufferType::PIXEL_UNPACK_BUFFER;
2563 break;
2564 default:
2565 if (IsHighWebGL()) {
2566 break;
2567 }
2568 return false;
2569 }
2570 return true;
2571 }
2572
CheckBufferDataUsage(napi_env env,GLenum usage)2573 bool WebGLRenderingContextBaseImpl::CheckBufferDataUsage(napi_env env, GLenum usage)
2574 {
2575 return CheckGLenum(usage, { GL_STREAM_DRAW, GL_STATIC_DRAW, GL_DYNAMIC_DRAW },
2576 { GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_READ, GL_DYNAMIC_COPY });
2577 }
2578
CheckPixelsFormat(napi_env env,GLenum format)2579 bool WebGLRenderingContextBaseImpl::CheckPixelsFormat(napi_env env, GLenum format)
2580 {
2581 return CheckGLenum(format, { GL_ALPHA, GL_RGB, GL_RGBA },
2582 {
2583 GL_RED,
2584 GL_RED_INTEGER,
2585 GL_RG,
2586 GL_RG_INTEGER,
2587 GL_RGBA,
2588 GL_RGBA_INTEGER,
2589 GL_LUMINANCE_ALPHA,
2590 GL_LUMINANCE,
2591 GL_ALPHA,
2592 GL_RGB,
2593 GL_RGB_INTEGER,
2594 });
2595 }
2596
CheckPixelsType(napi_env env,GLenum type)2597 bool WebGLRenderingContextBaseImpl::CheckPixelsType(napi_env env, GLenum type)
2598 {
2599 return CheckGLenum(type,
2600 { 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,
2601 GL_HALF_FLOAT_OES },
2602 { GL_UNSIGNED_BYTE, GL_BYTE, GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT_5_6_5,
2603 GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, GL_SHORT, GL_UNSIGNED_INT,
2604 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
2605 });
2606 }
2607
CheckStencil(napi_env env)2608 bool WebGLRenderingContextBaseImpl::CheckStencil(napi_env env)
2609 {
2610 if (stencilMask_[0] != stencilMask_[1] || stencilFuncRef_[0] != stencilFuncRef_[1] ||
2611 stencilFuncMask_[0] != stencilFuncMask_[1]) {
2612 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
2613 "front and back stencils settings do not match");
2614 return false;
2615 }
2616 return true;
2617 }
2618
CheckLocationName(const std::string & name)2619 bool WebGLRenderingContextBaseImpl::CheckLocationName(const std::string& name)
2620 {
2621 if (name.size() > MAX_LOCATION_LENGTH) {
2622 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "check name size failed.%{public}zu",
2623 name.size());
2624 return false;
2625 }
2626 if (!WebGLArg::CheckString(name)) {
2627 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE, "CheckString failed.");
2628 return false;
2629 }
2630 if (WebGLArg::CheckReservedPrefix(name)) {
2631 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION, "CheckReservedPrefix failed.");
2632 return false;
2633 }
2634 return true;
2635 }
2636
CheckRenderBufferStorage(napi_env env,const TexStorageArg & arg)2637 WebGLRenderbuffer* WebGLRenderingContextBaseImpl::CheckRenderBufferStorage(napi_env env, const TexStorageArg& arg)
2638 {
2639 uint32_t index = 0;
2640 if (!CheckRenderBufferTarget(env, arg.target, index)) {
2641 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
2642 "WebGL renderbufferStorage invalid target %{public}u", arg.target);
2643 return nullptr;
2644 }
2645 if (!CheckInternalFormat(env, arg.internalFormat)) {
2646 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_ENUM,
2647 "WebGL renderbufferStorage invalid internalFormat %{public}u", arg.internalFormat);
2648 return nullptr;
2649 }
2650 if (arg.width < 0 || arg.height < 0) {
2651 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_VALUE,
2652 "WebGL renderbufferStorage invalid size %{public}d %{public}d", arg.width, arg.height);
2653 return nullptr;
2654 }
2655 WebGLRenderbuffer* renderBuffer = GetObjectInstance<WebGLRenderbuffer>(env, boundRenderBufferIds_[index]);
2656 if (renderBuffer == nullptr) {
2657 SET_ERROR_WITH_LOG(WebGLRenderingContextBase::INVALID_OPERATION,
2658 "WebGL renderbufferStorage can not get bound render buffer Id %{public}u", boundRenderBufferIds_[index]);
2659 return nullptr;
2660 }
2661 return renderBuffer;
2662 }
2663
CheckProgramLinkStatus(WebGLProgram * program)2664 bool WebGLRenderingContextBaseImpl::CheckProgramLinkStatus(WebGLProgram* program)
2665 {
2666 if (program == nullptr) {
2667 return false;
2668 }
2669 GLint params = 0;
2670 glGetProgramiv(static_cast<GLuint>(program->GetProgramId()), WebGLRenderingContextBase::LINK_STATUS, ¶ms);
2671 if (params) {
2672 return true;
2673 }
2674 return false;
2675 }
2676
GetUniformTypeMap(GLenum type)2677 const UniformTypeMap* WebGLRenderingContextBaseImpl::GetUniformTypeMap(GLenum type)
2678 {
2679 const static UniformTypeMap baseTypeMap[] = {
2680 { GL_FLOAT, GL_FLOAT, 1, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2681 { GL_FLOAT_VEC2, GL_FLOAT, 2, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2682 { GL_FLOAT_VEC3, GL_FLOAT, 3, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2683 { GL_FLOAT_VEC4, GL_FLOAT, 4, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2684 { GL_FLOAT_MAT2, GL_FLOAT, 4, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2685 { GL_FLOAT_MAT3, GL_FLOAT, 9, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2686 { GL_FLOAT_MAT4, GL_FLOAT, 16, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2687
2688 { GL_INT, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2689 { GL_INT_VEC2, GL_INT, 2, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2690 { GL_INT_VEC3, GL_INT, 3, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2691 { GL_INT_VEC4, GL_INT, 4, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2692
2693 { GL_BOOL, GL_BOOL, 1, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2694 { GL_BOOL_VEC2, GL_BOOL, 2, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2695 { GL_BOOL_VEC3, GL_BOOL, 3, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2696 { GL_BOOL_VEC4, GL_BOOL, 4, BUFFER_DATA_INT_32, BUFFER_DATA_BOOLEAN },
2697
2698 { GL_SAMPLER_2D, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2699 { GL_SAMPLER_CUBE, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2700 };
2701
2702 const static UniformTypeMap webgl2BaseTypeMap[] = {
2703 { GL_UNSIGNED_INT, GL_UNSIGNED_INT, 1, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2704 { GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT, 2, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2705 { GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT, 3, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2706 { GL_UNSIGNED_INT_VEC4, GL_UNSIGNED_INT, 4, BUFFER_DATA_UINT_32, BUFFER_DATA_UINT_32 },
2707
2708 { GL_FLOAT_MAT2x3, GL_FLOAT, 6, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2709 { GL_FLOAT_MAT2x4, GL_FLOAT, 8, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2710 { GL_FLOAT_MAT3x2, GL_FLOAT, 6, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2711 { GL_FLOAT_MAT3x4, GL_FLOAT, 12, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2712 { GL_FLOAT_MAT4x2, GL_FLOAT, 8, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2713 { GL_FLOAT_MAT4x3, GL_FLOAT, 12, BUFFER_DATA_FLOAT_32, BUFFER_DATA_FLOAT_32 },
2714
2715 { GL_SAMPLER_3D, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2716 { GL_SAMPLER_2D_ARRAY, GL_INT, 1, BUFFER_DATA_INT_32, BUFFER_DATA_INT_32 },
2717 };
2718 for (size_t i = 0; i < sizeof(baseTypeMap) / sizeof(baseTypeMap[0]); i++) {
2719 if (baseTypeMap[i].type == type) {
2720 return &baseTypeMap[i];
2721 }
2722 }
2723 if (!IsHighWebGL()) {
2724 return nullptr;
2725 }
2726 for (size_t i = 0; i < sizeof(webgl2BaseTypeMap) / sizeof(webgl2BaseTypeMap[0]); i++) {
2727 if (webgl2BaseTypeMap[i].type == type) {
2728 return &webgl2BaseTypeMap[i];
2729 }
2730 }
2731 return nullptr;
2732 }
2733
CheckFrameBufferBoundComplete(napi_env env)2734 GLenum WebGLRenderingContextBaseImpl::CheckFrameBufferBoundComplete(napi_env env)
2735 {
2736 WebGLFramebuffer* framebufferBinding = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
2737 if (framebufferBinding &&
2738 framebufferBinding->CheckStatus(env, this) != WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE) {
2739 return WebGLRenderingContextBase::INVALID_FRAMEBUFFER_OPERATION;
2740 }
2741 GLenum complete = glCheckFramebufferStatus(WebGLRenderingContextBase::FRAMEBUFFER);
2742 LOGD("CheckFrameBufferBoundComplete complete %{public}u", complete);
2743 if (complete != WebGLRenderingContextBase::FRAMEBUFFER_COMPLETE) {
2744 return WebGLRenderingContextBase::INVALID_FRAMEBUFFER_OPERATION;
2745 }
2746 return WebGLRenderingContextBase::NO_ERROR;
2747 }
2748
CheckReadPixelsArg(napi_env env,const PixelsArg & arg,uint64_t bufferSize)2749 GLenum WebGLRenderingContextBaseImpl::CheckReadPixelsArg(napi_env env, const PixelsArg& arg, uint64_t bufferSize)
2750 {
2751 if (!CheckPixelsFormat(env, arg.format) || !CheckPixelsType(env, arg.type)) {
2752 return WebGLRenderingContextBase::INVALID_ENUM;
2753 }
2754 return 0;
2755 }
2756
CheckVertexAttribPointer(napi_env env,const VertexAttribArg & vertexInfo)2757 GLenum WebGLRenderingContextBaseImpl::CheckVertexAttribPointer(napi_env env, const VertexAttribArg& vertexInfo)
2758 {
2759 if (vertexInfo.index >= GetMaxVertexAttribs()) {
2760 LOGE("WebGL vertexAttribPointer invalid index %{public}u", vertexInfo.index);
2761 return WebGLRenderingContextBase::INVALID_VALUE;
2762 }
2763 // check size, 4 is max vertexInfo size, 255 is max vertexInfo stride
2764 if (vertexInfo.size < 1 || vertexInfo.size > 4 || vertexInfo.stride < 0 || vertexInfo.stride > 255) {
2765 LOGE("WebGL vertexAttribPointer invalid size %{public}d %{public}d", vertexInfo.size, vertexInfo.stride);
2766 return WebGLRenderingContextBase::INVALID_VALUE;
2767 }
2768 // check offset
2769 WebGLBuffer* webGLBuffer = GetBoundBuffer(env, WebGLRenderingContextBase::ARRAY_BUFFER);
2770 if (webGLBuffer == nullptr || webGLBuffer->GetBufferSize() == 0) {
2771 LOGE("WebGL vertexAttribPointer can not bind buffer");
2772 return WebGLRenderingContextBase::INVALID_OPERATION;
2773 }
2774
2775 // check offset
2776 if (vertexInfo.offset >= static_cast<GLintptr>(webGLBuffer->GetBufferSize())) {
2777 LOGE("WebGL vertexAttribPointer invalid offset %{public}u", static_cast<unsigned int>(vertexInfo.offset));
2778 return WebGLRenderingContextBase::INVALID_VALUE;
2779 }
2780
2781 uint32_t typeSize = WebGLArg::GetWebGLDataSize(vertexInfo.type);
2782 if ((static_cast<uint32_t>(vertexInfo.stride) & static_cast<uint32_t>(typeSize - 1)) ||
2783 (static_cast<uint32_t>(vertexInfo.offset) & static_cast<uint32_t>(typeSize - 1))) {
2784 return WebGLRenderingContextBase::INVALID_OPERATION;
2785 }
2786 return WebGLRenderingContextBase::NO_ERROR;
2787 }
2788
GetBoundFrameBufferColorFormat(napi_env env)2789 GLenum WebGLRenderingContextBaseImpl::GetBoundFrameBufferColorFormat(napi_env env)
2790 {
2791 WebGLFramebuffer* frameBuffer = GetBoundFrameBuffer(env, WebGLRenderingContextBase::FRAMEBUFFER);
2792 if (frameBuffer != nullptr) {
2793 WebGLAttachmentInfo info = {};
2794 if (frameBuffer->GetWebGLAttachmentInfo(env, this, frameBuffer->GetAttachment(GL_COLOR_ATTACHMENT0), info)) {
2795 return info.format;
2796 }
2797 }
2798 auto webGlContextAttributes = webGLRenderingContext_->CreateWebGlContextAttributes();
2799 if (webGlContextAttributes != nullptr && webGlContextAttributes->alpha_) {
2800 return GL_RGBA;
2801 }
2802 return GL_RGB;
2803 }
2804
GetVertexAttribInfo(GLint index)2805 VertexAttribInfo* WebGLRenderingContextBaseImpl::GetVertexAttribInfo(GLint index)
2806 {
2807 if (index < 0 || index >= static_cast<GLint>(arrayVertexAttribs_.size())) {
2808 LOGE("Invalid index for VertexAttrib %{public}d, max %{public}zu",
2809 index, arrayVertexAttribs_.size());
2810 return nullptr;
2811 }
2812 return &arrayVertexAttribs_[index];
2813 }
2814
CheckReadBufferMode(GLenum mode)2815 bool WebGLRenderingContextBaseImpl::CheckReadBufferMode(GLenum mode)
2816 {
2817 switch (mode) {
2818 case WebGLRenderingContextBase::BACK:
2819 case WebGLRenderingContextBase::NONE:
2820 case WebGLRenderingContextBase::COLOR_ATTACHMENT0:
2821 return true;
2822 default: {
2823 if (mode < WebGLRenderingContextBase::COLOR_ATTACHMENT0) {
2824 return false;
2825 }
2826 if (mode > static_cast<GLenum>(WebGLRenderingContextBase::COLOR_ATTACHMENT0 + GetMaxColorAttachments())) {
2827 return false;
2828 }
2829 break;
2830 }
2831 }
2832 return true;
2833 }
2834
GetMaxColorAttachments()2835 GLint WebGLRenderingContextBaseImpl::GetMaxColorAttachments()
2836 {
2837 if (!maxColorAttachments_) {
2838 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments_);
2839 }
2840 LOGD("maxColorAttachments %{public}d", maxColorAttachments_);
2841 return maxColorAttachments_;
2842 }
2843
GetValidFrameBuffer(napi_env env,napi_value object)2844 WebGLFramebuffer* WebGLRenderingContextBaseImpl::GetValidFrameBuffer(napi_env env, napi_value object)
2845 {
2846 WebGLFramebuffer* webGlFramebuffer = WebGLObject::GetObjectInstance<WebGLFramebuffer>(env, object);
2847 if (webGlFramebuffer == nullptr) {
2848 return nullptr;
2849 }
2850 return GetObjectInstance<WebGLFramebuffer>(env, webGlFramebuffer->GetFramebuffer());
2851 }
2852
GetValidBuffer(napi_env env,napi_value object)2853 WebGLBuffer* WebGLRenderingContextBaseImpl::GetValidBuffer(napi_env env, napi_value object)
2854 {
2855 WebGLBuffer* buffer = WebGLObject::GetObjectInstance<WebGLBuffer>(env, object);
2856 if (buffer == nullptr) {
2857 return nullptr;
2858 }
2859 return GetObjectInstance<WebGLBuffer>(env, buffer->GetBufferId());
2860 }
2861
GetValidRenderBuffer(napi_env env,napi_value object)2862 WebGLRenderbuffer* WebGLRenderingContextBaseImpl::GetValidRenderBuffer(napi_env env, napi_value object)
2863 {
2864 WebGLRenderbuffer* renderBuffer = WebGLObject::GetObjectInstance<WebGLRenderbuffer>(env, object);
2865 if (renderBuffer == nullptr) {
2866 return nullptr;
2867 }
2868 return GetObjectInstance<WebGLRenderbuffer>(env, renderBuffer->GetRenderbuffer());
2869 }
2870 } // namespace Impl
2871 } // namespace Rosen
2872 } // namespace OHOS
2873