modify dirty region dfx of RT

Signed-off-by: shiyueeee <nieshiyue@huawei.com>
Change-Id: I98969fe495821ddcf06e1f5c954f99f29c0b7e34
This commit is contained in:
shiyueeee 2023-02-21 17:21:58 +08:00
parent 876ef10db5
commit fbf8a397bb
6 changed files with 102 additions and 77 deletions

View File

@ -24,14 +24,24 @@
namespace OHOS {
namespace Rosen {
// classify dfx debug options
enum DebugRegionType {
CURRENT_SUB,
CURRENT_SUB = 0,
CURRENT_WHOLE,
MULTI_HISTORY,
EGL_DAMAGE,
TYPE_MAX
};
// classify types that cause region dirty
enum DirtyRegionType {
UPDATE_DIRTY_REGION = 0,
OVERLAY_RECT,
FILTER_RECT,
REMOVE_CHILD,
TYPE_AMOUNT
};
class RSB_EXPORT RSDirtyRegionManager final {
public:
static constexpr int32_t ALIGNED_BITS = 32;
@ -55,10 +65,6 @@ public:
bool IsDirty() const;
void UpdateDirty(bool enableAligned = false);
void UpdateDirtyByAligned(int32_t alignedBits = ALIGNED_BITS);
void UpdateDirtyCanvasNodes(NodeId id, const RectI& rect);
void UpdateDirtySurfaceNodes(NodeId id, const RectI& rect);
void GetDirtyCanvasNodes(std::map<NodeId, RectI>& target) const;
void GetDirtySurfaceNodes(std::map<NodeId, RectI>& target) const;
bool SetBufferAge(const int age);
bool SetSurfaceSize(const int32_t width, const int32_t height);
RectI GetSurfaceRect() const
@ -67,7 +73,7 @@ public:
}
void ResetDirtyAsSurfaceSize();
void UpdateDebugRegionTypeEnable();
void UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType);
inline bool IsDebugRegionTypeEnable(DebugRegionType var) const
{
@ -76,11 +82,13 @@ public:
}
return false;
}
inline bool IsDebugEnabled() const
{
return RSSystemProperties::GetDirtyRegionDebugType() != DirtyRegionDebugType::DISABLED;
}
// added for dirty region dfx
void UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType = RSRenderNodeType::CANVAS_NODE,
DirtyRegionType dirtyType = DirtyRegionType::UPDATE_DIRTY_REGION, const RectI& rect = RectI());
void GetDirtyRegionInfo(std::map<NodeId, RectI>& target,
RSRenderNodeType nodeType = RSRenderNodeType::CANVAS_NODE,
DirtyRegionType dirtyType = DirtyRegionType::UPDATE_DIRTY_REGION) const;
private:
RectI MergeHistory(unsigned int age, RectI rect) const;
@ -91,8 +99,9 @@ private:
RectI surfaceRect_;
RectI dirtyRegion_;
std::map<NodeId, RectI> dirtyCanvasNodes_;
std::map<NodeId, RectI> dirtySurfaceNodes_;
// added for dfx
std::vector<std::map<NodeId, RectI>> dirtyCanvasNodeInfo_;
std::vector<std::map<NodeId, RectI>> dirtySurfaceNodeInfo_;
std::vector<bool> debugRegionEnabled_;
std::vector<RectI> dirtyHistory_;
int historyHead_ = -1;

View File

