split mode

Change-Id: Ibb867534ba877ada08c03698fd5a31d1f2e66c8c
Signed-off-by: lizheng <lizheng2@huawei.com>
This commit is contained in:
lizheng 2021-12-16 15:02:06 +08:00
parent 3e2a628d2b
commit 2d7cebeacd
58 changed files with 2633 additions and 450 deletions

View File

@ -19,6 +19,7 @@ group("default") {
public_deps = [
":default.scss",
":graphic.rc",
"frameworks/animation_server:animation_server",
"frameworks/bootanimation:bootanimation",
"frameworks/bootanimation:bootanimation-480x960.raw",
"frameworks/dumper:gdumper",
@ -30,10 +31,6 @@ group("default") {
"frameworks/wmservice:wmservice_test",
"frameworks/wmtest:wmtest",
]
if (ace_enable_gpu) {
public_deps += [ "frameworks/animation_server:animation_server" ]
}
}
## Install graphic.rc to /system/etc/init/graphic.rc {{{

View File

@ -50,6 +50,15 @@
}
}
#WINDOW_TYPE_SPLIT_LINE {
z-index: 0;
position: relative;
horizon-align: middle;
vertical-align: middle;
width: 100.0%;
height: 100.0%;
}
#WINDOW_TYPE_STATUS_BAR {
z-index: 10;
position: static;
@ -79,6 +88,9 @@
#WINDOW_TYPE_SYSTEM_UI {
z-index: 31;
position: relative;
width: 100%;
height: 100%;
}
#WINDOW_TYPE_LAUNCHER {

View File

@ -12,6 +12,7 @@
# limitations under the License.
import("//build/ohos.gni")
import("//foundation/graphic/standard/graphic_config.gni")
## Build libanimation_service.so {{{
config("libanimation_service_config") {
@ -47,12 +48,14 @@ ohos_shared_library("libanimation_service") {
public_configs = [ ":libanimation_service_public_config" ]
deps = [
"//foundation/communication/ipc/interfaces/innerkits/ipc_core:ipc_core",
"//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy",
"//foundation/graphic/standard/utils:libgslogger",
]
public_deps = [ "//utils/native/base:utils" ]
public_deps = [
"//foundation/communication/ipc/interfaces/innerkits/ipc_core:ipc_core",
"//utils/native/base:utils",
]
part_name = "graphic_standard"
subsystem_name = "graphic"
@ -84,11 +87,16 @@ ohos_executable("animation_server") {
"server/src/animation_server.cpp",
"server/src/animation_service_stub.cpp",
"server/src/main.cpp",
"server/src/rotation_animation.cpp",
"server/src/shader.cpp",
"server/src/texture.cpp",
]
if (ace_enable_gpu) {
sources += [
"server/src/rotation_animation.cpp",
"server/src/shader.cpp",
"server/src/texture.cpp",
]
}
configs = [ ":animation_server_config" ]
deps = [
@ -97,9 +105,11 @@ ohos_executable("animation_server") {
"//foundation/graphic/standard:libvsync_client",
"//foundation/graphic/standard:libwmclient",
"//foundation/graphic/standard:libwmservice",
"//foundation/graphic/standard/utils:cpudraw",
"//foundation/graphic/standard/utils:graphic_bytrace",
"//foundation/graphic/standard/utils:libgslogger",
"//foundation/graphic/standard/utils:matrix",
"//foundation/multimodalinput/input/frameworks/proxy:libmmi-client",
]
part_name = "graphic_standard"

View File

@ -26,6 +26,8 @@ public:
AnimationServiceProxy(const sptr<IRemoteObject>& impl);
GSError StartRotationAnimation(int32_t did, int32_t degree) override;
GSError SplitModeCreateBackground() override;
GSError SplitModeCreateMiddleLine() override;
private:
static inline BrokerDelegator<AnimationServiceProxy> delegator_;

View File

@ -55,4 +55,56 @@ GSError AnimationServiceProxy::StartRotationAnimation(int32_t did, int32_t degre
return ret;
}
GSError AnimationServiceProxy::SplitModeCreateBackground()
{
MessageParcel data;
MessageParcel reply;
MessageOption option;
auto retval = data.WriteInterfaceToken(GetDescriptor());
if (!retval) {
GSLOG2HI(ERROR) << "WriteInterfaceToken failed";
return GSERROR_INVALID_ARGUMENTS;
}
int32_t res = Remote()->SendRequest(SPLIT_MODE_CREATE_BACKGOUND, data, reply, option);
if (res) {
GSLOG2HI(ERROR) << "SendRequest failed, retval=" << res;
return GSERROR_BINDER;
}
GSError ret = static_cast<enum GSError>(reply.ReadInt32());
if (ret != GSERROR_OK) {
GSLOG2HI(ERROR) << "Call return failed: " << ret;
}
return ret;
}
GSError AnimationServiceProxy::SplitModeCreateMiddleLine()
{
MessageParcel data;
MessageParcel reply;
MessageOption option;
auto retval = data.WriteInterfaceToken(GetDescriptor());
if (!retval) {
GSLOG2HI(ERROR) << "WriteInterfaceToken failed";
return GSERROR_INVALID_ARGUMENTS;
}
int32_t res = Remote()->SendRequest(SPLIT_MODE_CREATE_MIDDLE_LINE, data, reply, option);
if (res) {
GSLOG2HI(ERROR) << "SendRequest failed, retval=" << res;
return GSERROR_BINDER;
}
GSError ret = static_cast<enum GSError>(reply.ReadInt32());
if (ret != GSERROR_OK) {
GSLOG2HI(ERROR) << "Call return failed: " << ret;
}
return ret;
}
} // namespace OHOS

View File

@ -24,9 +24,9 @@ namespace {
DEFINE_HILOG_LABEL("IAnimationService");
} // namespace
GSError IAnimationService::Init()
GSError IAnimationService::Init(bool reinit)
{
if (animationService != nullptr) {
if (animationService != nullptr && reinit == false) {
return GSERROR_OK;
}

View File

@ -22,16 +22,20 @@
namespace OHOS {
class IAnimationService : public IRemoteBroker {
public:
static GSError Init();
static GSError Init(bool reinit = false);
static sptr<IAnimationService> Get();
virtual GSError StartRotationAnimation(int32_t did, int32_t degree) = 0;
virtual GSError SplitModeCreateBackground() = 0;
virtual GSError SplitModeCreateMiddleLine() = 0;
DECLARE_INTERFACE_DESCRIPTOR(u"IAnimationService");
protected:
enum {
START_ROTATION_ANIMATION = 0,
SPLIT_MODE_CREATE_BACKGOUND = 1,
SPLIT_MODE_CREATE_MIDDLE_LINE = 2,
};
private:

View File

@ -20,14 +20,19 @@
#include <functional>
#include <unistd.h>
#include <egl_surface.h>
#include <promise.h>
#include <touch_event_handler.h>
#include <vsync_helper.h>
#include <window_manager.h>
#include <window_manager_service_client.h>
#include "animation_service_stub.h"
#include "rotation_animation.h"
#ifdef ACE_ENABLE_GPU
#include <egl_surface.h>
#endif
namespace OHOS {
using PromiseGSError = Promise<GSError>;
@ -47,22 +52,55 @@ public:
GSError Init();
GSError StartRotationAnimation(int32_t did, int32_t degree) override;
GSError SplitModeCreateBackground() override;
GSError SplitModeCreateMiddleLine() override;
void OnScreenShot(const struct WMImageInfo &info) override;
void OnSplitStatusChange(SplitStatus status);
bool OnTouch(const TouchEvent &event);
private:
void StartAnimation(struct Animation &animation);
void AnimationSync(int64_t time, void *data);
void RotationDraw();
VsyncError RequestNextVsync();
void SplitWindowUpdate();
void SplitWindowDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count);
std::shared_ptr<AppExecFwk::EventHandler> handler = nullptr;
sptr<VsyncHelper> vhelper = nullptr;
sptr<Window> window = nullptr;
#ifdef ACE_ENABLE_GPU
sptr<EglRenderSurface> eglSurface = nullptr;
std::atomic<bool> isAnimationRunning = false;
sptr<PromiseAnimationScreenshotInfo> screenshotPromise = nullptr;
std::unique_ptr<RotationAnimation> ranimation = nullptr;
#endif
sptr<Window> splitWindow = nullptr;
bool haveMiddleLine = false;
bool midlineDown = false;
int32_t midlineYBackup = -100;
int32_t midlineY = -100;
int32_t downX = 0;
int32_t downY = 0;
class TouchEventHandler : public MMI::TouchEventHandler {
public:
explicit TouchEventHandler(AnimationServer *server) : server_(server)
{
}
virtual bool OnTouch(const TouchEvent &event) override
{
return server_->OnTouch(event);
}
private:
AnimationServer *server_ = nullptr;
};
sptr<TouchEventHandler> thandler = nullptr;
sptr<IRemoteObject> token = new IPCObjectStub(u"animation_server");
};
} // namespace OHOS

View File

@ -31,6 +31,8 @@ public:
private:
int32_t StartRotationAnimationRemote(MessageParcel& data, MessageParcel& reply, MessageOption& options);
int32_t SplitModeCreateBackgroundRemote(MessageParcel& data, MessageParcel& reply, MessageOption& options);
int32_t SplitModeCreateMiddleLineRemote(MessageParcel& data, MessageParcel& reply, MessageOption& options);
using AnimationServiceStubFunc = int32_t (AnimationServiceStub::*)(MessageParcel &arguments,
MessageParcel &reply, MessageOption &option);

View File

@ -18,9 +18,11 @@
#include <cassert>
#include <chrono>
#include <fstream>
#include <sys/time.h>
#include <multimodal_event_handler.h>
#include <securec.h>
#include <sys/time.h>
#include <cpudraw.h>
#include <graphic_bytrace.h>
#include <gslogger.h>
@ -29,19 +31,6 @@ namespace {
DEFINE_HILOG_LABEL("AnimationServer");
} // namespace
GSError AnimationServer::StartRotationAnimation(int32_t did, int32_t degree)
{
if (isAnimationRunning == false) {
struct Animation animation {
.degree = degree,
.retval = new Promise<GSError>(),
};
handler->PostTask(std::bind(&AnimationServer::StartAnimation, this, std::ref(animation)));
return animation.retval->Await();
}
return GSERROR_ANIMATION_RUNNING;
}
GSError AnimationServer::Init()
{
handler = AppExecFwk::EventHandler::Current();
@ -53,6 +42,19 @@ GSError AnimationServer::Init()
return static_cast<enum GSError>(wret);
}
WindowManagerServiceClient::GetInstance()->Init();
auto splitOption = WindowOption::Get();
splitOption->SetWindowType(WINDOW_TYPE_SPLIT_LINE);
wret = wm->CreateWindow(splitWindow, splitOption);
if (wret != WM_OK || splitWindow == nullptr) {
GSLOG2HI(ERROR) << "WindowManager::CreateWindow failed: " << WMErrorStr(wret);
return static_cast<enum GSError>(wret);
}
splitWindow->Hide();
auto func = std::bind(&AnimationServer::OnSplitStatusChange, this, std::placeholders::_1);
splitWindow->OnSplitStatusChange(func);
auto option = WindowOption::Get();
option->SetWindowType(WINDOW_TYPE_ANIMATION);
wret = wm->CreateWindow(window, option);
@ -62,11 +64,55 @@ GSError AnimationServer::Init()
}
window->Hide();
#ifdef ACE_ENABLE_GPU
auto producer = window->GetProducer();
eglSurface = EglRenderSurface::CreateEglSurfaceAsProducer(producer);
#endif
return GSERROR_OK;
}
GSError AnimationServer::StartRotationAnimation(int32_t did, int32_t degree)
{
#ifdef ACE_ENABLE_GPU
if (isAnimationRunning == false) {
struct Animation animation {
.degree = degree,
.retval = new Promise<GSError>(),
};
handler->PostTask(std::bind(&AnimationServer::StartAnimation, this, std::ref(animation)));
return animation.retval->Await();
}
return GSERROR_ANIMATION_RUNNING;
#else
return GSERROR_NOT_SUPPORT;
#endif
}
GSError AnimationServer::SplitModeCreateBackground()
{
ScopedBytrace trace(__func__);
GSLOG2HI(DEBUG);
splitWindow->Show();
splitWindow->SwitchTop();
if (thandler == nullptr) {
thandler = new TouchEventHandler(this);
MMIEventHdl.RegisterStandardizedEventHandle(this, splitWindow->GetID(), thandler);
}
handler->PostTask(std::bind(&AnimationServer::SplitWindowUpdate, this));
return GSERROR_OK;
}
GSError AnimationServer::SplitModeCreateMiddleLine()
{
ScopedBytrace trace(__func__);
GSLOG2HI(DEBUG);
midlineY = splitWindow->GetHeight() / 2 + splitWindow->GetY();
haveMiddleLine = true;
handler->PostTask(std::bind(&AnimationServer::SplitWindowUpdate, this));
return GSERROR_OK;
}
#ifdef ACE_ENABLE_GPU
void AnimationServer::StartAnimation(struct Animation &animation)
{
if (isAnimationRunning) {
@ -74,7 +120,7 @@ void AnimationServer::StartAnimation(struct Animation &animation)
return;
}
ScopedBytrace(__func__);
ScopedBytrace trace(__func__);
isAnimationRunning = true;
GSLOG2HI(INFO) << "Animation Start";
window->Hide();
@ -121,15 +167,17 @@ void AnimationServer::StartAnimation(struct Animation &animation)
return;
}
animation.retval->Resolve(static_cast<enum GSError>(RequestNextVsync()));
struct FrameCallback cb = { .callback_ = std::bind(&AnimationServer::AnimationSync, this, SYNC_FUNC_ARG) };
animation.retval->Resolve(static_cast<enum GSError>(vhelper->RequestFrameCallback(cb)));
}
void AnimationServer::AnimationSync(int64_t time, void *data)
{
ScopedBytrace sb(__func__);
ScopedBytrace trace(__func__);
if (ranimation->Draw()) {
eglSurface->SwapBuffers();
RequestNextVsync();
struct FrameCallback cb = { .callback_ = std::bind(&AnimationServer::AnimationSync, this, SYNC_FUNC_ARG) };
vhelper->RequestFrameCallback(cb);
sb.End();
} else {
sb.End();
@ -139,14 +187,6 @@ void AnimationServer::AnimationSync(int64_t time, void *data)
}
}
VsyncError AnimationServer::RequestNextVsync()
{
struct FrameCallback cb = {
.callback_ = std::bind(&AnimationServer::AnimationSync, this, SYNC_FUNC_ARG),
};
return vhelper->RequestFrameCallback(cb);
}
void AnimationServer::OnScreenShot(const struct WMImageInfo &info)
{
int32_t length = info.size;
@ -171,4 +211,115 @@ void AnimationServer::OnScreenShot(const struct WMImageInfo &info)
screenshotPromise->Resolve(ainfo);
}
#else
void AnimationServer::StartAnimation(struct Animation &animation)
{
}
void AnimationServer::AnimationSync(int64_t time, void *data)
{
}
void AnimationServer::OnScreenShot(const struct WMImageInfo &info)
{
}
#endif
void AnimationServer::SplitWindowUpdate()
{
ScopedBytrace trace(__func__);
sptr<SurfaceBuffer> buffer;
auto surface = splitWindow->GetSurface();
BufferRequestConfig rconfig = {
.width = surface->GetDefaultWidth(),
.height = surface->GetDefaultHeight(),
.strideAlignment = 0x8,
.format = PIXEL_FMT_RGBA_8888,
.usage = surface->GetDefaultUsage(),
.timeout = 0,
};
SurfaceError ret = surface->RequestBufferNoFence(buffer, rconfig);
if (ret == SURFACE_ERROR_NO_BUFFER) {
return;
} else if (ret != SURFACE_ERROR_OK || buffer == nullptr) {
return;
}
auto addr = buffer->GetVirAddr();
if (addr == nullptr) {
surface->CancelBuffer(buffer);
return;
}
static int32_t count = 0;
SplitWindowDraw(buffer->GetVirAddr(), rconfig.width, rconfig.height, count);
count++;
BufferFlushConfig fconfig = {
.damage = {
.w = rconfig.width,
.h = rconfig.height,
},
};
surface->FlushBuffer(buffer, -1, fconfig);
}
void AnimationServer::SplitWindowDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count)
{
ScopedBytrace trace(__func__);
GSLOG2HI(DEBUG) << "midlineY: " << midlineY << ", midlineDown: " << midlineDown;
CPUDraw draw(vaddr, width, height);
draw.SetColor(0xff000000);
draw.DrawRect(0, 0, width, height);
if (haveMiddleLine == false) {
draw.SetColor(0xff333333);
draw.DrawRect(0.1 * width, 0.025 * height, 0.8 * width, 0.4 * height);
draw.DrawRect(0.1 * width, 0.575 * height, 0.8 * width, 0.4 * height);
} else {
auto midlineYlocal = midlineY - splitWindow->GetY();
draw.SetColor(midlineDown ? 0xffffffff : 0xffcccccc);
draw.DrawRect(0, midlineYlocal - height * 0.05, width, height * 0.1);
}
}
void AnimationServer::OnSplitStatusChange(SplitStatus status)
{
ScopedBytrace trace(__func__);
if (status == SPLIT_STATUS_DESTROY) {
splitWindow->Hide();
haveMiddleLine = false;
}
}
bool AnimationServer::OnTouch(const TouchEvent &event)
{
ScopedBytrace trace(__func__);
auto wms = WindowManagerServiceClient::GetInstance()->GetService();
int32_t index = event.GetIndex();
int32_t x = event.GetPointerPosition(index).GetX();
int32_t y = event.GetPointerPosition(index).GetY();
GSLOG2HI(DEBUG) << "touch event: " << event.GetAction() << " " << x << " " << y;
if (event.GetAction() == TouchEnum::PRIMARY_POINT_DOWN) {
wms->SetSplitMode(SPLIT_MODE_DIVIDER_TOUCH_DOWN);
midlineDown = true;
downX = x;
downY = y;
midlineYBackup = midlineY;
handler->PostTask(std::bind(&AnimationServer::SplitWindowUpdate, this));
} else if (event.GetAction() == TouchEnum::POINT_MOVE) {
midlineY = midlineYBackup + y - downY;
wms->SetSplitMode(SPLIT_MODE_DIVIDER_TOUCH_MOVE, x, midlineY);
handler->PostTask(std::bind(&AnimationServer::SplitWindowUpdate, this));
} else if (event.GetAction() == TouchEnum::PRIMARY_POINT_UP) {
wms->SetSplitMode(SPLIT_MODE_DIVIDER_TOUCH_UP);
midlineDown = false;
handler->PostTask(std::bind(&AnimationServer::SplitWindowUpdate, this));
} else {
return true;
}
return false;
}
} // namespace OHOS

