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