1 /*
2 * Copyright (c) 2025 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
17 #include "rs_sub_thread_cache.h"
18
19 #include <memory>
20
21 #include "impl_interface/region_impl.h"
22 #include "rs_trace.h"
23
24 #include "common/rs_color.h"
25 #include "common/rs_common_def.h"
26 #include "common/rs_obj_abs_geometry.h"
27 #include "common/rs_optional_trace.h"
28 #include "draw/brush.h"
29 #include "drawable/rs_surface_render_node_drawable.h"
30 #include "feature/uifirst/rs_sub_thread_manager.h"
31 #include "feature/uifirst/rs_uifirst_manager.h"
32 #include "memory/rs_tag_tracker.h"
33 #include "params/rs_screen_render_params.h"
34 #include "params/rs_surface_render_params.h"
35 #include "pipeline/render_thread/rs_uni_render_thread.h"
36 #include "pipeline/render_thread/rs_uni_render_util.h"
37 #include "pipeline/main_thread/rs_main_thread.h"
38 #include "pipeline/rs_paint_filter_canvas.h"
39 #include "pipeline/rs_surface_render_node.h"
40 #include "pipeline/sk_resource_manager.h"
41 #include "platform/common/rs_log.h"
42 #include "render/rs_drawing_filter.h"
43 #include "rs_profiler.h"
44 #include "rs_frame_report.h"
45 #include "utils/rect.h"
46 #include "utils/region.h"
47 #ifdef RS_ENABLE_VK
48 #ifdef USE_M133_SKIA
49 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
50 #else
51 #include "include/gpu/GrBackendSurface.h"
52 #endif
53 #include "platform/ohos/backend/native_buffer_utils.h"
54 #include "platform/ohos/backend/rs_vulkan_context.h"
55 #endif
56
57 #undef LOG_TAG
58 #define LOG_TAG "RsSubThreadCache"
59
60 namespace {
__anon4cca00ee0202() 61 static const OHOS::Rosen::Drawing::Matrix IDENTITY_MATRIX = []() {
62 OHOS::Rosen::Drawing::Matrix matrix;
63 matrix.SetMatrix(1.0f, 0.0f, 0.0f,
64 0.0f, 1.0f, 0.0f,
65 0.0f, 0.0f, 1.0f);
66 return matrix;
67 }();
68 constexpr float SCALE_DIFF = 0.01f;
69 }
70
71 namespace OHOS::Rosen::DrawableV2 {
RsSubThreadCache()72 RsSubThreadCache::RsSubThreadCache()
73 : syncUifirstDirtyManager_(std::make_shared<RSDirtyRegionManager>())
74 {}
75
BufferFormatNeedUpdate(std::shared_ptr<Drawing::Surface> cacheSurface,bool isNeedFP16)76 bool RsSubThreadCache::BufferFormatNeedUpdate(std::shared_ptr<Drawing::Surface> cacheSurface,
77 bool isNeedFP16)
78 {
79 bool bufferFormatNeedUpdate = cacheSurface ? isNeedFP16 &&
80 cacheSurface->GetImageInfo().GetColorType() != Drawing::ColorType::COLORTYPE_RGBA_F16 : false;
81 RS_LOGD("BufferFormatNeedUpdate: %{public}d", bufferFormatNeedUpdate);
82 return bufferFormatNeedUpdate;
83 }
84
GetCacheSurfaceProcessedStatus() const85 CacheProcessStatus RsSubThreadCache::GetCacheSurfaceProcessedStatus() const
86 {
87 return uiFirstParams.cacheProcessStatus_.load();
88 }
89
SetCacheSurfaceProcessedStatus(CacheProcessStatus cacheProcessStatus)90 void RsSubThreadCache::SetCacheSurfaceProcessedStatus(CacheProcessStatus cacheProcessStatus)
91 {
92 if (cacheProcessStatus == CacheProcessStatus::DONE || cacheProcessStatus == CacheProcessStatus::SKIPPED) {
93 RSUiFirstProcessStateCheckerHelper::NotifyAll([this, cacheProcessStatus] {
94 uiFirstParams.cacheProcessStatus_.store(cacheProcessStatus);
95 });
96 } else {
97 uiFirstParams.cacheProcessStatus_.store(cacheProcessStatus);
98 }
99 }
100
GetCacheSurface(uint32_t threadIndex)101 std::shared_ptr<Drawing::Surface> RsSubThreadCache::GetCacheSurface(uint32_t threadIndex)
102 {
103 if (cacheSurfaceThreadIndex_ == threadIndex) {
104 return cacheSurface_;
105 }
106 return nullptr;
107 }
108
ClearCacheSurfaceInThread()109 void RsSubThreadCache::ClearCacheSurfaceInThread()
110 {
111 RS_TRACE_NAME_FMT("ClearCacheSurfaceInThread id:%" PRIu64, nodeId_);
112 RS_LOGI("ClearCacheSurfaceInThread id:%{public}" PRIu64, nodeId_);
113 std::scoped_lock<std::recursive_mutex> lock(completeResourceMutex_);
114 if (clearCacheSurfaceFunc_) {
115 clearCacheSurfaceFunc_(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
116 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
117 }
118 ClearCacheSurface();
119 }
120
ClearCacheSurfaceOnly()121 void RsSubThreadCache::ClearCacheSurfaceOnly()
122 {
123 RS_TRACE_NAME_FMT("ClearCacheSurfaceOnly id:%" PRIu64, nodeId_);
124 RS_LOGI("ClearCacheSurfaceOnly id:%{public}" PRIu64, nodeId_);
125 if (cacheSurface_ == nullptr) {
126 return;
127 }
128 if (clearCacheSurfaceFunc_) {
129 clearCacheSurfaceFunc_(
130 std::move(cacheSurface_), nullptr, cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
131 }
132 ClearCacheSurface(false);
133 cacheSurface_.reset();
134 }
135
GetCompletedImage(RSPaintFilterCanvas & canvas,uint32_t threadIndex,bool isUIFirst)136 std::shared_ptr<Drawing::Image> RsSubThreadCache::GetCompletedImage(
137 RSPaintFilterCanvas& canvas, uint32_t threadIndex, bool isUIFirst)
138 {
139 auto gpuContext = canvas.GetGPUContext();
140 if (!gpuContext) {
141 RS_LOGE("GetCompletedImage GetGPUContext nullptr");
142 return nullptr;
143 }
144 if (isUIFirst) {
145 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
146 std::scoped_lock<std::recursive_mutex> lock(completeResourceMutex_);
147 if (!cacheCompletedBackendTexture_.IsValid()) {
148 RS_LOGE("GetCompletedImage invalid grBackendTexture_");
149 return nullptr;
150 }
151 auto colorType = Drawing::COLORTYPE_RGBA_8888;
152 #ifdef RS_ENABLE_VK
153 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
154 OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
155 if (!cacheCompletedSurface_ || !cacheCompletedCleanupHelper_) {
156 RS_LOGE("GetCompletedImage %{public}s is nullptr",
157 cacheCompletedSurface_ == nullptr ? "surface" : "cleanupHelper");
158 return nullptr;
159 }
160 }
161 auto vkTexture = cacheCompletedBackendTexture_.GetTextureInfo().GetVKTextureInfo();
162 // When the colorType is FP16, the colorspace of the uifirst buffer must be sRGB
163 // In other cases, ensure the image's color space matches the target surface's color profile.
164 auto colorSpace = Drawing::ColorSpace::CreateSRGB();
165 if (vkTexture != nullptr && vkTexture->format == VK_FORMAT_R16G16B16A16_SFLOAT) {
166 colorType = Drawing::ColorType::COLORTYPE_RGBA_F16;
167 } else if (cacheCompletedSurface_) {
168 colorSpace = cacheCompletedSurface_->GetImageInfo().GetColorSpace();
169 }
170 #endif
171 auto image = std::make_shared<Drawing::Image>();
172 Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
173 Drawing::BitmapFormat info = Drawing::BitmapFormat{ colorType,
174 Drawing::ALPHATYPE_PREMUL };
175 #ifdef RS_ENABLE_GL
176 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
177 OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
178 image->BuildFromTexture(*gpuContext, cacheCompletedBackendTexture_.GetTextureInfo(),
179 origin, info, nullptr);
180 }
181 #endif
182
183 #ifdef RS_ENABLE_VK
184 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
185 OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
186 image->BuildFromTexture(*gpuContext, cacheCompletedBackendTexture_.GetTextureInfo(),
187 origin, info, colorSpace, NativeBufferUtils::DeleteVkImage, cacheCompletedCleanupHelper_->Ref());
188 }
189 #endif
190 return image;
191 #endif
192 }
193
194 if (!cacheCompletedSurface_) {
195 RS_LOGE("GetCompletedImage invalid cacheCompletedSurface");
196 return nullptr;
197 }
198 auto completeImage = cacheCompletedSurface_->GetImageSnapshot();
199 if (!completeImage) {
200 RS_LOGE("GetCompletedImage Get complete image failed");
201 return nullptr;
202 }
203 if (threadIndex == completedSurfaceThreadIndex_) {
204 return completeImage;
205 }
206 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
207 Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
208 auto backendTexture = completeImage->GetBackendTexture(false, &origin);
209 if (!backendTexture.IsValid()) {
210 RS_LOGE("GetCompletedImage get backendTexture failed");
211 return nullptr;
212 }
213 SharedTextureContext* sharedContext = new SharedTextureContext(completeImage);
214 auto cacheImage = std::make_shared<Drawing::Image>();
215 Drawing::BitmapFormat info =
216 Drawing::BitmapFormat{ completeImage->GetColorType(), completeImage->GetAlphaType() };
217 bool ret = cacheImage->BuildFromTexture(*gpuContext, backendTexture.GetTextureInfo(),
218 origin, info, nullptr, SKResourceManager::DeleteSharedTextureContext, sharedContext);
219 if (!ret) {
220 RS_LOGE("GetCompletedImage image BuildFromTexture failed");
221 return nullptr;
222 }
223 return cacheImage;
224 #else
225 return completeImage;
226 #endif
227 }
228
DrawCacheSurface(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,RSPaintFilterCanvas & canvas,const Vector2f & boundSize,uint32_t threadIndex,bool isUIFirst)229 bool RsSubThreadCache::DrawCacheSurface(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
230 RSPaintFilterCanvas& canvas, const Vector2f& boundSize, uint32_t threadIndex, bool isUIFirst)
231 {
232 if (!surfaceDrawable) {
233 RS_LOGE("DrawCacheSurface surfaceDrawable is nullptr. id:%{public}" PRIu64, nodeId_);
234 return false;
235 }
236 if (ROSEN_EQ(surfaceDrawable->boundsWidth_, 0.f) || ROSEN_EQ(surfaceDrawable->boundsHeight_, 0.f)) {
237 RS_LOGE("DrawCacheSurface surface bound is 0. id:%{public}" PRIu64, nodeId_);
238 return false;
239 }
240
241 auto cacheImage = GetCompletedImage(canvas, threadIndex, isUIFirst);
242 RSBaseRenderUtil::WriteCacheImageRenderNodeToPng(cacheImage, "cacheImage");
243 if (cacheImage == nullptr || ROSEN_EQ(cacheImage->GetWidth(), 0) ||
244 ROSEN_EQ(cacheImage->GetHeight(), 0)) {
245 RS_LOGE("DrawCacheSurface cacheImage invalid. id:%{public}" PRIu64, nodeId_);
246 return false;
247 }
248 canvas.Save();
249 const auto& gravityMatrix = surfaceDrawable->GetGravityMatrix(cacheImage->GetWidth(), cacheImage->GetHeight());
250 float scaleX = boundSize.x_ / static_cast<float>(cacheImage->GetWidth());
251 float scaleY = boundSize.y_ / static_cast<float>(cacheImage->GetHeight());
252 if (ROSEN_EQ(scaleY, scaleX, SCALE_DIFF)) {
253 canvas.Scale(scaleX, scaleY);
254 } else {
255 canvas.Scale(gravityMatrix.Get(Drawing::Matrix::SCALE_X), gravityMatrix.Get(Drawing::Matrix::SCALE_Y));
256 }
257 if (RSSystemProperties::GetRecordingEnabled()) {
258 if (cacheImage->IsTextureBacked()) {
259 RS_LOGI("DrawCacheSurface convert cacheImage from texture to raster image");
260 cacheImage = cacheImage->MakeRasterImage();
261 if (!cacheImage) {
262 RS_LOGE("DrawCacheSurface: MakeRasterImage failed");
263 canvas.Restore();
264 return false;
265 }
266 }
267 }
268 Drawing::Brush brush;
269 canvas.AttachBrush(brush);
270 auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
271 auto translateX = gravityMatrix.Get(Drawing::Matrix::TRANS_X);
272 auto translateY = gravityMatrix.Get(Drawing::Matrix::TRANS_Y);
273 DrawBehindWindowBeforeCache(canvas, translateX, translateY);
274 auto stencilVal = canvas.GetStencilVal();
275 if (stencilVal > Drawing::Canvas::INVALID_STENCIL_VAL && stencilVal < canvas.GetMaxStencilVal()) {
276 RS_OPTIONAL_TRACE_NAME_FMT("DrawImageWithStencil, stencilVal: %" PRId64 "", stencilVal);
277 RS_LOGD("DrawImageWithStencil, stencilVal: %{public}" PRId64 "", stencilVal);
278 canvas.DrawImageWithStencil(*cacheImage, translateX, translateY, samplingOptions,
279 static_cast<uint32_t>(stencilVal));
280 } else {
281 canvas.DrawImage(*cacheImage, translateX, translateY, samplingOptions);
282 }
283 canvas.DetachBrush();
284 canvas.Restore();
285 return true;
286 }
287
InitCacheSurface(Drawing::GPUContext * gpuContext,std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> nodeDrawable,ClearCacheSurfaceFunc func,uint32_t threadIndex,bool isNeedFP16)288 void RsSubThreadCache::InitCacheSurface(Drawing::GPUContext* gpuContext,
289 std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> nodeDrawable,
290 ClearCacheSurfaceFunc func, uint32_t threadIndex, bool isNeedFP16)
291 {
292 RS_TRACE_NAME_FMT("InitCanvasSurface id:%" PRIu64" targetColorGamut:%d isNeedFP16:%d",
293 nodeId_, targetColorGamut_, isNeedFP16);
294 if (!nodeDrawable) {
295 RS_LOGE("InitCacheSurface nodeDrawable is nullptr");
296 return;
297 }
298 if (func) {
299 cacheSurfaceThreadIndex_ = threadIndex;
300 if (!clearCacheSurfaceFunc_) {
301 clearCacheSurfaceFunc_ = func;
302 }
303 if (cacheSurface_) {
304 func(std::move(cacheSurface_), nullptr,
305 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
306 cacheSurface_ = nullptr;
307 }
308 } else {
309 cacheSurface_ = nullptr;
310 }
311
312 float width = 0.0f;
313 float height = 0.0f;
314 if (const auto& params = nodeDrawable->GetRenderParams()) {
315 auto size = params->GetCacheSize();
316 nodeDrawable->boundsWidth_ = size.x_;
317 nodeDrawable->boundsHeight_ = size.y_;
318 } else {
319 RS_LOGE("uifirst cannot get cachesize");
320 }
321
322 width = nodeDrawable->boundsWidth_;
323 height = nodeDrawable->boundsHeight_;
324
325 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
326 if (gpuContext == nullptr) {
327 if (func) {
328 std::scoped_lock<std::recursive_mutex> lock(completeResourceMutex_);
329 func(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
330 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
331 ClearCacheSurface();
332 }
333 RS_LOGE("InitCacheSurface gpuContext == nullptr");
334 return;
335 }
336 #ifdef RS_ENABLE_GL
337 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
338 OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
339 Drawing::ImageInfo info = Drawing::ImageInfo::MakeN32Premul(width, height);
340 cacheSurface_ = Drawing::Surface::MakeRenderTarget(gpuContext, true, info);
341 }
342 #endif
343 #ifdef RS_ENABLE_VK
344 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
345 OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
346 VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
347 auto colorType = Drawing::ColorType::COLORTYPE_RGBA_8888;
348 // When the colorType is FP16, the colorspace of the uifirst buffer must be sRGB
349 // In other cases, the colorspace follows the targetColorGamut_
350 auto colorSpace = Drawing::ColorSpace::CreateSRGB();
351 RS_LOGD("InitCacheSurface sub thread cache's targetColorGamut_ is [%{public}d]", targetColorGamut_);
352 if (isNeedFP16) {
353 format = VK_FORMAT_R16G16B16A16_SFLOAT;
354 colorType = Drawing::ColorType::COLORTYPE_RGBA_F16;
355 RS_LOGD("InitCacheSurface colorType is FP16, take colorspace to sRGB");
356 } else if (targetColorGamut_ != GRAPHIC_COLOR_GAMUT_SRGB) {
357 colorSpace =
358 Drawing::ColorSpace::CreateRGB(Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
359 }
360 cacheBackendTexture_ = NativeBufferUtils::MakeBackendTexture(
361 width, height, ExtractPid(nodeDrawable->nodeId_), format);
362 auto vkTextureInfo = cacheBackendTexture_.GetTextureInfo().GetVKTextureInfo();
363 if (!cacheBackendTexture_.IsValid() || !vkTextureInfo) {
364 if (func) {
365 std::scoped_lock<std::recursive_mutex> lock(completeResourceMutex_);
366 func(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
367 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
368 ClearCacheSurface();
369 }
370 RS_LOGE("InitCacheSurface !cacheBackendTexture_.IsValid() || !vkTextureInfo");
371 return;
372 }
373 cacheCleanupHelper_ = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
374 vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory, vkTextureInfo->vkAlloc.statName);
375 cacheSurface_ = Drawing::Surface::MakeFromBackendTexture(
376 gpuContext, cacheBackendTexture_.GetTextureInfo(), Drawing::TextureOrigin::BOTTOM_LEFT,
377 1, colorType, colorSpace, NativeBufferUtils::DeleteVkImage, cacheCleanupHelper_);
378 }
379 #endif
380 #else
381 cacheSurface_ = Drawing::Surface::MakeRasterN32Premul(width, height);
382 #endif
383 }
384
ResetUifirst(bool isOnlyClearCache)385 void RsSubThreadCache::ResetUifirst(bool isOnlyClearCache)
386 {
387 RS_LOGI("ResetUifirst id:%{public}" PRIu64 ", isOnlyClearCache:%{public}d", nodeId_, isOnlyClearCache);
388 if (isOnlyClearCache) {
389 ClearCacheSurfaceOnly();
390 } else {
391 ClearCacheSurfaceInThread();
392 }
393 }
394
HasCachedTexture() const395 bool RsSubThreadCache::HasCachedTexture() const
396 {
397 return isCacheCompletedValid_;
398 }
399
IsCacheValid() const400 bool RsSubThreadCache::IsCacheValid() const
401 {
402 return isCacheValid_;
403 }
404
NeedInitCacheSurface(RSSurfaceRenderParams * surfaceParams)405 bool RsSubThreadCache::NeedInitCacheSurface(RSSurfaceRenderParams* surfaceParams)
406 {
407 int width = 0;
408 int height = 0;
409
410 if (surfaceParams) {
411 auto size = surfaceParams->GetCacheSize();
412 width = size.x_;
413 height = size.y_;
414 }
415
416 if (cacheSurface_ == nullptr) {
417 return true;
418 }
419 auto cacheCanvas = cacheSurface_->GetCanvas();
420 if (cacheCanvas == nullptr) {
421 return true;
422 }
423 return cacheCanvas->GetWidth() != width || cacheCanvas->GetHeight() != height;
424 }
425
426 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
UpdateBackendTexture()427 void RsSubThreadCache::UpdateBackendTexture()
428 {
429 RS_TRACE_NAME_FMT("UpdateBackendTexture");
430 if (cacheSurface_ == nullptr) {
431 RS_LOGE("UpdateBackendTexture cacheSurface is nullptr");
432 return;
433 }
434 cacheBackendTexture_ = cacheSurface_->GetBackendTexture();
435 isCacheValid_ = true;
436 }
437 #endif
438
UpdateCompletedCacheSurface()439 void RsSubThreadCache::UpdateCompletedCacheSurface()
440 {
441 RS_TRACE_NAME_FMT("UpdateCompletedCacheSurface id:%" PRIu64, nodeId_);
442 RS_LOGD("UpdateCompletedCacheSurface id:%{public}" PRIu64, nodeId_);
443 if (cacheSurface_ == nullptr || !IsCacheValid()) {
444 RS_LOGE("cacheSurface is nullptr, cache and completeCache swap failed");
445 isCacheValid_ = false;
446 return;
447 }
448 // renderthread not use, subthread done not use
449 std::swap(cacheSurface_, cacheCompletedSurface_);
450 std::swap(cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
451 std::swap(cacheSurfaceInfo_, cacheCompletedSurfaceInfo_);
452 std::swap(cacheBehindWindowData_, cacheCompletedBehindWindowData_);
453 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
454 std::swap(cacheBackendTexture_, cacheCompletedBackendTexture_);
455 #ifdef RS_ENABLE_VK
456 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
457 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
458 std::swap(cacheCleanupHelper_, cacheCompletedCleanupHelper_);
459 }
460 #endif
461 std::swap(isCacheValid_, isCacheCompletedValid_);
462 isTextureValid_.store(true);
463 SetCacheSurfaceNeedUpdated(false);
464 #endif
465 RSBaseRenderUtil::WriteCacheImageRenderNodeToPng(cacheSurface_, "cacheSurface_");
466 RSBaseRenderUtil::WriteCacheImageRenderNodeToPng(cacheCompletedSurface_, "cacheCompletedSurface_");
467 }
468
ClearCacheSurface(bool isClearCompletedCacheSurface)469 void RsSubThreadCache::ClearCacheSurface(bool isClearCompletedCacheSurface)
470 {
471 cacheSurface_ = nullptr;
472 cacheSurfaceInfo_ = { -1, -1, -1.f };
473 isCacheValid_ = false;
474 ResetCacheBehindWindowData();
475 #ifdef RS_ENABLE_VK
476 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
477 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
478 cacheCleanupHelper_ = nullptr;
479 }
480 #endif
481 if (isClearCompletedCacheSurface) {
482 std::scoped_lock<std::recursive_mutex> lock(completeResourceMutex_);
483 cacheCompletedSurface_ = nullptr;
484 cacheCompletedSurfaceInfo_ = { -1, -1, -1.f };
485 isCacheCompletedValid_ = false;
486 ResetCacheCompletedBehindWindowData();
487 #ifdef RS_ENABLE_VK
488 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
489 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
490 cacheCompletedCleanupHelper_ = nullptr;
491 }
492 #endif
493 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
494 isTextureValid_.store(false);
495 #endif
496 }
497 }
498
SetTaskFrameCount(uint64_t frameCount)499 void RsSubThreadCache::SetTaskFrameCount(uint64_t frameCount)
500 {
501 frameCount_ = frameCount;
502 }
503
GetTaskFrameCount() const504 uint64_t RsSubThreadCache::GetTaskFrameCount() const
505 {
506 return frameCount_;
507 }
508
GetSyncUifirstDirtyManager() const509 std::shared_ptr<RSDirtyRegionManager> RsSubThreadCache::GetSyncUifirstDirtyManager() const
510 {
511 return syncUifirstDirtyManager_;
512 }
513
UpdateCacheSurfaceDirtyManager(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,bool hasCompletateCache,bool isLastFrameSkip)514 bool RsSubThreadCache::UpdateCacheSurfaceDirtyManager(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
515 bool hasCompletateCache, bool isLastFrameSkip)
516 {
517 if (!surfaceDrawable) {
518 RS_LOGE("UpdateCacheSurfaceDirtyManager surfaceDrawable is nullptr");
519 return false;
520 }
521 if (!syncUifirstDirtyManager_ || !surfaceDrawable->syncDirtyManager_) {
522 RS_LOGE("UpdateCacheSurfaceDirtyManager dirty manager is nullptr");
523 return false;
524 }
525 syncUifirstDirtyManager_->Clear();
526 auto curDirtyRegion = surfaceDrawable->syncDirtyManager_->GetDirtyRegion();
527 auto& curFrameDirtyRegion = surfaceDrawable->syncDirtyManager_->GetUifirstFrameDirtyRegion();
528 curDirtyRegion = curDirtyRegion.JoinRect(curFrameDirtyRegion);
529 if (isLastFrameSkip) {
530 curDirtyRegion = curDirtyRegion.JoinRect(syncUifirstDirtyManager_->GetUiLatestHistoryDirtyRegions(1));
531 }
532 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetRenderParams().get());
533 if (!surfaceParams) {
534 RS_LOGE("UpdateCacheSurfaceDirtyManager surfaceParams is nullptr");
535 return false;
536 }
537 if (!hasCompletateCache) {
538 curDirtyRegion = surfaceParams->GetAbsDrawRect();
539 }
540 RS_TRACE_NAME_FMT("UpdateCacheSurfaceDirtyManager[%s] %" PRIu64", curDirtyRegion[%d %d %d %d], hasCache:%d",
541 surfaceDrawable->GetName().c_str(), surfaceDrawable->GetId(), curDirtyRegion.GetLeft(),
542 curDirtyRegion.GetTop(), curDirtyRegion.GetWidth(), curDirtyRegion.GetHeight(), hasCompletateCache);
543 syncUifirstDirtyManager_->MergeDirtyRect(curDirtyRegion);
544 // set history dirty count
545 syncUifirstDirtyManager_->SetBufferAge(1); // 1 means buffer age
546 // update history dirty count
547 syncUifirstDirtyManager_->UpdateDirty(false);
548 return true;
549 }
550
UpdateUifirstDirtyManager(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable)551 void RsSubThreadCache::UpdateUifirstDirtyManager(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable)
552 {
553 if (!(RSUifirstManager::Instance().GetUiFirstType() == UiFirstCcmType::MULTI &&
554 RSSystemProperties::GetUIFirstDirtyEnabled())) {
555 return;
556 }
557 if (!surfaceDrawable) {
558 RS_LOGE("UpdateUifirstDirtyManager surfaceDrawable is nullptr");
559 return;
560 }
561 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetRenderParams().get());
562 if (!surfaceParams) {
563 RS_LOGE("UpdateUifirstDirtyManager params is nullptr");
564 UpdateDirtyRecordCompletatedState(false);
565 return;
566 }
567 bool isCacheValid = IsCacheValid();
568 bool isLastFrameSkip = GetSurfaceSkipCount() > 0;
569 auto isRecordCompletate = UpdateCacheSurfaceDirtyManager(surfaceDrawable, isCacheValid, isLastFrameSkip);
570 // nested surfacenode uifirstDirtyManager update is required
571 for (const auto& nestedDrawable : surfaceDrawable->
572 GetDrawableVectorById(surfaceParams->GetAllSubSurfaceNodeIds())) {
573 auto surfaceNodeDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(nestedDrawable);
574 if (surfaceNodeDrawable) {
575 isRecordCompletate = isRecordCompletate && surfaceNodeDrawable->GetRsSubThreadCache()
576 .UpdateCacheSurfaceDirtyManager(surfaceNodeDrawable.get(), isCacheValid, isLastFrameSkip);
577 }
578 }
579 UpdateDirtyRecordCompletatedState(isRecordCompletate);
580 }
581
IsDirtyRecordCompletated()582 bool RsSubThreadCache::IsDirtyRecordCompletated()
583 {
584 bool isDirtyRecordCompletated = isDirtyRecordCompletated_;
585 isDirtyRecordCompletated_ = false;
586 return isDirtyRecordCompletated;
587 }
588
UpdateDirtyRecordCompletatedState(bool isCompletate)589 void RsSubThreadCache::UpdateDirtyRecordCompletatedState(bool isCompletate)
590 {
591 isDirtyRecordCompletated_ = isCompletate;
592 }
593
SetUifirstDirtyRegion(Drawing::Region dirtyRegion)594 void RsSubThreadCache::SetUifirstDirtyRegion(Drawing::Region dirtyRegion)
595 {
596 uifirstDirtyRegion_ = dirtyRegion;
597 }
598
GetUifirstDirtyRegion() const599 Drawing::Region RsSubThreadCache::GetUifirstDirtyRegion() const
600 {
601 return uifirstDirtyRegion_;
602 }
603
SetUifrstDirtyEnableFlag(bool dirtyEnableFlag)604 void RsSubThreadCache::SetUifrstDirtyEnableFlag(bool dirtyEnableFlag)
605 {
606 uifrstDirtyEnableFlag_ = dirtyEnableFlag;
607 }
608
GetUifrstDirtyEnableFlag() const609 bool RsSubThreadCache::GetUifrstDirtyEnableFlag() const
610 {
611 return uifrstDirtyEnableFlag_;
612 }
613
GetCurDirtyRegionWithMatrix(const Drawing::Matrix & matrix,Drawing::RectF & latestDirtyRect,Drawing::RectF & absDrawRect)614 bool RsSubThreadCache::GetCurDirtyRegionWithMatrix(const Drawing::Matrix& matrix,
615 Drawing::RectF& latestDirtyRect, Drawing::RectF& absDrawRect)
616 {
617 Drawing::Matrix inverseMatrix;
618 if (!matrix.Invert(inverseMatrix)) {
619 return false;
620 }
621 Drawing::RectF latestDirtyRectTemp = {0, 0, 0, 0};
622 Drawing::RectF absDrawRectTemp = {0, 0, 0, 0};
623 std::swap(latestDirtyRectTemp, latestDirtyRect);
624 std::swap(absDrawRectTemp, absDrawRect);
625 inverseMatrix.MapRect(latestDirtyRect, latestDirtyRectTemp);
626 inverseMatrix.MapRect(absDrawRect, absDrawRectTemp);
627 return true;
628 }
629
CalculateUifirstDirtyRegion(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,Drawing::RectI & dirtyRect)630 bool RsSubThreadCache::CalculateUifirstDirtyRegion(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
631 Drawing::RectI& dirtyRect)
632 {
633 if (!surfaceDrawable) {
634 RS_LOGE("CalculateUifirstDirtyRegion surfaceDrawable is nullptr");
635 return false;
636 }
637 auto uifirstDirtyManager = GetSyncUifirstDirtyManager();
638 if (!uifirstDirtyManager) {
639 RS_LOGE("CalculateUifirstDirtyRegion uifirstDirtyManager is nullptr");
640 return false;
641 }
642 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetRenderParams().get());
643 if (!surfaceParams) {
644 RS_LOGE("CalculateUifirstDirtyRegion surfaceParams is nullptr");
645 return false;
646 }
647 RectI latestDirtyRect = uifirstDirtyManager->GetUiLatestHistoryDirtyRegions();
648 if (latestDirtyRect.IsEmpty()) {
649 dirtyRect = {};
650 return true;
651 }
652 auto absDrawRect = surfaceParams->GetAbsDrawRect();
653 if (absDrawRect.GetWidth() == 0 || absDrawRect.GetHeight() == 0 ||
654 !absDrawRect.IsInsideOf(surfaceParams->GetScreenRect())) {
655 RS_LOGD("absRect params is err or out of dispaly");
656 return false;
657 }
658 Drawing::RectF curDrityRegion = Drawing::RectF(latestDirtyRect.GetLeft(), latestDirtyRect.GetTop(),
659 latestDirtyRect.GetRight(), latestDirtyRect.GetBottom());
660 Drawing::RectF curAbsDrawRect = Drawing::RectF(absDrawRect.GetLeft(), absDrawRect.GetTop(),
661 absDrawRect.GetRight(), absDrawRect.GetBottom());
662 if (!GetCurDirtyRegionWithMatrix(surfaceParams->GetDirtyRegionMatrix(), curDrityRegion, curAbsDrawRect)) {
663 return false;
664 }
665 auto surfaceBounds = surfaceParams->GetBounds();
666 float widthScale = surfaceBounds.GetWidth() / curAbsDrawRect.GetWidth();
667 float heightScale = surfaceBounds.GetHeight() / curAbsDrawRect.GetHeight();
668 float left = (curDrityRegion.GetLeft() - curAbsDrawRect.GetLeft()) * widthScale;
669 float top = (curDrityRegion.GetTop() - curAbsDrawRect.GetTop()) * heightScale;
670 float width = curDrityRegion.GetWidth() * widthScale;
671 float height = curDrityRegion.GetHeight() * heightScale;
672 Drawing::RectF tempRect = Drawing::RectF(left, top, left + width, top + height);
673 dirtyRect = tempRect.RoundOut();
674 RS_TRACE_NAME_FMT("lR[%.1f %.1f %.1f %.1f], absR[%.1f %.1f %.1f %.1f], resultR[%d %d %d %d]",
675 curDrityRegion.GetLeft(), curDrityRegion.GetTop(), curDrityRegion.GetWidth(), curDrityRegion.GetHeight(),
676 curAbsDrawRect.GetLeft(), curAbsDrawRect.GetTop(), curAbsDrawRect.GetWidth(), curAbsDrawRect.GetHeight(),
677 dirtyRect.GetLeft(), dirtyRect.GetTop(), dirtyRect.GetWidth(), dirtyRect.GetHeight());
678 return true;
679 }
680
MergeUifirstAllSurfaceDirtyRegion(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,Drawing::RectI & dirtyRects)681 bool RsSubThreadCache::MergeUifirstAllSurfaceDirtyRegion(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
682 Drawing::RectI& dirtyRects)
683 {
684 if (!(RSUifirstManager::Instance().GetUiFirstType() == UiFirstCcmType::MULTI &&
685 RSSystemProperties::GetUIFirstDirtyEnabled())) {
686 return false;
687 }
688 if (!surfaceDrawable) {
689 RS_LOGE("MergeUifirstAllSurfaceDirtyRegion surfaceDrawable is nullptr");
690 return false;
691 }
692 uifirstMergedDirtyRegion_ = {};
693 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetUifirstRenderParams().get());
694 if (!surfaceParams) {
695 RS_LOGE("CalculateUifirstDirtyRegion params is nullptr");
696 return false;
697 }
698 if (!surfaceParams->IsLeashWindow() || !IsDirtyRecordCompletated()) {
699 RS_LOGD("MergeUifirstAllSurfaceDirtyRegion not support");
700 return false;
701 }
702 Drawing::RectI tempRect = {};
703 bool isCalculateSucc = CalculateUifirstDirtyRegion(surfaceDrawable, tempRect);
704 uifirstMergedDirtyRegion_.SetRect(tempRect);
705 dirtyRects.Join(tempRect);
706 for (const auto& nestedDrawable : surfaceDrawable->
707 GetDrawableVectorById(surfaceParams->GetAllSubSurfaceNodeIds())) {
708 auto surfaceNodeDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(nestedDrawable);
709 if (surfaceNodeDrawable) {
710 tempRect = {};
711 isCalculateSucc = isCalculateSucc && surfaceNodeDrawable->GetRsSubThreadCache().
712 CalculateUifirstDirtyRegion(surfaceNodeDrawable.get(), tempRect);
713 Drawing::Region resultRegion;
714 resultRegion.SetRect(tempRect);
715 uifirstMergedDirtyRegion_.Op(resultRegion, Drawing::RegionOp::UNION);
716 dirtyRects.Join(tempRect);
717 }
718 }
719 return isCalculateSucc;
720 }
721
UpadteAllSurfaceUifirstDirtyEnableState(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,bool isEnableDirtyRegion)722 void RsSubThreadCache::UpadteAllSurfaceUifirstDirtyEnableState(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
723 bool isEnableDirtyRegion)
724 {
725 if (!(RSUifirstManager::Instance().GetUiFirstType() == UiFirstCcmType::MULTI &&
726 RSSystemProperties::GetUIFirstDirtyEnabled())) {
727 return;
728 }
729 if (!surfaceDrawable) {
730 RS_LOGE("UpadteAllSurfaceUifirstDirtyEnableState surfaceDrawable is nullptr");
731 return;
732 }
733 SetUifirstDirtyRegion(uifirstMergedDirtyRegion_);
734 SetUifrstDirtyEnableFlag(isEnableDirtyRegion);
735 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetUifirstRenderParams().get());
736 if (!surfaceParams) {
737 RS_LOGE("UpadteAllSurfaceUifirstDirtyState params is nullptr");
738 return;
739 }
740 for (const auto& nestedDrawable : surfaceDrawable->
741 GetDrawableVectorById(surfaceParams->GetAllSubSurfaceNodeIds())) {
742 auto surfaceNodeDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(nestedDrawable);
743 if (surfaceNodeDrawable) {
744 surfaceNodeDrawable->GetRsSubThreadCache().SetUifirstDirtyRegion(uifirstMergedDirtyRegion_);
745 surfaceNodeDrawable->GetRsSubThreadCache().SetUifrstDirtyEnableFlag(isEnableDirtyRegion);
746 }
747 }
748 }
749
PushDirtyRegionToStack(RSPaintFilterCanvas & canvas,Drawing::Region & resultRegion)750 void RsSubThreadCache::PushDirtyRegionToStack(RSPaintFilterCanvas& canvas, Drawing::Region& resultRegion)
751 {
752 if (canvas.GetIsParallelCanvas()) {
753 if (GetUifrstDirtyEnableFlag()) {
754 auto uifirstDirtyRegion = GetUifirstDirtyRegion();
755 canvas.PushDirtyRegion(uifirstDirtyRegion);
756 }
757 } else {
758 canvas.PushDirtyRegion(resultRegion);
759 }
760 }
761
UifirstDirtyRegionDfx(Drawing::Canvas & canvas,Drawing::RectI & surfaceDrawRect)762 void RsSubThreadCache::UifirstDirtyRegionDfx(Drawing::Canvas& canvas, Drawing::RectI& surfaceDrawRect)
763 {
764 if (!RSSystemProperties::GetUIFirstDirtyDebugEnabled()) {
765 return;
766 }
767 const int defaultTextOffsetX = 6; // text position is 6 pixelSize right side of the Rect
768 const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the Rect
769 Drawing::Brush rectBrush;
770 rectBrush.SetColor(Drawing::Color(0x80FFB6C1));
771 rectBrush.SetAntiAlias(true);
772 rectBrush.SetAlphaF(0.4f); // alpha 0.4 by default
773 std::shared_ptr<Drawing::Typeface> typeFace = nullptr;
774 std::string position = "pos:[" + surfaceDrawRect.ToString() + "]";
775 // font size: 24
776 std::shared_ptr<Drawing::TextBlob> textBlob =
777 Drawing::TextBlob::MakeFromString(position.c_str(), Drawing::Font(typeFace, 24.0f, 0.6f, 0.0f));
778 canvas.AttachBrush(rectBrush);
779 canvas.DrawRect(surfaceDrawRect);
780 canvas.DetachBrush();
781 canvas.AttachBrush(Drawing::Brush());
782 canvas.DrawTextBlob(textBlob.get(),
783 surfaceDrawRect.GetLeft() + defaultTextOffsetX, surfaceDrawRect.GetTop() + defaultTextOffsetY);
784 canvas.DetachBrush();
785 }
786
SubDraw(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,Drawing::Canvas & canvas)787 void RsSubThreadCache::SubDraw(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable, Drawing::Canvas& canvas)
788 {
789 if (!surfaceDrawable) {
790 RS_LOGE("SubDraw surfaceDrawable is nullptr");
791 return;
792 }
793 const auto& uifirstParams = surfaceDrawable->GetUifirstRenderParams();
794 auto debugSize = uifirstParams ? uifirstParams->GetCacheSize() : Vector2f(0.f, 0.f);
795 RS_TRACE_NAME_FMT("RsSubThreadCache::SubDraw[%s] %" PRIu64 ", w:%.1f h:%.1f, isHigh:%d",
796 surfaceDrawable->GetName().c_str(), surfaceDrawable->GetId(), debugSize.x_, debugSize.y_,
797 IsHighPostPriority());
798
799 auto rscanvas = reinterpret_cast<RSPaintFilterCanvas*>(&canvas);
800 if (!rscanvas) {
801 RS_LOGE("SubDraw, rscanvas is nullptr");
802 return;
803 }
804 Drawing::Rect bounds = uifirstParams ? uifirstParams->GetBounds() : Drawing::Rect(0, 0, 0, 0);
805
806 auto parentSurfaceMatrix = RSRenderParams::GetParentSurfaceMatrix();
807 RSRenderParams::SetParentSurfaceMatrix(IDENTITY_MATRIX);
808
809 // merge uifirst dirty region
810 Drawing::RectI uifirstSurfaceDrawRects = {};
811 auto dirtyEnableFlag = MergeUifirstAllSurfaceDirtyRegion(surfaceDrawable, uifirstSurfaceDrawRects);
812 UpadteAllSurfaceUifirstDirtyEnableState(surfaceDrawable, dirtyEnableFlag);
813 if (!dirtyEnableFlag) {
814 rscanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
815 } else {
816 rscanvas->ClipRegion(uifirstMergedDirtyRegion_);
817 rscanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
818 }
819 {
820 RS_TRACE_NAME_FMT("uifirstDirtyMerged[%d %d %d %d], dirtyEnableFlag:%d",
821 uifirstSurfaceDrawRects.GetLeft(), uifirstSurfaceDrawRects.GetTop(),
822 uifirstSurfaceDrawRects.GetWidth(), uifirstSurfaceDrawRects.GetHeight(), dirtyEnableFlag);
823 }
824
825 ClearTotalProcessedSurfaceCount();
826 RSRenderNodeDrawable::ClearProcessedNodeCount();
827 surfaceDrawable->DrawUifirstContentChildren(*rscanvas, bounds);
828 int totalNodes = RSRenderNodeDrawable::GetProcessedNodeCount();
829 int totalSurfaces = GetTotalProcessedSurfaceCount();
830 RS_TRACE_NAME_FMT("SubDraw totalSurfaces:%d totalNodes:%d", totalSurfaces, totalNodes);
831 if (totalSurfaces <= 0 || totalNodes <= 0) {
832 RS_LOGI("subDraw id:%{public}" PRIu64 ",name:%{public}s,totalSurfaces:%{public}d,totalNodes:%{public}d",
833 surfaceDrawable->GetId(), surfaceDrawable->name_.c_str(), totalSurfaces, totalNodes);
834 } else {
835 RS_LOGD("subDraw id:%{public}" PRIu64 ",name:%{public}s,totalSurfaces:%{public}d,totalNodes:%{public}d",
836 surfaceDrawable->GetId(), surfaceDrawable->name_.c_str(), totalSurfaces, totalNodes);
837 }
838 RSRenderParams::SetParentSurfaceMatrix(parentSurfaceMatrix);
839 // uifirst dirty dfx
840 UifirstDirtyRegionDfx(*rscanvas, uifirstSurfaceDrawRects);
841 }
842
SetSubThreadSkip(bool isSubThreadSkip)843 void RsSubThreadCache::SetSubThreadSkip(bool isSubThreadSkip)
844 {
845 isSubThreadSkip_ = isSubThreadSkip;
846 }
847
GetTotalProcessedSurfaceCount() const848 int RsSubThreadCache::GetTotalProcessedSurfaceCount() const
849 {
850 return totalProcessedSurfaceCount_;
851 }
852
TotalProcessedSurfaceCountInc(RSPaintFilterCanvas & canvas)853 void RsSubThreadCache::TotalProcessedSurfaceCountInc(RSPaintFilterCanvas& canvas)
854 {
855 if (canvas.GetIsParallelCanvas()) {
856 ++totalProcessedSurfaceCount_;
857 }
858 }
859
ClearTotalProcessedSurfaceCount()860 void RsSubThreadCache::ClearTotalProcessedSurfaceCount()
861 {
862 totalProcessedSurfaceCount_ = 0;
863 }
864
ProcessSurfaceSkipCount()865 void RsSubThreadCache::ProcessSurfaceSkipCount()
866 {
867 isSurfaceSkipCount_++;
868 }
869
ResetSurfaceSkipCount()870 void RsSubThreadCache::ResetSurfaceSkipCount()
871 {
872 isSurfaceSkipCount_ = 0;
873 isSurfaceSkipPriority_ = 0;
874 }
875
GetSurfaceSkipCount() const876 int32_t RsSubThreadCache::GetSurfaceSkipCount() const
877 {
878 return isSurfaceSkipCount_;
879 }
880
GetSurfaceSkipPriority()881 int32_t RsSubThreadCache::GetSurfaceSkipPriority()
882 {
883 return ++isSurfaceSkipPriority_;
884 }
885
GetUifirstPostOrder() const886 uint32_t RsSubThreadCache::GetUifirstPostOrder() const
887 {
888 return uifirstPostOrder_;
889 }
890
SetUifirstPostOrder(uint32_t order)891 void RsSubThreadCache::SetUifirstPostOrder(uint32_t order)
892 {
893 uifirstPostOrder_ = order;
894 }
895
IsHighPostPriority()896 bool RsSubThreadCache::IsHighPostPriority()
897 {
898 return isHighPostPriority_;
899 }
900
SetHighPostPriority(bool postPriority)901 void RsSubThreadCache::SetHighPostPriority(bool postPriority)
902 {
903 isHighPostPriority_ = postPriority;
904 }
905
UpdateCacheSurfaceInfo(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> nodeDrawable)906 void RsSubThreadCache::UpdateCacheSurfaceInfo(std::shared_ptr<DrawableV2::RSSurfaceRenderNodeDrawable> nodeDrawable)
907 {
908 if (!nodeDrawable) {
909 return;
910 }
911 const auto& params = nodeDrawable->GetRenderParams();
912 if (params) {
913 cacheSurfaceInfo_.processedSurfaceCount = GetTotalProcessedSurfaceCount();
914 cacheSurfaceInfo_.processedNodeCount = RSRenderNodeDrawable::GetProcessedNodeCount();
915 cacheSurfaceInfo_.alpha = params->GetGlobalAlpha();
916 }
917 }
918
DrawUIFirstCache(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,RSPaintFilterCanvas & rscanvas,bool canSkipWait)919 bool RsSubThreadCache::DrawUIFirstCache(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
920 RSPaintFilterCanvas& rscanvas, bool canSkipWait)
921 {
922 if (!surfaceDrawable) {
923 RS_LOGE("DrawUIFirstCache surfaceDrawable is nullptr");
924 return false;
925 }
926 RS_TRACE_NAME_FMT("DrawUIFirstCache_NOSTARTING");
927 const auto& params = surfaceDrawable->GetRenderParams();
928 if (!params) {
929 RS_LOGE("DrawUIFirstCache params is nullptr");
930 return false;
931 }
932
933 static constexpr int REQUEST_SET_FRAME_LOAD_ID = 100006;
934 static constexpr int REQUEST_FRAME_AWARE_LOAD = 90;
935 static constexpr int REQUEST_FRAME_STANDARD_LOAD = 50;
936 if (!HasCachedTexture()) {
937 RS_TRACE_NAME_FMT("HandleSubThreadNode wait %d %" PRIu64 "", canSkipWait, surfaceDrawable->nodeId_);
938 if (canSkipWait) {
939 RS_LOGI("uifirst skip wait id:%{public}" PRIu64 ",name:%{public}s", surfaceDrawable->nodeId_,
940 surfaceDrawable->name_.c_str());
941 return false; // draw nothing
942 }
943 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
944 bool frameParamEnable = RsFrameReport::GetInstance().GetEnable();
945 if (frameParamEnable) {
946 RsFrameReport::GetInstance().SetFrameParam(
947 REQUEST_SET_FRAME_LOAD_ID, REQUEST_FRAME_AWARE_LOAD, 0, GetLastFrameUsedThreadIndex());
948 }
949 RSSubThreadManager::Instance()->WaitNodeTask(surfaceDrawable->nodeId_);
950 if (frameParamEnable) {
951 RsFrameReport::GetInstance().SetFrameParam(
952 REQUEST_SET_FRAME_LOAD_ID, REQUEST_FRAME_STANDARD_LOAD, 0, GetLastFrameUsedThreadIndex());
953 }
954 UpdateCompletedCacheSurface();
955 #endif
956 }
957 return DrawCacheSurface(surfaceDrawable, rscanvas, params->GetCacheSize(), UNI_MAIN_THREAD_INDEX, true);
958 }
959
DrawUIFirstCacheWithStarting(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,RSPaintFilterCanvas & rscanvas,NodeId startingWindowId)960 bool RsSubThreadCache::DrawUIFirstCacheWithStarting(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
961 RSPaintFilterCanvas& rscanvas, NodeId startingWindowId)
962 {
963 if (!surfaceDrawable) {
964 RS_LOGE("DrawUIFirstCacheWithStarting surfaceDrawable is nullptr");
965 return false;
966 }
967 bool hasCachedTexture = HasCachedTexture();
968 RS_TRACE_NAME_FMT("DrawUIFirstCacheWithStarting hasCache:%d, nodeId:%" PRIu64, hasCachedTexture, startingWindowId);
969 auto startingNodeDrawable = RSRenderNodeDrawableAdapter::GetDrawableById(startingWindowId);
970 if (UNLIKELY(!hasCachedTexture && !startingNodeDrawable)) {
971 RS_LOGI("DrawUIFirstCacheWithStarting with no cache and no starting window. id:%{public}" PRIu64,
972 surfaceDrawable->GetId());
973 // no cache and starting window, we should wait subthread
974 return DrawUIFirstCache(surfaceDrawable, rscanvas, false);
975 }
976 bool ret = true;
977 if (startingNodeDrawable) {
978 const auto& startingParams = startingNodeDrawable->GetRenderParams();
979 if (!hasCachedTexture && startingParams && !ROSEN_EQ(startingParams->GetAlpha(), 1.0f)) {
980 // no cache and starting window alpha is not 1.0, we should wait subthread
981 ret = DrawUIFirstCache(surfaceDrawable, rscanvas, false);
982 RS_TRACE_NAME_FMT("wait and drawStarting, GetAlpha:%f, GetGlobalAlpha:%f",
983 startingParams->GetAlpha(), startingParams->GetGlobalAlpha());
984 startingNodeDrawable->Draw(rscanvas);
985 return ret;
986 }
987 }
988 const auto& params = surfaceDrawable->GetRenderParams();
989 if (!params) {
990 RS_LOGE("RSUniRenderUtil::HandleSubThreadNodeDrawable params is nullptr");
991 return false;
992 }
993 // draw surface content
994 if (hasCachedTexture) {
995 ret = DrawCacheSurface(surfaceDrawable, rscanvas, params->GetCacheSize(), UNI_MAIN_THREAD_INDEX, true);
996 }
997 // draw starting window
998 if (startingNodeDrawable) {
999 RS_TRACE_NAME_FMT("drawStarting");
1000 startingNodeDrawable->Draw(rscanvas);
1001 }
1002 return ret;
1003 }
1004
DealWithUIFirstCache(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams,RSRenderThreadParams & uniParams)1005 bool RsSubThreadCache::DealWithUIFirstCache(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
1006 RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams, RSRenderThreadParams& uniParams)
1007 {
1008 if (!surfaceDrawable) {
1009 RS_LOGE("DealWithUIFirstCache surfaceDrawable is nullptr");
1010 return false;
1011 }
1012 if (drawWindowCache_.DealWithCachedWindow(surfaceDrawable, canvas, surfaceParams, uniParams)) {
1013 return true;
1014 }
1015 auto enableType = surfaceParams.GetUifirstNodeEnableParam();
1016 auto cacheState = GetCacheSurfaceProcessedStatus();
1017 if ((!RSUniRenderThread::GetCaptureParam().isSnapshot_ && enableType == MultiThreadCacheType::NONE &&
1018 // WAITING may change to DOING in subThread at any time
1019 cacheState != CacheProcessStatus::WAITING && cacheState != CacheProcessStatus::DOING) ||
1020 (RSUniRenderThread::GetCaptureParam().isSnapshot_ && !HasCachedTexture())) {
1021 return false;
1022 }
1023 if (RSUniRenderThread::GetCaptureParam().isSnapshot_) {
1024 RS_LOGI("%{public}s name:%{public}s surfaceCount:%{public}d nodeCount:%{public}d alpha:%{public}f",
1025 __func__, surfaceDrawable->GetName().c_str(), cacheCompletedSurfaceInfo_.processedSurfaceCount,
1026 cacheCompletedSurfaceInfo_.processedNodeCount, cacheCompletedSurfaceInfo_.alpha);
1027 }
1028 RS_TRACE_NAME_FMT("DrawUIFirstCache [%s] %" PRIu64 ", type %d, cacheState:%d",
1029 surfaceParams.GetName().c_str(), surfaceParams.GetId(), enableType, cacheState);
1030 Drawing::Rect bounds = surfaceParams.GetBounds();
1031 RSAutoCanvasRestore acr(&canvas);
1032 // Alpha and matrix have been applied in func CaptureSurface
1033 if (!RSUniRenderThread::GetCaptureParam().isSnapshot_ && !RSUniRenderThread::GetCaptureParam().isMirror_) {
1034 canvas.MultiplyAlpha(surfaceParams.GetAlpha());
1035 canvas.ConcatMatrix(surfaceParams.GetMatrix());
1036 }
1037 // This branch is entered only when the conditions for executing the DrawUIFirstCache function are met.
1038 if (surfaceParams.GetGlobalPositionEnabled() &&
1039 surfaceParams.GetUifirstUseStarting() == INVALID_NODEID) {
1040 auto matrix = surfaceParams.GetMatrix();
1041 Drawing::Matrix inverseMatrix;
1042 if (!matrix.Invert(inverseMatrix)) {
1043 RS_LOGW("%{public}s name: %{public}s matrix invert inverseMatrix Failed", __func__,
1044 surfaceParams.GetName().c_str());
1045 }
1046 canvas.ConcatMatrix(inverseMatrix);
1047 canvas.Translate(-surfaceDrawable->offsetX_, -surfaceDrawable->offsetY_);
1048 canvas.ConcatMatrix(matrix);
1049 RS_LOGD("DealWithUIFirstCache Translate screenId=[%{public}" PRIu64 "] "
1050 "offsetX=%{public}d offsetY=%{public}d", surfaceDrawable->curDisplayScreenId_, surfaceDrawable->offsetX_,
1051 surfaceDrawable->offsetY_);
1052 }
1053
1054 auto stencilVal = surfaceParams.GetStencilVal();
1055 if (surfaceParams.IsLeashWindow()) {
1056 surfaceDrawable->DrawLeashWindowBackground(canvas, bounds,
1057 uniParams.IsStencilPixelOcclusionCullingEnabled(), stencilVal);
1058 } else {
1059 surfaceDrawable->DrawBackground(canvas, bounds);
1060 }
1061 canvas.SetStencilVal(stencilVal);
1062 bool drawCacheSuccess = true;
1063 if (surfaceParams.GetUifirstUseStarting() != INVALID_NODEID) {
1064 drawCacheSuccess = DrawUIFirstCacheWithStarting(surfaceDrawable, canvas, surfaceParams.GetUifirstUseStarting());
1065 } else {
1066 drawCacheSuccess = DrawUIFirstCache(surfaceDrawable, canvas, false);
1067 }
1068 canvas.SetStencilVal(Drawing::Canvas::INVALID_STENCIL_VAL);
1069 if (!drawCacheSuccess) {
1070 surfaceDrawable->SetDrawSkipType(DrawSkipType::UI_FIRST_CACHE_FAIL);
1071 RS_TRACE_NAME_FMT("[%s] reuse failed!", surfaceParams.GetName().c_str());
1072 RS_LOGI("uifirst %{public}s drawcache failed! id:%{public}" PRIu64, surfaceDrawable->name_.c_str(),
1073 surfaceDrawable->nodeId_);
1074 }
1075 surfaceDrawable->DrawForeground(canvas, bounds);
1076 surfaceDrawable->DrawWatermark(canvas, surfaceParams);
1077 if (uniParams.GetUIFirstDebugEnabled()) {
1078 DrawUIFirstDfx(canvas, enableType, surfaceParams, drawCacheSuccess);
1079 }
1080 return true;
1081 }
1082
DrawUIFirstDfx(RSPaintFilterCanvas & canvas,MultiThreadCacheType enableType,RSSurfaceRenderParams & surfaceParams,bool drawCacheSuccess)1083 void RsSubThreadCache::DrawUIFirstDfx(RSPaintFilterCanvas& canvas, MultiThreadCacheType enableType,
1084 RSSurfaceRenderParams& surfaceParams, bool drawCacheSuccess)
1085 {
1086 auto sizeDebug = surfaceParams.GetCacheSize();
1087 Drawing::Brush rectBrush;
1088 if (drawCacheSuccess) {
1089 if (enableType == MultiThreadCacheType::ARKTS_CARD) {
1090 // rgba: Alpha 128, blue 128
1091 rectBrush.SetColor(Drawing::Color(0, 0, 128, 128));
1092 } else {
1093 // rgba: Alpha 128, green 128, blue 128
1094 rectBrush.SetColor(Drawing::Color(0, 128, 128, 128));
1095 }
1096 } else {
1097 // rgba: Alpha 128, red 128
1098 rectBrush.SetColor(Drawing::Color(128, 0, 0, 128));
1099 }
1100 canvas.AttachBrush(rectBrush);
1101 canvas.DrawRect(Drawing::Rect(0, 0, sizeDebug.x_, sizeDebug.y_));
1102 canvas.DetachBrush();
1103 }
1104
SetCacheBehindWindowData(const std::shared_ptr<RSPaintFilterCanvas::CacheBehindWindowData> & data)1105 void RsSubThreadCache::SetCacheBehindWindowData(const std::shared_ptr<RSPaintFilterCanvas::CacheBehindWindowData>& data)
1106 {
1107 cacheBehindWindowData_ = data;
1108 }
1109
SetCacheCompletedBehindWindowData(const std::shared_ptr<RSPaintFilterCanvas::CacheBehindWindowData> & data)1110 void RsSubThreadCache::SetCacheCompletedBehindWindowData(
1111 const std::shared_ptr<RSPaintFilterCanvas::CacheBehindWindowData>& data)
1112 {
1113 cacheCompletedBehindWindowData_ = data;
1114 }
1115
ResetCacheBehindWindowData()1116 void RsSubThreadCache::ResetCacheBehindWindowData()
1117 {
1118 cacheBehindWindowData_.reset();
1119 }
1120
ResetCacheCompletedBehindWindowData()1121 void RsSubThreadCache::ResetCacheCompletedBehindWindowData()
1122 {
1123 cacheCompletedBehindWindowData_.reset();
1124 }
1125
DrawBehindWindowBeforeCache(RSPaintFilterCanvas & canvas,const Drawing::scalar px,const Drawing::scalar py)1126 void RsSubThreadCache::DrawBehindWindowBeforeCache(RSPaintFilterCanvas& canvas,
1127 const Drawing::scalar px, const Drawing::scalar py)
1128 {
1129 if (!cacheCompletedBehindWindowData_) {
1130 RS_LOGD("DrawBehindWindowBeforeCache no need to draw");
1131 return;
1132 }
1133 if (!cacheCompletedBehindWindowData_->filter_ || !cacheCompletedBehindWindowData_->rect_.IsValid()) {
1134 RS_LOGE("DrawBehindWindowBeforeCache data is not valid");
1135 return;
1136 }
1137 auto surface = canvas.GetSurface();
1138 if (!surface) {
1139 RS_LOGE("DrawBehindWindowBeforeCache surface is nullptr");
1140 return;
1141 }
1142 RSAutoCanvasRestore acr(&canvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
1143 canvas.Translate(px, py);
1144 Drawing::Rect absRect;
1145 canvas.GetTotalMatrix().MapRect(absRect, cacheCompletedBehindWindowData_->rect_);
1146 Drawing::RectI imageRect(std::ceil(absRect.GetLeft()), std::ceil(absRect.GetTop()), std::ceil(absRect.GetRight()),
1147 std::ceil(absRect.GetBottom()));
1148 auto deviceRect = Drawing::RectI(0, 0, surface->Width(), surface->Height());
1149 imageRect.Intersect(deviceRect);
1150 auto filter = std::static_pointer_cast<RSDrawingFilter>(cacheCompletedBehindWindowData_->filter_);
1151 auto imageSnapshot = surface->GetImageSnapshot(imageRect);
1152 if (!imageSnapshot) {
1153 RS_LOGE("DrawBehindWindowBeforeCache imageSnapshot is nullptr");
1154 return;
1155 }
1156 filter->PreProcess(imageSnapshot);
1157 Drawing::Rect srcRect = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1158 Drawing::Rect dstRect = imageRect;
1159 canvas.ResetMatrix();
1160 filter->DrawImageRect(canvas, imageSnapshot, srcRect, dstRect);
1161 filter->PostProcess(canvas);
1162 RS_TRACE_NAME_FMT("RsSubThreadCache::DrawBehindWindowBeforeCache imageRect:%s", imageRect.ToString().c_str());
1163 }
1164 } // namespace OHOS::Rosen
1165