1 /*
2  * Copyright (c) 2022 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 "gles_render_backend.h"
17 
18 #include "egl_manager.h"
19 #include "drawing_utils.h"
20 #include "skia_adapter/skia_surface.h"
21 #include "surface_ohos_gl.h"
22 #include "iostream"
23 
24 namespace OHOS {
25 namespace Rosen {
GLESRenderBackend()26 GLESRenderBackend::GLESRenderBackend() noexcept
27 {
28     eglManager_ = new EGLManager();
29 }
30 
~GLESRenderBackend()31 GLESRenderBackend::~GLESRenderBackend()
32 {
33     if (eglManager_) {
34         delete eglManager_;
35         eglManager_ = nullptr;
36     }
37 }
38 
InitDrawContext()39 void GLESRenderBackend::InitDrawContext()
40 {
41     if (eglManager_ == nullptr) {
42         LOGE("eglManager_ is nullptr, can not InitDrawContext");
43         return;
44     }
45     eglManager_->Init();
46 }
47 
SetUpGrContext()48 bool GLESRenderBackend::SetUpGrContext()
49 {
50     if (grContext_ != nullptr) {
51         LOGD("grContext has already created!!");
52         return true;
53     }
54 
55     sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
56     if (glInterface.get() == nullptr) {
57         LOGE("SetUpGrContext failed to make native interface");
58         return false;
59     }
60 
61     GrContextOptions options;
62     options.fPreferExternalImagesOverES3 = true;
63     options.fDisableDistanceFieldPaths = true;
64     options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
65     // fix svg antialiasing bug
66     options.fGpuPathRenderers &= ~GpuPathRenderers::kAtlas;
67 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
68     sk_sp<GrDirectContext> grContext(GrDirectContext::MakeGL(std::move(glInterface), options));
69     if (grContext == nullptr) {
70         LOGE("SetUpGrContext grContext is null");
71         return false;
72     }
73 #else
74     sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
75     if (grContext == nullptr) {
76         LOGE("SetUpGrContext grContext is null");
77         return false;
78     }
79 #endif
80     grContext_ = std::move(grContext);
81     LOGI("SetUpGrContext done");
82     return true;
83 }
84 
SetUpDrContext()85 bool GLESRenderBackend::SetUpDrContext()
86 {
87     if (drGPUContext_ != nullptr) {
88         LOGD("Drawing GPUContext has already created!!");
89         return true;
90     }
91 
92     Drawing::GPUContextOptions options;
93 
94     auto drGPUContext = std::make_shared<Drawing::GPUContext>();
95     if (!drGPUContext->BuildFromGL(options)) {
96         LOGE("SetUpGrContext drGPUContext is null");
97         return false;
98     }
99     drGPUContext_ = std::move(drGPUContext);
100     return true;
101 }
102 
MakeCurrent()103 void GLESRenderBackend::MakeCurrent()
104 {
105     if (eglManager_ == nullptr) {
106         LOGE("eglManager_ is nullptr, can not MakeCurrent");
107         return;
108     }
109     eglManager_->MakeCurrent();
110 }
111 
SwapBuffers()112 void GLESRenderBackend::SwapBuffers()
113 {
114     if (eglManager_ == nullptr) {
115         LOGE("eglManager_ is nullptr, can not SwapBuffers");
116         return;
117     }
118     eglManager_->SwapBuffers();
119 }
120 
CreateSurface(void * window)121 void* GLESRenderBackend::CreateSurface(void* window)
122 {
123     if (eglManager_ == nullptr) {
124         LOGE("eglManager_ is nullptr, can not CreateSurface");
125         return nullptr;
126     }
127     return static_cast<void*>(eglManager_->CreateSurface((EGLNativeWindowType)window));
128 }
129 
SetDamageRegion(int32_t left,int32_t top,int32_t width,int32_t height)130 void GLESRenderBackend::SetDamageRegion(int32_t left, int32_t top, int32_t width, int32_t height)
131 {
132     if (eglManager_ == nullptr) {
133         LOGE("eglManager_ is nullptr, can not SetDamageRegion");
134         return;
135     }
136     eglManager_->SetDamageRegion(left, top, width, height);
137 }
138 
Destroy()139 void GLESRenderBackend::Destroy()
140 {
141     grContext_ = nullptr;
142     skSurface_ = nullptr;
143 }
144 
RenderFrame()145 void GLESRenderBackend::RenderFrame()
146 {
147     // flush commands
148     if (pSkSurface_->getCanvas() != nullptr) {
149         LOGD("RenderFrame: Canvas");
150         std::cout << "GLESRenderBackend::RenderFrame flushing" << std::endl;
151         pSkSurface_->getCanvas()->flush();
152     } else {
153         LOGW("canvas is nullptr!!!");
154     }
155 }
156 
AcquireSkCanvas(std::unique_ptr<SurfaceFrame> & frame)157 SkCanvas* GLESRenderBackend::AcquireSkCanvas(std::unique_ptr<SurfaceFrame>& frame)
158 {
159     if (!SetUpGrContext()) {
160         LOGE("GrContext is not ready!!!");
161         return nullptr;
162     }
163 
164     SurfaceFrameOhosGl* framePtr = static_cast<SurfaceFrameOhosGl*>(frame.get());
165 
166     if (GetGrContext() == nullptr) {
167         LOGE("GrContext is not ready!!!");
168         return nullptr;
169     }
170 
171     GrGLFramebufferInfo framebufferInfo;
172     framebufferInfo.fFBOID = 0;
173     framebufferInfo.fFormat = GL_RGBA8;
174 
175     SkColorType colorType = kRGBA_8888_SkColorType;
176 
177     int32_t width = framePtr->GetWidth();
178     int32_t height = framePtr->GetHeight();
179     const int stencilBufferSize = 8;
180 
181     GrBackendRenderTarget backendRenderTarget(width, height, 0, stencilBufferSize, framebufferInfo);
182 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
183     SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry);
184 #else
185     SkSurfaceProps surfaceProps = SkSurfaceProps::kLegacyFontHost_InitType;
186 #endif
187     skSurface_ = SkSurface::MakeFromBackendRenderTarget(
188         GetGrContext(), backendRenderTarget, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &surfaceProps);
189     if (skSurface_ == nullptr) {
190         LOGW("skSurface is nullptr");
191         return nullptr;
192     }
193     pSkSurface_ = skSurface_.get();
194     LOGI("CreateCanvas successfully!!!");
195 
196     return skSurface_->getCanvas();
197 }
198 
AcquireDrCanvas(std::unique_ptr<SurfaceFrame> & frame)199 Drawing::Canvas* GLESRenderBackend::AcquireDrCanvas(std::unique_ptr<SurfaceFrame>& frame)
200 {
201     if (!SetUpDrContext()) {
202         LOGE("GrContext is not ready!!!");
203         return nullptr;
204     }
205 
206     SurfaceFrameOhosGl* framePtr = static_cast<SurfaceFrameOhosGl*>(frame.get());
207 
208     int32_t width = framePtr->GetWidth();
209     int32_t height = framePtr->GetHeight();
210 
211     std::shared_ptr<Drawing::ColorSpace> colorSpace = nullptr;
212 
213     colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
214         Drawing::CMSMatrixType::DCIP3);
215 
216     struct Drawing::FrameBuffer bufferInfo;
217     bufferInfo.width = width;
218     bufferInfo.height = height;
219     bufferInfo.FBOID = 0;
220     bufferInfo.Format = GL_RGBA8;
221     bufferInfo.colorType = Drawing::COLORTYPE_RGBA_8888;
222     bufferInfo.gpuContext = drGPUContext_;
223     bufferInfo.colorSpace = colorSpace;
224 
225     drSurface_ = std::make_shared<Drawing::Surface>();
226     if (!drSurface_->Bind(bufferInfo)) {
227         LOGW("surface_ is nullptr");
228         drSurface_ = nullptr;
229         return nullptr;
230     }
231 
232     LOGD("CreateCanvas successfully!!!");
233     pSkSurface_ = drSurface_->GetImpl<Drawing::SkiaSurface>()->GetSkSurface().get();
234     return drSurface_->GetCanvas().get();
235 }
236 }
237 }