• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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