From b8c6890ca7fee0a4e586257c2665d1223041682d Mon Sep 17 00:00:00 2001 From: tttaaaooo Date: Thu, 14 Mar 2024 15:01:01 +0800 Subject: [PATCH] sync and update opinc feature. Signed-off-by: tttaaaooo Change-Id: I3034ec6e489d418cb57f2d5a85e7dfe225d99d4f --- graphic_config.gni | 13 +- rosen/modules/2d_graphics/BUILD.gn | 7 +- .../2d_graphics/include/draw/OpListHandle.h | 19 +- .../src/drawing/draw/OpListHandle.cpp | 1 + .../src/drawing/draw/core_canvas.cpp | 55 +- .../src/drawing/draw/core_canvas.h | 7 +- .../drawing/engine_adapter/impl_factory.cpp | 2 +- .../impl_interface/core_canvas_impl.h | 7 +- .../skia_adapter/skia_canvas.cpp | 76 ++- .../engine_adapter/skia_adapter/skia_canvas.h | 14 +- .../skia_adapter/skia_canvas_autocache.cpp | 625 ++++++++++++++++++ .../skia_adapter/skia_canvas_autocache.h | 133 ++++ .../skia_adapter/skia_canvas_op.h | 63 ++ .../skia_adapter/skia_impl_factory.cpp | 5 +- .../skia_adapter/skia_oplist_handle.h | 42 ++ rosen/modules/render_service/BUILD.gn | 4 +- .../core/pipeline/rs_uni_render_visitor.cpp | 111 +++- .../core/pipeline/rs_uni_render_visitor.h | 8 +- rosen/modules/render_service_base/BUILD.gn | 7 +- .../include/pipeline/rs_paint_filter_canvas.h | 7 +- .../include/pipeline/rs_render_node.h | 10 +- .../include/property/rs_properties.h | 6 - .../src/pipeline/rs_paint_filter_canvas.cpp | 25 +- .../src/pipeline/rs_render_node.cpp | 95 ++- .../src/platform/ohos/BUILD.gn | 4 +- .../platform/ohos/rs_system_properties.cpp | 11 +- .../src/property/rs_properties.cpp | 49 -- 27 files changed, 1165 insertions(+), 241 deletions(-) create mode 100644 rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.cpp create mode 100644 rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.h create mode 100644 rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_op.h create mode 100644 rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_oplist_handle.h diff --git a/graphic_config.gni b/graphic_config.gni index 5f0b04fe9d..42c676c4fd 100644 --- a/graphic_config.gni +++ b/graphic_config.gni @@ -29,7 +29,7 @@ declare_args() { graphic_2d_feature_enable_flutter_vulkan = false graphic_2d_feature_enable_opengl = true graphic_2d_feature_enable_ddgr = false - graphic_2d_feature_enable_ddgr_opinc = false + graphic_2d_feature_enable_opinc = false graphic_2d_feature_enable_filter_cache = true graphic_2d_feature_parallel_upload_enable = true enable_text_gine = true @@ -61,6 +61,7 @@ if (graphic_2d_feature_product == "phone") { graphic_2d_feature_enable_vulkan = true graphic_2d_feature_enable_ddgr = false graphic_2d_feature_enable_stack_culling = true + graphic_2d_feature_enable_opinc = false } gpu_defines = [] @@ -78,12 +79,8 @@ if (graphic_2d_feature_ace_enable_gpu) { "RS_ENABLE_VK", ] if (graphic_2d_feature_enable_ddgr) { - graphic_2d_feature_enable_ddgr_opinc = true gpu_defines += [ "ENABLE_DDGR_OPTIMIZE" ] import("//foundation/graphic/graphic_2d_ext/ddgr/config.gni") - if (graphic_2d_feature_enable_ddgr_opinc) { - gpu_defines += [ "DDGR_ENABLE_FEATURE_OPINC" ] - } } } if (graphic_2d_feature_enable_opengl) { @@ -95,6 +92,12 @@ if (graphic_2d_feature_ace_enable_gpu) { if (graphic_2d_feature_enable_stack_culling) { gpu_defines += [ "RS_ENABLE_STACK_CULLING" ] } + + if (graphic_2d_feature_enable_opinc) { + import("//foundation/graphic/graphic_2d_ext/opinc/config.gni") + gpu_defines += [ "DDGR_ENABLE_FEATURE_OPINC" ] + } + if (graphic_2d_feature_enable_recording_dcl) { rs_enable_recording_dcl = true gpu_defines += [ "ENABLE_RECORDING_DCL" ] diff --git a/rosen/modules/2d_graphics/BUILD.gn b/rosen/modules/2d_graphics/BUILD.gn index abe51d131e..ac4b8f4751 100755 --- a/rosen/modules/2d_graphics/BUILD.gn +++ b/rosen/modules/2d_graphics/BUILD.gn @@ -48,7 +48,7 @@ config("export_config") { defines = [ "ACE_ENABLE_GPU" ] } - if (graphic_2d_feature_enable_ddgr_opinc) { + if (graphic_2d_feature_enable_opinc) { defines += [ "DDGR_ENABLE_FEATURE_OPINC" ] } } @@ -122,6 +122,7 @@ template("graphics2d_source_set") { "$drawing_src_dir/engine_adapter/skia_adapter/skia_blender.cpp", "$drawing_src_dir/engine_adapter/skia_adapter/skia_camera.cpp", "$drawing_src_dir/engine_adapter/skia_adapter/skia_canvas.cpp", + "$drawing_src_dir/engine_adapter/skia_adapter/skia_canvas_autocache.cpp", "$drawing_src_dir/engine_adapter/skia_adapter/skia_color_filter.cpp", "$drawing_src_dir/engine_adapter/skia_adapter/skia_color_space.cpp", "$drawing_src_dir/engine_adapter/skia_adapter/skia_data.cpp", @@ -235,7 +236,7 @@ template("graphics2d_source_set") { defines += [ "ROSEN_EMULATOR" ] } - if (graphic_2d_feature_enable_ddgr_opinc) { + if (graphic_2d_feature_enable_opinc) { defines += [ "DDGR_ENABLE_FEATURE_OPINC" ] } @@ -264,9 +265,7 @@ template("graphics2d_source_set") { graphic_2d_feature_enable_ddgr) { defines += [ "ENABLE_DDGR_OPTIMIZE" ] sources += ddgr_adapter_opt_set.drawing_ddgr_adapter_src_set - include_dirs += ddgr_adapter_opt_set.drawing_ddgr_adapter_include_set - public_deps += [ "$graphic_2d_ext_root/ddgr:libddgr" ] } diff --git a/rosen/modules/2d_graphics/include/draw/OpListHandle.h b/rosen/modules/2d_graphics/include/draw/OpListHandle.h index da06c35b7f..9fad950707 100644 --- a/rosen/modules/2d_graphics/include/draw/OpListHandle.h +++ b/rosen/modules/2d_graphics/include/draw/OpListHandle.h @@ -16,6 +16,8 @@ #ifndef OP_LIST_HANDLE_H #define OP_LIST_HANDLE_H +#include +#include #include "drawing/engine_adapter/impl_interface/OpListHandleImpl.h" namespace OHOS { @@ -36,9 +38,23 @@ enum CanDrawOpErrType : int { class DRAWING_API OpListHandle { public: +struct OpInfo { + bool canReUseCache = false; + int num = 0; + int percent = 0; + Rect unionRect; + std::vector drawAreaRects; +}; + OpListHandle(); + OpListHandle(OpInfo opinfo); ~OpListHandle() {} + const OpInfo &GetOpInfo() const + { + return opInfo_; + } + template T* GetImpl() const { @@ -46,7 +62,8 @@ template } private: - std::shared_ptr opImpl_; + std::shared_ptr opImpl_; // for opinc diff + OpInfo opInfo_; }; } // namespace Drawing } // namespace Rosen diff --git a/rosen/modules/2d_graphics/src/drawing/draw/OpListHandle.cpp b/rosen/modules/2d_graphics/src/drawing/draw/OpListHandle.cpp index 8b0f28071d..b6b913f479 100644 --- a/rosen/modules/2d_graphics/src/drawing/draw/OpListHandle.cpp +++ b/rosen/modules/2d_graphics/src/drawing/draw/OpListHandle.cpp @@ -21,6 +21,7 @@ namespace Rosen { namespace Drawing { OpListHandle::OpListHandle() : opImpl_(ImplFactory::CreateOplistHandleImpl()) {} +OpListHandle::OpListHandle(OpInfo opinfo) : opImpl_(ImplFactory::CreateOplistHandleImpl()), opInfo_(opinfo) {} } // namespace Drawing } // namespace Rosen diff --git a/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.cpp b/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.cpp index 36046f7534..de95151899 100755 --- a/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.cpp +++ b/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.cpp @@ -189,24 +189,6 @@ void CoreCanvas::DrawVertices(const Vertices& vertices, BlendMode mode) impl_->DrawVertices(vertices, mode); } -void CoreCanvas::DrawBitmap(const Bitmap& bitmap, const scalar px, const scalar py) -{ - AttachPaint(); - impl_->DrawBitmap(bitmap, px, py); -} - -void CoreCanvas::DrawImageNine(const Image* image, const RectI& center, const Rect& dst, - FilterMode filter, const Brush* brush) -{ - impl_->DrawImageNine(image, center, dst, filter, brush); -} - -void CoreCanvas::DrawImageLattice(const Image* image, const Lattice& lattice, const Rect& dst, - FilterMode filter, const Brush* brush) -{ - impl_->DrawImageLattice(image, lattice, dst, filter, brush); -} - // opinc_begin bool CoreCanvas::BeginOpRecording(const Rect* bound, bool isDynamic) { @@ -228,28 +210,35 @@ int CoreCanvas::CanDrawOpList(Drawing::OpListHandle handle) return impl_->CanDrawOpList(handle); } -void CoreCanvas::PreOpListDrawArea(const Matrix& matrix) +bool CoreCanvas::OpCalculateBefore(const Matrix& matrix) { - impl_->PreOpListDrawArea(matrix); + return impl_->OpCalculateBefore(matrix); } -bool CoreCanvas::CanUseOpListDrawArea(Drawing::OpListHandle handle, const Rect* bound) +std::shared_ptr CoreCanvas::OpCalculateAfter(const Rect& bound) { - return impl_->CanUseOpListDrawArea(handle, bound); -} - -Drawing::OpListHandle CoreCanvas::GetOpListDrawArea() -{ - return impl_->GetOpListDrawArea(); -} - -void CoreCanvas::OpincDrawImageRect(const Image& image, Drawing::OpListHandle drawAreas, - const SamplingOptions& sampling, SrcRectConstraint constraint) -{ - impl_->OpincDrawImageRect(image, drawAreas, sampling, constraint); + return impl_->OpCalculateAfter(bound); } // opinc_end +void CoreCanvas::DrawBitmap(const Bitmap& bitmap, const scalar px, const scalar py) +{ + AttachPaint(); + impl_->DrawBitmap(bitmap, px, py); +} + +void CoreCanvas::DrawImageNine(const Image* image, const RectI& center, const Rect& dst, + FilterMode filter, const Brush* brush) +{ + impl_->DrawImageNine(image, center, dst, filter, brush); +} + +void CoreCanvas::DrawImageLattice(const Image* image, const Lattice& lattice, const Rect& dst, + FilterMode filter, const Brush* brush) +{ + impl_->DrawImageLattice(image, lattice, dst, filter, brush); +} + void CoreCanvas::DrawImage(const Image& image, const scalar px, const scalar py, const SamplingOptions& sampling) { AttachPaint(); diff --git a/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.h b/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.h index 9522434d25..2a4c5bc6a9 100755 --- a/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.h +++ b/rosen/modules/2d_graphics/src/drawing/draw/core_canvas.h @@ -379,11 +379,8 @@ public: virtual Drawing::OpListHandle EndOpRecording(); virtual void DrawOpList(Drawing::OpListHandle handle); virtual int CanDrawOpList(Drawing::OpListHandle handle); - virtual void PreOpListDrawArea(const Matrix& matrix); - virtual bool CanUseOpListDrawArea(Drawing::OpListHandle handle, const Rect* bound = nullptr); - virtual Drawing::OpListHandle GetOpListDrawArea(); - virtual void OpincDrawImageRect(const Image& image, Drawing::OpListHandle drawAreas, - const SamplingOptions& sampling, SrcRectConstraint constraint); + virtual bool OpCalculateBefore(const Matrix& matrix); + virtual std::shared_ptr OpCalculateAfter(const Rect& bound); // opinc_end // image diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_factory.cpp b/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_factory.cpp index 53846107db..dab7d8ea90 100644 --- a/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_factory.cpp +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_factory.cpp @@ -254,7 +254,7 @@ std::unique_ptr ImplFactory::CreateSurfaceImpl() std::unique_ptr ImplFactory::CreateOplistHandleImpl() { #ifdef ENABLE_DDGR_OPTIMIZE - if (GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) { + if (SystemProperties::GetGpuApiType() == GpuApiType::DDGR) { return DDGRImplFactory::CreateOplistHandle(); } #endif diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_interface/core_canvas_impl.h b/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_interface/core_canvas_impl.h index 86e7e23509..faaa331c26 100644 --- a/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_interface/core_canvas_impl.h +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/impl_interface/core_canvas_impl.h @@ -114,11 +114,8 @@ public: virtual Drawing::OpListHandle EndOpRecording() = 0; virtual void DrawOpList(Drawing::OpListHandle handle) = 0; virtual int CanDrawOpList(Drawing::OpListHandle handle) = 0; - virtual void PreOpListDrawArea(const Matrix& matrix) = 0; - virtual bool CanUseOpListDrawArea(Drawing::OpListHandle handle, const Rect* bound = nullptr) = 0; - virtual Drawing::OpListHandle GetOpListDrawArea() = 0; - virtual void OpincDrawImageRect(const Image& image, Drawing::OpListHandle drawAreas, - const SamplingOptions& sampling, SrcRectConstraint constraint) = 0; + virtual bool OpCalculateBefore(const Matrix& matrix) = 0; + virtual std::shared_ptr OpCalculateAfter(const Rect& bound) = 0; // opinc_end // image diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.cpp b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.cpp index 50aaded9e0..29910c0c19 100644 --- a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.cpp +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.cpp @@ -31,6 +31,10 @@ #include "skia_text_blob.h" #include "skia_surface.h" #include "include/effects/SkRuntimeEffect.h" +// opinc_begin +#include "skia_canvas_autocache.h" +#include "skia_oplist_handle.h" +// opinc_end #include "draw/core_canvas.h" #include "draw/canvas.h" @@ -623,29 +627,67 @@ int SkiaCanvas::CanDrawOpList(Drawing::OpListHandle handle) return -1; } -void SkiaCanvas::PreOpListDrawArea(const Matrix& matrix) +bool SkiaCanvas::OpCalculateBefore(const Matrix& matrix) { - LOGD("SkiaCanvas! %{public}s, %{public}d", __FUNCTION__, __LINE__); - return; + if (!skCanvas_) { + LOGD("skCanvas_ is null, return on line, %{public}d", __LINE__); + return false; + } + if (skiaCanvasOp_ || skCanvasBackup_) { + LOGD("PreOpListDrawArea is nested %{public}d", __LINE__); + return false; + } + auto m = matrix.GetImpl(); + if (!m) { + LOGD("get matrix null, return on line, %{public}d", __LINE__); + return false; + } + auto tmp = std::make_shared(skCanvas_); + if (!tmp) { + LOGD("create opinccanvas null, return on line, %{public}d", __LINE__); + return false; + } + tmp->Init(m->ExportSkiaMatrix()); + skiaCanvasOp_ = tmp; + skCanvasBackup_ = skiaCanvasOp_.get(); + std::swap(skCanvas_, skCanvasBackup_); + return true; } -bool SkiaCanvas::CanUseOpListDrawArea(Drawing::OpListHandle handle, const Rect* bound) +std::shared_ptr SkiaCanvas::OpCalculateAfter(const Rect& bound) { - LOGD("SkiaCanvas! %{public}s, %{public}d", __FUNCTION__, __LINE__); - return false; -} + std::shared_ptr handle = nullptr; + if (!skCanvas_ || !skiaCanvasOp_) { + LOGD("skCanvas_ is null, return on line, %{public}d", __LINE__); + return handle; + } -Drawing::OpListHandle SkiaCanvas::GetOpListDrawArea() -{ - LOGD("SkiaCanvas! %{public}s, %{public}d", __FUNCTION__, __LINE__); - return {}; -} + do { + auto nodeBound = SkRect::MakeLTRB(bound.GetLeft(), bound.GetTop(), bound.GetRight(), bound.GetBottom()); + if (!skiaCanvasOp_->OpCanCache(nodeBound)) { + break; + } -void SkiaCanvas::OpincDrawImageRect(const Image& image, Drawing::OpListHandle drawAreas, - const SamplingOptions& sampling, SrcRectConstraint constraint) -{ - LOGD("SkiaCanvas! %{public}s, %{public}d", __FUNCTION__, __LINE__); - return; + int opNum = skiaCanvasOp_->GetOpsNum(); + int percent = skiaCanvasOp_->GetOpsPercent(); + auto& skUnionRect = skiaCanvasOp_->GetOpUnionRect(); + auto& skOpListDrawArea = skiaCanvasOp_->GetOpListDrawArea(); + if (skUnionRect.isEmpty() || opNum == 0 || percent == 0 || skOpListDrawArea.size() == 0) { + break; + } + Drawing::Rect unionRect(skUnionRect.left(), skUnionRect.top(), skUnionRect.right(), skUnionRect.bottom()); + std::vector rects; + for (auto &item : skOpListDrawArea) { + rects.emplace_back(Drawing::Rect(item.left(), item.top(), item.right(), item.bottom())); + } + Drawing::OpListHandle::OpInfo opinfo{ true, opNum, percent, std::move(unionRect), std::move(rects) }; + handle = std::make_shared(std::move(opinfo)); + } while (false); + + std::swap(skCanvas_, skCanvasBackup_); // restore canvas + skiaCanvasOp_ = nullptr; + skCanvasBackup_ = nullptr; + return handle; } // opinc_end diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.h b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.h index 13947cbd4b..a79b4a0638 100755 --- a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.h +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas.h @@ -34,6 +34,9 @@ #include "skia_picture.h" #include "skia_region.h" #include "skia_vertices.h" +// opinc_begin +#include "skia_canvas_op.h" +// opinc_end #include "common/rs_macros.h" #include "impl_interface/core_canvas_impl.h" @@ -104,11 +107,8 @@ public: Drawing::OpListHandle EndOpRecording() override; void DrawOpList(Drawing::OpListHandle handle) override; int CanDrawOpList(Drawing::OpListHandle handle) override; - void PreOpListDrawArea(const Matrix& matrix) override; - bool CanUseOpListDrawArea(Drawing::OpListHandle handle, const Rect* bound = nullptr) override; - Drawing::OpListHandle GetOpListDrawArea() override; - void OpincDrawImageRect(const Image& image, Drawing::OpListHandle drawAreas, - const SamplingOptions& sampling, SrcRectConstraint constraint) override; + bool OpCalculateBefore(const Matrix& matrix) override; + std::shared_ptr OpCalculateAfter(const Rect& bound) override; // opinc_end // image @@ -173,6 +173,10 @@ private: bool ConvertToHMSymbolData(const DrawingHMSymbolData& symbol, HMSymbolData& skSymbol); std::shared_ptr skiaCanvas_; SkCanvas* skCanvas_; + // opinc_begin + SkCanvas* skCanvasBackup_; + std::shared_ptr skiaCanvasOp_ = nullptr; + // opinc_end SkiaPaint skiaPaint_; }; } // namespace Drawing diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.cpp b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.cpp new file mode 100644 index 0000000000..533bc2acc6 --- /dev/null +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.cpp @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "skia_canvas_autocache.h" + +#include "include/core/SkPaint.h" +#include "include/core/SkPixmap.h" +#include "include/core/SkSurface.h" +#include "include/core/SkRRect.h" +#include "include/core/SkRegion.h" +#include "include/core/SkPath.h" +#include "include/core/SkVertices.h" +#include "include/core/SkPathEffect.h" +#include "include/core/SkImageFilter.h" +#include "include/core/SkColorFilter.h" +#include "include/core/SkImage.h" +#include "include/core/SkMaskFilter.h" +#include "include/core/SkPicture.h" +#include "include/core/SkTextBlob.h" +#include "include/core/SkDrawable.h" +#include "src/core/SkGlyphRun.h" +#include "src/utils/SkPatchUtils.h" +#include "src/core/SkCanvasPriv.h" +#include "src/core/SkTLazy.h" +#include "src/core/SkMatrixPriv.h" + +#include "utils/log.h" + +namespace OHOS { +namespace Rosen { +namespace Drawing { + +static constexpr int32_t MAX_PERCENTAGE = 8; +static constexpr int32_t MIN_OPS_NUM = 3; +static constexpr int32_t MAX_OPS_NUM = 8; +static constexpr int32_t PERCENT = 100; + +SkiaCanvasAutoCache::SkiaCanvasAutoCache(SkCanvas* canvas) + : SkiaCanvasOp(canvas) +{ + SkMatrix originMatrix = canvas->getTotalMatrix(); + if (!originMatrix.invert(&originMatrixInvert_)) { + LOGE("opinc originMatrix cannot invert"); + opCanCache_ = false; + } + rejectBounds_ = canvas->getTotalMatrix().mapRect(canvas->getLocalClipBounds()); + this->clipRect(SkRect::Make(canvas->getDeviceClipBounds())); + this->setMatrix(originMatrix); + this->addCanvas(canvas); +} + +void SkiaCanvasAutoCache::Init(const SkMatrix& m) +{ + if (!m.invert(&nodeMatrix_)) { + LOGE("opinc originMatrix cannot invert"); + opCanCache_ = false; + } + nodeMatrix_.preConcat(originMatrixInvert_); +} + +bool SkiaCanvasAutoCache::OpCanCache(const SkRect& bound) +{ +#ifdef DDGR_ENABLE_FEATURE_OP_INC_DFX + MergeDrawAreaRects(); +#endif + do { + if (!opCanCache_ || totalOpNums_ == 0 || drawAreaRects_.size() == 0) { + opCanCache_ = false; + calNotSupport_ = __LINE__; + break; + } + MergeDrawAreaRects(); // get unionDrawArea_ + if (((int)(unionDrawArea_.width()) > (int)(bound.width())) || + ((int)(unionDrawArea_.height()) > (int)(bound.height()))) { + opCanCache_ = false; + calNotSupport_ = __LINE__; + break; + } + + percent_ = (totalDrawAreas_ * PERCENT) / ((int)(unionDrawArea_.width()) * (int)(unionDrawArea_.height())); + if (totalOpNums_ >= MAX_OPS_NUM || + (percent_ > MAX_PERCENTAGE && totalOpNums_ > MIN_OPS_NUM)) { + opCanCache_ = true; + break; + } + opCanCache_ = false; + calNotSupport_ = __LINE__; + } while (false); +#ifdef DDGR_ENABLE_FEATURE_OP_INC_DFX + ShowDrawResult(bound); +#endif + return opCanCache_; +} + +std::vector& SkiaCanvasAutoCache::GetOpListDrawArea() +{ + return drawAreaRects_; +} + +SkRect& SkiaCanvasAutoCache::GetOpUnionRect() +{ + return unionDrawArea_; +} + +bool SkiaCanvasAutoCache::OpShouldRecord() const +{ + return opCanCache_; +} + +void SkiaCanvasAutoCache::RecordUnsupportOp(const char* name) +{ + SkPaint paint; + RecordUnsupportOp(name, paint); +} + +void SkiaCanvasAutoCache::RecordUnsupportOp(const char* name, const SkPaint& paint) +{ +#ifdef DDGR_ENABLE_FEATURE_OP_INC_DFX + if (name != nullptr) { + std::string ret(name); + ret.append("_"); + if (paint.asBlendMode().has_value()) { + ret.append(std::string(SkBlendMode_Name(paint.asBlendMode().value()))); + } else { + ret.append("noblend"); + } + ret.append("_"); + ret.append(std::to_string(paint.getAlpha())); + debugNotSupportOps_[ret.c_str()]++; + } +#endif + opCanCache_ = false; +} + +static bool CmpSkRectLTRB(const SkRect& a, const SkRect& b) +{ + if (a.left() < b.left()) { + return true; + } + if (a.left() > b.left()) { + return false; + } + if (a.top() < b.top()) { + return true; + } + if (a.top() > b.top()) { + return false; + } + if (a.right() < b.right()) { + return true; + } + if (a.right() > b.right()) { + return false; + } + if (a.bottom() < b.bottom()) { + return true; + } + if (a.bottom() > b.bottom()) { + return false; + } + return false; +} + +/* The intersecting regins are merged into one rect. The disjoint regions are not merged. */ +void SkiaCanvasAutoCache::MergeDrawAreaRects() +{ + std::vector& drawAreaRects = drawAreaRects_; + for (uint32_t i = 0; i < drawAreaRects.size(); i++) { + for (uint32_t j = 0; j < drawAreaRects.size(); j++) { + if (i != j && drawAreaRects[i].intersects(drawAreaRects[j])) { + drawAreaRects[i].join(drawAreaRects[j]); + drawAreaRects[j] = drawAreaRects[i]; + } + } + } + std::sort(drawAreaRects.begin(), drawAreaRects.end(), CmpSkRectLTRB); + drawAreaRects.erase(std::unique(drawAreaRects.begin(), drawAreaRects.end()), drawAreaRects.end()); + + for (uint32_t i = 0; i < drawAreaRects.size(); i++) { + for (uint32_t j = 0; j < drawAreaRects.size(); j++) { + if (drawAreaRects[i].intersects(drawAreaRects[j])) { + opCanCache_ = false; + return; + } + } + } + + SkRect unionDrawAreaTemp = SkRect::MakeEmpty(); + for (uint32_t i = 0; i < drawAreaRects.size(); i++) { + drawAreaRects[i] = nodeMatrix_.mapRect(drawAreaRects[i]); + unionDrawAreaTemp.join(drawAreaRects[i]); + } + unionDrawAreaTemp.roundOut(&unionDrawArea_); +} + +void SkiaCanvasAutoCache::ShowDrawResult(const SkRect& bound) +{ +#ifdef DDGR_ENABLE_FEATURE_OP_INC_DFX + std::vector& drawAreaRects = drawAreaRects_; + LOGI("DDGR draw result %d, canvas w%d h%d, opNum%d, percent%d, cal%d, " + "node[%.2f %.2f %.2f %.2f] bound[%.2f %.2f %.2f %.2f] reject[%.2f %.2f %.2f %.2f]" + "rect num %d not support %d", + opCanCache_, proxy()->imageInfo().width(), proxy()->imageInfo().height(), + totalOpNums_, percent_, calNotSupport_, + bound.x(), bound.y(), bound.width(), bound().height(), + unionDrawArea_.x(), unionDrawArea_.y(), unionDrawArea_.width(), unionDrawArea_.height(), + (int)drawAreaRects.size(), (int)debugNotSupportOps_.size()); + for (uint32_t i = 0; i < drawAreaRects.size(); i++) { + SkRect &rect = drawAreaRects[i]; + LOGI("DDGR rect[%u], [%.2f %.2f %.2f %.2f]", i, rect.x(), rect.y(), rect.width(), rect.height()); + } + + int j = 0; + for (auto& iter : debugNotSupportOps_) { + LOGI("DDGR ops[%d] [%s %d]", j, iter.first.c_str(), iter.second); + j++; + } +#endif +} + +static SkPaint ProcessPaintForImage(const SkPaint* paint) +{ + SkPaint ret; + if (paint) { + ret = *paint; + ret.setStyle(SkPaint::kFill_Style); + ret.setPathEffect(nullptr); + } + return ret; +} + +static SkPaint ProcessPaintForVertices(SkPaint paint) +{ + paint.setStyle(SkPaint::kFill_Style); + paint.setMaskFilter(nullptr); + paint.setPathEffect(nullptr); + return paint; +} + +static inline bool BlendModeCanCache(SkBlendMode mode) +{ + return (mode == SkBlendMode::kSrcOver) || (mode == SkBlendMode::kSrc); +} + +static inline bool PaintCanCache(const SkPaint& paint) +{ + const auto bm = paint.asBlendMode(); + if (bm && !BlendModeCanCache(bm.value())) { + return false; + } + return true; +} + +bool SkiaCanvasAutoCache::RecordDrawArea(const SkRect& bounds, const SkPaint& paint, const SkMatrix* matrix) +{ + if (!bounds.isFinite() || paint.nothingToDraw()) { + return true; + } + + if (PaintCanCache(paint) && paint.canComputeFastBounds()) { + SkRect tmp = matrix ? matrix->mapRect(bounds) : bounds; + SkRect devRect = getTotalMatrix().mapRect(paint.computeFastBounds(tmp, &tmp)); + if (!devRect.isEmpty()) { + drawAreaRects_.push_back(devRect); + totalOpNums_++; + totalDrawAreas_ += (int)(devRect.width()) * (int)(devRect.height()); + } + return true; + } + return false; +} + +SkCanvas::SaveLayerStrategy SkiaCanvasAutoCache::getSaveLayerStrategy(const SaveLayerRec& rec) +{ + if (OpShouldRecord()) { + if (rec.fPaint && !PaintCanCache(*rec.fPaint)) { + RecordUnsupportOp(__func__, *rec.fPaint); + } + } + return this->SkNWayCanvas::getSaveLayerStrategy(rec); +} + +bool SkiaCanvasAutoCache::onDoSaveBehind(const SkRect* rect) +{ + RecordUnsupportOp(__func__); + return this->SkNWayCanvas::onDoSaveBehind(rect); +} + +void SkiaCanvasAutoCache::onDrawPaint(const SkPaint& paint) +{ + if ((!paint.nothingToDraw()) && !this->isClipEmpty()) { + RecordUnsupportOp(__func__, paint); + } + this->SkNWayCanvas::onDrawPaint(paint); +} + +void SkiaCanvasAutoCache::onDrawBehind(const SkPaint& paint) +{ + RecordUnsupportOp(__func__, paint); + this->SkNWayCanvas::onDrawBehind(paint); +} + +void SkiaCanvasAutoCache::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], + const SkPaint& paint) +{ + if (count <= 0 || paint.nothingToDraw()) { + return; + } + + if (OpShouldRecord()) { + SkRect bounds; + if (count == 2) { // 2: two points + bounds.set(pts[0], pts[1]); + } else { + bounds.setBounds(pts, SkToInt(count)); + } + SkPaint strokePaint = paint; + strokePaint.setStyle(SkPaint::kStroke_Style); + if (!RecordDrawArea(bounds, strokePaint)) { + RecordUnsupportOp(__func__, strokePaint); + } + } + this->SkNWayCanvas::onDrawPoints(mode, count, pts, paint); +} + +void SkiaCanvasAutoCache::onDrawRect(const SkRect& rect, const SkPaint& paint) +{ + if (OpShouldRecord()) { + if (!RecordDrawArea(rect, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawRect(rect, paint); +} + +void SkiaCanvasAutoCache::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) +{ + if (OpShouldRecord()) { + const SkRect& bounds = rrect.getBounds(); + if (!RecordDrawArea(bounds, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawRRect(rrect, paint); +} + +void SkiaCanvasAutoCache::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, + const SkPaint& paint) +{ + if (OpShouldRecord()) { + if (!RecordDrawArea(outer.getBounds(), paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawDRRect(outer, inner, paint); +} + +void SkiaCanvasAutoCache::onDrawRegion(const SkRegion& region, const SkPaint& paint) +{ + if (OpShouldRecord()) { + const SkRect bounds = SkRect::Make(region.getBounds()); + if (!RecordDrawArea(bounds, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawRegion(region, paint); +} + +void SkiaCanvasAutoCache::onDrawOval(const SkRect& rect, const SkPaint& paint) +{ + if (OpShouldRecord()) { + if (!RecordDrawArea(rect, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawOval(rect, paint); +} + +void SkiaCanvasAutoCache::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, + bool useCenter, const SkPaint& paint) +{ + if (OpShouldRecord()) { + if (!RecordDrawArea(rect, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawArc(rect, startAngle, sweepAngle, useCenter, paint); +} + +void SkiaCanvasAutoCache::onDrawPath(const SkPath& path, const SkPaint& paint) +{ + if (OpShouldRecord()) { + if (!path.isInverseFillType()) { + const SkRect& pathBounds = path.getBounds(); + if (!RecordDrawArea(pathBounds, paint)) { + RecordUnsupportOp(__func__, paint); + } + } else { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawPath(path, paint); +} + +/* image not null, SkCanvas::drawImage will RETURN_ON_NULL(image) */ +void SkiaCanvasAutoCache::onDrawImage2(const SkImage* image, SkScalar left, SkScalar top, + const SkSamplingOptions& sampling, const SkPaint* paint) +{ + SkPaint realPaint = paint ? *paint : SkPaint(); + if (OpShouldRecord()) { + SkRect bounds = SkRect::MakeXYWH(left, top, image->width(), image->height()); + if (!RecordDrawArea(bounds, realPaint)) { + RecordUnsupportOp(__func__, realPaint); + } + } + this->SkNWayCanvas::onDrawImage2(image, left, top, sampling, paint); +} + +void SkiaCanvasAutoCache::onDrawImageRect2(const SkImage* image, const SkRect& src, + const SkRect& dst, const SkSamplingOptions& sampling, + const SkPaint* paint, SrcRectConstraint constraint) +{ + if (OpShouldRecord()) { + SkPaint realPaint = ProcessPaintForImage(paint); + if (!RecordDrawArea(dst, realPaint)) { + RecordUnsupportOp(__func__, realPaint); + } + } + this->SkNWayCanvas::onDrawImageRect2(image, src, dst, sampling, paint, constraint); +} + +void SkiaCanvasAutoCache::onDrawImageLattice2(const SkImage* image, const Lattice& lattice, + const SkRect& dst, SkFilterMode filter, + const SkPaint* paint) +{ + if (OpShouldRecord()) { + SkPaint realPaint = ProcessPaintForImage(paint); + if (!RecordDrawArea(dst, realPaint)) { + RecordUnsupportOp(__func__, realPaint); + } + } + this->SkNWayCanvas::onDrawImageLattice2(image, lattice, dst, filter, paint); +} + +/* vertices not null, SkCanvas::drawVertices() will RETURN_ON_NULL(vertices) */ +void SkiaCanvasAutoCache::onDrawVerticesObject(const SkVertices* vertices, + SkBlendMode bmode, const SkPaint& paint) +{ + if (OpShouldRecord()) { + SkPaint realPaint = ProcessPaintForVertices(paint); + if (!BlendModeCanCache(bmode) || !RecordDrawArea(vertices->bounds(), realPaint)) { + RecordUnsupportOp(__func__, realPaint); + } + } + this->SkNWayCanvas::onDrawVerticesObject(vertices, bmode, paint); +} + +void SkiaCanvasAutoCache::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], + const SkPoint texCoords[4], SkBlendMode bmode, + const SkPaint& paint) +{ + if (OpShouldRecord()) { + SkPaint realPaint = ProcessPaintForVertices(paint); + SkRect bounds; + bounds.setBounds(cubics, SkPatchUtils::kNumCtrlPts); + if (!BlendModeCanCache(bmode) || !RecordDrawArea(bounds, realPaint)) { + RecordUnsupportOp(__func__, realPaint); + } + } + this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, paint); +} + +/* picture not null, SkCanvas::drawPicture() will RETURN_ON_NULL(picture) */ +void SkiaCanvasAutoCache::onDrawPicture(const SkPicture* picture, const SkMatrix* m, + const SkPaint* originalPaint) +{ + SkPaint tmpPaint = originalPaint ? *originalPaint : SkPaint(); + const SkPaint* newPaint = &tmpPaint; + if ((picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) || + !RecordDrawArea(picture->cullRect(), tmpPaint, m)) { + RecordUnsupportOp(__func__, tmpPaint); + } + + if (!originalPaint) { + if ((std::fabs(newPaint->getAlphaf() - 1.0f) <= std::numeric_limits::epsilon()) && + newPaint->getColorFilter() == nullptr && + newPaint->getImageFilter() == nullptr && newPaint->asBlendMode() == SkBlendMode::kSrcOver) { + newPaint = nullptr; + } + } + this->SkNWayCanvas::onDrawPicture(picture, m, newPaint); +} + +void SkiaCanvasAutoCache::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) +{ + this->SkNWayCanvas::onDrawDrawable(drawable, matrix); +} + +void SkiaCanvasAutoCache::onDrawGlyphRunList(const SkGlyphRunList& list, const SkPaint& paint) +{ + if (OpShouldRecord()) { + SkRect bounds = list.sourceBounds(); + if (!RecordDrawArea(bounds, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawGlyphRunList(list, paint); +} + +/* blob not null, SkCanvas::drawTextBlob() will RETURN_ON_NULL(blob) */ +void SkiaCanvasAutoCache::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint& paint) +{ + if (OpShouldRecord()) { + if (!RecordDrawArea(blob->bounds().makeOffset({x, y}), paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawTextBlob(blob, x, y, paint); +} + +void SkiaCanvasAutoCache::onDrawAtlas2(const SkImage* image, const SkRSXform xform[], + const SkRect tex[], const SkColor colors[], int count, + SkBlendMode bmode, const SkSamplingOptions& sampling, + const SkRect* cull, const SkPaint* paint) +{ + if (OpShouldRecord()) { + SkPaint realPaint = ProcessPaintForVertices(ProcessPaintForImage(paint)); + if (!cull || !BlendModeCanCache(bmode) || !RecordDrawArea(*cull, realPaint)) { + RecordUnsupportOp(__func__, realPaint); + } + } + this->SkNWayCanvas::onDrawAtlas2(image, xform, tex, colors, count, bmode, sampling, cull, paint); +} + +void SkiaCanvasAutoCache::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) +{ + // enable onDrawAnnotation for skp when debug + RecordUnsupportOp(__func__); + this->SkNWayCanvas::onDrawAnnotation(rect, key, value); +} + +void SkiaCanvasAutoCache::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) +{ + RecordUnsupportOp(__func__); + this->SkNWayCanvas::onDrawShadowRec(path, rec); +} + +void SkiaCanvasAutoCache::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], + QuadAAFlags aa, const SkColor4f& color, SkBlendMode mode) +{ + if (OpShouldRecord()) { + SkPaint paint; + paint.setColor(color); + paint.setBlendMode(mode); + if (!BlendModeCanCache(mode) || !RecordDrawArea(rect, paint)) { + RecordUnsupportOp(__func__, paint); + } + } + this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, color, mode); +} + +void SkiaCanvasAutoCache::onDrawEdgeAAImageSet2(const ImageSetEntry set[], int count, + const SkPoint dstClips[], + const SkMatrix preViewMatrices[], + const SkSamplingOptions& sampling, + const SkPaint* paint, + SrcRectConstraint constraint) +{ + RecordUnsupportOp(__func__); + this->SkNWayCanvas::onDrawEdgeAAImageSet2( + set, count, dstClips, preViewMatrices, sampling, paint, constraint); +} + +sk_sp SkiaCanvasAutoCache::onNewSurface(const SkImageInfo& info, + const SkSurfaceProps& props) +{ + return this->proxy()->makeSurface(info, &props); +} + +bool SkiaCanvasAutoCache::onPeekPixels(SkPixmap* pixmap) +{ + return this->proxy()->peekPixels(pixmap); +} + +bool SkiaCanvasAutoCache::onAccessTopLayerPixels(SkPixmap* pixmap) +{ + SkImageInfo info; + size_t rowByteSize; + + void* addr = this->proxy()->accessTopLayerPixels(&info, &rowByteSize); + if (!addr) { + return false; + } + + if (pixmap) { + pixmap->reset(info, addr, rowByteSize); + } + return true; +} + +SkImageInfo SkiaCanvasAutoCache::onImageInfo() const +{ + return this->proxy()->imageInfo(); +} + +bool SkiaCanvasAutoCache::onGetProps(SkSurfaceProps* props) const +{ + return this->proxy()->getProps(props); +} +} // namespace Drawing +} // namespace Rosen +} // namespace OHOS diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.h b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.h new file mode 100644 index 0000000000..b671ea27a7 --- /dev/null +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_autocache.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SKIACANVAS_AUTOCACHE_H +#define SKIACANVAS_AUTOCACHE_H + +#include +#include +#include +#include "skia_canvas_op.h" +#include "include/utils/SkNWayCanvas.h" +#include "include/core/SkCanvasVirtualEnforcer.h" + +namespace OHOS { +namespace Rosen { +namespace Drawing { +class SkiaCanvasAutoCache : public SkiaCanvasOp { +public: + explicit SkiaCanvasAutoCache(SkCanvas* canvas); + + // drawing func + bool OpCanCache(const SkRect& bound) override; + std::vector& GetOpListDrawArea() override; + SkRect& GetOpUnionRect() override; + + int GetOpsNum() override + { + return totalOpNums_; + } + + int GetOpsPercent() override + { + return percent_; + } + + void Init(const SkMatrix& m); + + // dfx + void ShowDrawResult(const SkRect &bound); + + SkISize getBaseLayerSize() const override + { + return proxy()->getBaseLayerSize(); + } + + GrRecordingContext* recordingContext() override + { + return proxy()->recordingContext(); + } + +protected: + SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override; + bool onDoSaveBehind(const SkRect* rect) override; + void onDrawPaint(const SkPaint&) override; + void onDrawBehind(const SkPaint&) override; + void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override; + void onDrawRect(const SkRect&, const SkPaint&) override; + void onDrawRRect(const SkRRect&, const SkPaint&) override; + void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override; + void onDrawRegion(const SkRegion&, const SkPaint&) override; + void onDrawOval(const SkRect&, const SkPaint&) override; + void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override; + void onDrawPath(const SkPath&, const SkPaint&) override; + + void onDrawImage2(const SkImage*, SkScalar, SkScalar, const SkSamplingOptions&, + const SkPaint*) override; + void onDrawImageRect2(const SkImage*, const SkRect&, const SkRect&, const SkSamplingOptions&, + const SkPaint*, SrcRectConstraint) override; + void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect&, SkFilterMode, + const SkPaint*) override; + void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int, + SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override; + + void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override; + void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], + const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint) override; + void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override; + void onDrawDrawable(SkDrawable*, const SkMatrix*) override; + + void onDrawGlyphRunList(const SkGlyphRunList&, const SkPaint&) override; + void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint& paint) override; + void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override; + void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override; + + void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], QuadAAFlags, const SkColor4f&, + SkBlendMode) override; + void onDrawEdgeAAImageSet2(const ImageSetEntry[], int count, const SkPoint[], const SkMatrix[], + const SkSamplingOptions&, const SkPaint*, SrcRectConstraint) override; + + // draw on actual canvas + sk_sp onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override; + bool onPeekPixels(SkPixmap* pixmap) override; + bool onAccessTopLayerPixels(SkPixmap* pixmap) override; + SkImageInfo onImageInfo() const override; + bool onGetProps(SkSurfaceProps* props) const override; + +private: + bool OpShouldRecord() const; + void RecordUnsupportOp(const char* name); + void RecordUnsupportOp(const char* name, const SkPaint& paint); + bool RecordDrawArea(const SkRect& bounds, const SkPaint& paint, const SkMatrix* matrix = nullptr); + void MergeDrawAreaRects(); + SkCanvas* proxy() const { return fList[0]; } + + std::vector drawAreaRects_; + SkRect unionDrawArea_ = SkRect::MakeEmpty(); + SkRect rejectBounds_ = SkRect::MakeEmpty(); + SkMatrix originMatrixInvert_; + SkMatrix nodeMatrix_; + int totalOpNums_ = 0; + int64_t totalDrawAreas_ = 0; + int percent_ = 0; + bool opCanCache_ = true; + std::map debugNotSupportOps_; + int calNotSupport_ = 0; +}; +} // namespace Drawing +} // namespace Rosen +} // namespace OHOS +#endif diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_op.h b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_op.h new file mode 100644 index 0000000000..976f3b191c --- /dev/null +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_canvas_op.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SKIACANVAS_OP_H +#define SKIACANVAS_OP_H + +#include "include/utils/SkNWayCanvas.h" +#include "include/core/SkCanvasVirtualEnforcer.h" + +namespace OHOS { +namespace Rosen { +namespace Drawing { +class SkiaCanvasOp : public SkCanvasVirtualEnforcer { +public: + explicit SkiaCanvasOp(SkCanvas* canvas) + : SkCanvasVirtualEnforcer(canvas->imageInfo().width(), + canvas->imageInfo().height()) {} + + virtual ~SkiaCanvasOp() = default; + + virtual bool OpCanCache(const SkRect& bound) + { + return false; + } + + virtual std::vector& GetOpListDrawArea() + { + static std::vector defaultRects; + return defaultRects; + } + + virtual SkRect& GetOpUnionRect() + { + static SkRect defaultRect; + return defaultRect; + } + + virtual int GetOpsNum() + { + return 0; + } + + virtual int GetOpsPercent() + { + return 0; + } +}; +} // namespace Drawing +} // namespace Rosen +} // namespace OHOS +#endif diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_impl_factory.cpp b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_impl_factory.cpp index ea5bd6122a..7e3716bc3e 100644 --- a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_impl_factory.cpp +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_impl_factory.cpp @@ -49,6 +49,9 @@ #include "skia_adapter/skia_trace_memory_dump.h" #include "skia_adapter/skia_memory_stream.h" #include "skia_adapter/skia_gradient_blur.h" +// opinc_begin +#include "skia_adapter/skia_oplist_handle.h" +// opinc_end namespace OHOS { namespace Rosen { @@ -172,7 +175,7 @@ std::unique_ptr SkiaImplFactory::CreateSurface() // opinc_begin std::unique_ptr SkiaImplFactory::CreateOplistHandle() { - return nullptr; + return std::make_unique(); } // opinc_end diff --git a/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_oplist_handle.h b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_oplist_handle.h new file mode 100644 index 0000000000..88e60ca0d3 --- /dev/null +++ b/rosen/modules/2d_graphics/src/drawing/engine_adapter/skia_adapter/skia_oplist_handle.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SKIA_OPLIST_HANDLE_H +#define SKIA_OPLIST_HANDLE_H + +#include "SkRect.h" +// opinc_begin +#include "draw/OpListHandle.h" +// opinc_end + +namespace OHOS { +namespace Rosen { +namespace Drawing { +class SkiaOpListHandle : public OpListHandleImpl { +public: + static inline constexpr AdapterType TYPE = AdapterType::SKIA_ADAPTER; + + SkiaOpListHandle() = default; + ~SkiaOpListHandle() override {} + + AdapterType GetType() const override + { + return AdapterType::SKIA_ADAPTER; + } +}; +} // namespace Drawing +} // namespace Rosen +} // namespace OHOS +#endif diff --git a/rosen/modules/render_service/BUILD.gn b/rosen/modules/render_service/BUILD.gn index c678f13b4c..bcaeb78a08 100644 --- a/rosen/modules/render_service/BUILD.gn +++ b/rosen/modules/render_service/BUILD.gn @@ -182,8 +182,8 @@ ohos_shared_library("librender_service") { include_dirs += [ "$video_processing_engine_root/interfaces/inner_api" ] } - if (graphic_2d_feature_enable_ddgr_opinc) { - include_dirs += ddgr_adapter_opt_set.ddgr_opinc_include_set + if (graphic_2d_feature_enable_opinc) { + include_dirs += opinc_adapter_opt_set.opinc_include_set } deps = [ 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 4dcfa95f71..73e5556b0a 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 @@ -277,13 +277,19 @@ void RSUniRenderVisitor::UpdateSubTreeInCache(const std::shared_ptrGetAutoCache()->OpincStartMarkStableStaticNode(unchangeMark_, autoCacheChildDisable_); + bool isPrepareAutoCache = autoCacheEnable_ && !isDiscardSurface_ && unchangeMarkEnable_; + if (isPrepareAutoCache) { + child->GetAutoCache()->OpincStartMarkStableNode(unchangeMark_, true); } #endif if (child->IsDirty()) { curDirty_ = child->IsDirty(); child->Prepare(shared_from_this()); +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isPrepareAutoCache) { + child->GetAutoCache()->OpincEndMarkStableNode(unchangeMark_); + } +#endif continue; } // set flag for surface node whose children contain shared transition node @@ -295,11 +301,21 @@ void RSUniRenderVisitor::UpdateSubTreeInCache(const std::shared_ptrIsHardwareEnabledType()) { PrepareSurfaceRenderNode(*surfaceNode); +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isPrepareAutoCache) { + child->GetAutoCache()->OpincEndMarkStableNode(unchangeMark_); + } +#endif return; } } else if (auto effectNode = child->ReinterpretCastTo()) { // effectNode need to update effectRegion so effectNode and use-effect child should be updated PrepareEffectNodeIfCacheReuse(cacheRootNode, effectNode); +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isPrepareAutoCache) { + child->GetAutoCache()->OpincEndMarkStableNode(unchangeMark_); + } +#endif return; } if (child->GetRenderProperties().NeedFilter() || child->GetRenderProperties().GetUseEffect()) { @@ -314,8 +330,8 @@ void RSUniRenderVisitor::UpdateSubTreeInCache(const std::shared_ptrGetSortedChildren()); #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - child->GetAutoCache()->OpincEndMarkStableStaticNode(unchangeMark_, autoCacheChildDisable_); + if (isPrepareAutoCache) { + child->GetAutoCache()->OpincEndMarkStableNode(unchangeMark_); } #endif } @@ -1150,11 +1166,6 @@ void RSUniRenderVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node) RS_OPTIONAL_TRACE_NAME("RSUniRender::Prepare:[" + node.GetName() + "] nodeid: " + std::to_string(node.GetId()) + " pid: " + std::to_string(ExtractPid(node.GetId())) + ", nodeType " + std::to_string(static_cast(node.GetSurfaceNodeType()))); -#ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - node->GetAutoCache()->DisableAutoCacheWithForce(unchangeMark_); - } -#endif if (curDisplayNode_ == nullptr) { ROSEN_LOGE("RSUniRenderVisitor::PrepareSurfaceRenderNode, curDisplayNode_ is nullptr."); return; @@ -1227,7 +1238,7 @@ void RSUniRenderVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node) #ifdef DDGR_ENABLE_FEATURE_OPINC if (autoCacheEnable_ && node.IsappWindow()) { - node->GetAutoCache()->OpincSetInAppStateStart(unchangeMark_, opNodeDepth_, opIncSubtreePropDirty_); + node->GetAutoCache()->OpincSetInAppStateStart(unchangeMarkEnable_, unchangeMark_, isDiscardSurface_); } #endif // Update node properties, including position (dstrect), OldDirty() @@ -1358,7 +1369,7 @@ void RSUniRenderVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node) node.SetOpaqueRegionBaseInfo(screenRect, geoPtr->GetAbsRect(), screenRotation, isFocused, dstCornerRadius); #ifdef DDGR_ENABLE_FEATURE_OPINC if (autoCacheEnable_ && node.IsappWindow()) { - node->GetAutoCache()->OpincSetInAppStateEnd(unchangeMark_); + node->GetAutoCache()->OpincSetInAppStateEnd(unchangeMarkEnable_, unchangeMark_, isDiscardSurface_); } #endif if (node.IsMainWindowType()) { @@ -1541,9 +1552,9 @@ void RSUniRenderVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode &node) curSurfaceNode_->SetSubNodeShouldPaint(); } #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - node->GetAutoCache()->OpincStartMarkStableNode(unchangeMark_, autoCacheChildDisable_, - opIncSubtreePropDirty_, opNodeDepth_); + bool isPrepareAutoCache = autoCacheEnable_ && !isDiscardSurface_ && unchangeMarkEnable_; + if (isPrepareAutoCache) { + node->GetAutoCache()->OpincStartMarkStableNode(unchangeMark_, false); } #endif // if canvasNode is not sub node of surfaceNode, merge the dirtyRegion to curDisplayDirtyManager_ @@ -1651,8 +1662,8 @@ void RSUniRenderVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode &node) dirtyFlag_ = dirtyFlag; prepareClipRect_ = prepareClipRect; #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - node->GetAutoCache()->OpincEndMarkStableNode(unchangeMark_, autoCacheChildDisable_, opNodeDepth_); + if (isPrepareAutoCache) { + node->GetAutoCache()->OpincEndMarkStableNode(unchangeMark_); } #endif #if defined(RS_ENABLE_DRIVEN_RENDER) @@ -1746,7 +1757,7 @@ void RSUniRenderVisitor::DrawDirtyRectForDFX(const RectI& dirtyRect, const Drawi } #else std::string position = std::to_string(dirtyRect.left_) + ',' + std::to_string(dirtyRect.top_) + ',' + - std::to_string(dirtyRect.width_) + ',' + std::to_string(dirtyRect.height_); + std::to_string(dirtyRect.width_) + ',' + std::to_string(dirtyRect.height_) + extra; #endif const int defaultTextOffsetX = edgeWidth; const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the Rect @@ -2687,8 +2698,8 @@ void RSUniRenderVisitor::ProcessDisplayRenderNode(RSDisplayRenderNode& node) } #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheDrawingEnable_) { - DrawCacheRegionForDFX(autoCacheRenderNodeInfos_); + if (autoCacheDrawingEnable_ && !RSSystemParameters::GetDrawingCacheEnableDfx()) { + DrawAutoCacheRegionForDFX(autoCacheRenderNodeInfos_); } #endif @@ -3560,12 +3571,27 @@ bool RSUniRenderVisitor::UpdateCacheSurface(RSRenderNode& node) if (node.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE) { node.SetDrawingCacheRootId(node.GetId()); } + +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (RSSystemParameters::IsOpincRealDrawCacheEnable() && node.GetAutoCache()->isComputeDrawAreaSucc()) { + auto& unionRect = node.GetAutoCache()->GetOpListUnionArea(); + canvas_->Translate(-unionRect.GetLeft(), -unionRect.GetTop()); + } +#endif + node.ProcessRenderContents(*canvas_); // Set a count to label the ProcessChildren in updateCacheProcess updateCacheProcessCnt_++; ProcessChildren(node); updateCacheProcessCnt_--; +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (RSSystemParameters::IsOpincRealDrawCacheEnable() && node.GetAutoCache()->isComputeDrawAreaSucc()) { + auto& unionRect = node.GetAutoCache()->GetOpListUnionArea(); + canvas_->Translate(unionRect.GetLeft(), unionRect.GetTop()); + } +#endif + if (cacheType == CacheType::ANIMATE_PROPERTY) { if (node.GetRenderProperties().IsShadowValid() && !node.GetRenderProperties().IsSpherizeValid()) { @@ -3803,7 +3829,7 @@ void RSUniRenderVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node) { #ifdef DDGR_ENABLE_FEATURE_OPINC if (autoCacheEnable_) { - node.GetAutoCache->OpIncStateInitWithSurface(nodeCacheType_, opincRootRect_, isDiscardSurface_, isSubThread_); + node.GetAutoCache->OpIncStateInitWithSurface(nodeCacheType_, isDiscardSurface_, isSubThread_); } #endif if (isUIFirst_ && isSubThread_) { @@ -4275,15 +4301,31 @@ void RSUniRenderVisitor::UpdateCacheRenderNodeMap(RSRenderNode& node) void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node) { +#ifdef DDGR_ENABLE_FEATURE_OP_INC_DFX + RS_TRACE_NAME_FMT("process_canvas %.2f, %s", canvas_ ? canvas_->GetAlpha() : -1.0f, + node.GetAutoCache()->GetNodeDebugInfo().c_str()); +#endif processedCanvasNodeInCurrentSurface_++; if (!node.ShouldPaint() || (canvas_ && canvas_->GetDeviceClipBounds().IsEmpty() && hardwareEnabledNodes_.empty())) { +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isOpincDropNodeExt_) { + return; + } +#else return; +#endif } auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry()); if (isSkipCanvasNodeOutOfScreen_ && !isSubNodeOfSurfaceInProcess_ && !node.HasSubSurface() && geoPtr && IsOutOfScreenRegion(geoPtr->GetAbsRect()) && !isSubThread_) { +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isOpincDropNodeExt_) { + return; + } +#else return; +#endif } node.MarkNodeSingleFrameComposer(isNodeSingleFrameComposer_); @@ -4302,7 +4344,13 @@ void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node) (node.GetRenderProperties().GetBoundsGeometry()->GetAbsRect()).ToString().c_str()); node.isCoveredByOtherNode_ = false; +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isOpincDropNodeExt_) { + return; + } +#else return; +#endif } } #endif @@ -4346,12 +4394,19 @@ void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node) drivenInfo_->currDrivenRenderMode != DrivenUniRenderMode::RENDER_WITH_NORMAL) { // skip render driven node sub tree if (RSDrivenRenderManager::GetInstance().ClipHoleForDrivenNode(*canvas_, node)) { +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (isOpincDropNodeExt_) { + return; + } +#else return; +#endif } } #endif #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { + bool isProcessAutoCache = autoCacheEnable_ && !isDiscardSurface_ && node->GetAutoCache()->IsOpincUnchangeNode(); + if (isProcessAutoCache) { if (node->GetAutoCache()->BeforeDrawCache(nodeCacheType_, autoCacheRenderNodeInfos_, autoCacheDrawingEnable_, isDiscardSurface_, canvas_, screenInfo_.width, screenInfo_.height)) { return; @@ -4384,7 +4439,7 @@ void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node) if (property.IsSpherizeValid()) { DrawSpherize(node); #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { + if (isProcessAutoCache) { node->GetAutoCache()->AfterDrawCache(nodeCacheType_); } #endif @@ -4401,21 +4456,21 @@ void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node) } CheckAndSetNodeCacheType(node); #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - node->GetAutoCache()->BeforeDrawCache(canvas_, opincRootRect_, isOpincDropNodeExt_); + if (isProcessAutoCache) { + node->GetAutoCache()->OpincCalculateBefore(canvas_, isOpincDropNodeExt_); } #endif DrawChildCanvasRenderNode(node); #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - node->GetAutoCache()->AfterDrawCache(canvas_, isOpincDropNodeExt_); + if (isProcessAutoCache) { + node->GetAutoCache()->OpincCalculateAfter(canvas_, isOpincDropNodeExt_); } #endif notRunCheckAndSetNodeCacheType_ = false; canvas_->Restore(); #ifdef DDGR_ENABLE_FEATURE_OPINC - if (autoCacheEnable_) { - node->GetAutoCache()->AfterDrawCache(canvas_, isDiscardSurface_, nodeCacheType_, true); + if (isProcessAutoCache) { + node->GetAutoCache()->AfterDrawCache(canvas_, isDiscardSurface_, nodeCacheType_); } #endif } diff --git a/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.h b/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.h index 3977411157..2feda28d0b 100644 --- a/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.h +++ b/rosen/modules/render_service/core/pipeline/rs_uni_render_visitor.h @@ -127,9 +127,6 @@ public: drivenInfo_->hasDrivenNodeMarkRender = hasDrivenNodeMarkRender; } -#ifdef DDGR_ENABLE_FEATURE_OPINC - void OpincSetRectChangeState(RSCanvasRenderNode& node, RectI& boundsRect); -#endif void SetHardwareEnabledNodes(const std::vector>& hardwareEnabledNodes); void AssignGlobalZOrderAndCreateLayer(std::vector>& nodesInZOrder); void ScaleMirrorIfNeed(RSDisplayRenderNode& node, bool canvasRotation = false); @@ -410,15 +407,12 @@ private: bool isSubSurfaceEnabled_ = false; #ifdef DDGR_ENABLE_FEATURE_OPINC bool autoCacheEnable_ = false; - bool autoCacheChildDisable_ = false; bool autoCacheDrawingEnable_ = false; RSRenderNode::RSAutoCache::NodeStragyType nodeCacheType_ = RSRenderNode::RSAutoCache::CACHE_NONE; bool unchangeMark_ = false; + bool unchangeMarkEnable_ = false; bool isDiscardSurface_ = true; std::vector> autoCacheRenderNodeInfos_; - int opNodeDepth_ = 0; - bool opIncSubtreePropDirty_ = false; - Drawing::Rect opincRootRect_; bool isOpincDropNodeExt_ = true; #endif diff --git a/rosen/modules/render_service_base/BUILD.gn b/rosen/modules/render_service_base/BUILD.gn index e4422ef33c..455f8be91c 100644 --- a/rosen/modules/render_service_base/BUILD.gn +++ b/rosen/modules/render_service_base/BUILD.gn @@ -379,6 +379,7 @@ ohos_source_set("render_service_base_src") { } include_dirs = [ + "$graphic_2d_root/rosen/modules/utils", "$graphic_2d_root/frameworks/surface/include", "$graphic_2d_root/rosen/modules/render_service_base/src", "$graphic_2d_root/rosen/modules/render_service_base/include", @@ -394,9 +395,9 @@ ohos_source_set("render_service_base_src") { ] external_deps = [ "hilog:libhilog" ] - if (graphic_2d_feature_enable_ddgr_opinc) { - include_dirs += ddgr_adapter_opt_set.ddgr_opinc_include_set - sources += ddgr_adapter_opt_set.ddgr_opinc_src_set + if (graphic_2d_feature_enable_opinc) { + include_dirs += opinc_adapter_opt_set.opinc_include_set + sources += opinc_adapter_opt_set.opinc_src_set } if (!is_mingw && !is_mac && !is_cross_platform) { 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 7804aaefa4..5bd3cd7a96 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 @@ -78,11 +78,8 @@ public: Drawing::OpListHandle EndOpRecording() override; void DrawOpList(Drawing::OpListHandle handle) override; int CanDrawOpList(Drawing::OpListHandle handle) override; - void PreOpListDrawArea(const Drawing::Matrix& matrix) override; - bool CanUseOpListDrawArea(Drawing::OpListHandle handle, const Drawing::Rect* bound = nullptr) override; - Drawing::OpListHandle GetOpListDrawArea() override; - void OpincDrawImageRect(const Drawing::Image& image, Drawing::OpListHandle drawAreas, - const Drawing::SamplingOptions& sampling, Drawing::SrcRectConstraint constraint) override; + bool OpCalculateBefore(const Drawing::Matrix& matrix) override; + std::shared_ptr OpCalculateAfter(const Drawing::Rect& bound) override; // opinc_end void DrawBitmap(const Drawing::Bitmap& bitmap, const Drawing::scalar px, const Drawing::scalar py) override; diff --git a/rosen/modules/render_service_base/include/pipeline/rs_render_node.h b/rosen/modules/render_service_base/include/pipeline/rs_render_node.h index 4f709dcea2..3d82faef80 100644 --- a/rosen/modules/render_service_base/include/pipeline/rs_render_node.h +++ b/rosen/modules/render_service_base/include/pipeline/rs_render_node.h @@ -259,8 +259,8 @@ public: bool HasUseEffectNodes() const; bool HasSubSurface() const; - bool NeedInitCacheSurface() const; - bool NeedInitCacheCompletedSurface() const; + bool NeedInitCacheSurface(); + bool NeedInitCacheCompletedSurface(); bool IsPureContainer() const; bool IsContentNode() const; @@ -316,8 +316,6 @@ public: } #ifdef DDGR_ENABLE_FEATURE_OPINC - bool IsOnTreeDirty(); - void SetDirtyByOnTree(bool forceAddToActiveList = false); Vector4f GetOptionBufferBound() const; Vector2f GetOpincBufferSize() const; Drawing::Rect GetOpincBufferBound() const; @@ -473,6 +471,7 @@ public: class RSAutoCache; const std::shared_ptr& GetAutoCache(); bool isOpincRectOutParent_ = false; + bool isOpincPrepareDis_ = false; #endif #ifdef RS_ENABLE_STACK_CULLING @@ -492,9 +491,6 @@ protected: enum class NodeDirty { CLEAN = 0, - #ifdef DDGR_ENABLE_FEATURE_OPINC - ON_TREE_DIRTY, - #endif DIRTY, }; void SetClean(); diff --git a/rosen/modules/render_service_base/include/property/rs_properties.h b/rosen/modules/render_service_base/include/property/rs_properties.h index 810ec66846..8391fede05 100755 --- a/rosen/modules/render_service_base/include/property/rs_properties.h +++ b/rosen/modules/render_service_base/include/property/rs_properties.h @@ -126,9 +126,6 @@ public: float GetTranslateX() const; float GetTranslateY() const; float GetTranslateZ() const; -#ifdef DDGR_ENABLE_FEATURE_OPINC - bool GetOpincPropDirty() const; -#endif void SetScale(Vector2f scale); void SetScaleX(float sx); @@ -372,9 +369,6 @@ private: bool isDrawn_ = false; bool alphaNeedApply_ = false; bool systemBarEffect_ = false; -#ifdef DDGR_ENABLE_FEATURE_OPINC - bool isOpincPropDirty_ = false; -#endif bool hasBounds_ = false; bool useEffect_ = false; diff --git a/rosen/modules/render_service_base/src/pipeline/rs_paint_filter_canvas.cpp b/rosen/modules/render_service_base/src/pipeline/rs_paint_filter_canvas.cpp index d9a95f7a4c..855ab232cd 100644 --- a/rosen/modules/render_service_base/src/pipeline/rs_paint_filter_canvas.cpp +++ b/rosen/modules/render_service_base/src/pipeline/rs_paint_filter_canvas.cpp @@ -364,35 +364,20 @@ int RSPaintFilterCanvasBase::CanDrawOpList(Drawing::OpListHandle handle) return -1; } -void RSPaintFilterCanvasBase::PreOpListDrawArea(const Matrix& matrix) +bool RSPaintFilterCanvasBase::OpCalculateBefore(const Matrix& matrix) { if (canvas_ != nullptr && OnFilter()) { - canvas_->PreOpListDrawArea(matrix); - } -} - -bool RSPaintFilterCanvasBase::CanUseOpListDrawArea(Drawing::OpListHandle handle, const Rect* bound) -{ - if (canvas_ != nullptr && OnFilter()) { - return canvas_->CanUseOpListDrawArea(handle, bound); + return canvas_->OpCalculateBefore(matrix); } return false; } -Drawing::OpListHandle RSPaintFilterCanvasBase::GetOpListDrawArea() +std::shared_ptr RSPaintFilterCanvasBase::OpCalculateAfter(const Rect& bound) { if (canvas_ != nullptr && OnFilter()) { - return canvas_->GetOpListDrawArea(); - } - return {}; -} - -void RSPaintFilterCanvasBase::OpincDrawImageRect(const Image& image, Drawing::OpListHandle drawAreas, - const SamplingOptions& sampling, SrcRectConstraint constraint) -{ - if (canvas_ != nullptr && OnFilter()) { - canvas_->OpincDrawImageRect(image, drawAreas, sampling, constraint); + return canvas_->OpCalculateAfter(bound); } + return nullptr; } // opinc_end diff --git a/rosen/modules/render_service_base/src/pipeline/rs_render_node.cpp b/rosen/modules/render_service_base/src/pipeline/rs_render_node.cpp index 48daf3d11f..113cc3a1f0 100644 --- a/rosen/modules/render_service_base/src/pipeline/rs_render_node.cpp +++ b/rosen/modules/render_service_base/src/pipeline/rs_render_node.cpp @@ -783,11 +783,7 @@ void RSRenderNode::SetDirty(bool forceAddToActiveList) { bool dirtyEmpty = dirtyTypes_.none(); // TO avoid redundant add, only add if both: 1. on-tree node 2. newly dirty node (or forceAddToActiveList = true) -#ifdef DDGR_ENABLE_FEATURE_OPINC - if (dirtyStatus_ < NodeDirty::DIRTY || dirtyEmpty || forceAddToActiveList) { -#else if (dirtyStatus_ == NodeDirty::CLEAN || dirtyEmpty || forceAddToActiveList) { -#endif if (auto context = GetContext().lock()) { context->AddActiveNode(shared_from_this()); } @@ -795,24 +791,6 @@ void RSRenderNode::SetDirty(bool forceAddToActiveList) dirtyStatus_ = NodeDirty::DIRTY; } -#ifdef DDGR_ENABLE_FEATURE_OPINC -void RSRenderNode::SetDirtyByOnTree(bool forceAddToActiveList) -{ - bool dirtyEmpty = dirtyTypes_.none(); - if (isOnTheTree_ && (dirtyStatus_ < NodeDirty::ON_TREE_DIRTY || dirtyEmpty || forceAddToActiveList)) { - if (auto context = GetContext().lock()) { - context->AddActiveNode(shared_from_this()); - } - } - dirtyStatus_ = NodeDirty::ON_TREE_DIRTY; -} - -bool RSRenderNode::IsOnTreeDirty() -{ - return dirtyStatus_ == NodeDirty::ON_TREE_DIRTY && !GetRenderProperties().IsDirty(); -} -#endif - void RSRenderNode::SetClean() { isNewOnTree_ = false; @@ -1492,7 +1470,7 @@ bool RSRenderNode::GetBootAnimation() const return isBootAnimation_; } -bool RSRenderNode::NeedInitCacheSurface() const +bool RSRenderNode::NeedInitCacheSurface() { auto cacheType = GetCacheType(); int width = 0; @@ -1506,9 +1484,21 @@ bool RSRenderNode::NeedInitCacheSurface() const width = shadowRect.GetWidth(); height = shadowRect.GetHeight(); } else { +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (RSSystemProperties::IsOpincRealDrawCacheEnable() && GetAutoCache()->isComputeDrawAreaSucc()) { + auto& unionRect = GetAutoCache()->GetOpListUnionArea(); + width = unionRect.GetWidth(); + height = unionRect.GetHeight(); + } else { + Vector2f size = GetOptionalBufferSize(); + width = size.x_; + height = size.y_; + } +#else Vector2f size = GetOptionalBufferSize(); width = size.x_; height = size.y_; +#endif } std::scoped_lock lock(surfaceMutex_); if (cacheSurface_ == nullptr) { @@ -1521,11 +1511,25 @@ bool RSRenderNode::NeedInitCacheSurface() const return cacheCanvas->GetWidth() != width || cacheCanvas->GetHeight() != height; } -bool RSRenderNode::NeedInitCacheCompletedSurface() const +bool RSRenderNode::NeedInitCacheCompletedSurface() { +#ifdef DDGR_ENABLE_FEATURE_OPINC + int width = 0; + int height = 0; + if (RSSystemProperties::IsOpincRealDrawCacheEnable() && GetAutoCache()->isComputeDrawAreaSucc()) { + auto& unionRect = GetAutoCache()->GetOpListUnionArea(); + width = static_cast(unionRect.GetWidth()); + height = static_cast(unionRect.GetHeight()); + } else { + Vector2f size = GetOptionalBufferSize(); + width = static_cast(size.x_); + height = static_cast(size.y_); + } +#else Vector2f size = GetOptionalBufferSize(); int width = static_cast(size.x_); int height = static_cast(size.y_); +#endif std::scoped_lock lock(surfaceMutex_); if (cacheCompletedSurface_ == nullptr) { return true; @@ -1569,8 +1573,19 @@ void RSRenderNode::InitCacheSurface(Drawing::GPUContext* gpuContext, ClearCacheS shadowRectOffsetX_ = -shadowRect.GetLeft(); shadowRectOffsetY_ = -shadowRect.GetTop(); } else { +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (RSSystemProperties::IsOpincRealDrawCacheEnable() && GetAutoCache()->isComputeDrawAreaSucc()) { + auto& unionRect = GetAutoCache()->GetOpListUnionArea(); + width = unionRect.GetWidth(); + height = unionRect.GetHeight(); + } else { + width = boundsWidth_; + height = boundsHeight_; + } +#else width = boundsWidth_; height = boundsHeight_; +#endif } #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE) if (gpuContext == nullptr) { @@ -1667,8 +1682,17 @@ void RSRenderNode::DrawCacheSurface(RSPaintFilterCanvas& canvas, uint32_t thread auto cacheType = GetCacheType(); canvas.Save(); Vector2f size = GetOptionalBufferSize(); +#ifdef DDGR_ENABLE_FEATURE_OPINC + float scaleX = 1.0f; + float scaleY = 1.0f; + if (!(RSSystemProperties::IsOpincRealDrawCacheEnable() && GetAutoCache()->isComputeDrawAreaSucc())) { + scaleX = size.x_ / boundsWidth_; + scaleY = size.y_ / boundsHeight_; + } +#else float scaleX = size.x_ / boundsWidth_; float scaleY = size.y_ / boundsHeight_; +#endif canvas.Scale(scaleX, scaleY); auto cacheImage = GetCompletedImage(canvas, threadIndex, isUIFirst); if (cacheImage == nullptr) { @@ -1696,6 +1720,16 @@ void RSRenderNode::DrawCacheSurface(RSPaintFilterCanvas& canvas, uint32_t thread canvas.DrawImage(*cacheImage, -shadowRectOffsetX_ * scaleX + gravityTranslate.x_, -shadowRectOffsetY_ * scaleY + gravityTranslate.y_, samplingOptions); } else { +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (RSSystemProperties::IsOpincRealDrawCacheEnable() && GetAutoCache()->isComputeDrawAreaSucc() && + GetAutoCache()->DrawAutoCache(canvas, *cacheImage, samplingOptions, + Drawing::SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT)) { + canvas.DetachBrush(); + GetAutoCache()->DrawAutoCacheDfx(canvas); + canvas.Restore(); + return; + } +#endif if (canvas.GetTotalMatrix().HasPerspective()) { // In case of perspective transformation, make dstRect 1px outset to anti-alias Drawing::Rect dst(0, 0, cacheImage->GetWidth(), cacheImage->GetHeight()); @@ -1882,7 +1916,7 @@ void RSRenderNode::CheckGroupableAnimation(const PropertyId& id, bool isAnimAdd) bool RSRenderNode::IsForcedDrawInGroup() const { #ifdef DDGR_ENABLE_FEATURE_OPINC - return nodeGroupType_ & NodeGroupType::GROUPED_BY_USER || nodeGroupType_ & NodeGroupType::GROUPED_BY_AUTO; + return nodeGroupType_ & (NodeGroupType::GROUPED_BY_USER | NodeGroupType::GROUPED_BY_AUTO); #else return nodeGroupType_ & NodeGroupType::GROUPED_BY_USER; #endif @@ -1908,7 +1942,7 @@ void RSRenderNode::MarkNodeGroup(NodeGroupType type, bool isNodeGroup, bool incl nodeGroupType_ &= ~type; } #ifdef DDGR_ENABLE_FEATURE_OPINC - if (!(nodeGroupType_ & NodeGroupType::GROUPED_BY_AUTO)) { + if (type != NodeGroupType::GROUPED_BY_AUTO)) { SetDirty(); } #else @@ -2136,11 +2170,7 @@ void RSRenderNode::OnTreeStateChanged() { if (isOnTheTree_) { // Set dirty and force add to active node list, re-generate children list if needed -#ifdef DDGR_ENABLE_FEATURE_OPINC - SetDirtyByOnTree(true); -#else SetDirty(true); -#endif } #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)) if (!isOnTheTree_) { @@ -2483,6 +2513,11 @@ void RSRenderNode::SetDrawingCacheChanged(bool cacheChanged) { isDrawingCacheChanged_ = drawingCacheNeedUpdate_ || cacheChanged; drawingCacheNeedUpdate_ = isDrawingCacheChanged_; +#ifdef DDGR_ENABLE_FEATURE_OPINC + if (RSSystemProperties::IsDdgrOpincEnable()) { + GetAutoCache()->SetOpincCacheChanged(cacheChanged); + } +#endif } bool RSRenderNode::GetDrawingCacheChanged() const { diff --git a/rosen/modules/render_service_base/src/platform/ohos/BUILD.gn b/rosen/modules/render_service_base/src/platform/ohos/BUILD.gn index 0d731609da..fb95ef4eec 100644 --- a/rosen/modules/render_service_base/src/platform/ohos/BUILD.gn +++ b/rosen/modules/render_service_base/src/platform/ohos/BUILD.gn @@ -147,8 +147,8 @@ ohos_source_set("rosen_ohos_sources") { ] } - if (graphic_2d_feature_enable_ddgr_opinc) { - include_dirs += ddgr_adapter_opt_set.ddgr_opinc_include_set + if (graphic_2d_feature_enable_opinc) { + include_dirs += opinc_adapter_opt_set.opinc_include_set } external_deps = [ diff --git a/rosen/modules/render_service_base/src/platform/ohos/rs_system_properties.cpp b/rosen/modules/render_service_base/src/platform/ohos/rs_system_properties.cpp index 28d3e4da21..c5d54f1389 100755 --- a/rosen/modules/render_service_base/src/platform/ohos/rs_system_properties.cpp +++ b/rosen/modules/render_service_base/src/platform/ohos/rs_system_properties.cpp @@ -675,7 +675,7 @@ const DdgrOpincType RSSystemProperties::ddgrOpincType_ = static_cast(std::atoi((system::GetParameter("persist.ddgr.opinctype", "2")).c_str())); const DdgrOpincDfxType RSSystemProperties::ddgrOpincDfxType_ = static_cast(std::atoi(( - system::GetParameter("persist.ddgr.opinctype.debugtype", "0")).c_str())); + system::GetParameter("persist.rosen.ddgr.opinctype.debugtype", "0")).c_str())); DdgrOpincType RSSystemProperties::GetDdgrOpincType() { @@ -689,7 +689,8 @@ bool RSSystemProperties::IsDdgrOpincEnable() GetDdgrOpincType() == DdgrOpincType::DDGR_RENDERCACHE || GetDdgrOpincType() == DdgrOpincType::DDGR_OPINCUPDATE) && (RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR)) || - (GetDdgrOpincType() == DdgrOpincType::DDGR_UNRESTRICTED_MODE); + (GetDdgrOpincType() == DdgrOpincType::DDGR_UNRESTRICTED_MODE) || + (GetDdgrOpincType() == DdgrOpincType::DDGR_AUTOCACHE_REALDRAW); } bool RSSystemProperties::IsOpincRealDrawCacheEnable() @@ -708,11 +709,11 @@ bool RSSystemProperties::GetAutoCacheDebugEnabled() } #endif - #ifdef RS_ENABLE_STACK_CULLING -bool GetViewOcclusionCullingEnabled() +bool RSSystemProperties::GetViewOcclusionCullingEnabled() { - static bool stackViewCullingEnabled = system::GetBoolParameter("persist.sys.graphic.stack.culling.enabled", true); + static bool stackViewCullingEnabled = + system::GetBoolParameter("persist.sys.graphic.stack.culling.enabled", true); return stackViewCullingEnabled; } #endif diff --git a/rosen/modules/render_service_base/src/property/rs_properties.cpp b/rosen/modules/render_service_base/src/property/rs_properties.cpp index 16aa648926..250ea3fb4c 100644 --- a/rosen/modules/render_service_base/src/property/rs_properties.cpp +++ b/rosen/modules/render_service_base/src/property/rs_properties.cpp @@ -180,9 +180,6 @@ void RSProperties::SetBounds(Vector4f bounds) boundsGeo_->SetRect(bounds.x_, bounds.y_, bounds.z_, bounds.w_); hasBounds_ = true; geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -192,9 +189,6 @@ void RSProperties::SetBoundsSize(Vector2f size) hasBounds_ = true; geoDirty_ = true; contentDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -220,9 +214,6 @@ void RSProperties::SetBoundsPosition(Vector2f position) { boundsGeo_->SetPosition(position.x_, position.y_); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -230,9 +221,6 @@ void RSProperties::SetBoundsPositionX(float positionX) { boundsGeo_->SetX(positionX); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -240,9 +228,6 @@ void RSProperties::SetBoundsPositionY(float positionY) { boundsGeo_->SetY(positionY); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -288,9 +273,6 @@ void RSProperties::SetFrame(Vector4f frame) } frameGeo_->SetRect(frame.x_, frame.y_, frame.z_, frame.w_); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -299,9 +281,6 @@ void RSProperties::SetFrameSize(Vector2f size) frameGeo_->SetSize(size.x_, size.y_); geoDirty_ = true; contentDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -325,9 +304,6 @@ void RSProperties::SetFramePosition(Vector2f position) { frameGeo_->SetPosition(position.x_, position.y_); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -335,9 +311,6 @@ void RSProperties::SetFramePositionX(float positionX) { frameGeo_->SetX(positionX); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -345,9 +318,6 @@ void RSProperties::SetFramePositionY(float positionY) { frameGeo_->SetY(positionY); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -645,21 +615,11 @@ void RSProperties::SetSkewY(float skewY) SetDirty(); } -#ifdef DDGR_ENABLE_FEATURE_OPINC -bool RSProperties::GetOpincPropDirty() const -{ - return isOpincPropDirty_ && !alphaNeedApply_; -} -#endif - void RSProperties::SetTranslate(Vector2f translate) { boundsGeo_->SetTranslateX(translate[0]); boundsGeo_->SetTranslateY(translate[1]); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -667,9 +627,6 @@ void RSProperties::SetTranslateX(float translate) { boundsGeo_->SetTranslateX(translate); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -677,9 +634,6 @@ void RSProperties::SetTranslateY(float translate) { boundsGeo_->SetTranslateY(translate); geoDirty_ = true; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = true; -#endif SetDirty(); } @@ -1565,9 +1519,6 @@ void RSProperties::ResetDirty() isDirty_ = false; geoDirty_ = false; contentDirty_ = false; -#ifdef DDGR_ENABLE_FEATURE_OPINC - isOpincPropDirty_ = false; -#endif } bool RSProperties::IsDirty() const