1 /*
2 * Copyright (c) 2021 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 <sstream>
19 #include <string>
20
21 #include "rs_trace.h"
22 #include "window.h"
23
24 #ifdef RS_ENABLE_VK
25 #include "platform/ohos/backend/rs_vulkan_context.h"
26 #endif
27
28 #ifdef RS_ENABLE_GL
29 #include "EGL/egl.h"
30 #endif
31
32 #include "memory/rs_tag_tracker.h"
33
34 #include "render_context_log.h"
35
36 namespace OHOS {
37 namespace Rosen {
38 using GetPlatformDisplayExt = PFNEGLGETPLATFORMDISPLAYEXTPROC;
39 constexpr const char* EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland";
40 constexpr const char* EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland";
41 constexpr int32_t EGL_CONTEXT_CLIENT_VERSION_NUM = 2;
42 constexpr char CHARACTER_WHITESPACE = ' ';
43 constexpr const char* CHARACTER_STRING_WHITESPACE = " ";
44 constexpr const char* EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT";
45 constexpr const char* EGL_KHR_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
46
47 // use functor to call gel*KHR API
GetEGLSetDamageRegionKHRFunc()48 static PFNEGLSETDAMAGEREGIONKHRPROC GetEGLSetDamageRegionKHRFunc()
49 {
50 static auto func = reinterpret_cast<PFNEGLSETDAMAGEREGIONKHRPROC>(eglGetProcAddress("eglSetDamageRegionKHR"));
51 return func;
52 }
53
CheckEglExtension(const char * extensions,const char * extension)54 static bool CheckEglExtension(const char* extensions, const char* extension)
55 {
56 size_t extlen = strlen(extension);
57 const char* end = extensions + strlen(extensions);
58
59 while (extensions < end) {
60 size_t n = 0;
61 /* Skip whitespaces, if any */
62 if (*extensions == CHARACTER_WHITESPACE) {
63 extensions++;
64 continue;
65 }
66
67 n = strcspn(extensions, CHARACTER_STRING_WHITESPACE);
68
69 /* Compare strings */
70 if (n == extlen && strncmp(extension, extensions, n) == 0) {
71 return true; /* Found */
72 }
73 extensions += n;
74 }
75 /* Not found */
76 return false;
77 }
78
GetPlatformEglDisplay(EGLenum platform,void * native_display,const EGLint * attrib_list)79 static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void* native_display, const EGLint* attrib_list)
80 {
81 static GetPlatformDisplayExt eglGetPlatformDisplayExt = NULL;
82
83 if (!eglGetPlatformDisplayExt) {
84 const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
85 if (extensions &&
86 (CheckEglExtension(extensions, EGL_EXT_PLATFORM_WAYLAND) ||
87 CheckEglExtension(extensions, EGL_KHR_PLATFORM_WAYLAND))) {
88 eglGetPlatformDisplayExt = reinterpret_cast<GetPlatformDisplayExt>(
89 eglGetProcAddress(EGL_GET_PLATFORM_DISPLAY_EXT));
90 }
91 }
92
93 if (eglGetPlatformDisplayExt) {
94 return eglGetPlatformDisplayExt(platform, native_display, attrib_list);
95 }
96
97 return eglGetDisplay(static_cast<EGLNativeDisplayType>(native_display));
98 }
99
RenderContext()100 RenderContext::RenderContext()
101 #ifndef USE_ROSEN_DRAWING
102 : grContext_(nullptr),
103 skSurface_(nullptr),
104 #else
105 : drGPUContext_(nullptr),
106 surface_(nullptr),
107 #endif
108 nativeWindow_(nullptr),
109 eglDisplay_(EGL_NO_DISPLAY),
110 eglContext_(EGL_NO_CONTEXT),
111 eglSurface_(EGL_NO_SURFACE),
112 config_(nullptr),
113 mHandler_(nullptr)
114 {}
115
~RenderContext()116 RenderContext::~RenderContext()
117 {
118 if (eglDisplay_ == EGL_NO_DISPLAY) {
119 return;
120 }
121
122 eglDestroyContext(eglDisplay_, eglContext_);
123 if (pbufferSurface_ != EGL_NO_SURFACE) {
124 eglDestroySurface(eglDisplay_, pbufferSurface_);
125 }
126 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
127 eglTerminate(eglDisplay_);
128 eglReleaseThread();
129
130 eglDisplay_ = EGL_NO_DISPLAY;
131 eglContext_ = EGL_NO_CONTEXT;
132 eglSurface_ = EGL_NO_SURFACE;
133 pbufferSurface_ = EGL_NO_SURFACE;
134 #ifndef USE_ROSEN_DRAWING
135 grContext_ = nullptr;
136 skSurface_ = nullptr;
137 #else
138 drGPUContext_ = nullptr;
139 surface_ = nullptr;
140 #endif
141 mHandler_ = nullptr;
142 }
143
CreatePbufferSurface()144 void RenderContext::CreatePbufferSurface()
145 {
146 const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
147
148 if ((extensions != nullptr) &&
149 (!CheckEglExtension(extensions, EGL_KHR_SURFACELESS_CONTEXT)) &&
150 (pbufferSurface_ == EGL_NO_SURFACE)) {
151 EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
152 pbufferSurface_ = eglCreatePbufferSurface(eglDisplay_, config_, attribs);
153 if (pbufferSurface_ == EGL_NO_SURFACE) {
154 LOGE("Failed to create pbuffer surface");
155 return;
156 }
157 }
158 }
159
InitializeEglContext()160 void RenderContext::InitializeEglContext()
161 {
162 if (IsEglContextReady()) {
163 return;
164 }
165
166 LOGD("Creating EGLContext!!!");
167 eglDisplay_ = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, NULL);
168 if (eglDisplay_ == EGL_NO_DISPLAY) {
169 LOGW("Failed to create EGLDisplay gl errno : %{public}x", eglGetError());
170 return;
171 }
172
173 EGLint major, minor;
174 if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {
175 LOGE("Failed to initialize EGLDisplay");
176 return;
177 }
178
179 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
180 LOGE("Failed to bind OpenGL ES API");
181 return;
182 }
183
184 unsigned int ret;
185 EGLint count;
186 EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
187 EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_NONE };
188
189 ret = eglChooseConfig(eglDisplay_, config_attribs, &config_, 1, &count);
190 if (!(ret && static_cast<unsigned int>(count) >= 1)) {
191 LOGE("Failed to eglChooseConfig");
192 return;
193 }
194
195 static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE };
196
197 eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, context_attribs);
198 if (eglContext_ == EGL_NO_CONTEXT) {
199 LOGE("Failed to create egl context %{public}x", eglGetError());
200 return;
201 }
202 CreatePbufferSurface();
203 if (!eglMakeCurrent(eglDisplay_, pbufferSurface_, pbufferSurface_, eglContext_)) {
204 LOGE("Failed to make current on surface, error is %{public}x", eglGetError());
205 return;
206 }
207
208 LOGD("Create EGL context successfully, version %{public}d.%{public}d", major, minor);
209 }
210
MakeCurrent(EGLSurface surface,EGLContext context)211 void RenderContext::MakeCurrent(EGLSurface surface, EGLContext context)
212 {
213 if (surface == EGL_NO_SURFACE) {
214 surface = pbufferSurface_;
215 }
216 if (context == EGL_NO_CONTEXT) {
217 context = eglContext_;
218 }
219 if (!eglMakeCurrent(eglDisplay_, surface, surface, context)) {
220 LOGE("Failed to make current on surface, error is %{public}x", eglGetError());
221 }
222 eglSurface_ = surface;
223 }
224
SetAndMakeCurrentShareContex(EGLContext shareContext)225 void RenderContext::SetAndMakeCurrentShareContex(EGLContext shareContext)
226 {
227 eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, shareContext);
228 eglContext_ = shareContext;
229 }
230
ShareMakeCurrent(EGLContext shareContext)231 void RenderContext::ShareMakeCurrent(EGLContext shareContext)
232 {
233 eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, shareContext);
234 }
235
ShareMakeCurrentNoSurface(EGLContext shareContext)236 void RenderContext::ShareMakeCurrentNoSurface(EGLContext shareContext)
237 {
238 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, shareContext);
239 }
240
MakeSelfCurrent()241 void RenderContext::MakeSelfCurrent()
242 {
243 eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_);
244 }
245
CreateShareContext()246 EGLContext RenderContext::CreateShareContext()
247 {
248 std::unique_lock<std::mutex> lock(shareContextMutex_);
249 static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE};
250 auto eglShareContext = eglCreateContext(eglDisplay_, config_, eglContext_, context_attribs);
251 return eglShareContext;
252 }
253
SwapBuffers(EGLSurface surface) const254 void RenderContext::SwapBuffers(EGLSurface surface) const
255 {
256 RS_TRACE_FUNC();
257 if (!eglSwapBuffers(eglDisplay_, surface)) {
258 LOGE("Failed to SwapBuffers on surface, error is %{public}x", eglGetError());
259 } else {
260 LOGD("SwapBuffers successfully");
261 }
262 }
263
DestroyEGLSurface(EGLSurface surface)264 void RenderContext::DestroyEGLSurface(EGLSurface surface)
265 {
266 if (!eglDestroySurface(eglDisplay_, surface)) {
267 LOGE("Failed to DestroyEGLSurface surface, error is %{public}x", eglGetError());
268 }
269 }
270
CreateEGLSurface(EGLNativeWindowType eglNativeWindow)271 EGLSurface RenderContext::CreateEGLSurface(EGLNativeWindowType eglNativeWindow)
272 {
273 if (!IsEglContextReady()) {
274 LOGE("EGL context has not initialized");
275 return EGL_NO_SURFACE;
276 }
277 nativeWindow_ = eglNativeWindow;
278
279 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
280
281 EGLSurface surface = eglCreateWindowSurface(eglDisplay_, config_, nativeWindow_, NULL);
282 if (surface == EGL_NO_SURFACE) {
283 LOGW("Failed to create eglsurface!!! %{public}x", eglGetError());
284 return EGL_NO_SURFACE;
285 }
286
287 LOGD("CreateEGLSurface");
288
289 eglSurface_ = surface;
290 return surface;
291 }
292
293 #ifndef USE_ROSEN_DRAWING
294 #ifdef RS_ENABLE_GL
InitGrContextOptions(GrContextOptions & options)295 void RenderContext::InitGrContextOptions(GrContextOptions &options)
296 {
297 if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
298 return;
299 }
300 options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
301 // fix svg antialiasing bug
302 options.fGpuPathRenderers &= ~GpuPathRenderers::kAtlas;
303 options.fPreferExternalImagesOverES3 = true;
304 options.fDisableDistanceFieldPaths = true;
305
306 // Advanced Filter
307 options.fProcessName = "render_service";
308 }
309 #endif
310
SetUpGrContext(sk_sp<GrDirectContext> skContext)311 bool RenderContext::SetUpGrContext(sk_sp<GrDirectContext> skContext)
312 {
313 if (grContext_ != nullptr) {
314 LOGD("grContext has already created!!");
315 return true;
316 }
317 #ifdef RS_ENABLE_GL
318 (void)skContext;
319 if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
320 RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
321 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
322 if (glInterface.get() == nullptr) {
323 LOGE("SetUpGrContext failed to make native interface");
324 return false;
325 }
326
327 GrContextOptions options;
328 InitGrContextOptions(options);
329 mHandler_ = std::make_shared<MemoryHandler>();
330 auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
331 auto size = glesVersion ? strlen(glesVersion) : 0;
332 if (isUniRenderMode_) {
333 cacheDir_ = UNIRENDER_CACHE_DIR;
334 }
335 mHandler_->ConfigureContext(&options, glesVersion, size, cacheDir_, isUniRenderMode_);
336
337 #if defined(NEW_SKIA)
338 sk_sp<GrDirectContext> grContext(GrDirectContext::MakeGL(std::move(glInterface), options));
339 #else
340 sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
341 #endif
342 if (grContext == nullptr) {
343 LOGE("SetUpGrContext grContext is null");
344 return false;
345 }
346 grContext_ = std::move(grContext);
347 return true;
348 }
349 #endif
350
351 #ifdef RS_ENABLE_VK
352 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
353 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
354 if (skContext == nullptr) {
355 skContext = RsVulkanContext::GetSingleton().CreateSkContext();
356 }
357 sk_sp<GrDirectContext> grContext(skContext);
358 if (grContext == nullptr) {
359 LOGE("SetUpGrContext grContext is null");
360 return false;
361 }
362 grContext_ = std::move(grContext);
363 return true;
364 }
365 #endif
366 return false;
367 }
368 #else
SetUpGpuContext(std::shared_ptr<Drawing::GPUContext> drawingContext)369 bool RenderContext::SetUpGpuContext(std::shared_ptr<Drawing::GPUContext> drawingContext)
370 {
371 if (drGPUContext_ != nullptr) {
372 LOGD("Drawing GPUContext has already created!!");
373 return true;
374 }
375 #ifdef RS_ENABLE_GL
376 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
377 mHandler_ = std::make_shared<MemoryHandler>();
378 auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
379 if (isUniRenderMode_) {
380 cacheDir_ = UNIRENDER_CACHE_DIR;
381 }
382 Drawing::GPUContextOptions options;
383 auto size = glesVersion ? strlen(glesVersion) : 0;
384 mHandler_->ConfigureContext(&options, glesVersion, size, cacheDir_, isUniRenderMode_);
385
386 auto drGPUContext = std::make_shared<Drawing::GPUContext>();
387 if (!drGPUContext->BuildFromGL(options)) {
388 LOGE("SetUpGrContext drGPUContext is null");
389 return false;
390 }
391 drGPUContext_ = std::move(drGPUContext);
392 return true;
393 }
394 #endif
395 #ifdef RS_ENABLE_VK
396 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
397 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
398 if (drawingContext == nullptr) {
399 drawingContext = RsVulkanContext::GetSingleton().CreateDrawingContext();
400 }
401 std::shared_ptr<Drawing::GPUContext> drGPUContext(drawingContext);
402 drGPUContext_ = std::move(drGPUContext);
403 return true;
404 }
405 #endif
406 return false;
407 }
408 #endif
409
410 #ifdef RS_ENABLE_VK
AbandonContext()411 void RenderContext::AbandonContext()
412 {
413 if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
414 RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
415 return;
416 }
417 #ifndef USE_ROSEN_DRAWING
418 if (grContext_ == nullptr) {
419 #else
420 if (drGPUContext_ == nullptr) {
421 #endif
422 LOGD("grContext is nullptr.");
423 return;
424 }
425 #ifndef USE_ROSEN_DRAWING
426 grContext_->flushAndSubmit(true);
427 grContext_->purgeUnlockAndSafeCacheGpuResources();
428 #else
429 drGPUContext_->FlushAndSubmit(true);
430 drGPUContext_->PurgeUnlockAndSafeCacheGpuResources();
431 #endif
432 }
433 #endif
434
435 #ifndef USE_ROSEN_DRAWING
436 sk_sp<SkSurface> RenderContext::AcquireSurface(int width, int height)
437 {
438 if (!SetUpGrContext(nullptr)) {
439 LOGE("GrContext is not ready!!!");
440 return nullptr;
441 }
442
443 GrGLFramebufferInfo framebufferInfo;
444 framebufferInfo.fFBOID = 0;
445 framebufferInfo.fFormat = GL_RGBA8;
446 SkColorType colorType = kRGBA_8888_SkColorType;
447
448 if (pixelFormat_ == GRAPHIC_PIXEL_FMT_RGBA_1010102) {
449 framebufferInfo.fFormat = GL_RGB10_A2;
450 colorType = kRGBA_1010102_SkColorType;
451 }
452
453 GrBackendRenderTarget backendRenderTarget(width, height, 0, 8, framebufferInfo);
454 #if defined(NEW_SKIA)
455 SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry);
456 #else
457 SkSurfaceProps surfaceProps = SkSurfaceProps::kLegacyFontHost_InitType;
458 #endif
459
460 sk_sp<SkColorSpace> skColorSpace = ConvertColorGamutToSkColorSpace(colorSpace_);
461
462 RSTagTracker tagTracker(GetGrContext(), RSTagTracker::TAGTYPE::TAG_ACQUIRE_SURFACE);
463
464 skSurface_ = SkSurface::MakeFromBackendRenderTarget(
465 GetGrContext(), backendRenderTarget, kBottomLeft_GrSurfaceOrigin, colorType, skColorSpace, &surfaceProps);
466 if (skSurface_ == nullptr) {
467 LOGW("skSurface is nullptr");
468 return nullptr;
469 }
470
471 LOGD("CreateCanvas successfully!!!");
472 return skSurface_;
473 }
474 #else
475 std::shared_ptr<Drawing::Surface> RenderContext::AcquireSurface(int width, int height)
476 {
477 if (!SetUpGpuContext(nullptr)) {
478 LOGE("GrContext is not ready!!!");
479 return nullptr;
480 }
481
482 std::shared_ptr<Drawing::ColorSpace> colorSpace = nullptr;
483
484 switch (colorSpace_) {
485 // [planning] in order to stay consistant with the colorspace used before, we disabled
486 // COLOR_GAMUT_SRGB to let the branch to default, then skColorSpace is set to nullptr
487 case GRAPHIC_COLOR_GAMUT_DISPLAY_P3:
488 colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
489 Drawing::CMSMatrixType::DCIP3);
490 break;
491 case GRAPHIC_COLOR_GAMUT_ADOBE_RGB:
492 colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
493 Drawing::CMSMatrixType::ADOBE_RGB);
494 break;
495 case GRAPHIC_COLOR_GAMUT_BT2020:
496 colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
497 Drawing::CMSMatrixType::REC2020);
498 break;
499 default:
500 break;
501 }
502
503 RSTagTracker tagTracker(GetDrGPUContext(), RSTagTracker::TAGTYPE::TAG_ACQUIRE_SURFACE);
504
505 struct Drawing::FrameBuffer bufferInfo;
506 bufferInfo.width = width;
507 bufferInfo.height = height;
508 bufferInfo.FBOID = 0;
509 bufferInfo.Format = GL_RGBA8;
510 bufferInfo.gpuContext = drGPUContext_;
511 bufferInfo.colorSpace = colorSpace;
512 bufferInfo.colorType = Drawing::COLORTYPE_RGBA_8888;
513
514 if (pixelFormat_ == GRAPHIC_PIXEL_FMT_RGBA_1010102) {
515 bufferInfo.Format = GL_RGB10_A2;
516 bufferInfo.colorType = Drawing::COLORTYPE_RGBA_1010102;
517 }
518
519 surface_ = std::make_shared<Drawing::Surface>();
520 if (!surface_->Bind(bufferInfo)) {
521 LOGW("surface_ is nullptr");
522 surface_ = nullptr;
523 return nullptr;
524 }
525
526 LOGD("CreateCanvas successfully!!!");
527 return surface_;
528 }
529 #endif
530
531 void RenderContext::RenderFrame()
532 {
533 RS_TRACE_FUNC();
534 // flush commands
535 #ifndef USE_ROSEN_DRAWING
536 if (skSurface_->getCanvas() != nullptr) {
537 LOGD("RenderFrame: Canvas");
538 RSTagTracker tagTracker(GetGrContext(), RSTagTracker::TAGTYPE::TAG_RENDER_FRAME);
539 skSurface_->getCanvas()->flush();
540 #else
541 if (surface_ != nullptr && surface_->GetCanvas() != nullptr) {
542 LOGD("RenderFrame: Canvas");
543 RSTagTracker tagTracker(GetDrGPUContext(), RSTagTracker::TAGTYPE::TAG_RENDER_FRAME);
544 surface_->GetCanvas()->Flush();
545 #endif
546 } else {
547 LOGW("canvas is nullptr!!!");
548 }
549 }
550
551 EGLint RenderContext::QueryEglBufferAge()
552 {
553 if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr)) {
554 LOGE("eglDisplay or eglSurface is nullptr");
555 return EGL_UNKNOWN;
556 }
557 EGLint bufferAge = EGL_UNKNOWN;
558 EGLBoolean ret = eglQuerySurface(eglDisplay_, eglSurface_, EGL_BUFFER_AGE_KHR, &bufferAge);
559 if (ret == EGL_FALSE) {
560 LOGE("eglQuerySurface is failed");
561 return EGL_UNKNOWN;
562 }
563 return bufferAge;
564 }
565
566 void RenderContext::DamageFrame(int32_t left, int32_t top, int32_t width, int32_t height)
567 {
568 if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr)) {
569 LOGE("eglDisplay or eglSurface is nullptr");
570 return;
571 }
572 RS_TRACE_FUNC();
573
574 EGLint rect[4];
575 rect[0] = left;
576 rect[1] = top;
577 rect[2] = width;
578 rect[3] = height;
579
580 EGLBoolean ret = GetEGLSetDamageRegionKHRFunc()(eglDisplay_, eglSurface_, rect, 1);
581 if (ret == EGL_FALSE) {
582 LOGE("eglSetDamageRegionKHR is failed");
583 }
584 }
585
586 void RenderContext::DamageFrame(const std::vector<RectI> &rects)
587 {
588 if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr)) {
589 LOGE("eglDisplay or eglSurface is nullptr");
590 return;
591 }
592 RS_TRACE_FUNC();
593
594 size_t size = rects.size();
595 if (size == 0) {
596 LOGD("invalid rects size");
597 return;
598 }
599
600 EGLint eglRect[size * 4]; // 4 is size of RectI.
601 int index = 0;
602 for (const RectI& rect : rects) {
603 eglRect[index * 4] = rect.left_; // 4 is size of RectI.
604 eglRect[index * 4 + 1] = rect.top_; // 4 is size of RectI.
605 eglRect[index * 4 + 2] = rect.width_; // 4 is size of RectI, 2 is the index of the width_ subscript.
606 eglRect[index * 4 + 3] = rect.height_; // 4 is size of RectI, 3 is the index of the height_ subscript.
607 index++;
608 }
609
610 EGLBoolean ret = GetEGLSetDamageRegionKHRFunc()(eglDisplay_, eglSurface_, eglRect, size);
611 if (ret == EGL_FALSE) {
612 LOGE("eglSetDamageRegionKHR is failed");
613 }
614 }
615
616 void RenderContext::ClearRedundantResources()
617 {
618 RS_TRACE_FUNC();
619 #ifndef USE_ROSEN_DRAWING
620 if (grContext_ != nullptr) {
621 LOGD("grContext clear redundant resources");
622 grContext_->flush();
623 // GPU resources that haven't been used in the past 10 seconds
624 grContext_->purgeResourcesNotUsedInMs(std::chrono::seconds(10));
625 }
626 #else
627 if (drGPUContext_ != nullptr) {
628 LOGD("grContext clear redundant resources");
629 drGPUContext_->Flush();
630 // GPU resources that haven't been used in the past 10 seconds
631 drGPUContext_->PerformDeferredCleanup(std::chrono::seconds(10));
632 }
633 #endif
634 }
635
636 sk_sp<SkColorSpace> RenderContext::ConvertColorGamutToSkColorSpace(GraphicColorGamut colorGamut)
637 {
638 sk_sp<SkColorSpace> skColorSpace = nullptr;
639 switch (colorGamut) {
640 // [planning] in order to stay consistant with the colorspace used before, we disabled
641 // GRAPHIC_COLOR_GAMUT_SRGB to let the branch to default, then skColorSpace is set to nullptr
642 case GRAPHIC_COLOR_GAMUT_DISPLAY_P3:
643 #if defined(NEW_SKIA)
644 skColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3);
645 #else
646 skColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
647 #endif
648 break;
649 case GRAPHIC_COLOR_GAMUT_ADOBE_RGB:
650 skColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kAdobeRGB);
651 break;
652 case GRAPHIC_COLOR_GAMUT_BT2020:
653 skColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kRec2020);
654 break;
655 default:
656 break;
657 }
658
659 return skColorSpace;
660 }
661
662 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
663 std::string RenderContext::GetShaderCacheSize() const
664 {
665 #ifdef RS_ENABLE_VK
666 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
667 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
668 if (RsVulkanContext::GetSingleton().GetMemoryHandler()) {
669 return RsVulkanContext::GetSingleton().GetMemoryHandler()->QuerryShader();
670 }
671 }
672 #else
673 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
674 if (mHandler_) {
675 return mHandler_->QuerryShader();
676 }
677 }
678 #endif
679 LOGD("GetShaderCacheSize no shader cache");
680 return "";
681 }
682
683 std::string RenderContext::CleanAllShaderCache() const
684 {
685 #ifdef RS_ENABLE_VK
686 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
687 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
688 if (RsVulkanContext::GetSingleton().GetMemoryHandler()) {
689 return RsVulkanContext::GetSingleton().GetMemoryHandler()->ClearShader();
690 }
691 }
692 #else
693 if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
694 if (mHandler_) {
695 return mHandler_->ClearShader();
696 }
697 }
698 #endif
699 LOGD("CleanAllShaderCache no shader cache");
700 return "";
701 }
702 #endif
703
704 RenderContextFactory& RenderContextFactory::GetInstance()
705 {
706 static RenderContextFactory rf;
707 return rf;
708 }
709 } // namespace Rosen
710 } // namespace OHOS
711