• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_virtual_processor.h"
17 
18 #include <ctime>
19 #include <parameters.h>
20 
21 #include "metadata_helper.h"
22 #include "sync_fence.h"
23 
24 #include "common/rs_optional_trace.h"
25 #include "drawable/rs_screen_render_node_drawable.h"
26 #include "drawable/rs_logical_display_render_node_drawable.h"
27 #include "graphic_feature_param_manager.h"
28 #include "params/rs_logical_display_render_params.h"
29 #include "platform/common/rs_log.h"
30 #include "platform/ohos/backend/rs_surface_frame_ohos_raster.h"
31 #include "rs_uni_render_util.h"
32 #include "pipeline/main_thread/rs_main_thread.h"
33 #include "string_utils.h"
34 
35 namespace OHOS {
36 namespace Rosen {
InitForRenderThread(DrawableV2::RSScreenRenderNodeDrawable & screenDrawable,std::shared_ptr<RSBaseRenderEngine> renderEngine)37 bool RSUniRenderVirtualProcessor::InitForRenderThread(DrawableV2::RSScreenRenderNodeDrawable& screenDrawable,
38     std::shared_ptr<RSBaseRenderEngine> renderEngine)
39 {
40     if (!RSProcessor::InitForRenderThread(screenDrawable, renderEngine)) {
41         return false;
42     }
43 
44     // Do expand screen if the mirror id is invalid.
45     auto screenManager = CreateOrGetScreenManager();
46     if (screenManager == nullptr) {
47         return false;
48     }
49     auto params = static_cast<RSScreenRenderParams*>(screenDrawable.GetRenderParams().get());
50     if (!params) {
51         return false;
52     }
53 
54     virtualScreenId_ = params->GetScreenId();
55     VirtualScreenStatus screenStatus = screenManager->GetVirtualScreenStatus(virtualScreenId_);
56     if (screenStatus == VIRTUAL_SCREEN_PAUSE) {
57         RS_LOGD("RSUniRenderVirtualProcessor::Init screenStatus is pause");
58         return false;
59     }
60 
61     scaleMode_ = screenManager->GetScaleMode(virtualScreenId_);
62     const auto& virtualScreenInfo = params->GetScreenInfo();
63     enableVisibleRect_ = virtualScreenInfo.enableVisibleRect;
64     canvasRotation_ = screenManager->GetCanvasRotation(virtualScreenId_);
65     if (enableVisibleRect_) {
66         const auto& rect = screenManager->GetMirrorScreenVisibleRect(virtualScreenId_);
67         visibleRect_ = Drawing::RectI(rect.x, rect.y, rect.x + rect.w, rect.y + rect.h);
68         // not support rotation for MirrorScreen visibleRect
69         canvasRotation_ = screenManager->IsVisibleRectSupportRotation(virtualScreenId_);
70     }
71     bool mirrorScreenHDR = false;
72     bool expandScreenHDR = false;
73     renderFrameConfig_.colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
74     auto mirroredScreenDrawable =
75         std::static_pointer_cast<DrawableV2::RSScreenRenderNodeDrawable>(params->GetMirrorSourceDrawable().lock());
76     if (mirroredScreenDrawable) {
77         auto childDrawables = params->GetDisplayDrawables();
78         if (childDrawables.empty() || childDrawables.front() == nullptr) {
79             RS_LOGE("RSUniRenderVirtualProcessor::InitForRenderThread: no child display in mirror screen");
80             return false;
81         }
82         auto displayDrawable = childDrawables.front();
83         auto displayParams = static_cast<RSLogicalDisplayRenderParams*>(displayDrawable->GetRenderParams().get());
84         auto mirroredDisplayDrawable = std::static_pointer_cast<DrawableV2::RSLogicalDisplayRenderNodeDrawable>(
85             displayParams->GetMirrorSourceDrawable().lock());
86         auto mirroredDisplayParams = static_cast<RSLogicalDisplayRenderParams*>(
87             mirroredDisplayDrawable->GetRenderParams().get());
88         auto mirroredScreenParams = static_cast<RSScreenRenderParams*>(mirroredScreenDrawable->GetRenderParams().get());
89         screenRotation_ = mirroredDisplayParams->GetScreenRotation();
90         screenCorrection_ = screenManager->GetScreenCorrection(mirroredDisplayParams->GetScreenId());
91         if (params->GetNewColorSpace() != GRAPHIC_COLOR_GAMUT_SRGB &&
92             mirroredScreenParams->GetNewColorSpace() != GRAPHIC_COLOR_GAMUT_SRGB) {
93             renderFrameConfig_.colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
94             RS_LOGD("RSUniRenderVirtualProcessor::Init Set virtual screen buffer colorGamut to P3.");
95         }
96         mirrorScreenHDR = RSHdrUtil::IsHDRCast(params, renderFrameConfig_);
97         RS_LOGD("RSUniRenderVirtualProcessor::Init HDRCast mirrorScreenHDR: %{public}d", mirrorScreenHDR);
98     } else {
99         if (params->GetNewColorSpace() != GRAPHIC_COLOR_GAMUT_SRGB) {
100             renderFrameConfig_.colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
101         }
102         expandScreenHDR = RSHdrUtil::IsHDRCast(params, renderFrameConfig_);
103         RS_LOGD("RSUniRenderVirtualProcessor::Init HDRCast expandScreenHDR: %{public}d", expandScreenHDR);
104     }
105 
106     SetVirtualScreenSize(screenDrawable, screenManager);
107 
108     renderFrameConfig_.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA;
109     FrameContextConfig frameContextConfig = FrameContextConfig(false);
110     frameContextConfig.isVirtual = true;
111     frameContextConfig.timeOut = 0;
112 
113     producerSurface_ = screenManager->GetProducerSurface(virtualScreenId_);
114     if (producerSurface_ == nullptr) {
115         RS_LOGE("RSUniRenderVirtualProcessor::Init for Screen(id %{public}" PRIu64 "): ProducerSurface is null!",
116             virtualScreenId_);
117         return false;
118     }
119 #ifdef RS_ENABLE_GL
120     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
121         renderFrame_ = renderEngine_->RequestFrame(producerSurface_, renderFrameConfig_, forceCPU_, false,
122             frameContextConfig);
123     }
124 #endif
125     if (renderFrame_ == nullptr) {
126         uint64_t pSurfaceUniqueId = producerSurface_->GetUniqueId();
127         auto rsSurface = screenDrawable.GetVirtualSurface(pSurfaceUniqueId);
128         if (rsSurface == nullptr || screenManager->GetAndResetVirtualSurfaceUpdateFlag(virtualScreenId_)) {
129             RS_LOGD("RSUniRenderVirtualProcessor::Init Make rssurface from producer Screen(id %{public}" PRIu64 ")",
130                 virtualScreenId_);
131             RS_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::Init Make rssurface from producer Screen(id %" PRIu64 ")",
132                 virtualScreenId_);
133             rsSurface = renderEngine_->MakeRSSurface(producerSurface_, forceCPU_);
134             screenDrawable.SetVirtualSurface(rsSurface, pSurfaceUniqueId);
135         }
136         renderFrame_ = renderEngine_->RequestFrame(
137             std::static_pointer_cast<RSSurfaceOhos>(rsSurface), renderFrameConfig_, forceCPU_, false,
138             frameContextConfig);
139     }
140     if (renderFrame_ == nullptr) {
141         RS_LOGE("RSUniRenderVirtualProcessor::Init for Screen(id %{public}" PRIu64 "): RenderFrame is null!",
142             virtualScreenId_);
143         return false;
144     }
145 
146     RS_LOGD("RSUniRenderVirtualProcessor::Init, RequestFrame succeed.");
147     RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::Init, RequestFrame succeed, colorSpace: %d.",
148         renderFrameConfig_.colorGamut);
149     uint64_t pSurfaceUniqueId = producerSurface_->GetUniqueId();
150     auto rsSurface = screenDrawable.GetVirtualSurface(pSurfaceUniqueId);
151     if (rsSurface != nullptr && SetColorSpaceForMetadata(rsSurface->GetColorSpace()) != GSERROR_OK) {
152         RS_LOGD("RSUniRenderVirtualProcessor::SetColorSpaceForMetadata failed.");
153     }
154 #ifdef USE_VIDEO_PROCESSING_ENGINE
155     if (mirrorScreenHDR || expandScreenHDR) {
156         if (RSHdrUtil::SetMetadata(RSHDRUtilConst::HDR_CAST_OUT_COLORSPACE, renderFrame_) != GSERROR_OK) {
157             RS_LOGD("RSUniRenderVirtualProcessor::Init SetMetadata failed");
158         }
159     }
160 #endif
161     canvas_ = renderFrame_->GetCanvas();
162     if (canvas_ == nullptr) {
163         RS_LOGE("RSUniRenderVirtualProcessor::Init for Screen(id %{public}" PRIu64 "): Canvas is null!",
164             virtualScreenId_);
165         return false;
166     }
167 
168     return true;
169 }
170 
UpdateMirrorInfo(DrawableV2::RSLogicalDisplayRenderNodeDrawable & displayDrawable)171 bool RSUniRenderVirtualProcessor::UpdateMirrorInfo(DrawableV2::RSLogicalDisplayRenderNodeDrawable& displayDrawable)
172 {
173     if (!RSProcessor::UpdateMirrorInfo(displayDrawable)) {
174         return false;
175     }
176     auto params = static_cast<RSLogicalDisplayRenderParams*>(displayDrawable.GetRenderParams().get());
177     if (!params) {
178         return false;
179     }
180     auto screenManager = CreateOrGetScreenManager();
181     if (screenManager == nullptr) {
182         return false;
183     }
184     auto mirroredDisplayDrawable = std::static_pointer_cast<DrawableV2::RSLogicalDisplayRenderNodeDrawable>(
185         params->GetMirrorSourceDrawable().lock());
186     if (mirroredDisplayDrawable) {
187         auto& mirroredParams = mirroredDisplayDrawable->GetRenderParams();
188         if (mirroredParams) {
189             auto mirroredDisplayParams = static_cast<RSLogicalDisplayRenderParams*>(mirroredParams.get());
190             auto mainScreenInfo = screenManager->QueryScreenInfo(mirroredDisplayParams->GetScreenId());
191             mirroredScreenWidth_ = mirroredDisplayParams->GetBounds().GetWidth();
192             mirroredScreenHeight_ = mirroredDisplayParams->GetBounds().GetHeight();
193             if (mirroredDisplayParams->GetNodeRotation() == ScreenRotation::ROTATION_90 ||
194                 mirroredDisplayParams->GetNodeRotation() == ScreenRotation::ROTATION_270) {
195                 std::swap(mirroredScreenWidth_, mirroredScreenHeight_);
196             }
197             if (mainScreenInfo.isSamplingOn) {
198                 mirroredScreenWidth_ *= mainScreenInfo.samplingScale;
199                 mirroredScreenHeight_ *= mainScreenInfo.samplingScale;
200             }
201             mirroredTranslateX_ = mirroredDisplayParams->GetOffsetX();
202             mirroredTranslateY_ = mirroredDisplayParams->GetOffsetY();
203             isMirroredDisplayRotating_ = mirroredDisplayParams->IsRotationChanged();
204         }
205     }
206     return true;
207 }
208 
CanvasInit(DrawableV2::RSLogicalDisplayRenderNodeDrawable & displayDrawable)209 void RSUniRenderVirtualProcessor::CanvasInit(DrawableV2::RSLogicalDisplayRenderNodeDrawable& displayDrawable)
210 {
211     // Save the initial canvas state
212     canvas_->Save();
213     if (displayDrawable.IsFirstTimeToProcessor() || canvasRotation_ || autoBufferRotation_) {
214         if (displayDrawable.IsFirstTimeToProcessor()) {
215             RS_LOGI("RSUniRenderVirtualProcessor::FirstInit, id: %{public}" PRIu64 ", "
216                 "screen(%{public}f, %{public}f, %{public}f, %{public}f), "
217                 "rotation: %{public}d, correction: %{public}d, needRotation: %{public}d, scaleMode: %{public}d, "
218                 "autoBufferRotation: %{public}d", virtualScreenId_, virtualScreenWidth_, virtualScreenHeight_,
219                 mirroredScreenWidth_, mirroredScreenHeight_, screenRotation_, screenCorrection_, canvasRotation_,
220                 scaleMode_, autoBufferRotation_);
221         }
222         displayDrawable.SetOriginScreenRotation(screenRotation_);
223     }
224     auto rotationDiff =
225         static_cast<int>(displayDrawable.GetOriginScreenRotation()) - static_cast<int>(screenCorrection_);
226     auto rotationAngle = static_cast<ScreenRotation>((rotationDiff + SCREEN_ROTATION_NUM) % SCREEN_ROTATION_NUM);
227     OriginScreenRotation(rotationAngle, renderFrameConfig_.width, renderFrameConfig_.height);
228 
229     RS_LOGD("RSUniRenderVirtualProcessor::CanvasInit, id: %{public}" PRIu64 ", "
230         "screen(%{public}f, %{public}f, %{public}f, %{public}f), "
231         "rotation: %{public}d, correction: %{public}d, needRotation: %{public}d, rotationAngle: %{public}d, "
232         "scaleMode: %{public}d, autoBufferRotation: %{public}d",
233         virtualScreenId_, virtualScreenWidth_, virtualScreenHeight_, mirroredScreenWidth_, mirroredScreenHeight_,
234         screenRotation_, screenCorrection_, canvasRotation_, rotationAngle, scaleMode_, autoBufferRotation_);
235 }
236 
GetBufferAge() const237 int32_t RSUniRenderVirtualProcessor::GetBufferAge() const
238 {
239     if (renderFrame_ == nullptr) {
240         RS_LOGE("RSUniRenderVirtualProcessor::GetBufferAge renderFrame_ is null.");
241         return 0;
242     }
243     return renderFrame_->GetBufferAge();
244 }
245 
SetColorSpaceForMetadata(GraphicColorGamut colorSpace)246 GSError RSUniRenderVirtualProcessor::SetColorSpaceForMetadata(GraphicColorGamut colorSpace)
247 {
248     if (renderFrame_ == nullptr) {
249         RS_LOGD("RSUniRenderVirtualProcessor::SetColorSpaceForMetadata renderFrame is null.");
250         return GSERROR_INVALID_ARGUMENTS;
251     }
252     auto rsSurface = renderFrame_->GetSurface();
253     if (rsSurface == nullptr) {
254         RS_LOGD("RSUniRenderVirtualProcessor::SetColorSpaceForMetadata surface is null.");
255         return GSERROR_INVALID_ARGUMENTS;
256     }
257     auto buffer = rsSurface->GetCurrentBuffer();
258     if (buffer == nullptr) {
259         RS_LOGD("RSUniRenderVirtualProcessor::SetColorSpaceForMetadata buffer is null.");
260         return GSERROR_NO_BUFFER;
261     }
262     using namespace HDI::Display::Graphic::Common::V1_0;
263     auto iter = COLORSPACE_TYPE.find(colorSpace);
264     if (iter == COLORSPACE_TYPE.end()) {
265         return GSERROR_OK;
266     }
267     CM_ColorSpaceInfo colorSpaceInfo;
268     GSError ret = MetadataHelper::ConvertColorSpaceTypeToInfo(iter->second, colorSpaceInfo);
269     if (ret != GSERROR_OK) {
270         RS_LOGD("RSUniRenderVirtualProcessor::SetColorSpaceForMetadata ConvertColorSpaceTypeToInfo failed.");
271         return ret;
272     }
273     std::vector<uint8_t> colorSpaceVec;
274     if (MetadataHelper::ConvertMetadataToVec(colorSpaceInfo, colorSpaceVec) != GSERROR_OK) {
275         RS_LOGD("RSUniRenderVirtualProcessor::SetColorSpaceForMetadata ConvertMetadataToVec failed.");
276         return GSERROR_API_FAILED;
277     }
278     return buffer->SetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceVec);
279 }
280 
SetDirtyInfo(const std::vector<RectI> & damageRegion)281 void RSUniRenderVirtualProcessor::SetDirtyInfo(const std::vector<RectI>& damageRegion)
282 {
283     if (renderFrame_ == nullptr) {
284         RS_LOGW("RSUniRenderVirtualProcessor::SetDirtyInfo renderFrame_ is null.");
285         return;
286     }
287     renderFrame_->SetDamageRegion(damageRegion);
288     if (SetRoiRegionToCodec(damageRegion) != GSERROR_OK) {
289         RS_LOGD("RSUniRenderVirtualProcessor::SetDirtyInfo SetRoiRegionToCodec failed.");
290     }
291 }
292 
SetRoiRegionToCodec(const std::vector<RectI> & damageRegion)293 GSError RSUniRenderVirtualProcessor::SetRoiRegionToCodec(const std::vector<RectI>& damageRegion)
294 {
295     if (renderFrame_ == nullptr) {
296         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec renderFrame is null.");
297         return GSERROR_INVALID_ARGUMENTS;
298     }
299 
300     auto& rsSurface = renderFrame_->GetSurface();
301     if (rsSurface == nullptr) {
302         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec surface is null.");
303         return GSERROR_INVALID_ARGUMENTS;
304     }
305 
306     auto buffer = rsSurface->GetCurrentBuffer();
307     if (buffer == nullptr) {
308         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec buffer is null, not support get surfacebuffer.");
309         return GSERROR_NO_BUFFER;
310     }
311 
312     RoiRegions roiRegions;
313     const RectI screenRect{0, 0, originalVirtualScreenWidth_, originalVirtualScreenHeight_};
314     if (damageRegion.size() <= ROI_REGIONS_MAX_CNT) {
315         for (auto rect : damageRegion) {
316             rect = rect.IntersectRect(screenRect);
317             if (!rect.IsEmpty()) {
318                 RoiRegionInfo region = RoiRegionInfo{rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()};
319                 roiRegions.regions[roiRegions.regionCnt++] = region;
320             }
321         }
322     } else {
323         RectI mergedRect;
324         for (auto& rect : damageRegion) {
325             mergedRect = mergedRect.JoinRect(rect);
326         }
327         mergedRect = mergedRect.IntersectRect(screenRect);
328         if (!mergedRect.IsEmpty()) {
329             RoiRegionInfo region = RoiRegionInfo{mergedRect.GetLeft(), mergedRect.GetTop(),
330                 mergedRect.GetWidth(), mergedRect.GetHeight()};
331             roiRegions.regions[roiRegions.regionCnt++] = region;
332         }
333     }
334 
335     std::vector<uint8_t> roiRegionsVec;
336     auto ret = MetadataHelper::ConvertMetadataToVec(roiRegions, roiRegionsVec);
337     if (ret != GSERROR_OK) {
338         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec ConvertMetadataToVec failed.");
339         return ret;
340     }
341     return buffer->SetMetadata(GrallocBufferAttr::GRALLOC_BUFFER_ATTR_BUFFER_ROI_INFO, roiRegionsVec);
342 }
343 
OriginScreenRotation(ScreenRotation screenRotation,float width,float height)344 void RSUniRenderVirtualProcessor::OriginScreenRotation(ScreenRotation screenRotation, float width, float height)
345 {
346     if (screenRotation == ScreenRotation::ROTATION_0) {
347         return;
348     } else if (screenRotation == ScreenRotation::ROTATION_90) {
349         canvas_->Translate(width / 2.0f, height / 2.0f);
350         canvas_->Rotate(90, 0, 0); // 90 degrees
351         canvas_->Translate(-(height / 2.0f), -(width / 2.0f));
352     } else if (screenRotation == ScreenRotation::ROTATION_180) {
353         canvas_->Rotate(180, width / 2.0f, height / 2.0f); // 180 degrees
354     } else if (screenRotation == ScreenRotation::ROTATION_270) {
355         canvas_->Translate(width / 2.0f, height / 2.0f);
356         canvas_->Rotate(270, 0, 0); // 270 degrees
357         canvas_->Translate(-(height / 2.0f), -(width / 2.0f));
358     }
359 }
360 
CalculateTransform(ScreenRotation rotation)361 void RSUniRenderVirtualProcessor::CalculateTransform(ScreenRotation rotation)
362 {
363     if (canvas_ == nullptr) {
364         RS_LOGE("RSUniRenderVirtualProcessor::CalculateTransform: Canvas is null!");
365         return;
366     }
367 
368     canvas_->Save();
369     ScaleMirrorIfNeed(rotation, *canvas_);
370     canvasMatrix_ = canvas_->GetTotalMatrix();
371 }
372 
ScaleMirrorIfNeed(const ScreenRotation angle,RSPaintFilterCanvas & canvas)373 void RSUniRenderVirtualProcessor::ScaleMirrorIfNeed(const ScreenRotation angle, RSPaintFilterCanvas& canvas)
374 {
375     if (screenCorrection_ == ScreenRotation::ROTATION_90 ||
376         screenCorrection_ == ScreenRotation::ROTATION_270) {
377         std::swap(virtualScreenWidth_, virtualScreenHeight_);
378     }
379 
380     if (angle == ScreenRotation::ROTATION_90 ||
381         angle == ScreenRotation::ROTATION_270) {
382         std::swap(virtualScreenWidth_, virtualScreenHeight_);
383     }
384 
385     float mirroredScreenWidth = mirroredScreenWidth_;
386     float mirroredScreenHeight = mirroredScreenHeight_;
387     if (enableVisibleRect_) {
388         mirroredScreenWidth = visibleRect_.GetWidth();
389         mirroredScreenHeight = visibleRect_.GetHeight();
390         if (mirroredScreenWidth < EPSILON || mirroredScreenHeight < EPSILON) {
391             RS_LOGE("RSUniRenderVirtualProcessor::ScaleMirrorIfNeed, input is illegal.");
392             return;
393         }
394     }
395 
396     RS_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::ScaleMirrorIfNeed:(%f, %f, %f, %f), "
397         "screenCorrection:%d, oriRotation:%d, scaleMode_: %d",
398         mirroredScreenWidth, mirroredScreenHeight, virtualScreenWidth_, virtualScreenHeight_,
399         static_cast<int>(screenCorrection_), static_cast<int>(angle), static_cast<int>(scaleMode_));
400 
401     bool needScale = ROSEN_NE(mirroredScreenWidth, virtualScreenWidth_) ||
402                      ROSEN_NE(mirroredScreenHeight, virtualScreenHeight_);
403     if (needScale) {
404         if (scaleMode_ == ScreenScaleMode::FILL_MODE) {
405             Fill(canvas, mirroredScreenWidth, mirroredScreenHeight, virtualScreenWidth_, virtualScreenHeight_);
406         } else if (scaleMode_ == ScreenScaleMode::UNISCALE_MODE) {
407             UniScale(canvas, mirroredScreenWidth, mirroredScreenHeight, virtualScreenWidth_, virtualScreenHeight_);
408         }
409     }
410 
411     if (enableVisibleRect_) {
412         if (!drawMirrorCopy_) {
413             canvas.Translate(-visibleRect_.GetLeft(), -visibleRect_.GetTop());
414         }
415         RS_LOGD("RSUniRenderVirtualProcessor::ScaleMirrorIfNeed: Scale With VisibleRect, "
416             "mirrorScaleX_: %{public}f, mirrorScaleY_: %{public}f", mirrorScaleX_, mirrorScaleY_);
417     } else {
418         canvas.Translate(-mirroredTranslateX_, -mirroredTranslateY_);
419     }
420 }
421 
MergeFenceForHardwareEnabledDrawables()422 void RSUniRenderVirtualProcessor::MergeFenceForHardwareEnabledDrawables()
423 {
424     auto& renderThreadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
425     if (!renderThreadParams) {
426         RS_LOGE("RSUniRenderVirtualProcessor::%{public}s renderThreadParams null!", __func__);
427         return;
428     }
429     if (renderFrame_ == nullptr) {
430         RS_LOGE("RSUniRenderVirtualProcessor::%{public}s renderFrame_ null!", __func__);
431         return;
432     }
433     auto acquireFence = renderFrame_->GetAcquireFence();
434     if (!acquireFence || !acquireFence->IsValid()) {
435         RS_LOGE("RSUniRenderVirtualProcessor::%{public}s acquireFence not valid!", __func__);
436         return;
437     }
438     for (const auto& [_, __, drawable] : renderThreadParams->GetHardwareEnabledTypeDrawables()) {
439         if (!drawable) {
440             RS_LOGW("RSUniRenderVirtualProcessor::%{public}s drawable null!", __func__);
441             continue;
442         }
443         auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSScreenRenderNodeDrawable>(drawable);
444         auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetRenderParams().get());
445         if (!surfaceParams) {
446             RS_LOGW("RSUniRenderVirtualProcessor::%{public}s surfaceParams null!", __func__);
447             continue;
448         }
449         auto buffer = surfaceParams->GetBuffer();
450         if (!buffer) {
451             RS_LOGI("RSUniRenderVirtualProcessor::%{public}s buffer null!", __func__);
452             continue;
453         }
454         if (surfaceParams->GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
455             continue; // skip protected layer
456         }
457         RS_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::%s: fence merged id: %" PRIu64 " name: %s",
458             __func__, surfaceParams->GetId(), surfaceParams->GetName().c_str());
459         RS_LOGD("RSUniRenderVirtualProcessor::%{public}s: fence merged id: %{public}" PRIu64 " name: %{public}s",
460             __func__, surfaceParams->GetId(), surfaceParams->GetName().c_str());
461         buffer->SetAndMergeSyncFence(acquireFence);
462     }
463 }
464 
PostProcess()465 void RSUniRenderVirtualProcessor::PostProcess()
466 {
467     if (renderFrame_ == nullptr || renderEngine_ == nullptr) {
468         RS_LOGE("RSUniRenderVirtualProcessor::PostProcess renderFrame or renderEngine is nullptr");
469         return;
470     }
471     auto surfaceOhos = renderFrame_->GetSurface();
472     RSBaseRenderEngine::SetUiTimeStamp(renderFrame_, surfaceOhos);
473     renderFrame_->Flush();
474     // Merge virtual screen fence to hardware enabled drawables, preventing buffer from being released too early.
475     MergeFenceForHardwareEnabledDrawables();
476     RS_LOGD("RSUniRenderVirtualProcessor::PostProcess, FlushFrame succeed.");
477     RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::PostProcess, FlushFrame succeed.");
478 }
479 
ProcessSurface(RSSurfaceRenderNode & node)480 void RSUniRenderVirtualProcessor::ProcessSurface(RSSurfaceRenderNode& node)
481 {
482     (void)node;
483     RS_LOGI("RSUniRenderVirtualProcessor::ProcessSurface() is not supported.");
484 }
485 
ProcessScreenSurfaceForRenderThread(DrawableV2::RSScreenRenderNodeDrawable & screenDrawable)486 void RSUniRenderVirtualProcessor::ProcessScreenSurfaceForRenderThread(
487     DrawableV2::RSScreenRenderNodeDrawable& screenDrawable)
488 {
489     if (!isMirror_) {
490         return;
491     }
492     auto surfaceHandler = screenDrawable.GetRSSurfaceHandlerOnDraw();
493     if (canvas_ == nullptr || surfaceHandler->GetBuffer() == nullptr) {
494         RS_LOGE("RSUniRenderVirtualProcessor::ProcessScreenSurface: Canvas or buffer is null!");
495         return;
496     }
497     auto params = RSUniRenderUtil::CreateBufferDrawParam(*surfaceHandler, forceCPU_);
498     if (renderEngine_ == nullptr) {
499         return;
500     }
501     params.isMirror = true;
502     if (enableVisibleRect_) {
503         params.srcRect = visibleRect_;
504         params.dstRect = Drawing::Rect(0, 0, visibleRect_.GetWidth(), visibleRect_.GetHeight());
505     }
506     renderEngine_->DrawScreenNodeWithParams(*canvas_, *surfaceHandler, params);
507     canvas_->Restore();
508 }
509 
Fill(RSPaintFilterCanvas & canvas,float mainWidth,float mainHeight,float mirrorWidth,float mirrorHeight)510 void RSUniRenderVirtualProcessor::Fill(RSPaintFilterCanvas& canvas,
511     float mainWidth, float mainHeight, float mirrorWidth, float mirrorHeight)
512 {
513     if (mainWidth > 0 && mainHeight > 0) {
514         mirrorScaleX_ = mirrorWidth / mainWidth;
515         mirrorScaleY_ = mirrorHeight / mainHeight;
516         canvas.Scale(mirrorScaleX_, mirrorScaleY_);
517     }
518 }
519 
UniScale(RSPaintFilterCanvas & canvas,float mainWidth,float mainHeight,float mirrorWidth,float mirrorHeight)520 void RSUniRenderVirtualProcessor::UniScale(RSPaintFilterCanvas& canvas,
521     float mainWidth, float mainHeight, float mirrorWidth, float mirrorHeight)
522 {
523     if (ROSEN_LE(mainWidth, 0) || ROSEN_LE(mainHeight, 0) || ROSEN_LE(mirrorWidth, 0) || ROSEN_LE(mirrorHeight, 0)) {
524         return;
525     }
526     float startX = 0.0f;
527     float startY = 0.0f;
528     mirrorScaleX_ = mirrorWidth / mainWidth;
529     mirrorScaleY_ = mirrorHeight / mainHeight;
530     if (mirrorScaleY_ < mirrorScaleX_) {
531         mirrorScaleX_ = mirrorScaleY_;
532         startX = (mirrorWidth / mirrorScaleX_ - mainWidth) / 2; // 2 for calc X
533     } else {
534         mirrorScaleY_ = mirrorScaleX_;
535         startY = (mirrorHeight / mirrorScaleY_ - mainHeight) / 2; // 2 for calc Y
536     }
537 
538     if (EnableSlrScale() && !isMirroredDisplayRotating_) {
539         if (slrManager_ == nullptr) {
540             slrManager_ = std::make_shared<RSSLRScaleFunction>(virtualScreenWidth_, virtualScreenHeight_,
541                 mirroredScreenWidth_, mirroredScreenHeight_);
542         } else {
543             slrManager_->CheckOrRefreshScreen(virtualScreenWidth_, virtualScreenHeight_,
544                 mirroredScreenWidth_, mirroredScreenHeight_);
545         }
546         slrManager_->CheckOrRefreshColorSpace(renderFrameConfig_.colorGamut);
547         slrManager_->CanvasScale(canvas);
548         RS_LOGD("RSUniRenderVirtualProcessor::UniScale: Scale With SLR, color is %{public}d.",
549             renderFrameConfig_.colorGamut);
550         return;
551     }
552 
553     canvas.Scale(mirrorScaleX_, mirrorScaleY_);
554     canvas.Translate(startX, startY);
555     RS_LOGD("RSUniRenderVirtualProcessor::UniScale: Translate startX: %{public}f, startY: %{public}f", startX, startY);
556 }
557 
EnableSlrScale()558 bool RSUniRenderVirtualProcessor::EnableSlrScale()
559 {
560     float slrScale = std::min(mirrorScaleX_, mirrorScaleY_);
561     if (MultiScreenParam::IsSlrScaleEnabled() && RSSystemProperties::GetSLRScaleEnabled() &&
562         (slrScale < SLR_SCALE_THR_HIGH) && !enableVisibleRect_ && drawMirrorCopy_) {
563         return true;
564     }
565     return false;
566 }
567 
ProcessCacheImage(Drawing::Image & cacheImage)568 void RSUniRenderVirtualProcessor::ProcessCacheImage(Drawing::Image& cacheImage)
569 {
570     if (canvas_ == nullptr) {
571         RS_LOGE("RSUniRenderVirtualProcessor::ProcessCacheImage: Canvas is null!");
572         return;
573     }
574     if (EnableSlrScale() && slrManager_) {
575         slrManager_->ProcessCacheImage(*canvas_, cacheImage);
576         RS_LOGD("RSUniRenderVirtualProcessor::ProcessCacheImage: Darw With SLR.");
577         return;
578     }
579     RSUniRenderUtil::ProcessCacheImage(*canvas_, cacheImage);
580 }
581 
CanvasClipRegionForUniscaleMode(const Drawing::Matrix & visibleClipRectMatrix,const ScreenInfo & mainScreenInfo)582 void RSUniRenderVirtualProcessor::CanvasClipRegionForUniscaleMode(const Drawing::Matrix& visibleClipRectMatrix,
583     const ScreenInfo& mainScreenInfo)
584 {
585     if (canvas_ == nullptr) {
586         RS_LOGE("RSUniRenderVirtualProcessor::CanvasClipRegion: Canvas is null!");
587         return;
588     }
589     if (scaleMode_ != ScreenScaleMode::UNISCALE_MODE) {
590         return;
591     }
592     Drawing::Rect rect(mirroredTranslateX_, mirroredTranslateY_,
593         mirroredTranslateX_ + mirroredScreenWidth_, mirroredTranslateY_ + mirroredScreenHeight_);
594     // SLR scaling does not scale canvas, get scale matrix from slrManager_ if SLR scaling is enabled.
595     auto matrix = EnableSlrScale() && slrManager_ ? slrManager_->GetScaleMatrix() : canvas_->GetTotalMatrix();
596     if (enableVisibleRect_) {
597         if (drawMirrorCopy_) {
598             rect = Drawing::Rect(0, 0, visibleRect_.GetWidth(), visibleRect_.GetHeight());
599         } else {
600             rect = visibleRect_;
601             if (mainScreenInfo.isSamplingOn && !RSSystemProperties::GetSLRScaleEnabled()) {
602                 // If SLR scaling is not enabled, apply visibleClipRectMatrix to rect to exclude sampling operation.
603                 matrix = visibleClipRectMatrix;
604             }
605         }
606     }
607     matrix.MapRect(rect, rect);
608     Drawing::RectI rectI = {rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()};
609     Drawing::Region clipRegion;
610     clipRegion.SetRect(rectI);
611     canvas_->ClipRegion(clipRegion);
612     RS_LOGD("RSUniRenderVirtualProcessor::CanvasClipRegionForUniscaleMode, clipRect: %{public}s",
613         rectI.ToString().c_str());
614 }
615 
ProcessRcdSurface(RSRcdSurfaceRenderNode & node)616 void RSUniRenderVirtualProcessor::ProcessRcdSurface(RSRcdSurfaceRenderNode& node)
617 {
618     RS_LOGI("RSUniRenderVirtualProcessor::ProcessRcdSurface() is not supported.");
619 }
620 
CheckIfBufferSizeNeedChange(ScreenRotation firstBufferRotation,ScreenRotation curBufferRotation)621 bool RSUniRenderVirtualProcessor::CheckIfBufferSizeNeedChange(
622     ScreenRotation firstBufferRotation, ScreenRotation curBufferRotation)
623 {
624     auto rotationDiff = static_cast<int>(firstBufferRotation) - static_cast<int>(curBufferRotation);
625     return rotationDiff % 2;    // %2, If the difference is odd, buffer's width and height need a swap.
626 }
627 
SetVirtualScreenSize(DrawableV2::RSScreenRenderNodeDrawable & screenNodeDrawble,const sptr<RSScreenManager> & screenManager)628 void RSUniRenderVirtualProcessor::SetVirtualScreenSize(
629     DrawableV2::RSScreenRenderNodeDrawable& screenNodeDrawble, const sptr<RSScreenManager>& screenManager)
630 {
631     auto virtualScreenInfo = screenManager->QueryScreenInfo(virtualScreenId_);
632     autoBufferRotation_ = screenManager->GetVirtualScreenAutoRotation(virtualScreenId_);
633     if (autoBufferRotation_) {
634         auto rotationDiff = static_cast<int>(screenRotation_) - static_cast<int>(screenCorrection_);
635         auto curBufferRotation =
636             static_cast<ScreenRotation>((rotationDiff + SCREEN_ROTATION_NUM) % SCREEN_ROTATION_NUM);
637         ScreenRotation firstBufferRotation = screenNodeDrawble.GetFirstBufferRotation();
638         if (firstBufferRotation == ScreenRotation::INVALID_SCREEN_ROTATION) {
639             screenNodeDrawble.SetFirstBufferRotation(curBufferRotation);
640             RS_LOGI("RSUniRenderVirtualProcessor::%{public}s, set firstBufferRotation: %{public}d,"
641                 "width: %{public}" PRIu32 ", height: %{public}" PRIu32, __func__, static_cast<int>(curBufferRotation),
642                 renderFrameConfig_.width, renderFrameConfig_.height);
643         } else if (CheckIfBufferSizeNeedChange(firstBufferRotation, curBufferRotation)) {
644             std::swap(renderFrameConfig_.width, renderFrameConfig_.height);
645             std::swap(virtualScreenInfo.width, virtualScreenInfo.height);
646             RS_LOGI("RSUniRenderVirtualProcessor::%{public}s, swap buffer width and height, width: %{public}" PRIu32
647                 ", height: %{public}" PRIu32, __func__, renderFrameConfig_.width, renderFrameConfig_.height);
648             RS_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::%s: swap buffer width and height, "
649                 "width: %" PRIu32 "height: %" PRIu32, __func__, renderFrameConfig_.width, renderFrameConfig_.height);
650         }
651     }
652 
653     virtualScreenWidth_ = static_cast<float>(virtualScreenInfo.width);
654     virtualScreenHeight_ = static_cast<float>(virtualScreenInfo.height);
655     originalVirtualScreenWidth_ = virtualScreenWidth_;
656     originalVirtualScreenHeight_ = virtualScreenHeight_;
657 }
658 } // namespace Rosen
659 } // namespace OHOS
660