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