• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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