View File

@ -25,6 +25,8 @@ DEFINE_HILOG_LABEL("AnimationServiceStub");
AnimationServiceStub::AnimationServiceStub()
{
memberFuncMap_[START_ROTATION_ANIMATION] = &AnimationServiceStub::StartRotationAnimationRemote;
memberFuncMap_[SPLIT_MODE_CREATE_BACKGOUND] = &AnimationServiceStub::SplitModeCreateBackgroundRemote;
memberFuncMap_[SPLIT_MODE_CREATE_MIDDLE_LINE] = &AnimationServiceStub::SplitModeCreateMiddleLineRemote;
}
int32_t AnimationServiceStub::OnRemoteRequest(uint32_t code,
@ -54,4 +56,18 @@ int32_t AnimationServiceStub::StartRotationAnimationRemote(MessageParcel& data,
reply.WriteInt32(gret);
return 0;
}
int32_t AnimationServiceStub::SplitModeCreateBackgroundRemote(MessageParcel& data,
MessageParcel& reply, MessageOption& options)
{
reply.WriteInt32(SplitModeCreateBackground());
return 0;
}
int32_t AnimationServiceStub::SplitModeCreateMiddleLineRemote(MessageParcel& data,
MessageParcel& reply, MessageOption& options)
{
reply.WriteInt32(SplitModeCreateMiddleLine());
return 0;
}
} // namespace OHOS

View File

@ -66,6 +66,7 @@ public:
virtual void OnVisibilityChange(WindowVisibilityChangeFunc func) override;
virtual void OnTypeChange(WindowTypeChangeFunc func) override;
virtual void OnModeChange(WindowModeChangeFunc func) override;
virtual void OnSplitStatusChange(SplitStatusChangeFunc func) override;
// listener
virtual WMError OnTouch(OnTouchFunc cb) override;

View File

@ -47,6 +47,9 @@ public:
MOCKABLE sptr<Promise<struct WMSWindowInfo>> CreateWindow(
const sptr<WlSurface> &wlSurface, int32_t did, WindowType type);
virtual void RegisterWindowSizeChange(WindowSizeChangeFunc func);
virtual void RegisterSplitModeChange(SplitStatusChangeFunc func);
private:
WindowManagerServer() = default;
MOCKABLE ~WindowManagerServer() = default;
@ -58,8 +61,12 @@ private:
static void OnWindowChange(void *, struct wms *,
uint32_t status, uint32_t wid, int32_t x, int32_t y, int32_t width, int32_t height);
static void OnWindowSizeChange(void *, struct wms *, int32_t width, int32_t height);
static void OnSplitStatusChange(void *, struct wms *, uint32_t status);
static inline std::queue<sptr<Promise<struct WMSWindowInfo>>> promiseQueue;
static inline WindowSizeChangeFunc onWindowSizeChange;
static inline SplitStatusChangeFunc onSplitModeChange;
};
} // namespace OHOS

View File

@ -89,6 +89,11 @@ WMError WindowImpl::CreateRemoteWindow(sptr<WindowImpl> &wi,
return wminfo.wret;
}
auto onWindowSizeChange = [&attr = wi->attr](int32_t width, int32_t height) {
attr.SetWidthHeight(width, height);
};
windowManagerServer->RegisterWindowSizeChange(onWindowSizeChange);
wi->attr.SetID(wminfo.wid);
wi->attr.SetType(option->GetWindowType());
wi->attr.SetVisibility(true);
@ -401,6 +406,12 @@ void WindowImpl::OnModeChange(WindowModeChangeFunc func)
attr.OnModeChange(func);
}
void WindowImpl::OnSplitStatusChange(SplitStatusChangeFunc func)
{
auto windowManagerServer = SingletonContainer::Get<WindowManagerServer>();
windowManagerServer->RegisterSplitModeChange(func);
}
WMError WindowImpl::OnTouch(OnTouchFunc cb)
{
CHECK_DESTROY(WM_ERROR_DESTROYED_OBJECT);

View File

@ -56,6 +56,8 @@ void WindowManagerServer::OnAppear(const GetServiceFunc get, const std::string &
wms = static_cast<struct wms *>(ret);
const struct wms_listener listener = {
.window_status = &WindowManagerServer::OnWindowChange,
.window_size_change = &WindowManagerServer::OnWindowSizeChange,
.split_mode_change = &WindowManagerServer::OnSplitStatusChange,
};
wms_add_listener(wms, &listener, nullptr);
}
@ -87,6 +89,22 @@ void WindowManagerServer::OnWindowChange(void *, struct wms *,
}
}
void WindowManagerServer::OnWindowSizeChange(void *, struct wms *, int32_t width, int32_t height)
{
WMLOGFI("%{public}dx%{public}d", width, height);
if (onWindowSizeChange) {
onWindowSizeChange(width, height);
}
}
void WindowManagerServer::OnSplitStatusChange(void *, struct wms *, uint32_t status)
{
WMLOGFI("OnSplitStatusChange status: %{public}u", status);
if (onSplitModeChange) {
onSplitModeChange(static_cast<enum SplitStatus>(status));
}
}
sptr<Promise<struct WMSWindowInfo>> WindowManagerServer::CreateWindow(
const sptr<WlSurface> &wlSurface, int32_t did, WindowType type)
{
@ -104,4 +122,14 @@ sptr<Promise<struct WMSWindowInfo>> WindowManagerServer::CreateWindow(
delegator.Dep<WlDisplay>()->Flush();
return ret;
}
void WindowManagerServer::RegisterSplitModeChange(SplitStatusChangeFunc func)
{
onSplitModeChange = func;
}
void WindowManagerServer::RegisterWindowSizeChange(WindowSizeChangeFunc func)
{
onWindowSizeChange = func;
}
} // namespace OHOS

View File

@ -33,6 +33,7 @@ config("wmserver_config") {
"//third_party/wayland-ivi-extension/ivi-input-modules/ivi-input-controller/src/",
"//utils/native/base/include",
"//foundation/graphic/standard/interfaces/innerkits/wmclient",
"//foundation/graphic/standard/interfaces/innerkits/wmservice",
]
cflags = [
@ -51,6 +52,7 @@ ohos_shared_library("wmserver") {
"src/layout_controller.cpp",
"src/rects.cpp",
"src/screen_info.c",
"src/split_mode.cpp",
"src/wmserver.c",
]
@ -61,9 +63,12 @@ ohos_shared_library("wmserver") {
deps = [
":layout_header",
"//drivers/peripheral/display/hal:hdi_display_device",
"//foundation/graphic/standard/frameworks/animation_server:libanimation_service",
"//foundation/graphic/standard/utils:graphic_bytrace",
"//foundation/multimodalinput/input/patch/diff_libinput_mmi:libinput-third-mmi",
"//third_party/wayland_standard:wayland_core_protocol",
"//third_party/weston:libexec_weston",
"//third_party/weston:trace",
"//utils/native/base:utils",
]

View File

@ -28,6 +28,7 @@
<entry name="inner_error" value="4"/>
<entry name="other" value="5"/>
<entry name="api_failed" value="6"/>
<entry name="invalid_operation" value="7"/>
</enum>
<event name="reply_error">
@ -146,6 +147,12 @@
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</event>
<event name="window_size_change">
<description summary="window size change"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</event>
<!-- Window Ctor Dtor }}} -->
<!-- Global Window Event {{{ -->
@ -298,6 +305,19 @@
</request>
<!-- Virtual Display }}}-->
<!-- Split Mode {{{ -->
<request name="set_split_mode">
<description summary="set split mode"/>
<arg name="mode" type="uint" summary="split mode"/>
<arg name="x" type="int" summary="x"/>
<arg name="y" type="int" summary="y"/>
</request>
<event name="split_mode_change">
<description summary="split_mode return value"/>
<arg name="status" type="uint" summary="status"/>
</event>
<!-- Split Mode }}} -->
</interface>
<interface name="screen_info" version="1">

View File

