!17220 canvas lostop in occlusion area

Merge pull request !17220 from redermens/exportnode
This commit is contained in:
openharmony_ci 2024-11-22 03:38:51 +00:00 committed by Gitee
commit 1cd53f72a0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 145 additions and 102 deletions

View File

@ -17,6 +17,7 @@
#include "common/rs_background_thread.h"
#include "common/rs_common_def.h"
#include "common/rs_optional_trace.h"
#include "offscreen_render/rs_offscreen_render_thread.h"
#include "params/rs_canvas_drawing_render_params.h"
#include "pipeline/rs_main_thread.h"
@ -228,6 +229,9 @@ void RSCanvasDrawingRenderNodeDrawable::Purge()
isPurgeMatrix_ = true;
curThreadInfo_.second(std::move(surface_));
surface_ = nullptr;
recordingCanvas_ = nullptr;
image_ = nullptr;
canvas_ = nullptr;
}
#endif
RSRenderNodeDrawableAdapter::Purge();
@ -252,30 +256,35 @@ void RSCanvasDrawingRenderNodeDrawable::PostPlaybackInCorrespondThread()
{
auto canvasDrawingPtr = shared_from_this();
pid_t threadId = threadId_;
RS_OPTIONAL_TRACE_NAME_FMT("post playback task node[%llu]", GetId());
auto task = [this, canvasDrawingPtr, threadId]() {
std::unique_lock<std::recursive_mutex> lock(drawableMutex_);
// default in unirenderthread
if (!renderParams_ || renderParams_->GetCanvasDrawingSurfaceChanged()) {
if (!IsNeedDraw()) {
return;
}
if (!renderParams_) {
RS_LOGE("PostPlaybackInCorrespondThread NodeId[%{public}" PRIu64 "] renderParams null", GetId());
return;
}
if (threadId != threadId_) {
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::PostPlayback ThreadId Error NodeId[%{public}" PRIu64 "],"
RS_LOGE("PostPlaybackInCorrespondThread ThreadId Error NodeId[%{public}" PRIu64 "],"
"threadId[%{public}d], threadId_[%{public}d]", GetId(), threadId, threadId_.load());
return;
}
auto surfaceParams = renderParams_->GetCanvasDrawingSurfaceParams();
if (surfaceParams.width == 0 || surfaceParams.height == 0) {
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::PostPlayback Area Error NodeId[%{public}" PRIu64 "],"
"width[%{public}d], height[%{public}d]", GetId(), surfaceParams.width, surfaceParams.height);
SetNeedDraw(false);
return;
if (renderParams_->GetCanvasDrawingSurfaceChanged()) {
ResetSurface();
RS_LOGI("PostPlaybackInCorrespondThread NodeId[%{public}" PRIu64 "] SurfaceChanged Reset Surface", GetId());
renderParams_->SetCanvasDrawingSurfaceChanged(false);
}
auto surfaceParams = renderParams_->GetCanvasDrawingSurfaceParams();
if (!surface_ || !canvas_) {
if (!ResetSurfaceforPlayback(surfaceParams.width, surfaceParams.height)) {
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::PostPlayback Reset Surface Error NodeId[%{public}" PRIu64
RS_LOGE("PostPlaybackInCorrespondThread Reset Surface Error NodeId[%{public}" PRIu64
"], width[%{public}d], height[%{public}d]", GetId(), surfaceParams.width, surfaceParams.height);
return;
}
@ -288,6 +297,8 @@ void RSCanvasDrawingRenderNodeDrawable::PostPlaybackInCorrespondThread()
};
SetSurfaceClearFunc({ threadIdx, clearFunc }, threadId);
}
RS_OPTIONAL_TRACE_NAME_FMT("PostPlaybackInCorrespondThread NodeId[%llu]", GetId());
RS_LOGI("CanvasDrawing PostPlayback NodeId[%{public}" PRIu64 "] finish draw", GetId());
auto rect = GetRenderParams()->GetBounds();
DrawContent(*canvas_, rect);
SetNeedDraw(false);
@ -465,8 +476,9 @@ void RSCanvasDrawingRenderNodeDrawable::ProcessCPURenderInBackgroundThread(std::
void RSCanvasDrawingRenderNodeDrawable::ResetSurface()
{
RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ResetSurface NodeId[%{public}" PRIu64 "] ResetSurface", GetId());
if (surface_ && surface_->GetImageInfo().GetWidth() > EDGE_WIDTH_LIMIT) {
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface id:%{public}" PRIu64 "", nodeId_);
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurface id:%{public}" PRIu64 "]", nodeId_);
}
#ifdef RS_ENABLE_VK
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
@ -660,6 +672,36 @@ void RSCanvasDrawingRenderNodeDrawable::DrawCaptureImage(RSPaintFilterCanvas& ca
#endif
}
#ifdef RS_ENABLE_VK
bool RSCanvasDrawingRenderNodeDrawable::ReleaseSurfaceVK(int width, int height)
{
if (!backendTexture_.IsValid() || !backendTexture_.GetTextureInfo().GetVKTextureInfo()) {
backendTexture_ = RSUniRenderUtil::MakeBackendTexture(width, height);
if (!backendTexture_.IsValid()) {
if ((RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) &&
(vulkanCleanupHelper_ && isPurge_)) {
vulkanCleanupHelper_->UnRef();
isPurge_ = false;
}
surface_ = nullptr;
recordingCanvas_ = nullptr;
image_ = nullptr;
canvas_ = nullptr;
backendTexture_ = {};
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
vulkanCleanupHelper_ = nullptr;
}
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForVK size too big [%{public}d, %{public}d] failed",
width, height);
return false;
}
}
return true;
}
#endif
bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForVK(int width, int height, RSPaintFilterCanvas& canvas)
{
Drawing::ImageInfo info =
@ -674,30 +716,8 @@ bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForVK(int width, int height,
isGpuSurface_ = false;
surface_ = Drawing::Surface::MakeRaster(info);
} else {
if (!backendTexture_.IsValid() || !backendTexture_.GetTextureInfo().GetVKTextureInfo()) {
backendTexture_ = RSUniRenderUtil::MakeBackendTexture(width, height);
if (!backendTexture_.IsValid()) {
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
if (vulkanCleanupHelper_ && isPurge_) {
vulkanCleanupHelper_->UnRef();
isPurge_ = false;
}
}
surface_ = nullptr;
recordingCanvas_ = nullptr;
image_ = nullptr;
canvas_ = nullptr;
backendTexture_ = {};
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
vulkanCleanupHelper_ = nullptr;
}
RS_LOGE(
"RSCanvasDrawingRenderNodeDrawable::ResetSurfaceForVK size too big [%{public}d, %{public}d] failed",
width, height);
return false;
}
if (!ReleaseSurfaceVK(width, height)) {
return false;
}
auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
if (vulkanCleanupHelper_ == nullptr) {
@ -798,12 +818,12 @@ bool RSCanvasDrawingRenderNodeDrawable::GetCurrentContext(std::shared_ptr<Drawin
return true;
}
#if defined(RS_ENABLE_GL)
bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetGL(
int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext)
{
Drawing::ImageInfo info =
Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
#if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
surface_ = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
if (!surface_) {
isGpuSurface_ = false;
@ -816,41 +836,22 @@ bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetGL(
canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
return true;
}
#else
surface_ = Drawing::Surface::MakeRaster(info);
#endif
return true;
}
#endif
#if defined(RS_ENABLE_VK)
bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetVk(
bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetVK(
int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext)
{
Drawing::ImageInfo info =
Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
bool isNewCreate = false;
if (!backendTexture_.IsValid() || !backendTexture_.GetTextureInfo().GetVKTextureInfo()) {
backendTexture_ = RSUniRenderUtil::MakeBackendTexture(width, height);
if (!backendTexture_.IsValid()) {
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
if (vulkanCleanupHelper_ && isPurge_) {
vulkanCleanupHelper_->UnRef();
isPurge_ = false;
}
}
surface_ = nullptr;
recordingCanvas_ = nullptr;
image_ = nullptr;
canvas_ = nullptr;
backendTexture_ = {};
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
vulkanCleanupHelper_ = nullptr;
}
RS_LOGE("RSCanvasDrawingRenderNodeDrawable::VK backendTexture invalid, nodeId[%{public}" PRIu64 "]",
GetId());
return false;
}
#if defined(RS_ENABLE_VK)
if (!ReleaseSurfaceVK(width, height)) {
return false;
}
auto vkTextureInfo = backendTexture_.GetTextureInfo().GetVKTextureInfo();
if (vulkanCleanupHelper_ == nullptr) {
@ -874,14 +875,17 @@ bool RSCanvasDrawingRenderNodeDrawable::GpuContextResetVk(
return true;
}
return true;
}
#else
surface_ = Drawing::Surface::MakeRaster(info);
#endif
return true;
}
bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceforPlayback(int width, int height)
{
Drawing::ImageInfo info =
Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
RS_LOGI("RSCanvasDrawingRenderNodeDrawable::ResetSurfaceforPlayback NodeId[%{public}" PRIu64 "]", GetId());
std::shared_ptr<Drawing::GPUContext> gpuContext;
if (canvas_ == nullptr) {
if (!GetCurrentContext(gpuContext)) {
@ -897,25 +901,23 @@ bool RSCanvasDrawingRenderNodeDrawable::ResetSurfaceforPlayback(int width, int h
isGpuSurface_ = false;
surface_ = Drawing::Surface::MakeRaster(info);
} else {
#if defined(RS_ENABLE_GL)
if (!GpuContextResetGL(width, height, gpuContext)) {
return false;
if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
if (!GpuContextResetGL(width, height, gpuContext)) {
return false;
}
if (canvas_) {
return true;
}
}
if (canvas_) {
return true;
if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
if (!GpuContextResetVK(width, height, gpuContext)) {
return false;
}
if (canvas_) {
return true;
}
}
#else
#if defined(RS_ENABLE_VK)
if (!GpuContextResetVk(width, height, gpuContext)) {
return false;
}
if (canvas_) {
return true;
}
#else
surface_ = Drawing::Surface::MakeRaster(info);
#endif
#endif
}
if (!surface_) {

View File

@ -72,11 +72,10 @@ private:
void DrawRenderContent(Drawing::Canvas& canvas, const Drawing::Rect& rect);
bool ResetSurfaceForGL(int width, int height, RSPaintFilterCanvas& canvas);
bool ResetSurfaceForVK(int width, int height, RSPaintFilterCanvas& canvas);
#if defined(RS_ENABLE_GL)
bool GpuContextResetGL(int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext);
#endif
#if defined(RS_ENABLE_VK)
bool GpuContextResetVk(int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext);
bool GpuContextResetVK(int width, int height, std::shared_ptr<Drawing::GPUContext>& gpuContext);
#ifdef RS_ENABLE_VK
bool ReleaseSurfaceVK(int width, int height);
#endif
bool ResetSurfaceforPlayback(int width, int height);
bool GetCurrentContext(std::shared_ptr<Drawing::GPUContext>& grContext);

View File

@ -1217,7 +1217,7 @@ void RSMainThread::ProcessCommandForUniRender()
if (canvasDrawingNode == nullptr) {
return;
}
if (canvasDrawingNode->IsNeedProcess() && !canvasDrawingNode->IsOnTheTree()) {
if (canvasDrawingNode->IsNeedProcess()) {
auto drawableNode = DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(canvasDrawingNode);
if (!drawableNode) {
RS_LOGE("RSMainThread::ProcessCommandForUniRender GetCanvasDrawable Failed NodeId[%{public}" PRIu64 "]",

View File

@ -80,7 +80,7 @@ private:
explicit RSCanvasDrawingRenderNode(
NodeId id, const std::weak_ptr<RSContext>& context = {}, bool isTextureExportNode = false);
void ApplyDrawCmdModifier(RSModifierContext& context, RSModifierType type);
void CheckDrawCmdListSize(RSModifierType type);
void CheckDrawCmdListSize(RSModifierType type);
bool ResetSurface(int width, int height, RSPaintFilterCanvas& canvas);
bool GetSizeFromDrawCmdModifiers(int& width, int& height);
bool IsNeedResetSurface() const;
@ -109,7 +109,6 @@ private:
// Used in uni render thread.
uint32_t drawingNodeRenderID = UNI_MAIN_THREAD_INDEX;
uint32_t playbackNotOnTreeCmdSize_ = 0;
friend class RSCanvasDrawingNodeCommandHelper;
};

View File

@ -208,15 +208,17 @@ bool RSCanvasDrawingRenderNode::IsNeedProcess() const
void RSCanvasDrawingRenderNode::ContentStyleSlotUpdate()
{
//update content_style when node not on tree, need check (waitSync_ false, not on tree, surface not changed)
// update content_style when node not on tree, need check (waitSync_ false, not on tree, never on tree
// not texture exportnode, unirender mode)
// if canvas drawing node never on tree, should not update, it will lost renderParams->localDrawRect_
#ifdef RS_ENABLE_GPU
if (IsWaitSync() || IsOnTheTree() || isNeverOnTree_ || !stagingRenderParams_ ||
stagingRenderParams_->GetCanvasDrawingSurfaceChanged() || RSUniRenderJudgement::IsUniRender()) {
!RSUniRenderJudgement::IsUniRender() || GetIsTextureExportNode()) {
return;
}
#else
if (IsWaitSync() || IsOnTheTree() || isNeverOnTree_ || !stagingRenderParams_ ||
RSUniRenderJudgement::IsUniRender()) {
!RSUniRenderJudgement::IsUniRender() || GetIsTextureExportNode()) {
return;
}
#endif
@ -233,15 +235,31 @@ void RSCanvasDrawingRenderNode::ContentStyleSlotUpdate()
}
#endif
playbackNotOnTreeCmdSize_ += drawCmdLists_[RSModifierType::CONTENT_STYLE].size();
RS_OPTIONAL_TRACE_NAME_FMT("node[%llu], NotOnTreeDraw Cmdlist Size[%lu]", GetId(), playbackNotOnTreeCmdSize_);
//only update content_style dirtyType
auto savedirtyTypes = dirtyTypes_;
dirtyTypes_.reset();
dirtyTypes_.set(static_cast<int>(RSModifierType::CONTENT_STYLE), true);
UpdateDrawableVecV2();
// Clear node some resource
ClearResource();
// update state
dirtyTypes_.reset();
if (!IsWaitSync()) {
RS_LOGE("RSCanvasDrawingRenderNode::ContentStyleSlotUpdate NodeId[%{public}" PRIu64
"] UpdateDrawableVecV2 failed, dirtySlots empty", GetId());
return;
}
RS_LOGI("RSCanvasDrawingRenderNode::ContentStyleSlotUpdate NodeId[%{public}" PRIu64 "]", GetId());
RS_OPTIONAL_TRACE_NAME_FMT("canvas drawing node[%llu] ContentStyleSlotUpdate", GetId());
// clear content_style drawcmdlist
std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
auto contentCmdList = drawCmdLists_.find(RSModifierType::CONTENT_STYLE);
if (contentCmdList != drawCmdLists_.end()) {
contentCmdList->second.clear();
}
savedirtyTypes.set(static_cast<int>(RSModifierType::CONTENT_STYLE), false);
dirtyTypes_ = savedirtyTypes;
AddToPendingSyncList();
}
@ -508,10 +526,12 @@ void RSCanvasDrawingRenderNode::CheckDrawCmdListSize(RSModifierType type)
{
bool overflow = drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT;
if (overflow) {
RS_OPTIONAL_TRACE_NAME_FMT("AddDitryType id:[%llu] StateOnTheTree[%d] ModifierType[%d] ModifierCmdSize[%d]",
GetId(), type, drawCmdLists_[type].size(), IsOnTheTree());
if (overflow != lastOverflowStatus_) {
RS_LOGE("AddDirtyType Out of Cmdlist Limit, This Node[%{public}" PRIu64 "] with Modifier[%{public}hd]"
" have drawcmdlist:%{public}zu",
GetId(), type, drawCmdLists_[type].size());
" have drawcmdlist:%{public}zu, StateOnTheTree[%{public}d]",
GetId(), type, drawCmdLists_[type].size(), IsOnTheTree());
}
// If such nodes are not drawn, The drawcmdlists don't clearOp during recording, As a result, there are
// too many drawOp, so we need to add the limit of drawcmdlists.
@ -521,8 +541,8 @@ void RSCanvasDrawingRenderNode::CheckDrawCmdListSize(RSModifierType type)
}
if (drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT) {
RS_LOGE("AddDirtyType Cmdlist Protect Error, This Node[%{public}" PRIu64 "] with Modifier[%{public}hd]"
" have drawcmdlist:%{public}zu",
GetId(), type, drawCmdLists_[type].size());
" have drawcmdlist:%{public}zu, StateOnTheTree[%{public}d]",
GetId(), type, drawCmdLists_[type].size(), IsOnTheTree());
}
}
lastOverflowStatus_ = overflow;
@ -586,7 +606,7 @@ const std::map<RSModifierType, std::list<Drawing::DrawCmdListPtr>>& RSCanvasDraw
void RSCanvasDrawingRenderNode::ClearResource()
{
if (RSUniRenderJudgement::IsUniRender()) {
if (RSUniRenderJudgement::IsUniRender() && !GetIsTextureExportNode()) {
std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
drawCmdLists_.clear();
}

View File

@ -4335,7 +4335,9 @@ void RSRenderNode::OnSync()
foregroundFilterInteractWithDirty_ = false;
// Reset Sync Flag
renderDrawable_->SetNeedDraw(true);
if (waitSync_) {
renderDrawable_->SetNeedDraw(true);
}
waitSync_ = false;
lastFrameSynced_ = !isLeashWindowPartialSkip;

View File

@ -27,6 +27,7 @@
#include "pipeline/rs_render_engine.h"
#include "pipeline/rs_root_render_node.h"
#include "pipeline/rs_uni_render_engine.h"
#include "pipeline/rs_canvas_drawing_render_node.h"
#include "platform/common/rs_innovation.h"
#include "platform/common/rs_system_properties.h"
#if defined(ACCESSIBILITY_ENABLE)
@ -781,6 +782,13 @@ HWTEST_F(RSMainThreadTest, ProcessCommandForUniRender, TestSize.Level1)
mainThread->effectiveTransactionDataIndexMap_[0].second.emplace_back(std::move(data));
// empty data
mainThread->effectiveTransactionDataIndexMap_[0].second.emplace_back(nullptr);
NodeId nodeId =1;
std::weak_ptr<RSContext> context = {};
auto rsCanvasDrawingRenderNode = std::make_shared<RSCanvasDrawingRenderNode>(nodeId, context);
auto drawableNode = DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(rsCanvasDrawingRenderNode);
drawableNode->SetNeedDraw(true);
mainThread->context_->nodeMap.RegisterRenderNode(rsCanvasDrawingRenderNode);
mainThread->ProcessCommandForUniRender();
}
@ -4064,6 +4072,19 @@ HWTEST_F(RSMainThreadTest, OnCommitDumpClientNodeTree, TestSize.Level2)
ASSERT_TRUE(!mainThread->nodeTreeDumpTasks_[taskId].data.empty());
}
/**
* @tc.name: TraverseCanvasDrawingNodesNotOnTree
* @tc.desc: test TraverseCanvasDrawingNodesNotOnTree
* @tc.type: FUNC
* @tc.require: issueIB56EL
*/
HWTEST_F(RSMainThreadTest, TraverseCanvasDrawingNodesNotOnTree, TestSize.Level2)
{
auto mainThread = RSMainThread::Instance();
ASSERT_NE(mainThread, nullptr);
mainThread->TraverseCanvasDrawingNodesNotOnTree();
}
/**
* @tc.name: CheckIsAihdrSurface
* @tc.desc: Test CheckIsAihdrSurface