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