@ -0,0 +1,543 @@
/*
* Copyright (c) 2021 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.
*/
#include "split_mode.h"
#include <map>
#include <graphic_bytrace.h>
#include <ianimation_service.h>
#include <ivi-layout-private.h>
#include <window_manager_type.h>
#include <wms-server-protocol.h>
#include "wmserver.h"
#include "layout_controller.h"
#include <trace.h>
DEFINE_LOG_LABEL("SplitMode");
using namespace OHOS;
int32_t g_x = 0;
int32_t g_y = 0;
bool g_reinit = false;
constexpr double lineHeight = 0.1;
constexpr double lineHeightHalf = lineHeight / 2;
void GetSplitModeShowArea(int32_t &x, int32_t &y, int32_t &width, int32_t &height)
{
struct layout layout = {};
LayoutControllerCalcWindowDefaultLayout(WINDOW_TYPE_NORMAL, WINDOW_MODE_UNSET, NULL, &layout);
x = layout.x;
y = layout.y;
width = layout.w;
height = layout.h;
}
void ChangeSplitMode(struct WindowSurface *ws, enum SplitStatus status)
{
ScopedBytrace trace(__func__);
wms_send_split_mode_change(ws->controller->pWlResource, status);
LOG_INFO("%d", status);
}
void ChangeWindowPosition(struct WindowSurface *ws, int32_t x, int32_t y)
{
ScopedBytrace trace(__func__);
SetWindowPosition(ws, x, y);
LOG_INFO("%d move to (%d, %d)", ws->surfaceId, x, y);
}
void ChangeWindowSize(struct WindowSurface *ws, int32_t w, int32_t h)
{
ScopedBytrace trace(__func__);
wms_send_window_size_change(ws->controller->pWlResource, w, h);
LOG_INFO("%d resize to %dx%d", ws->surfaceId, w, h);
}
uint32_t GetSplitMode()
{
struct WmsContext *ctx = GetWmsInstance();
return ctx->splitMode;
}
void SetSplitMode(uint32_t type)
{
ScopedBytrace trace(__func__);
struct WmsContext *ctx = GetWmsInstance();
ctx->splitMode = type;
LOG_INFO("splitMode -> %d", ctx->splitMode);
}
struct WindowSurface *GetWindow(std::function<bool(struct WindowSurface *ws)> condition)
{
struct WmsContext *ctx = GetWmsInstance();
struct WindowSurface *ws = NULL;
wl_list_for_each(ws, &ctx->wlListWindow, link) {
if (condition(ws)) {
return ws;
}
}
return nullptr;
}
void ForeachWindow(std::function<bool(struct WindowSurface *ws)> condition,
std::function<void(struct WindowSurface *ws)> action)
{
ScopedBytrace trace(__func__);
struct WmsContext *ctx = GetWmsInstance();
struct WindowSurface *ws = NULL;
wl_list_for_each(ws, &ctx->wlListWindow, link) {
if (condition(ws)) {
action(ws);
}
}
}
struct WindowSurface *GetSplitedWindow()
{
auto condition = [](struct WindowSurface *ws) {
return ws->isSplited;
};
return GetWindow(condition);
}
struct WindowSurface *GetLineWindow()
{
auto condition = [](struct WindowSurface *ws) {
return ws->type == WINDOW_TYPE_SPLIT_LINE;
};
return GetWindow(condition);
}
bool GetSplitedWindows(struct WindowSurface *&top, struct WindowSurface *&bottom)
{
top = GetSplitedWindow();
if (top == nullptr) {
LOG_ERROR("no splitWindow");
return false;
}
auto condition = [top](struct WindowSurface *ws) {
return ws->isSplited && ws != top;
};
bottom = GetWindow(condition);
if (bottom == nullptr) {
LOG_ERROR("no two splitWindow");
return false;
}
if (top->y > bottom->y) {
auto tmp = top;
top = bottom;
bottom = tmp;
}
return true;
}
bool To0Null()
{
auto condition = [](struct WindowSurface *ws) {
return ws->isSplited;
};
auto action = [](struct WindowSurface *ws) {
ws->isSplited = false;
int32_t defX = 0, defY = 0, defWidth = 0, defHeight = 0;
GetSplitModeShowArea(defX, defY, defWidth, defHeight);
ChangeWindowPosition(ws, defX, defY);
ChangeWindowSize(ws, defWidth, defHeight);
ChangeSplitMode(ws, SPLIT_STATUS_RETAIN);
return false;
};
ForeachWindow(condition, action);
auto lineWindow = GetLineWindow();
if (lineWindow) {
ChangeSplitMode(lineWindow, SPLIT_STATUS_DESTROY);
}
AddSurfaceDestroyListener(nullptr);
return true;
}
bool To1Unenable()
{
auto condition = [](struct WindowSurface *ws) {
return ws->type == WINDOW_TYPE_NORMAL;
};
auto ws = GetWindow(condition);
ws->isSplited = true;
ChangeSplitMode(ws, SPLIT_STATUS_VAGUE);
return true;
}
void OnSwitchTop(struct WindowSurface *ws)
{
if (ws->type != WINDOW_TYPE_SPLIT_LINE) {
return;
}
ws = GetSplitedWindow();
if (ws == nullptr) {
LOG_ERROR("no splitWindow");
return;
}
struct WmsContext *ctx = GetWmsInstance();
ctx->pLayoutInterface->surface_change_top(ws->layoutSurface);
ctx->pLayoutInterface->commit_changes();
AddSetWindowTopListener(nullptr);
}
void OnSurfaceDestroy(struct WindowSurface *surface)
{
LOG_INFO("OnSurfaceDestroy: %d", surface->surfaceId);
if (surface->isSplited == false) {
return;
}
AddSurfaceDestroyListener(nullptr);
SetSplitMode(SPLIT_MODE_NULL);
LOG_INFO("exit split mode");
auto lineWindow = GetLineWindow();
if (lineWindow) {
ChangeSplitMode(lineWindow, SPLIT_STATUS_DESTROY);
}
auto condition = [surface](struct WindowSurface *ws) {
return ws->isSplited && ws != surface;
};
auto ws = GetWindow(condition);
if (ws == nullptr) {
return;
}
ws->isSplited = false;
int32_t defX = 0, defY = 0, defWidth = 0, defHeight = 0;
GetSplitModeShowArea(defX, defY, defWidth, defHeight);
ChangeWindowPosition(ws, defX, defY);
ChangeWindowSize(ws, defWidth, defHeight);
ChangeSplitMode(ws, SPLIT_STATUS_RETAIN);
auto ctx = GetWmsInstance();
ctx->pLayoutInterface->surface_change_top(ws->layoutSurface);
ctx->pLayoutInterface->commit_changes();
}
bool To2Single(struct WindowSurface *ws)
{
int32_t defX = 0, defY = 0, defWidth = 0, defHeight = 0;
GetSplitModeShowArea(defX, defY, defWidth, defHeight);
// vectical-align: middle, height: 1 - lineHeight
ChangeWindowPosition(ws, defX, defY + defHeight * lineHeightHalf);
ChangeWindowSize(ws, defWidth, defHeight * (1 - lineHeight));
ws->isSplited = true;
ChangeSplitMode(ws, SPLIT_STATUS_VAGUE);
return true;
}
bool To2Single0()
{
AddSurfaceDestroyListener(OnSurfaceDestroy);
auto condition = [](struct WindowSurface *ws) {
return ws->type == WINDOW_TYPE_NORMAL;
};
struct WindowSurface *ws = GetWindow(condition);
if (ws == nullptr) {
LOG_ERROR("ws is nullptr, cannot found WINDOW_TYPE_NORMAL window");
return false;
}
AddSetWindowTopListener(OnSwitchTop);
if (IAnimationService::Get() == nullptr) {
LOG_ERROR("IAnimationService::Get is nullptr");
return false;
}
auto ret = IAnimationService::Get()->SplitModeCreateBackground();
if (ret) {
LOG_ERROR("SplitModeCreateBackground failed: %s", GSErrorStr(ret).c_str());
if (ret == GSERROR_BINDER) {
g_reinit = true;
}
return false;
}
return To2Single(ws);
}
bool To2Single3()
{
struct WindowSurface *ws = nullptr;
ws = GetSplitedWindow();
if (ws == nullptr) {
LOG_ERROR("no split window");
return false;
}
return To2Single(ws);
}
bool To3Select()
{
auto ws = GetSplitedWindow();
int32_t defX = 0, defY = 0, defWidth = 0, defHeight = 0;
GetSplitModeShowArea(defX, defY, defWidth, defHeight);
LOG_INFO("Select g_y: %d %p", g_y, ws);
if (ws == nullptr) {
LOG_ERROR("ws is nullptr");
return false;
}
int32_t height = defHeight * (1 - lineHeight) / 2;
if (g_y > defY + defHeight * 0.5) {
// select bottom, ws move to top
LOG_INFO("Select bottom");
// vectical-align: top
ChangeWindowPosition(ws, defX, defY);
ChangeWindowSize(ws, defWidth, height);
} else {
// select bottom, ws move to bottom
LOG_INFO("Select top");
// vectical-align: bottom
ChangeWindowPosition(ws, defX, defY + defHeight - height);
ChangeWindowSize(ws, defWidth, height);
}
ChangeSplitMode(ws, SPLIT_STATUS_VAGUE);
return true;
}
bool To4Confirm()
{
if (IAnimationService::Get() == nullptr) {
LOG_ERROR("IAnimationService::Get is nullptr");
return false;
}
auto ret = IAnimationService::Get()->SplitModeCreateMiddleLine();
if (ret) {
LOG_ERROR("SplitModeCreateMiddleLine failed: %d", ret);
if (ret == GSERROR_BINDER) {
g_reinit = true;
}
return false;
}
auto condition = [](struct WindowSurface *ws) {
return ws->type == WINDOW_TYPE_NORMAL && ws->isSplited == false;
};
auto win1 = GetWindow(condition);
if (win1 == nullptr) {
LOG_ERROR("win1 is nullptr");
return false;
}
auto win2 = GetSplitedWindow();
if (win2 == nullptr) {
LOG_ERROR("win2 is nullptr");
return false;
}
int32_t defX = 0, defY = 0, defWidth = 0, defHeight = 0;
GetSplitModeShowArea(defX, defY, defWidth, defHeight);
int32_t y = 0;
if (win2->y <= defY + defHeight / 2) {
y = defHeight - (defHeight * (1 - lineHeight) / 2);
}
win1->isSplited = true;
ChangeWindowPosition(win1, defX, defY + y);
ChangeWindowSize(win1, win2->width, win2->height);
ChangeSplitMode(win1, SPLIT_STATUS_CLEAR);
ChangeSplitMode(win2, SPLIT_STATUS_CLEAR);
return true;
}
bool To5TouchDown()
{
auto condition = [](struct WindowSurface *ws) {
return ws->isSplited;
};
auto action = [](struct WindowSurface *ws) {
ChangeSplitMode(ws, SPLIT_STATUS_VAGUE);
};
ForeachWindow(condition, action);
return true;
}
bool To6TouchMove()
{
struct WindowSurface *topWindow;
struct WindowSurface *bottomWindow;
if (!GetSplitedWindows(topWindow, bottomWindow)) {
LOG_ERROR("no two splitWindow");
return false;
}
int32_t defX = 0, defY = 0, defWidth = 0, defHeight = 0;
GetSplitModeShowArea(defX, defY, defWidth, defHeight);
LOG_INFO("g_y: %d", g_y);
ChangeWindowSize(topWindow, defWidth, g_y - defY - defHeight * lineHeightHalf);
ChangeSplitMode(topWindow, SPLIT_STATUS_VAGUE);
ChangeWindowPosition(bottomWindow, defX, g_y + defHeight * lineHeightHalf);
ChangeWindowSize(bottomWindow, defWidth, defY + defHeight - g_y - defHeight * lineHeightHalf);
ChangeSplitMode(bottomWindow, SPLIT_STATUS_VAGUE);
return true;
}
bool To7TouchUp5()
{
struct WindowSurface *topWindow;
struct WindowSurface *bottomWindow;
if (!GetSplitedWindows(topWindow, bottomWindow)) {
LOG_ERROR("no two splitWindow");
return false;
}
ChangeSplitMode(topWindow, SPLIT_STATUS_CLEAR);
ChangeSplitMode(bottomWindow, SPLIT_STATUS_CLEAR);
return true;
}
bool To7TouchUp6()
{
struct WindowSurface *topWindow;
struct WindowSurface *bottomWindow;
if (!GetSplitedWindows(topWindow, bottomWindow)) {
LOG_ERROR("no two splitWindow");
return false;
}
int32_t x = 0, y = 0, w = 0, h = 0;
GetSplitModeShowArea(x, y, w, h);
int32_t diff = g_y - y;
LOG_INFO("diff: %d", diff);
if (0.2 * h <= diff && diff <= h * 0.8) {
ChangeSplitMode(topWindow, SPLIT_STATUS_CLEAR);
ChangeSplitMode(bottomWindow, SPLIT_STATUS_CLEAR);
return true;
}
auto longWindow = topWindow;
auto shortWindow = bottomWindow;
if (bottomWindow->height > topWindow->height) {
longWindow = bottomWindow;
shortWindow = topWindow;
}
ChangeSplitMode(shortWindow, SPLIT_STATUS_DESTROY);
ChangeSplitMode(GetLineWindow(), SPLIT_STATUS_DESTROY);
longWindow->isSplited = false;
ChangeWindowPosition(longWindow, x, y);
ChangeWindowSize(longWindow, w, h);
ChangeSplitMode(longWindow, SPLIT_STATUS_RETAIN);
struct WmsContext *ctx = GetWmsInstance();
SetSplitMode(SPLIT_MODE_NULL);
LOG_INFO("exit split mode");
ctx->pLayoutInterface->surface_change_top(longWindow->layoutSurface);
ctx->pLayoutInterface->commit_changes();
return true;
}
bool Ignore()
{
return true;
}
/* split mode state machine:
* /-\ /-* /-*
* |7| ----> |0| <---> |1|
* \-/ \-/ \-/
* ^
* ^ \ ^
* | \ |
* | \ v
* | |
* | | /-* /-*
* | | |2| <---> |3|
* | \ \-/ \-/
* | \
* | \ |
* | \ |
* | \ v
* v
* /-* /-\ /-\
* |6| <---- |5| <---- |4|
* \-/ \-/ \-/
*/
bool(* stateMachine[SPLIT_MODE_MAX][SPLIT_MODE_MAX])() = {
/* From 0NULL 1UNENABLE 2SINGLE 3SELECT 4CONFIRM 5TOUCHDOWN 6TOUCHMOVE 7TOUCHUP */
{ Ignore, To0Null, To0Null, nullptr, nullptr, nullptr, nullptr, To0Null },
{ To1Unenable, Ignore, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr },
{ To2Single0, nullptr, Ignore, To2Single3, nullptr, nullptr, nullptr, nullptr },
{ nullptr, nullptr, To3Select, To3Select, nullptr, nullptr, nullptr, nullptr },
{ nullptr, nullptr, nullptr, To4Confirm, nullptr, nullptr, nullptr, nullptr },
{ nullptr, nullptr, nullptr, nullptr, To5TouchDown, nullptr, nullptr, To5TouchDown },
{ nullptr, nullptr, nullptr, nullptr, nullptr, To6TouchMove, To6TouchMove, nullptr },
{ nullptr, nullptr, nullptr, nullptr, nullptr, To7TouchUp5, To7TouchUp6, nullptr },
};
void ControllerSetSplitMode(struct wl_client *client,
struct wl_resource *resource,
uint32_t type, int32_t x, int32_t y)
{
ScopedBytrace trace(__func__);
LOG_SCOPE();
LOG_INFO("type: %d", type);
if (!(0 <= type && type < SPLIT_MODE_MAX)) {
LOG_ERROR("invalid");
wms_send_reply_error(resource, WMS_ERROR_INVALID_PARAM);
return;
}
if (IAnimationService::Init(g_reinit) == GSERROR_OK) {
g_reinit = false;
}
auto currentType = GetSplitMode();
LOG_INFO("from %u to %u", currentType, type);
auto func = stateMachine[type][currentType];
if (func == nullptr) {
LOG_ERROR("cannot");
wms_send_reply_error(resource, WMS_ERROR_INVALID_OPERATION);
return;
}
if (type == SPLIT_MODE_SELECT || type == SPLIT_MODE_DIVIDER_TOUCH_MOVE) {
g_x = x;
g_y = y;
}
LOG_ENTERS("stateMachine");
ScopedBytrace trace2("stateMachine");
auto ret = func();
trace2.End();
LOG_EXITS("stateMachine");
if (ret) {
LOG_INFO("success");
SetSplitMode(type);
wms_send_reply_error(resource, WMS_ERROR_OK);
} else {
LOG_ERROR("failure");
wms_send_reply_error(resource, WMS_ERROR_API_FAILED);
}
return;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2021 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 FRAMEWORKS_WMSERVER_SRC_SPLIT_MODE_H
#define FRAMEWORKS_WMSERVER_SRC_SPLIT_MODE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct wl_client;
struct wl_resource;
struct WindowSurface;
void ControllerSetSplitMode(struct wl_client *client,
struct wl_resource *resource,
uint32_t type, int32_t x, int32_t y);
#ifdef __cplusplus
}
#endif
#endif // FRAMEWORKS_WMSERVER_SRC_SPLIT_MODE_H

View File

