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