From 7412c3a072f81cdc782872e5c8e2435bafdec519 Mon Sep 17 00:00:00 2001 From: yangfan479 Date: Mon, 29 Apr 2024 11:51:25 +0800 Subject: [PATCH] =?UTF-8?q?[=E6=8B=86=E6=B5=81=E6=B0=B4=E9=80=82=E9=85=8D]?= =?UTF-8?q?=E5=A4=9A=E5=B1=8F=E4=B8=8B=E4=B8=BB=E5=B1=8F=E4=BD=BF=E8=83=BD?= =?UTF-8?q?=E8=84=8F=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangfan479 --- .../rs_display_render_node_drawable.cpp | 114 ++++++++++++++++-- .../rs_display_render_node_drawable.h | 11 +- .../core/pipeline/rs_uni_render_visitor.cpp | 5 +- .../include/params/rs_render_thread_params.h | 12 ++ .../include/pipeline/rs_paint_filter_canvas.h | 5 + .../rs_render_node_drawable_adapter.cpp | 4 + 6 files changed, 132 insertions(+), 19 deletions(-) diff --git a/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.cpp b/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.cpp index f271087bf5..497b8f19d3 100644 --- a/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.cpp +++ b/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.cpp @@ -244,14 +244,13 @@ static inline Drawing::Region GetFilpedRegion(std::vector& rects, ScreenI return region; } -static inline void ClipRegion(Drawing::Canvas& canvas, Drawing::Region& region) +static void ClipRegion(Drawing::Canvas& canvas, Drawing::Region& region, bool clear = true) { if (region.IsEmpty()) { // [planning] Remove this after frame buffer can cancel canvas.ClipRect(Drawing::Rect()); } else if (region.IsRect()) { canvas.ClipRegion(region); - canvas.Clear(Drawing::Color::COLOR_TRANSPARENT); } else { RS_TRACE_NAME("RSDisplayDrawable: clipPath"); #ifdef RS_ENABLE_VK @@ -269,6 +268,11 @@ static inline void ClipRegion(Drawing::Canvas& canvas, Drawing::Region& region) canvas.ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true); #endif } + + // clear canvas after clip region if need + if (clear && !region.IsEmpty()) { + canvas.Clear(Drawing::Color::COLOR_TRANSPARENT); + } } bool RSDisplayRenderNodeDrawable::CheckDisplayNodeSkip(std::shared_ptr displayNode, @@ -413,8 +417,11 @@ void RSDisplayRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas) if (mirroredNode) { DrawMirrorScreen(*displayNodeSp, *params, processor); } else { + bool isOpDropped = uniParam->IsOpDropped(); + uniParam->SetOpDropped(false); auto expandProcessor = std::static_pointer_cast(processor); DrawExpandScreen(*expandProcessor); + uniParam->SetOpDropped(isOpDropped); } processor->PostProcess(); return; @@ -467,6 +474,7 @@ void RSDisplayRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas) curCanvas_->ConcatMatrix(params->GetMatrix()); if (uniParam->IsOpDropped()) { auto region = GetFilpedRegion(damageRegionrects, screenInfo); + uniParam->SetClipRegion(region); ClipRegion(*curCanvas_, region); } else { curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT); @@ -522,6 +530,11 @@ void RSDisplayRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas) void RSDisplayRenderNodeDrawable::DrawMirrorScreen(RSDisplayRenderNode& displayNodeSp, RSDisplayRenderParams& params, std::shared_ptr processor) { + auto uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams().get(); + if (!uniParam) { + RS_LOGE("RSDisplayRenderNodeDrawable::DrawMirrorScreen uniParam is null"); + return; + } auto mirroredNode = params.GetMirrorSource().lock(); auto mirroredParams = static_cast(mirroredNode->GetRenderParams().get()); auto hasSecSurface = mirroredParams->GetDisplayHasSecSurface(); @@ -547,6 +560,11 @@ void RSDisplayRenderNodeDrawable::DrawMirrorScreen(RSDisplayRenderNode& displayN curCanvas_->Save(); ScaleMirrorIfNeed(displayNodeSp, processor); RotateMirrorCanvasIfNeed(displayNodeSp); + PrepareOffscreenRender(*mirroredNode); + curCanvas_->Save(); + Drawing::Region clipRegion; + clipRegion.Clone(uniParam->GetClipRegion()); + ResetRotateIfNeed(*mirroredNode, *mirroredProcessor, clipRegion); std::shared_ptr cacheImageProcessed = GetCacheImageFromMirrorNode(mirroredNode); mirroredNode->SetCacheImgForCapture(nullptr); bool noSpecialLayer = (!hasSecSurface[mirroredNode->GetScreenId()] && @@ -554,8 +572,9 @@ void RSDisplayRenderNodeDrawable::DrawMirrorScreen(RSDisplayRenderNode& displayN if (cacheImageProcessed && noSpecialLayer) { RS_LOGD("RSDisplayRenderNodeDrawable::DrawMirrorScreen, Enable recording optimization."); RSUniRenderThread::Instance().GetRSRenderThreadParams()->SetHasCaptureImg(true); - processCacheImage(*cacheImageProcessed, *mirroredNode, *mirroredProcessor); + ProcessCacheImage(*cacheImageProcessed); } + curCanvas_->Restore(); auto mirroredNodeDrawable = std::static_pointer_cast( DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(std::move(mirroredNode))); // set mirror screen capture param @@ -563,14 +582,24 @@ void RSDisplayRenderNodeDrawable::DrawMirrorScreen(RSDisplayRenderNode& displayN float mirrorScaleY = mirroredProcessor->GetMirrorScaleY(); RSUniRenderThread::SetCaptureParam(CaptureParam(true, false, true, mirrorScaleX, mirrorScaleY)); parentSurfaceMatrix_ = curCanvas_->GetTotalMatrix(); + if (uniParam->IsOpDropped() && cacheImageProcessed && noSpecialLayer) { + ClipRegion(*curCanvas_, clipRegion, false); + } + bool isOpDropped = uniParam->IsOpDropped(); + uniParam->SetOpDropped(false); mirroredNodeDrawable->OnCapture(*curCanvas_); + uniParam->SetOpDropped(isOpDropped); RSUniRenderThread::ResetCaptureParam(); + FinishOffscreenRender(Drawing::SamplingOptions(Drawing::CubicResampler::Mitchell())); curCanvas_->Restore(); RSUniRenderThread::Instance().GetRSRenderThreadParams()->SetHasCaptureImg(false); RSUniRenderThread::Instance().GetRSRenderThreadParams()->SetStartVisit(false); } else { + bool isOpDropped = uniParam->IsOpDropped(); + uniParam->SetOpDropped(false); mirroredNode->SetOriginScreenRotation(displayNodeSp.GetOriginScreenRotation()); processor->ProcessDisplaySurface(*mirroredNode); + uniParam->SetOpDropped(isOpDropped); } } @@ -617,24 +646,34 @@ void RSDisplayRenderNodeDrawable::SetCanvasBlack(RSProcessor& processor) curCanvas_->SetDisableFilterCache(false); } -void RSDisplayRenderNodeDrawable::processCacheImage(Drawing::Image& cacheImageProcessed, - RSDisplayRenderNode& mirroredNode, RSUniRenderVirtualProcessor& mirroredProcessor) +void RSDisplayRenderNodeDrawable::ResetRotateIfNeed(RSDisplayRenderNode& mirroredNode, + RSUniRenderVirtualProcessor& mirroredProcessor, Drawing::Region& clipRegion) { - curCanvas_->Save(); - if (mirroredNode.GetResetRotate()) { - Drawing::Matrix invertMatrix; - if (mirroredProcessor.GetScreenTransformMatrix().Invert(invertMatrix)) { - // If both canvas and skImage have rotated, we need to reset the canvas - curCanvas_->ConcatMatrix(invertMatrix); + Drawing::Matrix invertMatrix; + if (mirroredNode.GetResetRotate() && + mirroredProcessor.GetScreenTransformMatrix().Invert(invertMatrix)) { + // If both canvas and skImage have rotated, we need to reset the canvas + curCanvas_->ConcatMatrix(invertMatrix); + + // If both canvas and clipRegion have rotated, we need to reset the clipRegion + Drawing::Path path; + if (clipRegion.GetBoundaryPath(&path)) { + path.Transform(invertMatrix); + Drawing::Region clip; + clip.SetRect(Drawing::RectI(0, 0, curCanvas_->GetWidth(), curCanvas_->GetHeight())); + clipRegion.SetPath(path, clip); } } +} + +void RSDisplayRenderNodeDrawable::ProcessCacheImage(Drawing::Image& cacheImageProcessed) +{ Drawing::Brush brush; brush.SetAntiAlias(true); curCanvas_->AttachBrush(brush); auto sampling = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NEAREST); curCanvas_->DrawImage(cacheImageProcessed, 0, 0, sampling); curCanvas_->DetachBrush(); - curCanvas_->Restore(); } std::shared_ptr RSDisplayRenderNodeDrawable::GetCacheImageFromMirrorNode( @@ -982,4 +1021,55 @@ void RSDisplayRenderNodeDrawable::DrawCurtainScreen( canvas.DrawRect(Drawing::Rect(0, 0, screenWidth, screenHeight)); canvas.DetachBrush(); } + +void RSDisplayRenderNodeDrawable::PrepareOffscreenRender(const RSRenderNode& node) +{ + // cleanup + canvasBackup_ = nullptr; + offscreenSurface_ = nullptr; + // check offscreen size and hardware renderer + const auto& property = node.GetRenderProperties(); + int32_t offscreenWidth = property.GetFrameWidth(); + int32_t offscreenHeight = property.GetFrameHeight(); + if (offscreenWidth <= 0 || offscreenHeight <= 0) { + RS_LOGE("RSDisplayRenderNodeDrawable::PrepareOffscreenRender, offscreenWidth or offscreenHeight is invalid"); + return; + } + if (curCanvas_->GetSurface() == nullptr) { + curCanvas_->ClipRect(Drawing::Rect(0, 0, offscreenWidth, offscreenHeight), Drawing::ClipOp::INTERSECT, false); + RS_LOGE("RSDisplayRenderNodeDrawable::PrepareOffscreenRender, current surface is nullptr"); + return; + } + // create offscreen surface and canvas + offscreenSurface_ = curCanvas_->GetSurface()->MakeSurface(offscreenWidth, offscreenHeight); + if (offscreenSurface_ == nullptr) { + RS_LOGE("RSDisplayRenderNodeDrawable::PrepareOffscreenRender, offscreenSurface is nullptr"); + curCanvas_->ClipRect(Drawing::Rect(0, 0, offscreenWidth, offscreenHeight), Drawing::ClipOp::INTERSECT, false); + return; + } + auto offscreenCanvas = std::make_shared(offscreenSurface_.get()); + + // copy current canvas properties into offscreen canvas + offscreenCanvas->CopyConfiguration(*curCanvas_); + + // backup current canvas and replace with offscreen canvas + canvasBackup_ = std::exchange(curCanvas_, offscreenCanvas); +} + +void RSDisplayRenderNodeDrawable::FinishOffscreenRender(const Drawing::SamplingOptions& sampling) +{ + if (canvasBackup_ == nullptr) { + RS_LOGE("RSDisplayRenderNodeDrawable::FinishOffscreenRender, canvasBackup_ is nullptr"); + return; + } + // draw offscreen surface to current canvas + Drawing::Brush paint; + paint.SetAntiAlias(true); + canvasBackup_->AttachBrush(paint); + canvasBackup_->DrawImage(*offscreenSurface_->GetImageSnapshot().get(), 0, 0, sampling); + canvasBackup_->DetachBrush(); + // restore current canvas and cleanup + offscreenSurface_ = nullptr; + curCanvas_ = std::move(canvasBackup_); +} } // namespace OHOS::Rosen::DrawableV2 diff --git a/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.h b/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.h index 4534fda463..45064ffc0b 100644 --- a/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.h +++ b/rosen/modules/render_service/core/drawable/rs_display_render_node_drawable.h @@ -61,14 +61,19 @@ private: void PostClearMemoryTask() const; std::shared_ptr GetCacheImageFromMirrorNode( std::shared_ptr mirrorNode); - void processCacheImage(Drawing::Image& cacheImageProcessed, - RSDisplayRenderNode& mirroredNode, RSUniRenderVirtualProcessor& mirroredProcessor); + void ResetRotateIfNeed(RSDisplayRenderNode& mirroredNode, RSUniRenderVirtualProcessor& mirroredProcessor, + Drawing::Region& clipRegion); + void ProcessCacheImage(Drawing::Image& cacheImageProcessed); void SetCanvasBlack(RSProcessor& processor); + // Prepare for off-screen render + void PrepareOffscreenRender(const RSRenderNode& node); + void FinishOffscreenRender(const Drawing::SamplingOptions& sampling); using Registrar = RenderNodeDrawableRegistrar; static Registrar instance_; mutable std::shared_ptr curCanvas_; - Drawing::Region clipRegion_; + std::shared_ptr offscreenSurface_; // temporary holds offscreen surface + std::shared_ptr canvasBackup_; // backup current canvas before offscreen rende bool canvasRotation_ = false; }; } // namespace DrawableV2 diff --git a/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.cpp b/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.cpp index ae84f53c94..00225c616a 100644 --- a/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.cpp +++ b/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.cpp @@ -215,10 +215,6 @@ void RSUniRenderVisitor::PartialRenderOptionInit() { partialRenderType_ = RSSystemProperties::GetUniPartialRenderEnabled(); isPartialRenderEnabled_ = (partialRenderType_ != PartialRenderType::DISABLED); - sptr screenManager = CreateOrGetScreenManager(); - auto screenNum = screenManager->GetAllScreenIds().size(); - isPartialRenderEnabled_ = (screenNum <= 1) && (partialRenderType_ != PartialRenderType::DISABLED) && - RSMainThread::Instance()->IsSingleDisplay(); dirtyRegionDebugType_ = RSSystemProperties::GetDirtyRegionDebugType(); surfaceRegionDebugType_ = RSSystemProperties::GetSurfaceRegionDfxType(); isRegionDebugEnabled_ = (dirtyRegionDebugType_ != DirtyRegionDebugType::DISABLED) || @@ -1552,6 +1548,7 @@ bool RSUniRenderVisitor::BeforeUpdateSurfaceDirtyCalc(RSSurfaceRenderNode& node) // 1. init and record surface info if (node.GetName().find(CAPTURE_WINDOW_NAME) != std::string::npos) { hasCaptureWindow_[currentVisitDisplay_] = true; + node.SetContentDirty(); } // only need collect first level node's security & skip layer info if (node.GetId() == node.GetFirstLevelNodeId()) { diff --git a/rosen/modules/render_service_base/include/params/rs_render_thread_params.h b/rosen/modules/render_service_base/include/params/rs_render_thread_params.h index afd347a235..7063b1cedd 100644 --- a/rosen/modules/render_service_base/include/params/rs_render_thread_params.h +++ b/rosen/modules/render_service_base/include/params/rs_render_thread_params.h @@ -227,6 +227,16 @@ public: { return context_.lock(); } + + void SetClipRegion(const Drawing::Region& clipRegion) + { + clipRegion_.Clone(clipRegion); + } + + const Drawing::Region& GetClipRegion() const + { + return clipRegion_; + } private: bool startVisit_ = false; bool hasCaptureImg_ = false; @@ -262,6 +272,8 @@ private: bool isUniRenderAndOnVsync_ = false; std::weak_ptr context_; + Drawing::Region clipRegion_; + friend class RSMainThread; friend class RSUniRenderVisitor; friend class RSDirtyRectsDfx; diff --git a/rosen/modules/render_service_base/include/pipeline/rs_paint_filter_canvas.h b/rosen/modules/render_service_base/include/pipeline/rs_paint_filter_canvas.h index ad9a6bfe2e..af4672495c 100644 --- a/rosen/modules/render_service_base/include/pipeline/rs_paint_filter_canvas.h +++ b/rosen/modules/render_service_base/include/pipeline/rs_paint_filter_canvas.h @@ -274,6 +274,11 @@ public: bool GetRecordingState() const override; void SetRecordingState(bool flag) override; + const std::stack& GetOffscreenDataList() const + { + return offscreenDataList_; + } + protected: using Env = struct { Color envForegroundColor_; diff --git a/rosen/modules/render_service_base/src/drawable/rs_render_node_drawable_adapter.cpp b/rosen/modules/render_service_base/src/drawable/rs_render_node_drawable_adapter.cpp index bebd5343c4..a9c6ff49e3 100644 --- a/rosen/modules/render_service_base/src/drawable/rs_render_node_drawable_adapter.cpp +++ b/rosen/modules/render_service_base/src/drawable/rs_render_node_drawable_adapter.cpp @@ -300,6 +300,10 @@ bool RSRenderNodeDrawableAdapter::QuickReject(Drawing::Canvas& canvas, RectF loc Drawing::Rect dst; canvas.GetTotalMatrix().MapRect( dst, { localDrawRect.GetLeft(), localDrawRect.GetTop(), localDrawRect.GetRight(), localDrawRect.GetBottom() }); + auto originalCanvas = paintFilterCanvas->GetOriginalCanvas(); + if (originalCanvas && !paintFilterCanvas->GetOffscreenDataList().empty()) { + originalCanvas->GetTotalMatrix().MapRect(dst, dst); + } auto deviceClipRegion = paintFilterCanvas->GetCurDirtyRegion(); Drawing::Region dstRegion; dstRegion.SetRect(dst.RoundOut()); -- Gitee