@ -29,6 +29,7 @@
#include "libweston-internal.h"
#include "screen_info.h"
#include "weston.h"
#include "split_mode.h"
#define LOG_LABEL "wms-controller"
@ -57,46 +58,6 @@
#define ASSERT assert
#define DEFAULT_SEAT_NAME "default"
struct WindowSurface {
struct WmsController *controller;
struct ivi_layout_surface *layoutSurface;
struct weston_surface *surface;
struct wl_listener surfaceDestroyListener;
struct wl_listener propertyChangedListener;
uint32_t surfaceId;
uint32_t screenId;
uint32_t type;
uint32_t mode;
int32_t x;
int32_t y;
int32_t width;
int32_t height;
int32_t lastSurfaceWidth;
int32_t lastSurfaceHeight;
int32_t firstCommit;
struct wl_list link;
};
struct ScreenshotFrameListener {
struct wl_listener frameListener;
struct wl_listener outputDestroyed;
uint32_t idScreen;
struct weston_output *output;
};
struct WmsController {
struct wl_resource *pWlResource;
uint32_t id;
uint32_t windowIdFlags;
struct wl_client *pWlClient;
struct wl_list wlListLink;
struct wl_list wlListLinkRes;
struct WmsContext *pWmsCtx;
struct ScreenshotFrameListener stListener;
};
static struct WmsContext g_wmsCtx = {0};
static ScreenInfoChangeListener g_screenInfoChangeListener = NULL;
@ -203,7 +164,7 @@ static struct WindowSurface *GetWindowSurface(const struct weston_surface *surfa
return windowSurface;
}
static void SetSourceRectangle(const struct WindowSurface *windowSurface,
void SetSourceRectangle(const struct WindowSurface *windowSurface,
int32_t x, int32_t y, int32_t width, int32_t height)
{
const struct ivi_layout_interface_for_wms *layoutInterface = windowSurface->controller->pWmsCtx->pLayoutInterface;
@ -230,7 +191,7 @@ static void SetSourceRectangle(const struct WindowSurface *windowSurface,
(uint32_t)x, (uint32_t)y, (uint32_t)width, (uint32_t)height);
}
static void SetDestinationRectangle(struct WindowSurface *windowSurface,
void SetDestinationRectangle(struct WindowSurface *windowSurface,
int32_t x, int32_t y, int32_t width, int32_t height)
{
const struct ivi_layout_interface_for_wms *layoutInterface = windowSurface->controller->pWmsCtx->pLayoutInterface;
@ -380,10 +341,9 @@ static uint32_t GetWindowId(struct WmsController *pController)
return windowId;
}
static struct ivi_layout_layer *GetLayer(struct weston_output *westonOutput,
struct ivi_layout_interface_for_wms *pLayoutInterface,
uint32_t layerId, bool *isNewLayer)
struct ivi_layout_layer *GetLayer(struct weston_output *westonOutput, uint32_t layerId, bool *isNewLayer)
{
struct ivi_layout_interface_for_wms *pLayoutInterface = GetWmsInstance()->pLayoutInterface;
LOGD("start.");
struct ivi_layout_layer *layoutLayer = pLayoutInterface->get_layer_from_id(layerId);
if (!layoutLayer) {
@ -475,8 +435,7 @@ static bool AddSurface(struct WindowSurface *windowSurface,
bool isNewLayer = false;
struct weston_output *westonOutput = screen->westonOutput;
uint32_t layerId = GetLayerId(screen->screenId, windowType, windowMode);
struct ivi_layout_layer *layoutLayer = GetLayer(screen->westonOutput,
layoutInterface, layerId, &isNewLayer);
struct ivi_layout_layer *layoutLayer = GetLayer(screen->westonOutput, layerId, &isNewLayer);
if (!layoutLayer) {
LOGE("GetLayer failed.");
return false;
@ -544,7 +503,6 @@ static bool AddWindow(struct WindowSurface *windowSurface)
// window position,size calc.
CalcWindowInfo(windowSurface);
LOGD("end.");
return true;
}
@ -686,8 +644,7 @@ static bool ScreenCopyLayers(struct WmsContext *ctx, struct WmsScreen *screenFro
for (int32_t layer_i = 0; layer_i < layersCount; layer_i++) {
uint32_t layerIdOld = ctx->pLayoutInterface->get_id_of_layer(layers[layer_i]);
uint32_t layerIdNew = ChangeLayerId(layerIdOld, screenFrom->screenId, screenTo->screenId);
struct ivi_layout_layer *layerNew = GetLayer(screenTo->westonOutput,
ctx->pLayoutInterface, layerIdNew, NULL);
struct ivi_layout_layer *layerNew = GetLayer(screenTo->westonOutput, layerIdNew, NULL);
if (!layerNew) {
LOGE("GetLayer failed.");
free(layers);
@ -981,7 +938,7 @@ static void ControllerDestroyVirtualDisplay(struct wl_client *pWlClient,
LOGD("end. DestroyVirtualDisplay");
}
static void SetWindowPosition(struct WindowSurface *ws,
void SetWindowPosition(struct WindowSurface *ws,
int32_t x, int32_t y)
{
SetDestinationRectangle(ws, x, y, ws->width, ws->height);
@ -989,7 +946,7 @@ static void SetWindowPosition(struct WindowSurface *ws,
ws->y = y;
}
static void SetWindowSize(struct WindowSurface *ws,
void SetWindowSize(struct WindowSurface *ws,
uint32_t width, uint32_t height)
{
SetSourceRectangle(ws, 0, 0, width, height);
@ -1464,6 +1421,12 @@ static void ControllerSetNavigationBarVisibility(const struct wl_client *client,
LOGD("end.");
}
void(*g_onSetWindowTop)(struct WindowSurface *ws);
void AddSetWindowTopListener(void(*fn)(struct WindowSurface *ws))
{
g_onSetWindowTop = fn;
}
static void ControllerSetWindowTop(struct wl_client *client,
struct wl_resource *resource, uint32_t windowId)
{
@ -1489,6 +1452,10 @@ static void ControllerSetWindowTop(struct wl_client *client,
ctx->pLayoutInterface->surface_change_top(windowSurface->layoutSurface);
if (g_onSetWindowTop) {
g_onSetWindowTop(windowSurface);
}
if (!SetWindowFocus(windowSurface)) {
LOGE("SetWindowFocus failed.");
wms_send_reply_error(resource, WMS_ERROR_INNER_ERROR);
@ -1501,10 +1468,19 @@ static void ControllerSetWindowTop(struct wl_client *client,
LOGD("end.");
}
void(*g_onSurfaceDestroy)(struct WindowSurface *ws);
void AddSurfaceDestroyListener(void(*fn)(struct WindowSurface *ws))
{
g_onSurfaceDestroy = fn;
}
static void SurfaceDestroy(const struct WindowSurface *surface)
{
ASSERT(surface != NULL);
LOGD("surfaceId:%{public}d start.", surface->surfaceId);
if (g_onSurfaceDestroy) {
g_onSurfaceDestroy(surface);
}
wl_list_remove(&surface->surfaceDestroyListener.link);
wl_list_remove(&surface->propertyChangedListener.link);
@ -1585,6 +1561,7 @@ static void WindowSurfaceDestroy(const struct wl_listener *listener,
LOGD("end.");
}
static void CreateWindow(struct WmsController *pWmsController,
struct weston_surface *pWestonSurface,
uint32_t windowId, uint32_t screenId, uint32_t windowType)
@ -1623,6 +1600,7 @@ static void CreateWindow(struct WmsController *pWmsController,
pWindow->surfaceId = windowId;
pWindow->type = windowType;
pWindow->mode = WINDOW_MODE_UNSET;
pWindow->isSplited = false;
pWindow->screenId = screenId;
if (!AddWindow(pWindow)) {
@ -2006,6 +1984,7 @@ static const struct wms_interface g_controllerImplementation = {
ControllerWindowshot,
ControllerCreateVirtualDisplay,
ControllerDestroyVirtualDisplay,
ControllerSetSplitMode,
};
static void UnbindWmsController(struct wl_resource *pResource)
@ -2291,6 +2270,8 @@ static int WmsContextInit(struct WmsContext *ctx, struct weston_compositor *comp
wl_signal_add(&compositor->destroy_signal, &ctx->wlListenerDestroy);
ctx->splitMode = SPLIT_MODE_NULL;
LayoutControllerInit(0, 0);
return 0;
}

View File

@ -24,6 +24,10 @@
#include <ivi-layout-export.h>
#include <wms-server-protocol.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef USE_IVI_INPUT_FOCUS
#define INPUT_DEVICE_KEYBOARD ((unsigned int) 1 << 0)
#define INPUT_DEVICE_POINTER ((unsigned int) 1 << 1)
@ -49,6 +53,7 @@ struct WmsContext {
const struct ivi_input_interface_for_wms *pInputInterface;
#endif
DeviceFuncs *deviceFuncs;
uint32_t splitMode;
};
struct WmsSeat {
@ -70,4 +75,59 @@ struct WmsScreen {
struct WmsContext *GetWmsInstance(void);
struct WindowSurface {
struct WmsController *controller;
struct ivi_layout_surface *layoutSurface;
struct weston_surface *surface;
struct wl_listener surfaceDestroyListener;
struct wl_listener propertyChangedListener;
uint32_t surfaceId;
uint32_t screenId;
uint32_t type;
uint32_t mode;
int32_t x;
int32_t y;
int32_t width;
int32_t height;
int32_t lastSurfaceWidth;
int32_t lastSurfaceHeight;
int32_t firstCommit;
bool isSplited;
struct wl_list link;
};
struct ScreenshotFrameListener {
struct wl_listener frameListener;
struct wl_listener outputDestroyed;
uint32_t idScreen;
struct weston_output *output;
};
struct WmsController {
struct wl_resource *pWlResource;
uint32_t id;
uint32_t windowIdFlags;
struct wl_client *pWlClient;
struct wl_list wlListLink;
struct wl_list wlListLinkRes;
struct WmsContext *pWmsCtx;
struct ScreenshotFrameListener stListener;
};
void SetDestinationRectangle(struct WindowSurface *windowSurface,
int32_t x, int32_t y, int32_t width, int32_t height);
void SetSourceRectangle(const struct WindowSurface *windowSurface,
int32_t x, int32_t y, int32_t width, int32_t height);
void SetWindowPosition(struct WindowSurface *ws, int32_t x, int32_t y);
void SetWindowSize(struct WindowSurface *ws, uint32_t width, uint32_t height);
struct ivi_layout_layer *GetLayer(struct weston_output *westonOutput, uint32_t layerId, bool *isNewLayer);
void AddSetWindowTopListener(void(*fn)(struct WindowSurface *ws));
void AddSurfaceDestroyListener(void(*fn)(struct WindowSurface *ws));
#ifdef __cplusplus
}
#endif
#endif // FRAMEWORKS_WMSERVER_SRC_WMSERVER_H

View File

@ -64,6 +64,8 @@ public:
virtual GSError StartRotationAnimation(uint32_t did, int32_t degree) override;
virtual sptr<PromiseWMError> SetSplitMode(SplitMode mode, int32_t x, int32_t y) override;
static void OnReply(wms_error);
static void OnDisplayChange(uint32_t, const char *, wms_screen_status, int32_t, int32_t, wms_screen_type type);
static void OnDisplayPower(uint32_t, int32_t);

View File

@ -114,11 +114,13 @@ void RegistryGlobal(void *ppwms, struct wl_registry *registry,
OnDisplayBacklight,
OnDisplayModeChange,
nullptr,
nullptr,
OnGlobalWindowStatus,
OnScreenShotDone,
OnScreenShotError,
OnWindowShotDone,
OnWindowShotError,
nullptr,
};
if (pwms != nullptr) {
wms_add_listener(pwms, &listener, nullptr);

View File

@ -510,4 +510,15 @@ GSError WindowManagerServiceProxy::StartRotationAnimation(uint32_t did, int32_t
return as->StartRotationAnimation(did, degree);
}
sptr<PromiseWMError> WindowManagerServiceProxy::SetSplitMode(SplitMode mode, int32_t x, int32_t y)
{
WMLOGFI("mode: %{public}d, x: %{public}d, y: %{public}d", mode, x, y);
sptr<PromiseWMError> ret = new PromiseWMError();
std::lock_guard<std::mutex> lock(promiseQueueMutex);
promiseQueue.push(ret);
wms_set_split_mode(wms, mode, x, y);
wl_display_flush(display);
return ret;
}
} // namespace OHOS

View File

@ -57,6 +57,7 @@ ohos_executable("wmtest") {
"test/wmclient_native_test_18.cpp",
"test/wmclient_native_test_19.cpp",
"test/wmclient_native_test_2.cpp",
"test/wmclient_native_test_20.cpp",
"test/wmclient_native_test_26.cpp",
"test/wmclient_native_test_27.cpp",
"test/wmclient_native_test_28.cpp",
@ -82,6 +83,7 @@ ohos_executable("wmtest") {
if (ace_enable_gpu) {
sources += [
"frameworks/egl_native_test_class.cpp",
"test/wmclient_native_test_31.cpp",
"test/wmservice_native_test_6.cpp",
]
@ -96,6 +98,9 @@ ohos_executable("wmtest") {
"//foundation/graphic/standard:libvsync_client",
"//foundation/graphic/standard:libwmclient",
"//foundation/graphic/standard:libwmservice",
"//foundation/graphic/standard/frameworks/animation_server:libanimation_service",
"//foundation/graphic/standard/utils:cpudraw",
"//foundation/graphic/standard/utils:graphic_bytrace",
"//foundation/graphic/standard/utils:libgslogger",
"//foundation/graphic/standard/utils:option_parser",
"//foundation/graphic/standard/utils:raw_parser",

View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2021 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.
*/
#include "native_test_class.h"
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <securec.h>
#include <sys/time.h>
#include <display_type.h>
#include "inative_test.h"
#include "util.h"
namespace OHOS {
sptr<EGLNativeTestSync> EGLNativeTestSync::CreateSync(EGLDrawFunc drawFunc,
sptr<EglSurface> &peglsurface, uint32_t width, uint32_t height, void *data)
{
if (drawFunc != nullptr && peglsurface != nullptr) {
sptr<EGLNativeTestSync> nts = new EGLNativeTestSync();
nts->draw = drawFunc;
nts->eglsurface = peglsurface;
nts->width_ = width;
nts->height_ = height;
RequestSync(std::bind(&EGLNativeTestSync::Sync, nts, SYNC_FUNC_ARG), data);
return nts;
}
return nullptr;
}
void EGLNativeTestSync::Sync(int64_t, void *data)
{
if (!GLContextInit()) {
printf("GLContextInit failed.\n");
return;
}
if (sret == SURFACE_ERROR_OK) {
draw(&glCtx, eglsurface, width_, height_);
count++;
}
sret = eglsurface->SwapBuffers();
RequestSync(std::bind(&EGLNativeTestSync::Sync, this, SYNC_FUNC_ARG), data);
}
namespace {
const char *g_vertShaderText =
"uniform float offset;\n"
"attribute vec4 pos;\n"
"attribute vec4 color;\n"
"varying vec4 v_color;\n"
"void main() {\n"
" gl_Position = pos + vec4(offset, offset, 0.0, 0.0);\n"
" v_color = color;\n"
"}\n";
const char *g_fragShaderText =
"precision mediump float;\n"
"varying vec4 v_color;\n"
"void main() {\n"
" gl_FragColor = v_color;\n"
"}\n";
static GLuint CreateShader(const char *source, GLenum shaderType)
{
GLuint shader;
GLint status;
shader = glCreateShader(shaderType);
assert(shader != 0);
glShaderSource(shader, 1, (const char **) &source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
constexpr int32_t maxLogLength = 1000;
char log[maxLogLength];
GLsizei len;
glGetShaderInfoLog(shader, maxLogLength, &len, log);
fprintf(stderr, "Error: compiling %s: %.*s\n",
shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment", len, log);
return 0;
}
return shader;
}
static GLuint CreateAndLinkProgram(GLuint vert, GLuint frag)
{
GLint status;
GLuint program = glCreateProgram();
glAttachShader(program, vert);
glAttachShader(program, frag);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (!status) {
constexpr int32_t maxLogLength = 1000;
char log[maxLogLength];
GLsizei len;
glGetProgramInfoLog(program, maxLogLength, &len, log);
fprintf(stderr, "Error: linking:\n%.*s\n", len, log);
return 0;
}
return program;
}
} // namespace
bool EGLNativeTestSync::GLContextInit()
{
if (bInit) {
return bInit;
}
if (eglsurface == nullptr) {
printf("GLContextInit eglsurface is nullptr\n");
return bInit;
}
if (eglsurface->InitContext() != SURFACE_ERROR_OK) {
printf("GLContextInit InitContext failed\n");
return bInit;
}
GLuint vert = CreateShader(g_vertShaderText, GL_VERTEX_SHADER);
GLuint frag = CreateShader(g_fragShaderText, GL_FRAGMENT_SHADER);
glCtx.program = CreateAndLinkProgram(vert, frag);
glDeleteShader(vert);
glDeleteShader(frag);
glCtx.pos = glGetAttribLocation(glCtx.program, "pos");
glCtx.color = glGetAttribLocation(glCtx.program, "color");
glUseProgram(glCtx.program);
glCtx.offsetUniform = glGetUniformLocation(glCtx.program, "offset");
if (glCtx.program == 0) {
printf("glCtx.program = 0.\n");
} else {
bInit = true;
}
return bInit;
}
void EGLNativeTestDraw::FlushDraw(GLContext *ctx, sptr<EglSurface> &eglsurface, uint32_t width, uint32_t height)
{
/* Complete a movement iteration in 5000 ms. */
static const GLfloat verts[][0x2] = {
{ -0.5, -0.5 },
{ -0.5, 0.5 },
{ 0.5, -0.5 },
{ 0.5, 0.5 }
};
static const GLfloat colors[][0x3] = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 },
{ 1, 1, 0 }
};
/* Split time_ms in repeating windows of [0, iterationMs) and map them
* to offsets in the [-0.5, 0.5) range. */
constexpr uint64_t iterationMs = 5000000000;
GLfloat offset = (GetNowTime() % iterationMs) / static_cast<double>(iterationMs);
glViewport(0, 0, width, height);
glUniform1f(ctx->offsetUniform, offset - 0.5);
glClearColor(0.0, 1.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
constexpr int32_t sizePosVertexAttribute = 2;
constexpr int32_t sizeColorsVertexAttribute = 3;
glVertexAttribPointer(ctx->pos, sizePosVertexAttribute, GL_FLOAT, GL_FALSE, 0, verts);
glVertexAttribPointer(ctx->color, sizeColorsVertexAttribute, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(ctx->pos);
glEnableVertexAttribArray(ctx->color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 0x4);
glDisableVertexAttribArray(ctx->pos);
glDisableVertexAttribArray(ctx->color);
}
} // namespace OHOS

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2021 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 FRAMEWORKS_WMTEST_FRAMEWORKS_EGL_NATIVE_TEST_CLASS
#define FRAMEWORKS_WMTEST_FRAMEWORKS_EGL_NATIVE_TEST_CLASS
#include <cstdint>
#include <functional>
#include <optional>
#include <refbase.h>
#include <window_manager.h>
#include <egl_surface.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
namespace OHOS {
typedef struct {
GLuint program;
GLuint pos;
GLuint color;
GLuint offsetUniform;
} GLContext;
using EGLDrawFunc = std::function<void(GLContext *,
sptr<EglSurface> &psurface, uint32_t width, uint32_t height)>;
class EGLNativeTestSync : public RefBase {
public:
static sptr<EGLNativeTestSync> CreateSync(EGLDrawFunc drawFunc,
sptr<EglSurface> &psurface, uint32_t width, uint32_t height, void *data = nullptr);
private:
void Sync(int64_t, void *);
bool GLContextInit();
sptr<EglSurface> eglsurface = nullptr;
EGLDrawFunc draw = nullptr;
GLContext glCtx;
bool bInit = false;
SurfaceError sret = SURFACE_ERROR_OK;
uint32_t width_ = 0;
uint32_t height_ = 0;
};
class EGLNativeTestDraw {
public:
static void FlushDraw(GLContext *ctx, sptr<EglSurface> &eglsurface, uint32_t width, uint32_t height);
};
} // namespace OHOS
#endif // FRAMEWORKS_WMTEST_FRAMEWORKS_EGL_NATIVE_TEST_CLASS

View File

@ -16,26 +16,157 @@
#include "inative_test.h"
#include <algorithm>
#include <codecvt>
#include <gslogger.h>
#include <sstream>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <vector>
#include <unistd.h>
#include "inative_test_key_handler.h"
#include "inative_test_touch_handler.h"
#include "util.h"
namespace OHOS {
void INativeTest::VisitTests(VisitTestFunc func)
INativeTest *INativeTest::VisitTests(VisitTestFunc func)
{
auto sortFunc = [](const auto &it, const auto &jt) {
if (it->GetDomain() == jt->GetDomain()) {
if (it->GetDomain() != jt->GetDomain()) {
return it->GetDomain() < jt->GetDomain();
}
if (it->GetID() != jt->GetID()) {
return it->GetID() < jt->GetID();
}
return it->GetDomain() < jt->GetDomain();
return it->GetProcessSequence() < jt->GetProcessSequence();
};
std::sort(tests.begin(), tests.end(), sortFunc);
for (auto &test : tests) {
func(test);
if (func(test)) {
return test;
}
}
return nullptr;
}
INativeTest::INativeTest()
{
tests.push_back(this);
keyHandler = new INativeTestKeyEventHandler(this);
touchHandler = new INativeTestTouchEventHandler(this);
}
uint32_t INativeTest::GetLastTime() const
{
return LAST_TIME_FOREVER;
}
enum AutoLoadService operator |(const enum AutoLoadService &l, const enum AutoLoadService &r)
{
return static_cast<enum AutoLoadService>(static_cast<int32_t>(l) | static_cast<int32_t>(r));
}
bool operator &(const enum AutoLoadService &l, const enum AutoLoadService &r)
{
return (static_cast<int32_t>(l) & static_cast<int32_t>(r)) != 0;
}
enum AutoLoadService INativeTest::GetAutoLoadService() const
{
return AutoLoadService::Null;
}
bool INativeTest::OnKey(const KeyEvent &event)
{
return false;
}
bool INativeTest::OnTouch(const TouchEvent &event)
{
return false;
}
void INativeTest::GetToken()
{
if (token == nullptr) {
std::stringstream ss;
ss << GetDomain() << GetID() << GetProcessSequence();
auto sss = ss.str();
auto u16 = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t >().from_bytes(sss);
token = new IPCObjectStub(u16);
}
}
int32_t INativeTest::ListenWindowKeyEvent(int32_t windowID)
{
GetToken();
return MMIEventHdl.RegisterStandardizedEventHandle(token, windowID, keyHandler);
}
int32_t INativeTest::ListenWindowTouchEvent(int32_t windowID)
{
GetToken();
return MMIEventHdl.RegisterStandardizedEventHandle(token, windowID, touchHandler);
}
void INativeTest::ListenWindowInputEvent(int32_t windowID)
{
ListenWindowKeyEvent(windowID);
ListenWindowTouchEvent(windowID);
}
int32_t INativeTest::GetProcessNumber() const
{
return 1;
}
int32_t INativeTest::GetProcessSequence() const
{
return -1;
}
int32_t INativeTest::StartSubprocess(int32_t id)
{
GSLOG7SO(INFO) << "StartSubprocess " << id;
auto pid = fork();
if (pid < 0) {
return pid;
}
if (pid == 0) {
std::vector<const char *> args;
for (const char **p = processArgv; *p != nullptr; p++) {
args.push_back(*p);
}
std::stringstream ss;
ss << "--process=" << id;
auto sss = ss.str();
args.push_back(sss.c_str());
args.insert(args.end(), extraArgs.begin(), extraArgs.end());
args.push_back(nullptr);
auto ret = execvp(args[0], const_cast<char *const *>(args.data()));
GSLOG7SO(ERROR) << "execvp return: " << ret << ", " << errno;
ExitTest();
return ret;
}
return 0;
}
void INativeTest::SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &handler)
{
this->handler = handler;
}
void INativeTest::PostTask(std::function<void()> func, uint32_t delayTime) const
{
handler->PostTask(func, delayTime);
}
void INativeTest::ExitTest() const
{
GSLOG7SO(INFO) << "exiting, call PostTask(&AppExecFwk::EventRunner::Stop)";
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, handler->GetEventRunner()));
}
} // namespace OHOS

View File

@ -21,9 +21,25 @@
#include <string>
#include <vector>
#include <ipc_object_stub.h>
#include <key_event_handler.h>
#include <multimodal_event_handler.h>
#include <touch_event_handler.h>
#include <vsync_helper.h>
#include <window_manager.h>
#include <window_manager_service_client.h>
namespace OHOS {
class INativeTest;
using VisitTestFunc = std::function<void(INativeTest *)>;
using VisitTestFunc = std::function<bool(INativeTest *)>;
enum class AutoLoadService : int32_t {
Null = 0,
WindowManager = 1 << 0,
WindowManagerService = 1 << 1,
};
enum AutoLoadService operator |(const enum AutoLoadService &l, const enum AutoLoadService &r);
bool operator &(const enum AutoLoadService &l, const enum AutoLoadService &r);
class INativeTest {
public:
@ -31,17 +47,48 @@ public:
LAST_TIME_FOREVER = 999999999,
};
static void VisitTests(VisitTestFunc func);
static INativeTest *VisitTests(VisitTestFunc func);
INativeTest();
virtual ~INativeTest() = default;
virtual std::string GetDescription() const = 0;
virtual std::string GetDomain() const = 0;
virtual int32_t GetID() const = 0;
virtual uint32_t GetLastTime() const = 0;
virtual void Run(int32_t argc, const char **argv) = 0;
virtual uint32_t GetLastTime() const;
// auto load service
virtual enum AutoLoadService GetAutoLoadService() const;
sptr<WindowManager> windowManager = nullptr;
sptr<IWindowManagerService> windowManagerService = nullptr;
// input
virtual bool OnKey(const KeyEvent &event);
virtual bool OnTouch(const TouchEvent &event);
void GetToken();
int32_t ListenWindowKeyEvent(int32_t windowID);
int32_t ListenWindowTouchEvent(int32_t windowID);
void ListenWindowInputEvent(int32_t windowID); // key and touch
// multiple process
virtual int32_t GetProcessNumber() const;
virtual int32_t GetProcessSequence() const;
const char **processArgv = nullptr;
std::vector<const char *> extraArgs;
int32_t StartSubprocess(int32_t id);
// thread pool
void SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler> &handler);
void PostTask(std::function<void()> func, uint32_t delayTime = 0) const;
void ExitTest() const;
private:
static inline std::vector<INativeTest *> tests;
std::shared_ptr<AppExecFwk::EventHandler> handler = nullptr;
sptr<MMI::KeyEventHandler> keyHandler = nullptr;
sptr<MMI::TouchEventHandler> touchHandler = nullptr;
sptr<IRemoteObject> token = nullptr;
};
} // namespace OHOS

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 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 FRAMEWORKS_WM_SRC_TEST_INATIVE_TEST_KEY_EVENT_HANDLER_H
#define FRAMEWORKS_WM_SRC_TEST_INATIVE_TEST_KEY_EVENT_HANDLER_H
#include <graphic_bytrace.h>
#include "inative_test.h"
namespace OHOS {
class INativeTest;
class INativeTestKeyEventHandler : public MMI::KeyEventHandler {
public:
explicit INativeTestKeyEventHandler(INativeTest *test) : test_(test)
{
}
virtual bool OnKey(const KeyEvent &event) override
{
ScopedBytrace trace(__func__);
return test_->OnKey(event);
}
private:
INativeTest *test_ = nullptr;
};
} // namespace OHOS
#endif // FRAMEWORKS_WM_SRC_TEST_INATIVE_TEST_KEY_EVENT_HANDLER_H

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 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 FRAMEWORKS_WM_SRC_TEST_INATIVE_TEST_TOUCH_EVENT_HANDLER_H
#define FRAMEWORKS_WM_SRC_TEST_INATIVE_TEST_TOUCH_EVENT_HANDLER_H
#include <graphic_bytrace.h>
#include "inative_test.h"
namespace OHOS {
class INativeTest;
class INativeTestTouchEventHandler : public MMI::TouchEventHandler {
public:
explicit INativeTestTouchEventHandler(INativeTest *test) : test_(test)
{
}
virtual bool OnTouch(const TouchEvent &event) override
{
ScopedBytrace trace(__func__);
return test_->OnTouch(event);
}
private:
INativeTest *test_ = nullptr;
};
} // namespace OHOS
#endif // FRAMEWORKS_WM_SRC_TEST_INATIVE_TEST_TOUCH_EVENT_HANDLER_H

View File

@ -20,6 +20,7 @@
#include <unistd.h>
#include <vector>
#include <gslogger.h>
#include <vsync_helper.h>
#include <window_manager.h>
@ -32,10 +33,14 @@ using namespace OHOS;
namespace {
void Usage(const char *argv0)
{
std::cerr << "Usage: " << argv0 << " [option] type id" << std::endl;
std::cerr << "-d, --display[=0] Created Window's Display ID" << std::endl;
GSLOG0SE(INFO) << "Usage: " << argv0 << " [option] type id";
GSLOG0SE(INFO) << " Option:";
GSLOG0SE(INFO) << " -d, --display[=0] Created Window's Display ID";
GSLOG0SE(INFO) << "";
GSLOG0SE(INFO) << " Available Tests: type, id, description (time) [process]";
auto visitFunc = [](const INativeTest *test) {
std::stringstream ss;
ss << " ";
ss << test->GetDomain() << ", id=";
ss << test->GetID() << ": ";
ss << test->GetDescription();
@ -43,10 +48,69 @@ void Usage(const char *argv0)
constexpr double msecToSec = 1000.0;
ss << " (last " << std::setprecision(1) << test->GetLastTime() / msecToSec << "s)";
}
std::cout << ss.str() << std::endl;
if (test->GetProcessNumber() <= 1) {
GSLOG0SE(INFO) << ss.str();
return false;
}
if (test->GetProcessSequence() == -1) {
ss << " [process number:" << test->GetProcessNumber() << "]";
GSLOG0SE(INFO) << ss.str();
return false;
}
ss << " [" << test->GetProcessSequence() << "/" << test->GetProcessNumber() << "]";
auto sss = ss.str();
auto size = sss.find_first_of(':') + 1;
sss.erase(0, size);
sss.insert(sss.begin(), size, ' ');
GSLOG0SE(INFO) << sss;
return false;
};
INativeTest::VisitTests(visitFunc);
}
bool GetTestFunc(INativeTest *test, MainOption &option)
{
if (test->GetDomain() != option.domain) {
return false;
}
if (test->GetID() != option.testcase) {
return false;
}
if (test->GetProcessSequence() != option.processSequence) {
return false;
}
return true;
};
int32_t LoadService(INativeTest *test)
{
if (test->GetAutoLoadService() & AutoLoadService::WindowManager) {
test->windowManager = WindowManager::GetInstance();
auto wret = test->windowManager->Init();
if (wret) {
GSLOG7SO(ERROR) << "WindowManager Init failed with " << WMErrorStr(wret);
return wret;
}
}
if (test->GetAutoLoadService() & AutoLoadService::WindowManagerService) {
auto wmsc = WindowManagerServiceClient::GetInstance();
auto wret = wmsc->Init();
if (wret) {
GSLOG7SO(ERROR) << "WindowManagerServiceClient Init failed with " << WMErrorStr(wret);
return wret;
}
test->windowManagerService = wmsc->GetService();
}
return 0;
}
} // namespace
int32_t main(int32_t argc, const char **argv)
@ -54,36 +118,38 @@ int32_t main(int32_t argc, const char **argv)
// parse option
MainOption option;
if (option.Parse(argc, argv)) {
std::cerr << option.GetErrorString() << std::endl;
GSLOG0SE(ERROR) << option.GetErrorString() << std::endl;
Usage(argv[0]);
GSLOG7SE(ERROR) << "exiting, return 1";
return 1;
}
// find test
INativeTest *found = nullptr;
auto visitFunc = [&option, &found](INativeTest *test) {
if (test->GetDomain() == option.domain && test->GetID() == option.testcase) {
found = test;
}
};
INativeTest::VisitTests(visitFunc);
auto visitFunc = std::bind(GetTestFunc, std::placeholders::_1, std::ref(option));
INativeTest *found = INativeTest::VisitTests(visitFunc);
if (found == nullptr) {
printf("not found test %d\n", option.testcase);
GSLOG7SE(ERROR) << "not found test " << option.testcase << ", exiting, return 1";
return 1;
}
// default value assign
NativeTestFactory::defaultDisplayID = option.displayID;
found->processArgv = argv;
if (LoadService(found)) {
GSLOG7SE(ERROR) << "exiting, return 1";
return 1;
}
// run test
auto runner = AppExecFwk::EventRunner::Create(false);
auto handler = std::make_shared<AppExecFwk::EventHandler>(runner);
handler->PostTask(std::bind(&INativeTest::Run, found, option.GetSkippedArgc(), option.GetSkippedArgv()));
found->SetEventHandler(std::move(std::make_shared<AppExecFwk::EventHandler>(runner)));
found->PostTask(std::bind(&INativeTest::Run, found, option.GetSkippedArgc(), option.GetSkippedArgv()));
if (found->GetLastTime() != INativeTest::LAST_TIME_FOREVER) {
handler->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner), found->GetLastTime());
found->PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner), found->GetLastTime());
}
printf("%d %s run! pid=%d\n", found->GetID(), found->GetDescription().c_str(), getpid());
runner->Run();
GSLOG7SO(INFO) << "exiting, return 0";
return 0;
}

View File

@ -20,6 +20,7 @@ MainOption::MainOption()
AddArguments(domain);
AddArguments(testcase);
AddOption("d", "display", displayID);
AddOption("p", "process", processSequence);
}
int32_t MainOption::Parse(int32_t argc, const char **argv)

View File

@ -27,6 +27,7 @@ public:
std::string domain = "";
int32_t testcase = -1;
int32_t displayID = 0;
int32_t processSequence = -1;
};
#endif // FRAMEWORKS_WMTEST_FRAMEWORKS_MAIN_OPTION_H

View File

@ -18,20 +18,15 @@
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <securec.h>
#include <sys/time.h>
#include <display_type.h>
#include <graphic_bytrace.h>
#include <securec.h>
#include "inative_test.h"
#include "util.h"
#define TIME_BASE 1000
#define TIMEMS_RANGER 0.5
#define SIZE_POS_VERTEX_ATTRIBUTE 2
#define SIZE_COLORS_VERTEX_ATTRIBUTE 3
#define NUMBER_VERTICES 4
namespace OHOS {
sptr<Window> NativeTestFactory::CreateWindow(WindowType type,
sptr<Surface> csurface,
@ -72,149 +67,9 @@ sptr<NativeTestSync> NativeTestSync::CreateSync(DrawFunc drawFunc, sptr<Surface>
return nullptr;
}
#ifdef ACE_ENABLE_GPU
sptr<NativeTestSync> NativeTestSync::CreateSyncEgl(DrawFuncEgl drawFunc,
sptr<EglSurface> &peglsurface, uint32_t width, uint32_t height, void *data)
{
if (drawFunc != nullptr && peglsurface != nullptr) {
sptr<NativeTestSync> nts = new NativeTestSync();
nts->drawEgl = drawFunc;
nts->eglsurface = peglsurface;
nts->width_ = width;
nts->height_ = height;
RequestSync(std::bind(&NativeTestSync::SyncEgl, nts, SYNC_FUNC_ARG), data);
return nts;
}
return nullptr;
}
void NativeTestSync::SyncEgl(int64_t, void *data)
{
if (!GLContextInit()) {
printf("GLContextInit failed.\n");
return;
}
if (sret == SURFACE_ERROR_OK) {
drawEgl(&glCtx, eglsurface, width_, height_);
count++;
}
sret = eglsurface->SwapBuffers();
RequestSync(std::bind(&NativeTestSync::SyncEgl, this, SYNC_FUNC_ARG), data);
}
#endif
#ifdef ACE_ENABLE_GPU
namespace {
const char *g_vertShaderText =
"uniform float offset;\n"
"attribute vec4 pos;\n"
"attribute vec4 color;\n"
"varying vec4 v_color;\n"
"void main() {\n"
" gl_Position = pos + vec4(offset, offset, 0.0, 0.0);\n"
" v_color = color;\n"
"}\n";
const char *g_fragShaderText =
"precision mediump float;\n"
"varying vec4 v_color;\n"
"void main() {\n"
" gl_FragColor = v_color;\n"
"}\n";
static GLuint CreateShader(const char *source, GLenum shaderType)
{
GLuint shader;
GLint status;
shader = glCreateShader(shaderType);
assert(shader != 0);
glShaderSource(shader, 1, (const char **) &source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
constexpr int32_t maxLogLength = 1000;
char log[maxLogLength];
GLsizei len;
glGetShaderInfoLog(shader, maxLogLength, &len, log);
fprintf(stderr, "Error: compiling %s: %.*s\n",
shaderType == GL_VERTEX_SHADER ? "vertex" : "fragment", len, log);
return 0;
}
return shader;
}
static GLuint CreateAndLinkProgram(GLuint vert, GLuint frag)
{
GLint status;
GLuint program = glCreateProgram();
glAttachShader(program, vert);
glAttachShader(program, frag);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (!status) {
constexpr int32_t maxLogLength = 1000;
char log[maxLogLength];
GLsizei len;
glGetProgramInfoLog(program, maxLogLength, &len, log);
fprintf(stderr, "Error: linking:\n%.*s\n", len, log);
return 0;
}
return program;
}
} // namespace
bool NativeTestSync::GLContextInit()
{
if (bInit) {
return bInit;
}
if (eglsurface == nullptr) {
printf("GLContextInit eglsurface is nullptr\n");
return bInit;
}
if (eglsurface->InitContext() != SURFACE_ERROR_OK) {
printf("GLContextInit InitContext failed\n");
return bInit;
}
GLuint vert = CreateShader(g_vertShaderText, GL_VERTEX_SHADER);
GLuint frag = CreateShader(g_fragShaderText, GL_FRAGMENT_SHADER);
glCtx.program = CreateAndLinkProgram(vert, frag);
glDeleteShader(vert);
glDeleteShader(frag);
glCtx.pos = glGetAttribLocation(glCtx.program, "pos");
glCtx.color = glGetAttribLocation(glCtx.program, "color");
glUseProgram(glCtx.program);
glCtx.offsetUniform = glGetUniformLocation(glCtx.program, "offset");
if (glCtx.program == 0) {
printf("glCtx.program = 0.\n");
} else {
bInit = true;
}
return bInit;
}
#endif
void NativeTestSync::Sync(int64_t, void *data)
{
ScopedBytrace trace(__func__);
if (surface == nullptr) {
printf("NativeTestSync surface is nullptr\n");
return;
@ -256,6 +111,77 @@ void NativeTestSync::Sync(int64_t, void *data)
RequestSync(std::bind(&NativeTestSync::Sync, this, SYNC_FUNC_ARG), data);
}
sptr<NativeTestDrawer> NativeTestDrawer::CreateDrawer(DrawFunc drawFunc, sptr<Surface> &psurface, void *data)
{
if (drawFunc != nullptr && psurface != nullptr) {
sptr<NativeTestDrawer> ntd = new NativeTestDrawer();
ntd->draw = drawFunc;
ntd->surface = psurface;
ntd->data = data;
return ntd;
}
return nullptr;
}
void NativeTestDrawer::SetDrawFunc(DrawFunc draw)
{
this->draw = draw;
}
void NativeTestDrawer::DrawOnce()
{
if (isDrawing == false) {
RequestSync(std::bind(&NativeTestDrawer::Sync, this, SYNC_FUNC_ARG), data);
isDrawing = true;
}
}
void NativeTestDrawer::Sync(int64_t, void *data)
{
ScopedBytrace trace(__func__);
if (surface == nullptr) {
printf("NativeTestDrawer surface is nullptr\n");
return;
}
if (isDrawing == true) {
isDrawing = false;
}
sptr<SurfaceBuffer> buffer;
BufferRequestConfig rconfig = {
.width = surface->GetDefaultWidth(),
.height = surface->GetDefaultHeight(),
.strideAlignment = 0x8,
.format = PIXEL_FMT_RGBA_8888,
.usage = surface->GetDefaultUsage(),
.timeout = 0,
};
if (data != nullptr) {
rconfig = *reinterpret_cast<BufferRequestConfig *>(data);
}
SurfaceError ret = surface->RequestBufferNoFence(buffer, rconfig);
if (ret == SURFACE_ERROR_NO_BUFFER) {
DrawOnce();
return;
} else if (ret != SURFACE_ERROR_OK || buffer == nullptr) {
printf("NativeTestDrawer surface request buffer failed\n");
return;
}
draw(buffer->GetVirAddr(), rconfig.width, rconfig.height, count);
count++;
BufferFlushConfig fconfig = {
.damage = {
.w = rconfig.width,
.h = rconfig.height,
},
};
surface->FlushBuffer(buffer, -1, fconfig);
}
void NativeTestDraw::FlushDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count)
{
auto addr = static_cast<uint8_t *>(vaddr);
@ -379,8 +305,7 @@ void NativeTestDraw::RainbowDraw(void *vaddr, uint32_t width, uint32_t height, u
(func(index + rOffset * (height / 0x6)) << rShift);
};
constexpr uint32_t framerate = 100;
uint32_t offset = (count % framerate) * height / framerate;
uint32_t offset = (count % RainbowDrawFramerate) * height / RainbowDrawFramerate;
for (uint32_t i = 0; i < height; i++) {
auto color = selectColor(offset + i);
drawOneLine(i, color);
@ -440,50 +365,16 @@ void NativeTestDraw::BoxDraw(void *vaddr, uint32_t width, uint32_t height, uint3
drawOnce(abs((count + 1) % (framecount * 0x2 - 1) - framecount), color);
}
#ifdef ACE_ENABLE_GPU
void NativeTestDraw::FlushDrawEgl(GlContext *ctx, sptr<EglSurface> &eglsurface, uint32_t width, uint32_t height)
void NativeTestDraw::PureColorDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count, uint32_t *color)
{
/* Complete a movement iteration in 5000 ms. */
static const uint64_t iterationMs = 5000;
static const GLfloat verts[4][2] = {
{ -0.5, -0.5 },
{ -0.5, 0.5 },
{ 0.5, -0.5 },
{ 0.5, 0.5 }
};
static const GLfloat colors[4][3] = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 },
{ 1, 1, 0 }
};
GLfloat offset;
struct timeval tv;
uint64_t timeMs;
auto addr = static_cast<uint32_t *>(vaddr);
if (addr == nullptr || color == nullptr) {
return;
}
gettimeofday(&tv, NULL);
timeMs = tv.tv_sec * TIME_BASE + tv.tv_usec / TIME_BASE;
/* Split time_ms in repeating windows of [0, iterationMs) and map them
* to offsets in the [-0.5, 0.5) range. */
offset = (timeMs % iterationMs) / (float) iterationMs - TIMEMS_RANGER;
glViewport(0, 0, width, height);
glUniform1f(ctx->offsetUniform, offset);
glClearColor(0.0, 1.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(ctx->pos, SIZE_POS_VERTEX_ATTRIBUTE, GL_FLOAT, GL_FALSE, 0, verts);
glVertexAttribPointer(ctx->color, SIZE_COLORS_VERTEX_ATTRIBUTE, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(ctx->pos);
glEnableVertexAttribArray(ctx->color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, NUMBER_VERTICES);
glDisableVertexAttribArray(ctx->pos);
glDisableVertexAttribArray(ctx->color);
uint32_t c = *color;
for (uint32_t i = 0; i < width * height; i++) {
addr[i] = c;
}
}
#endif
} // namespace OHOS

View File

@ -23,21 +23,7 @@
#include <refbase.h>
#include <window_manager.h>
#ifdef ACE_ENABLE_GPU
#include <egl_surface.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif
namespace OHOS {
#ifdef ACE_ENABLE_GPU
typedef struct {
GLuint program;
GLuint pos;
GLuint color;
GLuint offsetUniform;
} GlContext;
#endif
class NativeTestFactory {
public:
@ -48,18 +34,9 @@ public:
};
using DrawFunc = std::function<void(void *, uint32_t, uint32_t, uint32_t)>;
#ifdef ACE_ENABLE_GPU
using DrawFuncEgl = std::function<void(GlContext *,
sptr<EglSurface> &psurface, uint32_t width, uint32_t height)>;
#endif
class NativeTestSync : public RefBase {
public:
static sptr<NativeTestSync> CreateSync(DrawFunc drawFunc, sptr<Surface> &psurface, void *data = nullptr);
#ifdef ACE_ENABLE_GPU
static sptr<NativeTestSync> CreateSyncEgl(DrawFuncEgl drawFunc,
sptr<EglSurface> &psurface, uint32_t width, uint32_t height, void *data = nullptr);
#endif
private:
void Sync(int64_t, void *);
@ -67,18 +44,24 @@ private:
sptr<Surface> surface = nullptr;
DrawFunc draw = nullptr;
uint32_t count = 0;
};
#ifdef ACE_ENABLE_GPU
void SyncEgl(int64_t, void *);
bool GLContextInit();
sptr<EglSurface> eglsurface = nullptr;
DrawFuncEgl drawEgl = nullptr;
GlContext glCtx;
bool bInit = false;
SurfaceError sret = SURFACE_ERROR_OK;
uint32_t width_ = 0;
uint32_t height_ = 0;
#endif
class NativeTestDrawer : public RefBase {
public:
static sptr<NativeTestDrawer> CreateDrawer(DrawFunc drawFunc, sptr<Surface> &psurface, void *data = nullptr);
void SetDrawFunc(DrawFunc draw);
void DrawOnce();
private:
void Sync(int64_t, void *);
sptr<Surface> surface = nullptr;
DrawFunc draw = nullptr;
uint32_t count = 0;
bool isDrawing = false;
void *data = nullptr;
};
class NativeTestDraw {
@ -87,10 +70,9 @@ public:
static void ColorDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count);
static void BlackDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count);
static void RainbowDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count);
static inline constexpr int32_t RainbowDrawFramerate = 100;
static void BoxDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count);
#ifdef ACE_ENABLE_GPU
static void FlushDrawEgl(GlContext *ctx, sptr<EglSurface> &eglsurface, uint32_t width, uint32_t height);
#endif
static void PureColorDraw(void *vaddr, uint32_t width, uint32_t height, uint32_t count, uint32_t *color);
};
} // namespace OHOS

View File

@ -19,6 +19,8 @@
#include <thread>
#include <unistd.h>
#include <gslogger.h>
using namespace std::chrono_literals;
namespace OHOS {
@ -42,26 +44,6 @@ uint32_t RequestSync(const SyncFunc syncFunc, void *data)
return VsyncHelper::Current()->RequestFrameCallback(cb);
}
void PostTask(std::function<void()> func, uint32_t delayTime)
{
auto handler = AppExecFwk::EventHandler::Current();
if (handler) {
handler->PostTask(func, delayTime);
}
}
void ExitTest()
{
auto runner = AppExecFwk::EventRunner::Current();
if (runner) {
printf("exiting\n");
PostTask(std::bind(&AppExecFwk::EventRunner::Stop, runner));
} else {
printf("exit\n");
exit(0);
}
}
int64_t GetNowTime()
{
auto now = std::chrono::steady_clock::now().time_since_epoch();

View File

@ -24,8 +24,6 @@
namespace OHOS {
void SetVsyncRate(int32_t rate);
uint32_t RequestSync(const SyncFunc syncFunc, void *data = nullptr);
void PostTask(std::function<void()> func, uint32_t delayTime = 0);
void ExitTest();
int64_t GetNowTime();
} // namespace OHOS

View File

@ -60,7 +60,7 @@ public:
int32_t signals[] = {SIGINT, SIGKILL, SIGTERM, SIGTSTP, SIGQUIT, SIGHUP};
for (uint32_t i = 0; i < sizeof(signals) / sizeof(*signals); i++) {
if (signals[i] == signal) {
ExitTest();
exit(0);
break;
}
}

View File

@ -71,7 +71,7 @@ public:
auto subpsurface = subwindow->GetSurface();
config.width = subpsurface->GetDefaultWidth();
config.height = subpsurface->GetDefaultHeight();
config.strideAlignment = 0x8,
config.strideAlignment = 0x8;
config.format = PIXEL_FMT_RGBA_8888;
config.usage = subpsurface->GetDefaultUsage();
subwindowSync = NativeTestSync::CreateSync(NativeTestDraw::RainbowDraw, subpsurface, &config);

View File

@ -119,13 +119,28 @@ public:
return;
}
window->SwitchTop();
auto onSizeChange = [this](uint32_t w, uint32_t h) {
printf("onSizeChange %u %u\n", w, h);
config.width = w;
config.height = h;
window->Resize(w, h);
};
window->OnSizeChange(onSizeChange);
auto surface = window->GetSurface();
windowSync = NativeTestSync::CreateSync(NativeTestDraw::FlushDraw, surface);
config.width = surface->GetDefaultWidth();
config.height = surface->GetDefaultHeight();
config.strideAlignment = 0x8;
config.format = PIXEL_FMT_RGBA_8888;
config.usage = surface->GetDefaultUsage();
window->SwitchTop();
windowSync = NativeTestSync::CreateSync(NativeTestDraw::FlushDraw, surface, &config);
}
private:
sptr<Window> window = nullptr;
sptr<NativeTestSync> windowSync = nullptr;
BufferRequestConfig config = {};
} g_autoload;
} // namespace

View File

@ -0,0 +1,441 @@
/*
* Copyright (c) 2021 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.
*/
#include "wmclient_native_test_20.h"
#include <chrono>
#include <cstdio>
#include <sstream>
#include <thread>
#include <unistd.h>
#include <cpudraw.h>
#include <graphic_bytrace.h>
#include <gslogger.h>
#include <ipc_object_stub.h>
#include <option_parser.h>
#include <window_manager.h>
#include <window_manager_service_client.h>
#include "inative_test.h"
#include "native_test_class.h"
#include "util.h"
using namespace OHOS;
using namespace std::chrono_literals;
namespace {
class WMClientNativeTest20 : public INativeTest {
public:
virtual std::string GetDescription() const override
{
constexpr const char *desc = "split mode";
return desc;
}
virtual std::string GetDomain() const override
{
constexpr const char *domain = "wmclient";
return domain;
}
virtual int32_t GetID() const override
{
constexpr int32_t id = 20;
return id;
}
virtual enum AutoLoadService GetAutoLoadService() const override
{
return AutoLoadService::WindowManager;
}
virtual int32_t GetProcessNumber() const override
{
return 3;
}
virtual void Run(int32_t argc, const char **argv) override
{
GSLOG7SO(INFO) << "fork return: " << StartSubprocess(0);
GSLOG7SO(INFO) << "fork return: " << StartSubprocess(1);
ExitTest();
}
} g_autoload;
class WMClientNativeTest20Sub0 : public WMClientNativeTest20 {
public:
virtual std::string GetDescription() const override
{
constexpr const char *desc = "splited application mocker";
return desc;
}
virtual int32_t GetProcessSequence() const override
{
return 0;
}
virtual void Run(int32_t argc, const char **argv) override
{
ScopedBytrace trace(__func__);
GSLOG7SO(INFO) << getpid() << " run0";
window = NativeTestFactory::CreateWindow(WINDOW_TYPE_NORMAL);
if (window == nullptr) {
GSLOG7SO(ERROR) << "NativeTestFactory::CreateWindow return nullptr";
ExitTest();
return;
}
auto onSizeChange = [this](uint32_t w, uint32_t h) {
GSLOG7SO(INFO) << "onSizeChange " << w << "x" << h;
config.width = w;
config.height = h;
window->Resize(w, h);
PostTask(std::bind(&NativeTestDrawer::DrawOnce, windowDrawer));
};
window->OnSizeChange(onSizeChange);
auto func = std::bind(&WMClientNativeTest20Sub0::OnSplitStatusChange, this, std::placeholders::_1);
window->OnSplitStatusChange(func);
ListenWindowInputEvent(window->GetID());
auto surface = window->GetSurface();
config.width = surface->GetDefaultWidth();
config.height = surface->GetDefaultHeight();
config.strideAlignment = 0x8;
config.format = PIXEL_FMT_RGBA_8888;
config.usage = surface->GetDefaultUsage();
window->SwitchTop();
auto draw = std::bind(&WMClientNativeTest20Sub0::Draw, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
windowDrawer = NativeTestDrawer::CreateDrawer(draw, surface, &config);
windowDrawer->DrawOnce();
}
void Draw(void *vaddr, uint32_t width, uint32_t height, uint32_t count)
{
ScopedBytrace trace(__func__);
count = NativeTestDraw::RainbowDrawFramerate / 0x2;
if (adjStatus == SPLIT_STATUS_CLEAR) {
count = 0;
}
NativeTestDraw::RainbowDraw(vaddr, width, height, count);
}
virtual bool OnKey(const KeyEvent &event) override
{
GSLOG7SO(DEBUG) << "[" << event.GetKeyCode() << "]";
if (event.IsKeyDown() == true && event.GetKeyCode() == KeyEventEnum::KEY_BACK) {
ExitTest();
return false;
}
return true;
}
virtual bool OnTouch(const TouchEvent &event) override
{
if (event.GetAction() == TouchEnum::PRIMARY_POINT_DOWN) {
window->SwitchTop();
}
GSLOG7SO(DEBUG) << "[" << event.GetAction() << "]"
<< "(" << event.GetPointerPosition(event.GetIndex()).GetX()
<< ", " << event.GetPointerPosition(event.GetIndex()).GetY()
<< ")";
return false;
}
void OnSplitStatusChange(SplitStatus status)
{
ScopedBytrace trace(__func__);
if (status == SPLIT_STATUS_DESTROY) {
GSLOG7SO(INFO) << "SPLIT_STATUS_DESTROY";
ExitTest();
} else if (status == SPLIT_STATUS_RETAIN) {
GSLOG7SO(INFO) << "SPLIT_STATUS_RETAIN";
adjStatus = SPLIT_STATUS_CLEAR;
PostTask(std::bind(&NativeTestDrawer::DrawOnce, windowDrawer));
} else {
if (adjStatus != status) {
GSLOG7SO(INFO) << "SPLIT_STATUS_" << status;
}
adjStatus = status;
PostTask(std::bind(&NativeTestDrawer::DrawOnce, windowDrawer));
}
}
protected:
sptr<NativeTestDrawer> windowDrawer = nullptr;
SplitStatus adjStatus = SPLIT_STATUS_CLEAR;
private:
sptr<Window> window = nullptr;
BufferRequestConfig config = {};
} g_autoload0;
class WMClientNativeTest20Sub1 : public WMClientNativeTest20 {
public:
virtual std::string GetDescription() const override
{
constexpr const char *desc = "systemui mocker";
return desc;
}
virtual int32_t GetProcessSequence() const override
{
return 1;
}
virtual enum AutoLoadService GetAutoLoadService() const override
{
return AutoLoadService::WindowManager | AutoLoadService::WindowManagerService;
}
virtual void Run(int32_t argc, const char **argv) override
{
ScopedBytrace trace(__func__);
window = NativeTestFactory::CreateWindow(WINDOW_TYPE_SYSTEM_UI);
if (window == nullptr) {
GSLOG7SO(ERROR) << "NativeTestFactory::CreateWindow return nullptr";
ExitTest();
return;
}
auto surface = window->GetSurface();
window->SwitchTop();
auto draw = std::bind(&WMClientNativeTest20Sub1::Draw, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
windowDrawer = NativeTestDrawer::CreateDrawer(draw, surface);
windowDrawer->DrawOnce();
for (auto &icon : icons) {
icon.rect.x *= window->GetWidth();
icon.rect.y *= window->GetHeight();
icon.rect.w *= window->GetWidth();
icon.rect.h *= window->GetHeight();
}
total.x *= window->GetWidth();
total.y *= window->GetHeight();
total.w *= window->GetWidth();
total.h *= window->GetHeight();
ListenWindowInputEvent(window->GetID());
}
void Draw(void *vaddr, uint32_t width, uint32_t height, uint32_t count)
{
ScopedBytrace trace(__func__);
GSLOG7SO(INFO) << "currentIcon: " << currentIcon;
CPUDraw draw(vaddr, width, height);
draw.SetColor(0x00000000);
draw.DrawRect(0, 0, width, height);
draw.SetColor(0xffffffff);
draw.DrawRect(total);
draw.SetColor(0xffaaaaaa);
draw.SetBorder(0x2);
draw.DrawBorder(total);
for (auto &icon : icons) {
draw.SetColor(icon.c);
draw.DrawRect(icon.rect);
}
}
virtual bool OnKey(const KeyEvent &event) override
{
GSLOG7SO(DEBUG) << "[" << event.GetKeyCode() << "]";
if (event.IsKeyDown() == true && event.GetKeyCode() == KeyEventEnum::KEY_BACK) {
ExitTest();
return false;
}
return true;
}
virtual bool OnTouch(const TouchEvent &event) override
{
ScopedBytrace trace(__func__);
if (event.GetAction() == TouchEnum::PRIMARY_POINT_DOWN) {
window->SwitchTop();
}
int32_t index = event.GetIndex();
int32_t x = event.GetPointerPosition(index).GetX();
int32_t y = event.GetPointerPosition(index).GetY();
if (event.GetAction() == TouchEnum::PRIMARY_POINT_DOWN) {
downX = x;
downY = y;
currentIcon = nullptr;
for (auto &icon : icons) {
if (icon.rect.Contain(x, y)) {
currentIcon = &icon;
backupIcon = icon;
GSLOG7SO(INFO) << "selected: " << currentIcon
<< " " << currentIcon->rect.x << ", " << currentIcon->rect.y;
if (currentIcon != &icons[0]) {
SetSplitMode(SPLIT_MODE_SINGLE);
} else {
SetSplitMode(SPLIT_MODE_UNENABLE);
}
break;
}
}
return false;
}
if (event.GetAction() == TouchEnum::POINT_MOVE && currentIcon) {
currentIcon->rect.x = backupIcon.rect.x + x - downX;
currentIcon->rect.y = backupIcon.rect.y + y - downY;
PostTask(std::bind(&NativeTestDrawer::DrawOnce, windowDrawer));
if (currentIcon != &icons[0]) {
if (total.Contain(x, y)) {
SetSplitMode(SPLIT_MODE_SINGLE);
} else {
static int32_t lastX = -1;
static int32_t lastY = -1;
if (lastX != x || lastY != y) {
SetSplitMode(SPLIT_MODE_SELECT, x, y);
}
lastX = x;
lastY = y;
}
}
return false;
}
if (event.GetAction() == TouchEnum::PRIMARY_POINT_UP && currentIcon) {
if (currentIcon != &icons[0]) {
// center point (x, y)
auto x = currentIcon->rect.x + currentIcon->rect.w / 0x2;
auto y = currentIcon->rect.y + currentIcon->rect.y / 0x2;
if (total.Contain(x, y)) {
SetSplitMode(SPLIT_MODE_NULL);
} else {
StartProcess2();
return false;
}
} else {
SetSplitMode(SPLIT_MODE_NULL);
}
*currentIcon = backupIcon;
PostTask(std::bind(&NativeTestDrawer::DrawOnce, windowDrawer));
return false;
}
return true;
}
SplitMode lastMode = SPLIT_MODE_NULL;
void SetSplitMode(SplitMode mode, int32_t x = 0, int32_t y = 0)
{
ScopedBytrace trace(__func__);
if (lastMode != mode) {
GSLOG7SO(INFO) << static_cast<int32_t>(mode);
lastMode = mode;
}
windowManagerService->SetSplitMode(mode, x, y);
}
void StartProcess2()
{
extraArgs.clear();
std::stringstream ss;
ss << "--color=" << std::hex << std::showbase << currentIcon->c;
auto sss = ss.str();
extraArgs.push_back(sss.c_str());
GSLOG7SO(INFO) << "fork return: " << StartSubprocess(2);
std::this_thread::sleep_for(1s);
SetSplitMode(SPLIT_MODE_CONFIRM);
ExitTest();
return;
}
private:
sptr<Window> window = nullptr;
sptr<NativeTestDrawer> windowDrawer = nullptr;
static constexpr double xx = 0.7;
static constexpr double ww = 0.3;
static constexpr double yy = 0.1;
static constexpr double hh = 0.8;
struct Position {
struct CPUDrawRect rect;
uint32_t c;
};
struct Position icons[0x4] = {
{ { xx + 0.15 * ww, yy + 1 * hh / 9, 0.7 * ww, hh / 9 }, 0xffff0000 },
{ { xx + 0.15 * ww, yy + 3 * hh / 9, 0.7 * ww, hh / 9 }, 0xff00ff00 },
{ { xx + 0.15 * ww, yy + 5 * hh / 9, 0.7 * ww, hh / 9 }, 0xff0000ff },
{ { xx + 0.15 * ww, yy + 7 * hh / 9, 0.7 * ww, hh / 9 }, 0xffff00ff },
};
struct Position *currentIcon = nullptr;
struct Position backupIcon;
struct CPUDrawRect total = { xx, yy, ww, hh };
int32_t downX = 0;
int32_t downY = 0;
} g_autoload1;
class WMClientNativeTest20Sub2 : public WMClientNativeTest20Sub0 {
public:
virtual std::string GetDescription() const override
{
constexpr const char *desc = "spliting application mocker";
return desc;
}
virtual int32_t GetProcessSequence() const override
{
return 2;
}
virtual void Run(int32_t argc, const char **argv) override
{
OptionParser parser;
parser.AddOption("c", "color", color);
if (parser.Parse(argc, argv)) {
GSLOG7SE(ERROR) << parser.GetErrorString();
ExitTest();
return;
}
GSLOG7SO(INFO) << "color: " << std::hex << std::showbase << color;
WMClientNativeTest20Sub0::Run(argc, argv);
auto draw = std::bind(&WMClientNativeTest20Sub2::Draw, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
windowDrawer->SetDrawFunc(draw);
windowDrawer->DrawOnce();
}
void Draw(void *vaddr, uint32_t width, uint32_t height, uint32_t count)
{
ScopedBytrace trace(__func__);
CPUDraw draw(vaddr, width, height);
draw.SetColor(color);
if (adjStatus == SPLIT_STATUS_VAGUE) {
draw.SetColor((0xffffffff - color) | 0xff000000);
}
draw.DrawRect(0, 0, width, height);
}
private:
uint32_t color = 0xffff0000;
} g_autoload2;
} // namespace

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2021 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 FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_20_H
#define FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_20_H
#endif // FRAMEWORKS_WMTEST_TEST_WMCLIENT_WMCLIENT_NATIVE_TEST_20_H

View File

@ -22,6 +22,7 @@
#include "inative_test.h"
#include "native_test_class.h"
#include "egl_native_test_class.h"
#include "util.h"
using namespace OHOS;

View File

@ -59,9 +59,7 @@ public:
::std::placeholders::_3, ::std::placeholders::_4);
mainSync = NativeTestSync::CreateSync(draw, surface);
token_ = new IPCObjectStub(u"token");
keyEventHandle_ = new KeyEventHandle(this);
MMIEventHdl.RegisterStandardizedEventHandle(token_, mainWindow->GetID(), keyEventHandle_);
ListenWindowKeyEvent(mainWindow->GetID());
}
void EnterPIPMode()
@ -100,10 +98,7 @@ public:
::std::placeholders::_3, ::std::placeholders::_4);
pipSync = NativeTestSync::CreateSync(draw, pipSurface);
token_ = new IPCObjectStub(u"token");
touchEventHandle_ = new TouchEventHandle(this);
MMIEventHdl.RegisterStandardizedEventHandle(token_, pipWindow->GetID(), touchEventHandle_);
ListenWindowTouchEvent(pipWindow->GetID());
int x = 100, y = 100, w = 300, h = 200;
pipWindow->Move(x, y);
@ -137,15 +132,15 @@ public:
onPIPModeChange = func;
}
bool OnKeyPrivate(const KeyEvent &event)
virtual bool OnKey(const KeyEvent &event) override
{
if (event.IsKeyDown() == true && event.GetKeyCode() == OHOS::KeyEventEnum::KEY_BACK) {
return OnKey(event);
return OnKeyPublic(event);
}
return false;
}
bool OnTouchPrivate(const TouchEvent &event)
virtual bool OnTouch(const TouchEvent &event) override
{
int index = event.GetIndex();
if (event.GetAction() == OHOS::TouchEnum::POINT_MOVE) {
@ -157,7 +152,7 @@ public:
touchUpFlag = false;
return true;
} else if (event.GetAction() == OHOS::TouchEnum::PRIMARY_POINT_UP && touchUpFlag == true) {
return OnTouch(event);
return OnTouchPublic(event);
} else if (event.GetAction() == OHOS::TouchEnum::PRIMARY_POINT_UP && touchUpFlag == false) {
DownX = 0;
DownY = 0;
@ -176,49 +171,15 @@ public:
}
}
virtual bool OnKey(const KeyEvent &event) = 0;
virtual bool OnTouch(const TouchEvent &event) = 0;
virtual bool OnKeyPublic(const KeyEvent &event) = 0;
virtual bool OnTouchPublic(const TouchEvent &event) = 0;
private:
class KeyEventHandle : public MMI::KeyEventHandler {
public:
explicit KeyEventHandle(WMClientNativeTest32Ability *test) : test(test)
{
}
virtual bool OnKey(const KeyEvent &event) override
{
return test->OnKeyPrivate(event);
}
private:
WMClientNativeTest32Ability *test;
};
class TouchEventHandle : public MMI::TouchEventHandler {
public:
explicit TouchEventHandle(WMClientNativeTest32Ability *test) : test(test)
{
}
virtual bool OnTouch(const TouchEvent &event) override
{
return test->OnTouchPrivate(event);
}
private:
WMClientNativeTest32Ability *test;
};
sptr<Window> mainWindow = nullptr;
sptr<Window> pipWindow = nullptr;
sptr<NativeTestSync> mainSync = nullptr;
sptr<NativeTestSync> pipSync = nullptr;
sptr<IRemoteObject> token_ = nullptr;
sptr<KeyEventHandle> keyEventHandle_ = nullptr;
sptr<TouchEventHandle> touchEventHandle_ = nullptr;
bool pipMode = false;
bool touchUpFlag = true;
std::function<void(bool)> onPIPModeChange = nullptr;
@ -274,13 +235,13 @@ public:
}
}
bool OnTouch(const TouchEvent &event) override
virtual bool OnTouchPublic(const TouchEvent &event) override
{
ExitPIPMode();
return true;
}
bool OnKey(const KeyEvent &event) override
virtual bool OnKeyPublic(const KeyEvent &event) override
{
drawptr = NativeTestDraw::ColorDraw;
EnterPIPMode();
@ -291,4 +252,4 @@ public:
private:
DrawFunc drawptr = NativeTestDraw::FlushDraw;
} g_autoload;
} // namespace
} // namespace

View File

@ -56,6 +56,7 @@ public:
virtual void OnVisibilityChange(WindowVisibilityChangeFunc func) = 0;
virtual void OnTypeChange(WindowTypeChangeFunc func) = 0;
virtual void OnModeChange(WindowModeChangeFunc func) = 0;
virtual void OnSplitStatusChange(SplitStatusChangeFunc func) = 0;
// listener
virtual WMError OnTouch(OnTouchFunc cb) = 0;

View File

@ -67,6 +67,33 @@ enum DisplayType {
DISPLAY_TYPE_VIRTUAL,
DISPLAY_TYPE_MAX,
};
enum SplitStatus {
SPLIT_STATUS_CLEAR = 0,
SPLIT_STATUS_VAGUE = 1,
SPLIT_STATUS_RETAIN = 2,
SPLIT_STATUS_DESTROY = 3,
SPLIT_STATUS_MAX,
};
enum WindowSplitMode {
WINDOW_SPLIT_MODE_UNSET = 0,
WINDOW_SPLIT_MODE_SET = 1,
WINDOW_SPLIT_MODE_MAX,
};
enum SplitMode {
SPLIT_MODE_NULL = 0,
SPLIT_MODE_UNENABLE = 1,
SPLIT_MODE_SINGLE = 2,
SPLIT_MODE_SELECT = 3,
SPLIT_MODE_CONFIRM = 4,
SPLIT_MODE_DIVIDER_TOUCH_DOWN = 5,
SPLIT_MODE_DIVIDER_TOUCH_MOVE = 6,
SPLIT_MODE_DIVIDER_TOUCH_UP = 7,
SPLIT_MODE_MAX,
};
struct WMDisplayInfo {
int32_t id;
uint32_t width;
@ -78,8 +105,9 @@ struct WMDisplayInfo {
};
#ifdef __cplusplus
using WindowModeChangeFunc = std::function<void(WindowMode mode)>;
using BeforeFrameSubmitFunc = std::function<void()>;
using WindowModeChangeFunc = std::function<void(WindowMode mode)>;
using BeforeFrameSubmitFunc = std::function<void()>;
using SplitStatusChangeFunc = std::function<void(SplitStatus status)>;
} // namespace OHOS
#endif

View File

@ -54,6 +54,7 @@ namespace OHOS {
macro(WINDOW_TYPE_TOAST), \
macro(WINDOW_TYPE_WALLPAPER), \
macro(WINDOW_TYPE_ANIMATION), \
macro(WINDOW_TYPE_SPLIT_LINE), \
macro(WINDOW_TYPE_MAX),
#define DEFINE_ENUM_WINDOW_TYPE(id) id

View File

@ -25,6 +25,7 @@
#include "iwindow_change_listener_clazz.h"
#include "iwindow_manager_display_listener_clazz.h"
#include "window_manager_service_type.h"
namespace OHOS {
@ -65,6 +66,8 @@ public:
virtual sptr<PromiseWMError> DestroyVirtualDisplay(uint32_t did) = 0;
virtual GSError StartRotationAnimation(uint32_t did, int32_t degree) = 0;
virtual sptr<PromiseWMError> SetSplitMode(SplitMode mode, int32_t x = 0, int32_t y = 0) = 0;
};
} // namespace OHOS

View File

@ -56,6 +56,7 @@ using PromiseWMError = Promise<WMError>;
using PromiseWMSImageInfo = Promise<WMSImageInfo>;
using PromisePowerStatus = Promise<PowerStatus>;
using PromiseBacklight = Promise<Backlight>;
} // namespace OHOS
#endif // INTERFACES_INNERKITS_WMSERVICE_WINDOW_MANAGER_SERVICE_TYPE_H

View File

@ -46,3 +46,7 @@ group("matrix") {
group("raw_parser") {
public_deps = [ "raw_parser:raw_parser" ]
}
group("cpudraw") {
public_deps = [ "cpudraw:cpudraw" ]
}

40
utils/cpudraw/BUILD.gn Normal file
View File

@ -0,0 +1,40 @@
# Copyright (c) 2021 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.
import("//build/ohos.gni")
## Build cpudraw.a {{{
config("cpudraw_config") {
visibility = [ ":*" ]
cflags = [
"-Wall",
"-Werror",
"-g3",
]
}
config("cpudraw_public_config") {
include_dirs = [ "export" ]
}
ohos_static_library("cpudraw") {
sources = [ "src/cpudraw.cpp" ]
configs = [ ":cpudraw_config" ]
public_configs = [ ":cpudraw_public_config" ]
deps = [ "..:graphic_bytrace" ]
}
## Build cpudraw.a }}}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2021 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 UTILS_INCLUDE_CPUDRAW_EXPORT_CPUDRAW_H
#define UTILS_INCLUDE_CPUDRAW_EXPORT_CPUDRAW_H
#include <cstdint>
struct CPUDrawRect {
double x;
double y;
double w;
double h;
bool Contain(int32_t x2, int32_t y2);
};
class CPUDraw {
public:
CPUDraw(void *vaddr, int32_t width, int32_t height);
void SetColor(const uint32_t &color);
void SetBorder(const int32_t &border);
void DrawBorder(const int32_t &x, const int32_t &y, const int32_t &w, const int32_t &h);
void DrawBorder(const struct CPUDrawRect &rect);
void DrawRect(const int32_t &x, const int32_t &y, const int32_t &w, const int32_t &h);
void DrawRect(const struct CPUDrawRect &rect);
private:
int32_t Min(const int32_t &a, const int32_t &b);
int32_t Max(const int32_t &a, const int32_t &b);
uint32_t *addr = nullptr;
int32_t width = 0;
int32_t height = 0;
uint32_t color = 0xffffffff;
int32_t border = 0;
};
#endif // UTILS_INCLUDE_CPUDRAW_EXPORT_CPUDRAW_H

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2021 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.
*/
#include "cpudraw.h"
#include <graphic_bytrace.h>
bool CPUDrawRect::Contain(int32_t x2, int32_t y2)
{
return x <= x2 && x2 <= x + w && y <= y2 && y2 <= y + h;
}
CPUDraw::CPUDraw(void *vaddr, int32_t width, int32_t height)
: addr(reinterpret_cast<uint32_t *>(vaddr)), width(width), height(height)
{
}
void CPUDraw::SetColor(const uint32_t &color)
{
this->color = color;
}
void CPUDraw::SetBorder(const int32_t &border)
{
this->border = border;
}
void CPUDraw::DrawBorder(const struct CPUDrawRect &rect)
{
DrawBorder(rect.x, rect.y, rect.w, rect.h);
}
void CPUDraw::DrawBorder(const int32_t &x, const int32_t &y, const int32_t &w, const int32_t &h)
{
ScopedBytrace trace(__func__);
DrawRect(x, y, border, h);
DrawRect(x + w - border, y, border, h);
DrawRect(x, y, w, border);
DrawRect(x, y + h - border, w, border);
}
void CPUDraw::DrawRect(const struct CPUDrawRect &rect)
{
DrawRect(rect.x, rect.y, rect.w, rect.h);
}
void CPUDraw::DrawRect(const int32_t &x, const int32_t &y, const int32_t &w, const int32_t &h)
{
ScopedBytrace trace(__func__);
for (int32_t j = Max(y, 0); j < Min(y + h, height); j++) {
for (int32_t i = Max(x, 0); i < Min(x + w, width); i++) {
addr[j * width + i] = color;
}
}
}
int32_t CPUDraw::Min(const int32_t &a, const int32_t &b)
{
return a < b ? a : b;
}
int32_t CPUDraw::Max(const int32_t &a, const int32_t &b)
{
return a > b ? a : b;
}

View File

@ -38,6 +38,7 @@ public:
static void FuncLine(Gslogger &logger, enum LOG_PHASE phase); // 2
static void FileLine(Gslogger &logger, enum LOG_PHASE phase); // 3
static void FileFuncLine(Gslogger &logger, enum LOG_PHASE phase); // 4
static void PidTid(Gslogger &logger, enum LOG_PHASE phase); // +5
Gslogger(const std::string &file, const std::string &func, int line, enum LOG_LEVEL level, ...);
virtual ~Gslogger() override;
@ -78,33 +79,83 @@ private:
// hilog
#define DEFINE_HILOG_LABEL(str) \
namespace { constexpr const char *HILOG_LABEL = str; }
#define GSLOG0HI(level) Gslogger(LOGGER_ARG(level), Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG1HI(level) Gslogger(LOGGER_ARG(level), Gslogger::Func, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG2HI(level) Gslogger(LOGGER_ARG(level), Gslogger::FuncLine, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG3HI(level) Gslogger(LOGGER_ARG(level), Gslogger::FileLine, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG4HI(level) Gslogger(LOGGER_ARG(level), Gslogger::FileFuncLine, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG0HI(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG1HI(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Func, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG2HI(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FuncLine, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG3HI(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileLine, Gslogger::Hilog, HILOG_LABEL, NULL)
#define GSLOG4HI(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileFuncLine, Gslogger::Hilog, HILOG_LABEL, NULL)
// stdout
#define GSLOG0SO(level) Gslogger(LOGGER_ARG(level), Gslogger::Stdout, NULL)
#define GSLOG1SO(level) Gslogger(LOGGER_ARG(level), Gslogger::Func, Gslogger::Stdout, NULL)
#define GSLOG2SO(level) Gslogger(LOGGER_ARG(level), Gslogger::FuncLine, Gslogger::Stdout, NULL)
#define GSLOG3SO(level) Gslogger(LOGGER_ARG(level), Gslogger::FileLine, Gslogger::Stdout, NULL)
#define GSLOG4SO(level) Gslogger(LOGGER_ARG(level), Gslogger::FileFuncLine, Gslogger::Stdout, NULL)
#define GSLOG0SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Stdout, NULL)
#define GSLOG1SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Func, Gslogger::Stdout, NULL)
#define GSLOG2SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FuncLine, Gslogger::Stdout, NULL)
#define GSLOG3SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileLine, Gslogger::Stdout, NULL)
#define GSLOG4SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileFuncLine, Gslogger::Stdout, NULL)
#define GSLOG5SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::Stdout, NULL)
#define GSLOG6SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::Func, Gslogger::Stdout, NULL)
#define GSLOG7SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FuncLine, Gslogger::Stdout, NULL)
#define GSLOG8SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileLine, Gslogger::Stdout, NULL)
#define GSLOG9SO(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileFuncLine, Gslogger::Stdout, NULL)
// stderr
#define GSLOG0SE(level) Gslogger(LOGGER_ARG(level), Gslogger::Stderr, NULL)
#define GSLOG1SE(level) Gslogger(LOGGER_ARG(level), Gslogger::Func, Gslogger::Stderr, NULL)
#define GSLOG2SE(level) Gslogger(LOGGER_ARG(level), Gslogger::FuncLine, Gslogger::Stderr, NULL)
#define GSLOG3SE(level) Gslogger(LOGGER_ARG(level), Gslogger::FileLine, Gslogger::Stderr, NULL)
#define GSLOG4SE(level) Gslogger(LOGGER_ARG(level), Gslogger::FileFuncLine, Gslogger::Stderr, NULL)
#define GSLOG0SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Stderr, NULL)
#define GSLOG1SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Func, Gslogger::Stderr, NULL)
#define GSLOG2SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FuncLine, Gslogger::Stderr, NULL)
#define GSLOG3SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileLine, Gslogger::Stderr, NULL)
#define GSLOG4SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileFuncLine, Gslogger::Stderr, NULL)
#define GSLOG5SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::Stderr, NULL)
#define GSLOG6SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::Func, Gslogger::Stderr, NULL)
#define GSLOG7SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FuncLine, Gslogger::Stderr, NULL)
#define GSLOG8SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileLine, Gslogger::Stderr, NULL)
#define GSLOG9SE(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileFuncLine, Gslogger::Stderr, NULL)
// filelog
#define DEFINE_FILE_LABEL(str) \
namespace { constexpr const char *FILE_LABEL = str; }
#define GSLOG0F(level) Gslogger(LOGGER_ARG(level), Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG1F(level) Gslogger(LOGGER_ARG(level), Gslogger::Func, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG2F(level) Gslogger(LOGGER_ARG(level), Gslogger::FuncLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG3F(level) Gslogger(LOGGER_ARG(level), Gslogger::FileLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG4F(level) Gslogger(LOGGER_ARG(level), Gslogger::FileFuncLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG0F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG1F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::Func, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG2F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FuncLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG3F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG4F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::FileFuncLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG5F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG6F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::Func, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG7F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FuncLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG8F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileLine, Gslogger::FileLog, FILE_LABEL, NULL)
#define GSLOG9F(level) Gslogger(LOGGER_ARG(level), \
Gslogger::PidTid, Gslogger::FileFuncLine, Gslogger::FileLog, FILE_LABEL, NULL)
#endif // UTILS_INCLUDE_LOGGER_EXPORT_GSLOGGER_H

View File

@ -15,8 +15,10 @@
#include "gslogger.h"
#include <iostream>
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <hilog/log.h>
namespace {
@ -139,6 +141,13 @@ void Gslogger::FileFuncLine(Gslogger& logger, enum LOG_PHASE phase)
}
}
void Gslogger::PidTid(Gslogger &logger, enum LOG_PHASE phase)
{
if (phase == LOG_PHASE::BEGIN) {
logger << "[" << getpid() << "][" << gettid() << "]";
}
}
Gslogger::Gslogger(const std::string &file, const std::string &func, int line, enum LOG_LEVEL level, ...)
{
file_ = file;

View File

@ -39,6 +39,12 @@ public:
return AddOption(shortOpt, longOpt, &result, Option::ValueType::i32);
}
template<>
int32_t AddOption<uint32_t>(const std::string &shortOpt, const std::string &longOpt, uint32_t &result)
{
return AddOption(shortOpt, longOpt, &result, Option::ValueType::u32);
}
template<>
int32_t AddOption<int64_t>(const std::string &shortOpt, const std::string &longOpt, int64_t &result)
{
@ -76,6 +82,12 @@ public:
return AddArguments(&result, Argument::ValueType::i32);
}
template<>
int32_t AddArguments<uint32_t>(uint32_t &result)
{
return AddArguments(&result, Argument::ValueType::u32);
}
template<>
int32_t AddArguments<int64_t>(int64_t &result)
{
@ -110,6 +122,7 @@ private:
const std::string lo;
union Value {
int32_t i32;
uint32_t u32;
int64_t i64;
double f64;
std::string str;
@ -117,6 +130,7 @@ private:
} *result;
enum class ValueType {
i32,
u32,
i64,
f64,
str,
@ -130,12 +144,14 @@ private:
struct Argument {
union Value {
int32_t i32;
uint32_t u32;
int64_t i64;
double f64;
std::string str;
} *result;
enum class ValueType {
i32,
u32,
i64,
f64,
str,

View File

@ -15,6 +15,7 @@
#include <option_parser.h>
#include <iomanip>
#include <sstream>
enum {
@ -33,10 +34,13 @@ int32_t OptionParser::ParseArgument(const char *arg, const char *arg2)
std::stringstream ss(arg);
switch (arguments.front().type) {
case Argument::ValueType::i32:
ss >> arguments.front().result->i32;
ss >> std::setbase(0) >> arguments.front().result->i32;
break;
case Argument::ValueType::u32:
ss >> std::setbase(0) >> arguments.front().result->u32;
break;
case Argument::ValueType::i64:
ss >> arguments.front().result->i64;
ss >> std::setbase(0) >> arguments.front().result->i64;
break;
case Argument::ValueType::f64:
ss >> arguments.front().result->f64;
@ -93,10 +97,13 @@ int32_t OptionParser::ParseShortOption(const char *arg1, const char *arg2)
std::stringstream ss(arg2);
switch (option.type) {
case Option::ValueType::i32:
ss >> option.result->i32;
ss >> std::setbase(0) >> option.result->i32;
break;
case Option::ValueType::u32:
ss >> std::setbase(0) >> option.result->u32;
break;
case Option::ValueType::i64:
ss >> option.result->i64;
ss >> std::setbase(0) >> option.result->i64;
break;
case Option::ValueType::f64:
ss >> option.result->f64;
@ -168,10 +175,13 @@ int32_t OptionParser::ParseLongOption(const char *arg1, const char *arg2)
std::stringstream ss(arg2);
switch (option.type) {
case Option::ValueType::i32:
ss >> option.result->i32;
ss >> std::setbase(0) >> option.result->i32;
break;
case Option::ValueType::u32:
ss >> std::setbase(0) >> option.result->u32;
break;
case Option::ValueType::i64:
ss >> option.result->i64;
ss >> std::setbase(0) >> option.result->i64;
break;
case Option::ValueType::f64:
ss >> option.result->f64;