1 /*
2 * Copyright (c) 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_base_render_engine.h"
17 #include <memory>
18 #include "rs_divided_render_util.h"
19 #include "common/rs_optional_trace.h"
20 #include "pipeline/rs_uni_render_judgement.h"
21 #include "platform/common/rs_log.h"
22 #include "platform/common/rs_system_properties.h"
23 #if defined(NEW_RENDER_CONTEXT)
24 #include "render_context_factory.h"
25 #include "rs_surface_factory.h"
26 #include "ohos/rs_render_surface_ohos.h"
27 #else
28 #include "platform/ohos/backend/rs_surface_ohos_gl.h"
29 #include "platform/ohos/backend/rs_surface_ohos_raster.h"
30 #ifdef RS_ENABLE_VK
31 #include "platform/ohos/backend/rs_surface_ohos_vulkan.h"
32 #endif
33 #endif
34 #include "render/rs_skia_filter.h"
35
36 #include "drawing_context.h"
37 #include "rs_render_surface_frame.h"
38 #include "render_context_base.h"
39 #include "include/core/SkCanvas.h"
40 #include "include/core/SkSurface.h"
41
42 #ifndef ROSEN_CROSS_PLATFORM
43 #include "surface_type.h"
44 #endif
45 #include "pipeline/rs_egl_image_manager.h"
46
47 #include "pipeline/rs_display_render_node.h"
48 #include "pipeline/rs_main_thread.h"
49 #include "render_context/render_context.h"
50
51 namespace OHOS {
52 namespace Rosen {
RSBaseRenderEngine()53 RSBaseRenderEngine::RSBaseRenderEngine()
54 {
55 }
56
~RSBaseRenderEngine()57 RSBaseRenderEngine::~RSBaseRenderEngine() noexcept
58 {
59 }
60
Init()61 void RSBaseRenderEngine::Init()
62 {
63 #if defined(NEW_RENDER_CONTEXT)
64 RenderType renderType = RenderType::GLES;
65 #if defined(RS_ENABLE_GL)
66 renderType = RenderType::GLES;
67 #elif defined(RS_ENABLE_VK)
68 renderType = RenderType::VULKAN;
69 #else
70 renderType = RenderType::RASTER;
71 #endif
72 renderContext_ = RenderContextBaseFactory::CreateRenderContext(renderType);
73 renderContext_->Init();
74 drawingContext_ = std::make_shared<Rosen::DrawingContext>(renderContext_->GetRenderType());
75 drawingContext_->SetUpDrawingContext();
76 #else
77 #if (defined RS_ENABLE_GL) || (defined RS_ENABLE_VK)
78 renderContext_ = std::make_shared<RenderContext>();
79 renderContext_->InitializeEglContext();
80 if (RSUniRenderJudgement::IsUniRender()) {
81 RS_LOGI("RSRenderEngine::RSRenderEngine set new cacheDir");
82 renderContext_->SetUniRenderMode(true);
83 }
84 #ifndef USE_ROSEN_DRAWING
85 renderContext_->SetUpGrContext();
86 #else
87 renderContext_->SetUpGpuContext();
88 #endif // USE_ROSEN_DRAWING
89 #endif // RS_ENABLE_GL || RS_ENABLE_VK
90 #endif
91 #if defined(RS_ENABLE_EGLIMAGE)
92 #if defined(NEW_RENDER_CONTEXT)
93 std::shared_ptr<RSRenderSurfaceFrame> frame = renderContext_->GetRSRenderSurfaceFrame();
94 eglImageManager_ = std::make_shared<RSEglImageManager>(frame->eglState->eglDisplay);
95 #else
96 eglImageManager_ = std::make_shared<RSEglImageManager>(renderContext_->GetEGLDisplay());
97 #endif
98 #endif // RS_ENABLE_EGLIMAGE
99 }
100
NeedForceCPU(const std::vector<LayerInfoPtr> & layers)101 bool RSBaseRenderEngine::NeedForceCPU(const std::vector<LayerInfoPtr>& layers)
102 {
103 #ifdef RS_ENABLE_GL
104 bool forceCPU = false;
105 for (const auto& layer: layers) {
106 if (layer == nullptr) {
107 continue;
108 }
109
110 auto buffer = layer->GetBuffer();
111 if (buffer == nullptr) {
112 continue;
113 }
114
115 #ifndef RS_ENABLE_EGLIMAGE
116 const auto bufferFormat = buffer->GetFormat();
117 if (bufferFormat == GRAPHIC_PIXEL_FMT_YCRCB_420_SP || bufferFormat == GRAPHIC_PIXEL_FMT_YCBCR_420_SP) {
118 forceCPU = true;
119 break;
120 }
121 #endif
122
123 GraphicColorGamut srcGamut = static_cast<GraphicColorGamut>(buffer->GetSurfaceBufferColorGamut());
124 GraphicColorGamut dstGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
125 if (srcGamut != dstGamut) {
126 forceCPU = true;
127 break;
128 }
129 }
130
131 return forceCPU;
132 #else
133 return true;
134 #endif
135 }
136
137 #ifndef USE_ROSEN_DRAWING
CreateEglImageFromBuffer(RSPaintFilterCanvas & canvas,const sptr<SurfaceBuffer> & buffer,const sptr<SyncFence> & acquireFence,const uint32_t threadIndex)138 sk_sp<SkImage> RSBaseRenderEngine::CreateEglImageFromBuffer(RSPaintFilterCanvas& canvas,
139 const sptr<SurfaceBuffer>& buffer, const sptr<SyncFence>& acquireFence, const uint32_t threadIndex)
140 #else
141 std::shared_ptr<Drawing::Image> RSBaseRenderEngine::CreateEglImageFromBuffer(RSPaintFilterCanvas& canvas,
142 const sptr<SurfaceBuffer>& buffer, const sptr<SyncFence>& acquireFence, const uint32_t threadIndex)
143 #endif
144 {
145 #ifdef RS_ENABLE_EGLIMAGE
146 if (!RSBaseRenderUtil::IsBufferValid(buffer)) {
147 RS_LOGE("RSBaseRenderEngine::CreateEglImageFromBuffer invalid param!");
148 return nullptr;
149 }
150 #ifndef USE_ROSEN_DRAWING
151 #ifdef NEW_SKIA
152 if (canvas.recordingContext() == nullptr) {
153 #else
154 if (canvas.getGrContext() == nullptr) {
155 #endif
156 #else
157 if (canvas.GetGPUContext() == nullptr) {
158 #endif
159 RS_LOGE("RSBaseRenderEngine::CreateEglImageFromBuffer GrContext is null!");
160 return nullptr;
161 }
162 auto eglTextureId = eglImageManager_->MapEglImageFromSurfaceBuffer(buffer, acquireFence, threadIndex);
163 if (eglTextureId == 0) {
164 RS_LOGE("RSBaseRenderEngine::CreateEglImageFromBuffer MapEglImageFromSurfaceBuffer return invalid texture ID");
165 return nullptr;
166 }
167 #ifndef USE_ROSEN_DRAWING
168 SkColorType colorType = (buffer->GetFormat() == GRAPHIC_PIXEL_FMT_BGRA_8888) ?
169 kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
170 GrGLTextureInfo grExternalTextureInfo = { GL_TEXTURE_EXTERNAL_OES, eglTextureId, GL_RGBA8 };
171 GrBackendTexture backendTexture(buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight(),
172 GrMipMapped::kNo, grExternalTextureInfo);
173 #ifdef NEW_SKIA
174 return SkImage::MakeFromTexture(canvas.recordingContext(), backendTexture,
175 kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType, nullptr);
176 #else
177 return SkImage::MakeFromTexture(canvas.getGrContext(), backendTexture,
178 kTopLeft_GrSurfaceOrigin, colorType, kPremul_SkAlphaType, nullptr);
179 #endif
180 #else
181 Drawing::ColorType colorType = (buffer->GetFormat() == GRAPHIC_PIXEL_FMT_BGRA_8888) ?
182 Drawing::ColorType::COLORTYPE_BGRA_8888 : Drawing::ColorType::COLORTYPE_RGBA_8888;
183 Drawing::BitmapFormat bitmapFormat = { colorType, Drawing::AlphaType::ALPHATYPE_PREMUL };
184
185 Drawing::TextureInfo externalTextureInfo;
186 externalTextureInfo.SetWidth(buffer->GetSurfaceBufferWidth());
187 externalTextureInfo.SetHeight(buffer->GetSurfaceBufferHeight());
188 externalTextureInfo.SetIsMipMapped(false);
189 externalTextureInfo.SetTarget(GL_TEXTURE_EXTERNAL_OES);
190 externalTextureInfo.SetID(eglTextureId);
191 externalTextureInfo.SetFormat(GL_RGBA8);
192
193 auto image = std::make_shared<Drawing::Image>();
194 if (!image->BuildFromTexture(*canvas.GetGPUContext(), externalTextureInfo,
195 Drawing::TextureOrigin::TOP_LEFT, bitmapFormat, nullptr)) {
196 RS_LOGE("RSBaseRenderEngine::CreateEglImageFromBuffer image BuildFromTexture failed");
197 return nullptr;
198 }
199 return image;
200 #endif
201 #else
202 return nullptr;
203 #endif // RS_ENABLE_EGLIMAGE
204 }
205
206 #ifdef NEW_RENDER_CONTEXT
207 std::unique_ptr<RSRenderFrame> RSBaseRenderEngine::RequestFrame(
208 const std::shared_ptr<RSRenderSurfaceOhos>& rsSurface,
209 const BufferRequestConfig& config, bool forceCPU, bool useAFBC)
210 #else
211 std::unique_ptr<RSRenderFrame> RSBaseRenderEngine::RequestFrame(const std::shared_ptr<RSSurfaceOhos>& rsSurface,
212 const BufferRequestConfig& config, bool forceCPU, bool useAFBC)
213 #endif
214 {
215 if (rsSurface == nullptr) {
216 RS_LOGE("RSBaseRenderEngine::RequestFrame: surface is null!");
217 return nullptr;
218 }
219 RS_OPTIONAL_TRACE_BEGIN("RSBaseRenderEngine::RequestFrame(RSSurface)");
220 rsSurface->SetSurfacePixelFormat(config.format);
221
222 auto bufferUsage = config.usage;
223 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
224 if (forceCPU) {
225 bufferUsage |= BUFFER_USAGE_CPU_WRITE;
226 }
227 #else // (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
228 bufferUsage |= BUFFER_USAGE_CPU_WRITE;
229 #endif // (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
230 rsSurface->SetSurfaceBufferUsage(bufferUsage);
231
232 // check if we can use GPU context
233 #if defined(NEW_RENDER_CONTEXT)
234 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
235 if (forceCPU) {
236 std::shared_ptr<RenderContextBase> renderContextRaster = RenderContextBaseFactory::CreateRenderContext(
237 RenderType::RASTER);
238 renderContextRaster->Init();
239 std::shared_ptr<DrawingContext> drawingContextRaster = std::make_shared<DrawingContext>(RenderType::RASTER);
240 rsSurface->SetRenderContext(renderContextRaster);
241 rsSurface->SetDrawingContext(drawingContextRaster);
242 RS_LOGD("RSBaseRenderEngine::RequestFrame force CPU");
243 } else {
244 if (renderContext_ != nullptr) {
245 rsSurface->SetRenderContext(renderContext_);
246 }
247 if (drawingContext_ != nullptr) {
248 rsSurface->SetDrawingContext(drawingContext_);
249 }
250 }
251 #endif
252 #else
253 #ifdef RS_ENABLE_GL
254 if (renderContext_ != nullptr) {
255 rsSurface->SetRenderContext(renderContext_.get());
256 }
257 #endif
258 #endif
259 auto surfaceFrame = rsSurface->RequestFrame(config.width, config.height, 0, useAFBC);
260 RS_OPTIONAL_TRACE_END();
261 if (surfaceFrame == nullptr) {
262 RS_LOGE("RSBaseRenderEngine::RequestFrame: request SurfaceFrame failed!");
263 return nullptr;
264 }
265 #ifdef NEW_RENDER_CONTEXT
266 return std::make_unique<RSRenderFrame>(rsSurface);
267 #else
268 return std::make_unique<RSRenderFrame>(rsSurface, std::move(surfaceFrame));
269 #endif
270 }
271
272 std::unique_ptr<RSRenderFrame> RSBaseRenderEngine::RequestFrame(const sptr<Surface>& targetSurface,
273 const BufferRequestConfig& config, bool forceCPU, bool useAFBC)
274 {
275 RS_OPTIONAL_TRACE_BEGIN("RSBaseRenderEngine::RequestFrame(targetSurface)");
276 if (targetSurface == nullptr) {
277 RS_LOGE("RSBaseRenderEngine::RequestFrame: surface is null!");
278 RS_OPTIONAL_TRACE_END();
279 return nullptr;
280 }
281
282 #if defined(NEW_RENDER_CONTEXT)
283 std::shared_ptr<RSRenderSurfaceOhos> rsSurface = nullptr;
284 std::shared_ptr<RSRenderSurface> renderSurface = RSSurfaceFactory::CreateRSSurface(PlatformName::OHOS,
285 targetSurface);
286 rsSurface = std::static_pointer_cast<RSRenderSurfaceOhos>(renderSurface);
287 #else
288 std::shared_ptr<RSSurfaceOhos> rsSurface = nullptr;
289 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
290 if (forceCPU) {
291 rsSurface = std::make_shared<RSSurfaceOhosRaster>(targetSurface);
292 } else {
293 rsSurface = std::make_shared<RSSurfaceOhosGl>(targetSurface);
294 }
295 #elif defined(RS_ENABLE_VK)
296 rsSurface = std::make_shared<RSSurfaceOhosVulkan>(targetSurface);
297 #else
298 rsSurface = std::make_shared<RSSurfaceOhosRaster>(targetSurface);
299 #endif // (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
300 #endif
301 RS_OPTIONAL_TRACE_END();
302 return RequestFrame(rsSurface, config, forceCPU, useAFBC);
303 }
304
305 #ifdef NEW_RENDER_CONTEXT
306 void RSBaseRenderEngine::SetUiTimeStamp(const std::unique_ptr<RSRenderFrame>& renderFrame,
307 std::shared_ptr<RSRenderSurfaceOhos> surfaceOhos)
308 #else
309 void RSBaseRenderEngine::SetUiTimeStamp(const std::unique_ptr<RSRenderFrame>& renderFrame,
310 std::shared_ptr<RSSurfaceOhos> surfaceOhos)
311 #endif
312 {
313 if (surfaceOhos == nullptr) {
314 RS_LOGE("RSBaseRenderEngine::SetUiTimeStamp: surfaceOhos is null!");
315 return;
316 }
317
318 if (renderFrame == nullptr) {
319 RS_LOGE("RSBaseRenderEngine::SetUiTimeStamp: renderFrame is null!.");
320 return;
321 }
322
323 #ifdef NEW_RENDER_CONTEXT
324 surfaceOhos->SetUiTimeStamp();
325 #else
326 auto& frame = renderFrame->GetFrame();
327 surfaceOhos->SetUiTimeStamp(frame);
328 #endif
329 }
330
331 void RSBaseRenderEngine::DrawDisplayNodeWithParams(RSPaintFilterCanvas& canvas, RSDisplayRenderNode& node,
332 BufferDrawParam& params)
333 {
334 if (params.useCPU) {
335 DrawBuffer(canvas, params);
336 } else {
337 RegisterDeleteBufferListener(node.GetConsumer());
338 DrawImage(canvas, params);
339 }
340 }
341
342 void RSBaseRenderEngine::SetColorFilterMode(ColorFilterMode mode)
343 {
344 uint32_t uMode = static_cast<uint32_t>(mode);
345 uint32_t uInvertMode = static_cast<uint32_t>(ColorFilterMode::INVERT_COLOR_ENABLE_MODE);
346 uint32_t ucolorFilterMode = static_cast<uint32_t>(colorFilterMode_);
347 bool isInvertModeEnabled = ((ucolorFilterMode & uInvertMode) == uInvertMode);
348
349 switch (mode) {
350 case ColorFilterMode::INVERT_COLOR_DISABLE_MODE: {
351 if (colorFilterMode_ != ColorFilterMode::COLOR_FILTER_END) {
352 colorFilterMode_ = static_cast<ColorFilterMode>(ucolorFilterMode & ~uInvertMode);
353 }
354 break;
355 }
356 case ColorFilterMode::INVERT_COLOR_ENABLE_MODE: {
357 if (colorFilterMode_ != ColorFilterMode::COLOR_FILTER_END) {
358 colorFilterMode_ = static_cast<ColorFilterMode>(ucolorFilterMode | uInvertMode);
359 } else {
360 colorFilterMode_ = mode;
361 }
362 break;
363 }
364 case ColorFilterMode::DALTONIZATION_PROTANOMALY_MODE:
365 case ColorFilterMode::DALTONIZATION_DEUTERANOMALY_MODE:
366 case ColorFilterMode::DALTONIZATION_TRITANOMALY_MODE: {
367 if (isInvertModeEnabled) {
368 colorFilterMode_ = static_cast<ColorFilterMode>(uMode | uInvertMode);
369 } else {
370 colorFilterMode_ = mode;
371 }
372 break;
373 }
374 case ColorFilterMode::DALTONIZATION_NORMAL_MODE: {
375 if (isInvertModeEnabled) {
376 colorFilterMode_ = ColorFilterMode::INVERT_COLOR_ENABLE_MODE;
377 } else {
378 colorFilterMode_ = ColorFilterMode::COLOR_FILTER_END;
379 }
380 break;
381 }
382
383 // INVERT_DALTONIZATION_PROTANOMALY_MODE, INVERT_DALTONIZATION_DEUTERANOMALY_MODE
384 // INVERT_DALTONIZATION_TRITANOMALY_MODE and COLOR_FILTER_END can not be set directly
385 case ColorFilterMode::INVERT_DALTONIZATION_PROTANOMALY_MODE: // fall-through
386 case ColorFilterMode::INVERT_DALTONIZATION_DEUTERANOMALY_MODE: // fall-through
387 case ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE: // fall-through
388 case ColorFilterMode::COLOR_FILTER_END: // fall-through
389 default: {
390 colorFilterMode_ = ColorFilterMode::COLOR_FILTER_END;
391 break;
392 }
393 }
394 }
395
396 void RSBaseRenderEngine::DrawBuffer(RSPaintFilterCanvas& canvas, BufferDrawParam& params)
397 {
398 RS_OPTIONAL_TRACE_BEGIN("RSBaseRenderEngine::DrawBuffer(CPU)");
399 #ifndef USE_ROSEN_DRAWING
400 SkBitmap bitmap;
401 #else
402 Drawing::Bitmap bitmap;
403 #endif
404 std::vector<uint8_t> newBuffer;
405 if (!RSBaseRenderUtil::ConvertBufferToBitmap(params.buffer, newBuffer, params.targetColorGamut, bitmap,
406 params.metaDatas)) {
407 RS_LOGE("RSDividedRenderUtil::DrawBuffer: create bitmap failed.");
408 RS_OPTIONAL_TRACE_END();
409 return;
410 }
411 #ifndef USE_ROSEN_DRAWING
412 #ifdef NEW_SKIA
413 canvas.drawImageRect(bitmap.asImage(), params.srcRect, params.dstRect,
414 SkSamplingOptions(), &(params.paint), SkCanvas::kStrict_SrcRectConstraint);
415 #else
416 canvas.drawBitmapRect(bitmap, params.srcRect, params.dstRect, &(params.paint));
417 #endif
418 #else
419 Drawing::Image drImage;
420 drImage.BuildFromBitmap(bitmap);
421 canvas.DrawImageRect(drImage, params.srcRect, params.dstRect, Drawing::SamplingOptions(),
422 Drawing::SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT);
423 #endif
424 RS_OPTIONAL_TRACE_END();
425 }
426
427 void RSBaseRenderEngine::DrawImage(RSPaintFilterCanvas& canvas, BufferDrawParam& params)
428 {
429 RS_OPTIONAL_TRACE_BEGIN("RSBaseRenderEngine::DrawImage(GPU)");
430 auto image = CreateEglImageFromBuffer(canvas, params.buffer, params.acquireFence, params.threadIndex);
431 if (image == nullptr) {
432 RS_LOGE("RSBaseRenderEngine::DrawImage: image is nullptr!");
433 RS_OPTIONAL_TRACE_END();
434 return;
435 }
436 #ifndef USE_ROSEN_DRAWING
437 #ifdef NEW_SKIA
438 canvas.drawImageRect(image, params.srcRect, params.dstRect,
439 SkSamplingOptions(), &(params.paint), SkCanvas::kStrict_SrcRectConstraint);
440 #else
441 canvas.drawImageRect(image, params.srcRect, params.dstRect, &(params.paint));
442 #endif
443 #else
444 canvas.AttachBrush(params.paint);
445 canvas.DrawImageRect(*image.get(), params.srcRect, params.dstRect,
446 Drawing::SamplingOptions(), Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
447 canvas.DetachBrush();
448 #endif
449 RS_OPTIONAL_TRACE_END();
450 }
451
452 void RSBaseRenderEngine::RegisterDeleteBufferListener(const sptr<IConsumerSurface>& consumer, bool isForUniRedraw)
453 {
454 #ifdef RS_ENABLE_EGLIMAGE
455 auto regUnMapEglImageFunc = [this, isForUniRedraw](int32_t bufferId) {
456 if (isForUniRedraw) {
457 eglImageManager_->UnMapEglImageFromSurfaceBufferForUniRedraw(bufferId);
458 } else {
459 eglImageManager_->UnMapEglImageFromSurfaceBuffer(bufferId);
460 }
461 };
462 if (consumer == nullptr ||
463 (consumer->RegisterDeleteBufferListener(regUnMapEglImageFunc, isForUniRedraw) != GSERROR_OK)) {
464 RS_LOGE("RSBaseRenderEngine::RegisterDeleteBufferListener: failed to register UnMapEglImage callback.");
465 }
466 #endif // #ifdef RS_ENABLE_EGLIMAGE
467 }
468
469 void RSBaseRenderEngine::RegisterDeleteBufferListener(RSSurfaceHandler& handler)
470 {
471 #ifdef RS_ENABLE_EGLIMAGE
472 auto regUnMapEglImageFunc = [this](int32_t bufferId) {
473 eglImageManager_->UnMapEglImageFromSurfaceBuffer(bufferId);
474 };
475 handler.RegisterDeleteBufferListener(regUnMapEglImageFunc);
476 #endif // #ifdef RS_ENABLE_EGLIMAGE
477 }
478
479 void RSBaseRenderEngine::ShrinkCachesIfNeeded(bool isForUniRedraw)
480 {
481 #ifdef RS_ENABLE_EGLIMAGE
482 if (eglImageManager_ != nullptr) {
483 eglImageManager_->ShrinkCachesIfNeeded(isForUniRedraw);
484 }
485 #endif // RS_ENABLE_EGLIMAGE
486 }
487 } // namespace Rosen
488 } // namespace OHOS
489