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 IMAGE_LOGD(
146 "PixelGPU::MakeCurrent eglSurface %{public}p=>%{public}p eglContext %{public}p=>%{public}p",
147 oldEglSurfaceDraw_, currSurfaceDraw, oldEglContext_, currContext);
148 }
149
150 if (eglMakeCurrent(eglDisplay_, currSurfaceDraw, currSurfaceRead, currContext) != EGL_TRUE) {
151 EGLint surfaceId = -1;
152 eglQuerySurface(eglDisplay_, currSurfaceDraw, EGL_CONFIG_ID, &surfaceId);
153 IMAGE_LOGE(
154 "PixelMapGlContext::MakeCurrent failed %{public}d, error is %{public}x needCurrent %{public}d",
155 surfaceId,
156 eglGetError(), needCurrent);
157 return false;
158 }
159 return true;
160 }
161
MakeCurrent(EGLSurface surface) const162 void PixelMapGlContext::MakeCurrent(EGLSurface surface) const
163 {
164 EGLSurface currSurface = surface;
165 if (currSurface == EGL_NO_SURFACE) {
166 currSurface = pbufferSurface_;
167 }
168
169 if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) {
170 EGLint surfaceId = -1;
171 eglQuerySurface(eglDisplay_, surface, EGL_CONFIG_ID, &surfaceId);
172 IMAGE_LOGE(
173 "PixelMapGlContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x",
174 surfaceId,
175 eglGetError());
176 }
177 }
178
InitGrContext()179 bool PixelMapGlContext::InitGrContext()
180 {
181 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
182 if (glInterface == nullptr) {
183 IMAGE_LOGE("SetUpGrContext failed to make native interface");
184 return false;
185 }
186
187 GrContextOptions options;
188 options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
189 options.fPreferExternalImagesOverES3 = true;
190 options.fDisableDistanceFieldPaths = true;
191 grContext_ = GrDirectContext::MakeGL(std::move(glInterface), options);
192 return grContext_ != nullptr;
193 }
194
Clear()195 void PixelMapGlContext::Clear() noexcept
196 {
197 if (eglDisplay_ == EGL_NO_DISPLAY) {
198 return;
199 }
200
201 grContext_ = nullptr;
202
203 if (pbufferSurface_ != EGL_NO_SURFACE) {
204 EGLBoolean ret = eglDestroySurface(eglDisplay_, pbufferSurface_);
205 if (ret != EGL_TRUE) {
206 IMAGE_LOGE("PixelMapGlContext::Clear() failed error is %{public}x.", eglGetError());
207 }
208 pbufferSurface_ = EGL_NO_SURFACE;
209 }
210
211 (void)eglDestroyContext(eglDisplay_, eglContext_);
212 eglContext_ = EGL_NO_CONTEXT;
213 }
214 } // namespace Media
215 } // namespace OHOS
216