@ -95,9 +95,10 @@ RectI RSDirtyRegionManager::GetPixelAlignedRect(const RectI& rect, int32_t align
void RSDirtyRegionManager::Clear()
{
dirtyRegion_.Clear();
dirtyCanvasNodes_.clear();
dirtySurfaceNodes_.clear();
UpdateDebugRegionTypeEnable();
dirtyCanvasNodeInfo_.clear();
dirtyCanvasNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
dirtySurfaceNodeInfo_.clear();
dirtySurfaceNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
}
bool RSDirtyRegionManager::IsDirty() const
@ -124,24 +125,31 @@ void RSDirtyRegionManager::UpdateDirtyByAligned(int32_t alignedBits)
dirtyRegion_ = GetPixelAlignedRect(dirtyRegion_, alignedBits);
}
void RSDirtyRegionManager::UpdateDirtyCanvasNodes(NodeId id, const RectI& rect)
void RSDirtyRegionManager::UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType,
DirtyRegionType dirtyType, const RectI& rect)
{
dirtyCanvasNodes_[id] = rect;
if (dirtyType >= DirtyRegionType::TYPE_AMOUNT || dirtyType < 0 || rect.IsEmpty()) {
return;
}
if (nodeType == RSRenderNodeType::CANVAS_NODE) {
dirtyCanvasNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
} else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
dirtySurfaceNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
}
}
void RSDirtyRegionManager::UpdateDirtySurfaceNodes(NodeId id, const RectI& rect)
void RSDirtyRegionManager::GetDirtyRegionInfo(std::map<NodeId, RectI>& target,
RSRenderNodeType nodeType, DirtyRegionType dirtyType) const
{
dirtySurfaceNodes_[id] = rect;
}
void RSDirtyRegionManager::GetDirtyCanvasNodes(std::map<NodeId, RectI>& target) const
{
target = dirtyCanvasNodes_;
}
void RSDirtyRegionManager::GetDirtySurfaceNodes(std::map<NodeId, RectI>& target) const
{
target = dirtySurfaceNodes_;
target.clear();
if (dirtyType >= DirtyRegionType::TYPE_AMOUNT || dirtyType < 0) {
return;
}
if (nodeType == RSRenderNodeType::CANVAS_NODE) {
target = dirtyCanvasNodeInfo_[dirtyType];
} else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
target = dirtySurfaceNodeInfo_[dirtyType];
}
}
bool RSDirtyRegionManager::SetBufferAge(const int age)
@ -168,9 +176,8 @@ void RSDirtyRegionManager::ResetDirtyAsSurfaceSize()
dirtyRegion_ = surfaceRect_;
}
void RSDirtyRegionManager::UpdateDebugRegionTypeEnable()
void RSDirtyRegionManager::UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)
{
DirtyRegionDebugType dirtyDebugType = RSSystemProperties::GetDirtyRegionDebugType();
debugRegionEnabled_.assign(DebugRegionType::TYPE_MAX, false);
switch (dirtyDebugType) {
case DirtyRegionDebugType::CURRENT_SUB:

View File

@ -76,11 +76,14 @@ bool RSRenderThreadVisitor::IsValidRootRenderNode(RSRootRenderNode& node)
void RSRenderThreadVisitor::SetPartialRenderStatus(PartialRenderType status, bool isRenderForced)
{
isRenderForced_ = isRenderForced;
dfxDirtyType_ = RSSystemProperties::GetDirtyRegionDebugType();
isEglSetDamageRegion_ = !isRenderForced_ && (status != PartialRenderType::DISABLED);
isOpDropped_ = !isRenderForced_ && (status == PartialRenderType::SET_DAMAGE_AND_DROP_OP);
if (partialRenderStatus_ == status) {
ROSEN_LOGD("SetPartialRenderStatus: %d->%d, isRenderForced_=%d, isEglSetDamageRegion_=%d, isOpDropped_=%d",
partialRenderStatus_, status, isRenderForced_, isEglSetDamageRegion_, isOpDropped_);
isOpDropped_ = (dfxDirtyType_ == DirtyRegionDebugType::DISABLED) && !isRenderForced_ &&
(status == PartialRenderType::SET_DAMAGE_AND_DROP_OP);
if (partialRenderStatus_ != status) {
ROSEN_LOGD("PartialRenderStatus: %d->%d, isRenderForced_=%d, dfxDirtyType_=%d,\
isEglSetDamageRegion_=%d, isOpDropped_=%d", partialRenderStatus_, status,
isRenderForced_, dfxDirtyType_, isEglSetDamageRegion_, isOpDropped_);
}
partialRenderStatus_ = status;
}
@ -103,6 +106,7 @@ void RSRenderThreadVisitor::PrepareRootRenderNode(RSRootRenderNode& node)
if (isIdle_) {
curDirtyManager_ = node.GetDirtyManager();
curDirtyManager_->Clear();
curDirtyManager_->UpdateDebugRegionTypeEnable(dfxDirtyType_);
// After the node calls ApplyModifiers, the modifiers assign the renderProperties to the node
// Otherwise node.GetSuggestedBufferHeight always less than 0, causing black screen
node.ApplyModifiers();
@ -147,8 +151,10 @@ void RSRenderThreadVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode& node)
rsParent = nodeParent->ReinterpretCastTo<RSRenderNode>();
}
dirtyFlag_ = node.Update(*curDirtyManager_, rsParent ? &(rsParent->GetRenderProperties()) : nullptr, dirtyFlag_);
if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
curDirtyManager_->UpdateDirtyCanvasNodes(node.GetId(), node.GetOldDirty());
if (node.IsDirtyRegionUpdated() && curDirtyManager_ != nullptr &&
curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
curDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::CANVAS_NODE,
DirtyRegionType::UPDATE_DIRTY_REGION, node.GetOldDirty());
}
ResetAndPrepareChildrenNode(node, nodeParent);
dirtyFlag_ = dirtyFlag;
@ -170,28 +176,29 @@ void RSRenderThreadVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node)
node.SetDirty();
}
dirtyFlag_ = node.Update(*curDirtyManager_, rsParent ? &(rsParent->GetRenderProperties()) : nullptr, dirtyFlag_);
if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
curDirtyManager_->UpdateDirtySurfaceNodes(node.GetId(), node.GetOldDirty());
if (node.IsDirtyRegionUpdated() && curDirtyManager_ != nullptr &&
curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
curDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::SURFACE_NODE,
DirtyRegionType::UPDATE_DIRTY_REGION, node.GetOldDirty());
}
ResetAndPrepareChildrenNode(node, nodeParent);
dirtyFlag_ = dirtyFlag;
}
void RSRenderThreadVisitor::DrawRectOnCanvas(const RectI& dirtyRect, const SkColor color,
const SkPaint::Style fillType, float alpha)
const SkPaint::Style fillType, float alpha, int strokeWidth)
{
if (dirtyRect.width_ <= 0 || dirtyRect.height_ <= 0) {
if (dirtyRect.IsEmpty()) {
ROSEN_LOGD("DrawRectOnCanvas dirty rect is invalid.");
return;
}
auto skRect = SkRect::MakeXYWH(dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
const int defaultEdgeWidth = 6;
SkPaint rectPaint;
rectPaint.setColor(color);
rectPaint.setAntiAlias(true);
rectPaint.setAlphaf(alpha);
rectPaint.setStyle(fillType);
rectPaint.setStrokeWidth(defaultEdgeWidth);
rectPaint.setStrokeWidth(strokeWidth);
if (fillType == SkPaint::kFill_Style) {
rectPaint.setStrokeJoin(SkPaint::kRound_Join);
}
@ -203,52 +210,53 @@ void RSRenderThreadVisitor::DrawDirtyRegion()
auto dirtyRect = RectI();
const float fillAlpha = 0.2;
const float edgeAlpha = 0.4;
const float subFactor = 2.0;
if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::MULTI_HISTORY)) {
dirtyRect = curDirtyManager_->GetDirtyRegion();
if (dirtyRect.IsEmpty()) {
ROSEN_LOGD("DrawDirtyRegion his dirty rect is invalid. dirtyRect = [%d, %d, %d, %d]",
dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
ROSEN_LOGD("DrawDirtyRegion his dirty rect is invalid. dirtyRect = %s", dirtyRect.ToString().c_str());
} else {
ROSEN_LOGD("DrawDirtyRegion his dirty rect. dirtyRect = [%d, %d, %d, %d]",
dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
ROSEN_LOGD("DrawDirtyRegion his dirty rect. dirtyRect = %s", dirtyRect.ToString().c_str());
// green
DrawRectOnCanvas(dirtyRect, 0xFF0AFF0A, SkPaint::kFill_Style, fillAlpha / subFactor);
DrawRectOnCanvas(dirtyRect, 0xFF0AFF0A, SkPaint::kStroke_Style, edgeAlpha);
DrawRectOnCanvas(dirtyRect, 0x442FDD2F, SkPaint::kFill_Style, fillAlpha);
DrawRectOnCanvas(dirtyRect, 0xFF2FDD2F, SkPaint::kStroke_Style, edgeAlpha);
}
}
if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_WHOLE)) {
dirtyRect = curDirtyManager_->GetLatestDirtyRegion();
if (dirtyRect.IsEmpty()) {
ROSEN_LOGD("DrawDirtyRegion current frame's dirty rect is invalid. dirtyRect = [%d, %d, %d, %d]",
dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
ROSEN_LOGD("DrawDirtyRegion current frame's dirty rect is invalid. dirtyRect = %s",
dirtyRect.ToString().c_str());
} else {
ROSEN_LOGD("DrawDirtyRegion cur dirty rect. dirtyRect = [%d, %d, %d, %d]",
dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
ROSEN_LOGD("DrawDirtyRegion cur dirty rect. dirtyRect = %s", dirtyRect.ToString().c_str());
// yellow
DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, SkPaint::kFill_Style, fillAlpha);
DrawRectOnCanvas(dirtyRect, 0x88FFFF00, SkPaint::kFill_Style, fillAlpha);
DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, SkPaint::kStroke_Style, edgeAlpha);
}
}
if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
std::map<NodeId, RectI> dirtySubRects_;
curDirtyManager_->GetDirtyCanvasNodes(dirtySubRects_);
for (const auto& [nid, subRect] : dirtySubRects_) {
ROSEN_LOGD("DrawDirtyRegion canvasNode id %" PRIu64 " is dirty. dirtyRect = [%d, %d, %d, %d]", nid,
subRect.left_, subRect.top_, subRect.width_, subRect.height_);
// red
DrawRectOnCanvas(subRect, 0xFFFF0000, SkPaint::kStroke_Style, edgeAlpha / subFactor);
const int strokeWidth = 4;
std::map<NodeId, RectI> dirtyRegionRects_;
curDirtyManager_->GetDirtyRegionInfo(dirtyRegionRects_, RSRenderNodeType::CANVAS_NODE,
DirtyRegionType::UPDATE_DIRTY_REGION);
ROSEN_LOGD("DrawDirtyRegion canvas dirtyRegionRects_ size %zu", dirtyRegionRects_.size());
// Draw Canvas Node
for (const auto& [nid, subRect] : dirtyRegionRects_) {
ROSEN_LOGD("DrawDirtyRegion canvas node id %" PRIu64 " is dirty. dirtyRect = %s",
nid, subRect.ToString().c_str());
DrawRectOnCanvas(subRect, 0x88FF0000, SkPaint::kStroke_Style, edgeAlpha, strokeWidth);
}
curDirtyManager_->GetDirtySurfaceNodes(dirtySubRects_);
for (const auto& [nid, subRect] : dirtySubRects_) {
ROSEN_LOGD("DrawDirtyRegion surfaceNode id %" PRIu64 " is dirty. dirtyRect = [%d, %d, %d, %d]", nid,
subRect.left_, subRect.top_, subRect.width_, subRect.height_);
// light purple
DrawRectOnCanvas(subRect, 0xFFD899D8, SkPaint::kStroke_Style, edgeAlpha);
curDirtyManager_->GetDirtyRegionInfo(dirtyRegionRects_, RSRenderNodeType::SURFACE_NODE,
DirtyRegionType::UPDATE_DIRTY_REGION);
ROSEN_LOGD("DrawDirtyRegion surface dirtyRegionRects_ size %zu", dirtyRegionRects_.size());
// Draw Surface Node
for (const auto& [nid, subRect] : dirtyRegionRects_) {
ROSEN_LOGD("DrawDirtyRegion surface node id %" PRIu64 " is dirty. dirtyRect = %s",
nid, subRect.ToString().c_str());
DrawRectOnCanvas(subRect, 0xFFD864D8, SkPaint::kStroke_Style, edgeAlpha, strokeWidth);
}
}
}
@ -451,7 +459,7 @@ void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
transactionProxy->FlushImplicitTransactionFromRT(uiTimestamp_);
}
if (curDirtyManager_->IsDirty() && curDirtyManager_->IsDebugEnabled()) {
if ((dfxDirtyType_ != DirtyRegionDebugType::DISABLED) && curDirtyManager_->IsDirty()) {
ROSEN_LOGD("ProcessRootRenderNode %s [%" PRIu64 "] draw dirtyRect", ptr->GetName().c_str(), node.GetId());
DrawDirtyRegion();
}

View File

@ -52,7 +52,8 @@ public:
// Partial render status and renderForce flag should be updated by rt thread
void SetPartialRenderStatus(PartialRenderType status, bool isRenderForced);
private:
void DrawRectOnCanvas(const RectI& dirtyRect, const SkColor color, const SkPaint::Style fillType, float alpha);
void DrawRectOnCanvas(const RectI& dirtyRect, const SkColor color, const SkPaint::Style fillType, float alpha,
int strokeWidth = 6);
void DrawDirtyRegion();
// Update damageRegion based on buffer age, and then set it through egl api
void UpdateDirtyAndSetEGLDamageRegion(std::unique_ptr<RSSurfaceFrame>& surfaceFrame);
@ -63,6 +64,7 @@ private:
bool isRenderForced_ = false;
bool isEglSetDamageRegion_ = false;
bool isOpDropped_ = false;
DirtyRegionDebugType dfxDirtyType_ = DirtyRegionDebugType::DISABLED;
PartialRenderType partialRenderStatus_ = PartialRenderType::DISABLED;
RectI curDirtyRegion_ = RectI();
bool dirtyFlag_ = false;

View File

@ -199,6 +199,8 @@ bool RSDirtyRegionManagerFuzzTest(const uint8_t* data, size_t size)
RectI rect(left, top, width, height);
uint64_t u_id = GetData<uint64_t>();
NodeId id = static_cast<NodeId>(u_id);
RSRenderNodeType nodeType = GetData<RSRenderNodeType>();
DirtyRegionType dirtyType = GetData<DirtyRegionType>();
std::map<NodeId, RectI> target;
target.insert(std::pair<NodeId, RectI>(id, rect));
@ -207,10 +209,8 @@ bool RSDirtyRegionManagerFuzzTest(const uint8_t* data, size_t size)
manager.GetRectFlipWithinSurface(rect);
RSDirtyRegionManager::GetPixelAlignedRect(rect, GetData<int32_t>());
manager.UpdateDirtyByAligned(GetData<int32_t>());
manager.UpdateDirtyCanvasNodes(id, rect);
manager.UpdateDirtySurfaceNodes(id, rect);
manager.GetDirtyCanvasNodes(target);
manager.GetDirtySurfaceNodes(target);
manager.UpdateDirtyRegionInfoForDfx(id, nodeType, dirtyType, rect);
manager.GetDirtyRegionInfo(target, nodeType, dirtyType);
manager.SetBufferAge(GetData<int>());
manager.SetSurfaceSize(GetData<int32_t>(), GetData<int32_t>());
manager.IsDebugRegionTypeEnable(GetData<DebugRegionType>());

View File

@ -507,7 +507,6 @@ HWTEST_F(RSRenderThreadVisitorTest, ProcessRootRenderNode007, TestSize.Level1)
rootnode->Process(rsRenderThreadVisitor);
rsRenderThreadVisitor->SetPartialRenderStatus(PartialRenderType::SET_DAMAGE, true);
rootnode->UpdateSuggestedBufferSize(10, 10);
rootnode->GetDirtyManager()->UpdateDirtyCanvasNodes(nodeId, rootnode->GetOldDirty());
constexpr NodeId nodeId2 = TestSrc::limitNumber::Uint64[1];
auto canvasnode = std::make_shared<RSCanvasRenderNode>(nodeId2);
canvasnode->GetMutableRenderProperties().SetAlpha(1.f);