!10138 修复拆流水显示效果问题

Merge pull request !10138 from ZhangPeng/PR-fix-pipeline-misc-display-issues
This commit is contained in:
openharmony_ci 2024-04-18 11:50:51 +00:00 committed by Gitee
commit 17fc224bc0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
19 changed files with 308 additions and 243 deletions

View File

@ -53,7 +53,7 @@ void RSRenderNodeShadowDrawable::Draw(Drawing::Canvas& canvas)
return;
}
SetSkipShadow(false);
SetSkip(SkipType::NONE);
DrawRangeImpl(canvas, rect, 0, shadowIndex + 1);
}

View File

@ -173,6 +173,7 @@ void RSSurfaceRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
bool isSelfDrawingSurface = surfaceParams->GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE;
if (isSelfDrawingSurface && !surfaceParams->IsSpherizeValid()) {
SetSkip(surfaceParams->GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
rscanvas->Save();
}
@ -299,6 +300,7 @@ void RSSurfaceRenderNodeDrawable::CaptureSingleSurfaceNode(RSSurfaceRenderNode&
auto nodeType = surfaceParams.GetSurfaceNodeType();
bool isSelfDrawingSurface = (nodeType == RSSurfaceNodeType::SELF_DRAWING_NODE);
if (isSelfDrawingSurface && !surfaceParams.IsSpherizeValid()) {
SetSkip(surfaceParams.GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
canvas.Save();
}
@ -389,6 +391,7 @@ void RSSurfaceRenderNodeDrawable::CaptureSurfaceInDisplay(RSSurfaceRenderNode& s
auto nodeType = surfaceParams.GetSurfaceNodeType();
bool isSelfDrawingSurface = (nodeType == RSSurfaceNodeType::SELF_DRAWING_NODE);
if (isSelfDrawingSurface) {
SetSkip(surfaceParams.GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
canvas.Save();
}

View File

@ -5228,10 +5228,10 @@ void RSUniRenderVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
bool backgroundTransparent = !node.GetAncoForceDoDirect() &&
(static_cast<uint8_t>(node.GetRenderProperties().GetBackgroundColor().GetAlpha()) < UINT8_MAX);
node.SetHardwareForcedDisabledState(
(node.IsHardwareForcedDisabledByFilter() || canvas_->GetAlpha() < 1.f ||
backgroundTransparent || IsRosenWebHardwareDisabled(node, rotation) ||
(node.IsHardwareForcedDisabledByFilter() || canvas_->GetAlpha() < 1.f || backgroundTransparent ||
IsRosenWebHardwareDisabled(node, rotation) ||
RSUniRenderUtil::GetRotationDegreeFromMatrix(node.GetTotalMatrix()) % ROTATION_90 != 0 ||
canvas_->GetBlendOffscreenLayerCnt() > 0) &&
canvas_->HasOffscreenLayer()) &&
(!node.IsHardwareEnabledTopSurface() || node.HasSubNodeShouldPaint()));
node.SetHardwareDisabledByCache(isUpdateCachedSurface_);
node.ResetHardwareForcedDisabledBySrcRect();

View File

@ -204,13 +204,18 @@ private:
class RSEndBlendModeDrawable : public RSDrawable {
public:
RSEndBlendModeDrawable() = default;
RSEndBlendModeDrawable(int blendApplyType) : blendApplyType_(blendApplyType) {}
~RSEndBlendModeDrawable() override = default;
static RSDrawable::Ptr OnGenerate(const RSRenderNode& node);
bool OnUpdate(const RSRenderNode& node) override;
void OnSync() override {};
void OnSync() override;
Drawing::RecordingCanvas::DrawFunc CreateDrawFunc() const override;
private:
bool needSync_ = false;
int blendApplyType_;
int stagingBlendApplyType_;
};
} // namespace DrawableV2
} // namespace OHOS::Rosen

View File

@ -56,7 +56,7 @@ public:
static void DrawUseEffect(RSPaintFilterCanvas* canvas);
static void BeginBlendMode(RSPaintFilterCanvas& canvas, int blendMode, int blendModeApplyType);
static void EndBlendMode(RSPaintFilterCanvas& canvas);
static void EndBlendMode(RSPaintFilterCanvas& canvas, int blendModeApplyType);
static Color CalculateInvertColor(const Color& backgroundColor);
static Color GetInvertBackgroundColor(RSPaintFilterCanvas& canvas, bool needClipToBounds,

View File

@ -33,6 +33,12 @@ class Canvas;
}
namespace DrawableV2 {
enum class SkipType : uint8_t {
NONE = 0,
SKIP_SHADOW = 1,
SKIP_BACKGROUND_COLOR = 2
};
class RSB_EXPORT RSRenderNodeDrawableAdapter {
public:
explicit RSRenderNodeDrawableAdapter(std::shared_ptr<const RSRenderNode>&& node);
@ -55,10 +61,7 @@ public:
static SharedPtr GetDrawableById(NodeId id);
static SharedPtr OnGenerateShadowDrawable(const std::shared_ptr<const RSRenderNode>& node);
void SetSkipShadow(bool skip)
{
skipShadow_ = skip;
}
void SetSkip(SkipType type);
protected:
// Util functions
@ -109,7 +112,7 @@ private:
static Generator shadowGenerator_;
static std::map<NodeId, WeakPtr> RenderNodeDrawableCache;
static inline std::mutex cacheMapMutex_;
bool skipShadow_ = false;
int8_t skipIndex_ = -1;
};
} // namespace DrawableV2

View File

@ -27,122 +27,122 @@ namespace Rosen {
// b. g_propertyToDrawableLut in rs_drawable_content.cpp
// 2. Property modifier(i.e. to be applied to RSProperties) MUST be added before CUSTOM enum, else wise it will not work
enum class RSModifierType : int16_t {
INVALID = 0, // 0
BOUNDS, // 1
FRAME, // 2
POSITION_Z, // 3
PIVOT, // 4
PIVOT_Z, // 5
QUATERNION, // 6
ROTATION, // 7
ROTATION_X, // 8
ROTATION_Y, // 9
CAMERA_DISTANCE, // 10
SCALE, // 11
SKEW, // 12
PERSP, // 13
TRANSLATE, // 14
TRANSLATE_Z, // 15
SUBLAYER_TRANSFORM, // 16
CORNER_RADIUS, // 17
ALPHA, // 18
ALPHA_OFFSCREEN, // 19
FOREGROUND_COLOR, // 20
BACKGROUND_COLOR, // 21
BACKGROUND_SHADER, // 22
BG_IMAGE, // 23
BG_IMAGE_INNER_RECT, // 24
BG_IMAGE_WIDTH, // 25
BG_IMAGE_HEIGHT, // 26
BG_IMAGE_POSITION_X, // 27
BG_IMAGE_POSITION_Y, // 28
SURFACE_BG_COLOR, // 29
BORDER_COLOR, // 30
BORDER_WIDTH, // 31
BORDER_STYLE, // 32
FILTER, // 33
BACKGROUND_FILTER, // 34
LINEAR_GRADIENT_BLUR_PARA, // 35
DYNAMIC_LIGHT_UP_RATE, // 36
DYNAMIC_LIGHT_UP_DEGREE, // 37
FRAME_GRAVITY, // 38
CLIP_RRECT, // 39
CLIP_BOUNDS, // 40
CLIP_TO_BOUNDS, // 41
CLIP_TO_FRAME, // 42
VISIBLE, // 43
SHADOW_COLOR, // 44
SHADOW_OFFSET_X, // 45
SHADOW_OFFSET_Y, // 46
SHADOW_ALPHA, // 47
SHADOW_ELEVATION, // 48
SHADOW_RADIUS, // 49
SHADOW_PATH, // 50
SHADOW_MASK, // 51
SHADOW_COLOR_STRATEGY, // 52
MASK, // 53
SPHERIZE, // 54
LIGHT_UP_EFFECT, // 55
PIXEL_STRETCH, // 56
PIXEL_STRETCH_PERCENT, // 57
USE_EFFECT, // 58
COLOR_BLEND_MODE, // 59
COLOR_BLEND_APPLY_TYPE, // 60
SANDBOX, // 61
GRAY_SCALE, // 62
BRIGHTNESS, // 63
CONTRAST, // 64
SATURATE, // 65
SEPIA, // 66
INVERT, // 67
AIINVERT, // 68
SYSTEMBAREFFECT, // 69
HUE_ROTATE, // 70
COLOR_BLEND, // 71
PARTICLE, // 72
SHADOW_IS_FILLED, // 73
OUTLINE_COLOR, // 74
OUTLINE_WIDTH, // 75
OUTLINE_STYLE, // 76
OUTLINE_RADIUS, // 77
USE_SHADOW_BATCHING, // 78
GREY_COEF, // 79
LIGHT_INTENSITY, // 80
LIGHT_COLOR, // 81
LIGHT_POSITION, // 82
ILLUMINATED_BORDER_WIDTH, // 83
ILLUMINATED_TYPE, // 84
BLOOM, // 85
PARTICLE_EMITTER_UPDATER, // 86
FOREGROUND_EFFECT_RADIUS, // 87
MOTION_BLUR_PARA, // 88
DYNAMIC_DIM_DEGREE, // 89
BACKGROUND_BLUR_RADIUS, // 90
BACKGROUND_BLUR_SATURATION, // 91
BACKGROUND_BLUR_BRIGHTNESS, // 92
BACKGROUND_BLUR_MASK_COLOR, // 93
BACKGROUND_BLUR_COLOR_MODE, // 94
BACKGROUND_BLUR_RADIUS_X, // 95
BACKGROUND_BLUR_RADIUS_Y, // 96
FOREGROUND_BLUR_RADIUS, // 97
FOREGROUND_BLUR_SATURATION, // 98
FOREGROUND_BLUR_BRIGHTNESS, // 99
FOREGROUND_BLUR_MASK_COLOR, // 100
FOREGROUND_BLUR_COLOR_MODE, // 101
FOREGROUND_BLUR_RADIUS_X, // 102
FOREGROUND_BLUR_RADIUS_Y, // 103
CUSTOM, // 104
EXTENDED, // 105
TRANSITION, // 106
BACKGROUND_STYLE, // 107
CONTENT_STYLE, // 108
FOREGROUND_STYLE, // 109
OVERLAY_STYLE, // 110
NODE_MODIFIER, // 111
ENV_FOREGROUND_COLOR, // 112
ENV_FOREGROUND_COLOR_STRATEGY, // 113
GEOMETRYTRANS, // 114
CHILDREN, // 115, PLACEHOLDER, no such modifier, but we need a dirty flag
INVALID = 0,
BOUNDS,
FRAME,
POSITION_Z,
PIVOT,
PIVOT_Z,
QUATERNION,
ROTATION,
ROTATION_X,
ROTATION_Y,
CAMERA_DISTANCE,
SCALE,
SKEW,
PERSP,
TRANSLATE,
TRANSLATE_Z,
SUBLAYER_TRANSFORM,
CORNER_RADIUS,
ALPHA,
ALPHA_OFFSCREEN,
FOREGROUND_COLOR,
BACKGROUND_COLOR,
BACKGROUND_SHADER,
BG_IMAGE,
BG_IMAGE_INNER_RECT,
BG_IMAGE_WIDTH,
BG_IMAGE_HEIGHT,
BG_IMAGE_POSITION_X,
BG_IMAGE_POSITION_Y,
SURFACE_BG_COLOR,
BORDER_COLOR,
BORDER_WIDTH,
BORDER_STYLE,
FILTER,
BACKGROUND_FILTER,
LINEAR_GRADIENT_BLUR_PARA,
DYNAMIC_LIGHT_UP_RATE,
DYNAMIC_LIGHT_UP_DEGREE,
FRAME_GRAVITY,
CLIP_RRECT,
CLIP_BOUNDS,
CLIP_TO_BOUNDS,
CLIP_TO_FRAME,
VISIBLE,
SHADOW_COLOR,
SHADOW_OFFSET_X,
SHADOW_OFFSET_Y,
SHADOW_ALPHA,
SHADOW_ELEVATION,
SHADOW_RADIUS,
SHADOW_PATH,
SHADOW_MASK,
SHADOW_COLOR_STRATEGY,
MASK,
SPHERIZE,
LIGHT_UP_EFFECT,
PIXEL_STRETCH,
PIXEL_STRETCH_PERCENT,
USE_EFFECT,
COLOR_BLEND_MODE,
COLOR_BLEND_APPLY_TYPE,
SANDBOX,
GRAY_SCALE,
BRIGHTNESS,
CONTRAST,
SATURATE,
SEPIA,
INVERT,
AIINVERT,
SYSTEMBAREFFECT,
HUE_ROTATE,
COLOR_BLEND,
PARTICLE,
SHADOW_IS_FILLED,
OUTLINE_COLOR,
OUTLINE_WIDTH,
OUTLINE_STYLE,
OUTLINE_RADIUS,
USE_SHADOW_BATCHING,
GREY_COEF,
LIGHT_INTENSITY,
LIGHT_COLOR,
LIGHT_POSITION,
ILLUMINATED_BORDER_WIDTH,
ILLUMINATED_TYPE,
BLOOM,
PARTICLE_EMITTER_UPDATER,
FOREGROUND_EFFECT_RADIUS,
MOTION_BLUR_PARA,
DYNAMIC_DIM_DEGREE,
BACKGROUND_BLUR_RADIUS,
BACKGROUND_BLUR_SATURATION,
BACKGROUND_BLUR_BRIGHTNESS,
BACKGROUND_BLUR_MASK_COLOR,
BACKGROUND_BLUR_COLOR_MODE,
BACKGROUND_BLUR_RADIUS_X,
BACKGROUND_BLUR_RADIUS_Y,
FOREGROUND_BLUR_RADIUS,
FOREGROUND_BLUR_SATURATION,
FOREGROUND_BLUR_BRIGHTNESS,
FOREGROUND_BLUR_MASK_COLOR,
FOREGROUND_BLUR_COLOR_MODE,
FOREGROUND_BLUR_RADIUS_X,
FOREGROUND_BLUR_RADIUS_Y,
CUSTOM,
EXTENDED,
TRANSITION,
BACKGROUND_STYLE,
CONTENT_STYLE,
FOREGROUND_STYLE,
OVERLAY_STYLE,
NODE_MODIFIER,
ENV_FOREGROUND_COLOR,
ENV_FOREGROUND_COLOR_STRATEGY,
GEOMETRYTRANS,
CHILDREN, // PLACEHOLDER, no such modifier, but we need a dirty flag
MAX_RS_MODIFIER_TYPE,
};
using ModifierDirtyTypes = std::bitset<static_cast<int>(RSModifierType::MAX_RS_MODIFIER_TYPE)>;

View File

@ -137,7 +137,7 @@ class RSB_EXPORT RSPaintFilterCanvas : public RSPaintFilterCanvasBase {
public:
RSPaintFilterCanvas(Drawing::Canvas* canvas, float alpha = 1.0f);
RSPaintFilterCanvas(Drawing::Surface* surface, float alpha = 1.0f);
~RSPaintFilterCanvas() override {};
~RSPaintFilterCanvas() override = default;;
void CopyConfiguration(const RSPaintFilterCanvas& other);
void PushDirtyRegion(Drawing::Region& resultRegion);
@ -162,11 +162,10 @@ public:
int GetEnvSaveCount() const;
void RestoreEnvToCount(int count);
// blendmode related
void SaveLayer(const Drawing::SaveLayerOps& saveLayerOps) override;
void SetBlendMode(std::optional<int> blendMode);
int GetBlendOffscreenLayerCnt() const
{
return 0;
};
bool HasOffscreenLayer() const;
// save/restore utils
struct SaveStatus {
@ -271,9 +270,8 @@ protected:
Color envForegroundColor_;
std::shared_ptr<CachedEffectData> effectData_;
std::optional<int> blendMode_;
bool hasOffscreenLayer_;
};
const std::stack<float>& GetAlphaStack();
const std::stack<Env>& GetEnvStack();
bool OnFilter() const override;
inline bool OnFilterWithBrush(Drawing::Brush& brush) const override

View File

@ -24,8 +24,8 @@ class RSCanvasListener;
class RSB_EXPORT RSListenedCanvas : public RSPaintFilterCanvas {
public:
RSListenedCanvas(Drawing::Canvas& canvas, float alpha = 1.0f);
RSListenedCanvas(Drawing::Surface& surface, float alpha = 1.0f);
RSListenedCanvas(Drawing::Canvas& canvas);
RSListenedCanvas(Drawing::Surface& surface);
void SetListener(const std::shared_ptr<RSCanvasListener>& listener);
// shapes

View File

@ -16,11 +16,13 @@
#include "drawable/rs_drawable.h"
#include <limits>
#include "drawable/rs_misc_drawable.h"
#include "drawable/rs_property_drawable.h"
#include "drawable/rs_property_drawable_background.h"
#include "drawable/rs_property_drawable_foreground.h"
#include "pipeline/rs_render_node.h"
#include "pipeline/rs_surface_render_node.h"
namespace OHOS::Rosen {
namespace {
@ -29,7 +31,7 @@ using namespace DrawableV2;
// NOTE: This LUT should always the same size and order as RSModifierType
// key = RSModifierType, value = RSDrawableSlot
constexpr int DIRTY_LUT_SIZE = static_cast<int>(RSModifierType::MAX_RS_MODIFIER_TYPE);
static const std::array<RSDrawableSlot, DIRTY_LUT_SIZE> g_propertyToDrawableLut = {
static constexpr std::array<RSDrawableSlot, DIRTY_LUT_SIZE> g_propertyToDrawableLut = {
RSDrawableSlot::INVALID, // INVALID
RSDrawableSlot::CLIP_TO_BOUNDS, // BOUNDS
RSDrawableSlot::FRAME_OFFSET, // FRAME
@ -118,6 +120,7 @@ static const std::array<RSDrawableSlot, DIRTY_LUT_SIZE> g_propertyToDrawableLut
RSDrawableSlot::POINT_LIGHT, // BLOOM
RSDrawableSlot::PARTICLE_EFFECT, // PARTICLE_EMITTER_UPDATER
RSDrawableSlot::FOREGROUND_FILTER, // FOREGROUND_EFFECT_RADIUS
RSDrawableSlot::INVALID, // MOTION_BLUR_PARA
RSDrawableSlot::DYNAMIC_DIM, // DYNAMIC_DIM
RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_RADIUS
RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_SATURATION
@ -126,13 +129,13 @@ static const std::array<RSDrawableSlot, DIRTY_LUT_SIZE> g_propertyToDrawableLut
RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_COLOR_MODE
RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_RADIUS_X
RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_RADIUS_Y
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_SATURATION
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_BRIGHTNESS
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_MASK_COLOR
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_COLOR_MODE
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS_X
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS_Y
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_SATURATION
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_BRIGHTNESS
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_MASK_COLOR
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_COLOR_MODE
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS_X
RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS_Y
RSDrawableSlot::INVALID, // CUSTOM
RSDrawableSlot::INVALID, // EXTENDED
RSDrawableSlot::TRANSITION, // TRANSITION
@ -147,6 +150,21 @@ static const std::array<RSDrawableSlot, DIRTY_LUT_SIZE> g_propertyToDrawableLut
RSDrawableSlot::CHILDREN, // CHILDREN
};
// Check if g_propertyToDrawableLut size match and is fully initialized (the last element should not be default value)
static_assert(g_propertyToDrawableLut.size() == static_cast<size_t>(RSModifierType::MAX_RS_MODIFIER_TYPE));
static_assert(g_propertyToDrawableLut.back() != RSDrawableSlot {});
// Randomly check some LUT index and value
static_assert(g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::USE_EFFECT)] == RSDrawableSlot::USE_EFFECT);
static_assert(
g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::FOREGROUND_COLOR)] == RSDrawableSlot::FOREGROUND_COLOR);
static_assert(
g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::CLIP_TO_FRAME)] == RSDrawableSlot::CLIP_TO_FRAME);
static_assert(
g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::USE_SHADOW_BATCHING)] == RSDrawableSlot::CHILDREN);
static_assert(g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::TRANSITION)] == RSDrawableSlot::TRANSITION);
static_assert(g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::CHILDREN)] == RSDrawableSlot::CHILDREN);
template<RSModifierType type>
static inline RSDrawable::Ptr ModifierGenerator(const RSRenderNode& node)
{
@ -243,9 +261,11 @@ static uint8_t CalculateDrawableVecStatus(RSRenderNode& node, const RSDrawable::
uint8_t result = 0;
auto& properties = node.GetRenderProperties();
// color blend mode has implicit dependency on clipToBounds
if (properties.GetClipToBounds() || properties.GetClipToRRect() || properties.GetClipBounds() != nullptr ||
properties.GetColorBlendMode() != static_cast<int>(RSColorBlendMode::NONE)) {
// ClipToBounds if either 1. is surface node, 2. has explicit clip properties, 3. has blend mode
bool shouldClipToBounds = node.IsInstanceOf<RSSurfaceRenderNode>() || properties.GetClipToBounds() ||
properties.GetClipToRRect() || properties.GetClipBounds() != nullptr ||
properties.GetColorBlendMode() != static_cast<int>(RSColorBlendMode::NONE);
if (shouldClipToBounds) {
result |= DrawableVecStatus::CLIP_TO_BOUNDS;
}
@ -303,6 +323,7 @@ inline static void SaveRestoreHelper(RSDrawable::Vec& drawableVec, RSDrawableSlo
static void OptimizeBoundsSaveRestore(RSRenderNode& node, RSDrawable::Vec& drawableVec, uint8_t flags)
{
// Erase existing save/clip/restore before re-generating
constexpr static std::array boundsSlotsToErase = {
RSDrawableSlot::BG_SAVE_BOUNDS,
RSDrawableSlot::CLIP_TO_BOUNDS,
@ -311,8 +332,6 @@ static void OptimizeBoundsSaveRestore(RSRenderNode& node, RSDrawable::Vec& drawa
RSDrawableSlot::FG_CLIP_TO_BOUNDS,
RSDrawableSlot::FG_RESTORE_BOUNDS,
};
// Erase existing save/clip/restore before re-generating
for (auto& slot : boundsSlotsToErase) {
drawableVec[static_cast<size_t>(slot)] = nullptr;
}
@ -424,31 +443,38 @@ std::unordered_set<RSDrawableSlot> RSDrawable::CalculateDirtySlots(
}
// Step 1.2: expand dirty slots by rules
// planning: border etc. should be updated when border radius changed
if (dirtySlots.count(RSDrawableSlot::FRAME_OFFSET)) {
if (drawableVec[static_cast<size_t>(RSDrawableSlot::CLIP_TO_FRAME)]) {
dirtySlots.emplace(RSDrawableSlot::CLIP_TO_FRAME);
}
}
// Step 1.3: if bounds changed, every existing drawable needs to be updated
if (dirtyTypes.test(static_cast<size_t>(RSModifierType::BOUNDS))) {
for (size_t i = 0; i < drawableVec.size(); i++) {
if (drawableVec[i]) {
dirtySlots.emplace(static_cast<RSDrawableSlot>(i));
// if bounds or cornerRadius changed, mark affected drawables as dirty
static constexpr std::array boundsDirtyTypes = {
RSDrawableSlot::MASK,
RSDrawableSlot::SHADOW,
RSDrawableSlot::OUTLINE,
RSDrawableSlot::CLIP_TO_BOUNDS,
RSDrawableSlot::BACKGROUND_COLOR,
RSDrawableSlot::BACKGROUND_SHADER,
RSDrawableSlot::BACKGROUND_IMAGE,
RSDrawableSlot::ENV_FOREGROUND_COLOR_STRATEGY,
RSDrawableSlot::FG_CLIP_TO_BOUNDS,
RSDrawableSlot::FOREGROUND_COLOR,
RSDrawableSlot::POINT_LIGHT,
RSDrawableSlot::BORDER,
RSDrawableSlot::PIXEL_STRETCH,
};
if (dirtyTypes.test(static_cast<size_t>(RSModifierType::BOUNDS)) ||
dirtyTypes.test(static_cast<size_t>(RSModifierType::CORNER_RADIUS))) {
for (auto slot : boundsDirtyTypes) {
if (drawableVec[static_cast<size_t>(slot)]) {
dirtySlots.emplace(slot);
}
}
}
// Step 1.4: if corner radius changed, update border and outline
if (dirtyTypes.test(static_cast<size_t>(RSModifierType::CORNER_RADIUS))) {
// border may should be updated with corner radius
if (drawableVec[static_cast<size_t>(RSDrawableSlot::BORDER)]) {
dirtySlots.emplace(RSDrawableSlot::BORDER);
// if frame changed, mark affected drawables as dirty
if (dirtySlots.count(RSDrawableSlot::FRAME_OFFSET)) {
if (drawableVec[static_cast<size_t>(RSDrawableSlot::CLIP_TO_FRAME)]) {
dirtySlots.emplace(RSDrawableSlot::CLIP_TO_FRAME);
}
if (drawableVec[static_cast<size_t>(RSDrawableSlot::OUTLINE)]) {
dirtySlots.emplace(RSDrawableSlot::OUTLINE);
if (drawableVec[static_cast<size_t>(RSDrawableSlot::FOREGROUND_FILTER)]) {
dirtySlots.emplace(RSDrawableSlot::FOREGROUND_FILTER);
}
}

View File

@ -45,7 +45,7 @@ bool RSChildrenDrawable::OnUpdate(const RSRenderNode& node)
continue;
}
if (auto childDrawable = RSRenderNodeDrawableAdapter::OnGenerate(child)) {
childDrawable->SetSkipShadow(false);
childDrawable->SetSkip(SkipType::NONE);
stagingChildrenDrawableVec_.push_back(std::move(childDrawable));
}
}
@ -63,7 +63,7 @@ bool RSChildrenDrawable::OnUpdate(const RSRenderNode& node)
stagingChildrenDrawableVec_.push_back(std::move(shadowDrawable));
}
if (auto childDrawable = RSRenderNodeDrawableAdapter::OnGenerate(child)) {
childDrawable->SetSkipShadow(true);
childDrawable->SetSkip(SkipType::SKIP_SHADOW);
pendingChildren.push_back(std::move(childDrawable));
}
}
@ -107,7 +107,7 @@ bool RSChildrenDrawable::OnSharedTransition(const RSRenderNode::SharedPtr& node)
// for higher hierarchy node, we add paired node (lower in hierarchy) first, then add it
if (auto childDrawable = RSRenderNodeDrawableAdapter::OnGenerate(pairedNode)) {
// NOTE: skip shared-transition shadow for now
childDrawable->SetSkipShadow(true);
childDrawable->SetSkip(SkipType::SKIP_SHADOW);
stagingChildrenDrawableVec_.push_back(std::move(childDrawable));
}
}
@ -306,7 +306,7 @@ RSDrawable::Ptr RSEndBlendModeDrawable::OnGenerate(const RSRenderNode& node)
return nullptr;
}
return std::make_shared<RSEndBlendModeDrawable>();
return std::make_shared<RSEndBlendModeDrawable>(properties.GetColorBlendApplyType());
};
bool RSEndBlendModeDrawable::OnUpdate(const RSRenderNode& node)
@ -318,14 +318,27 @@ bool RSEndBlendModeDrawable::OnUpdate(const RSRenderNode& node)
return false;
}
stagingBlendApplyType_ = properties.GetColorBlendApplyType();
needSync_ = true;
return true;
}
void RSEndBlendModeDrawable::OnSync()
{
if (needSync_ == false) {
return;
}
blendApplyType_ = stagingBlendApplyType_;
needSync_ = false;
}
Drawing::RecordingCanvas::DrawFunc RSEndBlendModeDrawable::CreateDrawFunc() const
{
return [](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
auto ptr = std::static_pointer_cast<const RSEndBlendModeDrawable>(shared_from_this());
return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
RSPropertyDrawableUtils::EndBlendMode(*paintFilterCanvas);
RSPropertyDrawableUtils::EndBlendMode(*paintFilterCanvas, ptr->blendApplyType_);
};
}

View File

@ -153,6 +153,7 @@ Drawing::RecordingCanvas::DrawFunc RSMaskShadowDrawable::CreateDrawFunc() const
{
auto ptr = std::static_pointer_cast<const RSMaskShadowDrawable>(shared_from_this());
return [ptr](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
Drawing::AutoCanvasRestore rst(*canvas, true);
RSPropertyDrawableUtils::CeilMatrixTrans(canvas);
ptr->drawCmdList_->Playback(*canvas);
};

View File

@ -17,8 +17,8 @@
#include "common/rs_optional_trace.h"
#include "platform/common/rs_log.h"
#include "render/rs_material_filter.h"
#include "property/rs_properties_painter.h"
#include "render/rs_material_filter.h"
namespace OHOS {
namespace Rosen {
@ -182,7 +182,6 @@ void RSPropertyDrawableUtils::CeilMatrixTrans(Drawing::Canvas* canvas)
{
// The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
// the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
Drawing::AutoCanvasRestore rst(*canvas, true);
auto matrix = canvas->GetTotalMatrix();
matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
@ -703,8 +702,8 @@ Drawing::Path RSPropertyDrawableUtils::CreateShadowPath(const std::shared_ptr<RS
void RSPropertyDrawableUtils::DrawShadow(Drawing::Canvas* canvas, Drawing::Path& path, const float& offsetX,
const float& offsetY, const float& elevation, const bool& isFilled, Color spotColor)
{
CeilMatrixTrans(canvas);
Drawing::AutoCanvasRestore acr(*canvas, true);
CeilMatrixTrans(canvas);
if (!isFilled) {
canvas->ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
}
@ -754,6 +753,12 @@ void RSPropertyDrawableUtils::DrawUseEffect(RSPaintFilterCanvas* canvas)
void RSPropertyDrawableUtils::BeginBlendMode(RSPaintFilterCanvas& canvas, int blendMode, int blendModeApplyType)
{
if (!canvas.HasOffscreenLayer() && RSPropertiesPainter::IsDangerousBlendMode(blendMode - 1, blendModeApplyType)) {
Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
canvas.SaveLayer(maskLayerRec);
ROSEN_LOGD("Dangerous offscreen blendmode may produce transparent pixels, add extra offscreen here.");
}
// fast blend mode
if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
canvas.SetBlendMode({ blendMode - 1 }); // map blendMode to SkBlendMode
@ -761,10 +766,8 @@ void RSPropertyDrawableUtils::BeginBlendMode(RSPaintFilterCanvas& canvas, int bl
}
// save layer mode
auto matrix = canvas.GetTotalMatrix();
matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
canvas.SetMatrix(matrix);
CeilMatrixTrans(&canvas);
Drawing::Brush blendBrush_;
blendBrush_.SetAlphaF(canvas.GetAlpha());
blendBrush_.SetBlendMode(static_cast<Drawing::BlendMode>(blendMode - 1)); // map blendMode to Drawing::BlendMode
@ -775,11 +778,12 @@ void RSPropertyDrawableUtils::BeginBlendMode(RSPaintFilterCanvas& canvas, int bl
canvas.SetAlpha(1.0f);
}
void RSPropertyDrawableUtils::EndBlendMode(RSPaintFilterCanvas& canvas)
void RSPropertyDrawableUtils::EndBlendMode(RSPaintFilterCanvas& canvas, int blendModeApplyType)
{
canvas.RestoreEnv();
canvas.RestoreAlpha();
canvas.Restore();
// RSRenderNodeDrawable will do other necessary work (restore canvas & env), we only need to restore alpha
if (blendModeApplyType != static_cast<int>(RSColorBlendApplyType::FAST)) {
canvas.RestoreAlpha();
}
}
Color RSPropertyDrawableUtils::CalculateInvertColor(const Color& backgroundColor)

View File

@ -129,13 +129,12 @@ void RSRenderNodeDrawableAdapter::DrawRangeImpl(
const auto& drawCmdList_ = renderNode_->drawCmdList_;
if (UNLIKELY(skipShadow_)) {
auto shadowIndex = renderNode_->drawCmdIndex_.shadowIndex_;
if (shadowIndex != -1 || start <= shadowIndex || end > shadowIndex) {
for (auto i = start; i < shadowIndex; i++) {
if (UNLIKELY(skipIndex_ != -1)) {
if (start <= skipIndex_ || end > skipIndex_) {
for (auto i = start; i < skipIndex_; i++) {
drawCmdList_[i](&canvas, &rect);
}
for (auto i = shadowIndex + 1; i < end; i++) {
for (auto i = skipIndex_ + 1; i < end; i++) {
drawCmdList_[i](&canvas, &rect);
}
}
@ -326,4 +325,19 @@ bool RSRenderNodeDrawableAdapter::HasFilterOrEffect() const
return renderNode_->drawCmdIndex_.shadowIndex_ != -1 || renderNode_->drawCmdIndex_.backgroundFilterIndex_ != -1 ||
renderNode_->drawCmdIndex_.useEffectIndex_ != -1;
}
void RSRenderNodeDrawableAdapter::SetSkip(SkipType type)
{
switch (type) {
case SkipType::SKIP_BACKGROUND_COLOR:
skipIndex_ = renderNode_->drawCmdIndex_.backgroundColorIndex_;
break;
case SkipType::SKIP_SHADOW:
skipIndex_ = renderNode_->drawCmdIndex_.shadowIndex_;
break;
case SkipType::NONE:
default:
skipIndex_ = -1;
break;
}
}
} // namespace OHOS::Rosen::DrawableV2

View File

@ -902,17 +902,18 @@ CoreCanvas& RSPaintFilterCanvasBase::DetachPaint()
}
RSPaintFilterCanvas::RSPaintFilterCanvas(Drawing::Canvas* canvas, float alpha)
: RSPaintFilterCanvasBase(canvas), alphaStack_({ std::clamp(alpha, 0.f, 1.f) }), // construct stack with given alpha
// Temporary fix, this default color should be 0x000000FF, fix this after foreground color refactor
envStack_({ Env({ RSColor(0xFF000000) }) }) // construct stack with default foreground color
{}
: RSPaintFilterCanvasBase(canvas), alphaStack_({ 1.0f }),
envStack_({ Env { .envForegroundColor_ = RSColor(0xFF000000), .hasOffscreenLayer_ = false } })
{
(void)alpha; // alpha is no longer used, but we keep it for backward compatibility
}
RSPaintFilterCanvas::RSPaintFilterCanvas(Drawing::Surface* surface, float alpha)
: RSPaintFilterCanvasBase(surface ? surface->GetCanvas().get() : nullptr), surface_(surface),
alphaStack_({ std::clamp(alpha, 0.f, 1.f) }), // construct stack with given alpha
// Temporary fix, this default color should be 0x000000FF, fix this after foreground color refactor
envStack_({ Env({ RSColor(0xFF000000) }) }) // construct stack with default foreground color
{}
: RSPaintFilterCanvasBase(surface ? surface->GetCanvas().get() : nullptr), surface_(surface), alphaStack_({ 1.0f }),
envStack_({ Env { .envForegroundColor_ = RSColor(0xFF000000), .hasOffscreenLayer_ = false } })
{
(void)alpha; // alpha is no longer used, but we keep it for backward compatibility
}
Drawing::Surface* RSPaintFilterCanvas::GetSurface() const
{
@ -1365,5 +1366,14 @@ bool RSPaintFilterCanvas::GetRecordDrawable() const
{
return recordDrawable_;
}
bool RSPaintFilterCanvas::HasOffscreenLayer() const
{
return envStack_.top().hasOffscreenLayer_;
}
void RSPaintFilterCanvas::SaveLayer(const Drawing::SaveLayerOps& saveLayerOps)
{
envStack_.top().hasOffscreenLayer_ = true;
RSPaintFilterCanvasBase::SaveLayer(saveLayerOps);
}
} // namespace Rosen
} // namespace OHOS

View File

@ -2107,61 +2107,62 @@ void RSRenderNode::UpdateDisplayList()
return;
}
int8_t index = 0;
// Note: the loop range is [begin, end], both end is included.
auto AppendDrawFunc = [&](RSDrawableSlot begin, RSDrawableSlot end) -> int8_t {
auto beginIndex = static_cast<int8_t>(begin);
auto AppendDrawFunc = [&](RSDrawableSlot end) -> int8_t {
auto endIndex = static_cast<int8_t>(end);
for (int8_t i = beginIndex; i <= endIndex; ++i) {
if (const auto& drawable = drawableVec_[i]) {
for (; index <= endIndex; ++index) {
if (const auto& drawable = drawableVec_[index]) {
stagingDrawCmdList_.emplace_back(drawable->CreateDrawFunc());
}
}
// If the last drawable exist, return its index, otherwise return -1
// If the end drawable exist, return its index, otherwise return -1
return drawableVec_[endIndex] != nullptr ? stagingDrawCmdList_.size() - 1 : -1;
};
// Update index of SHADOW
stagingDrawCmdIndex_.shadowIndex_ = AppendDrawFunc(RSDrawableSlot::SAVE_ALL, RSDrawableSlot::SHADOW);
stagingDrawCmdIndex_.shadowIndex_ = AppendDrawFunc(RSDrawableSlot::SHADOW);
AppendDrawFunc(RSDrawableSlot::FOREGROUND_FILTER, RSDrawableSlot::OUTLINE);
AppendDrawFunc(RSDrawableSlot::OUTLINE);
stagingDrawCmdIndex_.renderGroupBeginIndex_ = stagingDrawCmdList_.size();
// Update index of BACKGROUND_COLOR
stagingDrawCmdIndex_.backgroundColorIndex_ =
AppendDrawFunc(RSDrawableSlot::BG_SAVE_BOUNDS, RSDrawableSlot::BACKGROUND_COLOR);
AppendDrawFunc(RSDrawableSlot::BACKGROUND_COLOR);
// Update index of BACKGROUND_FILTER
stagingDrawCmdIndex_.backgroundFilterIndex_ =
AppendDrawFunc(RSDrawableSlot::BACKGROUND_SHADER, RSDrawableSlot::BACKGROUND_FILTER);
AppendDrawFunc(RSDrawableSlot::BACKGROUND_FILTER);
// Update index of USE_EFFECT
stagingDrawCmdIndex_.useEffectIndex_ = AppendDrawFunc(RSDrawableSlot::USE_EFFECT, RSDrawableSlot::USE_EFFECT);
stagingDrawCmdIndex_.useEffectIndex_ = AppendDrawFunc(RSDrawableSlot::USE_EFFECT);
AppendDrawFunc(RSDrawableSlot::BACKGROUND_STYLE, RSDrawableSlot::BG_RESTORE_BOUNDS);
AppendDrawFunc(RSDrawableSlot::BG_RESTORE_BOUNDS);
if (drawableVecStatus_ & FRAME_PROPERTY) {
// Update index of CONTENT_STYLE
stagingDrawCmdIndex_.contentIndex_ = AppendDrawFunc(RSDrawableSlot::SAVE_FRAME, RSDrawableSlot::CONTENT_STYLE);
stagingDrawCmdIndex_.contentIndex_ = AppendDrawFunc(RSDrawableSlot::CONTENT_STYLE);
// Update index of BACKGROUND_END
stagingDrawCmdIndex_.backgroundEndIndex_ = stagingDrawCmdIndex_.contentIndex_ == -1 ?
stagingDrawCmdList_.size() : stagingDrawCmdIndex_.contentIndex_;
// Update index of CHILDREN
stagingDrawCmdIndex_.childrenIndex_ = AppendDrawFunc(RSDrawableSlot::CHILDREN, RSDrawableSlot::CHILDREN);
stagingDrawCmdIndex_.childrenIndex_ = AppendDrawFunc(RSDrawableSlot::CHILDREN);
stagingDrawCmdIndex_.foregroundBeginIndex_ = stagingDrawCmdList_.size();
AppendDrawFunc(RSDrawableSlot::FOREGROUND_STYLE, RSDrawableSlot::RESTORE_FRAME);
AppendDrawFunc(RSDrawableSlot::RESTORE_FRAME);
} else {
// Nothing inside frame, skip useless slots and update indexes
stagingDrawCmdIndex_.contentIndex_ = -1;
stagingDrawCmdIndex_.childrenIndex_ = -1;
stagingDrawCmdIndex_.backgroundEndIndex_ = stagingDrawCmdList_.size();
stagingDrawCmdIndex_.foregroundBeginIndex_ = stagingDrawCmdList_.size();
index = static_cast<int8_t>(RSDrawableSlot::FG_SAVE_BOUNDS);
}
stagingDrawCmdIndex_.renderGroupEndIndex_ = stagingDrawCmdList_.size();
AppendDrawFunc(RSDrawableSlot::FG_SAVE_BOUNDS, RSDrawableSlot::RESTORE_ALL);
AppendDrawFunc(RSDrawableSlot::RESTORE_ALL);
stagingDrawCmdIndex_.endIndex_ = stagingDrawCmdList_.size();
stagingRenderParams_->SetContentEmpty(false);
#endif

View File

@ -20,15 +20,9 @@
namespace OHOS {
namespace Rosen {
RSListenedCanvas::RSListenedCanvas(Drawing::Canvas& canvas, float alpha)
: RSPaintFilterCanvas(&canvas, alpha)
{
}
RSListenedCanvas::RSListenedCanvas(Drawing::Canvas& canvas) : RSPaintFilterCanvas(&canvas) {}
RSListenedCanvas::RSListenedCanvas(Drawing::Surface& surface, float alpha)
: RSPaintFilterCanvas(&surface, alpha)
{
}
RSListenedCanvas::RSListenedCanvas(Drawing::Surface& surface) : RSPaintFilterCanvas(&surface) {}
void RSListenedCanvas::SetListener(const std::shared_ptr<RSCanvasListener> &listener)
{

View File

@ -53,7 +53,7 @@ constexpr uint8_t BORDER_TYPE_NONE = (uint32_t)BorderStyle::NONE;
using ResetPropertyFunc = void (*)(RSProperties* prop);
// Every modifier before RSModifierType::CUSTOM is property modifier, and it should have a ResetPropertyFunc
// NOTE: alway add new resetter when adding new property modifier
const std::array<ResetPropertyFunc, static_cast<int>(RSModifierType::CUSTOM)> g_propertyResetterLUT = {
constexpr static std::array<ResetPropertyFunc, static_cast<int>(RSModifierType::CUSTOM)> g_propertyResetterLUT = {
nullptr, // INVALID
nullptr, // BOUNDS
nullptr, // FRAME
@ -159,6 +159,10 @@ const std::array<ResetPropertyFunc, static_cast<int>(RSModifierType::CUSTOM)> g_
[](RSProperties* prop) { prop->SetForegroundBlurRadiusX(0.f); }, // FOREGROUND_BLUR_RADIUS_X
[](RSProperties* prop) { prop->SetForegroundBlurRadiusY(0.f); }, // FOREGROUND_BLUR_RADIUS_Y
};
// Check if g_propertyResetterLUT size match and is fully initialized (the last element should never be nullptr)
static_assert(g_propertyResetterLUT.size() == static_cast<size_t>(RSModifierType::CUSTOM));
static_assert(g_propertyResetterLUT.back() != nullptr);
} // namespace
// Only enable filter cache when uni-render is enabled and filter cache is enabled

View File

@ -17,25 +17,16 @@
#include <utility>
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint3.h"
#include "include/effects/SkImageFilters.h"
#include "include/effects/SkLumaColorFilter.h"
#include "include/utils/SkShadowUtils.h"
#include "src/image/SkImage_Base.h"
#include "common/rs_obj_abs_geometry.h"
#include "common/rs_optional_trace.h"
#include "pipeline/rs_canvas_render_node.h"
#include "pipeline/rs_effect_render_node.h"
#include "pipeline/rs_paint_filter_canvas.h"
#include "platform/common/rs_log.h"
#include "platform/common/rs_system_properties.h"
#include "property/rs_properties.h"
#include "property/rs_properties_def.h"
#include "property/rs_properties_painter.h"
#include "render/rs_skia_filter.h"
#include "platform/common/rs_system_properties.h"
namespace {
constexpr int PARAM_DOUBLE = 2;
@ -1096,9 +1087,9 @@ RSBlendSaveLayerDrawable::RSBlendSaveLayerDrawable(int blendMode)
void RSBlendSaveLayerDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
{
if (canvas.GetBlendOffscreenLayerCnt() == 0 &&
RSPropertiesPainter::IsDangerousBlendMode(static_cast<int>(blendBrush_.GetBlendMode()),
static_cast<int>(RSColorBlendApplyType::SAVE_LAYER))) {
if (!canvas.HasOffscreenLayer() &&
RSPropertiesPainter::IsDangerousBlendMode(
static_cast<int>(blendBrush_.GetBlendMode()), static_cast<int>(RSColorBlendApplyType::SAVE_LAYER))) {
Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
canvas.SaveLayer(maskLayerRec);
ROSEN_LOGD("Dangerous offscreen blendmode may produce transparent pixels, add extra offscreen here.");
@ -1118,7 +1109,7 @@ void RSBlendSaveLayerDrawable::Draw(const RSRenderContent& content, RSPaintFilte
void RSBlendFastDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
{
if (canvas.GetBlendOffscreenLayerCnt() == 0 &&
if (!canvas.HasOffscreenLayer() &&
RSPropertiesPainter::IsDangerousBlendMode(blendMode_ - 1, static_cast<int>(RSColorBlendApplyType::FAST))) {
Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
canvas.SaveLayer(maskLayerRec);
@ -1127,16 +1118,14 @@ void RSBlendFastDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanv
canvas.SetBlendMode({ blendMode_ - 1 }); // map blendMode to SkBlendMode
}
void RSBlendSaveLayerRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
{
canvas.RestoreAlpha();
canvas.Restore();
// SAVE_ALL slot will do all necessary restore
}
void RSBlendFastRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
{
canvas.Restore();
// SAVE_ALL slot will do all necessary restore
}
} // namespace OHOS::Rosen