diff --git a/adapter/ohos/build/config.gni b/adapter/ohos/build/config.gni index 4a761841..93f135ad 100644 --- a/adapter/ohos/build/config.gni +++ b/adapter/ohos/build/config.gni @@ -87,6 +87,10 @@ if (disable_gpu || enable_rosen_backend) { defines += [ "GPU_DISABLED" ] } +if (disable_gpu) { + defines += [ "UPLOAD_GPU_DISABLED" ] +} + if (form_components_support) { defines += [ "FORM_SUPPORTED" ] } diff --git a/adapter/ohos/entrance/BUILD.gn b/adapter/ohos/entrance/BUILD.gn index 355651f0..e614a596 100644 --- a/adapter/ohos/entrance/BUILD.gn +++ b/adapter/ohos/entrance/BUILD.gn @@ -52,7 +52,10 @@ template("ace_ohos_standard_source_set") { configs = [ "$ace_root:ace_config" ] if (defined(config.enable_rosen_backend) && config.enable_rosen_backend) { - configs += [ "//foundation/graphic/standard/rosen/modules/render_service_client:render_service_client_config" ] + configs += [ + "//foundation/graphic/standard/rosen/modules/render_service_base:export_config", + "//foundation/graphic/standard/rosen/modules/render_service_client:render_service_client_config", + ] } include_dirs = [ diff --git a/adapter/ohos/entrance/ace_ability.cpp b/adapter/ohos/entrance/ace_ability.cpp index edbc31e2..0476f8ac 100644 --- a/adapter/ohos/entrance/ace_ability.cpp +++ b/adapter/ohos/entrance/ace_ability.cpp @@ -184,6 +184,13 @@ void AceAbility::OnStart(const Want& want) ImageCache::SetCacheFileInfo(); }); OHOS::sptr window = Ability::GetWindow(); + std::shared_ptr rsUiDirector; + if (SystemProperties::GetRosenBackendEnabled()) { + rsUiDirector = OHOS::Rosen::RSUIDirector::Create(); + rsUiDirector->SetRSSurfaceNode(window->GetSurfaceNode()); + rsUiDirector->Init(); + } + // register surface change callback and window mode change callback OHOS::sptr thisAbility(this); window->RegisterWindowChangeListener(thisAbility); @@ -330,23 +337,20 @@ void AceAbility::OnStart(const Want& want) Ace::Platform::UIEnvCallback callback = nullptr; #ifdef ENABLE_ROSEN_BACKEND - callback = [window, id = abilityId_](const OHOS::Ace::RefPtr& context) mutable { - if (SystemProperties::GetRosenBackendEnabled()) { - auto rsUiDirector = OHOS::Rosen::RSUIDirector::Create(); - if (rsUiDirector != nullptr) { - rsUiDirector->SetRSSurfaceNode(window->GetSurfaceNode()); - rsUiDirector->SetUITaskRunner( - [taskExecutor = Platform::AceContainer::GetContainer(id)->GetTaskExecutor(), id]( - const std::function& task) { - ContainerScope scope(id); - taskExecutor->PostTask(task, TaskExecutor::TaskType::UI); - }); - if (context != nullptr) { - context->SetRSUIDirector(rsUiDirector); - } - rsUiDirector->Init(); - LOGI("Init Rosen Backend"); + callback = [window, id = abilityId_, flutterAceView, rsUiDirector]( + const OHOS::Ace::RefPtr& context) mutable { + if (rsUiDirector) { + rsUiDirector->SetUITaskRunner( + [taskExecutor = Platform::AceContainer::GetContainer(id)->GetTaskExecutor(), id]( + const std::function& task) { + ContainerScope scope(id); + taskExecutor->PostTask(task, TaskExecutor::TaskType::UI); + }); + if (context != nullptr) { + context->SetRSUIDirector(rsUiDirector); } + flutterAceView->InitIOManager(Platform::AceContainer::GetContainer(id)->GetTaskExecutor()); + LOGI("Init Rosen Backend"); } else { LOGI("not Init Rosen Backend"); } diff --git a/adapter/ohos/entrance/ace_rosen_sync_task.h b/adapter/ohos/entrance/ace_rosen_sync_task.h new file mode 100755 index 00000000..dfc53e5a --- /dev/null +++ b/adapter/ohos/entrance/ace_rosen_sync_task.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_ADAPTER_OHOS_CPP_ACE_ROSEN_SYNC_TASK_H +#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_ACE_ROSEN_SYNC_TASK_H + +#include "render_service_client/core/ui/rs_ui_director.h" +#include "transaction/rs_transaction_proxy.h" + +namespace OHOS::Ace::Platform { + +class AceRosenSyncTask : public Rosen::RSSyncTask { +public: + explicit AceRosenSyncTask(std::function&& task, unsigned long long timeoutNS = 50e6) + : Rosen::RSSyncTask(timeoutNS), task_(std::move(task)) + {} + virtual ~AceRosenSyncTask() = default; + +#ifdef ROSEN_OHOS + bool CheckHeader(Parcel& parcel) const override + { + return true; + } + + bool ReadFromParcel(Parcel& parcel) override + { + return true; + } + + bool Marshalling(Parcel& parcel) const override + { + return true; + } +#endif // ROSEN_OHOS + + void Process(Rosen::RSContext& context) override + { + if (task_) { + task_(); + } + } + +private: + std::function task_; +}; +} // namespace OHOS::Ace::Platform + +#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_ACE_ROSEN_SYNC_TASK_H \ No newline at end of file diff --git a/adapter/ohos/entrance/flutter_ace_view.cpp b/adapter/ohos/entrance/flutter_ace_view.cpp index 2d72e40e..5dc9f6f1 100644 --- a/adapter/ohos/entrance/flutter_ace_view.cpp +++ b/adapter/ohos/entrance/flutter_ace_view.cpp @@ -15,12 +15,21 @@ #include "adapter/ohos/entrance/flutter_ace_view.h" +#include #include #include +#include "flutter/fml/synchronization/waitable_event.h" +#include "flutter/shell/common/shell_io_manager.h" +#include "flutter/shell/gpu/gpu_surface_gl_delegate.h" #include "key_event.h" #include "pointer_event.h" +#if defined(ENABLE_ROSEN_BACKEND) and !defined(UPLOAD_GPU_DISABLED) +#include "adapter/ohos/entrance/ace_rosen_sync_task.h" +#endif + +#include "base/log/ace_trace.h" #include "base/log/dump_log.h" #include "base/log/event_report.h" #include "base/log/log.h" @@ -700,4 +709,82 @@ std::unique_ptr FlutterAceView::GetPlatformWindow() return nullptr; } +void FlutterAceView::InitIOManager(RefPtr taskExecutor) +{ +#if defined(ENABLE_ROSEN_BACKEND) and !defined(UPLOAD_GPU_DISABLED) + ACE_SCOPED_TRACE("InitIOManager"); + EGLContext shareContext = nullptr; + EGLSurface surface = nullptr; + auto callback = [&shareContext, &surface]() { + ACE_SCOPED_TRACE("create egl "); + EGLContext context = eglGetCurrentContext(); + if (context == EGL_NO_CONTEXT) { + LOGE("eglGetCurrentContext failed errorCode = [%{public}d]", eglGetError()); + return; + } + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (display == EGL_NO_DISPLAY) { + LOGE("eglGetDisplay failed errorCode = [%{public}d]", eglGetError()); + return; + } + EGLint attributes[] = { + // clang-format off + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 0, + EGL_STENCIL_SIZE, 0, + EGL_NONE, // termination sentinel + // clang-format on + }; + EGLint config_count = 0; + EGLConfig egl_config = nullptr; + if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) != EGL_TRUE) { + LOGE("Get EGLConfig failed errorCode = [%{public}d]", eglGetError()); + return; + } + EGLint contextAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + shareContext = eglCreateContext(display, egl_config, context, contextAttr); + if (shareContext == EGL_NO_CONTEXT) { + LOGE("eglCreateContext failed errorCode = [%{public}d]", eglGetError()); + return; + } + const EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; + surface = eglCreatePbufferSurface(display, egl_config, attribs); + if (surface == EGL_NO_SURFACE) { + LOGE("eglCreatePbufferSurface failed errorCode = [%{public}d]", eglGetError()); + return; + } + LOGI("create egl success"); + }; + auto task = std::make_shared(std::move(callback)); + Rosen::RSTransactionProxy::GetInstance()->ExecuteSynchronousTask(task); + + if (shareContext == EGL_NO_CONTEXT || surface == EGL_NO_SURFACE) { + LOGW("create egl env failed, image should not upload to gpu."); + return; + } + auto state = flutter::UIDartState::Current()->GetStateById(instanceId_); + if (state == nullptr) { + LOGE("state is nullptr"); + return; + } + fml::WeakPtr ioManager = state->GetIOManager(); + taskExecutor->PostSyncTask( + [surface, shareContext, ioManager]() { + ACE_SCOPED_TRACE("create resource_context "); + if (eglMakeCurrent(eglGetDisplay(EGL_DEFAULT_DISPLAY), surface, surface, shareContext) == EGL_TRUE) { + sk_sp resource_context = flutter::ShellIOManager::CreateCompatibleResourceLoadingContext( + GrBackend::kOpenGL_GrBackend, flutter::GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface()); + + ioManager->NotifyResourceContextAvailable(resource_context); + } + }, + TaskExecutor::TaskType::IO); +#endif +} + } // namespace OHOS::Ace::Platform \ No newline at end of file diff --git a/adapter/ohos/entrance/flutter_ace_view.h b/adapter/ohos/entrance/flutter_ace_view.h index 85a56b84..d96455ea 100644 --- a/adapter/ohos/entrance/flutter_ace_view.h +++ b/adapter/ohos/entrance/flutter_ace_view.h @@ -131,6 +131,8 @@ public: bool Dump(const std::vector& params) override; const void* GetNativeWindowById(uint64_t textureId) override; + void InitIOManager(RefPtr taskExecutor); + private: void NotifySurfaceChanged(int width, int height, WindowSizeChangeReason type) { diff --git a/adapter/ohos/entrance/ui_content_impl.cpp b/adapter/ohos/entrance/ui_content_impl.cpp index bdae9ad0..46899b50 100644 --- a/adapter/ohos/entrance/ui_content_impl.cpp +++ b/adapter/ohos/entrance/ui_content_impl.cpp @@ -39,6 +39,7 @@ #include "adapter/ohos/entrance/plugin_utils_impl.h" #include "base/geometry/rect.h" #include "base/log/log.h" +#include "base/log/ace_trace.h" #include "base/subwindow/subwindow_manager.h" #include "base/utils/system_properties.h" #include "core/common/ace_engine.h" @@ -238,6 +239,7 @@ std::string UIContentImpl::GetContentInfo() const void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::string& contentInfo, NativeValue* storage) { + ACE_FUNCTION_TRACE(); window_ = window; startUrl_ = contentInfo; if (!window_) { @@ -267,6 +269,13 @@ void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::str ImageCache::SetCacheFileInfo(); }); + std::shared_ptr rsUiDirector; + if (SystemProperties::GetRosenBackendEnabled()) { + rsUiDirector = OHOS::Rosen::RSUIDirector::Create(); + rsUiDirector->SetRSSurfaceNode(window->GetSurfaceNode()); + rsUiDirector->Init(); + } + int32_t deviceWidth = 0; int32_t deviceHeight = 0; float density = 1.0f; @@ -477,11 +486,10 @@ void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::str Ace::Platform::UIEnvCallback callback = nullptr; #ifdef ENABLE_ROSEN_BACKEND - callback = [window, id = instanceId_, container](const OHOS::Ace::RefPtr& context) { - if (SystemProperties::GetRosenBackendEnabled()) { - auto rsUiDirector = OHOS::Rosen::RSUIDirector::Create(); - if (rsUiDirector != nullptr) { - rsUiDirector->SetRSSurfaceNode(window->GetSurfaceNode()); + callback = [window, id = instanceId_, container, flutterAceView, rsUiDirector]( + const OHOS::Ace::RefPtr& context) { + if (rsUiDirector) { + ACE_SCOPED_TRACE("OHOS::Rosen::RSUIDirector::Create()"); rsUiDirector->SetUITaskRunner( [taskExecutor = container->GetTaskExecutor(), id](const std::function& task) { ContainerScope scope(id); @@ -491,9 +499,8 @@ void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::str if (context != nullptr) { context->SetRSUIDirector(rsUiDirector); } - rsUiDirector->Init(); + flutterAceView->InitIOManager(container->GetTaskExecutor()); LOGI("UIContent Init Rosen Backend"); - } } }; #endif diff --git a/frameworks/core/components/image/rosen_render_image.cpp b/frameworks/core/components/image/rosen_render_image.cpp index e3139b83..28b3ec15 100644 --- a/frameworks/core/components/image/rosen_render_image.cpp +++ b/frameworks/core/components/image/rosen_render_image.cpp @@ -234,7 +234,7 @@ void RosenRenderImage::ImageDataPaintSuccess(const fml::RefPtrimage(); + image_ = image; skiaDom_ = nullptr; svgDom_ = nullptr; if (imageDataNotReady_) { @@ -453,7 +453,9 @@ void RosenRenderImage::ProcessPixmapForPaint() skImage = SkImage::MakeFromRaster(imagePixmap, nullptr, nullptr); #endif } - image_ = std::move(skImage); + auto canvasImage = flutter::CanvasImage::Create(); + canvasImage->set_image(flutter::SkiaGPUObject(skImage, renderTaskHolder_->unrefQueue)); + image_ = canvasImage; if (!VerifySkImageDataFromPixmap(pixmap)) { LOGE("pixmap paint failed due to SkImage data verification fail. rawImageSize: %{public}s", rawImageSize_.ToString().c_str()); @@ -601,7 +603,7 @@ void RosenRenderImage::Paint(RenderContext& context, const Offset& offset) ApplyInterpolation(paint); sk_sp colorSpace = SkColorSpace::MakeSRGB(); if (image_) { - colorSpace = image_->refColorSpace(); + colorSpace = image_->image()->refColorSpace(); } #ifdef USE_SYSTEM_SKIA paint.setColor4f(paint.getColor4f(), colorSpace.get()); @@ -697,7 +699,7 @@ void RosenRenderImage::CanvasDrawImageRect( if (GetBackgroundImageFlag()) { return; } - if (!image_) { + if (!image_ || !image_->image()) { imageDataNotReady_ = true; LOGI("image data is not ready, rawImageSize_: %{public}s, image source: %{private}s", rawImageSize_.ToString().c_str(), sourceInfo_.ToString().c_str()); @@ -711,7 +713,7 @@ void RosenRenderImage::CanvasDrawImageRect( if (GetAdaptiveFrameRectFlag()) { recordingCanvas->translate(imageRenderPosition_.GetX() * -1, imageRenderPosition_.GetY() * -1); Rosen::RsImageInfo rsImageInfo(fitNum, repeatNum, radius, scale_); - recordingCanvas->DrawImageWithParm(image_, rsImageInfo, paint); + recordingCanvas->DrawImageWithParm(image_->image(), rsImageInfo, paint); return; } bool isLoading = ((imageLoadingStatus_ == ImageLoadingStatus::LOADING) || @@ -738,7 +740,7 @@ void RosenRenderImage::CanvasDrawImageRect( SkRect::MakeXYWH(realDstRect.Left() - imageRenderPosition_.GetX(), realDstRect.Top() - imageRenderPosition_.GetY(), realDstRect.Width(), realDstRect.Height()); - canvas->drawImageRect(image_, skSrcRect, skDstRect, &paint); + canvas->drawImageRect(image_->image(), skSrcRect, skDstRect, &paint); LOGD("dstRect params: %{public}s", realDstRect.ToString().c_str()); LOGD("scaledSrcRect params: %{public}s", scaledSrcRect.ToString().c_str()); #endif @@ -779,14 +781,14 @@ void RosenRenderImage::DrawImageOnCanvas(const Rect& srcRect, const Rect& dstRec recordingCanvas->save(); recordingCanvas->concat(sampleMatrix); - recordingCanvas->drawImageRect(image_, skSrcRect, skDstRect, &paint, SkCanvas::kFast_SrcRectConstraint); + recordingCanvas->drawImageRect(image_->image(), skSrcRect, skDstRect, &paint, SkCanvas::kFast_SrcRectConstraint); recordingCanvas->restore(); #endif } bool RosenRenderImage::VerifySkImageDataFromPixmap(const RefPtr& pixmap) const { - if (!image_) { + if (!image_ || !image_->image()) { LOGE("image data made from pixmap is null"); return false; } @@ -818,7 +820,7 @@ void RosenRenderImage::PaintBgImage(const std::shared_ptr& rsNode) if (!GetBackgroundImageFlag()) { return; } - if (currentDstRectList_.empty() || !image_) { + if (currentDstRectList_.empty() || !image_ || !image_->image()) { return; } @@ -827,7 +829,7 @@ void RosenRenderImage::PaintBgImage(const std::shared_ptr& rsNode) } #ifdef OHOS_PLATFORM auto rosenImage = std::make_shared(); - rosenImage->SetImage(image_); + rosenImage->SetImage(image_->image()); rosenImage->SetImageRepeat(static_cast(imageRepeat_)); rsNode->SetBgImageWidth(imageRenderSize_.Width()); rsNode->SetBgImageHeight(imageRenderSize_.Height()); @@ -1164,10 +1166,10 @@ void RosenRenderImage::ClearRenderObject() bool RosenRenderImage::IsSourceWideGamut() const { - if (sourceInfo_.IsSvg() || !image_) { + if (sourceInfo_.IsSvg() || !image_ || !image_->image()) { return false; } - return ImageProvider::IsWideGamut(image_->refColorSpace()); + return ImageProvider::IsWideGamut(image_->image()->refColorSpace()); } bool RosenRenderImage::RetryLoading() diff --git a/frameworks/core/components/image/rosen_render_image.h b/frameworks/core/components/image/rosen_render_image.h index 662ae697..886f52a4 100644 --- a/frameworks/core/components/image/rosen_render_image.h +++ b/frameworks/core/components/image/rosen_render_image.h @@ -120,7 +120,7 @@ private: sk_sp skiaDom_; RefPtr svgDom_; - sk_sp image_; + fml::RefPtr image_; bool loadSvgAfterLayout_ = false; bool loadSvgOnPaint_ = false; // only load svg trees without box and bind SkVector radii_[4] = { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } }; diff --git a/frameworks/core/image/image_provider.cpp b/frameworks/core/image/image_provider.cpp index 5c1d4c56..877a0c83 100644 --- a/frameworks/core/image/image_provider.cpp +++ b/frameworks/core/image/image_provider.cpp @@ -260,7 +260,7 @@ void ImageProvider::UploadImageToGPUForRender( LOGW("renderTaskHolder has been released."); return; } -#if defined(DUMP_DRAW_CMD) || defined(GPU_DISABLED) +#ifdef UPLOAD_GPU_DISABLED // If want to dump draw command or gpu disabled, should use CPU image. callback({ image, renderTaskHolder->unrefQueue }); #else diff --git a/frameworks/core/pipeline/pipeline_context.cpp b/frameworks/core/pipeline/pipeline_context.cpp index 32d243db..2d5c0cbc 100644 --- a/frameworks/core/pipeline/pipeline_context.cpp +++ b/frameworks/core/pipeline/pipeline_context.cpp @@ -199,13 +199,13 @@ void PipelineContext::FlushPipelineWithoutAnimation() FlushPostAnimation(); FlushLayout(); FlushRender(); - FlushMessages(); FlushRenderFinish(); FlushWindowBlur(); FlushFocus(); FireVisibleChangeEvent(); ProcessPostFlush(); ClearDeactivateElements(); + FlushMessages(); } void PipelineContext::FlushMessages()