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