• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "drawable/rs_surface_render_node_drawable.h"
17 #include "rs_draw_window_cache.h"
18 #include "rs_uni_render_thread.h"
19 #include "rs_trace.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 
~RSDrawWindowCache()24 RSDrawWindowCache::~RSDrawWindowCache()
25 {
26     ClearCache();
27 }
28 
DrawAndCacheWindowContent(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,RSPaintFilterCanvas & canvas,const Drawing::Rect & bounds)29 void RSDrawWindowCache::DrawAndCacheWindowContent(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
30     RSPaintFilterCanvas& canvas, const Drawing::Rect& bounds)
31 {
32     if (surfaceDrawable == nullptr) {
33         RS_LOGE("RSDrawWindowCache::DrawAndCacheWindowContent drawable nullptr.");
34         return;
35     }
36 
37     // prepare offscreen canvas
38     auto mainSurface = canvas.GetSurface();
39     if (mainSurface == nullptr) {
40         RS_LOGE("RSDrawWindowCache::DrawAndCacheWindowContent main surface nullptr.");
41         return;
42     }
43     auto windowSurface = mainSurface->MakeSurface(bounds.GetWidth(), bounds.GetHeight());
44     if (windowSurface == nullptr) {
45         RS_LOGE("RSDrawWindowCache::DrawAndCacheWindowContent surface nullptr.");
46         return;
47     }
48     auto windowCanvas = std::make_shared<RSPaintFilterCanvas>(windowSurface.get());
49     if (windowCanvas == nullptr) {
50         RS_LOGE("RSDrawWindowCache::DrawAndCacheWindowContent canvas nullptr.");
51         windowSurface = nullptr;
52         return;
53     }
54     RS_TRACE_NAME_FMT("DrawAndCacheWindow node[%lld] %s", surfaceDrawable->GetId(), surfaceDrawable->GetName().c_str());
55     // copy HDR properties into offscreen canvas
56     windowCanvas->CopyHDRConfiguration(canvas);
57     // copy current canvas properties into offscreen canvas
58     windowCanvas->CopyConfigurationToOffscreenCanvas(canvas);
59     windowCanvas->SetDisableFilterCache(true);
60     auto acr = std::make_unique<RSAutoCanvasRestore>(windowCanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
61     windowCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
62 
63     // draw window content/children onto offscreen canvas
64     auto& uniParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
65     bool isOpDropped = uniParams != nullptr ? uniParams->IsOpDropped() : true;
66     if (uniParams) {
67         uniParams->SetOpDropped(false); // temporarily close partial render
68     }
69     surfaceDrawable->DrawContent(*windowCanvas, bounds); // draw content
70     surfaceDrawable->DrawChildren(*windowCanvas, bounds); // draw children
71     if (uniParams) {
72         uniParams->SetOpDropped(isOpDropped);
73     }
74 
75     // cache and draw snapshot of offscreen canvas onto target canvas
76     image_ = windowSurface->GetImageSnapshot();
77     if (image_ == nullptr) {
78         RS_LOGE("RSDrawWindowCache::DrawAndCacheWindowContent snapshot nullptr.");
79         return;
80     }
81     Drawing::Brush paint;
82     paint.SetAntiAlias(true);
83     canvas.AttachBrush(paint);
84     auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NONE);
85     canvas.DrawImage(*image_, 0, 0, samplingOptions);
86     canvas.DetachBrush();
87 }
88 
DealWithCachedWindow(DrawableV2::RSSurfaceRenderNodeDrawable * surfaceDrawable,RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)89 bool RSDrawWindowCache::DealWithCachedWindow(DrawableV2::RSSurfaceRenderNodeDrawable* surfaceDrawable,
90     RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams)
91 {
92     if (surfaceDrawable == nullptr ||
93         surfaceDrawable->HasCachedTexture() ||
94         !HasCache() ||
95         surfaceParams.GetUifirstNodeEnableParam() == MultiThreadCacheType::NONE) {
96         ClearCache();
97         return false;
98     }
99     if (ROSEN_EQ(image_->GetWidth(), 0) || ROSEN_EQ(image_->GetHeight(), 0)) {
100         RS_LOGE("RSDrawWindowCache::DealWithCachedWindow buffer size is zero.");
101         return false;
102     }
103     RS_TRACE_NAME_FMT("DealWithCachedWindow node[%lld] %s",
104         surfaceDrawable->GetId(), surfaceDrawable->GetName().c_str());
105     RSAutoCanvasRestore acr(&canvas);
106     if (!RSUniRenderThread::GetCaptureParam().isSnapshot_) {
107         canvas.MultiplyAlpha(surfaceParams.GetAlpha());
108         canvas.ConcatMatrix(surfaceParams.GetMatrix());
109     }
110     auto boundSize = surfaceParams.GetFrameRect();
111     // draw background
112     surfaceDrawable->DrawBackground(canvas, boundSize);
113     float scaleX = boundSize.GetWidth() / static_cast<float>(image_->GetWidth());
114     float scaleY = boundSize.GetHeight() / static_cast<float>(image_->GetHeight());
115     canvas.Scale(scaleX, scaleY);
116     if (RSSystemProperties::GetRecordingEnabled()) {
117         if (image_->IsTextureBacked()) {
118             RS_LOGI("RSDrawWindowCache::DealWithCachedWindow convert image from texture to raster image.");
119             image_ = image_->MakeRasterImage();
120         }
121     }
122     Drawing::Brush brush;
123     canvas.AttachBrush(brush);
124     auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
125     auto gravityTranslate = surfaceDrawable->GetGravityTranslate(image_->GetWidth(), image_->GetHeight());
126     // draw content/children
127     canvas.DrawImage(*image_, gravityTranslate.x_, gravityTranslate.y_, samplingOptions);
128     canvas.DetachBrush();
129     // draw foreground
130     surfaceDrawable->DrawForeground(canvas, boundSize);
131     return true;
132 }
133 
ClearCache()134 void RSDrawWindowCache::ClearCache()
135 {
136     image_ = nullptr;
137 }
138 
HasCache() const139 bool RSDrawWindowCache::HasCache() const
140 {
141     return image_ != nullptr;
142 }
143 
144 } // Rosen
145 } // OHOS