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
16 #include "webgl/webgl_arg.h"
17
18 #include "context/webgl2_rendering_context_base.h"
19 #include "context/webgl_rendering_context_base.h"
20 #include "image_source.h"
21 #include "util/util.h"
22
23 namespace OHOS {
24 namespace Rosen {
25 using namespace std;
26 using namespace OHOS::Media;
Dump()27 void WebGLImageOption::Dump()
28 {
29 LOGD("ImageOption format 0x%{public}x type 0x%{public}x size [%{public}d, %{public}d]",
30 format, type, width, height);
31 }
32
GetWebGLArg(napi_value data,WebGLArgValue & arg,const WebGLArgInfo & func)33 bool WebGLArg::GetWebGLArg(napi_value data, WebGLArgValue& arg, const WebGLArgInfo& func)
34 {
35 bool succ = true;
36 switch (func.argType) {
37 case ARG_BOOL: {
38 tie(succ, arg.glBool) = NVal(env_, data).ToBool();
39 break;
40 }
41 case ARG_UINT: {
42 tie(succ, arg.glUint) = NVal(env_, data).ToUint32();
43 break;
44 }
45 case ARG_INT: {
46 tie(succ, arg.glInt) = NVal(env_, data).ToInt32();
47 break;
48 }
49 case ARG_FLOAT: {
50 double v;
51 tie(succ, v) = NVal(env_, data).ToDouble();
52 arg.glFloat = v;
53 break;
54 }
55 case ARG_ENUM: {
56 tie(succ, arg.glEnum) = NVal(env_, data).ToGLenum();
57 break;
58 }
59 case ARG_INTPTR: {
60 int64_t v = 0;
61 tie(succ, v) = NVal(env_, data).ToInt64();
62 arg.glIntptr = static_cast<GLintptr>(v);
63 break;
64 }
65 case ARG_SIZE: {
66 int64_t v = 0;
67 tie(succ, v) = NVal(env_, data).ToInt64();
68 arg.glSizei = static_cast<GLsizei>(v);
69 break;
70 }
71 case ARG_SIZEPTR: {
72 int64_t v = 0;
73 tie(succ, v) = NVal(env_, data).ToInt64();
74 arg.glSizeptr = static_cast<GLsizei>(v);
75 break;
76 }
77 default:
78 break;
79 }
80 return succ;
81 }
82
ToGLintptr(napi_env env,napi_value dataObj)83 std::tuple<GLenum, GLintptr> WebGLArg::ToGLintptr(napi_env env, napi_value dataObj)
84 {
85 int64_t data = 0;
86 bool succ = false;
87 tie(succ, data) = NVal(env, dataObj).ToInt64();
88 if (!succ) {
89 return make_tuple(WebGLRenderingContextBase::INVALID_VALUE, 0);
90 }
91 if (data < 0) {
92 return make_tuple(WebGLRenderingContextBase::INVALID_VALUE, 0);
93 }
94 if (data > static_cast<int64_t>(std::numeric_limits<int>::max())) {
95 return make_tuple(WebGLRenderingContextBase::INVALID_OPERATION, 0);
96 }
97 return make_tuple(WebGLRenderingContextBase::NO_ERROR, static_cast<GLintptr>(data));
98 }
99
100 template<class T>
DumpDataBuffer(const char * format) const101 void WebGLCommBuffer::DumpDataBuffer(const char* format) const
102 {
103 LOGD("WebGL WebGLCommBuffer dataLen_ %{public}u ", dataLen_);
104 size_t count = dataLen_ / sizeof(T);
105 size_t i = 0;
106 size_t max = count > MAX_DUMP ? MAX_DUMP : count;
107 for (; i < max; i++) {
108 LOGD(format, i, *reinterpret_cast<T*>(data_ + i * sizeof(T)));
109 }
110
111 if (count <= MAX_DUMP) {
112 return;
113 }
114 if (count > MAX_DUMP) {
115 i = count - MAX_DUMP;
116 }
117 for (; i < count; i++) {
118 LOGD(format, i, *reinterpret_cast<T*>(data_ + i * sizeof(T)));
119 }
120 }
121
DumpBuffer(BufferDataType destDataType) const122 void WebGLCommBuffer::DumpBuffer(BufferDataType destDataType) const
123 {
124 switch (destDataType) {
125 case BUFFER_DATA_BOOLEAN:
126 DumpDataBuffer<bool>("WebGL WebGLCommBuffer bool elm %{public}u %{public}d");
127 break;
128 case BUFFER_DATA_INT_8:
129 case BUFFER_DATA_UINT_8:
130 case BUFFER_DATA_UINT_8_CLAMPED:
131 DumpDataBuffer<uint8_t>("WebGL WebGLCommBuffer int8 elm %{public}u %{public}d");
132 break;
133 case BUFFER_DATA_INT_16:
134 case BUFFER_DATA_UINT_16:
135 DumpDataBuffer<uint16_t>("WebGL WebGLCommBuffer int16 elm %{public}u %{public}u");
136 break;
137 case BUFFER_DATA_INT_32:
138 case BUFFER_DATA_UINT_32:
139 DumpDataBuffer<uint32_t>("WebGL WebGLCommBuffer int32 elm %{public}u %{public}u");
140 break;
141 case BUFFER_DATA_FLOAT_32:
142 DumpDataBuffer<float>("WebGL WebGLCommBuffer float elm %{public}u %{public}f");
143 break;
144 case BUFFER_DATA_FLOAT_64:
145 DumpDataBuffer<double>("WebGL WebGLCommBuffer float64 elm %{public}u %{public}lf");
146 break;
147 case BUFFER_DATA_BIGINT_64:
148 case BUFFER_DATA_BIGUINT_64:
149 DumpDataBuffer<uint64_t>("WebGL WebGLCommBuffer int64 elm %{public}u %{public}u");
150 break;
151 case BUFFER_DATA_GLENUM:
152 DumpDataBuffer<GLenum>("WebGL WebGLCommBuffer glenum elm %{public}u %{public}x");
153 break;
154 default:
155 break;
156 }
157 }
158
GetBufferDataSize() const159 size_t WebGLCommBuffer::GetBufferDataSize() const
160 {
161 switch (type_) {
162 case BUFFER_DATA_BOOLEAN:
163 return sizeof(bool);
164 case BUFFER_DATA_INT_8:
165 case BUFFER_DATA_UINT_8:
166 case BUFFER_DATA_UINT_8_CLAMPED:
167 return sizeof(uint8_t);
168 case BUFFER_DATA_INT_16:
169 case BUFFER_DATA_UINT_16:
170 return sizeof(uint16_t);
171 case BUFFER_DATA_INT_32:
172 case BUFFER_DATA_FLOAT_32:
173 case BUFFER_DATA_UINT_32:
174 return sizeof(uint32_t);
175 case BUFFER_DATA_FLOAT_64:
176 return sizeof(double);
177 case BUFFER_DATA_BIGINT_64:
178 case BUFFER_DATA_BIGUINT_64:
179 return sizeof(uint64_t);
180 case BUFFER_DATA_GLENUM:
181 return sizeof(GLenum);
182 default:
183 break;
184 }
185 return sizeof(uint32_t);
186 }
187
188 template<class srcT, class dstT>
GetArrayElement(napi_value data,dstT defaultValue,napi_status (* getElementValue)(napi_env env_,napi_value element,srcT * value))189 napi_status WebGLReadBufferArg::GetArrayElement(
190 napi_value data, dstT defaultValue, napi_status (*getElementValue)(napi_env env_, napi_value element, srcT* value))
191 {
192 uint32_t length = 0;
193 napi_status status = napi_get_array_length(env_, data, &length);
194 if (status != napi_ok) {
195 return status;
196 }
197 LOGD("WebGL GetArrayData array len %{public}u ", length);
198 if (length == 0) {
199 return napi_ok;
200 }
201 buffer_.resize(length * sizeof(dstT));
202 data_ = buffer_.data();
203 uint8_t* buffer = buffer_.data();
204 for (uint32_t i = 0; i < length; i++) {
205 napi_value element;
206 status = napi_get_element(env_, data, i, &element);
207 if (status != napi_ok) {
208 return status;
209 }
210 srcT elm = 0;
211 if (NVal(env_, element).IsUndefined()) {
212 *reinterpret_cast<dstT*>(buffer) = defaultValue;
213 buffer += sizeof(dstT);
214 continue;
215 }
216
217 if (NVal(env_, element).IsNull()) {
218 *reinterpret_cast<dstT*>(buffer) = elm;
219 buffer += sizeof(dstT);
220 continue;
221 }
222 if ((status = getElementValue(env_, element, &elm)) != napi_ok) {
223 return status;
224 }
225 *reinterpret_cast<dstT*>(buffer) = elm;
226 buffer += sizeof(dstT);
227 }
228 dataLen_ = length * sizeof(dstT);
229 return napi_ok;
230 }
231
GetArrayData(napi_value data,BufferDataType destDataType)232 napi_status WebGLReadBufferArg::GetArrayData(napi_value data, BufferDataType destDataType)
233 {
234 napi_status status = napi_invalid_arg;
235 switch (destDataType) {
236 case BufferDataType::BUFFER_DATA_BOOLEAN:
237 status = GetArrayElement<bool, bool>(data, false, napi_get_value_bool);
238 break;
239 case BufferDataType::BUFFER_DATA_INT_8:
240 case BufferDataType::BUFFER_DATA_UINT_8:
241 case BufferDataType::BUFFER_DATA_UINT_8_CLAMPED:
242 status = GetArrayElement<uint32_t, uint8_t>(data, 0, napi_get_value_uint32);
243 break;
244 case BufferDataType::BUFFER_DATA_INT_16:
245 case BufferDataType::BUFFER_DATA_UINT_16:
246 status = GetArrayElement<uint32_t, uint16_t>(data, 0, napi_get_value_uint32);
247 break;
248 case BufferDataType::BUFFER_DATA_INT_32:
249 case BufferDataType::BUFFER_DATA_UINT_32:
250 status = GetArrayElement<uint32_t, uint32_t>(data, 0, napi_get_value_uint32);
251 break;
252 case BufferDataType::BUFFER_DATA_FLOAT_32: {
253 float def = 0;
254 (void)memset_s(&def, sizeof(def), 0xff, sizeof(def));
255 status = GetArrayElement<double, float>(data, def, napi_get_value_double);
256 break;
257 }
258 case BufferDataType::BUFFER_DATA_FLOAT_64:
259 status = GetArrayElement<double, double>(data, 0, napi_get_value_double);
260 break;
261 case BufferDataType::BUFFER_DATA_BIGINT_64:
262 case BufferDataType::BUFFER_DATA_BIGUINT_64:
263 status = GetArrayElement<int64_t, uint64_t>(data, 0, napi_get_value_int64);
264 break;
265 case BufferDataType::BUFFER_DATA_GLENUM:
266 status = GetArrayElement<int64_t, GLenum>(data, 0, napi_get_value_int64);
267 break;
268 default:
269 break;
270 }
271 if (status != napi_ok) {
272 return status;
273 }
274 type_ = destDataType;
275 data_ = buffer_.data();
276 return napi_ok;
277 }
278
279 // destDataType only for BUFFER_ARRAY
GenBufferData(napi_value data,BufferDataType destDataType)280 napi_status WebGLReadBufferArg::GenBufferData(napi_value data, BufferDataType destDataType)
281 {
282 if (data == nullptr) {
283 return napi_invalid_arg;
284 }
285 bool dataView, isArrayBuffer, typedArray, array = false;
286 napi_status status = napi_invalid_arg;
287 napi_is_dataview(env_, data, &dataView);
288 napi_is_arraybuffer(env_, data, &isArrayBuffer);
289 napi_is_typedarray(env_, data, &typedArray);
290 napi_is_array(env_, data, &array);
291 napi_value arrayBuffer = nullptr;
292 size_t byteOffset = 0;
293 if (dataView) {
294 LOGD("WebGL WebGLReadBufferArg DataView");
295 bufferType_ = BUFFER_DATA_VIEW;
296 type_ = BUFFER_DATA_UINT_8;
297 status = napi_get_dataview_info(
298 env_, data, &dataLen_, reinterpret_cast<void**>(&data_), &arrayBuffer, &byteOffset);
299 } else if (isArrayBuffer) {
300 LOGD("WebGL WebGLReadBufferArg ArrayBuffer");
301 bufferType_ = BUFFER_ARRAY_BUFFER;
302 type_ = BUFFER_DATA_UINT_8;
303 status = napi_get_arraybuffer_info(env_, data, reinterpret_cast<void**>(&data_), &dataLen_);
304 } else if (typedArray) {
305 LOGD("WebGL WebGLReadBufferArg TypedArray");
306 bufferType_ = BUFFER_TYPED_ARRAY;
307 napi_typedarray_type arrayType;
308 status = napi_get_typedarray_info(
309 env_, data, &arrayType, &dataLen_, reinterpret_cast<void**>(&data_), &arrayBuffer, &byteOffset);
310 type_ = (BufferDataType)arrayType;
311 } else if (array) {
312 LOGD("WebGL WebGLReadBufferArg array ");
313 bufferType_ = BUFFER_ARRAY;
314 status = GetArrayData(data, destDataType);
315 }
316 LOGD("WebGL GenBufferData type %{public}u length %{public}zu bufferType %{public}u", type_, dataLen_, bufferType_);
317 return status;
318 }
319
320 template<class dstT>
GenExternalArray()321 napi_value WebGLWriteBufferArg::GenExternalArray()
322 {
323 LOGD("GenExternalArray dataLen_[%{public}u %{public}u]", dataLen_, type_);
324 napi_value outputBuffer = nullptr;
325 size_t count = dataLen_ / sizeof(dstT);
326 napi_value outputArray = nullptr;
327 napi_status status = napi_ok;
328 if (data_ == nullptr) {
329 status = napi_create_arraybuffer(env_, dataLen_, reinterpret_cast<void **>(&data_), &outputBuffer);
330 } else {
331 status = napi_create_external_arraybuffer(
332 env_, data_, dataLen_,
333 [](napi_env env_, void* finalize_data, void* finalize_hint) {
334 LOGD("GenExternalArray free %{public}p", finalize_data);
335 delete[] reinterpret_cast<uint8_t*>(finalize_data);
336 },
337 nullptr, &outputBuffer);
338 }
339 if (status == napi_ok) {
340 status = napi_create_typedarray(env_, (napi_typedarray_type)type_, count, outputBuffer, 0, &outputArray);
341 }
342 if (status != napi_ok) {
343 LOGD("GenExternalArray error %{public}d", status);
344 }
345 data_ = nullptr;
346 return outputArray;
347 }
348
ToExternalArray(BufferDataType dstDataType)349 napi_value WebGLWriteBufferArg::ToExternalArray(BufferDataType dstDataType)
350 {
351 type_ = dstDataType;
352 switch (dstDataType) {
353 case BUFFER_DATA_BOOLEAN:
354 return GenExternalArray<bool>();
355 case BUFFER_DATA_INT_8:
356 case BUFFER_DATA_UINT_8:
357 case BUFFER_DATA_UINT_8_CLAMPED:
358 return GenExternalArray<uint8_t>();
359 case BUFFER_DATA_INT_16:
360 case BUFFER_DATA_UINT_16:
361 return GenExternalArray<uint16_t>();
362 case BUFFER_DATA_INT_32:
363 case BUFFER_DATA_UINT_32:
364 return GenExternalArray<uint32_t>();
365 case BUFFER_DATA_FLOAT_32:
366 return GenExternalArray<float>();
367 case BUFFER_DATA_FLOAT_64:
368 return GenExternalArray<double>();
369 case BUFFER_DATA_BIGINT_64:
370 case BUFFER_DATA_BIGUINT_64:
371 return GenExternalArray<uint64_t>();
372 default:
373 break;
374 }
375 return NVal::CreateNull(env_).val_;
376 }
377
378 template<class srcT, class dstT>
GenNormalArray(napi_status (* getNApiValue)(napi_env env_,dstT value,napi_value * element))379 napi_value WebGLWriteBufferArg::GenNormalArray(
380 napi_status (*getNApiValue)(napi_env env_, dstT value, napi_value* element))
381 {
382 napi_value res = nullptr;
383 size_t count = dataLen_ / sizeof(srcT);
384 napi_create_array_with_length(env_, count, &res);
385 for (size_t i = 0; i < count; i++) {
386 srcT data = *reinterpret_cast<srcT*>(data_ + i * sizeof(srcT));
387 napi_value element;
388 getNApiValue(env_, static_cast<dstT>(data), &element);
389 napi_set_element(env_, res, i, element);
390 }
391 return res;
392 }
393
ToNormalArray(BufferDataType srcDataType,BufferDataType dstDataType)394 napi_value WebGLWriteBufferArg::ToNormalArray(BufferDataType srcDataType, BufferDataType dstDataType)
395 {
396 type_ = dstDataType;
397 if (dstDataType == BUFFER_DATA_BOOLEAN) {
398 if (srcDataType == BUFFER_DATA_BOOLEAN) {
399 return GenNormalArray<bool, bool>(napi_get_boolean);
400 } else if (srcDataType == BUFFER_DATA_INT_32 || srcDataType == BUFFER_DATA_UINT_32) {
401 return GenNormalArray<uint32_t, bool>(napi_get_boolean);
402 }
403 return NVal::CreateNull(env_).val_;
404 }
405
406 if (dstDataType == BUFFER_DATA_INT_32 || dstDataType == BUFFER_DATA_UINT_32) {
407 if (srcDataType == BUFFER_DATA_INT_32 || srcDataType == BUFFER_DATA_UINT_32) {
408 return GenNormalArray<uint32_t, uint32_t>(napi_create_uint32);
409 }
410 return NVal::CreateNull(env_).val_;
411 }
412
413 if (dstDataType == BUFFER_DATA_BIGINT_64 || dstDataType == BUFFER_DATA_BIGUINT_64) {
414 if (srcDataType == BUFFER_DATA_INT_32 || srcDataType == BUFFER_DATA_UINT_32) {
415 return GenNormalArray<uint32_t, int64_t>(napi_create_int64);
416 }
417 return NVal::CreateNull(env_).val_;
418 }
419
420 if (srcDataType == BUFFER_DATA_FLOAT_32) {
421 if (srcDataType == BUFFER_DATA_FLOAT_32) {
422 return GenNormalArray<float, double>(napi_create_double);
423 }
424 }
425 return NVal::CreateNull(env_).val_;
426 }
427
428 template<class T>
GetObjectIntField(napi_value resultObject,const std::string & name)429 tuple<bool, T> WebGLImageSource::GetObjectIntField(napi_value resultObject, const std::string& name)
430 {
431 napi_value result = nullptr;
432 napi_status status = napi_get_named_property(env_, resultObject, name.c_str(), &result);
433 if (status != napi_ok) {
434 return make_tuple(false, 0);
435 }
436 int64_t res = 0;
437 status = napi_get_value_int64(env_, result, &res);
438 return make_tuple(status == napi_ok, static_cast<T>(res));
439 }
440
GetWebGLFormatMap(GLenum type,GLenum format)441 const WebGLFormatMap *WebGLImageSource::GetWebGLFormatMap(GLenum type, GLenum format)
442 {
443 static const WebGLFormatMap formatTypeMaps[] = {
444 {GL_RGBA, GL_UNSIGNED_BYTE, 4, 4, BUFFER_DATA_UINT_8, DECODE_RGBA_UBYTE},
445 {GL_RGB, GL_UNSIGNED_BYTE, 3, 3, BUFFER_DATA_UINT_8, DECODE_RGB_UBYTE},
446 {GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 4, 2, BUFFER_DATA_UINT_16, DECODE_RGBA_USHORT_4444},
447 {GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 4, 2, BUFFER_DATA_UINT_16, DECODE_RGBA_USHORT_5551},
448 {GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 3, 2, BUFFER_DATA_UINT_16, DECODE_RGB_USHORT_565},
449 {GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 2, 2, BUFFER_DATA_UINT_8, DECODE_LUMINANCE_ALPHA_UBYTE},
450 {GL_LUMINANCE, GL_UNSIGNED_BYTE, 1, 1, BUFFER_DATA_UINT_8, DECODE_LUMINANCE_UBYTE},
451 {GL_ALPHA, GL_UNSIGNED_BYTE, 1, 1, BUFFER_DATA_UINT_8, DECODE_ALPHA_UBYTE},
452 };
453 for (size_t i = 0; i < sizeof(formatTypeMaps) / sizeof(formatTypeMaps[0]); ++i) {
454 if (type == formatTypeMaps[i].type && format == formatTypeMaps[i].format) {
455 return &formatTypeMaps[i];
456 }
457 }
458 return nullptr;
459 }
460
~WebGLImageSource()461 WebGLImageSource::~WebGLImageSource()
462 {
463 imageData_.clear();
464 }
465
HandleImageSourceData(napi_value resultData,napi_valuetype valueType)466 bool WebGLImageSource::HandleImageSourceData(napi_value resultData, napi_valuetype valueType)
467 {
468 uint32_t errorCode = 0;
469 bool succ = false;
470 SourceOptions opts;
471 std::unique_ptr<OHOS::Media::ImageSource> imageSource = nullptr;
472 if (valueType == napi_string) { // File Path
473 size_t ignore = 0;
474 std::unique_ptr<char[]> source = nullptr;
475 tie(succ, source, ignore) = NVal(env_, resultData).ToUTF8String();
476 if (!succ) {
477 return false;
478 }
479 LOGD("WebGl ImageSource src: %{public}s", source.get());
480 imageSource = ImageSource::CreateImageSource(source.get(), opts, errorCode);
481 } else if (valueType == napi_number) { // Fd
482 int32_t fd = 0;
483 napi_get_value_int32(env_, resultData, &fd);
484 LOGD("WebGl ImageSource fdIndex is [%{public}d]", fd);
485 imageSource = ImageSource::CreateImageSource(fd, opts, errorCode);
486 } else {
487 LOGE("WebGl ImageSource not support type %{public}u", valueType);
488 return false;
489 }
490 if (imageSource == nullptr) {
491 LOGE("WebGl ImageSource fail to get errorCode %{public}u", errorCode);
492 return false;
493 }
494
495 ImageInfo imageInfo;
496 errorCode = imageSource->GetImageInfo(0, imageInfo);
497 if (errorCode == 0) {
498 errorCode = imageSource->GetImageInfo(imageInfo);
499 LOGD("WebGl ImageSource [%{public}u %{public}u] pixelFormat %{public}u colorSpace %{public}u"
500 " alphaType %{public}u", imageInfo.size.width, imageInfo.size.height, imageInfo.pixelFormat,
501 imageInfo.colorSpace, imageInfo.alphaType);
502 imageOption_.width = imageInfo.size.width;
503 imageOption_.height = imageInfo.size.height;
504 } else {
505 return false;
506 }
507 DecodeOptions decodeOpts;
508 pixelMap_ = imageSource->CreatePixelMap(decodeOpts, errorCode);
509 if (pixelMap_ == nullptr) {
510 LOGE("WebGl ImageSource fail to create pixel map");
511 return false;
512 }
513 return true;
514 }
515
DecodeData(const WebGLFormatMap * formatMap,uint8_t * array)516 void WebGLImageSource::DecodeData(const WebGLFormatMap* formatMap, uint8_t* array)
517 {
518 imageData_.clear();
519 for (int32_t i = 0; i < imageOption_.height; ++i) {
520 for (int32_t j = 0; j < imageOption_.width; ++j) {
521 uint8_t *data = array + formatMap->bytesPrePixel * (j + imageOption_.width * i);
522 // 0,1,2,3 -- red,green,blue,alpha
523 imageData_.emplace_back(FromARGB(static_cast<uint8_t>(data[3]),
524 static_cast<uint8_t>(data[0]), static_cast<uint8_t>(data[1]), static_cast<uint8_t>(data[2])).value);
525 }
526 }
527 }
528
DecodeDataForRGB_UBYTE(const WebGLFormatMap * formatMap,uint8_t * array)529 void WebGLImageSource::DecodeDataForRGB_UBYTE(const WebGLFormatMap* formatMap, uint8_t* array)
530 {
531 imageData_.clear();
532 for (int32_t i = 0; i < imageOption_.height; ++i) {
533 for (int32_t j = 0; j < imageOption_.width; ++j) {
534 uint8_t *data = array + formatMap->bytesPrePixel * (j + imageOption_.width * i);
535 // 0,1,2 -- red,green,blue
536 imageData_.emplace_back(FromRGB(
537 static_cast<uint8_t>(data[0]), static_cast<uint8_t>(data[1]), static_cast<uint8_t>(data[2])).value);
538 }
539 }
540 }
541
DecodeDataForRGBA_USHORT_4444(const WebGLFormatMap * formatMap,uint8_t * array)542 void WebGLImageSource::DecodeDataForRGBA_USHORT_4444(const WebGLFormatMap* formatMap, uint8_t* array)
543 {
544 imageData_.clear();
545 for (int32_t i = 0; i < imageOption_.height; ++i) {
546 for (int32_t j = 0; j < imageOption_.width; ++j) {
547 uint8_t *data = array + formatMap->bytesPrePixel * (j + imageOption_.width * i);
548 ColorParam_4_4_4_4 param;
549 param.value = *reinterpret_cast<uint16_t *>(data);
550 imageData_.emplace_back(FromARGB(
551 param.rgba.alpha, param.rgba.red, param.rgba.green, param.rgba.blue).value);
552 }
553 }
554 }
555
DecodeDataForRGBA_USHORT_5551(const WebGLFormatMap * formatMap,uint8_t * array)556 void WebGLImageSource::DecodeDataForRGBA_USHORT_5551(const WebGLFormatMap* formatMap, uint8_t* array)
557 {
558 imageData_.clear();
559 for (int32_t i = 0; i < imageOption_.height; ++i) {
560 for (int32_t j = 0; j < imageOption_.width; ++j) {
561 uint8_t *data = array + formatMap->bytesPrePixel * (j + imageOption_.width * i);
562 ColorParam_5_5_5_1 param;
563 param.value = *reinterpret_cast<uint16_t *>(data);
564 imageData_.emplace_back(FromARGB(
565 param.rgba.alpha, param.rgba.red, param.rgba.green, param.rgba.blue).value);
566 }
567 }
568 }
569
DecodeDataForRGB_USHORT_565(const WebGLFormatMap * formatMap,uint8_t * array)570 void WebGLImageSource::DecodeDataForRGB_USHORT_565(const WebGLFormatMap* formatMap, uint8_t* array)
571 {
572 imageData_.clear();
573 for (int32_t i = 0; i < imageOption_.height; ++i) {
574 for (int32_t j = 0; j < imageOption_.width; ++j) {
575 uint8_t *data = array + formatMap->bytesPrePixel * (j + imageOption_.width * i);
576 ColorParam_5_6_5 param;
577 param.value = *reinterpret_cast<uint16_t *>(data);
578 imageData_.emplace_back(FromRGB(param.rgb.red, param.rgb.green, param.rgb.blue).value);
579 }
580 }
581 }
582
DecodeImageData(const WebGLFormatMap * formatMap,const WebGLReadBufferArg * bufferDataArg,GLuint srcOffset)583 bool WebGLImageSource::DecodeImageData(
584 const WebGLFormatMap* formatMap, const WebGLReadBufferArg* bufferDataArg, GLuint srcOffset)
585 {
586 size_t maxSize = bufferDataArg->GetBufferLength() - srcOffset * formatMap->bytesPrePixel;
587 LOGD("GenImageSource element count %{public}zu %{public}u", maxSize, formatMap->bytesPrePixel);
588 if (maxSize < static_cast<size_t>(imageOption_.height * imageOption_.width * formatMap->bytesPrePixel)) {
589 LOGE("Invalid data element");
590 return false;
591 }
592
593 uint8_t *start = bufferDataArg->GetBuffer() + srcOffset;
594 switch (formatMap->decodeFunc) {
595 case DECODE_RGBA_UBYTE:
596 DecodeData(formatMap, start);
597 break;
598 case DECODE_RGB_UBYTE:
599 DecodeDataForRGB_UBYTE(formatMap, start);
600 break;
601 case DECODE_RGBA_USHORT_4444:
602 DecodeDataForRGBA_USHORT_4444(formatMap, start);
603 break;
604 case DECODE_RGBA_USHORT_5551:
605 DecodeDataForRGBA_USHORT_5551(formatMap, start);
606 break;
607 case DECODE_RGB_USHORT_565:
608 DecodeDataForRGB_USHORT_565(formatMap, start);
609 break;
610 default:
611 LOGE("Not support type %{public}u format %{public}u", imageOption_.type, imageOption_.format);
612 return false;
613 }
614
615 LOGD("GenImageSource imageData_ %{public}zu ", imageData_.size());
616 if (imageData_.size() != static_cast<size_t>(imageOption_.height * imageOption_.width)) {
617 return false;
618 }
619 return true;
620 }
621
GenImageSource(const WebGLImageOption & opt,napi_value pixels,GLuint srcOffset)622 GLenum WebGLImageSource::GenImageSource(const WebGLImageOption& opt, napi_value pixels, GLuint srcOffset)
623 {
624 imageOption_.Assign(opt);
625 imageOption_.Dump();
626 if (readBuffer_ != nullptr) {
627 readBuffer_.reset();
628 }
629 readBuffer_ = std::make_unique<WebGLReadBufferArg>(env_);
630 if (readBuffer_ == nullptr) {
631 return GL_INVALID_OPERATION;
632 }
633 const WebGLFormatMap *formatMap = GetWebGLFormatMap(imageOption_.type, imageOption_.format);
634 if (formatMap == nullptr) {
635 return false;
636 }
637 napi_status status = readBuffer_->GenBufferData(pixels, formatMap->dataType);
638 if (status != napi_ok) {
639 return GL_INVALID_VALUE;
640 }
641 if (readBuffer_->GetBufferDataType() != formatMap->dataType) {
642 return GL_INVALID_OPERATION;
643 }
644 if (!(unpackFlipY_ || unpackPremultiplyAlpha_)) {
645 srcOffset_ = srcOffset;
646 return GL_NO_ERROR;
647 }
648 bool succ = false;
649 if (readBuffer_->GetBufferDataType() == BUFFER_DATA_UINT_8 ||
650 readBuffer_->GetBufferDataType() == BUFFER_DATA_UINT_16) {
651 succ = DecodeImageData(formatMap, readBuffer_.get(), srcOffset);
652 } else {
653 return GL_INVALID_OPERATION;
654 }
655 if (!succ) {
656 return GL_INVALID_OPERATION;
657 }
658
659 Media::InitializationOptions opts;
660 opts.pixelFormat = Media::PixelFormat::RGBA_8888;
661 opts.size.width = imageOption_.width;
662 opts.size.height = imageOption_.height;
663 opts.editable = true;
664 pixelMap_ = Media::PixelMap::Create(imageData_.data(), imageData_.size(), opts);
665 return pixelMap_ == nullptr ? GL_INVALID_OPERATION : GL_NO_ERROR;
666 }
667
GenImageSource(const WebGLImageOption & opt,napi_value sourceImage)668 GLenum WebGLImageSource::GenImageSource(const WebGLImageOption& opt, napi_value sourceImage)
669 {
670 imageOption_.Assign(opt);
671 bool succ = false;
672 napi_value resultObject = nullptr;
673 napi_status status = napi_coerce_to_object(env_, sourceImage, &resultObject);
674 if (status != napi_ok) {
675 return GL_INVALID_VALUE;
676 }
677
678 // image maybe no width
679 tie(succ, imageOption_.width) = GetObjectIntField<GLsizei>(resultObject, "width");
680 if (!succ) {
681 return GL_INVALID_VALUE;
682 }
683 tie(succ, imageOption_.height) = GetObjectIntField<GLsizei>(resultObject, "height");
684 if (!succ) {
685 return GL_INVALID_VALUE;
686 }
687 LOGD("WebGl GenImageSource size [%{public}d %{public}d]", imageOption_.width, imageOption_.height);
688
689 napi_value resultData = nullptr;
690 status = napi_get_named_property(env_, resultObject, "data", &resultData);
691 if (status != napi_ok || NVal(env_, resultData).IsNull()) {
692 status = napi_get_named_property(env_, resultObject, "src", &resultData);
693 }
694 if (status != napi_ok || NVal(env_, resultData).IsNull()) {
695 LOGE("WebGl GenImageSource status %{public}u", status);
696 return GL_INVALID_VALUE;
697 }
698 napi_valuetype valueType;
699 napi_typeof(env_, resultData, &valueType);
700 if (valueType == napi_object) {
701 return GenImageSource(imageOption_, resultData, 0);
702 }
703 return HandleImageSourceData(resultData, valueType) ? GL_NO_ERROR : GL_INVALID_VALUE;
704 }
705
GetWebGLReadBuffer() const706 WebGLReadBufferArg *WebGLImageSource::GetWebGLReadBuffer() const
707 {
708 return readBuffer_ == nullptr ? nullptr : readBuffer_.get();
709 }
710
GetImageSourceData() const711 GLvoid* WebGLImageSource::GetImageSourceData() const
712 {
713 if (pixelMap_ == nullptr) {
714 return readBuffer_ == nullptr ? nullptr : reinterpret_cast<GLvoid*>(readBuffer_->GetBuffer() + srcOffset_);
715 }
716
717 LOGD("WebGl ImageSource [%{public}u %{public}u] byteCount %{public}u pixelBytes %{public}u rowBytes %{public}u "
718 " flipY %{public}u premultiplyAlpha %{public}u", pixelMap_->GetWidth(), pixelMap_->GetHeight(),
719 pixelMap_->GetByteCount(), pixelMap_->GetPixelBytes(), pixelMap_->GetRowBytes(),
720 unpackFlipY_, unpackPremultiplyAlpha_);
721 if (unpackFlipY_ || unpackPremultiplyAlpha_) {
722 pixelMap_->flip(false, unpackFlipY_);
723 }
724 return reinterpret_cast<GLvoid*>(const_cast<uint8_t*>(pixelMap_->GetPixels()));
725 }
726
GetWebGLDataSize(GLenum type)727 uint32_t WebGLArg::GetWebGLDataSize(GLenum type)
728 {
729 switch (type) {
730 case GL_BYTE:
731 return sizeof(GLbyte);
732 case GL_UNSIGNED_BYTE:
733 return sizeof(GLubyte);
734 case GL_SHORT:
735 return sizeof(GLshort);
736 case GL_UNSIGNED_SHORT:
737 return sizeof(GLushort);
738 case GL_INT:
739 return sizeof(GLint);
740 case GL_UNSIGNED_INT:
741 return sizeof(GLuint);
742 case GL_FLOAT:
743 return sizeof(GLfloat);
744 default:
745 break;
746 }
747 return sizeof(GLuint);
748 }
749
GetStringList(napi_env env,napi_value array,std::vector<char * > & list)750 bool WebGLArg::GetStringList(napi_env env, napi_value array, std::vector<char*>& list)
751 {
752 bool succ = false;
753 uint32_t count = 0;
754 napi_status status = napi_get_array_length(env, array, &count);
755 if (status != napi_ok) {
756 return false;
757 }
758 uint32_t i;
759 for (i = 0; i < count; i++) {
760 napi_value element;
761 status = napi_get_element(env, array, i, &element);
762 if (status != napi_ok) {
763 return false;
764 }
765 napi_value result;
766 status = napi_coerce_to_string(env, element, &result);
767 if (status != napi_ok) {
768 return false;
769 }
770 unique_ptr<char[]> name;
771 tie(succ, name, ignore) = NVal(env, result).ToUTF8String();
772 if (!succ) {
773 return false;
774 }
775 LOGD("WebGL2 GetStringList = %{public}s", name.get());
776 list.emplace_back(name.get());
777 name.release();
778 }
779 return true;
780 }
781
FreeStringList(std::vector<char * > & list)782 void WebGLArg::FreeStringList(std::vector<char*>& list)
783 {
784 for (size_t i = 0; i < list.size(); i++) {
785 if (list[i] != nullptr) {
786 delete[] list[i];
787 }
788 }
789 list.clear();
790 }
791
GetUint32Parameter(napi_env env,GLenum pname)792 napi_value WebGLArg::GetUint32Parameter(napi_env env, GLenum pname)
793 {
794 GLint value = 0;
795 glGetIntegerv(pname, &value);
796 napi_value res = nullptr;
797 napi_create_uint32(env, value, &res);
798 return res;
799 }
800
GetBoolParameter(napi_env env,GLenum pname)801 napi_value WebGLArg::GetBoolParameter(napi_env env, GLenum pname)
802 {
803 GLboolean value = 0;
804 glGetBooleanv(pname, &value);
805 napi_value res = nullptr;
806 napi_get_boolean(env, value, &res);
807 return res;
808 }
809
GetInt32Parameter(napi_env env,GLenum pname)810 napi_value WebGLArg::GetInt32Parameter(napi_env env, GLenum pname)
811 {
812 GLint value = 0;
813 glGetIntegerv(pname, &value);
814 napi_value res = nullptr;
815 napi_create_int32(env, value, &res);
816 return res;
817 }
818
GetInt64Parameter(napi_env env,GLenum pname)819 napi_value WebGLArg::GetInt64Parameter(napi_env env, GLenum pname)
820 {
821 GLint64 value = 0;
822 glGetInteger64v(pname, &value);
823 napi_value res = nullptr;
824 napi_create_int64(env, value, &res);
825 return res;
826 }
827
GetFloatParameter(napi_env env,GLenum pname)828 napi_value WebGLArg::GetFloatParameter(napi_env env, GLenum pname)
829 {
830 float value = 0;
831 glGetFloatv(pname, &value);
832 napi_value res = nullptr;
833 napi_create_double(env, static_cast<double>(value), &res);
834 return res;
835 }
836
Dump(const std::string & info) const837 void TexImageArg::Dump(const std::string& info) const
838 {
839 LOGD("%{public}s target %{public}u %{public}d internalFormat %{public}u format %{public}u %{public}u",
840 info.c_str(), target, level, internalFormat, format, type);
841 LOGD("width %{public}d height %{public}d border %{public}d depth %{public}d", width, height, border, depth);
842 }
843
Dump(const std::string & info) const844 void TexStorageArg::Dump(const std::string& info) const
845 {
846 LOGD("%{public}s target %{public}u %{public}d internalFormat %{public}u ",
847 info.c_str(), target, levels, internalFormat);
848 LOGD("width %{public}d height %{public}d depth %{public}d", width, height, depth);
849 }
850
Dump(const std::string & info) const851 void TexSubImage2DArg::Dump(const std::string& info) const
852 {
853 TexImageArg::Dump(info);
854 LOGD("xOffset %{public}u yOffset %{public}u", xOffset, yOffset);
855 }
856
Dump(const std::string & info) const857 void TexSubImage3DArg::Dump(const std::string& info) const
858 {
859 TexImageArg::Dump(info);
860 LOGD("xOffset %{public}u yOffset %{public}u zOffset %{public}u", xOffset, yOffset, zOffset);
861 }
862
Dump(const std::string & info) const863 void PixelsArg::Dump(const std::string& info) const
864 {
865 LOGD("%{public}s position [%{public}d %{public}d %{public}d %{public}d] format [%{public}u %{public}u]",
866 info.c_str(), x, y, width, height, format, type);
867 }
868
Dump(const std::string & info) const869 void VertexAttribArg::Dump(const std::string &info) const
870 {
871 LOGD("%{public}s vertexAttrib index %{public}u %{public}d type %{public}u %{public}d "
872 "stride [%{public}u %{public}u]",
873 info.c_str(), index, size, type, normalized, stride, offset);
874 }
875
GetUniformExtInfo(napi_env env,const NFuncArg & funcArg,int32_t start)876 bool UniformExtInfo::GetUniformExtInfo(napi_env env, const NFuncArg& funcArg, int32_t start)
877 {
878 bool succ = false;
879 if (start + 1 > static_cast<int32_t>(funcArg.GetMaxArgc())) {
880 LOGE("funcArg.GetMaxArgc : %{public}zu", funcArg.GetMaxArgc());
881 return false;
882 }
883 if (funcArg[start] != nullptr) {
884 tie(succ, srcOffset) = NVal(env, funcArg[start]).ToUint32();
885 if (!succ) {
886 return false;
887 }
888 LOGD("WebGL UniformMatrixInfo srcOffset = %{public}u", srcOffset);
889 }
890 if (funcArg[start + 1] != nullptr) {
891 tie(succ, srcLength) = NVal(env, funcArg[start + 1]).ToUint32();
892 if (!succ) {
893 return false;
894 }
895 LOGD("WebGL UniformMatrixInfo srcLength = %{public}u", srcLength);
896 }
897 return true;
898 }
899
GetBufferExt(napi_env env,napi_value offsetArg,napi_value lenArg)900 bool BufferExt::GetBufferExt(napi_env env, napi_value offsetArg, napi_value lenArg)
901 {
902 int64_t srcByteOffset = 0;
903 bool succ = false;
904 if (!NVal(env, offsetArg).IsNull()) {
905 tie(succ, srcByteOffset) = NVal(env, offsetArg).ToInt64();
906 if (!succ || srcByteOffset < 0) {
907 return false;
908 }
909 offset = static_cast<GLuint>(srcByteOffset);
910 }
911
912 if (!NVal(env, lenArg).IsNull()) {
913 tie(succ, srcByteOffset) = NVal(env, lenArg).ToInt64();
914 if (!succ || srcByteOffset < 0) {
915 return false;
916 }
917 length = static_cast<GLuint>(srcByteOffset);
918 }
919 return true;
920 }
921
CheckString(const std::string & str)922 bool WebGLArg::CheckString(const std::string& str)
923 {
924 for (size_t i = 0; i < str.length(); ++i) {
925 unsigned char c = str[i];
926 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid
927 if (c >= 9 && c <= 13) { // Match character: 9 TAB, 10 LF, 11 VT, 12 FF, 13 CR
928 continue;
929 }
930 // Printing characters are valid except " $ ` @ \ ' DEL.
931 if (isprint(c) && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') {
932 continue;
933 }
934 return false;
935 }
936 return true;
937 }
938
CheckReservedPrefix(const std::string & name)939 bool WebGLArg::CheckReservedPrefix(const std::string& name)
940 {
941 // 6: 'webgl_' length, 7: '_webgl_' length
942 if (strncmp("webgl_", name.c_str(), 6) == 0 || strncmp("_webgl_", name.c_str(), 7) == 0) {
943 return true;
944 }
945 return false;
946 }
947 } // namespace Rosen
948 } // namespace OHOS
949