TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / graphics / multi_window_composer_strategy.cpp
1 /*
2  * Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #include "anbox/graphics/multi_window_composer_strategy.h"
19 #include "anbox/wm/manager.h"
20 #include "anbox/utils.h"
21
22 namespace anbox {
23 namespace graphics {
24 MultiWindowComposerStrategy::MultiWindowComposerStrategy(const std::shared_ptr<wm::Manager> &wm) : wm_(wm) {}
25
26 std::map<std::shared_ptr<wm::Window>, RenderableList> MultiWindowComposerStrategy::process_layers(const RenderableList &renderables) {
27   WindowRenderableList win_layers;
28   for (const auto &renderable : renderables) {
29     // Ignore all surfaces which are not meant for a task
30     if (!utils::string_starts_with(renderable.name(), "org.anbox.surface."))
31       continue;
32
33     wm::Task::Id task_id = 0;
34     if (sscanf(renderable.name().c_str(), "org.anbox.surface.%d", &task_id) != 1 || !task_id)
35       continue;
36
37     auto w = wm_->find_window_for_task(task_id);
38     if (!w) continue;
39
40     if (win_layers.find(w) == win_layers.end()) {
41       win_layers.insert({w, {renderable}});
42       continue;
43     }
44
45     win_layers[w].push_back(renderable);
46   }
47
48   for (auto &w : win_layers) {
49     const auto &renderables = w.second;
50     RenderableList final_renderables;
51     auto new_window_frame = Rect::Invalid;
52     auto max_layer_area = -1;
53
54     for (auto &r : renderables) {
55       const auto layer_area = r.screen_position().width() * r.screen_position().height();
56       // We always prioritize layers which are lower in the list we got
57       // from SurfaceFlinger as they are already ordered.
58       if (layer_area < max_layer_area)
59         continue;
60
61       max_layer_area = layer_area;
62       new_window_frame = r.screen_position();
63     }
64
65     for (auto &r : renderables) {
66       // As we get absolute display coordinates from the Android hwcomposer we
67       // need to recalculate all layer coordinates into relatives ones to the
68       // window they are drawn into.
69       auto rect = Rect{
70           r.screen_position().left() - new_window_frame.left() + r.crop().left(),
71           r.screen_position().top() - new_window_frame.top() + r.crop().top(),
72           r.screen_position().right() - new_window_frame.left() + r.crop().left(),
73           r.screen_position().bottom() - new_window_frame.top() + r.crop().top()};
74
75       auto new_renderable = r;
76       new_renderable.set_screen_position(rect);
77       final_renderables.push_back(new_renderable);
78     }
79
80     w.second = final_renderables;
81   }
82
83   return win_layers;
84 }
85 }  // namespace graphics
86 }  // namespace anbox