• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
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