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 "common/rs_optional_trace.h"
21 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
22 #include "pipeline/rs_main_thread.h"
23 #include "pipeline/rs_base_render_util.h"
24 #include "platform/common/rs_log.h"
25 #include "property/rs_properties.h"
26 #include "render/rs_material_filter.h"
27 #include "render/rs_path.h"
28 #include "rs_trace.h"
29 #include "common/rs_optional_trace.h"
30 #include "scene_board_judgement.h"
31 #include <parameter.h>
32 #include <parameters.h>
33
34 namespace OHOS {
35 namespace Rosen {
MergeDirtyHistory(std::shared_ptr<RSDisplayRenderNode> & node,int32_t bufferAge,bool useAlignedDirtyRegion)36 void RSUniRenderUtil::MergeDirtyHistory(std::shared_ptr<RSDisplayRenderNode>& node, int32_t bufferAge,
37 bool useAlignedDirtyRegion)
38 {
39 // update all child surfacenode history
40 for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
41 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
42 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
43 continue;
44 }
45 auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
46 if (!surfaceDirtyManager->SetBufferAge(bufferAge)) {
47 ROSEN_LOGE("RSUniRenderUtil::MergeDirtyHistory with invalid buffer age %{public}d", bufferAge);
48 }
49 surfaceDirtyManager->IntersectDirtyRect(surfaceNode->GetOldDirtyInSurface());
50 surfaceDirtyManager->UpdateDirty(useAlignedDirtyRegion);
51 }
52 // update display dirtymanager
53 node->UpdateDisplayDirtyManager(bufferAge, useAlignedDirtyRegion);
54 }
55
MergeVisibleDirtyRegion(std::shared_ptr<RSDisplayRenderNode> & node,std::vector<NodeId> & hasVisibleDirtyRegionSurfaceVec,bool useAlignedDirtyRegion)56 Occlusion::Region RSUniRenderUtil::MergeVisibleDirtyRegion(std::shared_ptr<RSDisplayRenderNode>& node,
57 std::vector<NodeId>& hasVisibleDirtyRegionSurfaceVec, bool useAlignedDirtyRegion)
58 {
59 Occlusion::Region allSurfaceVisibleDirtyRegion;
60 for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
61 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
62 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow() || surfaceNode->GetDstRect().IsEmpty()) {
63 continue;
64 }
65 auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
66 auto surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegion();
67 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
68 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
69 auto visibleRegion = surfaceNode->GetVisibleRegion();
70 Occlusion::Region surfaceDirtyRegion { dirtyRect };
71 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
72 surfaceNode->SetVisibleDirtyRegion(surfaceVisibleDirtyRegion);
73 if (!surfaceVisibleDirtyRegion.IsEmpty()) {
74 hasVisibleDirtyRegionSurfaceVec.emplace_back(surfaceNode->GetId());
75 }
76 if (useAlignedDirtyRegion) {
77 Occlusion::Region alignedRegion = AlignedDirtyRegion(surfaceVisibleDirtyRegion);
78 surfaceNode->SetAlignedVisibleDirtyRegion(alignedRegion);
79 allSurfaceVisibleDirtyRegion.OrSelf(alignedRegion);
80 } else {
81 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
82 }
83 }
84 return allSurfaceVisibleDirtyRegion;
85 }
86
SrcRectScaleDown(BufferDrawParam & params,const RSSurfaceRenderNode & node)87 void RSUniRenderUtil::SrcRectScaleDown(BufferDrawParam& params, const RSSurfaceRenderNode& node)
88 {
89 ScalingMode scalingMode = ScalingMode::SCALING_MODE_SCALE_TO_WINDOW;
90 const auto& buffer = node.GetBuffer();
91 const auto& surface = node.GetConsumer();
92 if (buffer == nullptr || surface == nullptr) {
93 return;
94 }
95
96 if (surface->GetScalingMode(buffer->GetSeqNum(), scalingMode) == GSERROR_OK &&
97 scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
98 const RSProperties& property = node.GetRenderProperties();
99 #ifndef USE_ROSEN_DRAWING
100 uint32_t newWidth = static_cast<uint32_t>(params.srcRect.width());
101 uint32_t newHeight = static_cast<uint32_t>(params.srcRect.height());
102 #else
103 uint32_t newWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
104 uint32_t newHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
105 #endif
106 // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
107 uint32_t boundsWidth = static_cast<uint32_t>(property.GetBoundsWidth());
108 uint32_t boundsHeight = static_cast<uint32_t>(property.GetBoundsHeight());
109
110 // If transformType is not a multiple of 180, need to change the correspondence between width & height.
111 GraphicTransformType transformType = RSBaseRenderUtil::GetRotateTransform(surface->GetTransform());
112 if (transformType == GraphicTransformType::GRAPHIC_ROTATE_270 ||
113 transformType == GraphicTransformType::GRAPHIC_ROTATE_90) {
114 std::swap(boundsWidth, boundsHeight);
115 }
116
117 if (newWidth * boundsHeight > newHeight * boundsWidth) {
118 // too wide
119 if (boundsHeight == 0) {
120 return;
121 }
122 newWidth = boundsWidth * newHeight / boundsHeight;
123 } else if (newWidth * boundsHeight < newHeight * boundsWidth) {
124 // too tall
125 if (boundsWidth == 0) {
126 return;
127 }
128 newHeight = boundsHeight * newWidth / boundsWidth;
129 } else {
130 return;
131 }
132
133 #ifndef USE_ROSEN_DRAWING
134 uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.width());
135 uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.height());
136 #else
137 uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
138 uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
139 #endif
140 if (newWidth < currentWidth) {
141 // the crop is too wide
142 uint32_t dw = currentWidth - newWidth;
143 auto halfdw = dw / 2;
144 #ifndef USE_ROSEN_DRAWING
145 params.srcRect = SkRect::MakeXYWH(params.srcRect.left() + static_cast<int32_t>(halfdw),
146 params.srcRect.top(),
147 static_cast<int32_t>(newWidth),
148 params.srcRect.height());
149 #else
150 params.srcRect =
151 Drawing::Rect(params.srcRect.GetLeft() + static_cast<int32_t>(halfdw), params.srcRect.GetTop(),
152 params.srcRect.GetLeft() + static_cast<int32_t>(halfdw) + static_cast<int32_t>(newWidth),
153 params.srcRect.GetTop() + params.srcRect.GetHeight());
154 #endif
155 } else {
156 // thr crop is too tall
157 uint32_t dh = currentHeight - newHeight;
158 auto halfdh = dh / 2;
159 #ifndef USE_ROSEN_DRAWING
160 params.srcRect = SkRect::MakeXYWH(params.srcRect.left(),
161 params.srcRect.top() + static_cast<int32_t>(halfdh),
162 params.srcRect.width(),
163 static_cast<int32_t>(newHeight));
164 #else
165 params.srcRect =
166 Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + static_cast<int32_t>(halfdh),
167 params.srcRect.GetLeft() + params.srcRect.GetWidth(),
168 params.srcRect.GetTop() + static_cast<int32_t>(halfdh) + static_cast<int32_t>(newHeight));
169 #endif
170 }
171 #ifndef USE_ROSEN_DRAWING
172 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleDown surfaceNode id:%{public}" PRIu64 ","
173 " srcRect [%{public}f %{public}f %{public}f %{public}f]",
174 node.GetId(), params.srcRect.left(), params.srcRect.top(),
175 params.srcRect.width(), params.srcRect.height());
176 #else
177 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleDown surfaceNode id:%{public}" PRIu64 ","
178 " srcRect [%{public}f %{public}f %{public}f %{public}f]",
179 node.GetId(), params.srcRect.GetLeft(), params.srcRect.GetTop(),
180 params.srcRect.GetWidth(), params.srcRect.GetHeight());
181 #endif
182 }
183 }
184
CreateBufferDrawParam(const RSSurfaceRenderNode & node,bool forceCPU,uint32_t threadIndex)185 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSSurfaceRenderNode& node,
186 bool forceCPU, uint32_t threadIndex)
187 {
188 BufferDrawParam params;
189 params.threadIndex = threadIndex;
190 params.useBilinearInterpolation = node.NeedBilinearInterpolation();
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
IsNeedClient(RSSurfaceRenderNode & node,const ComposeInfo & info)335 bool RSUniRenderUtil::IsNeedClient(RSSurfaceRenderNode& node, const ComposeInfo& info)
336 {
337 if (RSBaseRenderUtil::IsForceClient()) {
338 RS_LOGD("RSUniRenderUtil::IsNeedClient: force client.");
339 return true;
340 }
341 const auto& property = node.GetRenderProperties();
342 if (property.GetRotation() != 0 || property.GetRotationX() != 0 || property.GetRotationY() != 0 ||
343 property.GetQuaternion() != Quaternion()) {
344 RS_LOGD("RSUniRenderUtil::IsNeedClient need client with RSSurfaceRenderNode rotation");
345 return true;
346 }
347 return false;
348 }
349
AlignedDirtyRegion(const Occlusion::Region & dirtyRegion,int32_t alignedBits)350 Occlusion::Region RSUniRenderUtil::AlignedDirtyRegion(const Occlusion::Region& dirtyRegion, int32_t alignedBits)
351 {
352 Occlusion::Region alignedRegion;
353 if (alignedBits <= 1) {
354 return dirtyRegion;
355 }
356 for (const auto& dirtyRect : dirtyRegion.GetRegionRects()) {
357 int32_t left = (dirtyRect.left_ / alignedBits) * alignedBits;
358 int32_t top = (dirtyRect.top_ / alignedBits) * alignedBits;
359 int32_t width = ((dirtyRect.right_ + alignedBits - 1) / alignedBits) * alignedBits - left;
360 int32_t height = ((dirtyRect.bottom_ + alignedBits - 1) / alignedBits) * alignedBits - top;
361 Occlusion::Rect rect = { left, top, left + width, top + height };
362 Occlusion::Region singleAlignedRegion(rect);
363 alignedRegion.OrSelf(singleAlignedRegion);
364 }
365 return alignedRegion;
366 }
367
HandleSubThreadNode(RSSurfaceRenderNode & node,RSPaintFilterCanvas & canvas)368 bool RSUniRenderUtil::HandleSubThreadNode(RSSurfaceRenderNode& node, RSPaintFilterCanvas& canvas)
369 {
370 if (node.IsMainThreadNode()) {
371 return false;
372 } else if (RSMainThread::Instance()->GetDeviceType() == DeviceType::PC &&
373 !node.QueryIfAllHwcChildrenForceDisabledByFilter()) {
374 return false; // this node should do DSS composition in mainThread although it is assigned to subThread
375 }
376 if (!node.HasCachedTexture()) {
377 RS_TRACE_NAME_FMT("HandleSubThreadNode wait %" PRIu64 "", node.GetId());
378 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
379 RSSubThreadManager::Instance()->WaitNodeTask(node.GetId());
380 node.UpdateCompletedCacheSurface();
381 #endif
382 }
383 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::HandleSubThreadNode %" PRIu64 "", node.GetId());
384 node.DrawCacheSurface(canvas, UNI_MAIN_THREAD_INDEX, true);
385 return true;
386 }
387
HandleCaptureNode(RSRenderNode & node,RSPaintFilterCanvas & canvas)388 bool RSUniRenderUtil::HandleCaptureNode(RSRenderNode& node, RSPaintFilterCanvas& canvas)
389 {
390 auto surfaceNodePtr = node.ReinterpretCastTo<RSSurfaceRenderNode>();
391 if (surfaceNodePtr == nullptr) {
392 return false;
393 }
394 if (surfaceNodePtr->IsAppWindow()) {
395 auto rsParent = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNodePtr->GetParent().lock());
396 auto curNode = surfaceNodePtr;
397 if (rsParent && rsParent->IsLeashWindow()) {
398 curNode = rsParent;
399 }
400 if (!curNode->ShouldPaint()) {
401 return false;
402 }
403 if (curNode->IsOnTheTree()) {
404 return HandleSubThreadNode(*curNode, canvas);
405 } else {
406 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
407 if (curNode->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
408 RSSubThreadManager::Instance()->WaitNodeTask(curNode->GetId());
409 }
410 #endif
411 return false;
412 }
413 }
414 return false;
415 }
416
417 #ifndef USE_ROSEN_DRAWING
GetRotationFromMatrix(SkMatrix matrix)418 int RSUniRenderUtil::GetRotationFromMatrix(SkMatrix matrix)
419 {
420 float value[9];
421 matrix.get9(value);
422
423 int rAngle = static_cast<int>(-round(atan2(value[SkMatrix::kMSkewX], value[SkMatrix::kMScaleX]) * (180 / PI)));
424 // transfer the result to anti-clockwise degrees
425 // only rotation with 90°, 180°, 270° are composed through hardware,
426 // in which situation the transformation of the layer needs to be set.
427 static const std::map<int, int> supportedDegrees = {{90, 270}, {180, 180}, {-90, 90}, {-180, 180}};
428 auto iter = supportedDegrees.find(rAngle);
429 return iter != supportedDegrees.end() ? iter->second : 0;
430 }
431
GetRotationDegreeFromMatrix(SkMatrix matrix)432 int RSUniRenderUtil::GetRotationDegreeFromMatrix(SkMatrix matrix)
433 {
434 float value[9];
435 matrix.get9(value);
436 return static_cast<int>(-round(atan2(value[SkMatrix::kMSkewX], value[SkMatrix::kMScaleX]) * (180 / PI)));
437 }
438
Is3DRotation(SkMatrix matrix)439 bool RSUniRenderUtil::Is3DRotation(SkMatrix matrix)
440 {
441 return !ROSEN_EQ(matrix.getSkewX(), 0.f) || matrix.getScaleX() < 0 ||
442 !ROSEN_EQ(matrix.getSkewY(), 0.f) || matrix.getScaleY() < 0;
443 }
444
445 #else
GetRotationFromMatrix(Drawing::Matrix matrix)446 int RSUniRenderUtil::GetRotationFromMatrix(Drawing::Matrix matrix)
447 {
448 Drawing::Matrix::Buffer value;
449 matrix.GetAll(value);
450
451 int rAngle = static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
452 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
453 // transfer the result to anti-clockwise degrees
454 // only rotation with 90°, 180°, 270° are composed through hardware,
455 // in which situation the transformation of the layer needs to be set.
456 static const std::map<int, int> supportedDegrees = {{90, 270}, {180, 180}, {-90, 90}, {-180, 180}};
457 auto iter = supportedDegrees.find(rAngle);
458 return iter != supportedDegrees.end() ? iter->second : 0;
459 }
460
GetRotationDegreeFromMatrix(Drawing::Matrix matrix)461 int RSUniRenderUtil::GetRotationDegreeFromMatrix(Drawing::Matrix matrix)
462 {
463 Drawing::Matrix::Buffer value;
464 matrix.GetAll(value);
465 return static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
466 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
467 }
468
Is3DRotation(Drawing::Matrix matrix)469 bool RSUniRenderUtil::Is3DRotation(Drawing::Matrix matrix)
470 {
471 return !ROSEN_EQ(matrix.Get(Drawing::Matrix::Index::SKEW_X), 0.f) ||
472 matrix.Get(Drawing::Matrix::Index::SCALE_X) < 0 ||
473 !ROSEN_EQ(matrix.Get(Drawing::Matrix::Index::SKEW_Y), 0.f) ||
474 matrix.Get(Drawing::Matrix::Index::SCALE_Y) < 0;
475 }
476
477 #endif
478
ReleaseColorPickerFilter(std::shared_ptr<RSFilter> RSFilter)479 void RSUniRenderUtil::ReleaseColorPickerFilter(std::shared_ptr<RSFilter> RSFilter)
480 {
481 auto materialFilter = std::static_pointer_cast<RSMaterialFilter>(RSFilter);
482 if (materialFilter->GetColorPickerCacheTask() == nullptr) {
483 return;
484 }
485 materialFilter->ReleaseColorPickerFilter();
486 }
487
ReleaseColorPickerResource(std::shared_ptr<RSRenderNode> & node)488 void RSUniRenderUtil::ReleaseColorPickerResource(std::shared_ptr<RSRenderNode>& node)
489 {
490 if (node == nullptr) {
491 return;
492 }
493 auto& properties = node->GetRenderProperties();
494 if (properties.GetColorPickerCacheTaskShadow() != nullptr) {
495 properties.ReleaseColorPickerTaskShadow();
496 }
497 if ((properties.GetFilter() != nullptr &&
498 properties.GetFilter()->GetFilterType() == RSFilter::MATERIAL)) {
499 ReleaseColorPickerFilter(properties.GetFilter());
500 }
501 if (properties.GetBackgroundFilter() != nullptr &&
502 properties.GetBackgroundFilter()->GetFilterType() == RSFilter::MATERIAL) {
503 ReleaseColorPickerFilter(properties.GetBackgroundFilter());
504 }
505 // Recursive to release color picker resource
506 for (auto& child : *node->GetChildren()) {
507 if (auto canvasChild = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(child)) {
508 ReleaseColorPickerResource(canvasChild);
509 }
510 }
511 }
512
IsNodeAssignSubThread(std::shared_ptr<RSSurfaceRenderNode> node,bool isDisplayRotation)513 bool RSUniRenderUtil::IsNodeAssignSubThread(std::shared_ptr<RSSurfaceRenderNode> node, bool isDisplayRotation)
514 {
515 bool isPhoneType = RSMainThread::Instance()->GetDeviceType() == DeviceType::PHONE;
516 bool isNeedAssignToSubThread = false;
517 if (isPhoneType && node->IsLeashWindow()) {
518 isNeedAssignToSubThread = (node->IsScale() || ROSEN_EQ(node->GetGlobalAlpha(), 0.0f) ||
519 node->GetForceUIFirst()) && !node->HasFilter();
520 RS_TRACE_NAME_FMT("Assign info: name[%s] id[%lu]"
521 " status:%d filter:%d isScale:%d forceUIFirst:%d isNeedAssign:%d",
522 node->GetName().c_str(), node->GetId(), node->GetCacheSurfaceProcessedStatus(),
523 node->HasFilter(), node->IsScale(), node->GetForceUIFirst(), isNeedAssignToSubThread);
524 }
525 std::string surfaceName = node->GetName();
526 bool needFilterSCB = surfaceName.substr(0, 3) == "SCB" ||
527 surfaceName.substr(0, 13) == "BlurComponent"; // filter BlurComponent, 13 is string len
528 if (needFilterSCB || node->IsSelfDrawingType()) {
529 return false;
530 }
531 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) { // node exceed one vsync
532 return true;
533 }
534 if (isPhoneType) {
535 return isNeedAssignToSubThread;
536 } else { // PC or TABLET
537 if ((node->IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
538 node->IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId())) &&
539 node->GetHasSharedTransitionNode()) {
540 return false;
541 }
542 return node->QuerySubAssignable(isDisplayRotation);
543 }
544 }
545
AssignWindowNodes(const std::shared_ptr<RSDisplayRenderNode> & displayNode,std::list<std::shared_ptr<RSSurfaceRenderNode>> & mainThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)546 void RSUniRenderUtil::AssignWindowNodes(const std::shared_ptr<RSDisplayRenderNode>& displayNode,
547 std::list<std::shared_ptr<RSSurfaceRenderNode>>& mainThreadNodes,
548 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
549 {
550 if (displayNode == nullptr) {
551 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes display node is null");
552 return;
553 }
554 bool isRotation = displayNode->IsRotationChanged();
555 std::vector<RSBaseRenderNode::SharedPtr> curAllSurfaces;
556 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
557 displayNode->CollectSurface(displayNode, curAllSurfaces, true, true);
558 } else {
559 curAllSurfaces = *displayNode->GetSortedChildren();
560 }
561 for (auto iter = curAllSurfaces.begin(); iter != curAllSurfaces.end(); iter++) {
562 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*iter);
563 if (node == nullptr) {
564 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes nullptr found in sortedChildren, this should not happen");
565 continue;
566 }
567
568 // release color picker resource when thread-switching between RS and subthread
569 bool lastIsNeedAssignToSubThread = node->GetLastIsNeedAssignToSubThread();
570 bool isNodeAssignSubThread = IsNodeAssignSubThread(node, isRotation);
571 if (isNodeAssignSubThread != lastIsNeedAssignToSubThread) {
572 auto renderNode = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(node);
573 ReleaseColorPickerResource(renderNode);
574 node->SetLastIsNeedAssignToSubThread(isNodeAssignSubThread);
575 }
576 if (isNodeAssignSubThread) {
577 AssignSubThreadNode(subThreadNodes, node);
578 } else {
579 AssignMainThreadNode(mainThreadNodes, node);
580 }
581 }
582 SortSubThreadNodes(subThreadNodes);
583 }
584
AssignMainThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>> & mainThreadNodes,const std::shared_ptr<RSSurfaceRenderNode> & node)585 void RSUniRenderUtil::AssignMainThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>>& mainThreadNodes,
586 const std::shared_ptr<RSSurfaceRenderNode>& node)
587 {
588 if (node == nullptr) {
589 ROSEN_LOGW("RSUniRenderUtil::AssignMainThreadNode node is nullptr");
590 return;
591 }
592 mainThreadNodes.emplace_back(node);
593 bool changeThread = !node->IsMainThreadNode();
594 node->SetIsMainThreadNode(true);
595 node->SetCacheType(CacheType::NONE);
596 HandleHardwareNode(node);
597 if (changeThread) {
598 RS_LOGD("RSUniRenderUtil::AssignMainThreadNode clear cache surface:[%{public}s, %{public}" PRIu64 "]",
599 node->GetName().c_str(), node->GetId());
600 ClearCacheSurface(*node, UNI_MAIN_THREAD_INDEX);
601 node->SetIsMainThreadNode(true);
602 node->SetTextureValidFlag(false);
603 }
604 if (RSMainThread::Instance()->GetDeviceType() == DeviceType::PC) {
605 RS_TRACE_NAME_FMT("AssignMainThread: name: %s, id: %lu, [HasTransparentSurface: %d, ChildHasFilter: %d,"
606 "HasFilter: %d, HasAbilityComponent: %d, QueryIfAllHwcChildrenForceDisabledByFilter: %d]",
607 node->GetName().c_str(), node->GetId(), node->GetHasTransparentSurface(),
608 node->ChildHasFilter(), node->HasFilter(), node->HasAbilityComponent(),
609 node->QueryIfAllHwcChildrenForceDisabledByFilter());
610 }
611 }
612
AssignSubThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes,const std::shared_ptr<RSSurfaceRenderNode> & node)613 void RSUniRenderUtil::AssignSubThreadNode(
614 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes, const std::shared_ptr<RSSurfaceRenderNode>& node)
615 {
616 if (node == nullptr) {
617 ROSEN_LOGW("RSUniRenderUtil::AssignSubThreadNode node is nullptr");
618 return;
619 }
620 node->SetNeedSubmitSubThread(true);
621 node->SetCacheType(CacheType::CONTENT);
622 node->SetIsMainThreadNode(false);
623 auto deviceType = RSMainThread::Instance()->GetDeviceType();
624 // skip complete static window, DO NOT assign it to subthread.
625 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DONE &&
626 node->HasCachedTexture() && node->IsUIFirstSelfDrawCheck() &&
627 (node->IsCurFrameStatic(deviceType) || node->IsVisibleDirtyEmpty(deviceType))) {
628 node->SetNeedSubmitSubThread(false);
629 RS_OPTIONAL_TRACE_NAME_FMT("subThreadNodes : static skip %s", node->GetName().c_str());
630 } else {
631 node->UpdateCacheSurfaceDirtyManager(2); // 2 means buffer age
632 }
633 node->SetLastFrameChildrenCnt(node->GetChildren()->size());
634 subThreadNodes.emplace_back(node);
635 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
636 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DONE &&
637 node->GetCacheSurface(UNI_MAIN_THREAD_INDEX, false) && node->GetCacheSurfaceNeedUpdated()) {
638 node->UpdateCompletedCacheSurface();
639 if (node->IsAppWindow() &&
640 !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node->GetParent().lock())) {
641 node->GetDirtyManager()->MergeDirtyRect(node->GetOldDirty());
642 } else {
643 for (auto& child : *node->GetSortedChildren()) {
644 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
645 if (surfaceNode && surfaceNode->IsAppWindow()) {
646 surfaceNode->GetDirtyManager()->MergeDirtyRect(surfaceNode->GetOldDirty());
647 break;
648 }
649 }
650 }
651 node->SetCacheSurfaceNeedUpdated(false);
652 }
653 #endif
654 bool isFocus = node->IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
655 (node->IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId()));
656 if ((deviceType == DeviceType::PC || deviceType == DeviceType::TABLET) && isFocus) {
657 node->SetPriority(NodePriorityType::SUB_FOCUSNODE_PRIORITY); // for resolving response latency
658 return;
659 }
660 if (node->HasCachedTexture()) {
661 node->SetPriority(NodePriorityType::SUB_LOW_PRIORITY);
662 } else {
663 node->SetPriority(NodePriorityType::SUB_HIGH_PRIORITY);
664 }
665 }
666
SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)667 void RSUniRenderUtil::SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
668 {
669 // sort subThreadNodes by priority and z-order
670 subThreadNodes.sort([](const auto& first, const auto& second) -> bool {
671 auto node1 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(first);
672 auto node2 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(second);
673 if (node1 == nullptr || node2 == nullptr) {
674 ROSEN_LOGE(
675 "RSUniRenderUtil::SortSubThreadNodes sort nullptr found in subThreadNodes, this should not happen");
676 return false;
677 }
678 if (node1->GetPriority() == node2->GetPriority()) {
679 return node2->GetRenderProperties().GetPositionZ() < node1->GetRenderProperties().GetPositionZ();
680 } else {
681 return node1->GetPriority() < node2->GetPriority();
682 }
683 });
684 }
685
CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & oldSubThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)686 void RSUniRenderUtil::CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& oldSubThreadNodes,
687 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
688 {
689 std::unordered_set<std::shared_ptr<RSSurfaceRenderNode>> nodes(subThreadNodes.begin(), subThreadNodes.end());
690 for (auto node : oldSubThreadNodes) {
691 if (nodes.count(node) > 0) {
692 continue;
693 }
694 // The node being processed by sub thread may have been removed.
695 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
696 subThreadNodes.emplace_back(node);
697 }
698 }
699 oldSubThreadNodes.clear();
700 oldSubThreadNodes = subThreadNodes;
701 }
702
HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode> & node)703 void RSUniRenderUtil::HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode>& node)
704 {
705 if (!node->HasHardwareNode()) {
706 return;
707 }
708 auto appWindow = node;
709 if (node->IsLeashWindow()) {
710 for (auto& child : *node->GetSortedChildren()) {
711 auto surfaceNodePtr = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
712 if (surfaceNodePtr && surfaceNodePtr->IsAppWindow()) {
713 appWindow = surfaceNodePtr;
714 break;
715 }
716 }
717 }
718 auto hardwareEnabledNodes = appWindow->GetChildHardwareEnabledNodes();
719 for (auto& hardwareEnabledNode : hardwareEnabledNodes) {
720 auto hardwareEnabledNodePtr = hardwareEnabledNode.lock();
721 if (hardwareEnabledNodePtr) {
722 hardwareEnabledNodePtr->SetHardwareDisabledByCache(false);
723 }
724 }
725 }
726
ClearSurfaceIfNeed(const RSRenderNodeMap & map,const std::shared_ptr<RSDisplayRenderNode> & displayNode,std::set<std::shared_ptr<RSBaseRenderNode>> & oldChildren,DeviceType deviceType)727 void RSUniRenderUtil::ClearSurfaceIfNeed(const RSRenderNodeMap& map,
728 const std::shared_ptr<RSDisplayRenderNode>& displayNode,
729 std::set<std::shared_ptr<RSBaseRenderNode>>& oldChildren,
730 DeviceType deviceType)
731 {
732 if (displayNode == nullptr) {
733 return;
734 }
735 std::vector<RSBaseRenderNode::SharedPtr> curAllSurfaces;
736 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
737 displayNode->CollectSurface(displayNode, curAllSurfaces, true, true);
738 } else {
739 curAllSurfaces = *displayNode->GetSortedChildren();
740 }
741 std::set<std::shared_ptr<RSBaseRenderNode>> tmpSet(curAllSurfaces.begin(), curAllSurfaces.end());
742 for (auto& child : oldChildren) {
743 auto surface = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
744 if (tmpSet.count(surface) == 0) {
745 if (surface && surface->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
746 tmpSet.emplace(surface);
747 continue;
748 }
749 if (surface && map.GetRenderNode(surface->GetId()) != nullptr) {
750 RS_LOGD("RSUniRenderUtil::ClearSurfaceIfNeed clear cache surface:[%{public}s, %{public}" PRIu64 "]",
751 surface->GetName().c_str(), surface->GetId());
752 if (deviceType == DeviceType::PHONE) {
753 ClearCacheSurface(*surface, UNI_MAIN_THREAD_INDEX);
754 surface->SetIsMainThreadNode(true);
755 surface->SetTextureValidFlag(false);
756 } else {
757 if (RSMainThread::Instance()->IsPCThreeFingerScenesListScene()) {
758 ClearCacheSurface(*surface, UNI_MAIN_THREAD_INDEX, false);
759 } else {
760 ClearCacheSurface(*surface, UNI_MAIN_THREAD_INDEX);
761 }
762 }
763 }
764 }
765 }
766 oldChildren.swap(tmpSet);
767 }
768
ClearCacheSurface(RSRenderNode & node,uint32_t threadIndex,bool isClearCompletedCacheSurface)769 void RSUniRenderUtil::ClearCacheSurface(RSRenderNode& node, uint32_t threadIndex, bool isClearCompletedCacheSurface)
770 {
771 RS_LOGD("ClearCacheSurface node: [%{public}" PRIu64 "]", node.GetId());
772 uint32_t cacheSurfaceThreadIndex = node.GetCacheSurfaceThreadIndex();
773 uint32_t completedSurfaceThreadIndex = node.GetCompletedSurfaceThreadIndex();
774 if (cacheSurfaceThreadIndex == threadIndex && completedSurfaceThreadIndex == threadIndex) {
775 node.ClearCacheSurface(isClearCompletedCacheSurface);
776 return;
777 }
778 #ifndef USE_ROSEN_DRAWING
779 sk_sp<SkSurface> completedCacheSurface = isClearCompletedCacheSurface ?
780 node.GetCompletedCacheSurface(threadIndex, false, true) : nullptr;
781 #else
782 std::shared_ptr<Drawing::Surface> completedCacheSurface = isClearCompletedCacheSurface ?
783 node.GetCompletedCacheSurface(threadIndex, false, true) : nullptr;
784 #endif
785 ClearNodeCacheSurface(node.GetCacheSurface(threadIndex, false, true),
786 std::move(completedCacheSurface), cacheSurfaceThreadIndex, completedSurfaceThreadIndex);
787 node.ClearCacheSurface(isClearCompletedCacheSurface);
788 }
789
790 #ifndef USE_ROSEN_DRAWING
ClearNodeCacheSurface(sk_sp<SkSurface> && cacheSurface,sk_sp<SkSurface> && cacheCompletedSurface,uint32_t cacheSurfaceThreadIndex,uint32_t completedSurfaceThreadIndex)791 void RSUniRenderUtil::ClearNodeCacheSurface(sk_sp<SkSurface>&& cacheSurface, sk_sp<SkSurface>&& cacheCompletedSurface,
792 uint32_t cacheSurfaceThreadIndex, uint32_t completedSurfaceThreadIndex)
793 #else
794 void RSUniRenderUtil::ClearNodeCacheSurface(std::shared_ptr<Drawing::Surface>&& cacheSurface,
795 std::shared_ptr<Drawing::Surface>&& cacheCompletedSurface,
796 uint32_t cacheSurfaceThreadIndex, uint32_t completedSurfaceThreadIndex)
797 #endif
798 {
799 PostReleaseSurfaceTask(std::move(cacheSurface), cacheSurfaceThreadIndex);
800 PostReleaseSurfaceTask(std::move(cacheCompletedSurface), completedSurfaceThreadIndex);
801 }
802
803 #ifndef USE_ROSEN_DRAWING
PostReleaseSurfaceTask(sk_sp<SkSurface> && surface,uint32_t threadIndex)804 void RSUniRenderUtil::PostReleaseSurfaceTask(sk_sp<SkSurface>&& surface, uint32_t threadIndex)
805 #else
806 void RSUniRenderUtil::PostReleaseSurfaceTask(std::shared_ptr<Drawing::Surface>&& surface, uint32_t threadIndex)
807 #endif
808 {
809 if (surface == nullptr) {
810 return;
811 }
812
813 if (threadIndex == UNI_MAIN_THREAD_INDEX) {
814 auto instance = RSMainThread::Instance();
815 instance->AddToReleaseQueue(std::move(surface));
816 instance->PostTask([instance] () {
817 instance->ReleaseSurface();
818 });
819 } else {
820 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
821 auto instance = RSSubThreadManager::Instance();
822 instance->AddToReleaseQueue(std::move(surface), threadIndex);
823 instance->ReleaseSurface(threadIndex);
824 #endif
825 }
826 }
827
FloorTransXYInCanvasMatrix(RSPaintFilterCanvas & canvas)828 void RSUniRenderUtil::FloorTransXYInCanvasMatrix(RSPaintFilterCanvas& canvas)
829 {
830 #ifndef USE_ROSEN_DRAWING
831 auto matrix = canvas.getTotalMatrix();
832 matrix.setTranslateX(std::floor(matrix.getTranslateX()));
833 matrix.setTranslateY(std::floor(matrix.getTranslateY()));
834 canvas.setMatrix(matrix);
835 #else
836 auto matrix = canvas.GetTotalMatrix();
837 matrix.Set(Drawing::Matrix::TRANS_X, std::floor(matrix.Get(Drawing::Matrix::TRANS_X)));
838 matrix.Set(Drawing::Matrix::TRANS_Y, std::floor(matrix.Get(Drawing::Matrix::TRANS_Y)));
839 canvas.SetMatrix(matrix);
840 #endif
841 }
842 } // namespace Rosen
843 } // namespace OHOS
844