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 "pixel_map_gl_context.h"
17
18 #undef LOG_DOMAIN
19 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
20 #undef LOG_TAG
21 #define LOG_TAG "PixelMapGlContext"
22
23 namespace OHOS {
24 namespace Media {
25
26 static bool displayInitFlag = false;
27 EGLDisplay PixelMapGlContext::eglDisplay_ = EGL_NO_DISPLAY;
28 EGLConfig PixelMapGlContext::config_ = nullptr;
29
PixelMapGlContext()30 PixelMapGlContext::PixelMapGlContext()
31 {
32 }
33
PixelMapGlContext(bool init)34 PixelMapGlContext::PixelMapGlContext(bool init)
35 {
36 if (init) {
37 InitEGLContext();
38 }
39 }
40
~PixelMapGlContext()41 PixelMapGlContext::~PixelMapGlContext() noexcept
42 {
43 Clear();
44 }
45
Init()46 bool PixelMapGlContext::Init()
47 {
48 if (!InitEGLContext()) {
49 return false;
50 }
51
52 if (!InitGrContext()) {
53 return false;
54 }
55
56 return true;
57 }
58
InitEGLContext()59 bool PixelMapGlContext::InitEGLContext()
60 {
61 ImageTrace imageTrace("PixelMapGlContext::InitEGLContext");
62 if (!displayInitFlag) {
63 eglDisplay_ = eglGetPlatformDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, nullptr);
64 if (eglDisplay_ == EGL_NO_DISPLAY) {
65 IMAGE_LOGE("PixelMapGlContext::Init: eglGetDisplay error: ");
66 return false;
67 }
68 EGLint major = 0;
69 EGLint minor = 0;
70 if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {
71 IMAGE_LOGE("Failed to initialize EGLDisplay");
72 return false;
73 }
74 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
75 IMAGE_LOGE("Failed to bind OpenGL ES API");
76 return false;
77 }
78 unsigned int ret;
79 EGLint count;
80 EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8,
81 EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE,
82 EGL_OPENGL_ES3_BIT, EGL_NONE };
83 ret = eglChooseConfig(eglDisplay_, configAttribs, &config_, 1, &count);
84 if (!(ret && static_cast<unsigned int>(count) >= 1)) {
85 IMAGE_LOGE("Failed to eglChooseConfig");
86 return false;
87 }
88 IMAGE_LOGE("PixelMapGlContext::Init");
89 displayInitFlag = true;
90 }
91
92 if (eglDisplay_ == EGL_NO_DISPLAY) {
93 return false;
94 }
95
96 static const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
97 eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, contextAttribs);
98 if (eglContext_ == EGL_NO_CONTEXT) {
99 IMAGE_LOGE("Failed to create egl context %{public}x", eglGetError());
100 return false;
101 }
102
103 if (!CreatePbufferSurface()) {
104 return false;
105 }
106 MakeCurrent(pbufferSurface_);
107
108 return true;
109 }
110
CreatePbufferSurface()111 bool PixelMapGlContext::CreatePbufferSurface()
112 {
113 if (pbufferSurface_ == EGL_NO_SURFACE) {
114 EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
115 pbufferSurface_ = eglCreatePbufferSurface(eglDisplay_, config_, attribs);
116 if (pbufferSurface_ == EGL_NO_SURFACE) {
117 IMAGE_LOGE(
118 "PixelMapGlContext::CreatePbufferSurface failed, error is %{public}x",
119 eglGetError());
120 return false;
121 }
122 }
123 return true;
124 }
125
MakeCurrentSimple(bool needCurrent)126 bool PixelMapGlContext::MakeCurrentSimple(bool needCurrent)
127 {
128 EGLSurface currSurfaceDraw = pbufferSurface_;
129 EGLSurface currSurfaceRead = pbufferSurface_;
130 EGLContext currContext = eglContext_;
131 if (!needCurrent) {
132 currSurfaceDraw = oldEglSurfaceDraw_;
133 currSurfaceRead = oldEglSurfaceRead_;
134 currContext = oldEglContext_;
135 } else {
136 EGLSurface oldSurface = eglGetCurrentSurface(EGL_DRAW);
137 EGLContext oldContext = eglGetCurrentContext();
138 if (oldSurface == currSurfaceDraw && oldContext == currContext) {
139 IMAGE_LOGI("PixelGPU::MakeCurrentSimple with same context");
140 return true;
141 }
142 oldEglSurfaceDraw_ = oldSurface;
143 oldEglSurfaceRead_ = eglGetCurrentSurface(EGL_READ);
144 oldEglContext_ = oldContext;
145 }
146
147 if (eglMakeCurrent(eglDisplay_, currSurfaceDraw, currSurfaceRead, currContext) != EGL_TRUE) {
148 EGLint surfaceId = -1;
149 eglQuerySurface(eglDisplay_, currSurfaceDraw, EGL_CONFIG_ID, &surfaceId);
150 IMAGE_LOGE(
151 "PixelMapGlContext::MakeCurrent failed %{public}d, error is %{public}x needCurrent %{public}d",
152 surfaceId,
153 eglGetError(), needCurrent);
154 return false;
155 }
156 return true;
157 }
158
MakeCurrent(EGLSurface surface) const159 void PixelMapGlContext::MakeCurrent(EGLSurface surface) const
160 {
161 EGLSurface currSurface = surface;
162 if (currSurface == EGL_NO_SURFACE) {
163 currSurface = pbufferSurface_;
164 }
165
166 if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) {
167 EGLint surfaceId = -1;
168 eglQuerySurface(eglDisplay_, surface, EGL_CONFIG_ID, &surfaceId);
169 IMAGE_LOGE(
170 "PixelMapGlContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x",
171 surfaceId,
172 eglGetError());
173 }
174 }
175
InitGrContext()176 bool PixelMapGlContext::InitGrContext()
177 {
178 #ifdef USE_M133_SKIA
179 sk_sp<const GrGLInterface> glInterface(GrGLMakeNativeInterface());
180 #else
181 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
182 #endif
183 if (glInterface == nullptr) {
184 IMAGE_LOGE("SetUpGrContext failed to make native interface");
185 return false;
186 }
187
188 GrContextOptions options;
189 options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
190 options.fPreferExternalImagesOverES3 = true;
191 options.fDisableDistanceFieldPaths = true;
192 #ifdef USE_M133_SKIA
193 grContext_ = GrDirectContexts::MakeGL(std::move(glInterface), options);
194 #else
195 grContext_ = GrDirectContext::MakeGL(std::move(glInterface), options);
196 #endif
197 return grContext_ != nullptr;
198 }
199
Clear()200 void PixelMapGlContext::Clear() noexcept
201 {
202 if (eglDisplay_ == EGL_NO_DISPLAY) {
203 return;
204 }
205
206 grContext_ = nullptr;
207
208 if (pbufferSurface_ != EGL_NO_SURFACE) {
209 EGLBoolean ret = eglDestroySurface(eglDisplay_, pbufferSurface_);
210 if (ret != EGL_TRUE) {
211 IMAGE_LOGE("PixelMapGlContext::Clear() failed error is %{public}x.", eglGetError());
212 }
213 pbufferSurface_ = EGL_NO_SURFACE;
214 }
215
216 (void)eglDestroyContext(eglDisplay_, eglContext_);
217 eglContext_ = EGL_NO_CONTEXT;
218 }
219 } // namespace Media
220 } // namespace OHOS
221