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 "glfw_render_context.h"
17 
18 #include <mutex>
19 
20 #include <GLFW/glfw3.h>
21 
22 #include "hilog/log.h"
23 
24 namespace OHOS::Rosen {
25 namespace {
26 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001403, "GlfwRC" };
27 }
28 
GetGlobal()29 std::shared_ptr<GlfwRenderContext> GlfwRenderContext::GetGlobal()
30 {
31     if (global_ == nullptr) {
32         static std::mutex mutex;
33         std::lock_guard lock(mutex);
34         if (global_ == nullptr) {
35             global_ = std::make_shared<GlfwRenderContext>();
36         }
37     }
38 
39     return global_;
40 }
41 
Init()42 int GlfwRenderContext::Init()
43 {
44     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "Init");
45     external_ = false;
46     int flag = glfwInit();
47     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "Init end");
48     return flag;
49 }
50 
InitFrom(void * glfwWindow)51 void GlfwRenderContext::InitFrom(void *glfwWindow)
52 {
53     if (glfwWindow == nullptr) {
54         ::OHOS::HiviewDFX::HiLog::Error(LABEL, "InitFrom glfwWindow is nullptr");
55         return;
56     }
57     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "InitFrom glfwWindow");
58 
59     external_ = true;
60 
61     // to be done: replace this with normal way, a no flutter way.
62     // from third_party/flutter/engine/flutter/shell/platform/glfw/flutter_glfw.cc +39
63     window_ = *reinterpret_cast<GLFWwindow **>(glfwWindow);
64 
65     glfwSetCharCallback(window_, nullptr);
66     glfwSetCursorEnterCallback(window_, nullptr);
67     glfwSetCursorPosCallback(window_, nullptr);
68     glfwSetFramebufferSizeCallback(window_, nullptr);
69     glfwSetKeyCallback(window_, nullptr);
70     glfwSetMouseButtonCallback(window_, nullptr);
71     glfwSetScrollCallback(window_, nullptr);
72     glfwSetWindowRefreshCallback(window_, nullptr);
73     glfwSetWindowUserPointer(window_, this);
74 
75     glfwGetWindowSize(window_, &width_, &height_);
76     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "glfwSetWindowSizeCallback %{public}d %{public}d", width_, height_);
77     glfwSetWindowSizeCallback(window_, GlfwRenderContext::OnSizeChanged);
78 }
79 
Terminate()80 void GlfwRenderContext::Terminate()
81 {
82     if (external_) {
83         return;
84     }
85 
86     glfwTerminate();
87 }
88 
CreateGlfwWindow(int32_t width,int32_t height,bool visible)89 int GlfwRenderContext::CreateGlfwWindow(int32_t width, int32_t height, bool visible)
90 {
91     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "CreateGlfwWindow");
92     if (external_) {
93         return 0;
94     }
95 
96     if (window_ != nullptr) {
97         return 0;
98     }
99 
100     auto flag = visible ? GLFW_TRUE : GLFW_FALSE;
101     glfwWindowHint(GLFW_DECORATED, flag);
102     glfwWindowHint(GLFW_VISIBLE, flag);
103     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "CreateGlfwWindow::glfwWindowHint end");
104     window_ = glfwCreateWindow(width, height, "glfw window", nullptr, nullptr);
105     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "CreateGlfwWindow::glfwCreateWindow end");
106     if (window_ == nullptr) {
107         return 1;
108     }
109 
110     glfwSetWindowUserPointer(window_, this);
111 
112     width_ = width;
113     height_ = height;
114     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "glfwSetWindowSizeCallback %{public}d %{public}d", width, height);
115     glfwSetWindowSizeCallback(window_, GlfwRenderContext::OnSizeChanged);
116     return 0;
117 }
118 
DestroyWindow()119 void GlfwRenderContext::DestroyWindow()
120 {
121     if (external_) {
122         return;
123     }
124 
125     if (window_ != nullptr) {
126         glfwDestroyWindow(window_);
127     }
128 }
129 
WindowShouldClose()130 int GlfwRenderContext::WindowShouldClose()
131 {
132     return glfwWindowShouldClose(window_);
133 }
134 
WaitForEvents()135 void GlfwRenderContext::WaitForEvents()
136 {
137     glfwWaitEvents();
138 }
139 
PollEvents()140 void GlfwRenderContext::PollEvents()
141 {
142     glfwPollEvents();
143 }
144 
GetWindowSize(int32_t & width,int32_t & height)145 void GlfwRenderContext::GetWindowSize(int32_t &width, int32_t &height)
146 {
147     glfwGetWindowSize(window_, &width, &height);
148 }
149 
SetWindowSize(int32_t width,int32_t height)150 void GlfwRenderContext::SetWindowSize(int32_t width, int32_t height)
151 {
152     width_ = width;
153     height_ = height;
154     glfwSetWindowSize(window_, width, height);
155 }
156 
SetWindowTitle(const std::string & title)157 void GlfwRenderContext::SetWindowTitle(const std::string &title)
158 {
159     glfwSetWindowTitle(window_, title.c_str());
160 }
161 
GetClipboardData()162 std::string GlfwRenderContext::GetClipboardData()
163 {
164     return glfwGetClipboardString(window_);
165 }
166 
SetClipboardData(const std::string & data)167 void GlfwRenderContext::SetClipboardData(const std::string &data)
168 {
169     glfwSetClipboardString(window_, data.c_str());
170 }
171 
MakeCurrent()172 void GlfwRenderContext::MakeCurrent()
173 {
174     glfwMakeContextCurrent(window_);
175 }
176 
SwapBuffers()177 void GlfwRenderContext::SwapBuffers()
178 {
179     glfwSwapBuffers(window_);
180 }
181 
OnMouseButton(const OnMouseButtonFunc & onMouseBotton)182 void GlfwRenderContext::OnMouseButton(const OnMouseButtonFunc &onMouseBotton)
183 {
184     onMouseBotton_ = onMouseBotton;
185     glfwSetMouseButtonCallback(window_, GlfwRenderContext::OnMouseButton);
186 }
187 
OnCursorPos(const OnCursorPosFunc & onCursorPos)188 void GlfwRenderContext::OnCursorPos(const OnCursorPosFunc &onCursorPos)
189 {
190     onCursorPos_ = onCursorPos;
191     glfwSetCursorPosCallback(window_, GlfwRenderContext::OnCursorPos);
192 }
193 
OnKey(const OnKeyFunc & onKey)194 void GlfwRenderContext::OnKey(const OnKeyFunc &onKey)
195 {
196     onKey_ = onKey;
197     glfwSetKeyCallback(window_, GlfwRenderContext::OnKey);
198 }
199 
OnChar(const OnCharFunc & onChar)200 void GlfwRenderContext::OnChar(const OnCharFunc &onChar)
201 {
202     onChar_ = onChar;
203     glfwSetCharCallback(window_, GlfwRenderContext::OnChar);
204 }
205 
OnSizeChanged(const OnSizeChangedFunc & onSizeChanged)206 void GlfwRenderContext::OnSizeChanged(const OnSizeChangedFunc &onSizeChanged)
207 {
208     onSizeChanged_ = onSizeChanged;
209     glfwSetWindowSizeCallback(window_, GlfwRenderContext::OnSizeChanged);
210 }
211 
OnMouseButton(GLFWwindow * window,int button,int action,int mods)212 void GlfwRenderContext::OnMouseButton(GLFWwindow *window, int button, int action, int mods)
213 {
214     const auto &that = reinterpret_cast<GlfwRenderContext *>(glfwGetWindowUserPointer(window));
215     if (that->onMouseBotton_) {
216         that->onMouseBotton_(button, action == GLFW_PRESS, mods);
217     }
218 }
219 
OnCursorPos(GLFWwindow * window,double x,double y)220 void GlfwRenderContext::OnCursorPos(GLFWwindow *window, double x, double y)
221 {
222     const auto &that = reinterpret_cast<GlfwRenderContext *>(glfwGetWindowUserPointer(window));
223     if (that->onCursorPos_) {
224         that->onCursorPos_(x, y);
225     }
226 }
227 
OnKey(GLFWwindow * window,int key,int scancode,int action,int mods)228 void GlfwRenderContext::OnKey(GLFWwindow *window, int key, int scancode, int action, int mods)
229 {
230     const auto &that = reinterpret_cast<GlfwRenderContext *>(glfwGetWindowUserPointer(window));
231     if (that->onKey_) {
232         that->onKey_(key, scancode, action, mods);
233     }
234 }
235 
OnChar(GLFWwindow * window,unsigned int codepoint)236 void GlfwRenderContext::OnChar(GLFWwindow *window, unsigned int codepoint)
237 {
238     const auto &that = reinterpret_cast<GlfwRenderContext *>(glfwGetWindowUserPointer(window));
239     if (that->onChar_) {
240         that->onChar_(codepoint);
241     }
242 }
243 
OnSizeChanged(GLFWwindow * window,int32_t width,int32_t height)244 void GlfwRenderContext::OnSizeChanged(GLFWwindow *window, int32_t width, int32_t height)
245 {
246     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "OnSizeChanged %{public}d %{public}d", width, height);
247 
248     const auto &that = reinterpret_cast<GlfwRenderContext *>(glfwGetWindowUserPointer(window));
249     if (that->width_ != width || that->height_ != height) {
250         glfwSetWindowSize(window, that->width_, that->height_);
251     }
252     that->onSizeChanged_(that->width_, that->height_);
253     ::OHOS::HiviewDFX::HiLog::Info(LABEL, "OnSizeChanged done %{public}d %{public}d", width, height);
254 }
255 } // namespace OHOS::Rosen
256