提交 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 ...@@ -48,51 +48,60 @@ std::map<std::shared_ptr<wm::Window>, RenderableList> MultiWindowComposerStrateg
for (auto &w : win_layers) { for (auto &w : win_layers) {
const auto &renderables = w.second; const auto &renderables = w.second;
RenderableList final_renderables; RenderableList final_renderables;
int top = 1080; auto window_frame = w.first->frame();
int left = 1920; bool resizeable = w.first->checkResizeable();
auto old_frame = w.first->last_frame();
for (auto &r : renderables) { int max_area = 0;
// We always prioritize layers which are lower in the list we got Rect max_rect;
// 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;
}
}
for (auto &r : renderables) { for (auto &r : renderables) {
// As we get absolute display coordinates from the Android hwcomposer we // As we get absolute display coordinates from the Android hwcomposer we
// need to recalculate all layer coordinates into relatives ones to the // need to recalculate all layer coordinates into relatives ones to the
// window they are drawn into. // window they are drawn into.
auto rect = Rect{ auto rect = Rect{
r.screen_position().left() - left + r.crop().left(), r.screen_position().left() - window_frame.left(),
r.screen_position().top() - top + r.crop().top(), r.screen_position().top() - window_frame.top(),
r.screen_position().right() - left + r.crop().left(), r.screen_position().right() - window_frame.left(),
r.screen_position().bottom() - top + r.crop().top()}; 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; auto new_renderable = r;
new_renderable.set_screen_position(rect); new_renderable.set_screen_position(rect);
final_renderables.push_back(new_renderable); 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 graphics
} // namespace anbox } // namespace anbox
...@@ -33,6 +33,7 @@ class MultiWindowComposerStrategy : public LayerComposer::Strategy { ...@@ -33,6 +33,7 @@ class MultiWindowComposerStrategy : public LayerComposer::Strategy {
private: private:
std::shared_ptr<wm::Manager> wm_; std::shared_ptr<wm::Manager> wm_;
WindowRenderableList last_renderables;
}; };
} // namespace graphics } // namespace graphics
} // namespace anbox } // namespace anbox
......
...@@ -279,11 +279,19 @@ void Window::process_event(const SDL_Event &event) { ...@@ -279,11 +279,19 @@ void Window::process_event(const SDL_Event &event) {
// SDL_WINDOWEVENT_SIZE_CHANGED is always sent. // SDL_WINDOWEVENT_SIZE_CHANGED is always sent.
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
if (observer_) { 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); observer_->window_resized(id_, event.window.data1, event.window.data2);
} }
break; break;
case SDL_WINDOWEVENT_MOVED: case SDL_WINDOWEVENT_MOVED:
if (observer_) { 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); observer_->window_moved(id_, event.window.data1, event.window.data2);
} }
break; break;
...@@ -305,6 +313,22 @@ Window::Id Window::id() const { return id_; } ...@@ -305,6 +313,22 @@ Window::Id Window::id() const { return id_; }
std::uint32_t Window::window_id() const { return SDL_GetWindowID(window_); } 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) { void Window::update_state(const wm::WindowState::List &states) {
if (!initialized.load() && !states.empty()) { if (!initialized.load() && !states.empty()) {
int w = 0; int w = 0;
...@@ -330,7 +354,6 @@ void Window::update_state(const wm::WindowState::List &states) { ...@@ -330,7 +354,6 @@ void Window::update_state(const wm::WindowState::List &states) {
y == rect.top()) { y == rect.top()) {
return; return;
} }
struct timeval now = (struct timeval) { 0 }; struct timeval now = (struct timeval) { 0 };
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
long long current_time = USEC_PER_SEC * (now.tv_sec) + now.tv_usec; 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 { ...@@ -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 USEC_PER_SEC = 1000000;
static const long long APP_START_MAX_TIME = 15 * USEC_PER_SEC; static const long long APP_START_MAX_TIME = 15 * USEC_PER_SEC;
static const long long timespan_db_click = 500000; static const long long timespan_db_click = 500000;
static const long long RESIZE_TIMESPAN = USEC_PER_SEC / 2;
struct mini_size { struct mini_size {
int minimum_width; int minimum_width;
...@@ -77,6 +78,8 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window { ...@@ -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; void update_state(const wm::WindowState::List &states) override;
bool check_db_clicked(int x, int y); bool check_db_clicked(int x, int y);
bool checkResizeable() override;
void setResizing(bool resizing) override;
void restore_window(); void restore_window();
Id id() const; Id id() const;
...@@ -93,6 +96,7 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window { ...@@ -93,6 +96,7 @@ class Window : public std::enable_shared_from_this<Window>, public wm::Window {
std::atomic<bool> initialized{false}; std::atomic<bool> initialized{false};
long long last_update_time{ 0 }; long long last_update_time{ 0 };
long long last_resize_time_{ 0 };
Id id_; Id id_;
std::shared_ptr<Observer> observer_; std::shared_ptr<Observer> observer_;
EGLNativeDisplayType native_display_; EGLNativeDisplayType native_display_;
......
...@@ -21,8 +21,9 @@ ...@@ -21,8 +21,9 @@
namespace anbox { namespace anbox {
namespace wm { namespace wm {
Window::Window(const std::shared_ptr<Renderer> &renderer, const Task::Id &task, const graphics::Rect &frame, const std::string &title) Window::Window(const std::shared_ptr<Renderer> &renderer, const Task::Id &task,
: renderer_(renderer), task_(task), frame_(frame), title_(title), native_window_(0) {} const graphics::Rect &frame, const std::string &title)
: renderer_(renderer), task_(task), frame_(frame), title_(title), native_window_(0), last_frame_(frame) {}
Window::~Window() { Window::~Window() {
release(); release();
...@@ -44,6 +45,8 @@ Task::Id Window::task() const { return task_; } ...@@ -44,6 +45,8 @@ Task::Id Window::task() const { return task_; }
graphics::Rect Window::frame() const { return frame_; } graphics::Rect Window::frame() const { return frame_; }
graphics::Rect Window::last_frame() const { return last_frame_; }
EGLNativeWindowType Window::native_handle() const { return native_window_; } EGLNativeWindowType Window::native_handle() const { return native_window_; }
std::string Window::title() const { return title_; } std::string Window::title() const { return title_; }
......
...@@ -53,15 +53,21 @@ class Window { ...@@ -53,15 +53,21 @@ class Window {
virtual void update_state(const WindowState::List &states); virtual void update_state(const WindowState::List &states);
void update_frame(const graphics::Rect &frame); void update_frame(const graphics::Rect &frame);
void update_last_frame(const graphics::Rect &frame);
virtual bool title_event_filter(int y); virtual bool title_event_filter(int y);
void set_native_handle(const EGLNativeWindowType &handle); void set_native_handle(const EGLNativeWindowType &handle);
EGLNativeWindowType native_handle() const; EGLNativeWindowType native_handle() const;
graphics::Rect frame() const; graphics::Rect frame() const;
graphics::Rect last_frame() const;
Task::Id task() const; Task::Id task() const;
std::string title() 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: private:
EGLNativeWindowType native_window_; EGLNativeWindowType native_window_;
std::shared_ptr<Renderer> renderer_; std::shared_ptr<Renderer> renderer_;
......
...@@ -125,7 +125,7 @@ TEST(LayerComposer, MapsLayersToWindows) { ...@@ -125,7 +125,7 @@ TEST(LayerComposer, MapsLayersToWindows) {
}; };
RenderableList second_window_renderables{ 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(), EXPECT_CALL(*renderer, draw(_, Rect{0, 0, first_window.frame().width(),
...@@ -171,12 +171,12 @@ TEST(LayerComposer, WindowPartiallyOffscreen) { ...@@ -171,12 +171,12 @@ TEST(LayerComposer, WindowPartiallyOffscreen) {
// but the layer covering the whole window is placed with its top left // but the layer covering the whole window is placed with its top left
// origin outside of the visible display area. // origin outside of the visible display area.
RenderableList renderables = { 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}}, {"org.anbox.surface.1", 1, 1.0f, {0, 0, 100, 200}, {0, 0, 100, 200}},
}; };
RenderableList expected_renderables{ 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}}, {"org.anbox.surface.1", 1, 1.0f, {100, 100, 200, 300}, {0, 0, 100, 200}},
}; };
...@@ -227,8 +227,8 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) { ...@@ -227,8 +227,8 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) {
}; };
RenderableList expected_renderables{ RenderableList expected_renderables{
{"org.anbox.surface.3", 0, 1.0f, {0, 24, 1024, 792}, {0, 0, 1024, 768}}, {"org.anbox.surface.3", 0, 1.0f, {0, 0, 1024, 768}, {0, 0, 1024, 768}},
{"org.anbox.surface.3", 1, 1.0f, {784, 0, 1044, 160}, {0, 0, 260, 160}}, {"org.anbox.surface.3", 1, 1.0f, {784, -24, 1044, 136}, {0, 0, 260, 160}},
}; };
EXPECT_CALL(*renderer, draw(_, Rect{0, 0, EXPECT_CALL(*renderer, draw(_, Rect{0, 0,
...@@ -241,5 +241,103 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) { ...@@ -241,5 +241,103 @@ TEST(LayerComposer, PopupShouldNotCauseWindowLayerOffset) {
composer.submit_layers(renderables); 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 graphics
} // namespace anbox } // namespace anbox
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册