提交 796fe1c5 编写于 作者: N night_xiaoye

renderer: solve black border appearing one of four sides of the window.

fix problem, some apps's main window renderers will overflow window, this will cause black areas appearing four sides of the window, solve it.
tests: change two layer_composer test cases to make sucess, and add new two test cases.
上级 441931a8
......@@ -48,51 +48,60 @@ std::map<std::shared_ptr<wm::Window>, RenderableList> MultiWindowComposerStrateg
for (auto &w : win_layers) {
const auto &renderables = w.second;
RenderableList final_renderables;
int top = 1080;
int left = 1920;
for (auto &r : renderables) {
// We always prioritize layers which are lower in the list we got
// from SurfaceFlinger as they are already ordered.
int current_left = r.screen_position().left();
int current_top = r.screen_position().top();
int half_diff = 2;
if (r.screen_position().width() > w.first->frame().width()) {
auto diff = r.screen_position().width() - w.first->frame().width();
current_left += diff / half_diff;
}
if (r.screen_position().height() > w.first->frame().height()) {
auto diff = r.screen_position().height() - w.first->frame().height();
current_top += diff / half_diff;
}
if (current_left < left) {
left = current_left;
}
if (current_top < top) {
top = current_top;
}
}
auto window_frame = w.first->frame();
bool resizeable = w.first->checkResizeable();
auto old_frame = w.first->last_frame();
int max_area = 0;
Rect max_rect;
for (auto &r : renderables) {
// As we get absolute display coordinates from the Android hwcomposer we
// need to recalculate all layer coordinates into relatives ones to the
// window they are drawn into.
auto rect = Rect{
r.screen_position().left() - left + r.crop().left(),
r.screen_position().top() - top + r.crop().top(),
r.screen_position().right() - left + r.crop().left(),
r.screen_position().bottom() - top + r.crop().top()};
r.screen_position().left() - window_frame.left(),
r.screen_position().top() - window_frame.top(),
r.screen_position().right() - window_frame.left(),
r.screen_position().bottom() - window_frame.top()};
if (rect.width() * rect.height() > max_area) {
max_area = rect.width() * rect.height();
max_rect = Rect(r.screen_position().left() - old_frame.left(),
r.screen_position().top() - old_frame.top(),
r.screen_position().right() - old_frame.left(),
r.screen_position().bottom() - old_frame.top());
}
auto new_renderable = r;
new_renderable.set_screen_position(rect);
final_renderables.push_back(new_renderable);
}
w.second = final_renderables;
}
bool changed = false;
if (resizeable) {
int max_old_area = 0;
Rect max_old_rect;
auto it = last_renderables.find(w.first);
if (it != last_renderables.end()) {
for (auto &rt : it->second) {
if (max_old_area < rt.screen_position().width() * rt.screen_position().height()) {
max_old_area = rt.screen_position().width() * rt.screen_position().height();
max_old_rect = rt.screen_position();
}
}
}
if (max_old_rect == max_rect) {
w.second = it->second;
changed = true;
} else {
w.first->setResizing(false);
}
}
return win_layers;
if(!changed) {
w.second = final_renderables;
}
}
last_renderables.swap(win_layers);
return last_renderables;
}
} // namespace graphics
} // namespace anbox
......@@ -33,6 +33,7 @@ class MultiWindowComposerStrategy : public LayerComposer::Strategy {
private:
std::shared_ptr<wm::Manager> wm_;
WindowRenderableList last_renderables;
};
} // namespace graphics
} // namespace anbox
......
......@@ -279,11 +279,19 @@ void Window::process_event(const SDL_Event &event) {
// SDL_WINDOWEVENT_SIZE_CHANGED is always sent.
case SDL_WINDOWEVENT_SIZE_CHANGED:
if (observer_) {
struct timeval now = (struct timeval) { 0 };
gettimeofday(&now, NULL);
last_resize_time_ = USEC_PER_SEC * (now.tv_sec) + now.tv_usec;
resizing_ = true;
observer_->window_resized(id_, event.window.data1, event.window.data2);
}
break;
case SDL_WINDOWEVENT_MOVED:
if (observer_) {
struct timeval now = (struct timeval) { 0 };
gettimeofday(&now, NULL);
last_resize_time_ = USEC_PER_SEC * (now.tv_sec) + now.tv_usec;
resizing_ = true;
observer_->window_moved(id_, event.window.data1, event.window.data2);
}
break;
......@@ -305,6 +313,22 @@ Window::Id Window::id() const { return id_; }
std::uint32_t Window::window_id() const { return SDL_GetWindowID(window_); }
bool Window::checkResizeable() {
struct timeval now = (struct timeval) { 0 };
gettimeofday(&now, NULL);
long long time_now = USEC_PER_SEC * (now.tv_sec) + now.tv_usec;
if (resizing_ && time_now - last_resize_time_ > RESIZE_TIMESPAN) {
last_frame_ = frame();
resizing_ = false;
}
return resizing_;
}
void Window::setResizing(bool resizing) {
last_frame_ = frame();
resizing_ = resizing;
}
void Window::update_state(const wm::WindowState::List &states) {
if (!initialized.load() && !states.empty()) {
int w = 0;
......@@ -330,7 +354,6 @@ void Window::update_state(const wm::WindowState::List &states) {
y == rect.top()) {
return;
}
struct timeval now = (struct timeval) { 0 };
gettimeofday(&now, NULL);
long long current_time = USEC_PER_SEC * (now.tv_sec) + now.tv_usec;
......
......@@ -41,6 +41,7 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window {
static const long long USEC_PER_SEC = 1000000;
static const long long APP_START_MAX_TIME = 15 * USEC_PER_SEC;
static const long long timespan_db_click = 500000;
static const long long RESIZE_TIMESPAN = USEC_PER_SEC / 2;
struct mini_size {
int minimum_width;
......@@ -77,6 +78,8 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window {
void update_state(const wm::WindowState::List &states) override;
bool check_db_clicked(int x, int y);
bool checkResizeable() override;
void setResizing(bool resizing) override;
void restore_window();
Id id() const;
......@@ -93,6 +96,7 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window {
std::atomic<bool> initialized{false};
long long last_update_time{ 0 };
long long last_resize_time_{ 0 };
Id id_;
std::shared_ptr<Observer> observer_;
EGLNativeDisplayType native_display_;
......
......@@ -21,8 +21,9 @@
namespace anbox {
namespace wm {
Window::Window(const std::shared_ptr<Renderer> &renderer, const Task::Id &task, const graphics::Rect &frame, const std::string &title)
: renderer_(renderer), task_(task), frame_(frame), title_(title), native_window_(0) {}
Window::Window(const std::shared_ptr<Renderer> &renderer, const Task::Id &task,
const graphics::Rect &frame, const std::string &title)
: renderer_(renderer), task_(task), frame_(frame), title_(title), native_window_(0), last_frame_(frame) {}
Window::~Window() {
release();
......@@ -44,6 +45,8 @@ Task::Id Window::task() const { return task_; }
graphics::Rect Window::frame() const { return frame_; }
graphics::Rect Window::last_frame() const { return last_frame_; }
EGLNativeWindowType Window::native_handle() const { return native_window_; }
std::string Window::title() const { return title_; }
......
......@@ -53,15 +53,21 @@ class Window {
virtual void update_state(const WindowState::List &states);
void update_frame(const graphics::Rect &frame);
void update_last_frame(const graphics::Rect &frame);
virtual bool title_event_filter(int y);
void set_native_handle(const EGLNativeWindowType &handle);
EGLNativeWindowType native_handle() const;
graphics::Rect frame() const;
graphics::Rect last_frame() const;
Task::Id task() const;
std::string title() const;
virtual bool checkResizeable() { return resizing_; }
virtual void setResizing(bool resizing) { resizing_ = resizing; }
protected:
graphics::Rect last_frame_;
bool resizing_{false};
private:
EGLNativeWindowType native_window_;
std::shared_ptr<Renderer> renderer_;
......
......@@ -125,7 +125,7 @@ TEST(LayerComposer, MapsLayersToWindows) {
};
RenderableList second_window_renderables{
{"org.anbox.surface.2", 1, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
{"org.anbox.surface.2", 1, 1.0f, {-300, -400, 724, 368}, {0, 0, 1024, 768}},
};
EXPECT_CALL(*renderer, draw(_, Rect{0, 0, first_window.frame().width(),
......@@ -171,12 +171,12 @@ TEST(LayerComposer, WindowPartiallyOffscreen) {
// but the layer covering the whole window is placed with its top left
// origin outside of the visible display area.
RenderableList renderables = {
{"org.anbox.surface.1", 0, 1.0f, {-100, -100, 924, 668}, {0, 0, 1024, 768}},
{"org.anbox.surface.1", 0, 1.0f, {0, 0, 924, 668}, {100, 100, 1024, 768}},
{"org.anbox.surface.1", 1, 1.0f, {0, 0, 100, 200}, {0, 0, 100, 200}},
};
RenderableList expected_renderables{
{"org.anbox.surface.1", 0, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
{"org.anbox.surface.1", 0, 1.0f, {100, 100, 1024, 768}, {100, 100, 1024, 768}},
{"org.anbox.surface.1", 1, 1.0f, {100, 100, 200, 300}, {0, 0, 100, 200}},
};
......@@ -227,8 +227,8 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) {
};
RenderableList expected_renderables{
{"org.anbox.surface.3", 0, 1.0f, {0, 24, 1024, 792}, {0, 0, 1024, 768}},
{"org.anbox.surface.3", 1, 1.0f, {784, 0, 1044, 160}, {0, 0, 260, 160}},
{"org.anbox.surface.3", 0, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
{"org.anbox.surface.3", 1, 1.0f, {784, -24, 1044, 136}, {0, 0, 260, 160}},
};
EXPECT_CALL(*renderer, draw(_, Rect{0, 0,
......@@ -241,5 +241,103 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) {
composer.submit_layers(renderables);
}
TEST(LayerComposer, ResizingShouldUseOldRender) {
auto renderer = std::make_shared<MockRenderer>();
platform::Configuration config;
// The default policy will create a dumb window instance when requested
// from the manager.
auto platform = platform::create(std::string(), nullptr, config);
auto app_db = std::make_shared<application::Database>();
auto wm = std::make_shared<wm::MultiWindowManager>(platform, nullptr, app_db);
auto single_window = wm::WindowState{
wm::Display::Id{1},
true,
graphics::Rect{1120, 270, 2144, 1038},
"org.anbox.foo",
wm::Task::Id{3},
wm::Stack::Id::Freeform,
};
auto window = platform->create_window(single_window.task(), single_window.frame(), single_window.package_name());
window->attach();
wm->insert_task(single_window.task(), window);
LayerComposer composer(renderer, std::make_shared<MultiWindowComposerStrategy>(wm));
RenderableList renderables_first = {
{"org.anbox.surface.3", 0, 1.0f, {1120,270,2144,1038}, {0, 0, 1024, 768}},
};
composer.submit_layers(renderables_first);
window->update_frame(graphics::Rect{0, 0, 1024, 768});
window->setResizing(true);
composer.submit_layers(renderables_first);
RenderableList expected_renderables{
{"org.anbox.surface.3", 0, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
};
EXPECT_CALL(*renderer, draw(_, Rect{0, 0,
single_window.frame().width(),
single_window.frame().height()},
expected_renderables))
.Times(1)
.WillOnce(Return(true));
composer.submit_layers(renderables_first);
}
TEST(LayerComposer, ResizeOverShouldUseNewRender) {
auto renderer = std::make_shared<MockRenderer>();
platform::Configuration config;
// The default policy will create a dumb window instance when requested
// from the manager.
auto platform = platform::create(std::string(), nullptr, config);
auto app_db = std::make_shared<application::Database>();
auto wm = std::make_shared<wm::MultiWindowManager>(platform, nullptr, app_db);
auto single_window = wm::WindowState{
wm::Display::Id{1},
true,
graphics::Rect{1120, 270, 2144, 1038},
"org.anbox.foo",
wm::Task::Id{3},
wm::Stack::Id::Freeform,
};
auto window = platform->create_window(single_window.task(), single_window.frame(), single_window.package_name());
window->attach();
wm->insert_task(single_window.task(), window);
LayerComposer composer(renderer, std::make_shared<MultiWindowComposerStrategy>(wm));
RenderableList renderables_first = {
{"org.anbox.surface.3", 0, 1.0f, {1120,270,2144,1038}, {0, 0, 1024, 768}},
};
RenderableList renderables_second = {
{"org.anbox.surface.3", 0, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
};
composer.submit_layers(renderables_first);
window->update_frame(graphics::Rect{0, 0, 1024, 768});
window->setResizing(true);
composer.submit_layers(renderables_first);
RenderableList expected_renderables{
{"org.anbox.surface.3", 0, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
};
EXPECT_CALL(*renderer, draw(_, Rect{0, 0,
single_window.frame().width(),
single_window.frame().height()},
expected_renderables))
.Times(1)
.WillOnce(Return(true));
composer.submit_layers(renderables_second);
EXPECT_TRUE(window->checkResizeable() == false);
}
} // namespace graphics
} // namespace anbox
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册