diff --git a/wayland_adapter/framework/BUILD.gn b/wayland_adapter/framework/BUILD.gn index e09181d02ac16d6f96d846a82fe01a54814093ca..dc7113ea0543f34bcb9c605e36bfcfb942f0b93b 100644 --- a/wayland_adapter/framework/BUILD.gn +++ b/wayland_adapter/framework/BUILD.gn @@ -13,6 +13,7 @@ import("//build/gn/fangtian.gni") import("//config.gni") +import("//display_server/ft_build/ds_config.gni") config("wayland_framework_public_config") { include_dirs = [ @@ -35,8 +36,16 @@ ft_source_set("wayland_framewok_sources") { public_configs = [ ":wayland_framework_public_config" ] + if (ds_enable_gpu) { + defines = [ "ENABLE_GPU" ] + } + deps = [ + "$window_manager_path/wm/ft_build:libwm", + "$display_server_root/rosen/modules/render_service_base/ft_build:librender_service_base", + "$display_server_root/rosen/modules/render_service_client/ft_build:librender_service_client", "//build/gn/configs/system_libs:hilog", + "//build/gn/configs/system_libs:image", "//display_server/drivers/hal/base:ft_event_loop", "//wayland_adapter/utils:wayland_adapter_utils_sources", "//wayland_adapter/wayland_protocols:wayland_protocols_sources", diff --git a/wayland_adapter/framework/core/wayland_surface.cpp b/wayland_adapter/framework/core/wayland_surface.cpp index 61d39d0452ee0068c4beef947257639db6732cf4..430214b2e360bf2014191b5a887bc583dc967220 100644 --- a/wayland_adapter/framework/core/wayland_surface.cpp +++ b/wayland_adapter/framework/core/wayland_surface.cpp @@ -118,8 +118,31 @@ WaylandSurface::WaylandSurface(struct wl_client *client, struct wl_resource *par WaylandSurface::~WaylandSurface() noexcept {} +void WaylandSurface::AddCommitCallback(SurfaceCommitCallback callback) +{ + commitCallbacks_.push_back(std::move(callback)); +} + +void WaylandSurface::AddAttachCallback(SurfaceAttachCallback callback) +{ + attachCallbacks_.push_back(std::move(callback)); +} + void WaylandSurface::Attach(struct wl_resource *bufferResource, int32_t x, int32_t y) { + wl_shm_buffer *shm = wl_shm_buffer_get(bufferResource); + if (shm == nullptr) { + LOG_ERROR("wl_shm_buffer_get fail"); + return; + } + + wl_shm_buffer_begin_access(shm); + + for (auto &cb : attachCallbacks_) { + cb(shm); + } + + wl_shm_buffer_end_access(shm); } void WaylandSurface::Damage(int32_t x, int32_t y, int32_t width, int32_t height) @@ -140,6 +163,9 @@ void WaylandSurface::SetInputRegion(struct wl_resource *regionResource) void WaylandSurface::Commit() { + for (auto &cb : commitCallbacks_) { + cb(); + } } void WaylandSurface::SetBufferTransform(int32_t transform) diff --git a/wayland_adapter/framework/core/wayland_surface.h b/wayland_adapter/framework/core/wayland_surface.h index 854dd6f7b1ae38e0a78bc82d98e5f0d3b12be3c7..b5a539aa16df79c933d334c10f21cb26c634bf56 100644 --- a/wayland_adapter/framework/core/wayland_surface.h +++ b/wayland_adapter/framework/core/wayland_surface.h @@ -15,10 +15,11 @@ #pragma once +#include + #include #include "wayland_resource_object.h" - namespace FT { namespace Wayland { struct IWaylandSurface { @@ -47,6 +48,11 @@ public: static OHOS::sptr Create(struct wl_client *client, struct wl_resource *parent, uint32_t version, uint32_t id); ~WaylandSurface() noexcept override; + using SurfaceCommitCallback = std::function; + void AddCommitCallback(SurfaceCommitCallback callback); + using SurfaceAttachCallback = std::function; + void AddAttachCallback(SurfaceAttachCallback callback); + private: WaylandSurface(struct wl_client *client, struct wl_resource *parent, uint32_t version, uint32_t id); @@ -61,8 +67,9 @@ private: void DamageBuffer(int32_t x, int32_t y, int32_t width, int32_t height); void Offset(int32_t x, int32_t y); -private: struct wl_resource *parent_ = nullptr; + std::list commitCallbacks_; + std::list attachCallbacks_; }; } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_surface.cpp b/wayland_adapter/framework/stable/wayland_xdg_surface.cpp index 159c644b08b86acce9c8b7873bae19fd0f00370f..793a3184c96c0e99b0d494e499c5d1de06253a32 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_surface.cpp +++ b/wayland_adapter/framework/stable/wayland_xdg_surface.cpp @@ -78,18 +78,23 @@ WaylandXdgSurface::WaylandXdgSurface(const OHOS::sptr &xdgWm : WaylandResourceObject(xdgWm->WlClient(), &xdg_surface_interface, xdgWm->Version(), id, &IWaylandXdgSurface::impl_), xdgWm_(xdgWm), - surface_(surface) {} + surface_(surface) +{ + surface->AddCommitCallback([this]() { OnSurfaceCommit(); }); + surface->AddAttachCallback([this](struct wl_shm_buffer *shm) { OnSurfaceAttach(shm); }); +} WaylandXdgSurface::~WaylandXdgSurface() noexcept {} void WaylandXdgSurface::GetToplevel(uint32_t id) { - auto xdgTopLevel = WaylandXdgToplevel::Create(this, id); - if (xdgTopLevel == nullptr) { + toplevel_ = WaylandXdgToplevel::Create(this, id); + if (toplevel_ == nullptr) { LOG_ERROR("no memory"); return; } - toplevel_ = xdgTopLevel; + + role_ = XdgSurfaceRole::TOPLEVEL; } void WaylandXdgSurface::GetPopup(uint32_t id, struct wl_resource *parent, struct wl_resource *positioner) @@ -103,5 +108,37 @@ void WaylandXdgSurface::SetWindowGeometry(int32_t x, int32_t y, int32_t width, i void WaylandXdgSurface::AckConfigure(uint32_t serial) { } + +void WaylandXdgSurface::OnSurfaceCommit() +{ + switch (role_) { + case XdgSurfaceRole::TOPLEVEL: { + auto topLevel = toplevel_.promote(); + if (topLevel != nullptr) { + topLevel->HandleCommit(); + } + break; + } + default: + break; + } + + xdg_surface_send_configure(WlResource(), wl_display_next_serial(WlDisplay())); +} + +void WaylandXdgSurface::OnSurfaceAttach(struct wl_shm_buffer *shm) +{ + switch (role_) { + case XdgSurfaceRole::TOPLEVEL: { + auto topLevel = toplevel_.promote(); + if (topLevel != nullptr) { + topLevel->HandleAttach(shm); + } + break; + } + default: + break; + } +} } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_surface.h b/wayland_adapter/framework/stable/wayland_xdg_surface.h index 69c0afe7a707c2fc0dddf0f5498d6d4a70f50f4e..f0487313037c94cda7626a53720a1a4d128cdec7 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_surface.h +++ b/wayland_adapter/framework/stable/wayland_xdg_surface.h @@ -18,6 +18,7 @@ #include #include "wayland_resource_object.h" #include "wayland_surface.h" +#include "xdg_surface_utils.h" namespace FT { namespace Wayland { @@ -47,7 +48,10 @@ private: void GetPopup(uint32_t id, struct wl_resource *parent, struct wl_resource *positioner); void SetWindowGeometry(int32_t x, int32_t y, int32_t width, int32_t height); void AckConfigure(uint32_t serial); + void OnSurfaceCommit(); + void OnSurfaceAttach(struct wl_shm_buffer *shm); + XdgSurfaceRole role_ = XdgSurfaceRole::NONE; OHOS::wptr xdgWm_; OHOS::wptr surface_; OHOS::wptr toplevel_; diff --git a/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp b/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp index 9ba686e891373e79b7af94cded7bebc8ebff2518..3c2d5bff2eb5c70d190387323ac67b266e11f48b 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp +++ b/wayland_adapter/framework/stable/wayland_xdg_toplevel.cpp @@ -16,6 +16,7 @@ #include "wayland_xdg_toplevel.h" #include "wayland_objects_pool.h" +#include "ui/rs_surface_extractor.h" namespace FT { namespace Wayland { @@ -133,10 +134,17 @@ WaylandXdgToplevel::WaylandXdgToplevel(const OHOS::sptr &xdgS id, &IWaylandXdgToplevel::impl_), xdgSurface_(xdgSurface) {} -WaylandXdgToplevel::~WaylandXdgToplevel() noexcept {} +WaylandXdgToplevel::~WaylandXdgToplevel() noexcept +{ + if (window_ != nullptr) { + window_->Hide(); + window_->Destroy(); + } +} void WaylandXdgToplevel::SetTitle(const char *title) { + pendingState_.title = title; } void WaylandXdgToplevel::Move(uint32_t serial) @@ -149,6 +157,7 @@ void WaylandXdgToplevel::Resize(uint32_t serial, uint32_t edges) void WaylandXdgToplevel::SetAppId(const char *appId) { + pendingState_.appId = appId; } void WaylandXdgToplevel::SetMaxSize(int32_t width, int32_t height) @@ -178,5 +187,102 @@ void WaylandXdgToplevel::UnSetFullscreen() void WaylandXdgToplevel::SetMinimized() { } + +void WaylandXdgToplevel::SendConfigure() +{ + struct wl_array states; + wl_array_init(&states); + xdg_toplevel_send_configure(WlResource(), pendingState_.width, pendingState_.height, &states); + wl_array_release(&states); +} + +void WaylandXdgToplevel::HandleCommit() +{ + if (window_ == nullptr) { + CreateWindow(); + } + SendConfigure(); +} + +void WaylandXdgToplevel::HandleAttach(struct wl_shm_buffer *shm) +{ + if (rsSurface_ == nullptr) { + LOG_ERROR("rsSurface_ is nullptr"); + return; + } + + SkColorType format = ShmFormatToSkia(wl_shm_buffer_get_format(shm)); + if (format == SkColorType::kUnknown_SkColorType) { + LOG_ERROR("unsupported format %{public}d", wl_shm_buffer_get_format(shm)); + return; + } + + int32_t stride = wl_shm_buffer_get_stride(shm); + int32_t width = wl_shm_buffer_get_width(shm); + int32_t height = wl_shm_buffer_get_height(shm); + if (stride <= 0 || width <= 0 || height <= 0) { + LOG_ERROR("invalid, stride:%{public}d width:%{public}d height:%{public}d", stride, width, height); + return; + } + + void *data = wl_shm_buffer_get_data(shm); + if (data == nullptr) { + LOG_ERROR("wl_shm_buffer_get_data fail"); + return; + } + + auto framePtr = rsSurface_->RequestFrame(width, height); + if (framePtr == nullptr) { + LOG_ERROR("RequestFrame failed"); + return; + } + + auto canvas = framePtr->GetCanvas(); + if (canvas == nullptr) { + LOG_ERROR("GetCanvas failed"); + return; + } + canvas->clear(SK_ColorTRANSPARENT); + + SkImageInfo imageInfo = SkImageInfo::Make(width, height, format, kUnpremul_SkAlphaType); + SkPixmap srcPixmap(imageInfo, data, stride); + SkBitmap srcBitmap; + srcBitmap.installPixels(srcPixmap); + canvas->drawBitmap(srcBitmap, 0, 0); + rsSurface_->FlushFrame(framePtr); +} + +void WaylandXdgToplevel::CreateWindow() +{ + OHOS::sptr option(new OHOS::Rosen::WindowOption()); + option->SetWindowRect({0, 0, pendingState_.width, pendingState_.height}); + option->SetWindowType(OHOS::Rosen::WindowType::APP_MAIN_WINDOW_BASE); + option->SetWindowMode(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING); + + window_ = OHOS::Rosen::Window::Create(pendingState_.appId, option); + if (window_ == nullptr) { + LOG_ERROR("Window::Create failed"); + return; + } + window_->Show(); + + surfaceNode_ = window_->GetSurfaceNode(); + if (surfaceNode_ == nullptr) { + LOG_ERROR("GetSurfaceNode failed"); + return; + } + + rsSurface_ = OHOS::Rosen::RSSurfaceExtractor::ExtractRSSurface(surfaceNode_); + if (rsSurface_ == nullptr) { + LOG_ERROR("ExtractRSSurface failed"); + return; + } + +#ifdef ENABLE_GPU + renderContext_ = std::make_unique(); + renderContext_->InitializeEglContext(); + rsSurface_->SetRenderContext(renderContext_.get()); +#endif +} } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/framework/stable/wayland_xdg_toplevel.h b/wayland_adapter/framework/stable/wayland_xdg_toplevel.h index 25979f43b66b72374ffaa67d2a078a8b380e8d2f..02e7b40c36da1d7c3e95d50a7abc8bb3acc384f6 100644 --- a/wayland_adapter/framework/stable/wayland_xdg_toplevel.h +++ b/wayland_adapter/framework/stable/wayland_xdg_toplevel.h @@ -17,6 +17,9 @@ #include #include "wayland_xdg_surface.h" +#include "window.h" +#include "ui/rs_surface_node.h" +#include "render_context/render_context.h" namespace FT { namespace Wayland { @@ -56,12 +59,23 @@ public: void SetMinimized(); void Move(uint32_t serial); void Resize(uint32_t serial, uint32_t edges); + void SendConfigure(); + void HandleCommit(); + void HandleAttach(struct wl_shm_buffer *shm); private: WaylandXdgToplevel(const OHOS::sptr &xdgSurface, uint32_t id); + void CreateWindow(); friend struct IWaylandXdgToplevel; OHOS::wptr xdgSurface_; + XdgSurfaceState pendingState_; +#ifdef ENABLE_GPU + std::unique_ptr renderContext_; +#endif + OHOS::sptr window_; + std::shared_ptr surfaceNode_; + std::shared_ptr rsSurface_; }; } // namespace Wayland } // namespace FT diff --git a/wayland_adapter/test/wayland_demo.cpp b/wayland_adapter/test/wayland_demo.cpp index 56a14952c929c460ffe80f33ba1fbf961eb5ca5e..b3dc48006e9944bfff4920fc4cfb26817d52e227 100644 --- a/wayland_adapter/test/wayland_demo.cpp +++ b/wayland_adapter/test/wayland_demo.cpp @@ -54,7 +54,7 @@ struct display { struct wl_compositor *compositor; struct xdg_wm_base *wm_base; struct wl_shm *shm; - bool has_xrgb = false; + bool has_rgba8888 = false; }; struct buffer { @@ -276,7 +276,7 @@ static struct buffer *WindowNextBuffer(struct window *window) } if (!buffer->buffer) { - int32_t ret = CreateShmBuffer(window->display, buffer, window->width, window->height, WL_SHM_FORMAT_XRGB8888); + int32_t ret = CreateShmBuffer(window->display, buffer, window->width, window->height, WL_SHM_FORMAT_RGBA8888); if (ret < 0) { return nullptr; } @@ -484,7 +484,7 @@ private: static void PaintPixels(void *data, int32_t padding, int32_t width, int32_t height, uint32_t time) { - SkImageInfo info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType); + SkImageInfo info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); SkBitmap bitmap; bitmap.installPixels(info, data, info.minRowBytes()); SkCanvas canvas(bitmap); @@ -521,8 +521,8 @@ static void ShmFormat(void *data, struct wl_shm *wl_shm, uint32_t format) { struct display *d = static_cast(data); - if (format == WL_SHM_FORMAT_XRGB8888) { - d->has_xrgb = true; + if (format == WL_SHM_FORMAT_RGBA8888) { + d->has_rgba8888 = true; } } struct wl_shm_listener shm_listener = {ShmFormat}; @@ -564,7 +564,7 @@ static struct display *CreateDisplay() pDisplay->display = wl_display_connect(nullptr); assert(pDisplay->display); - pDisplay->has_xrgb = false; + pDisplay->has_rgba8888 = false; pDisplay->registry = wl_display_get_registry(pDisplay->display); wl_registry_add_listener(pDisplay->registry, &g_registryListener, pDisplay); @@ -577,8 +577,8 @@ static struct display *CreateDisplay() wl_display_roundtrip(pDisplay->display); - if (!pDisplay->has_xrgb) { - fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n"); + if (!pDisplay->has_rgba8888) { + fprintf(stderr, "rgba8888 not available\n"); exit(1); } diff --git a/wayland_adapter/utils/include/xdg_surface_utils.h b/wayland_adapter/utils/include/xdg_surface_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..85f23bf6d3a8bb7321d4715dabdf3d1655520cab --- /dev/null +++ b/wayland_adapter/utils/include/xdg_surface_utils.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Huawei Technologies 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. + */ + +#pragma once + +#include + +#include +#include "wayland-server-protocol.h" + +namespace FT { +namespace Wayland { +static constexpr uint32_t DEFAULT_WIDTH = 500; +static constexpr uint32_t DEFAULT_HEIGHT = 500; +struct XdgSurfaceState { + uint32_t width = DEFAULT_WIDTH; + uint32_t height = DEFAULT_HEIGHT; + std::string title; + std::string appId; +}; + +enum class XdgSurfaceRole : uint32_t { + NONE = 0, + TOPLEVEL, + POPUP +}; + +static SkColorType ShmFormatToSkia(const uint32_t& shmFormat) +{ + switch (shmFormat) { + case WL_SHM_FORMAT_RGBA8888: + return SkColorType::kRGBA_8888_SkColorType; + default: + return SkColorType::kUnknown_SkColorType; + } +} +} // namespace Wayland +} // namespace FT diff --git a/wayland_adapter/wayland_server.cpp b/wayland_adapter/wayland_server.cpp index e8099acdebbd9a5e2900648f4723234922b7a4ea..7aee22ebc17c6e61767f9bc599f9228ebbd3b2d2 100644 --- a/wayland_adapter/wayland_server.cpp +++ b/wayland_adapter/wayland_server.cpp @@ -38,6 +38,8 @@ void WaylandServer::CreateGlobalObjects() { compositorGlobal_ = WaylandCompositor::Create(display_); xdgWmBaseGlobal_ = WaylandXdgWmBase::Create(display_); + + wl_display_add_shm_format(display_, WL_SHM_FORMAT_RGBA8888); wl_display_init_shm(display_); }