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