• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "pipeline/rs_hardware_thread.h"
17 
18 #include "hgm_core.h"
19 #include "pipeline/rs_base_render_util.h"
20 #include "pipeline/rs_uni_render_util.h"
21 #include "pipeline/rs_main_thread.h"
22 #include "pipeline/rs_uni_render_engine.h"
23 #include "platform/common/rs_log.h"
24 #include "platform/common/rs_system_properties.h"
25 #include "screen_manager/rs_screen_manager.h"
26 #include "rs_trace.h"
27 #include "hdi_backend.h"
28 
29 #ifdef RS_ENABLE_EGLIMAGE
30 #include "rs_egl_image_manager.h"
31 #endif // RS_ENABLE_EGLIMAGE
32 
33 namespace OHOS::Rosen {
Instance()34 RSHardwareThread& RSHardwareThread::Instance()
35 {
36     static RSHardwareThread instance;
37     return instance;
38 }
39 
Start()40 void RSHardwareThread::Start()
41 {
42     RS_LOGI("RSHardwareThread::Start()!");
43     hdiBackend_ = HdiBackend::GetInstance();
44     runner_ = AppExecFwk::EventRunner::Create("RSHardwareThread");
45     handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
46     redrawCb_ = std::bind(&RSHardwareThread::Redraw, this,std::placeholders::_1, std::placeholders::_2,
47         std::placeholders::_3);
48     if (handler_) {
49         ScheduleTask(
50             [this]() {
51                 auto screenManager = CreateOrGetScreenManager();
52                 if (screenManager == nullptr || !screenManager->Init()) {
53                     RS_LOGE("RSHardwareThread CreateOrGetScreenManager or init fail.");
54                     return;
55                 }
56                 uniRenderEngine_ = std::make_shared<RSUniRenderEngine>();
57                 uniRenderEngine_->Init();
58             }).wait();
59     }
60     auto onPrepareCompleteFunc = [this](auto& surface, const auto& param, void* data) {
61         OnPrepareComplete(surface, param, data);
62     };
63     if (hdiBackend_ != nullptr) {
64         hdiBackend_->RegPrepareComplete(onPrepareCompleteFunc, this);
65     }
66 }
67 
PostTask(const std::function<void ()> & task)68 void RSHardwareThread::PostTask(const std::function<void()>& task)
69 {
70     if (handler_) {
71         handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
72     }
73 }
74 
ReleaseBuffer(sptr<SurfaceBuffer> buffer,sptr<SyncFence> releaseFence,sptr<IConsumerSurface> cSurface)75 void RSHardwareThread::ReleaseBuffer(sptr<SurfaceBuffer> buffer, sptr<SyncFence> releaseFence,
76     sptr<IConsumerSurface> cSurface)
77 {
78     if (cSurface == nullptr) {
79         RS_LOGE("RsDebug RSHardwareThread:: ReleaseBuffer failed, no consumer!");
80         return;
81     }
82 
83     if (buffer != nullptr) {
84         RS_TRACE_NAME("RSHardwareThread::ReleaseBuffer");
85         auto ret = cSurface->ReleaseBuffer(buffer, releaseFence);
86         if (ret != OHOS::SURFACE_ERROR_OK) {
87             return;
88         }
89         // reset prevBuffer if we release it successfully,
90         // to avoid releasing the same buffer next frame in some situations.
91         buffer = nullptr;
92         releaseFence = SyncFence::INVALID_FENCE;
93     }
94 }
95 
ReleaseLayers(OutputPtr output,const std::unordered_map<uint32_t,LayerPtr> & layerMap)96 void RSHardwareThread::ReleaseLayers(OutputPtr output, const std::unordered_map<uint32_t, LayerPtr>& layerMap)
97 {
98     // get present timestamp from and set present timestamp to surface
99     for (const auto& [id, layer] : layerMap) {
100         if (layer == nullptr || layer->GetLayerInfo()->GetSurface() == nullptr) {
101             RS_LOGW("RSHardwareThread::ReleaseLayers: layer or layer's cSurface is nullptr");
102             continue;
103         }
104         LayerPresentTimestamp(layer->GetLayerInfo(), layer->GetLayerInfo()->GetSurface());
105     }
106 
107     // set all layers' releaseFence.
108     if (output == nullptr) {
109         RS_LOGE("RSHardwareThread::ReleaseLayers: output is nullptr");
110         return;
111     }
112     const auto layersReleaseFence = output->GetLayersReleaseFence();
113     if (layersReleaseFence.size() == 0) {
114         RS_LOGE("RSHardwareThread::ReleaseLayers: no layer needs to release");
115     }
116     for (const auto& [layer, fence] : layersReleaseFence) {
117         if (layer == nullptr) {
118             continue;
119         }
120         auto preBuffer = layer->GetPreBuffer();
121         auto consumer = layer->GetSurface();
122         ReleaseBuffer(preBuffer, fence, consumer);
123     }
124     RSMainThread::Instance()->NotifyDisplayNodeBufferReleased();
125 }
126 
CommitAndReleaseLayers(OutputPtr output,const std::vector<LayerInfoPtr> & layers)127 void RSHardwareThread::CommitAndReleaseLayers(OutputPtr output, const std::vector<LayerInfoPtr>& layers)
128 {
129     if (!handler_) {
130         RS_LOGE("RSHardwareThread::CommitAndReleaseLayers handler is nullptr");
131         return;
132     }
133     RSTaskMessage::RSTask task = [this, output = output, layers = layers]() {
134         RS_TRACE_NAME("RSHardwareThread::CommitAndReleaseLayers");
135         PerformSetActiveMode();
136         output->SetLayerInfo(layers);
137         hdiBackend_->Repaint(output);
138         auto layerMap = output->GetLayers();
139         ReleaseLayers(output, layerMap);
140     };
141     PostTask(task);
142 }
143 
PerformSetActiveMode()144 void RSHardwareThread::PerformSetActiveMode()
145 {
146     auto &hgmCore = OHOS::Rosen::HgmCore::Instance();
147     auto screenManager = CreateOrGetScreenManager();
148     if (screenManager == nullptr) {
149         RS_LOGE("RSHardwareThread CreateOrGetScreenManager fail.");
150         return;
151     }
152 
153     HgmRefreshRates newRate = RSSystemProperties::GetHgmRefreshRatesEnabled();
154     HgmRefreshRateModes newRateMode = RSSystemProperties::GetHgmRefreshRateModesEnabled();
155     if (hgmRefreshRates_ != newRate) {
156         hgmRefreshRates_ = newRate;
157         hgmCore.SetScreenRefreshRate(screenManager->GetDefaultScreenId(), 0, static_cast<int32_t>(hgmRefreshRates_));
158     }
159     if (hgmRefreshRateModes_ != newRateMode) {
160         hgmRefreshRateModes_ = newRateMode;
161         hgmCore.SetRefreshRateMode(static_cast<RefreshRateMode>(hgmRefreshRateModes_));
162     }
163 
164     if (lockRefreshRateOnce_ == false) {
165         hgmCore.SetDefaultRefreshRateMode();
166         lockRefreshRateOnce_ = true;
167     }
168 
169     std::unique_ptr<std::unordered_map<ScreenId, int32_t>> modeMap(hgmCore.GetModesToApply());
170     if (modeMap == nullptr) {
171         return;
172     }
173 
174     RS_TRACE_NAME("RSHardwareThread::PerformSetActiveMode setting active mode");
175     for (auto mapIter = modeMap->begin(); mapIter != modeMap->end(); ++mapIter) {
176         ScreenId id = mapIter->first;
177         int32_t modeId = mapIter->second;
178 
179         auto supportedModes = screenManager->GetScreenSupportedModes(id);
180         for (auto mode : supportedModes) {
181             std::string temp = "RSHardwareThread check modes w: " + std::to_string(mode.GetScreenWidth()) +
182                 ", h: " + std::to_string(mode.GetScreenHeight()) +
183                 ", rate: " + std::to_string(mode.GetScreenRefreshRate()) +
184                 ", id: " + std::to_string(mode.GetScreenModeId());
185             RS_LOGD(temp.c_str());
186         }
187 
188         screenManager->SetScreenActiveMode(id, modeId);
189     }
190 }
191 
OnPrepareComplete(sptr<Surface> & surface,const PrepareCompleteParam & param,void * data)192 void RSHardwareThread::OnPrepareComplete(sptr<Surface>& surface,
193     const PrepareCompleteParam& param, void* data)
194 {
195     // unused data.
196     (void)(data);
197 
198     if (!param.needFlushFramebuffer) {
199         return;
200     }
201 
202     if (redrawCb_ != nullptr) {
203         redrawCb_(surface, param.layers, param.screenId);
204     }
205 }
206 
Redraw(const sptr<Surface> & surface,const std::vector<LayerInfoPtr> & layers,uint32_t screenId)207 void RSHardwareThread::Redraw(const sptr<Surface>& surface, const std::vector<LayerInfoPtr>& layers, uint32_t screenId)
208 {
209     RS_TRACE_NAME("RSHardwareThread::Redraw");
210     if (surface == nullptr) {
211         RS_LOGE("RSHardwareThread::Redraw: surface is null.");
212         return;
213     }
214 
215     RS_LOGD("RsDebug RSHardwareThread::Redraw flush frame buffer start");
216     bool forceCPU = RSBaseRenderEngine::NeedForceCPU(layers);
217     auto screenManager = CreateOrGetScreenManager();
218     auto screenInfo = screenManager->QueryScreenInfo(screenId);
219     auto renderFrameConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo, true);
220     auto renderFrame = uniRenderEngine_->RequestFrame(surface, renderFrameConfig, forceCPU);
221     if (renderFrame == nullptr) {
222         RS_LOGE("RsDebug RSHardwareThread::Redraw:failed to request frame.");
223         return;
224     }
225     auto canvas = renderFrame->GetCanvas();
226     if (canvas == nullptr) {
227         RS_LOGE("RsDebug RSHardwareThread::Redraw:canvas is nullptr.");
228         return;
229     }
230 #ifdef RS_ENABLE_EGLIMAGE
231     std::unordered_map<int32_t, std::unique_ptr<ImageCacheSeq>> imageCacheSeqs;
232 #endif
233     for (const auto& layer : layers) {
234         if (layer == nullptr) {
235             continue;
236         }
237         if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE ||
238             layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE_CLEAR) {
239             continue;
240         }
241 #ifndef USE_ROSEN_DRAWING
242         auto saveCount = canvas->getSaveCount();
243 
244         canvas->save();
245         auto dstRect = layer->GetLayerSize();
246         SkRect clipRect = SkRect::MakeXYWH(static_cast<float>(dstRect.x), static_cast<float>(dstRect.y),
247             static_cast<float>(dstRect.w), static_cast<float>(dstRect.h));
248         canvas->clipRect(clipRect);
249 
250         // prepare BufferDrawParam
251         auto params = RSUniRenderUtil::CreateLayerBufferDrawParam(layer, forceCPU);
252         canvas->concat(params.matrix);
253 #else
254         auto saveCount = canvas->GetSaveCount();
255 
256         canvas->Save();
257         auto dstRect = layer->GetLayerSize();
258         Drawing::Rect clipRect = Drawing::Rect(static_cast<float>(dstRect.x), static_cast<float>(dstRect.y),
259             static_cast<float>(dstRect.w) + static_cast<float>(dstRect.x),
260             static_cast<float>(dstRect.h) + static_cast<float>(dstRect.y));
261         canvas->ClipRect(clipRect, Drawing::ClipOp::INTERSECT, false);
262 
263         // prepare BufferDrawParam
264         auto params = RSUniRenderUtil::CreateLayerBufferDrawParam(layer, forceCPU);
265         canvas->ConcatMatrix(params.matrix);
266 #endif
267 #ifndef RS_ENABLE_EGLIMAGE
268         uniRenderEngine_->DrawBuffer(*canvas, params);
269 #else
270         if (!params.useCPU) {
271             if (!RSBaseRenderUtil::IsBufferValid(params.buffer)) {
272                 RS_LOGE("RSHardwareThread::Redraw CreateEglImageFromBuffer invalid param!");
273                 continue;
274             }
275 #ifndef USE_ROSEN_DRAWING
276 #ifdef NEW_SKIA
277             if (canvas->recordingContext() == nullptr) {
278 #else
279             if (canvas->getGrContext() == nullptr) {
280 #endif
281 #else
282             if (canvas->GetGPUContext() == nullptr) {
283 #endif
284                 RS_LOGE("RSBaseRenderEngine::CreateEglImageFromBuffer GrContext is null!");
285                 continue;
286             }
287             auto eglImageCache = uniRenderEngine_->GetEglImageManager()->CreateImageCacheFromBuffer(params.buffer,
288                 params.acquireFence);
289             if (eglImageCache == nullptr) {
290                 continue;
291             }
292             auto eglTextureId = eglImageCache->TextureId();
293             if (eglTextureId == 0) {
294                 RS_LOGE("RSHardwareThread::Redraw CreateImageCacheFromBuffer return invalid texture ID");
295                 continue;
296             }
297             auto bufferId = params.buffer->GetSeqNum();
298             imageCacheSeqs[bufferId] = std::move(eglImageCache);
299 #ifndef USE_ROSEN_DRAWING
300             SkColorType colorType = (params.buffer->GetFormat() == GRAPHIC_PIXEL_FMT_BGRA_8888) ?
301                 kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
302             GrGLTextureInfo grExternalTextureInfo = { GL_TEXTURE_EXTERNAL_OES, eglTextureId, GL_RGBA8 };
303             GrBackendTexture backendTexture(params.buffer->GetSurfaceBufferWidth(),
304                 params.buffer->GetSurfaceBufferHeight(), GrMipMapped::kNo, grExternalTextureInfo);
305 #ifdef NEW_SKIA
306             auto image = SkImage::MakeFromTexture(canvas->recordingContext(), backendTexture,
307                 kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType, nullptr);
308 #else
309             auto image = SkImage::MakeFromTexture(canvas->getGrContext(), backendTexture,
310                 kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType, nullptr);
311 #endif
312             if (image == nullptr) {
313                 RS_LOGE("RSDividedRenderUtil::DrawImage: image is nullptr!");
314                 return;
315             }
316 #ifdef NEW_SKIA
317             RS_TRACE_NAME_FMT("DrawImage(GPU) seqNum: %d", bufferId);
318             canvas->drawImageRect(image, params.srcRect, params.dstRect, SkSamplingOptions(),
319                 &(params.paint), SkCanvas::kStrict_SrcRectConstraint);
320 #else
321             RS_TRACE_NAME_FMT("DrawImage(GPU) seqNum: %d", bufferId);
322             canvas->drawImageRect(image, params.srcRect, params.dstRect, &(params.paint));
323 #endif
324 #else // USE_ROSEN_DRAWING
325             Drawing::ColorType colorType = (params.buffer->GetFormat() == GRAPHIC_PIXEL_FMT_BGRA_8888) ?
326                 Drawing::ColorType::COLORTYPE_BGRA_8888 : Drawing::ColorType::COLORTYPE_RGBA_8888;
327             Drawing::BitmapFormat bitmapFormat = { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
328 
329             Drawing::TextureInfo externalTextureInfo;
330             externalTextureInfo.SetWidth(params.buffer->GetSurfaceBufferWidth());
331             externalTextureInfo.SetHeight(params.buffer->GetSurfaceBufferHeight());
332             externalTextureInfo.SetIsMipMapped(false);
333             externalTextureInfo.SetTarget(GL_TEXTURE_EXTERNAL_OES);
334             externalTextureInfo.SetID(eglTextureId);
335             externalTextureInfo.SetFormat(GL_RGBA8);
336 
337             auto image = std::make_shared<Drawing::Image>();
338             if (!image->BuildFromTexture(*canvas->GetGPUContext(), externalTextureInfo,
339                 Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr)) {
340                 RS_LOGE("RSDividedRenderUtil::DrawImage: image BuildFromTexture failed");
341                 return;
342             }
343             canvas->AttachBrush(params.paint);
344             RS_TRACE_NAME_FMT("DrawImage(GPU) seqNum: %d", bufferId);
345             canvas->DrawImageRect(*image, params.srcRect, params.dstRect,
346                 Drawing::SamplingOptions(), Drawing::SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT);
347             canvas->DetachBrush();
348 #endif // USE_ROSEN_DRAWING
349         } else {
350             uniRenderEngine_->DrawBuffer(*canvas, params);
351         }
352 #endif
353 #ifndef USE_ROSEN_DRAWING
354         canvas->restore();
355         canvas->restoreToCount(saveCount);
356 #else
357         canvas->Restore();
358         canvas->RestoreToCount(saveCount);
359 #endif
360     }
361     renderFrame->Flush();
362 #ifdef RS_ENABLE_EGLIMAGE
363     imageCacheSeqs.clear();
364 #endif
365     RS_LOGD("RsDebug RSHardwareThread::Redraw flush frame buffer end");
366 }
367 
368 // private func, guarantee the layer and surface are valid
369 void RSHardwareThread::LayerPresentTimestamp(const LayerInfoPtr& layer, const sptr<IConsumerSurface>& surface) const
370 {
371     if (!layer->IsSupportedPresentTimestamp()) {
372         return;
373     }
374     const auto& buffer = layer->GetBuffer();
375     if (buffer == nullptr) {
376         return;
377     }
378     if (surface->SetPresentTimestamp(buffer->GetSeqNum(), layer->GetPresentTimestamp()) != GSERROR_OK) {
379         RS_LOGD("RsDebug RSUniRenderComposerAdapter::LayerPresentTimestamp: SetPresentTimestamp failed");
380     }
381 }
382 }
383