1 /*
2  * Copyright (c) 2021-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 "context/webgl_rendering_context_basic_base.h"
17 
18 #include "context/webgl2_rendering_context.h"
19 #include "context/webgl_rendering_context.h"
20 #include "napi/n_class.h"
21 #include "util/egl_manager.h"
22 #include "util/log.h"
23 #include "util/object_manager.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 using namespace std;
30 namespace OHOS {
31 namespace Rosen {
32 
~WebGLRenderingContextBasicBase()33 WebGLRenderingContextBasicBase::~WebGLRenderingContextBasicBase()
34 {
35     if (eglSurface_ != nullptr) {
36         eglDestroySurface(EglManager::GetInstance().GetEGLDisplay(), eglSurface_);
37         eglSurface_ = nullptr;
38     }
39 }
40 
SetEglWindow(void * window)41 void WebGLRenderingContextBasicBase::SetEglWindow(void* window)
42 {
43     LOGD("WebGLRenderingContextBasicBase::SetEglWindow.");
44     eglWindow_ = reinterpret_cast<NativeWindow*>(window);
45 }
46 
Create(void * context)47 void WebGLRenderingContextBasicBase::Create(void* context)
48 {
49     LOGD("WebGLRenderingContextBasicBase::Create.");
50 }
51 
Init()52 void WebGLRenderingContextBasicBase::Init()
53 {
54     LOGD("WebGLRenderingContextBasicBase::Init. %{public}p", this);
55     EglManager::GetInstance().Init();
56     if (eglSurface_ == nullptr) {
57         eglSurface_ = EglManager::GetInstance().CreateSurface(eglWindow_);
58     }
59 }
60 
SetBitMapPtr(char * bitMapPtr,int bitMapWidth,int bitMapHeight)61 void WebGLRenderingContextBasicBase::SetBitMapPtr(char* bitMapPtr, int bitMapWidth, int bitMapHeight)
62 {
63     LOGD("WebGLRenderingContextBasicBase::SetBitMapPtr. %{public}p", this);
64     LOGD("WebGLRenderingContextBasicBase SetBitMapPtr [%{public}d %{public}d]", bitMapWidth, bitMapHeight);
65     bitMapPtr_ = bitMapPtr;
66     bitMapWidth_ = bitMapWidth;
67     bitMapHeight_ = bitMapHeight;
68     EglManager::GetInstance().SetPbufferAttributes(bitMapWidth, bitMapHeight);
69 }
70 
CreateTexture()71 uint64_t WebGLRenderingContextBasicBase::CreateTexture()
72 {
73     return 0;
74 }
75 
SetUpdateCallback(std::function<void ()> callback)76 void WebGLRenderingContextBasicBase::SetUpdateCallback(std::function<void()> callback)
77 {
78     updateCallback_ = callback;
79 }
80 
SetTexture(uint64_t id)81 void WebGLRenderingContextBasicBase::SetTexture(uint64_t id) {}
82 
Attach(uint64_t textureId)83 void WebGLRenderingContextBasicBase::Attach(uint64_t textureId) {}
84 
Update()85 void WebGLRenderingContextBasicBase::Update()
86 {
87     if (eglWindow_) {
88         LOGD("eglSwapBuffers");
89         EGLDisplay eglDisplay = EglManager::GetInstance().GetEGLDisplay();
90         eglSwapBuffers(eglDisplay, eglSurface_);
91     } else {
92         LOGD("glReadPixels packAlignment %{public}d", packAlignment_);
93         glPixelStorei(GL_PACK_ALIGNMENT, 4); // 4 alignment
94         glReadPixels(0, 0, bitMapWidth_, bitMapHeight_, GL_RGBA, GL_UNSIGNED_BYTE, bitMapPtr_);
95         glPixelStorei(GL_PACK_ALIGNMENT, packAlignment_);
96         LOGD("glReadPixels result %{public}u", glGetError());
97     }
98     if (updateCallback_) {
99         LOGD("mUpdateCallback");
100         updateCallback_();
101     } else {
102         LOGE("mUpdateCallback is null");
103     }
104 }
105 
Detach()106 void WebGLRenderingContextBasicBase::Detach() {}
107 
CreateSurface()108 bool WebGLRenderingContextBasicBase::CreateSurface()
109 {
110     if (eglSurface_ == nullptr) {
111         eglSurface_ = EglManager::GetInstance().CreateSurface(eglWindow_);
112         if (eglSurface_ == nullptr) {
113             return false;
114         }
115     }
116     return true;
117 }
118 
GetContextAttr(const std::string & str,const std::string & key,int keyLength,int value)119 string WebGLRenderingContextBasicBase::GetContextAttr(
120     const std::string& str, const std::string& key, int keyLength, int value)
121 {
122     size_t item = str.find(key);
123     if (item != string::npos) {
124         string itemVar = str.substr(item + keyLength, value);
125         return itemVar;
126     }
127     return "false";
128 }
129 
SetWebGLContextAttributes(const std::vector<std::string> & vec)130 bool WebGLRenderingContextBasicBase::SetWebGLContextAttributes(const std::vector<std::string>& vec)
131 {
132     if (vec.size() <= 1) {
133         return true;
134     }
135     if (webGlContextAttributes_ == nullptr) {
136         webGlContextAttributes_ = std::make_shared<WebGLContextAttributes>();
137         if (webGlContextAttributes_ == nullptr) {
138             return false;
139         }
140     }
141     for (size_t i = 1; i < vec.size(); i++) {
142         if (GetContextAttr(vec[i], "alpha", 7, 4) == "true") { // 7 alpha length  4 true
143             webGlContextAttributes_->alpha_ = true;
144         }
145         if (GetContextAttr(vec[i], "depth", 7, 4) == "true") { // 7 depth length  4 true
146             webGlContextAttributes_->depth_ = true;
147         }
148         if (GetContextAttr(vec[i], "stencil", 9, 4) == "true") { // 9 stencil length  4 true
149             webGlContextAttributes_->stencil_ = true;
150         }
151         if (GetContextAttr(vec[i], "premultipliedAlpha", 23, 4) == "true") { // 23 premultipliedAlpha length  4 true
152             webGlContextAttributes_->premultipliedAlpha_ = true;
153         }
154         // 18 preserveDrawingBuffer length 4 true
155         if (GetContextAttr(vec[i], "preserveDrawingBuffer", 18, 4) == "true") {
156             webGlContextAttributes_->preserveDrawingBuffer_ = true;
157         }
158         // 30 failIfMajorPerformanceCaveat length  4 true
159         if (GetContextAttr(vec[i], "failIfMajorPerformanceCaveat", 30, 4) == "true") {
160             webGlContextAttributes_->failIfMajorPerformanceCaveat_ = true;
161         }
162         if (GetContextAttr(vec[i], "desynchronized", 16, 4) == "true") { // 16 desynchronized length 4 true
163             webGlContextAttributes_->desynchronized_ = true;
164         }
165         string highPerformance = GetContextAttr(vec[i], "powerPreference", 18, 16); // 18 16 powerPreference length
166         if (highPerformance == "high-performance") {
167             webGlContextAttributes_->powerPreference_ = highPerformance;
168             return true;
169         }
170         string lowPower = GetContextAttr(vec[i], "powerPreference", 18, 9); // 18 9 powerPreference length
171         if (lowPower == "low-power") {
172             webGlContextAttributes_->powerPreference_ = lowPower;
173         } else {
174             if (GetContextAttr(vec[i], "powerPreference", 18, 7) == "default") { // 18 7 powerPreference length
175                 webGlContextAttributes_->powerPreference_ = "default";
176             }
177         }
178     }
179     return true;
180 }
181 
GetContextInstance(napi_env env,std::string className,napi_callback constructor,napi_finalize finalize_cb)182 napi_value WebGLRenderingContextBasicBase::GetContextInstance(napi_env env,
183     std::string className, napi_callback constructor, napi_finalize finalize_cb)
184 {
185     napi_value instanceValue = nullptr;
186     napi_status status;
187     if (contextRef_ == nullptr) {
188         napi_value contextClass = nullptr;
189         napi_define_class(env, className.c_str(), NAPI_AUTO_LENGTH, constructor, nullptr, 0, nullptr, &contextClass);
190         status = napi_new_instance(env, contextClass, 0, nullptr, &instanceValue);
191         if (status != napi_ok) {
192             return NVal::CreateNull(env).val_;
193         }
194         status = napi_wrap(env, instanceValue, static_cast<void*>(this), finalize_cb, nullptr, nullptr);
195         if (status != napi_ok) {
196             return NVal::CreateNull(env).val_;
197         }
198         status = napi_create_reference(env, instanceValue, 1, &contextRef_);
199         if (status != napi_ok) {
200             return NVal::CreateNull(env).val_;
201         }
202     } else {
203         status = napi_get_reference_value(env, contextRef_, &instanceValue);
204         if (status != napi_ok) {
205             return NVal::CreateNull(env).val_;
206         }
207     }
208     return instanceValue;
209 }
210 } // namespace Rosen
211 } // namespace OHOS
212 #ifdef __cplusplus
213 }
214 #endif
215