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 
23 #include "common/rs_optional_trace.h"
24 #include "drawable/rs_display_render_node_drawable.h"
25 #include "platform/common/rs_log.h"
26 #ifndef NEW_RENDER_CONTEXT
27 #include "platform/ohos/backend/rs_surface_frame_ohos_raster.h"
28 #endif
29 #include "pipeline/rs_uni_render_util.h"
30 #include "pipeline/rs_main_thread.h"
31 #include "string_utils.h"
32 
33 namespace OHOS {
34 namespace Rosen {
InitForRenderThread(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,ScreenId mirroredId,std::shared_ptr<RSBaseRenderEngine> renderEngine)35 bool RSUniRenderVirtualProcessor::InitForRenderThread(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
36     ScreenId mirroredId, std::shared_ptr<RSBaseRenderEngine> renderEngine)
37 {
38     if (!RSProcessor::InitForRenderThread(displayDrawable, mirroredId, renderEngine)) {
39         return false;
40     }
41 
42     // Do expand screen if the mirror id is invalid.
43     isExpand_ = (mirroredId == INVALID_SCREEN_ID);
44     auto screenManager = CreateOrGetScreenManager();
45     if (screenManager == nullptr) {
46         return false;
47     }
48     auto& params = displayDrawable.GetRenderParams();
49     if (!params) {
50         return false;
51     }
52     virtualScreenId_ = params->GetScreenId();
53     auto virtualScreenInfo = screenManager->QueryScreenInfo(virtualScreenId_);
54     canvasRotation_ = screenManager->GetCanvasRotation(virtualScreenId_);
55     scaleMode_ = screenManager->GetScaleMode(virtualScreenId_);
56     virtualScreenWidth_ = static_cast<float>(virtualScreenInfo.width);
57     virtualScreenHeight_ = static_cast<float>(virtualScreenInfo.height);
58     originalVirtualScreenWidth_ = virtualScreenWidth_;
59     originalVirtualScreenHeight_ = virtualScreenHeight_;
60     auto mirroredDisplayDrawable =
61         std::static_pointer_cast<DrawableV2::RSDisplayRenderNodeDrawable>(params->GetMirrorSourceDrawable().lock());
62     if (mirroredDisplayDrawable) {
63         auto& mirroredParams = mirroredDisplayDrawable->GetRenderParams();
64         if (mirroredParams) {
65             screenRotation_ = mirroredParams->GetScreenRotation();
66             screenCorrection_ = screenManager->GetScreenCorrection(mirroredParams->GetScreenId());
67             auto mainScreenInfo = screenManager->QueryScreenInfo(mirroredParams->GetScreenId());
68             mirroredScreenWidth_ = static_cast<float>(mainScreenInfo.width);
69             mirroredScreenHeight_ = static_cast<float>(mainScreenInfo.height);
70         }
71     }
72 
73     renderFrameConfig_.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA;
74     FrameContextConfig frameContextConfig = {false, false};
75     frameContextConfig.isVirtual = true;
76     frameContextConfig.timeOut = 0;
77 
78     producerSurface_ = screenManager->GetProducerSurface(virtualScreenId_);
79     if (producerSurface_ == nullptr) {
80         RS_LOGE("RSUniRenderVirtualProcessor::Init for Screen(id %{public}" PRIu64 "): ProducerSurface is null!",
81             virtualScreenId_);
82         return false;
83     }
84 #ifdef RS_ENABLE_GL
85     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
86         renderFrame_ = renderEngine_->RequestFrame(producerSurface_, renderFrameConfig_, forceCPU_, false,
87             frameContextConfig);
88     }
89 #endif
90     if (renderFrame_ == nullptr) {
91         uint64_t pSurfaceUniqueId = producerSurface_->GetUniqueId();
92         auto rsSurface = displayDrawable.GetVirtualSurface(pSurfaceUniqueId);
93         if (rsSurface == nullptr || screenManager->GetAndResetVirtualSurfaceUpdateFlag(virtualScreenId_)) {
94             RS_LOGD("RSUniRenderVirtualProcessor::Init Make rssurface from producer Screen(id %{public}" PRIu64 ")",
95                 virtualScreenId_);
96             RS_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::Init Make rssurface from producer Screen(id %" PRIu64 ")",
97                 virtualScreenId_);
98             rsSurface = renderEngine_->MakeRSSurface(producerSurface_, forceCPU_);
99             displayDrawable.SetVirtualSurface(rsSurface, pSurfaceUniqueId);
100         }
101 #ifdef NEW_RENDER_CONTEXT
102         renderFrame_ = renderEngine_->RequestFrame(
103             std::static_pointer_cast<RSRenderSurfaceOhos>(rsSurface), renderFrameConfig_, forceCPU_, false,
104             frameContextConfig);
105 #else
106         renderFrame_ = renderEngine_->RequestFrame(
107             std::static_pointer_cast<RSSurfaceOhos>(rsSurface), renderFrameConfig_, forceCPU_, false,
108             frameContextConfig);
109 #endif
110     }
111     if (renderFrame_ == nullptr) {
112         RS_LOGE("RSUniRenderVirtualProcessor::Init for Screen(id %{public}" PRIu64 "): RenderFrame is null!",
113             virtualScreenId_);
114         return false;
115     }
116 
117     RS_LOGD("RSUniRenderVirtualProcessor::Init, RequestFrame succeed.");
118     RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::Init, RequestFrame succeed.");
119 
120     canvas_ = renderFrame_->GetCanvas();
121     if (canvas_ == nullptr) {
122         RS_LOGE("RSUniRenderVirtualProcessor::Init for Screen(id %{public}" PRIu64 "): Canvas is null!",
123             virtualScreenId_);
124         return false;
125     }
126 
127     CanvasInit(displayDrawable);
128 
129     return true;
130 }
131 
CanvasInit(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable)132 void RSUniRenderVirtualProcessor::CanvasInit(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable)
133 {
134     // Save the initial canvas state
135     canvas_->Save();
136     // displayDrawable.GetRenderParams() not null in caller
137     if (displayDrawable.IsFirstTimeToProcessor() || canvasRotation_) {
138         if (displayDrawable.IsFirstTimeToProcessor()) {
139             RS_LOGI("RSUniRenderVirtualProcessor::FirstInit, id: %{public}" PRIu64 ", "
140                 "screen(%{public}f, %{public}f, %{public}f, %{public}f), "
141                 "rotation: %{public}d, correction: %{public}d, needRotation: %{public}d, scaleMode: %{public}d",
142                 displayDrawable.GetRenderParams()->GetScreenId(), virtualScreenWidth_, virtualScreenHeight_,
143                 mirroredScreenWidth_, mirroredScreenHeight_, screenRotation_, screenCorrection_, canvasRotation_,
144                 scaleMode_);
145         }
146         displayDrawable.SetOriginScreenRotation(screenRotation_);
147     }
148     auto rotationDiff =
149         static_cast<int>(displayDrawable.GetOriginScreenRotation()) - static_cast<int>(screenCorrection_);
150     auto rotationAngle = static_cast<ScreenRotation>((rotationDiff + SCREEN_ROTATION_NUM) % SCREEN_ROTATION_NUM);
151     OriginScreenRotation(rotationAngle, renderFrameConfig_.width, renderFrameConfig_.height);
152 
153     RS_LOGD("RSUniRenderVirtualProcessor::CanvasInit, id: %{public}" PRIu64 ", "
154             "screen(%{public}f, %{public}f, %{public}f, %{public}f), "
155             "rotation: %{public}d, correction: %{public}d, needRotation: %{public}d, rotationAngle: %{public}d",
156         displayDrawable.GetRenderParams()->GetScreenId(), virtualScreenWidth_, virtualScreenHeight_,
157         mirroredScreenWidth_, mirroredScreenHeight_, screenRotation_, screenCorrection_, canvasRotation_,
158         rotationAngle);
159 }
160 
GetBufferAge() const161 int32_t RSUniRenderVirtualProcessor::GetBufferAge() const
162 {
163     if (renderFrame_ == nullptr) {
164         RS_LOGE("RSUniRenderVirtualProcessor::GetBufferAge renderFrame_ is null.");
165         return 0;
166     }
167     return renderFrame_->GetBufferAge();
168 }
169 
SetDirtyInfo(std::vector<RectI> & damageRegion)170 void RSUniRenderVirtualProcessor::SetDirtyInfo(std::vector<RectI>& damageRegion)
171 {
172     if (renderFrame_ == nullptr) {
173         RS_LOGW("RSUniRenderVirtualProcessor::SetDirtyInfo renderFrame_ is null.");
174         return;
175     }
176     renderFrame_->SetDamageRegion(damageRegion);
177     if (SetRoiRegionToCodec(damageRegion) != GSERROR_OK) {
178         RS_LOGD("RSUniRenderVirtualProcessor::SetDirtyInfo SetRoiRegionToCodec failed.");
179     }
180 }
181 
SetRoiRegionToCodec(std::vector<RectI> & damageRegion)182 GSError RSUniRenderVirtualProcessor::SetRoiRegionToCodec(std::vector<RectI>& damageRegion)
183 {
184     auto& rsSurface = renderFrame_->GetSurface();
185     if (rsSurface == nullptr) {
186         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec surface is null.");
187         return GSERROR_INVALID_ARGUMENTS;
188     }
189 
190     auto buffer = rsSurface->GetCurrentBuffer();
191     if (buffer == nullptr) {
192         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec buffer is null, not support get surfacebuffer.");
193         return GSERROR_NO_BUFFER;
194     }
195 
196     RoiRegions roiRegions;
197     const RectI screenRect{0, 0, originalVirtualScreenWidth_, originalVirtualScreenHeight_};
198     if (damageRegion.size() <= ROI_REGIONS_MAX_CNT) {
199         for (auto rect : damageRegion) {
200             rect = rect.IntersectRect(screenRect);
201             if (!rect.IsEmpty()) {
202                 RoiRegionInfo region = RoiRegionInfo{rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()};
203                 roiRegions.regions[roiRegions.regionCnt++] = region;
204             }
205         }
206     } else {
207         RectI mergedRect;
208         for (auto& rect : damageRegion) {
209             mergedRect = mergedRect.JoinRect(rect);
210         }
211         mergedRect = mergedRect.IntersectRect(screenRect);
212         if (!mergedRect.IsEmpty()) {
213             RoiRegionInfo region = RoiRegionInfo{mergedRect.GetLeft(), mergedRect.GetTop(),
214                 mergedRect.GetWidth(), mergedRect.GetHeight()};
215             roiRegions.regions[roiRegions.regionCnt++] = region;
216         }
217     }
218 
219     std::vector<uint8_t> roiRegionsVec;
220     auto ret = MetadataHelper::ConvertMetadataToVec(roiRegions, roiRegionsVec);
221     if (ret != GSERROR_OK) {
222         RS_LOGD("RSUniRenderVirtualProcessor::SetRoiRegionToCodec ConvertMetadataToVec failed.");
223         return ret;
224     }
225     return buffer->SetMetadata(GrallocBufferAttr::GRALLOC_BUFFER_ATTR_BUFFER_ROI_INFO, roiRegionsVec);
226 }
227 
OriginScreenRotation(ScreenRotation screenRotation,float width,float height)228 void RSUniRenderVirtualProcessor::OriginScreenRotation(ScreenRotation screenRotation, float width, float height)
229 {
230     if (screenRotation == ScreenRotation::ROTATION_0) {
231         return;
232     } else if (screenRotation == ScreenRotation::ROTATION_90) {
233         canvas_->Translate(width / 2.0f, height / 2.0f);
234         canvas_->Rotate(90, 0, 0); // 90 degrees
235         canvas_->Translate(-(height / 2.0f), -(width / 2.0f));
236     } else if (screenRotation == ScreenRotation::ROTATION_180) {
237         canvas_->Rotate(180, width / 2.0f, height / 2.0f); // 180 degrees
238     } else if (screenRotation == ScreenRotation::ROTATION_270) {
239         canvas_->Translate(width / 2.0f, height / 2.0f);
240         canvas_->Rotate(270, 0, 0); // 270 degrees
241         canvas_->Translate(-(height / 2.0f), -(width / 2.0f));
242     }
243 }
244 
CalculateTransform(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable)245 void RSUniRenderVirtualProcessor::CalculateTransform(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable)
246 {
247     if (canvas_ == nullptr || displayDrawable.GetRSSurfaceHandlerOnDraw()->GetBuffer() == nullptr) {
248         RS_LOGE("RSUniRenderVirtualProcessor::CalculateTransform: Canvas or buffer is null!");
249         return;
250     }
251 
252     canvas_->Save();
253     ScreenRotation angle = displayDrawable.GetOriginScreenRotation();
254     ScaleMirrorIfNeed(angle, *canvas_);
255     canvasMatrix_ = canvas_->GetTotalMatrix();
256 }
257 
ScaleMirrorIfNeed(const ScreenRotation angle,RSPaintFilterCanvas & canvas)258 void RSUniRenderVirtualProcessor::ScaleMirrorIfNeed(const ScreenRotation angle, RSPaintFilterCanvas& canvas)
259 {
260     if (screenCorrection_ == ScreenRotation::ROTATION_90 ||
261         screenCorrection_ == ScreenRotation::ROTATION_270) {
262         std::swap(virtualScreenWidth_, virtualScreenHeight_);
263     }
264 
265     if (angle == ScreenRotation::ROTATION_90 ||
266         angle == ScreenRotation::ROTATION_270) {
267         std::swap(virtualScreenWidth_, virtualScreenHeight_);
268     }
269 
270     RS_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::ScaleMirrorIfNeed:(%f, %f, %f, %f), " \
271         "screenCorrection:%d, oriRotation:%d",
272         mirroredScreenWidth_, mirroredScreenHeight_, virtualScreenWidth_, virtualScreenHeight_,
273         static_cast<int>(screenCorrection_), static_cast<int>(angle));
274 
275     if (mirroredScreenWidth_ == virtualScreenWidth_ && mirroredScreenHeight_ == virtualScreenHeight_) {
276         return;
277     }
278 
279     if (scaleMode_ == ScreenScaleMode::FILL_MODE) {
280         Fill(canvas, mirroredScreenWidth_, mirroredScreenHeight_, virtualScreenWidth_, virtualScreenHeight_);
281     } else if (scaleMode_ == ScreenScaleMode::UNISCALE_MODE) {
282         UniScale(canvas, mirroredScreenWidth_, mirroredScreenHeight_, virtualScreenWidth_, virtualScreenHeight_);
283     }
284 }
285 
PostProcess()286 void RSUniRenderVirtualProcessor::PostProcess()
287 {
288     if (renderFrame_ == nullptr || renderEngine_ == nullptr) {
289         RS_LOGE("RSUniRenderVirtualProcessor::PostProcess renderFrame or renderEngine is nullptr");
290         return;
291     }
292     auto surfaceOhos = renderFrame_->GetSurface();
293     renderEngine_->SetUiTimeStamp(renderFrame_, surfaceOhos);
294     renderFrame_->Flush();
295     RS_LOGD("RSUniRenderVirtualProcessor::PostProcess, FlushFrame succeed.");
296     RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVirtualProcessor::PostProcess, FlushFrame succeed.");
297 }
298 
ProcessSurface(RSSurfaceRenderNode & node)299 void RSUniRenderVirtualProcessor::ProcessSurface(RSSurfaceRenderNode& node)
300 {
301     (void)node;
302     RS_LOGI("RSUniRenderVirtualProcessor::ProcessSurface() is not supported.");
303 }
304 
ProcessDisplaySurfaceForRenderThread(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable)305 void RSUniRenderVirtualProcessor::ProcessDisplaySurfaceForRenderThread(
306     DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable)
307 {
308     if (isExpand_) {
309         return;
310     }
311     auto surfaceHandler = displayDrawable.GetRSSurfaceHandlerOnDraw();
312     if (canvas_ == nullptr || surfaceHandler->GetBuffer() == nullptr) {
313         RS_LOGE("RSUniRenderVirtualProcessor::ProcessDisplaySurface: Canvas or buffer is null!");
314         return;
315     }
316     auto params = RSUniRenderUtil::CreateBufferDrawParam(*surfaceHandler, forceCPU_);
317     if (renderEngine_ == nullptr) {
318         return;
319     }
320     params.isMirror = true;
321     renderEngine_->DrawDisplayNodeWithParams(*canvas_, *surfaceHandler, params);
322     canvas_->Restore();
323 }
324 
Fill(RSPaintFilterCanvas & canvas,float mainWidth,float mainHeight,float mirrorWidth,float mirrorHeight)325 void RSUniRenderVirtualProcessor::Fill(RSPaintFilterCanvas& canvas,
326     float mainWidth, float mainHeight, float mirrorWidth, float mirrorHeight)
327 {
328     if (mainWidth > 0 && mainHeight > 0) {
329         mirrorScaleX_ = mirrorWidth / mainWidth;
330         mirrorScaleY_ = mirrorHeight / mainHeight;
331         canvas.Scale(mirrorScaleX_, mirrorScaleY_);
332     }
333 }
334 
UniScale(RSPaintFilterCanvas & canvas,float mainWidth,float mainHeight,float mirrorWidth,float mirrorHeight)335 void RSUniRenderVirtualProcessor::UniScale(RSPaintFilterCanvas& canvas,
336     float mainWidth, float mainHeight, float mirrorWidth, float mirrorHeight)
337 {
338     if (mainWidth > 0 && mainHeight > 0) {
339         float startX = 0.0f;
340         float startY = 0.0f;
341         mirrorScaleX_ = mirrorWidth / mainWidth;
342         mirrorScaleY_ = mirrorHeight / mainHeight;
343         if (mirrorScaleY_ < mirrorScaleX_) {
344             mirrorScaleX_ = mirrorScaleY_;
345             startX = (mirrorWidth - (mirrorScaleX_ * mainWidth)) / 2; // 2 for calc X
346         } else {
347             mirrorScaleY_ = mirrorScaleX_;
348             startY = (mirrorHeight - (mirrorScaleY_ * mainHeight)) / 2; // 2 for calc Y
349         }
350         canvas.Translate(startX, startY);
351         canvas.Scale(mirrorScaleX_, mirrorScaleY_);
352     }
353 }
354 
CanvasClipRegionForUniscaleMode()355 void RSUniRenderVirtualProcessor::CanvasClipRegionForUniscaleMode()
356 {
357     if (canvas_ == nullptr) {
358         RS_LOGE("RSUniRenderVirtualProcessor::CanvasClipRegion: Canvas is null!");
359         return;
360     }
361     if (scaleMode_ == ScreenScaleMode::UNISCALE_MODE) {
362         Drawing::Rect rect(0, 0, mirroredScreenWidth_, mirroredScreenHeight_);
363         canvas_->GetTotalMatrix().MapRect(rect, rect);
364         Drawing::RectI rectI = {rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom()};
365         Drawing::Region clipRegion;
366         clipRegion.SetRect(rectI);
367         canvas_->ClipRegion(clipRegion);
368     }
369 }
370 
ProcessRcdSurface(RSRcdSurfaceRenderNode & node)371 void RSUniRenderVirtualProcessor::ProcessRcdSurface(RSRcdSurfaceRenderNode& node)
372 {
373     RS_LOGI("RSUniRenderVirtualProcessor::ProcessRcdSurface() is not supported.");
374 }
375 } // namespace Rosen
376 } // namespace OHOS