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