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_composer_adapter.h"
17
18 #include <fstream>
19 #include <sstream>
20 #include <sys/time.h>
21
22 #include "common/rs_common_def.h"
23 #include "common/rs_obj_abs_geometry.h"
24 #include "platform/common/rs_log.h"
25 #include "rs_base_render_util.h"
26 #include "rs_divided_render_util.h"
27 #include "rs_trace.h"
28 #include "string_utils.h"
29
30 #ifdef USE_ROSEN_DRAWING
31 #include "draw/canvas.h"
32 #endif
33
34 namespace OHOS {
35 namespace Rosen {
Init(const ScreenInfo & screenInfo,int32_t offsetX,int32_t offsetY,float mirrorAdaptiveCoefficient,const FallbackCallback & cb)36 bool RSComposerAdapter::Init(const ScreenInfo& screenInfo, int32_t offsetX, int32_t offsetY,
37 float mirrorAdaptiveCoefficient, const FallbackCallback& cb)
38 {
39 hdiBackend_ = HdiBackend::GetInstance();
40 if (hdiBackend_ == nullptr) {
41 RS_LOGE("RSComposerAdapter::Init: hdiBackend is nullptr");
42 return false;
43 }
44 auto screenManager = CreateOrGetScreenManager();
45 if (screenManager == nullptr) {
46 RS_LOGE("RSComposerAdapter::Init: ScreenManager is nullptr");
47 return false;
48 }
49 output_ = screenManager->GetOutput(ToScreenPhysicalId(screenInfo.id));
50 if (output_ == nullptr) {
51 RS_LOGE("RSComposerAdapter::Init: output_ is nullptr");
52 return false;
53 }
54
55 fallbackCb_ = cb;
56 auto onPrepareCompleteFunc = [this](auto& surface, const auto& param, void* data) {
57 OnPrepareComplete(surface, param, data);
58 };
59 hdiBackend_->RegPrepareComplete(onPrepareCompleteFunc, this);
60
61 offsetX_ = offsetX;
62 offsetY_ = offsetY;
63 mirrorAdaptiveCoefficient_ = mirrorAdaptiveCoefficient;
64 screenInfo_ = screenInfo;
65
66 GraphicIRect damageRect {0, 0, static_cast<int32_t>(screenInfo_.width), static_cast<int32_t>(screenInfo_.height)};
67 std::vector<GraphicIRect> damageRects;
68 damageRects.emplace_back(damageRect);
69 output_->SetOutputDamages(damageRects);
70 bool directClientCompEnableStatus = RSSystemProperties::GetDirectClientCompEnableStatus();
71 output_->SetDirectClientCompEnableStatus(directClientCompEnableStatus);
72
73 #if ((defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)) || (defined RS_ENABLE_VK)
74 // enable direct GPU composition.
75 output_->SetLayerCompCapacity(LAYER_COMPOSITION_CAPACITY);
76 #else // (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
77 output_->SetLayerCompCapacity(LAYER_COMPOSITION_CAPACITY_INVALID);
78 #endif // (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
79
80 return true;
81 }
82
CommitLayers(const std::vector<LayerInfoPtr> & layers)83 void RSComposerAdapter::CommitLayers(const std::vector<LayerInfoPtr>& layers)
84 {
85 if (hdiBackend_ == nullptr) {
86 RS_LOGE("RSComposerAdapter::CommitLayers: backend is nullptr");
87 return;
88 }
89
90 if (output_ == nullptr) {
91 RS_LOGE("RSComposerAdapter::CommitLayers: output is nullptr");
92 return;
93 }
94
95 DumpLayersToFile(layers);
96
97 // do composition.
98 output_->SetLayerInfo(layers);
99 hdiBackend_->Repaint(output_);
100
101 // get present timestamp from and set present timestamp to surface
102 for (const auto& layer : layers) {
103 if (layer == nullptr || layer->GetSurface() == nullptr) {
104 RS_LOGW("RSComposerAdapter::CommitLayers: layer or layer's cSurface is nullptr");
105 continue;
106 }
107 LayerPresentTimestamp(layer, layer->GetSurface());
108 }
109
110 // set all layers' releaseFence.
111 const auto layersReleaseFence = output_->GetLayersReleaseFence();
112 for (const auto& [layer, fence] : layersReleaseFence) {
113 if (layer == nullptr) {
114 continue;
115 }
116
117 auto nodePtr = static_cast<RSBaseRenderNode*>(layer->GetLayerAdditionalInfo());
118 if (nodePtr == nullptr) {
119 RS_LOGW("RSComposerAdapter::PostProcess: layer's node is nullptr.");
120 continue;
121 }
122
123 RSSurfaceHandler* surfaceHandler = nullptr;
124 if (nodePtr->IsInstanceOf<RSSurfaceRenderNode>()) {
125 auto surfaceNode = static_cast<RSSurfaceRenderNode*>(nodePtr);
126 surfaceHandler = static_cast<RSSurfaceHandler*>(surfaceNode);
127 } else if (nodePtr->IsInstanceOf<RSDisplayRenderNode>()) {
128 auto displayNode = static_cast<RSDisplayRenderNode*>(nodePtr);
129 surfaceHandler = static_cast<RSSurfaceHandler*>(displayNode);
130 }
131 if (surfaceHandler == nullptr) {
132 continue;
133 }
134 surfaceHandler->SetReleaseFence(fence);
135 }
136 }
137
DumpLayersToFile(const std::vector<LayerInfoPtr> & layers)138 void RSComposerAdapter::DumpLayersToFile(const std::vector<LayerInfoPtr>& layers)
139 {
140 if (!RSSystemProperties::GetDumpLayersEnabled()) {
141 return;
142 }
143
144 for (auto &layerInfo : layers) {
145 if (layerInfo == nullptr || layerInfo->GetSurface() == nullptr) {
146 continue;
147 }
148 auto buffer = layerInfo->GetBuffer();
149 if (buffer == nullptr) {
150 RS_LOGW("RSComposerAdapter::DumpLayersToFile: Buffer is null");
151 continue;
152 }
153 struct timeval now;
154 gettimeofday(&now, nullptr);
155 constexpr int secToUsec = 1000 * 1000;
156 int64_t nowVal = static_cast<int64_t>(now.tv_sec) * secToUsec + static_cast<int64_t>(now.tv_usec);
157
158 std::stringstream ss;
159 ss << "/data/layer_" << layerInfo->GetSurface()->GetName() << "_" << nowVal << "_" << buffer->GetWidth()
160 << "x" << buffer->GetHeight() << ".raw";
161
162 std::ofstream rawDataFile(ss.str(), std::ofstream::binary);
163 if (!rawDataFile.good()) {
164 RS_LOGW("RSComposerAdapter::DumpLayersToFile: Open failed!");
165 continue;
166 }
167 rawDataFile.write(static_cast<const char *>(buffer->GetVirAddr()), buffer->GetSize());
168 rawDataFile.close();
169 }
170 }
171
172 // private func
IsOutOfScreenRegion(const ComposeInfo & info) const173 bool RSComposerAdapter::IsOutOfScreenRegion(const ComposeInfo& info) const
174 {
175 int32_t boundWidth = static_cast<int32_t>(screenInfo_.width);
176 int32_t boundHeight = static_cast<int32_t>(screenInfo_.height);
177 ScreenRotation rotation = screenInfo_.rotation;
178 if (rotation == ScreenRotation::ROTATION_90 || rotation == ScreenRotation::ROTATION_270) {
179 std::swap(boundWidth, boundHeight);
180 }
181
182 const auto& dstRect = info.dstRect;
183 if (dstRect.x + dstRect.w <= 0 ||
184 dstRect.x >= boundWidth ||
185 dstRect.y + dstRect.h <= 0 ||
186 dstRect.y >= boundHeight) {
187 return true;
188 }
189
190 return false;
191 }
192
193 #ifndef USE_ROSEN_DRAWING
DealWithNodeGravity(const RSSurfaceRenderNode & node,ComposeInfo & info) const194 void RSComposerAdapter::DealWithNodeGravity(const RSSurfaceRenderNode& node, ComposeInfo& info) const
195 {
196 const auto& property = node.GetRenderProperties();
197 const auto frameWidth = info.buffer->GetSurfaceBufferWidth();
198 const auto frameHeight = info.buffer->GetSurfaceBufferHeight();
199 const int boundsWidth = static_cast<int>(property.GetBoundsWidth());
200 const int boundsHeight = static_cast<int>(property.GetBoundsHeight());
201 const Gravity frameGravity = property.GetFrameGravity();
202 // we do not need to do additional works for Gravity::RESIZE and if frameSize == boundsSize.
203 if (frameGravity == Gravity::RESIZE || (frameWidth == boundsWidth && frameHeight == boundsHeight)) {
204 return;
205 }
206
207 auto traceInfo = node.GetName() + " DealWithNodeGravity " + std::to_string(static_cast<int>(frameGravity));
208 RS_TRACE_NAME(traceInfo.c_str());
209
210 // get current node's translate matrix and calculate gravity matrix.
211 #ifdef NEW_SKIA
212 auto translateMatrix = SkMatrix::Translate(
213 std::ceil(node.GetTotalMatrix().getTranslateX()), std::ceil(node.GetTotalMatrix().getTranslateY()));
214 #else
215 auto translateMatrix = SkMatrix::MakeTrans(
216 std::ceil(node.GetTotalMatrix().getTranslateX()), std::ceil(node.GetTotalMatrix().getTranslateY()));
217 #endif
218 SkMatrix gravityMatrix;
219 (void)RSPropertiesPainter::GetGravityMatrix(frameGravity,
220 RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix);
221
222 // create a canvas to calculate new dstRect and new srcRect
223 int32_t screenWidth = screenInfo_.width;
224 int32_t screenHeight = screenInfo_.height;
225 const auto screenRotation = screenInfo_.rotation;
226 if (screenRotation == ScreenRotation::ROTATION_90 || screenRotation == ScreenRotation::ROTATION_270) {
227 std::swap(screenWidth, screenHeight);
228 }
229 auto canvas = std::make_unique<SkCanvas>(screenWidth, screenHeight);
230 canvas->concat(translateMatrix);
231 SkRect clipRect;
232 gravityMatrix.mapRect(&clipRect, SkRect::MakeWH(frameWidth, frameHeight));
233 canvas->clipRect(clipRect);
234 canvas->concat(gravityMatrix);
235 SkIRect newDstRect = canvas->getDeviceClipBounds();
236 // we make the newDstRect as the intersection of new and old dstRect,
237 // to deal with the situation that frameSize > boundsSize.
238 newDstRect.intersect(SkIRect::MakeXYWH(info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h));
239 auto localRect = canvas->getLocalClipBounds();
240 int left = std::clamp<int>(localRect.left(), 0, frameWidth);
241 int top = std::clamp<int>(localRect.top(), 0, frameHeight);
242 int width = std::clamp<int>(localRect.width(), 0, frameWidth - left);
243 int height = std::clamp<int>(localRect.height(), 0, frameHeight - top);
244 GraphicIRect newSrcRect = {left, top, width, height};
245
246 // log and apply new dstRect and srcRect
247 RS_LOGD("RsDebug DealWithNodeGravity: name[%s], gravity[%d], oldDstRect[%d %d %d %d], newDstRect[%d %d %d %d],"\
248 " oldSrcRect[%d %d %d %d], newSrcRect[%d %d %d %d].",
249 node.GetName().c_str(), static_cast<int>(frameGravity),
250 info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h,
251 newDstRect.left(), newDstRect.top(), newDstRect.width(), newDstRect.height(),
252 info.srcRect.x, info.srcRect.y, info.srcRect.w, info.srcRect.h,
253 newSrcRect.x, newSrcRect.y, newSrcRect.w, newSrcRect.h);
254 info.dstRect = {newDstRect.left(), newDstRect.top(), newDstRect.width(), newDstRect.height()};
255 info.srcRect = newSrcRect;
256 }
257 #else
DealWithNodeGravity(const RSSurfaceRenderNode & node,ComposeInfo & info) const258 void RSComposerAdapter::DealWithNodeGravity(const RSSurfaceRenderNode& node, ComposeInfo& info) const
259 {
260 const auto& property = node.GetRenderProperties();
261 const auto frameWidth = info.buffer->GetSurfaceBufferWidth();
262 const auto frameHeight = info.buffer->GetSurfaceBufferHeight();
263 const int boundsWidth = static_cast<int>(property.GetBoundsWidth());
264 const int boundsHeight = static_cast<int>(property.GetBoundsHeight());
265 const Gravity frameGravity = property.GetFrameGravity();
266 // we do not need to do additional works for Gravity::RESIZE and if frameSize == boundsSize.
267 if (frameGravity == Gravity::RESIZE || (frameWidth == boundsWidth && frameHeight == boundsHeight)) {
268 return;
269 }
270
271 auto traceInfo = node.GetName() + " DealWithNodeGravity " + std::to_string(static_cast<int>(frameGravity));
272 RS_TRACE_NAME(traceInfo.c_str());
273
274 // get current node's translate matrix and calculate gravity matrix.
275 Drawing::Matrix translateMatrix;
276 translateMatrix.Translate(
277 std::ceil(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_X)),
278 std::ceil(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_Y)));
279 Drawing::Matrix gravityMatrix;
280 (void)RSPropertiesPainter::GetGravityMatrix(frameGravity,
281 RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix);
282
283 // create a canvas to calculate new dstRect and new srcRect
284 int32_t screenWidth = screenInfo_.width;
285 int32_t screenHeight = screenInfo_.height;
286 const auto screenRotation = screenInfo_.rotation;
287 if (screenRotation == ScreenRotation::ROTATION_90 || screenRotation == ScreenRotation::ROTATION_270) {
288 std::swap(screenWidth, screenHeight);
289 }
290 Drawing::Bitmap bitmap;
291 Drawing::BitmapFormat format { Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_OPAQUE };
292 bitmap.Build(screenWidth, screenHeight, format);
293 auto canvas = std::make_unique<Rosen::Drawing::Canvas>();
294 canvas->Bind(bitmap);
295 canvas->ConcatMatrix(translateMatrix);
296 Drawing::Rect clipRect;
297 Drawing::Rect srcRect(0, 0, frameWidth, frameHeight);
298 gravityMatrix.MapRect(clipRect, srcRect);
299 canvas->ClipRect(clipRect, Drawing::ClipOp::INTERSECT, false);
300 canvas->ConcatMatrix(gravityMatrix);
301 Drawing::RectI newDstRect = canvas->GetDeviceClipBounds();
302 // we make the newDstRect as the intersection of new and old dstRect,
303 // to deal with the situation that frameSize > boundsSize.
304 // replace Intersect
305 newDstRect.Intersect(Drawing::RectI(info.dstRect.x, info.dstRect.y,
306 info.dstRect.w + info.dstRect.x, info.dstRect.h + info.dstRect.y));
307 auto localRect = canvas->GetLocalClipBounds();
308 int left = std::clamp<int>(localRect.GetLeft(), 0, frameWidth);
309 int top = std::clamp<int>(localRect.GetTop(), 0, frameHeight);
310 int width = std::clamp<int>(localRect.GetWidth(), 0, frameWidth - left);
311 int height = std::clamp<int>(localRect.GetHeight(), 0, frameHeight - top);
312 GraphicIRect newSrcRect = {left, top, width, height};
313
314 // log and apply new dstRect and srcRect
315 RS_LOGD("RsDebug DealWithNodeGravity: name[%s], gravity[%d], oldDstRect[%d %d %d %d], newDstRect[%d %d %d %d],"\
316 " oldSrcRect[%d %d %d %d], newSrcRect[%d %d %d %d].",
317 node.GetName().c_str(), static_cast<int>(frameGravity),
318 info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h,
319 newDstRect.GetLeft(), newDstRect.GetTop(), newDstRect.GetWidth(), newDstRect.GetHeight(),
320 info.srcRect.x, info.srcRect.y, info.srcRect.w, info.srcRect.h,
321 newSrcRect.x, newSrcRect.y, newSrcRect.w, newSrcRect.h);
322 info.dstRect = {newDstRect.GetLeft(), newDstRect.GetTop(), newDstRect.GetWidth(), newDstRect.GetHeight()};
323 info.srcRect = newSrcRect;
324 }
325 #endif
326
GetComposerInfoSrcRect(ComposeInfo & info,const RSSurfaceRenderNode & node)327 void RSComposerAdapter::GetComposerInfoSrcRect(ComposeInfo &info, const RSSurfaceRenderNode& node)
328 {
329 const auto& property = node.GetRenderProperties();
330 const auto bufferWidth = info.buffer->GetSurfaceBufferWidth();
331 const auto bufferHeight = info.buffer->GetSurfaceBufferHeight();
332 const int boundsWidth = static_cast<int>(property.GetBoundsWidth());
333 const int boundsHeight = static_cast<int>(property.GetBoundsHeight());
334 if (bufferWidth != boundsWidth || bufferHeight != boundsHeight) {
335 // float will cause loss of accuracy, and the result will 1 pixel less
336 double xScale = (ROSEN_EQ(boundsWidth, 0) ? 1.0 : 1.0 * bufferWidth / boundsWidth);
337 double yScale = (ROSEN_EQ(boundsHeight, 0) ? 1.0 : 1.0 * bufferHeight / boundsHeight);
338 info.srcRect.x = info.srcRect.x * xScale;
339 info.srcRect.y = info.srcRect.y * yScale;
340 info.srcRect.w = info.srcRect.w * xScale;
341 info.srcRect.h = info.srcRect.h * yScale;
342 }
343 }
344
GetComposerInfoNeedClient(const ComposeInfo & info,RSSurfaceRenderNode & node) const345 bool RSComposerAdapter::GetComposerInfoNeedClient(const ComposeInfo &info, RSSurfaceRenderNode& node) const
346 {
347 bool needClient = RSBaseRenderUtil::IsNeedClient(node, info);
348 if (info.buffer->GetSurfaceBufferColorGamut() != static_cast<GraphicColorGamut>(screenInfo_.colorGamut)) {
349 needClient = true;
350 }
351 return needClient;
352 }
353
354 // private func, for RSSurfaceRenderNode.
BuildComposeInfo(RSSurfaceRenderNode & node,bool isTunnelCheck) const355 ComposeInfo RSComposerAdapter::BuildComposeInfo(RSSurfaceRenderNode& node, bool isTunnelCheck) const
356 {
357 const auto& dstRect = node.GetDstRect();
358 const auto& srcRect = node.GetSrcRect();
359 ComposeInfo info {};
360 info.srcRect = GraphicIRect {srcRect.left_, srcRect.top_, srcRect.width_, srcRect.height_};
361 info.dstRect = GraphicIRect {
362 static_cast<int32_t>(static_cast<float>(dstRect.left_) * mirrorAdaptiveCoefficient_),
363 static_cast<int32_t>(static_cast<float>(dstRect.top_) * mirrorAdaptiveCoefficient_),
364 static_cast<int32_t>(static_cast<float>(dstRect.width_) * mirrorAdaptiveCoefficient_),
365 static_cast<int32_t>(static_cast<float>(dstRect.height_) * mirrorAdaptiveCoefficient_)
366 };
367 info.zOrder = static_cast<int32_t>(node.GetGlobalZOrder());
368 info.alpha.enGlobalAlpha = true;
369 info.alpha.gAlpha = node.GetGlobalAlpha() * 255; // map gAlpha from float(0, 1) to uint8_t(0, 255).
370 info.fence = node.GetAcquireFence();
371 info.blendType = node.GetBlendType();
372
373 info.dstRect.x -= static_cast<int32_t>(static_cast<float>(offsetX_) * mirrorAdaptiveCoefficient_);
374 info.dstRect.y -= static_cast<int32_t>(static_cast<float>(offsetY_) * mirrorAdaptiveCoefficient_);
375 info.visibleRect = info.dstRect;
376 if (!isTunnelCheck) {
377 const auto& buffer = node.GetBuffer();
378 info.buffer = buffer;
379 GetComposerInfoSrcRect(info, node);
380 info.needClient = GetComposerInfoNeedClient(info, node);
381 DealWithNodeGravity(node, info);
382 } else {
383 info.needClient = false;
384 }
385 return info;
386 }
387
388 // private func, for RSDisplayRenderNode
BuildComposeInfo(RSDisplayRenderNode & node) const389 ComposeInfo RSComposerAdapter::BuildComposeInfo(RSDisplayRenderNode& node) const
390 {
391 const auto& buffer = node.GetBuffer(); // we guarantee the buffer is valid.
392 ComposeInfo info {};
393 info.srcRect = GraphicIRect {0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight()};
394 info.dstRect = GraphicIRect {
395 0,
396 0,
397 static_cast<int32_t>(static_cast<float>(screenInfo_.GetRotatedWidth()) * mirrorAdaptiveCoefficient_),
398 static_cast<int32_t>(static_cast<float>(screenInfo_.GetRotatedHeight()) * mirrorAdaptiveCoefficient_)
399 };
400 info.visibleRect = GraphicIRect {info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h};
401 info.zOrder = static_cast<int32_t>(node.GetGlobalZOrder());
402 info.alpha.enGlobalAlpha = false;
403 info.buffer = buffer;
404 info.fence = node.GetAcquireFence();
405 info.blendType = GRAPHIC_BLEND_NONE;
406 info.needClient = false;
407 return info;
408 }
409
SetComposeInfoToLayer(const LayerInfoPtr & layer,const ComposeInfo & info,const sptr<IConsumerSurface> & surface,RSBaseRenderNode * node) const410 void RSComposerAdapter::SetComposeInfoToLayer(
411 const LayerInfoPtr& layer,
412 const ComposeInfo& info,
413 const sptr<IConsumerSurface>& surface,
414 RSBaseRenderNode* node) const
415 {
416 if (layer == nullptr) {
417 return;
418 }
419 layer->SetSurface(surface);
420 layer->SetBuffer(info.buffer, info.fence);
421 layer->SetZorder(info.zOrder);
422 layer->SetAlpha(info.alpha);
423 layer->SetLayerSize(info.dstRect);
424 layer->SetLayerAdditionalInfo(node);
425 layer->SetCompositionType(info.needClient ?
426 GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT : GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE);
427 std::vector<GraphicIRect> visibleRegions;
428 visibleRegions.emplace_back(info.visibleRect);
429 layer->SetVisibleRegions(visibleRegions);
430 std::vector<GraphicIRect> dirtyRegions;
431 dirtyRegions.emplace_back(info.srcRect);
432 layer->SetDirtyRegions(dirtyRegions);
433 layer->SetBlendType(info.blendType);
434 layer->SetCropRect(info.srcRect);
435 if (node -> GetTunnelHandleChange()) {
436 layer->SetTunnelHandleChange(true);
437 layer->SetTunnelHandle(surface->GetTunnelHandle());
438 node ->SetTunnelHandleChange(false);
439 }
440 if (surface->GetTunnelHandle() != nullptr) {
441 return;
442 }
443 SetMetaDataInfoToLayer(layer, info, surface);
444 }
445
SetMetaDataInfoToLayer(const LayerInfoPtr & layer,const ComposeInfo & info,const sptr<IConsumerSurface> & surface) const446 void RSComposerAdapter::SetMetaDataInfoToLayer(const LayerInfoPtr& layer, const ComposeInfo& info,
447 const sptr<IConsumerSurface>& surface) const
448 {
449 HDRMetaDataType type;
450 if (surface->QueryMetaDataType(info.buffer->GetSeqNum(), type) != GSERROR_OK) {
451 RS_LOGE("RSComposerAdapter::SetComposeInfoToLayer: QueryMetaDataType failed");
452 return;
453 }
454 switch (type) {
455 case HDRMetaDataType::HDR_META_DATA: {
456 std::vector<GraphicHDRMetaData> metaData;
457 if (surface->GetMetaData(info.buffer->GetSeqNum(), metaData) != GSERROR_OK) {
458 RS_LOGE("RSComposerAdapter::SetComposeInfoToLayer: GetMetaData failed");
459 return;
460 }
461 layer->SetMetaData(metaData);
462 break;
463 }
464 case HDRMetaDataType::HDR_META_DATA_SET: {
465 GraphicHDRMetadataKey key;
466 std::vector<uint8_t> metaData;
467 if (surface->GetMetaDataSet(info.buffer->GetSeqNum(), key, metaData) != GSERROR_OK) {
468 RS_LOGE("RSComposerAdapter::SetComposeInfoToLayer: GetMetaDataSet failed");
469 return;
470 }
471 GraphicHDRMetaDataSet metaDataSet;
472 metaDataSet.key = key;
473 metaDataSet.metaData = metaData;
474 layer->SetMetaDataSet(metaDataSet);
475 break;
476 }
477 case HDRMetaDataType::HDR_NOT_USED: {
478 break;
479 }
480 default: {
481 break;
482 }
483 }
484 }
485
CheckStatusBeforeCreateLayer(RSSurfaceRenderNode & node,bool isTunnelCheck) const486 bool RSComposerAdapter::CheckStatusBeforeCreateLayer(RSSurfaceRenderNode& node, bool isTunnelCheck) const
487 {
488 if (output_ == nullptr) {
489 RS_LOGE("RSComposerAdapter::CheckStatusBeforeCreateLayer: output is nullptr");
490 return false;
491 }
492
493 const auto& buffer = node.GetBuffer();
494 if (isTunnelCheck == false && buffer == nullptr) {
495 RS_LOGD("RsDebug RSComposerAdapter::CheckStatusBeforeCreateLayer:node(%" PRIu64 ") has no available buffer.",
496 node.GetId());
497 return false;
498 }
499
500 const auto& dstRect = node.GetDstRect();
501 const auto& srcRect = node.GetSrcRect();
502 // check if the node's srcRect and dstRect are valid.
503 if (srcRect.width_ <= 0 || srcRect.height_ <= 0 || dstRect.width_ <= 0 || dstRect.height_ <= 0) {
504 return false;
505 }
506
507 auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
508 if (geoPtr == nullptr) {
509 RS_LOGW("RsDebug RSComposerAdapter::CheckStatusBeforeCreateLayer: node(%" PRIu64 ")'s geoPtr is nullptr!",
510 node.GetId());
511 return false;
512 }
513
514 if (!node.IsNotifyRTBufferAvailable()) {
515 // Only ipc for one time.
516 RS_LOGD("RsDebug RSPhysicalScreenProcessor::ProcessSurface id = %" PRIu64 " Notify RT buffer available",
517 node.GetId());
518 node.NotifyRTBufferAvailable();
519 }
520 return true;
521 }
522
CreateBufferLayer(RSSurfaceRenderNode & node) const523 LayerInfoPtr RSComposerAdapter::CreateBufferLayer(RSSurfaceRenderNode& node) const
524 {
525 if (!CheckStatusBeforeCreateLayer(node)) {
526 return nullptr;
527 }
528 ComposeInfo info = BuildComposeInfo(node);
529 if (IsOutOfScreenRegion(info)) {
530 RS_LOGD("RsDebug RSComposerAdapter::CreateBufferLayer: node(%" PRIu64
531 ") out of screen region, no need to composite.",
532 node.GetId());
533 return nullptr;
534 }
535 std::string traceInfo;
536 AppendFormat(traceInfo, "ProcessSurfaceNode:%s XYWH[%d %d %d %d]", node.GetName().c_str(),
537 info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h);
538 RS_TRACE_NAME(traceInfo.c_str());
539 RS_LOGD(
540 "RsDebug RSComposerAdapter::CreateBufferLayer surfaceNode id:%" PRIu64 " name:[%s] dst [%d %d %d %d]"
541 "SrcRect [%d %d] rawbuffer [%d %d] surfaceBuffer [%d %d], z:%f, globalZOrder:%d, blendType = %d",
542 node.GetId(), node.GetName().c_str(), info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h,
543 info.srcRect.w, info.srcRect.h, info.buffer->GetWidth(), info.buffer->GetHeight(),
544 info.buffer->GetSurfaceBufferWidth(), info.buffer->GetSurfaceBufferHeight(),
545 node.GetGlobalZOrder(), info.zOrder, info.blendType);
546 LayerInfoPtr layer = HdiLayerInfo::CreateHdiLayerInfo();
547 SetComposeInfoToLayer(layer, info, node.GetConsumer(), &node);
548 LayerRotate(layer, node);
549 LayerCrop(layer);
550 LayerScaleDown(layer);
551 return layer;
552 }
553
CreateTunnelLayer(RSSurfaceRenderNode & node) const554 LayerInfoPtr RSComposerAdapter::CreateTunnelLayer(RSSurfaceRenderNode& node) const
555 {
556 if (!CheckStatusBeforeCreateLayer(node, true)) {
557 return nullptr;
558 }
559 ComposeInfo info = BuildComposeInfo(node, true);
560 if (IsOutOfScreenRegion(info)) {
561 RS_LOGD("RsDebug RSComposerAdapter::CreateTunnelLayer: node(%" PRIu64
562 ") out of screen region, no need to composite.",
563 node.GetId());
564 return nullptr;
565 }
566 std::string traceInfo;
567 AppendFormat(traceInfo, "ProcessSurfaceNode:%s XYWH[%d %d %d %d]", node.GetName().c_str(),
568 info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h);
569 RS_TRACE_NAME(traceInfo.c_str());
570 LayerInfoPtr layer = HdiLayerInfo::CreateHdiLayerInfo();
571 SetComposeInfoToLayer(layer, info, node.GetConsumer(), &node);
572 LayerRotate(layer, node);
573 RS_LOGD("RsDebug RSComposerAdapter::CreateTunnelLayer surfaceNode id:%" PRIu64 " name:[%s] dst [%d %d %d %d]"
574 "SrcRect [%d %d], z:%f, globalZOrder:%d, blendType = %d",
575 node.GetId(), node.GetName().c_str(), info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h,
576 info.srcRect.w, info.srcRect.h, node.GetGlobalZOrder(), info.zOrder, info.blendType);
577 return layer;
578 }
579
CreateLayer(RSSurfaceRenderNode & node) const580 LayerInfoPtr RSComposerAdapter::CreateLayer(RSSurfaceRenderNode& node) const
581 {
582 auto& consumer = node.GetConsumer();
583 if (consumer == nullptr) {
584 RS_LOGE("RSComposerAdapter::CreateLayer get consumer fail");
585 return nullptr;
586 }
587 sptr<SurfaceTunnelHandle> handle = consumer->GetTunnelHandle();
588 if (handle != nullptr) {
589 return CreateTunnelLayer(node);
590 } else {
591 return CreateBufferLayer(node);
592 }
593 }
594
CreateLayer(RSDisplayRenderNode & node) const595 LayerInfoPtr RSComposerAdapter::CreateLayer(RSDisplayRenderNode& node) const
596 {
597 if (output_ == nullptr) {
598 RS_LOGE("RSComposerAdapter::CreateLayer: output is nullptr");
599 return nullptr;
600 }
601 if (!RSBaseRenderUtil::ConsumeAndUpdateBuffer(node)) {
602 RS_LOGE("RSComposerAdapter::CreateLayer consume buffer failed.");
603 return nullptr;
604 }
605
606 if (node.GetBuffer() == nullptr) {
607 RS_LOGE("RSComposerAdapter::CreateLayer buffer is nullptr.");
608 return nullptr;
609 }
610
611 ComposeInfo info = BuildComposeInfo(node);
612 RS_LOGD("RSComposerAdapter::ProcessSurface displayNode id:%" PRIu64 " dst [%d %d %d %d]"
613 "SrcRect [%d %d] rawbuffer [%d %d] surfaceBuffer [%d %d], globalZOrder:%d, blendType = %d",
614 node.GetId(), info.dstRect.x, info.dstRect.y, info.dstRect.w, info.dstRect.h, info.srcRect.w, info.srcRect.h,
615 info.buffer->GetWidth(), info.buffer->GetHeight(), info.buffer->GetSurfaceBufferWidth(),
616 info.buffer->GetSurfaceBufferHeight(), info.zOrder, info.blendType);
617 LayerInfoPtr layer = HdiLayerInfo::CreateHdiLayerInfo();
618 SetComposeInfoToLayer(layer, info, node.GetConsumer(), &node);
619 LayerRotate(layer, node);
620 // do not crop or scale down for displayNode's layer.
621 return layer;
622 }
623
GetSurfaceNodeRotation(RSBaseRenderNode & node)624 static int GetSurfaceNodeRotation(RSBaseRenderNode& node)
625 {
626 // only surface render node has the ability to rotate
627 // the rotation of display render node is calculated as screen rotation
628 if (node.GetType() != RSRenderNodeType::SURFACE_NODE) {
629 return 0;
630 }
631
632 auto& surfaceNode = static_cast<RSSurfaceRenderNode&>(node);
633 auto matrix = surfaceNode.GetTotalMatrix();
634 #ifndef USE_ROSEN_DRAWING
635 float value[9];
636 matrix.get9(value);
637
638 int rAngle = static_cast<int>(-round(atan2(value[SkMatrix::kMSkewX], value[SkMatrix::kMScaleX]) * (180 / PI)));
639 #else
640 Drawing::Matrix::Buffer value;
641 matrix.GetAll(value);
642
643 int rAngle = static_cast<int>(
644 -round(atan2(value[Drawing::Matrix::SKEW_X], value[Drawing::Matrix::SCALE_X]) * (180 / PI)));
645 #endif
646 // transfer the result to anti-clockwise degrees
647 // only rotation with 90°, 180°, 270° are composed through hardware,
648 // in which situation the transformation of the layer needs to be set.
649 static const std::map<int, int> supportedDegrees = {{90, 270}, {180, 180}, {-90, 90}};
650 auto iter = supportedDegrees.find(rAngle);
651 return iter != supportedDegrees.end() ? iter->second : 0;
652 }
653
SetLayerTransform(const LayerInfoPtr & layer,RSBaseRenderNode & node,const sptr<IConsumerSurface> & surface,ScreenRotation screenRotation)654 static void SetLayerTransform(const LayerInfoPtr& layer, RSBaseRenderNode& node,
655 const sptr<IConsumerSurface>& surface, ScreenRotation screenRotation)
656 {
657 // screenRotation: anti-clockwise, surfaceNodeRotation: anti-clockwise, surfaceTransform: anti-clockwise
658 // layerTransform: clockwise
659 int surfaceNodeRotation = GetSurfaceNodeRotation(node);
660 int totalRotation = (RotateEnumToInt(screenRotation) + surfaceNodeRotation +
661 RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(surface->GetTransform()))) % 360;
662 GraphicTransformType rotateEnum = RSBaseRenderUtil::RotateEnumToInt(totalRotation,
663 RSBaseRenderUtil::GetFlipTransform(surface->GetTransform()));
664 layer->SetTransform(rotateEnum);
665 }
666
SetLayerSize(const LayerInfoPtr & layer,const ScreenInfo & screenInfo)667 static void SetLayerSize(const LayerInfoPtr& layer, const ScreenInfo& screenInfo)
668 {
669 const auto screenWidth = static_cast<int32_t>(screenInfo.width);
670 const auto screenHeight = static_cast<int32_t>(screenInfo.height);
671 const auto screenRotation = screenInfo.rotation;
672 const auto rect = layer->GetLayerSize();
673 // screenRotation: anti-clockwise, surfaceTransform: anti-clockwise, layerTransform: clockwise
674 switch (screenRotation) {
675 case ScreenRotation::ROTATION_90: {
676 RS_LOGD("RsDebug ScreenRotation 90, Before Rotate layer size [%d %d %d %d]",
677 rect.x, rect.y, rect.w, rect.h);
678 layer->SetLayerSize(GraphicIRect {rect.y, screenHeight - rect.x - rect.w, rect.h, rect.w});
679 RS_LOGD("RsDebug ScreenRotation 90, After Rotate layer size [%d %d %d %d]",
680 layer->GetLayerSize().x, layer->GetLayerSize().y, layer->GetLayerSize().w, layer->GetLayerSize().h);
681 break;
682 }
683 case ScreenRotation::ROTATION_180: {
684 RS_LOGD("RsDebug ScreenRotation 180, Before Rotate layer size [%d %d %d %d]",
685 rect.x, rect.y, rect.w, rect.h);
686 layer->SetLayerSize(
687 GraphicIRect {screenWidth - rect.x - rect.w, screenHeight - rect.y - rect.h, rect.w, rect.h});
688 RS_LOGD("RsDebug ScreenRotation 180, After Rotate layer size [%d %d %d %d]",
689 layer->GetLayerSize().x, layer->GetLayerSize().y, layer->GetLayerSize().w, layer->GetLayerSize().h);
690 break;
691 }
692 case ScreenRotation::ROTATION_270: {
693 RS_LOGD("RsDebug ScreenRotation 270, Before Rotate layer size [%d %d %d %d]",
694 rect.x, rect.y, rect.w, rect.h);
695 layer->SetLayerSize(GraphicIRect {screenWidth - rect.y - rect.h, rect.x, rect.h, rect.w});
696 RS_LOGD("RsDebug ScreenRotation 270, After Rotate layer size [%d %d %d %d]",
697 layer->GetLayerSize().x, layer->GetLayerSize().y, layer->GetLayerSize().w, layer->GetLayerSize().h);
698 break;
699 }
700 default: {
701 break;
702 }
703 }
704 }
705
706 // private func, guarantee the layer is valid
LayerRotate(const LayerInfoPtr & layer,RSBaseRenderNode & node) const707 void RSComposerAdapter::LayerRotate(const LayerInfoPtr& layer, RSBaseRenderNode& node) const
708 {
709 auto surface = layer->GetSurface();
710 if (surface == nullptr) {
711 return;
712 }
713 SetLayerSize(layer, screenInfo_);
714 SetLayerTransform(layer, node, surface, screenInfo_.rotation);
715 }
716
717 // private func, guarantee the layer is valid
LayerCrop(const LayerInfoPtr & layer) const718 void RSComposerAdapter::LayerCrop(const LayerInfoPtr& layer) const
719 {
720 GraphicIRect dstRect = layer->GetLayerSize();
721 GraphicIRect srcRect = layer->GetCropRect();
722 GraphicIRect originSrcRect = srcRect;
723
724 RectI dstRectI(dstRect.x, dstRect.y, dstRect.w, dstRect.h);
725 int32_t screenWidth = static_cast<int32_t>(screenInfo_.width);
726 int32_t screenHeight = static_cast<int32_t>(screenInfo_.height);
727 RectI screenRectI(0, 0, screenWidth, screenHeight);
728 RectI resDstRect = dstRectI.IntersectRect(screenRectI);
729 if (resDstRect == dstRectI) {
730 return;
731 }
732 dstRect = {resDstRect.left_, resDstRect.top_, resDstRect.width_, resDstRect.height_};
733 srcRect.x = resDstRect.IsEmpty() ? 0 : std::ceil((resDstRect.left_ - dstRectI.left_) *
734 originSrcRect.w / dstRectI.width_);
735 srcRect.y = resDstRect.IsEmpty() ? 0 : std::ceil((resDstRect.top_ - dstRectI.top_) *
736 originSrcRect.h / dstRectI.height_);
737 srcRect.w = dstRectI.IsEmpty() ? 0 : originSrcRect.w * resDstRect.width_ / dstRectI.width_;
738 srcRect.h = dstRectI.IsEmpty() ? 0 : originSrcRect.h * resDstRect.height_ / dstRectI.height_;
739 layer->SetLayerSize(dstRect);
740 std::vector<GraphicIRect> dirtyRegions;
741 dirtyRegions.emplace_back(srcRect);
742 layer->SetDirtyRegions(dirtyRegions);
743 layer->SetCropRect(srcRect);
744 RS_LOGD("RsDebug RSComposerAdapter::LayerCrop layer has been cropped dst[%d %d %d %d] src[%d %d %d %d]",
745 dstRect.x, dstRect.y, dstRect.w, dstRect.h, srcRect.x, srcRect.y, srcRect.w, srcRect.h);
746 }
747
748 // private func, guarantee the layer is valid
LayerScaleDown(const LayerInfoPtr & layer)749 void RSComposerAdapter::LayerScaleDown(const LayerInfoPtr& layer)
750 {
751 ScalingMode scalingMode = ScalingMode::SCALING_MODE_SCALE_TO_WINDOW;
752 const auto& buffer = layer->GetBuffer();
753 const auto& surface = layer->GetSurface();
754 if (buffer == nullptr || surface == nullptr) {
755 return;
756 }
757
758 if (surface->GetScalingMode(buffer->GetSeqNum(), scalingMode) == GSERROR_OK &&
759 scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
760 GraphicIRect dstRect = layer->GetLayerSize();
761 GraphicIRect srcRect = layer->GetCropRect();
762
763 uint32_t newWidth = static_cast<uint32_t>(srcRect.w);
764 uint32_t newHeight = static_cast<uint32_t>(srcRect.h);
765
766 if (newWidth * dstRect.h > newHeight * dstRect.w) {
767 // too wide
768 newWidth = dstRect.w * newHeight / dstRect.h;
769 } else if (newWidth * dstRect.h < newHeight * dstRect.w) {
770 // too tall
771 newHeight = dstRect.h * newWidth / dstRect.w;
772 } else {
773 return;
774 }
775
776 uint32_t currentWidth = static_cast<uint32_t>(srcRect.w);
777 uint32_t currentHeight = static_cast<uint32_t>(srcRect.h);
778
779 if (newWidth < currentWidth) {
780 // the crop is too wide
781 uint32_t dw = currentWidth - newWidth;
782 auto halfdw = dw / 2;
783 srcRect.x += halfdw;
784 srcRect.w = newWidth;
785 } else {
786 // thr crop is too tall
787 uint32_t dh = currentHeight - newHeight;
788 auto halfdh = dh / 2;
789 srcRect.y += halfdh;
790 srcRect.h = newHeight;
791 }
792 std::vector<GraphicIRect> dirtyRegions;
793 dirtyRegions.emplace_back(srcRect);
794 layer->SetDirtyRegions(dirtyRegions);
795 layer->SetCropRect(srcRect);
796 RS_LOGD("RsDebug RSComposerAdapter::LayerScaleDown layer has been scaledown dst[%d %d %d %d]"\
797 "src[%d %d %d %d]", dstRect.x, dstRect.y, dstRect.w, dstRect.h,
798 srcRect.x, srcRect.y, srcRect.w, srcRect.h);
799 }
800 }
801
802 // private func, guarantee the layer and surface are valid
LayerPresentTimestamp(const LayerInfoPtr & layer,const sptr<IConsumerSurface> & surface)803 void RSComposerAdapter::LayerPresentTimestamp(const LayerInfoPtr& layer, const sptr<IConsumerSurface>& surface)
804 {
805 if (!layer->IsSupportedPresentTimestamp()) {
806 return;
807 }
808 const auto& buffer = layer->GetBuffer();
809 if (buffer == nullptr) {
810 return;
811 }
812 if (surface->SetPresentTimestamp(buffer->GetSeqNum(), layer->GetPresentTimestamp()) != GSERROR_OK) {
813 RS_LOGD("RsDebug RSComposerAdapter::LayerPresentTimestamp: SetPresentTimestamp failed");
814 }
815 }
816
OnPrepareComplete(sptr<Surface> & surface,const PrepareCompleteParam & param,void * data)817 void RSComposerAdapter::OnPrepareComplete(sptr<Surface>& surface, const PrepareCompleteParam& param, void* data)
818 {
819 // unused data.
820 (void)(data);
821
822 if (!param.needFlushFramebuffer) {
823 return;
824 }
825
826 if (fallbackCb_ != nullptr) {
827 fallbackCb_(surface, param.layers);
828 }
829 }
830
SetHdiBackendDevice(HdiDevice * device)831 void RSComposerAdapter::SetHdiBackendDevice(HdiDevice* device)
832 {
833 hdiBackend_->SetHdiBackendDevice(device);
834 }
835 } // namespace Rosen
836 } // namespace OHOS
837