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, Hardware
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 <parameter.h>
17 #include <parameters.h>
18 #include "gtest/gtest.h"
19
20 #include "EGL/egl.h"
21 #include "EGL/eglext.h"
22 #include "GLES3/gl32.h"
23
24 #include "draw/color.h"
25 #include "image/gpu_context.h"
26 #include "utils/log.h"
27
28 using namespace testing;
29 using namespace testing::ext;
30
31 namespace OHOS {
32 namespace Rosen {
33 namespace Drawing {
34 constexpr int32_t EGL_CONTEXT_CLIENT_VERSION_NUM = 2;
35
36 class ShaderPersistentCache : public GPUContextOptions::PersistentCache {
37 public:
38 ShaderPersistentCache() = default;
39 ~ShaderPersistentCache() override = default;
40
Load(const Data & key)41 std::shared_ptr<Data> Load(const Data& key) override { return nullptr; };
Store(const Data & key,const Data & data)42 void Store(const Data& key, const Data& data) override {};
43 };
44
45 class GpuContextTest : public testing::Test {
46 public:
47 static void SetUpTestCase();
48 static void TearDownTestCase();
49 void SetUp() override;
50 void TearDown() override;
51
52 static void InitEGL();
53 static void DestroyEGL();
54
55 private:
56 static EGLDisplay eglDisplay_;
57 static EGLContext eglContext_;
58 };
59
60 EGLDisplay GpuContextTest::eglDisplay_ = EGL_NO_DISPLAY;
61 EGLContext GpuContextTest::eglContext_ = EGL_NO_CONTEXT;
62
SetUpTestCase()63 void GpuContextTest::SetUpTestCase()
64 {
65 InitEGL();
66 }
67
TearDownTestCase()68 void GpuContextTest::TearDownTestCase()
69 {
70 DestroyEGL();
71 }
72
SetUp()73 void GpuContextTest::SetUp() {}
TearDown()74 void GpuContextTest::TearDown() {}
75
InitEGL()76 void GpuContextTest::InitEGL()
77 {
78 LOGI("Creating EGLContext!!!");
79 eglDisplay_ = eglGetDisplay(static_cast<EGLNativeDisplayType>(EGL_DEFAULT_DISPLAY));
80 if (eglDisplay_ == EGL_NO_DISPLAY) {
81 LOGW("Failed to create EGLDisplay gl errno : %{public}x", eglGetError());
82 return;
83 }
84
85 EGLint major, minor;
86 if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {
87 LOGE("Failed to initialize EGLDisplay");
88 return;
89 }
90
91 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
92 LOGE("Failed to bind OpenGL ES API");
93 return;
94 }
95
96 unsigned int ret;
97 EGLConfig config;
98 EGLint count;
99 EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
100 EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_NONE };
101
102 ret = eglChooseConfig(eglDisplay_, configAttribs, &config, 1, &count);
103 if (!(ret && static_cast<unsigned int>(count) >= 1)) {
104 LOGE("Failed to eglChooseConfig");
105 return;
106 }
107
108 static const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE };
109
110 eglContext_ = eglCreateContext(eglDisplay_, config, EGL_NO_CONTEXT, contextAttribs);
111 if (eglContext_ == EGL_NO_CONTEXT) {
112 LOGE("Failed to create egl context %{public}x", eglGetError());
113 return;
114 }
115 if (!eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext_)) {
116 LOGE("Failed to make current on surface, error is %{public}x", eglGetError());
117 return;
118 }
119
120 LOGI("Create EGL context successfully, version %{public}d.%{public}d", major, minor);
121 }
122
DestroyEGL()123 void GpuContextTest::DestroyEGL()
124 {
125 if (eglDisplay_ == EGL_NO_DISPLAY) {
126 return;
127 }
128
129 eglDestroyContext(eglDisplay_, eglContext_);
130 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
131 eglTerminate(eglDisplay_);
132 eglReleaseThread();
133
134 eglDisplay_ = EGL_NO_DISPLAY;
135 eglContext_ = EGL_NO_CONTEXT;
136 }
137
138 /**
139 * @tc.name: GPUContextCreateTest001
140 * @tc.desc: Test for creating GPUContext.
141 * @tc.type: FUNC
142 * @tc.require: I774GD
143 */
144 HWTEST_F(GpuContextTest, GPUContextCreateTest001, TestSize.Level1)
145 {
146 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
147 ASSERT_TRUE(gpuContext != nullptr);
148 }
149
150 /**
151 * @tc.name: GPUContextCreateTest001
152 * @tc.desc: Test for creating a GL GPUContext for a backend context.
153 * @tc.type: FUNC
154 * @tc.require: I774GD
155 */
156 HWTEST_F(GpuContextTest, BuildFromGLTest001, TestSize.Level1)
157 {
158 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
159 ASSERT_TRUE(gpuContext != nullptr);
160 GPUContextOptions options;
161 EXPECT_TRUE(gpuContext->BuildFromGL(options));
162
163 gpuContext->Flush();
164 std::chrono::milliseconds msNotUsed;
165 gpuContext->PerformDeferredCleanup(msNotUsed);
166 int32_t maxResource = 100;
167 size_t maxResourceBytes = 1000;
168 gpuContext->GetResourceCacheLimits(&maxResource, &maxResourceBytes);
169 gpuContext->SetResourceCacheLimits(maxResource, maxResourceBytes);
170 }
171
172 /**
173 * @tc.name: GPUContextCreateTest002
174 * @tc.desc: Test for creating a GL GPUContext for a backend context.
175 * @tc.type: FUNC
176 * @tc.require: I774GD
177 */
178 HWTEST_F(GpuContextTest, BuildFromGLTest002, TestSize.Level1)
179 {
180 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
181 ASSERT_TRUE(gpuContext != nullptr);
182 GPUContextOptions options;
183 auto persistentCache = std::make_shared<ShaderPersistentCache>();
184 options.SetPersistentCache(persistentCache.get());
185 EXPECT_TRUE(gpuContext->BuildFromGL(options));
186 }
187
188 #ifdef RS_ENABLE_VK
189 /**
190 * @tc.name: GPUContextCreateTest003
191 * @tc.desc: Test for creating a VK GPUContext for a backend context.
192 * @tc.type: FUNC
193 * @tc.require: I774GD
194 */
195 HWTEST_F(GpuContextTest, BuildFromVKTest001, TestSize.Level1)
196 {
197 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
198 ASSERT_TRUE(gpuContext != nullptr);
199 GrVkBackendContext grVkBackendContext;
200 auto type = system::GetParameter("persist.sys.graphic.GpuApitype", "-1");
201 system::SetParameter("persist.sys.graphic.GpuApitype", "0");
202 ASSERT_FALSE(gpuContext->BuildFromVK(grVkBackendContext));
203 system::SetParameter("persist.sys.graphic.GpuApitype", "1");
204 ASSERT_FALSE(gpuContext->BuildFromVK(grVkBackendContext));
205 system::SetParameter("persist.sys.graphic.GpuApitype", type);
206 }
207
208 /**
209 * @tc.name: GPUContextCreateTest004
210 * @tc.desc: Test for creating a VK GPUContext for a backend context.
211 * @tc.type: FUNC
212 * @tc.require: I774GD
213 */
214 HWTEST_F(GpuContextTest, BuildFromVKTest002, TestSize.Level1)
215 {
216 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
217 ASSERT_TRUE(gpuContext != nullptr);
218 GrVkBackendContext grVkBackendContext;
219 GPUContextOptions options;
220 options.SetAllowPathMaskCaching(true);
221 auto type = system::GetParameter("persist.sys.graphic.GpuApitype", "-1");
222 system::SetParameter("persist.sys.graphic.GpuApitype", "0");
223 ASSERT_FALSE(gpuContext->BuildFromVK(grVkBackendContext, options));
224 system::SetParameter("persist.sys.graphic.GpuApitype", "1");
225 ASSERT_FALSE(gpuContext->BuildFromVK(grVkBackendContext, options));
226 system::SetParameter("persist.sys.graphic.GpuApitype", type);
227 }
228 #endif
229
230 /**
231 * @tc.name: FlushTest001
232 * @tc.desc: Test for flushing to underlying 3D API specific objects.
233 * @tc.type: FUNC
234 * @tc.require: I774GD
235 */
236 HWTEST_F(GpuContextTest, FlushTest001, TestSize.Level1)
237 {
238 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
239 ASSERT_TRUE(gpuContext != nullptr);
240 gpuContext->Flush();
241 }
242
243 /**
244 * @tc.name: PerformDeferredCleanupTest001
245 * @tc.desc: Test for Purging GPU resources that haven't been used in the past 'msNotUsed' milliseconds.
246 * @tc.type: FUNC
247 * @tc.require: I774GD
248 */
249 HWTEST_F(GpuContextTest, PerformDeferredCleanupTest001, TestSize.Level1)
250 {
251 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
252 ASSERT_TRUE(gpuContext != nullptr);
253 std::chrono::milliseconds msNotUsed;
254 gpuContext->PerformDeferredCleanup(msNotUsed);
255 }
256
257 /**
258 * @tc.name: GetResourceCacheLimitsTest001
259 * @tc.desc: Test for geting the current GPU resource cache limits.
260 * @tc.type: FUNC
261 * @tc.require: I774GD
262 */
263 HWTEST_F(GpuContextTest, GetResourceCacheLimitsTest001, TestSize.Level1)
264 {
265 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
266 ASSERT_TRUE(gpuContext != nullptr);
267 int32_t maxResource = 0;
268 size_t maxResourceBytes = 0;
269 gpuContext->GetResourceCacheLimits(&maxResource, &maxResourceBytes);
270 }
271
272 /**
273 * @tc.name: GetResourceCacheLimitsTest002
274 * @tc.desc: Test for geting the current GPU resource cache limits.
275 * @tc.type: FUNC
276 * @tc.require: I774GD
277 */
278 HWTEST_F(GpuContextTest, GetResourceCacheLimitsTest002, TestSize.Level1)
279 {
280 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
281 ASSERT_TRUE(gpuContext != nullptr);
282 int32_t maxResource = 10;
283 size_t maxResourceBytes = 1000;
284 gpuContext->GetResourceCacheLimits(&maxResource, &maxResourceBytes);
285 }
286
287 /**
288 * @tc.name: SetResourceCacheLimitsTest001
289 * @tc.desc: Test for set specify the GPU resource cache limits.
290 * @tc.type: FUNC
291 * @tc.require: I774GD
292 */
293 HWTEST_F(GpuContextTest, SetResourceCacheLimitsTest001, TestSize.Level1)
294 {
295 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
296 ASSERT_TRUE(gpuContext != nullptr);
297 int32_t maxResource = 0;
298 size_t maxResourceBytes = 0;
299 gpuContext->SetResourceCacheLimits(maxResource, maxResourceBytes);
300 }
301
302 /**
303 * @tc.name: SetResourceCacheLimitsTest002
304 * @tc.desc: Test for set specify the GPU resource cache limits.
305 * @tc.type: FUNC
306 * @tc.require: I774GD
307 */
308 HWTEST_F(GpuContextTest, SetResourceCacheLimitsTest002, TestSize.Level1)
309 {
310 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
311 ASSERT_TRUE(gpuContext != nullptr);
312 int32_t maxResource = 100;
313 size_t maxResourceBytes = 1000;
314 gpuContext->SetResourceCacheLimits(maxResource, maxResourceBytes);
315 }
316
317 /**
318 * @tc.name: ReleaseResourcesAndAbandonContextTest001
319 * @tc.desc: Test for Purging GPU resources that haven't been used in the past 'msNotUsed' milliseconds.
320 * @tc.type: FUNC
321 * @tc.require: I774GD
322 */
323 HWTEST_F(GpuContextTest, ReleaseResourcesAndAbandonContextTest001, TestSize.Level1)
324 {
325 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
326 ASSERT_TRUE(gpuContext != nullptr);
327 gpuContext->ReleaseResourcesAndAbandonContext();
328 }
329
330 /**
331 * @tc.name: PurgeUnlockedResourcesByTagTest001
332 * @tc.desc: Test for Purging GPU resources that haven't been used in the past 'msNotUsed' milliseconds.
333 * @tc.type: FUNC
334 * @tc.require: I774GD
335 */
336 HWTEST_F(GpuContextTest, PurgeUnlockedResourcesByTagTest001, TestSize.Level1)
337 {
338 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
339 ASSERT_TRUE(gpuContext != nullptr);
340 GPUResourceTag tag(0, 0, 0, 0, "PurgeUnlockedResourcesByTagTest001");
341 gpuContext->PurgeUnlockedResourcesByTag(true, tag);
342 }
343
344 /**
345 * @tc.name: ReleaseByTagTest001
346 * @tc.desc: Test for Purging GPU resources that haven't been used in the past 'msNotUsed' milliseconds.
347 * @tc.type: FUNC
348 * @tc.require: I774GD
349 */
350 HWTEST_F(GpuContextTest, ReleaseByTagTest001, TestSize.Level1)
351 {
352 std::unique_ptr<GPUContext> gpuContext = std::make_unique<GPUContext>();
353 ASSERT_TRUE(gpuContext != nullptr);
354 GPUResourceTag tag(0, 0, 0, 0, "ReleaseByTagTest001");
355 gpuContext->ReleaseByTag(tag);
356 }
357
358 } // namespace Drawing
359 } // namespace Rosen
360 } // namespace OHOS
361