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 "render_context.h"
17
18 #include "image_log.h"
19
20 #undef LOG_DOMAIN
21 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
22
23 #undef LOG_TAG
24 #define LOG_TAG "PixelMap"
25
26 namespace OHOS {
27 namespace Media {
28
RenderContext()29 RenderContext::RenderContext()
30 {}
31
~RenderContext()32 RenderContext::~RenderContext() noexcept
33 {
34 Clear();
35 }
36
Init()37 bool RenderContext::Init()
38 {
39 if (!InitEGLContext()) {
40 return false;
41 }
42
43 if (!InitGrContext()) {
44 return false;
45 }
46
47 return true;
48 }
49
InitEGLContext()50 bool RenderContext::InitEGLContext()
51 {
52 eglDisplay_ = eglGetPlatformDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, nullptr);
53 if (eglDisplay_ == EGL_NO_DISPLAY) {
54 IMAGE_LOGE("RenderContext::Init: eglGetDisplay error: ");
55 return false;
56 }
57
58 EGLint major = 0;
59 EGLint minor = 0;
60 if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {
61 IMAGE_LOGE("Failed to initialize EGLDisplay");
62 return false;
63 }
64
65 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
66 IMAGE_LOGE("Failed to bind OpenGL ES API");
67 return false;
68 }
69
70 unsigned int ret;
71 EGLint count;
72 EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
73 EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_NONE };
74
75 ret = eglChooseConfig(eglDisplay_, configAttribs, &config_, 1, &count);
76 if (!(ret && static_cast<unsigned int>(count) >= 1)) {
77 IMAGE_LOGE("Failed to eglChooseConfig");
78 return false;
79 }
80
81 static const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
82 eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, contextAttribs);
83 if (eglContext_ == EGL_NO_CONTEXT) {
84 IMAGE_LOGE("Failed to create egl context %{public}x", eglGetError());
85 return false;
86 }
87
88 if (!CreatePbufferSurface()) {
89 return false;
90 }
91 MakeCurrent(pbufferSurface_);
92
93 return true;
94 }
95
CreatePbufferSurface()96 bool RenderContext::CreatePbufferSurface()
97 {
98 if (pbufferSurface_ == EGL_NO_SURFACE) {
99 EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
100 pbufferSurface_ = eglCreatePbufferSurface(eglDisplay_, config_, attribs);
101 if (pbufferSurface_ == EGL_NO_SURFACE) {
102 IMAGE_LOGE(
103 "RenderContext::CreatePbufferSurface failed, error is %{public}x",
104 eglGetError());
105 return false;
106 }
107 }
108 return true;
109 }
110
MakeCurrent(EGLSurface surface) const111 void RenderContext::MakeCurrent(EGLSurface surface) const
112 {
113 EGLSurface currSurface = surface;
114 if (currSurface == EGL_NO_SURFACE) {
115 currSurface = pbufferSurface_;
116 }
117
118 if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) {
119 EGLint surfaceId = -1;
120 eglQuerySurface(eglDisplay_, surface, EGL_CONFIG_ID, &surfaceId);
121 IMAGE_LOGE(
122 "RenderContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x",
123 surfaceId,
124 eglGetError());
125 }
126 }
127
InitGrContext()128 bool RenderContext::InitGrContext()
129 {
130 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
131 if (glInterface == nullptr) {
132 IMAGE_LOGE("SetUpGrContext failed to make native interface");
133 return false;
134 }
135
136 GrContextOptions options;
137 options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
138 options.fPreferExternalImagesOverES3 = true;
139 options.fDisableDistanceFieldPaths = true;
140 grContext_ = GrDirectContext::MakeGL(std::move(glInterface), options);
141 return grContext_ != nullptr;
142 }
143
Clear()144 void RenderContext::Clear() noexcept
145 {
146 if (eglDisplay_ == EGL_NO_DISPLAY) {
147 return;
148 }
149
150 grContext_ = nullptr;
151
152 if (pbufferSurface_ != EGL_NO_SURFACE) {
153 EGLBoolean ret = eglDestroySurface(eglDisplay_, pbufferSurface_);
154 if (ret != EGL_TRUE) {
155 IMAGE_LOGE("RenderContext::Clear() failed to destroy pbuffer surface, error is %{public}x.", eglGetError());
156 }
157 pbufferSurface_ = EGL_NO_SURFACE;
158 }
159
160 (void)eglDestroyContext(eglDisplay_, eglContext_);
161 (void)eglTerminate(eglDisplay_);
162 eglContext_ = EGL_NO_CONTEXT;
163 eglDisplay_ = EGL_NO_DISPLAY;
164 }
165 } // namespace Media
166 } // namespace OHOS
167