• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define EGL_EGLEXT_PROTOTYPES
17 #include "rs_sub_thread.h"
18 
19 #include <string>
20 #include "GLES3/gl3.h"
21 #include "include/core/SkCanvas.h"
22 #include "memory/rs_tag_tracker.h"
23 #include "rs_trace.h"
24 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
25 #include "pipeline/rs_main_thread.h"
26 #include "memory/rs_memory_graphic.h"
27 #include "memory/rs_memory_manager.h"
28 #include "pipeline/rs_uni_render_util.h"
29 #include "pipeline/rs_uni_render_visitor.h"
30 #include "pipeline/rs_surface_render_node.h"
31 #ifdef RES_SCHED_ENABLE
32 #include "res_type.h"
33 #include "res_sched_client.h"
34 #endif
35 
36 #ifdef RS_ENABLE_VK
37 #include "platform/ohos/backend/rs_vulkan_context.h"
38 #endif
39 
40 namespace OHOS::Rosen {
41 namespace {
42 #ifdef RES_SCHED_ENABLE
43     const uint32_t RS_SUB_QOS_LEVEL = 7;
44     constexpr const char* RS_BUNDLE_NAME = "render_service";
45 #endif
46 }
~RSSubThread()47 RSSubThread::~RSSubThread()
48 {
49     RS_LOGI("~RSSubThread():%{public}d", threadIndex_);
50     PostTask([this]() {
51         DestroyShareEglContext();
52     });
53 }
54 
Start()55 pid_t RSSubThread::Start()
56 {
57     RS_LOGI("RSSubThread::Start():%{public}d", threadIndex_);
58     std::string name = "RSSubThread" + std::to_string(threadIndex_);
59     runner_ = AppExecFwk::EventRunner::Create(name);
60     handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
61     pid_t tid;
62     PostSyncTask([&tid]() {
63         tid = gettid();
64     });
65     PostTask([this]() {
66 #ifdef RES_SCHED_ENABLE
67         std::string strBundleName = RS_BUNDLE_NAME;
68         std::string strPid = std::to_string(getpid());
69         std::string strTid = std::to_string(gettid());
70         std::string strQos = std::to_string(RS_SUB_QOS_LEVEL);
71         std::unordered_map<std::string, std::string> mapPayload;
72         mapPayload["pid"] = strPid;
73         mapPayload[strTid] = strQos;
74         mapPayload["bundleName"] = strBundleName;
75         uint32_t type = OHOS::ResourceSchedule::ResType::RES_TYPE_THREAD_QOS_CHANGE;
76         int64_t value = 0;
77         OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, value, mapPayload);
78 #endif
79         grContext_ = CreateShareGrContext();
80     });
81     return tid;
82 }
83 
PostTask(const std::function<void ()> & task,const std::string & name)84 void RSSubThread::PostTask(const std::function<void()>& task, const std::string& name)
85 {
86     if (handler_) {
87         handler_->PostImmediateTask(task, name);
88     }
89 }
90 
PostSyncTask(const std::function<void ()> & task)91 void RSSubThread::PostSyncTask(const std::function<void()>& task)
92 {
93     if (handler_) {
94         handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
95     }
96 }
97 
RemoveTask(const std::string & name)98 void RSSubThread::RemoveTask(const std::string& name)
99 {
100     if (handler_) {
101         handler_->RemoveTask(name);
102     }
103 }
104 
DumpMem(DfxString & log)105 void RSSubThread::DumpMem(DfxString& log)
106 {
107     PostSyncTask([&log, this]() {
108         MemoryManager::DumpDrawingGpuMemory(log, grContext_.get());
109     });
110 }
111 
GetAppGpuMemoryInMB()112 float RSSubThread::GetAppGpuMemoryInMB()
113 {
114     float total = 0.f;
115     PostSyncTask([&total, this]() {
116         total = MemoryManager::GetAppGpuMemoryInMB(grContext_.get());
117     });
118     return total;
119 }
120 
CreateShareEglContext()121 void RSSubThread::CreateShareEglContext()
122 {
123     if (renderContext_ == nullptr) {
124         RS_LOGE("renderContext_ is nullptr");
125         return;
126     }
127 #ifdef RS_ENABLE_GL
128     if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
129         return;
130     }
131     eglShareContext_ = renderContext_->CreateShareContext();
132     if (eglShareContext_ == EGL_NO_CONTEXT) {
133         RS_LOGE("eglShareContext_ is EGL_NO_CONTEXT");
134         return;
135     }
136     if (!eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
137         RS_LOGE("eglMakeCurrent failed");
138         return;
139     }
140 #endif
141 }
142 
DestroyShareEglContext()143 void RSSubThread::DestroyShareEglContext()
144 {
145 #ifdef RS_ENABLE_GL
146     if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
147         return;
148     }
149     if (renderContext_ != nullptr) {
150         eglDestroyContext(renderContext_->GetEGLDisplay(), eglShareContext_);
151         eglShareContext_ = EGL_NO_CONTEXT;
152         eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
153     }
154 #endif
155 }
156 
RenderCache(const std::shared_ptr<RSSuperRenderTask> & threadTask)157 void RSSubThread::RenderCache(const std::shared_ptr<RSSuperRenderTask>& threadTask)
158 {
159     if (threadTask == nullptr || threadTask->GetTaskSize() == 0) {
160         return;
161     }
162     if (grContext_ == nullptr) {
163         grContext_ = CreateShareGrContext();
164         if (grContext_ == nullptr) {
165             RS_LOGI("grContext is null");
166             return;
167         }
168     }
169     auto visitor = std::make_shared<RSUniRenderVisitor>();
170     visitor->SetSubThreadConfig(threadIndex_);
171     visitor->SetFocusedNodeId(RSMainThread::Instance()->GetFocusNodeId(),
172         RSMainThread::Instance()->GetFocusLeashWindowId());
173     auto screenManager = CreateOrGetScreenManager();
174     visitor->SetScreenInfo(screenManager->QueryScreenInfo(screenManager->GetDefaultScreenId()));
175 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
176     bool needRequestVsync = false;
177     while (threadTask->GetTaskSize() > 0) {
178         auto task = threadTask->GetNextRenderTask();
179         if (!task || (task->GetIdx() == 0)) {
180             RS_LOGE("renderTask is nullptr");
181             continue;
182         }
183         auto node = task->GetNode();
184         if (!node) {
185             RS_LOGE("surfaceNode is nullptr");
186             continue;
187         }
188         auto surfaceNodePtr = node->ReinterpretCastTo<RSSurfaceRenderNode>();
189         if (!surfaceNodePtr) {
190             RS_LOGE("RenderCache ReinterpretCastTo fail");
191             continue;
192         }
193         // flag CacheSurfaceProcessed is used for cacheCmdskippedNodes collection in rs_mainThread
194         surfaceNodePtr->SetCacheSurfaceProcessedStatus(CacheProcessStatus::DOING);
195         if (RSMainThread::Instance()->GetFrameCount() != threadTask->GetFrameCount()) {
196             surfaceNodePtr->SetCacheSurfaceProcessedStatus(CacheProcessStatus::WAITING);
197             continue;
198         }
199 
200         RS_TRACE_NAME_FMT("draw cache render node: [%s, %llu]", surfaceNodePtr->GetName().c_str(),
201             surfaceNodePtr->GetId());
202         if (surfaceNodePtr->GetCacheSurface(threadIndex_, true) == nullptr || surfaceNodePtr->NeedInitCacheSurface()) {
203             RSRenderNode::ClearCacheSurfaceFunc func = std::bind(&RSUniRenderUtil::ClearNodeCacheSurface,
204                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
205             surfaceNodePtr->InitCacheSurface(grContext_.get(), func, threadIndex_);
206         }
207 
208         RSTagTracker nodeProcessTracker(grContext_.get(), surfaceNodePtr->GetId(),
209             RSTagTracker::TAGTYPE::TAG_SUB_THREAD);
210         bool needNotify = !surfaceNodePtr->HasCachedTexture();
211         node->Process(visitor);
212         nodeProcessTracker.SetTagEnd();
213 #ifndef USE_ROSEN_DRAWING
214         auto cacheSurface = surfaceNodePtr->GetCacheSurface(threadIndex_, true);
215         if (cacheSurface) {
216             RS_TRACE_NAME_FMT("Render cache skSurface flush and submit");
217             RSTagTracker nodeFlushTracker(grContext_.get(), surfaceNodePtr->GetId(),
218                 RSTagTracker::TAGTYPE::TAG_SUB_THREAD);
219             cacheSurface->flushAndSubmit(true);
220             nodeFlushTracker.SetTagEnd();
221         }
222 #else
223         auto cacheSurface = surfaceNodePtr->GetCacheSurface(threadIndex_, true);
224         if (cacheSurface) {
225             RS_TRACE_NAME_FMT("Render cache skSurface flush and submit");
226             RSTagTracker nodeFlushTracker(grContext_.get(), surfaceNodePtr->GetId(),
227                 RSTagTracker::TAGTYPE::TAG_SUB_THREAD);
228             cacheSurface->FlushAndSubmit(true);
229             nodeFlushTracker.SetTagEnd();
230         }
231 #endif
232         surfaceNodePtr->UpdateBackendTexture();
233         RSMainThread::Instance()->PostTask([]() {
234             RSMainThread::Instance()->SetIsCachedSurfaceUpdated(true);
235         });
236         surfaceNodePtr->SetCacheSurfaceProcessedStatus(CacheProcessStatus::DONE);
237         surfaceNodePtr->SetCacheSurfaceNeedUpdated(true);
238         needRequestVsync = true;
239 
240         if (needNotify) {
241             RSSubThreadManager::Instance()->NodeTaskNotify(node->GetId());
242         }
243     }
244     if (needRequestVsync) {
245         RSMainThread::Instance()->RequestNextVSync();
246     }
247 #endif
248 }
249 
250 #ifndef USE_ROSEN_DRAWING
CreateShareGrContext()251 sk_sp<GrDirectContext> RSSubThread::CreateShareGrContext()
252 {
253     RS_TRACE_NAME("CreateShareGrContext");
254 #ifdef RS_ENABLE_GL
255     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
256         CreateShareEglContext();
257         const GrGLInterface *grGlInterface = GrGLCreateNativeInterface();
258         sk_sp<const GrGLInterface> glInterface(grGlInterface);
259         if (glInterface.get() == nullptr) {
260             RS_LOGE("CreateShareGrContext failed");
261             return nullptr;
262         }
263 
264         GrContextOptions options = {};
265         options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
266         // fix svg antialiasing bug
267         options.fGpuPathRenderers &= ~GpuPathRenderers::kAtlas;
268         options.fPreferExternalImagesOverES3 = true;
269         options.fDisableDistanceFieldPaths = true;
270 
271         auto handler = std::make_shared<MemoryHandler>();
272         auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
273         auto size = glesVersion ? strlen(glesVersion) : 0;
274         handler->ConfigureContext(&options, glesVersion, size);
275 
276         sk_sp<GrDirectContext> grContext = GrDirectContext::MakeGL(std::move(glInterface), options);
277         if (grContext == nullptr) {
278             RS_LOGE("nullptr grContext is null");
279             return nullptr;
280         }
281         return grContext;
282     }
283 #endif
284 
285 #ifdef RS_ENABLE_VK
286     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
287         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
288         sk_sp<GrDirectContext> grContext = GrDirectContext::MakeVulkan(
289             RsVulkanContext::GetSingleton().GetGrVkBackendContext());
290         if (grContext == nullptr) {
291             RS_LOGE("nullptr grContext is null");
292             return nullptr;
293         }
294         return grContext;
295     }
296 #endif
297     return nullptr;
298 }
299 #else
CreateShareGrContext()300 std::shared_ptr<Drawing::GPUContext> RSSubThread::CreateShareGrContext()
301 {
302     RS_TRACE_NAME("CreateShareGrContext");
303 #ifdef RS_ENABLE_GL
304     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
305         CreateShareEglContext();
306         auto gpuContext = std::make_shared<Drawing::GPUContext>();
307         Drawing::GPUContextOptions options;
308         auto handler = std::make_shared<MemoryHandler>();
309         auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
310         auto size = glesVersion ? strlen(glesVersion) : 0;
311         handler->ConfigureContext(&options, glesVersion, size);
312 
313         if (!gpuContext->BuildFromGL(options)) {
314             RS_LOGE("nullptr gpuContext is null");
315             return nullptr;
316         }
317         return gpuContext;
318     }
319 #endif
320 
321 #ifdef RS_ENABLE_VK
322     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
323         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
324         auto gpuContext = std::make_shared<Drawing::GPUContext>();
325         Drawing::GPUContextOptions options;
326         auto handler = std::make_shared<MemoryHandler>();
327         std::string vulkanVersion = RsVulkanContext::GetSingleton().GetVulkanVersion();
328         auto size = vulkanVersion.size();
329         handler->ConfigureContext(&options, vulkanVersion.c_str(), size);
330         if (!gpuContext->BuildFromVK(RsVulkanContext::GetSingleton().GetGrVkBackendContext(), options)) {
331             RS_LOGE("nullptr gpuContext is null");
332             return nullptr;
333         }
334         return gpuContext;
335     }
336 #endif
337     return nullptr;
338 }
339 #endif
340 
ResetGrContext()341 void RSSubThread::ResetGrContext()
342 {
343     RS_TRACE_NAME("ResetGrContext release resource");
344     if (grContext_ == nullptr) {
345         return;
346     }
347 #ifndef USE_ROSEN_DRAWING
348     grContext_->flushAndSubmit(true);
349     grContext_->freeGpuResources();
350 #else
351     grContext_->FlushAndSubmit(true);
352     grContext_->FreeGpuResources();
353 #endif
354 }
355 
ReleaseSurface()356 void RSSubThread::ReleaseSurface()
357 {
358     std::lock_guard<std::mutex> lock(mutex_);
359     while (tmpSurfaces_.size() > 0) {
360         auto tmp = tmpSurfaces_.front();
361         tmpSurfaces_.pop();
362         tmp = nullptr;
363     }
364 }
365 
366 #ifndef USE_ROSEN_DRAWING
AddToReleaseQueue(sk_sp<SkSurface> && surface)367 void RSSubThread::AddToReleaseQueue(sk_sp<SkSurface>&& surface)
368 #else
369 void RSSubThread::AddToReleaseQueue(std::shared_ptr<Drawing::Surface>&& surface)
370 #endif
371 {
372     std::lock_guard<std::mutex> lock(mutex_);
373     tmpSurfaces_.push(std::move(surface));
374 }
375 
CountSubMem(int pid)376 MemoryGraphic RSSubThread::CountSubMem(int pid)
377 {
378     MemoryGraphic memoryGraphic;
379     PostSyncTask([&pid, &memoryGraphic, this]() {
380         memoryGraphic = MemoryManager::CountPidMemory(pid, grContext_.get());
381     });
382     return memoryGraphic;
383 }
384 }
385