1 /*
2 * Copyright (c) 2022 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 "rs_uni_render_util.h"
17 #include <cstdint>
18 #include <unordered_set>
19
20 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
21 #include "pipeline/rs_main_thread.h"
22 #include "pipeline/rs_base_render_util.h"
23 #include "platform/common/rs_log.h"
24 #include "render/rs_path.h"
25 #include "rs_trace.h"
26 #include "common/rs_optional_trace.h"
27 #include "scene_board_judgement.h"
28 #include <parameter.h>
29 #include <parameters.h>
30
31 namespace OHOS {
32 namespace Rosen {
33 namespace {
34 constexpr const char* ENTRY_VIEW = "EntryView";
35 constexpr const char* WALLPAPER_VIEW = "WallpaperView";
36 constexpr const char* SCREENLOCK_WINDOW = "ScreenLockWindow";
37 constexpr const char* SYSUI_DROPDOWN = "SysUI_Dropdown";
38 constexpr const char* SYSUI_STATUS_BAR = "SysUI_StatusBar";
39 constexpr const char* PRIVACY_INDICATOR = "PrivacyIndicator";
40 constexpr const char* SCB_DESK_TOP = "SCBDesktop2";
41 constexpr const char* SCB_WALL_PAPER = "SCBWallpaper1";
42 constexpr const char* SCB_SCREEN_LOCK = "SCBScreenLock10";
43 constexpr const char* SCB_DROP_DOWN_PANEL = "SCBDropdownPanel7";
44 constexpr const char* SCB_STATUS_BAR = "SCBStatusBar6";
45 constexpr const char* SCB_NEGATIVE_SCREEN = "SCBNegativeScreen3";
46 constexpr const char* SCB_GESTURE_BACK = "SCBGestureBack9";
47 };
MergeDirtyHistory(std::shared_ptr<RSDisplayRenderNode> & node,int32_t bufferAge,bool useAlignedDirtyRegion)48 void RSUniRenderUtil::MergeDirtyHistory(std::shared_ptr<RSDisplayRenderNode>& node, int32_t bufferAge,
49 bool useAlignedDirtyRegion)
50 {
51 // update all child surfacenode history
52 for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
53 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
54 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
55 continue;
56 }
57 auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
58 if (!surfaceDirtyManager->SetBufferAge(bufferAge)) {
59 ROSEN_LOGE("RSUniRenderUtil::MergeVisibleDirtyRegion with invalid buffer age %d", bufferAge);
60 }
61 surfaceDirtyManager->IntersectDirtyRect(surfaceNode->GetOldDirtyInSurface());
62 surfaceDirtyManager->UpdateDirty(useAlignedDirtyRegion);
63 }
64 // update display dirtymanager
65 node->UpdateDisplayDirtyManager(bufferAge, useAlignedDirtyRegion);
66 }
67
MergeVisibleDirtyRegion(std::shared_ptr<RSDisplayRenderNode> & node,bool useAlignedDirtyRegion)68 Occlusion::Region RSUniRenderUtil::MergeVisibleDirtyRegion(std::shared_ptr<RSDisplayRenderNode>& node,
69 bool useAlignedDirtyRegion)
70 {
71 Occlusion::Region allSurfaceVisibleDirtyRegion;
72 for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
73 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
74 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow() || surfaceNode->GetDstRect().IsEmpty()) {
75 continue;
76 }
77 auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
78 auto surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegion();
79 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
80 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
81 auto visibleRegion = surfaceNode->GetVisibleRegion();
82 Occlusion::Region surfaceDirtyRegion { dirtyRect };
83 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
84 surfaceNode->SetVisibleDirtyRegion(surfaceVisibleDirtyRegion);
85 if (useAlignedDirtyRegion) {
86 Occlusion::Region alignedRegion = AlignedDirtyRegion(surfaceVisibleDirtyRegion);
87 surfaceNode->SetAlignedVisibleDirtyRegion(alignedRegion);
88 allSurfaceVisibleDirtyRegion.OrSelf(alignedRegion);
89 } else {
90 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
91 }
92 }
93 return allSurfaceVisibleDirtyRegion;
94 }
95
SrcRectScaleDown(BufferDrawParam & params,const RSSurfaceRenderNode & node)96 void RSUniRenderUtil::SrcRectScaleDown(BufferDrawParam& params, const RSSurfaceRenderNode& node)
97 {
98 ScalingMode scalingMode = ScalingMode::SCALING_MODE_SCALE_TO_WINDOW;
99 const auto& buffer = node.GetBuffer();
100 const auto& surface = node.GetConsumer();
101 if (buffer == nullptr || surface == nullptr) {
102 return;
103 }
104
105 if (surface->GetScalingMode(buffer->GetSeqNum(), scalingMode) == GSERROR_OK &&
106 scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
107 const RSProperties& property = node.GetRenderProperties();
108 #ifndef USE_ROSEN_DRAWING
109 uint32_t newWidth = static_cast<uint32_t>(params.srcRect.width());
110 uint32_t newHeight = static_cast<uint32_t>(params.srcRect.height());
111 #else
112 uint32_t newWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
113 uint32_t newHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
114 #endif
115 // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
116 uint32_t boundsWidth = static_cast<uint32_t>(property.GetBoundsWidth());
117 uint32_t boundsHeight = static_cast<uint32_t>(property.GetBoundsHeight());
118
119 // If transformType is not a multiple of 180, need to change the correspondence between width & height.
120 GraphicTransformType transformType = RSBaseRenderUtil::GetRotateTransform(surface->GetTransform());
121 if (transformType == GraphicTransformType::GRAPHIC_ROTATE_270 ||
122 transformType == GraphicTransformType::GRAPHIC_ROTATE_90) {
123 std::swap(boundsWidth, boundsHeight);
124 }
125
126 if (newWidth * boundsHeight > newHeight * boundsWidth) {
127 // too wide
128 newWidth = boundsWidth * newHeight / boundsHeight;
129 } else if (newWidth * boundsHeight < newHeight * boundsWidth) {
130 // too tall
131 newHeight = boundsHeight * newWidth / boundsWidth;
132 } else {
133 return;
134 }
135
136 #ifndef USE_ROSEN_DRAWING
137 uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.width());
138 uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.height());
139 #else
140 uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
141 uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
142 #endif
143 if (newWidth < currentWidth) {
144 // the crop is too wide
145 uint32_t dw = currentWidth - newWidth;
146 auto halfdw = dw / 2;
147 #ifndef USE_ROSEN_DRAWING
148 params.srcRect = SkRect::MakeXYWH(params.srcRect.left() + static_cast<int32_t>(halfdw),
149 params.srcRect.top(),
150 static_cast<int32_t>(newWidth),
151 params.srcRect.height());
152 #else
153 params.srcRect =
154 Drawing::Rect(params.srcRect.GetLeft() + static_cast<int32_t>(halfdw), params.srcRect.GetTop(),
155 params.srcRect.GetLeft() + static_cast<int32_t>(halfdw) + static_cast<int32_t>(newWidth),
156 params.srcRect.GetTop() + params.srcRect.GetHeight());
157 #endif
158 } else {
159 // thr crop is too tall
160 uint32_t dh = currentHeight - newHeight;
161 auto halfdh = dh / 2;
162 #ifndef USE_ROSEN_DRAWING
163 params.srcRect = SkRect::MakeXYWH(params.srcRect.left(),
164 params.srcRect.top() + static_cast<int32_t>(halfdh),
165 params.srcRect.width(),
166 static_cast<int32_t>(newHeight));
167 #else
168 params.srcRect =
169 Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + static_cast<int32_t>(halfdh),
170 params.srcRect.GetLeft() + params.srcRect.GetWidth(),
171 params.srcRect.GetTop() + static_cast<int32_t>(halfdh) + static_cast<int32_t>(newHeight));
172 #endif
173 }
174 #ifndef USE_ROSEN_DRAWING
175 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleDown surfaceNode id:%" PRIu64 ", srcRect [%f %f %f %f]",
176 node.GetId(), params.srcRect.left(), params.srcRect.top(),
177 params.srcRect.width(), params.srcRect.height());
178 #else
179 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleDown surfaceNode id:%" PRIu64 ", srcRect [%f %f %f %f]",
180 node.GetId(), params.srcRect.GetLeft(), params.srcRect.GetTop(),
181 params.srcRect.GetWidth(), params.srcRect.GetHeight());
182 #endif
183 }
184 }
185
CreateBufferDrawParam(const RSSurfaceRenderNode & node,bool forceCPU,uint32_t threadIndex)186 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSSurfaceRenderNode& node,
187 bool forceCPU, uint32_t threadIndex)
188 {
189 BufferDrawParam params;
190 params.threadIndex = threadIndex;
191 #ifdef RS_ENABLE_EGLIMAGE
192 params.useCPU = forceCPU;
193 #else // RS_ENABLE_EGLIMAGE
194 params.useCPU = true;
195 #endif // RS_ENABLE_EGLIMAGE
196 #ifndef USE_ROSEN_DRAWING
197 params.paint.setAntiAlias(true);
198 #ifndef NEW_SKIA
199 params.paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
200 #endif
201
202 const RSProperties& property = node.GetRenderProperties();
203 params.dstRect = SkRect::MakeWH(property.GetBoundsWidth(), property.GetBoundsHeight());
204 #else
205 params.paint.SetAntiAlias(true);
206 Drawing::Filter filter;
207 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
208 params.paint.SetFilter(filter);
209
210 const RSProperties& property = node.GetRenderProperties();
211 params.dstRect = Drawing::Rect(0, 0, property.GetBoundsWidth(), property.GetBoundsHeight());
212 #endif
213
214 const sptr<SurfaceBuffer>& buffer = node.GetBuffer();
215 if (buffer == nullptr) {
216 return params;
217 }
218 params.buffer = buffer;
219 params.acquireFence = node.GetAcquireFence();
220 #ifndef USE_ROSEN_DRAWING
221 params.srcRect = SkRect::MakeWH(buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
222 #else
223 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
224 #endif
225
226 auto& consumer = node.GetConsumer();
227 if (consumer == nullptr) {
228 return params;
229 }
230 auto transform = consumer->GetTransform();
231 RectF localBounds = { 0.0f, 0.0f, property.GetBoundsWidth(), property.GetBoundsHeight() };
232 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, property.GetFrameGravity(), localBounds, params);
233 RSBaseRenderUtil::FlipMatrix(transform, params);
234 SrcRectScaleDown(params, node);
235 return params;
236 }
237
CreateBufferDrawParam(const RSDisplayRenderNode & node,bool forceCPU)238 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSDisplayRenderNode& node, bool forceCPU)
239 {
240 BufferDrawParam params;
241 #ifdef RS_ENABLE_EGLIMAGE
242 params.useCPU = forceCPU;
243 #else // RS_ENABLE_EGLIMAGE
244 params.useCPU = true;
245 #endif // RS_ENABLE_EGLIMAGE
246 #ifndef USE_ROSEN_DRAWING
247 params.paint.setAntiAlias(true);
248 #ifndef NEW_SKIA
249 params.paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
250 #endif
251
252 const sptr<SurfaceBuffer>& buffer = node.GetBuffer();
253 params.buffer = buffer;
254 params.acquireFence = node.GetAcquireFence();
255 params.srcRect = SkRect::MakeWH(buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
256 params.dstRect = SkRect::MakeWH(buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
257 #else
258 params.paint.SetAntiAlias(true);
259 Drawing::Filter filter;
260 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
261 params.paint.SetFilter(filter);
262
263 const sptr<SurfaceBuffer>& buffer = node.GetBuffer();
264 params.buffer = buffer;
265 params.acquireFence = node.GetAcquireFence();
266 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
267 params.dstRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
268 #endif
269 return params;
270 }
271
CreateLayerBufferDrawParam(const LayerInfoPtr & layer,bool forceCPU)272 BufferDrawParam RSUniRenderUtil::CreateLayerBufferDrawParam(const LayerInfoPtr& layer, bool forceCPU)
273 {
274 BufferDrawParam params;
275 #ifdef RS_ENABLE_EGLIMAGE
276 params.useCPU = forceCPU;
277 #else // RS_ENABLE_EGLIMAGE
278 params.useCPU = true;
279 #endif // RS_ENABLE_EGLIMAGE
280 #ifndef USE_ROSEN_DRAWING
281 params.paint.setAntiAlias(true);
282 #ifndef NEW_SKIA
283 params.paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
284 #endif
285 params.paint.setAlphaf(layer->GetAlpha().gAlpha);
286 #else
287 params.paint.SetAntiAlias(true);
288 Drawing::Filter filter;
289 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
290 params.paint.SetFilter(filter);
291 params.paint.SetAlphaF(layer->GetAlpha().gAlpha);
292 #endif
293
294 sptr<SurfaceBuffer> buffer = layer->GetBuffer();
295 if (buffer == nullptr) {
296 return params;
297 }
298 params.acquireFence = layer->GetAcquireFence();
299 params.buffer = buffer;
300 #ifndef USE_ROSEN_DRAWING
301 params.srcRect = SkRect::MakeWH(buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
302 auto boundRect = layer->GetBoundSize();
303 params.dstRect = SkRect::MakeWH(boundRect.w, boundRect.h);
304
305 auto layerMatrix = layer->GetMatrix();
306 params.matrix = SkMatrix::MakeAll(layerMatrix.scaleX, layerMatrix.skewX, layerMatrix.transX,
307 layerMatrix.skewY, layerMatrix.scaleY, layerMatrix.transY,
308 layerMatrix.pers0, layerMatrix.pers1, layerMatrix.pers2);
309 #else
310 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
311 auto boundRect = layer->GetBoundSize();
312 params.dstRect = Drawing::Rect(0, 0, boundRect.w, boundRect.h);
313
314 auto layerMatrix = layer->GetMatrix();
315 params.matrix = Drawing::Matrix();
316 params.matrix.SetMatrix(layerMatrix.scaleX, layerMatrix.skewX, layerMatrix.transX, layerMatrix.skewY,
317 layerMatrix.scaleY, layerMatrix.transY, layerMatrix.pers0, layerMatrix.pers1, layerMatrix.pers2);
318 #endif
319 int nodeRotation = RSUniRenderUtil::GetRotationFromMatrix(params.matrix); // rotation degree anti-clockwise
320 auto layerTransform = layer->GetTransformType();
321 // calculate clockwise rotation degree excluded rotation in total matrix
322 int realRotation = (nodeRotation +
323 RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(layerTransform))) % 360;
324 auto flip = RSBaseRenderUtil::GetFlipTransform(layerTransform);
325 // calculate transform in anti-clockwise
326 auto transform = RSBaseRenderUtil::RotateEnumToInt(realRotation, flip);
327
328 RectF localBounds = { 0.0f, 0.0f, static_cast<float>(boundRect.w), static_cast<float>(boundRect.h) };
329 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, static_cast<Gravity>(layer->GetGravity()),
330 localBounds, params);
331 RSBaseRenderUtil::FlipMatrix(transform, params);
332 return params;
333 }
334
335 #ifndef USE_ROSEN_DRAWING
DrawCachedImage(RSSurfaceRenderNode & node,RSPaintFilterCanvas & canvas,sk_sp<SkImage> image)336 void RSUniRenderUtil::DrawCachedImage(RSSurfaceRenderNode& node, RSPaintFilterCanvas& canvas, sk_sp<SkImage> image)
337 {
338 if (image == nullptr) {
339 return;
340 }
341 canvas.save();
342 canvas.scale(node.GetRenderProperties().GetBoundsWidth() / image->width(),
343 node.GetRenderProperties().GetBoundsHeight() / image->height());
344 SkPaint paint;
345 #ifdef NEW_SKIA
346 canvas.drawImage(image.get(), 0.0, 0.0, SkSamplingOptions(), &paint);
347 #else
348 canvas.drawImage(image.get(), 0.0, 0.0, &paint);
349 #endif
350 canvas.restore();
351 }
352 #else
DrawCachedImage(RSSurfaceRenderNode & node,RSPaintFilterCanvas & canvas,std::shared_ptr<Drawing::Image> image)353 void RSUniRenderUtil::DrawCachedImage(RSSurfaceRenderNode& node, RSPaintFilterCanvas& canvas,
354 std::shared_ptr<Drawing::Image> image)
355 {
356 if (image == nullptr) {
357 return;
358 }
359 canvas.Save();
360 canvas.Scale(node.GetRenderProperties().GetBoundsWidth() / image->GetWidth(),
361 node.GetRenderProperties().GetBoundsHeight() / image->GetHeight());
362 Drawing::Brush brush;
363 canvas.AttachBrush(brush);
364 Drawing::SamplingOptions sampling =
365 Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NEAREST);
366 canvas.DrawImage(*image.get(), 0.0, 0.0, sampling);
367 canvas.DetachBrush();
368 canvas.Restore();
369 }
370 #endif
371
AlignedDirtyRegion(const Occlusion::Region & dirtyRegion,int32_t alignedBits)372 Occlusion::Region RSUniRenderUtil::AlignedDirtyRegion(const Occlusion::Region& dirtyRegion, int32_t alignedBits)
373 {
374 Occlusion::Region alignedRegion;
375 if (alignedBits <= 1) {
376 return dirtyRegion;
377 }
378 for (const auto& dirtyRect : dirtyRegion.GetRegionRects()) {
379 int32_t left = (dirtyRect.left_ / alignedBits) * alignedBits;
380 int32_t top = (dirtyRect.top_ / alignedBits) * alignedBits;
381 int32_t width = ((dirtyRect.right_ + alignedBits - 1) / alignedBits) * alignedBits - left;
382 int32_t height = ((dirtyRect.bottom_ + alignedBits - 1) / alignedBits) * alignedBits - top;
383 Occlusion::Rect rect = { left, top, left + width, top + height };
384 Occlusion::Region singleAlignedRegion(rect);
385 alignedRegion.OrSelf(singleAlignedRegion);
386 }
387 return alignedRegion;
388 }
389
HandleSubThreadNode(RSRenderNode & node,RSPaintFilterCanvas & canvas)390 bool RSUniRenderUtil::HandleSubThreadNode(RSRenderNode& node, RSPaintFilterCanvas& canvas)
391 {
392 if (node.IsMainThreadNode()) {
393 return false;
394 }
395 if (!node.HasCachedTexture()) {
396 RS_TRACE_NAME_FMT("HandleSubThreadNode wait %" PRIu64 "", node.GetId());
397 #if defined(RS_ENABLE_GL)
398 RSSubThreadManager::Instance()->WaitNodeTask(node.GetId());
399 node.UpdateCompletedCacheSurface();
400 #endif
401 }
402 RS_TRACE_NAME_FMT("RSUniRenderUtil::HandleSubThreadNode %" PRIu64 "", node.GetId());
403 node.DrawCacheSurface(canvas, UNI_MAIN_THREAD_INDEX, true);
404 return true;
405 }
406
HandleCaptureNode(RSRenderNode & node,RSPaintFilterCanvas & canvas)407 bool RSUniRenderUtil::HandleCaptureNode(RSRenderNode& node, RSPaintFilterCanvas& canvas)
408 {
409 auto surfaceNodePtr = node.ReinterpretCastTo<RSSurfaceRenderNode>();
410 if (surfaceNodePtr == nullptr) {
411 return false;
412 }
413 if (surfaceNodePtr->IsAppWindow()) {
414 auto rsParent = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNodePtr->GetParent().lock());
415 auto curNode = surfaceNodePtr;
416 if (rsParent && rsParent->IsLeashWindow()) {
417 curNode = rsParent;
418 }
419 if (!curNode->ShouldPaint()) {
420 return false;
421 }
422 if (curNode->IsOnTheTree()) {
423 return HandleSubThreadNode(*curNode, canvas);
424 } else {
425 #ifdef RS_ENABLE_GL
426 if (curNode->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
427 RSSubThreadManager::Instance()->WaitNodeTask(curNode->GetId());
428 }
429 #endif
430 return false;
431 }
432 }
433 return false;
434 }
435
436 #ifndef USE_ROSEN_DRAWING
GetRotationFromMatrix(SkMatrix matrix)437 int RSUniRenderUtil::GetRotationFromMatrix(SkMatrix matrix)
438 {
439 float value[9];
440 matrix.get9(value);
441
442 int rAngle = static_cast<int>(-round(atan2(value[SkMatrix::kMSkewX], value[SkMatrix::kMScaleX]) * (180 / PI)));
443 // transfer the result to anti-clockwise degrees
444 // only rotation with 90°, 180°, 270° are composed through hardware,
445 // in which situation the transformation of the layer needs to be set.
446 static const std::map<int, int> supportedDegrees = {{90, 270}, {180, 180}, {-90, 90}, {-180, 180}};
447 auto iter = supportedDegrees.find(rAngle);
448 return iter != supportedDegrees.end() ? iter->second : 0;
449 }
450 #else
GetRotationFromMatrix(Drawing::Matrix matrix)451 int RSUniRenderUtil::GetRotationFromMatrix(Drawing::Matrix matrix)
452 {
453 Drawing::Matrix::Buffer value;
454 matrix.GetAll(value);
455
456 int rAngle = static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
457 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
458 // transfer the result to anti-clockwise degrees
459 // only rotation with 90°, 180°, 270° are composed through hardware,
460 // in which situation the transformation of the layer needs to be set.
461 static const std::map<int, int> supportedDegrees = {{90, 270}, {180, 180}, {-90, 90}, {-180, 180}};
462 auto iter = supportedDegrees.find(rAngle);
463 return iter != supportedDegrees.end() ? iter->second : 0;
464 }
465 #endif
466
AssignWindowNodes(const std::shared_ptr<RSDisplayRenderNode> & displayNode,std::list<std::shared_ptr<RSSurfaceRenderNode>> & mainThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes,uint64_t focusNodeId,DeviceType deviceType)467 void RSUniRenderUtil::AssignWindowNodes(const std::shared_ptr<RSDisplayRenderNode>& displayNode,
468 std::list<std::shared_ptr<RSSurfaceRenderNode>>& mainThreadNodes,
469 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes, uint64_t focusNodeId, DeviceType deviceType)
470 {
471 if (displayNode == nullptr) {
472 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes display node is null");
473 return;
474 }
475 bool isRotation = displayNode->IsRotationChanged();
476 bool isScale = false;
477 uint32_t leashWindowCount = 0;
478 bool isFocusNodeFound = false;
479 uint64_t realFocusNodeId = 0;
480 std::string logInfo = "";
481 std::list<RSBaseRenderNode::SharedPtr> curAllSurfaces;
482 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
483 std::vector<RSBaseRenderNode::SharedPtr> curAllSurfacesVec;
484 displayNode->CollectSurface(displayNode, curAllSurfacesVec, true, true);
485 std::copy(curAllSurfacesVec.begin(), curAllSurfacesVec.end(), std::back_inserter(curAllSurfaces));
486 } else {
487 curAllSurfaces = displayNode->GetSortedChildren();
488 }
489 for (auto iter = curAllSurfaces.begin(); iter != curAllSurfaces.end(); iter++) {
490 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*iter);
491 if (node == nullptr) {
492 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes nullptr found in sortedChildren, this should not happen");
493 continue;
494 }
495 if (node->IsLeashWindow()) {
496 leashWindowCount++;
497 }
498 if (node->IsLeashWindow() && node->IsScale()) {
499 isScale = true;
500 }
501 if (deviceType != DeviceType::PHONE) {
502 if (node->GetId() == focusNodeId) {
503 isFocusNodeFound = true;
504 realFocusNodeId = focusNodeId;
505 }
506 if (!isFocusNodeFound && node->IsLeashWindow()) {
507 for (auto& child : node->GetSortedChildren()) {
508 if (child && child->GetId() == focusNodeId) {
509 isFocusNodeFound = true;
510 realFocusNodeId = node->GetId();
511 }
512 }
513 }
514 }
515 }
516 // trace info for assign window nodes
517 if (Rosen::RSSystemProperties::GetDebugTraceEnabled()) {
518 logInfo += "{ isScale: " + std::to_string(isScale) + ", " +
519 "leashWindowCount: " + std::to_string(leashWindowCount) + ", " +
520 "isRotation: " + std::to_string(isRotation) + " }; " +
521 "realFocusNodeId: " + std::to_string(realFocusNodeId) + " ]";
522 }
523 for (auto iter = curAllSurfaces.begin(); iter != curAllSurfaces.end(); iter++) {
524 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*iter);
525 if (node == nullptr) {
526 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes nullptr found in sortedChildren, this should not happen");
527 continue;
528 }
529 // trace info for assign window nodes
530 if (Rosen::RSSystemProperties::GetDebugTraceEnabled()) {
531 logInfo += "node:[ " + node->GetName() + ", " + std::to_string(node->GetId()) + " ]" +
532 "( " + std::to_string(static_cast<uint32_t>(node->GetCacheSurfaceProcessedStatus())) + ", " +
533 std::to_string(node->HasFilter()) + ", " + std::to_string(node->HasAbilityComponent()) + " ); ";
534 }
535 std::string surfaceName = node->GetName();
536 bool needFilter = surfaceName == ENTRY_VIEW || surfaceName == WALLPAPER_VIEW ||
537 surfaceName == SYSUI_STATUS_BAR || surfaceName == SCREENLOCK_WINDOW ||
538 surfaceName == SYSUI_DROPDOWN || surfaceName == PRIVACY_INDICATOR;
539 bool needFilterSCB = surfaceName == SCB_DESK_TOP || surfaceName == SCB_WALL_PAPER ||
540 surfaceName == SCB_SCREEN_LOCK || surfaceName == SCB_DROP_DOWN_PANEL || surfaceName == SCB_STATUS_BAR ||
541 surfaceName == SCB_NEGATIVE_SCREEN || surfaceName == SCB_GESTURE_BACK;
542 if (needFilter || needFilterSCB || node->IsSelfDrawingType()) {
543 AssignMainThreadNode(mainThreadNodes, node);
544 continue;
545 }
546 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) { // node exceed one vsync
547 AssignSubThreadNode(subThreadNodes, node);
548 continue;
549 }
550 if (deviceType == DeviceType::PHONE) {
551 if (isScale) { // app start or close scene
552 if (!node->HasFilter() && !node->HasAbilityComponent() && !isRotation) {
553 AssignSubThreadNode(subThreadNodes, node);
554 } else {
555 AssignMainThreadNode(mainThreadNodes, node);
556 }
557 } else { // other scene
558 AssignMainThreadNode(mainThreadNodes, node);
559 }
560 } else { // PC or TABLET
561 if (node->QuerySubAssignable(isRotation)) {
562 AssignSubThreadNode(subThreadNodes, node);
563 } else {
564 AssignMainThreadNode(mainThreadNodes, node);
565 }
566 }
567 }
568 SortSubThreadNodes(subThreadNodes);
569 RS_OPTIONAL_TRACE_NAME("RSUniRenderUtil::AssignWindowNodes:" + logInfo);
570 }
571
AssignMainThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>> & mainThreadNodes,const std::shared_ptr<RSSurfaceRenderNode> & node)572 void RSUniRenderUtil::AssignMainThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>>& mainThreadNodes,
573 const std::shared_ptr<RSSurfaceRenderNode>& node)
574 {
575 if (node == nullptr) {
576 ROSEN_LOGW("RSUniRenderUtil::AssignMainThreadNode node is nullptr");
577 return;
578 }
579 mainThreadNodes.emplace_back(node);
580 bool changeThread = !node->IsMainThreadNode();
581 node->SetIsMainThreadNode(true);
582 node->SetCacheType(CacheType::NONE);
583 HandleHardwareNode(node);
584 if (changeThread) {
585 RS_LOGD("RSUniRenderUtil::AssignMainThreadNode clear cache surface:[%s, %llu]",
586 node->GetName().c_str(), node->GetId());
587 ClearCacheSurface(node, UNI_MAIN_THREAD_INDEX);
588 node->SetTextureValidFlag(false);
589 }
590 }
591
AssignSubThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes,const std::shared_ptr<RSSurfaceRenderNode> & node,DeviceType deviceType)592 void RSUniRenderUtil::AssignSubThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes,
593 const std::shared_ptr<RSSurfaceRenderNode>& node, DeviceType deviceType)
594 {
595 if (node == nullptr) {
596 ROSEN_LOGW("RSUniRenderUtil::AssignSubThreadNode node is nullptr");
597 return;
598 }
599 if (deviceType == DeviceType::PC || deviceType == DeviceType::TABLET) {
600 node->SetCacheType(CacheType::ANIMATE_PROPERTY);
601 } else {
602 node->SetCacheType(CacheType::CONTENT);
603 }
604 node->SetIsMainThreadNode(false);
605
606 // skip complete static window, DO NOT assign it to subthread.
607 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DONE &&
608 node->IsCurrentFrameStatic() && node->HasCachedTexture()) {
609 RS_TRACE_NAME_FMT("subThreadNodes : static skip %s", node->GetName().c_str());
610 } else {
611 subThreadNodes.emplace_back(node);
612 node->UpdateCacheSurfaceDirtyManager(2); // 2 means buffer age
613 }
614
615 #if defined(RS_ENABLE_GL)
616 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DONE &&
617 node->GetCacheSurface(UNI_MAIN_THREAD_INDEX, false) && node->GetCacheSurfaceNeedUpdated()) {
618 node->UpdateCompletedCacheSurface();
619 for (auto& child : node->GetSortedChildren()) {
620 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
621 if (surfaceNode && surfaceNode->IsAppWindow()) {
622 surfaceNode->GetDirtyManager()->MergeDirtyRect(surfaceNode->GetOldDirty());
623 }
624 }
625 node->SetCacheSurfaceNeedUpdated(false);
626 }
627 #endif
628 if (node->HasCachedTexture()) {
629 node->SetPriority(NodePriorityType::SUB_LOW_PRIORITY);
630 } else {
631 node->SetPriority(NodePriorityType::SUB_HIGH_PRIORITY);
632 }
633 }
634
SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)635 void RSUniRenderUtil::SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
636 {
637 // sort subThreadNodes by priority and z-order
638 subThreadNodes.sort([](const auto& first, const auto& second) -> bool {
639 auto node1 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(first);
640 auto node2 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(second);
641 if (node1 == nullptr || node2 == nullptr) {
642 ROSEN_LOGE(
643 "RSUniRenderUtil::SortSubThreadNodes sort nullptr found in subThreadNodes, this should not happen");
644 return false;
645 }
646 if (node1->GetPriority() == node2->GetPriority()) {
647 return node2->GetRenderProperties().GetPositionZ() < node1->GetRenderProperties().GetPositionZ();
648 } else {
649 return node1->GetPriority() < node2->GetPriority();
650 }
651 });
652 }
653
CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & oldSubThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)654 void RSUniRenderUtil::CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& oldSubThreadNodes,
655 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
656 {
657 std::unordered_set<std::shared_ptr<RSSurfaceRenderNode>> nodes(subThreadNodes.begin(), subThreadNodes.end());
658 for (auto node : oldSubThreadNodes) {
659 if (nodes.count(node) > 0) {
660 continue;
661 }
662 // The node being processed by sub thread may have been removed.
663 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
664 subThreadNodes.emplace_back(node);
665 }
666 }
667 oldSubThreadNodes.clear();
668 oldSubThreadNodes = subThreadNodes;
669 }
670
HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode> & node)671 void RSUniRenderUtil::HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode>& node)
672 {
673 if (!node->HasHardwareNode()) {
674 return;
675 }
676 auto appWindow = node;
677 if (node->IsLeashWindow()) {
678 for (auto& child : node->GetSortedChildren()) {
679 auto surfaceNodePtr = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
680 if (surfaceNodePtr && surfaceNodePtr->IsAppWindow()) {
681 appWindow = surfaceNodePtr;
682 break;
683 }
684 }
685 }
686 auto hardwareEnabledNodes = appWindow->GetChildHardwareEnabledNodes();
687 for (auto& hardwareEnabledNode : hardwareEnabledNodes) {
688 auto hardwareEnabledNodePtr = hardwareEnabledNode.lock();
689 if (hardwareEnabledNodePtr) {
690 hardwareEnabledNodePtr->SetHardwareDisabledByCache(false);
691 }
692 }
693 }
694
ClearSurfaceIfNeed(const RSRenderNodeMap & map,const std::shared_ptr<RSDisplayRenderNode> & displayNode,std::set<std::shared_ptr<RSBaseRenderNode>> & oldChildren)695 void RSUniRenderUtil::ClearSurfaceIfNeed(const RSRenderNodeMap& map,
696 const std::shared_ptr<RSDisplayRenderNode>& displayNode,
697 std::set<std::shared_ptr<RSBaseRenderNode>>& oldChildren)
698 {
699 if (displayNode == nullptr) {
700 return;
701 }
702 std::list<RSBaseRenderNode::SharedPtr> curAllSurfaces;
703 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
704 std::vector<RSBaseRenderNode::SharedPtr> curAllSurfacesVec;
705 displayNode->CollectSurface(displayNode, curAllSurfacesVec, true, true);
706 std::copy(curAllSurfacesVec.begin(), curAllSurfacesVec.end(), std::back_inserter(curAllSurfaces));
707 } else {
708 curAllSurfaces = displayNode->GetSortedChildren();
709 }
710 std::set<std::shared_ptr<RSBaseRenderNode>> tmpSet(curAllSurfaces.begin(), curAllSurfaces.end());
711 for (auto& child : oldChildren) {
712 auto surface = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
713 if (tmpSet.count(surface) == 0) {
714 if (surface && map.GetRenderNode(surface->GetId()) != nullptr) {
715 RS_LOGD("RSUniRenderUtil::ClearSurfaceIfNeed clear cache surface:[%s, %llu]",
716 surface->GetName().c_str(), surface->GetId());
717 ClearCacheSurface(surface, UNI_MAIN_THREAD_INDEX);
718 surface->SetTextureValidFlag(false);
719 }
720 }
721 }
722 oldChildren.swap(tmpSet);
723 }
724
725 // for ui first
ClearCacheSurface(const std::shared_ptr<RSSurfaceRenderNode> & node,uint32_t threadIndex)726 void RSUniRenderUtil::ClearCacheSurface(const std::shared_ptr<RSSurfaceRenderNode>& node, uint32_t threadIndex)
727 {
728 RS_LOGD("ClearCacheSurface node in correct thread: [%llu]", node->GetId());
729 uint32_t cacheSurfaceThreadIndex = node->GetCacheSurfaceThreadIndex();
730 if (cacheSurfaceThreadIndex == threadIndex) {
731 node->ClearCacheSurface();
732 node->SetIsMainThreadNode(true);
733 return;
734 }
735 if (cacheSurfaceThreadIndex == UNI_MAIN_THREAD_INDEX) {
736 RSMainThread::Instance()->PostTask([node]() {
737 RS_LOGD("clear node cache surface in main thread");
738 node->ClearCacheSurface();
739 node->SetIsMainThreadNode(true);
740 });
741 } else {
742 #ifdef RS_ENABLE_GL
743 RSSubThreadManager::Instance()->PostTask([node]() {
744 RS_LOGD("clear node cache surface in sub thread");
745 node->ClearCacheSurface();
746 node->SetIsMainThreadNode(true);
747 }, cacheSurfaceThreadIndex);
748 #endif
749 }
750 }
751
ClearCacheSurface(RSRenderNode & node,uint32_t threadIndex)752 void RSUniRenderUtil::ClearCacheSurface(RSRenderNode& node, uint32_t threadIndex)
753 {
754 RS_LOGD("ClearCacheSurface node: [%llu]", node.GetId());
755 uint32_t cacheSurfaceThreadIndex = node.GetCacheSurfaceThreadIndex();
756 uint32_t completedSurfaceThreadIndex = node.GetCompletedSurfaceThreadIndex();
757 if (cacheSurfaceThreadIndex == threadIndex && completedSurfaceThreadIndex == threadIndex) {
758 node.ClearCacheSurface();
759 return;
760 }
761 auto cacheSurface = node.GetCacheSurface(threadIndex, true);
762 auto cacheCompletedSurface = node.GetCompletedCacheSurface(threadIndex, true);
763 node.ClearCacheSurface();
764 ClearNodeCacheSurface(cacheSurface, cacheCompletedSurface, cacheSurfaceThreadIndex, completedSurfaceThreadIndex);
765 }
766
767 #ifndef USE_ROSEN_DRAWING
ClearNodeCacheSurface(sk_sp<SkSurface> & cacheSurface,sk_sp<SkSurface> & cacheCompletedSurface,uint32_t cacheSurfaceThreadIndex,uint32_t completedSurfaceThreadIndex)768 void RSUniRenderUtil::ClearNodeCacheSurface(sk_sp<SkSurface>& cacheSurface, sk_sp<SkSurface>& cacheCompletedSurface,
769 uint32_t cacheSurfaceThreadIndex, uint32_t completedSurfaceThreadIndex)
770 #else
771 void RSUniRenderUtil::ClearNodeCacheSurface(std::shared_ptr<Drawing::Surface>& cacheSurface,
772 std::shared_ptr<Drawing::Surface>& cacheCompletedSurface,
773 uint32_t cacheSurfaceThreadIndex, uint32_t completedSurfaceThreadIndex)
774 #endif
775 {
776 PostReleaseSurfaceTask(cacheSurface, cacheSurfaceThreadIndex);
777 PostReleaseSurfaceTask(cacheCompletedSurface, completedSurfaceThreadIndex);
778 }
779
780 #ifndef USE_ROSEN_DRAWING
PostReleaseSurfaceTask(sk_sp<SkSurface> & surface,uint32_t threadIndex)781 void RSUniRenderUtil::PostReleaseSurfaceTask(sk_sp<SkSurface>& surface, uint32_t threadIndex)
782 #else
783 void RSUniRenderUtil::PostReleaseSurfaceTask(std::shared_ptr<Drawing::Surface>& surface, uint32_t threadId)
784 #endif
785 {
786 if (surface == nullptr) {
787 return;
788 }
789
790 auto task = [tmpSurface = surface]() mutable {
791 RS_LOGD("clear node cache surface in main thread");
792 tmpSurface = nullptr;
793 };
794 surface = nullptr;
795 if (threadIndex == UNI_MAIN_THREAD_INDEX) {
796 RSMainThread::Instance()->PostTask(task);
797 } else {
798 #ifdef RS_ENABLE_GL
799 RSSubThreadManager::Instance()->PostTask(task, threadIndex);
800 #endif
801 }
802 }
803
FloorTransXYInCanvasMatrix(RSPaintFilterCanvas & canvas)804 void RSUniRenderUtil::FloorTransXYInCanvasMatrix(RSPaintFilterCanvas& canvas)
805 {
806 #ifndef USE_ROSEN_DRAWING
807 auto matrix = canvas.getTotalMatrix();
808 matrix.setTranslateX(std::floor(matrix.getTranslateX()));
809 matrix.setTranslateY(std::floor(matrix.getTranslateY()));
810 canvas.setMatrix(matrix);
811 #else
812 auto matrix = canvas.GetTotalMatrix();
813 matrix.Set(Drawing::Matrix::TRANS_X, std::floor(matrix.Get(Drawing::Matrix::TRANS_X)));
814 matrix.Set(Drawing::Matrix::TRANS_Y, std::floor(matrix.Get(Drawing::Matrix::TRANS_Y)));
815 canvas.SetMatrix(matrix);
816 #endif
817 }
818 } // namespace Rosen
819 } // namespace OHOS
820