• 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     : drGPUContext_(nullptr),
102       surface_(nullptr),
103       nativeWindow_(nullptr),
104       eglDisplay_(EGL_NO_DISPLAY),
105       eglContext_(EGL_NO_CONTEXT),
106       eglSurface_(EGL_NO_SURFACE),
107       config_(nullptr),
108       mHandler_(nullptr)
109 {}
110 
~RenderContext()111 RenderContext::~RenderContext()
112 {
113     if (eglDisplay_ == EGL_NO_DISPLAY) {
114         return;
115     }
116 
117     eglDestroyContext(eglDisplay_, eglContext_);
118     if (pbufferSurface_ != EGL_NO_SURFACE) {
119         eglDestroySurface(eglDisplay_, pbufferSurface_);
120     }
121     eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
122     eglTerminate(eglDisplay_);
123     eglReleaseThread();
124 
125     eglDisplay_ = EGL_NO_DISPLAY;
126     eglContext_ = EGL_NO_CONTEXT;
127     eglSurface_ = EGL_NO_SURFACE;
128     pbufferSurface_ = EGL_NO_SURFACE;
129     drGPUContext_ = nullptr;
130     surface_ = nullptr;
131     mHandler_ = nullptr;
132 }
133 
CreatePbufferSurface()134 void RenderContext::CreatePbufferSurface()
135 {
136     const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
137 
138     if ((extensions != nullptr) &&
139        (!CheckEglExtension(extensions, EGL_KHR_SURFACELESS_CONTEXT)) &&
140        (pbufferSurface_ == EGL_NO_SURFACE)) {
141         EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
142         pbufferSurface_ = eglCreatePbufferSurface(eglDisplay_, config_, attribs);
143         if (pbufferSurface_ == EGL_NO_SURFACE) {
144             LOGE("Failed to create pbuffer surface");
145             return;
146         }
147     }
148 }
149 
InitializeEglContext()150 void RenderContext::InitializeEglContext()
151 {
152     if (IsEglContextReady()) {
153         return;
154     }
155 
156     LOGD("Creating EGLContext!!!");
157     eglDisplay_ = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, NULL);
158     if (eglDisplay_ == EGL_NO_DISPLAY) {
159         LOGW("Failed to create EGLDisplay gl errno : %{public}x", eglGetError());
160         return;
161     }
162 
163     EGLint major, minor;
164     if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {
165         LOGE("Failed to initialize EGLDisplay");
166         return;
167     }
168 
169     if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
170         LOGE("Failed to bind OpenGL ES API");
171         return;
172     }
173 
174     unsigned int ret;
175     EGLint count;
176     EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
177         EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_NONE };
178 
179     ret = eglChooseConfig(eglDisplay_, config_attribs, &config_, 1, &count);
180     if (!(ret && static_cast<unsigned int>(count) >= 1)) {
181         LOGE("Failed to eglChooseConfig");
182         return;
183     }
184 
185     static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE };
186 
187     eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, context_attribs);
188     if (eglContext_ == EGL_NO_CONTEXT) {
189         LOGE("Failed to create egl context %{public}x", eglGetError());
190         return;
191     }
192     CreatePbufferSurface();
193     if (!eglMakeCurrent(eglDisplay_, pbufferSurface_, pbufferSurface_, eglContext_)) {
194         LOGE("Failed to make current on surface, error is %{public}x", eglGetError());
195         return;
196     }
197 
198     LOGD("Create EGL context successfully, version %{public}d.%{public}d", major, minor);
199 }
200 
MakeCurrent(EGLSurface surface,EGLContext context)201 void RenderContext::MakeCurrent(EGLSurface surface, EGLContext context)
202 {
203     if (surface == EGL_NO_SURFACE) {
204         surface = pbufferSurface_;
205     }
206     if (context == EGL_NO_CONTEXT) {
207         context = eglContext_;
208     }
209     if (!eglMakeCurrent(eglDisplay_, surface, surface, context)) {
210         LOGE("Failed to make current on surface, error is %{public}x", eglGetError());
211     }
212     eglSurface_ = surface;
213 }
214 
SetAndMakeCurrentShareContex(EGLContext shareContext)215 void RenderContext::SetAndMakeCurrentShareContex(EGLContext shareContext)
216 {
217     eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, shareContext);
218     eglContext_ = shareContext;
219 }
220 
ShareMakeCurrent(EGLContext shareContext)221 void RenderContext::ShareMakeCurrent(EGLContext shareContext)
222 {
223     eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, shareContext);
224 }
225 
ShareMakeCurrentNoSurface(EGLContext shareContext)226 void RenderContext::ShareMakeCurrentNoSurface(EGLContext shareContext)
227 {
228     eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, shareContext);
229 }
230 
MakeSelfCurrent()231 void RenderContext::MakeSelfCurrent()
232 {
233     eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_);
234 }
235 
CreateShareContext()236 EGLContext RenderContext::CreateShareContext()
237 {
238     std::unique_lock<std::mutex> lock(shareContextMutex_);
239     static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE};
240     auto eglShareContext = eglCreateContext(eglDisplay_, config_, eglContext_, context_attribs);
241     return eglShareContext;
242 }
243 
SwapBuffers(EGLSurface surface) const244 void RenderContext::SwapBuffers(EGLSurface surface) const
245 {
246     RS_TRACE_FUNC();
247     if (!eglSwapBuffers(eglDisplay_, surface)) {
248         LOGE("Failed to SwapBuffers on surface, error is %{public}x", eglGetError());
249     } else {
250         LOGD("SwapBuffers successfully");
251     }
252 }
253 
DestroyEGLSurface(EGLSurface surface)254 void RenderContext::DestroyEGLSurface(EGLSurface surface)
255 {
256     if (!eglDestroySurface(eglDisplay_, surface)) {
257         LOGE("Failed to DestroyEGLSurface surface, error is %{public}x", eglGetError());
258     }
259 }
260 
CreateEGLSurface(EGLNativeWindowType eglNativeWindow)261 EGLSurface RenderContext::CreateEGLSurface(EGLNativeWindowType eglNativeWindow)
262 {
263     if (!IsEglContextReady()) {
264         LOGE("EGL context has not initialized");
265         return EGL_NO_SURFACE;
266     }
267     nativeWindow_ = eglNativeWindow;
268 
269     eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
270 
271     EGLSurface surface = eglCreateWindowSurface(eglDisplay_, config_, nativeWindow_, NULL);
272     if (surface == EGL_NO_SURFACE) {
273         LOGW("Failed to create eglsurface!!! %{public}x", eglGetError());
274         return EGL_NO_SURFACE;
275     }
276 
277     LOGD("CreateEGLSurface");
278 
279     eglSurface_ = surface;
280     return surface;
281 }
282 
SetUpGpuContext(std::shared_ptr<Drawing::GPUContext> drawingContext)283 bool RenderContext::SetUpGpuContext(std::shared_ptr<Drawing::GPUContext> drawingContext)
284 {
285     if (drGPUContext_ != nullptr) {
286         LOGD("Drawing GPUContext has already created!!");
287         return true;
288     }
289 #ifdef RS_ENABLE_GL
290     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
291         mHandler_ = std::make_shared<MemoryHandler>();
292         auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
293         if (isUniRenderMode_) {
294             cacheDir_ = UNIRENDER_CACHE_DIR;
295         }
296         Drawing::GPUContextOptions options;
297         options.SetIsUniRender(isUniRenderMode_);
298         if (glesVersion != nullptr) {
299             auto size = glesVersion ? strlen(glesVersion) : 0;
300             mHandler_->ConfigureContext(&options, glesVersion, size, cacheDir_, isUniRenderMode_);
301         }
302 
303         auto drGPUContext = std::make_shared<Drawing::GPUContext>();
304         if (!drGPUContext->BuildFromGL(options)) {
305             LOGE("SetUpGrContext drGPUContext is null");
306             return false;
307         }
308         drGPUContext_ = std::move(drGPUContext);
309         return true;
310     }
311 #endif
312 #ifdef RS_ENABLE_VK
313     if (RSSystemProperties::IsUseVulkan()) {
314         if (drawingContext == nullptr) {
315             drawingContext = RsVulkanContext::GetSingleton(cacheDir_).CreateDrawingContext();
316         }
317         std::shared_ptr<Drawing::GPUContext> drGPUContext(drawingContext);
318         drGPUContext_ = std::move(drGPUContext);
319         return true;
320     }
321 #endif
322     return false;
323 }
324 
325 #ifdef RS_ENABLE_VK
AbandonContext()326 void RenderContext::AbandonContext()
327 {
328     if (!RSSystemProperties::IsUseVulkan()) {
329         return;
330     }
331     if (drGPUContext_ == nullptr) {
332         LOGD("grContext is nullptr.");
333         return;
334     }
335     drGPUContext_->FlushAndSubmit(true);
336     drGPUContext_->PurgeUnlockAndSafeCacheGpuResources();
337 }
338 #endif
339 
AcquireSurface(int width,int height)340 std::shared_ptr<Drawing::Surface> RenderContext::AcquireSurface(int width, int height)
341 {
342     if (!SetUpGpuContext(nullptr)) {
343         LOGE("GrContext is not ready!!!");
344         return nullptr;
345     }
346 
347     std::shared_ptr<Drawing::ColorSpace> colorSpace = nullptr;
348 
349     switch (colorSpace_) {
350         // [planning] in order to stay consistant with the colorspace used before, we disabled
351         // COLOR_GAMUT_SRGB to let the branch to default, then skColorSpace is set to nullptr
352         case GRAPHIC_COLOR_GAMUT_DISPLAY_P3:
353             colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
354                 Drawing::CMSMatrixType::DCIP3);
355             break;
356         case GRAPHIC_COLOR_GAMUT_ADOBE_RGB:
357             colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
358                 Drawing::CMSMatrixType::ADOBE_RGB);
359             break;
360         case GRAPHIC_COLOR_GAMUT_BT2020:
361             colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
362                 Drawing::CMSMatrixType::REC2020);
363             break;
364         default:
365             break;
366     }
367 
368     RSTagTracker tagTracker(GetSharedDrGPUContext(), RSTagTracker::TAGTYPE::TAG_ACQUIRE_SURFACE);
369 
370     struct Drawing::FrameBuffer bufferInfo;
371     bufferInfo.width = width;
372     bufferInfo.height = height;
373     bufferInfo.FBOID = 0;
374     bufferInfo.Format = GL_RGBA8;
375     bufferInfo.gpuContext = drGPUContext_;
376     bufferInfo.colorSpace = colorSpace;
377     bufferInfo.colorType = Drawing::COLORTYPE_RGBA_8888;
378 
379     if (pixelFormat_ == GRAPHIC_PIXEL_FMT_RGBA_1010102) {
380         bufferInfo.Format = GL_RGB10_A2;
381         bufferInfo.colorType = Drawing::COLORTYPE_RGBA_1010102;
382     }
383 
384     surface_ = std::make_shared<Drawing::Surface>();
385     if (!surface_->Bind(bufferInfo)) {
386         LOGW("surface_ is nullptr");
387         surface_ = nullptr;
388         return nullptr;
389     }
390 
391     LOGD("CreateCanvas successfully!!!");
392     return surface_;
393 }
394 
RenderFrame()395 void RenderContext::RenderFrame()
396 {
397     RS_TRACE_FUNC();
398     // flush commands
399     if (surface_ != nullptr && surface_->GetCanvas() != nullptr) {
400         LOGD("RenderFrame: Canvas");
401         RSTagTracker tagTracker(GetSharedDrGPUContext(), RSTagTracker::TAGTYPE::TAG_RENDER_FRAME);
402         surface_->GetCanvas()->Flush();
403     } else {
404         LOGW("canvas is nullptr!!!");
405     }
406 }
407 
QueryEglBufferAge()408 EGLint RenderContext::QueryEglBufferAge()
409 {
410     if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr)) {
411         LOGE("eglDisplay or eglSurface is nullptr");
412         return EGL_UNKNOWN;
413     }
414     EGLint bufferAge = EGL_UNKNOWN;
415     EGLBoolean ret = eglQuerySurface(eglDisplay_, eglSurface_, EGL_BUFFER_AGE_KHR, &bufferAge);
416     if (ret == EGL_FALSE) {
417         LOGE("eglQuerySurface is failed");
418         return EGL_UNKNOWN;
419     }
420     return bufferAge;
421 }
422 
DamageFrame(int32_t left,int32_t top,int32_t width,int32_t height)423 void RenderContext::DamageFrame(int32_t left, int32_t top, int32_t width, int32_t height)
424 {
425     if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr)) {
426         LOGE("eglDisplay or eglSurface is nullptr");
427         return;
428     }
429     RS_TRACE_FUNC();
430 
431     EGLint rect[4];
432     rect[0] = left;
433     rect[1] = top;
434     rect[2] = width;
435     rect[3] = height;
436 
437     EGLBoolean ret = GetEGLSetDamageRegionKHRFunc()(eglDisplay_, eglSurface_, rect, 1);
438     if (ret == EGL_FALSE) {
439         LOGE("eglSetDamageRegionKHR is failed");
440     }
441 }
442 
DamageFrame(const std::vector<RectI> & rects)443 void RenderContext::DamageFrame(const std::vector<RectI> &rects)
444 {
445     if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr)) {
446         LOGE("eglDisplay or eglSurface is nullptr");
447         return;
448     }
449     RS_TRACE_FUNC();
450 
451     size_t size = rects.size();
452     if (size == 0) {
453         LOGD("invalid rects size");
454         return;
455     }
456 
457     EGLint eglRect[size * 4]; // 4 is size of RectI.
458     int index = 0;
459     for (const RectI& rect : rects) {
460         eglRect[index * 4] = rect.left_; // 4 is size of RectI.
461         eglRect[index * 4 + 1] = rect.top_; // 4 is size of RectI.
462         eglRect[index * 4 + 2] = rect.width_; // 4 is size of RectI, 2 is the index of the width_ subscript.
463         eglRect[index * 4 + 3] = rect.height_; // 4 is size of RectI, 3 is the index of the height_ subscript.
464         index++;
465     }
466 
467     EGLBoolean ret = GetEGLSetDamageRegionKHRFunc()(eglDisplay_, eglSurface_, eglRect, size);
468     if (ret == EGL_FALSE) {
469         LOGE("eglSetDamageRegionKHR is failed");
470     }
471 }
472 
ClearRedundantResources()473 void RenderContext::ClearRedundantResources()
474 {
475     RS_TRACE_FUNC();
476     if (drGPUContext_ != nullptr) {
477         LOGD("grContext clear redundant resources");
478         drGPUContext_->Flush();
479         // GPU resources that haven't been used in the past 10 seconds
480         drGPUContext_->PerformDeferredCleanup(std::chrono::seconds(10));
481     }
482 }
483 
ConvertColorGamutToColorSpace(GraphicColorGamut colorGamut)484 std::shared_ptr<Drawing::ColorSpace> RenderContext::ConvertColorGamutToColorSpace(GraphicColorGamut colorGamut)
485 {
486     std::shared_ptr<Drawing::ColorSpace> colorSpace = nullptr;
487     switch (colorGamut) {
488         // [planning] in order to stay consistant with the colorspace used before, we disabled
489         // GRAPHIC_COLOR_GAMUT_SRGB to let the branch to default, then skColorSpace is set to nullptr
490         case GRAPHIC_COLOR_GAMUT_DISPLAY_P3:
491             colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
492                 Drawing::CMSMatrixType::DCIP3);
493             break;
494         case GRAPHIC_COLOR_GAMUT_ADOBE_RGB:
495             colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
496                 Drawing::CMSMatrixType::ADOBE_RGB);
497             break;
498         case GRAPHIC_COLOR_GAMUT_BT2020:
499             colorSpace = Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB,
500                 Drawing::CMSMatrixType::REC2020);
501             break;
502         default:
503             colorSpace = Drawing::ColorSpace::CreateSRGB();
504             break;
505     }
506 
507     return colorSpace;
508 }
509 
510 #if defined(RS_ENABLE_VK)
CheckShaderCacheOverSoftLimit() const511 bool RenderContext::CheckShaderCacheOverSoftLimit() const
512 {
513     auto& shaderCache = ShaderCache::Instance();
514     if (!shaderCache.IfInitialized()) {
515         LOGE("CheckShaderCacheOverSoftLimit shaderCache not Initialized");
516         return false;
517     }
518     return shaderCache.CheckShaderCacheOverSoftLimit();
519 }
520 #endif
521 
522 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
GetShaderCacheSize() const523 std::string RenderContext::GetShaderCacheSize() const
524 {
525 #ifdef RS_ENABLE_VK
526     if (RSSystemProperties::IsUseVulkan()) {
527         if (RsVulkanContext::GetSingleton().GetMemoryHandler()) {
528             return RsVulkanContext::GetSingleton().GetMemoryHandler()->QuerryShader();
529         }
530     }
531 #else
532     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
533         if (mHandler_) {
534             return mHandler_->QuerryShader();
535         }
536     }
537 #endif
538     LOGD("GetShaderCacheSize no shader cache");
539     return "";
540 }
541 
CleanAllShaderCache() const542 std::string RenderContext::CleanAllShaderCache() const
543 {
544 #ifdef RS_ENABLE_VK
545     if (RSSystemProperties::IsUseVulkan()) {
546         if (RsVulkanContext::GetSingleton().GetMemoryHandler()) {
547             return RsVulkanContext::GetSingleton().GetMemoryHandler()->ClearShader();
548         }
549     }
550 #else
551     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
552         if (mHandler_) {
553             return mHandler_->ClearShader();
554         }
555     }
556 #endif
557     LOGD("CleanAllShaderCache no shader cache");
558     return "";
559 }
560 #endif
561 
GetInstance()562 RenderContextFactory& RenderContextFactory::GetInstance()
563 {
564     static RenderContextFactory rf;
565     return rf;
566 }
567 } // namespace Rosen
568 } // namespace OHOS
569