Enable scaling to fit various screen resolutions 25/14025/1 eel 5.0.3 5.1.0 eel/5.0.3 eel/5.1.0 eel_5.0.3 eel_5.1.0
authorTadao Tanikawa <tanikawa.tadao@jp.panasonic.com>
Wed, 16 May 2018 09:48:31 +0000 (09:48 +0000)
committerTadao Tanikawa <tanikawa.tadao@jp.panasonic.com>
Fri, 18 May 2018 06:57:15 +0000 (15:57 +0900)
Since the AGL HomeScreen of CES2018 assumes that the screen
resolution is 1080x1920px, the graphics of it partially
corrupted with others.

To fix this issue, now the AGL window manager automatically
scales size of HomeScreen to fit the resolution of the display.

By default, this scaling keeps HomeScreen's original aspect
rate (9:16). To ignore it, set the environment variable,
'HMI_SCALING_IGNORE_ASPECT'.
(E.g. set it in any file under /etc/afm/unit.env.d/)

Bug-AGL: SPEC-1138

Change-Id: Id11a07560fe254712aaab42018bfb4d1d87ad1df
Signed-off-by: Tadao Tanikawa <tanikawa.tadao@jp.panasonic.com>
layers.json
src/app.cpp
src/config.cpp
src/layers.cpp
src/layers.hpp
src/util.cpp
src/util.hpp

index cf7ed34..230da55 100644 (file)
@@ -3,6 +3,8 @@
 
    "main_surface": {
       "surface_role": "HomeScreen",
+      "width": 1080,
+      "height": 1920,
       "comment": "This surface should never be made invisible (The HomeScreen)"
    },
 
index e9d79f5..575ab85 100644 (file)
@@ -58,7 +58,6 @@ const char kKeyHeightPixel[] = "height_pixel";
 const char kKeyWidthMm[]     = "width_mm";
 const char kKeyHeightMm[]    = "height_mm";
 
-
 namespace {
 
 using nlohmann::json;
@@ -114,6 +113,10 @@ App::App(wl::display *d)
          } else {
             HMI_ERROR("wm", "%s", l.err().value());
          }
+
+         if (this->config.get_string("scaling_ignore_aspect")) {
+             this->layers.scaling_keep_aspect =false;
+         }
       }
    } catch (std::exception &e) {
       HMI_ERROR("wm", "Loading of configuration failed: %s", e.what());
@@ -237,11 +240,22 @@ int App::init_layers() {
    // Clear screen
    s->clear();
 
+   int width = this->layers.main_surface_width;
+   int height = this->layers.main_surface_height;
+
+   rectangle rect(width, height); // 1080x1920 by default
+   rect.scale(o->width, o->height, this->layers.scaling_keep_aspect);
+   rect.center(o->width, o->height);
+
+   HMI_DEBUG("wm", "Main surface (0,0),%dx%d to (%d,%d),%dx%d",
+             width, height, rect.left(), rect.top(), rect.width(), rect.height());
+
    // Quick and dirty setup of layers
    for (auto const &i : this->layers.mapping) {
-      c->layer_create(i.second.layer_id, o->width, o->height);
+      c->layer_create(i.second.layer_id, rect.width(), rect.height());
       auto &l = layers[i.second.layer_id];
-      l->set_destination_rectangle(0, 0, o->width, o->height);
+      l->set_source_rectangle(0, 0, width, height);
+      l->set_destination_rectangle(rect.left(), rect.top(), rect.width(), rect.height());
       l->set_visibility(1);
       HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"",
                i.second.name.c_str(), i.second.layer_id, i.second.role.c_str());
@@ -282,10 +296,10 @@ void App::surface_set_layout(int surface_id, optional<int> sub_surface_id) {
    // less-than-0 values refer to MAX + 1 - $VALUE
    // e.g. MAX is either screen width or height
    if (w < 0) {
-      w = this->controller->output_size.w + 1 + w;
+      w = this->layers.main_surface_width + 1 + w;
    }
    if (h < 0) {
-      h = this->controller->output_size.h + 1 + h;
+      h = this->layers.main_surface_height + 1 + h;
    }
 
    if (sub_surface_id) {
index c7e4ddb..cee9e91 100644 (file)
@@ -29,6 +29,11 @@ config::config() : cfg() {
    else {
       this->cfg["layers.json"] = std::string(path_layers_json) + std::string("/etc/layers.json");
    }
+
+   const char *ignore_aspect = getenv("HMI_SCALING_IGNORE_ASPECT");
+   if (ignore_aspect) {
+       this->cfg["scaling_ignore_aspect"] = std::string(ignore_aspect);
+   }
 }
 
 }  // namespace wm
index 04f944d..8698e83 100644 (file)
@@ -24,6 +24,9 @@
 
 namespace wm {
 
+const int default_main_width = 1080;
+const int default_main_height = 1920;
+
 using json = nlohmann::json;
 
 layer::layer(nlohmann::json const &j) {
@@ -104,6 +107,8 @@ struct result<struct layer_map> to_layer_map(nlohmann::json const &j) {
       auto msi = j.find("main_surface");
       if (msi != j.end()) {
          stl.main_surface_name = msi->value("surface_role", "");
+         stl.main_surface_width = msi->value("width", default_main_width);
+         stl.main_surface_height = msi->value("height", default_main_height);
          stl.main_surface = -1;
       }
 
index 1942229..fd0072b 100644 (file)
@@ -77,6 +77,9 @@ struct layer_map {
    layers_type layers;    // the actual layer IDs we have
    int main_surface;
    std::string main_surface_name;
+   int main_surface_width;
+   int main_surface_height;
+   bool scaling_keep_aspect = true;
    role_to_layer_map roles;
    addsurf_layer_map surfaces;  // additional surfaces on layers
 
index 2ae856f..1fb6ac8 100644 (file)
@@ -37,3 +37,30 @@ unique_fd::~unique_fd() {
       close(this->fd);
    }
 }
+
+void rectangle::scale(int to_w, int to_h, bool keep_aspect)
+{
+  if (!keep_aspect) {
+    w = to_w;
+    h = to_h;
+    return;
+  }
+
+  int64_t resized_w = int64_t(to_h) * int64_t(w) / int64_t(h);
+
+  if (resized_w <= to_w) {
+    /* use aspect by height */
+    w = resized_w;
+    h = to_h;
+  } else {
+    /* use aspect by width */
+    w = to_h;
+    h = int64_t(to_w) * int64_t(h) / int64_t(w);
+  }
+}
+
+void rectangle::center(int outer_w, int outer_h)
+{
+  x = (outer_w - w) / 2;
+  y = (outer_h - h) / 2;
+}
index f4e6e5f..6c6d0b9 100644 (file)
@@ -103,4 +103,22 @@ struct unique_fd {
    }
 };
 
+class rectangle
+{
+public:
+  explicit rectangle(int wd, int ht) : w(wd), h(ht) {};
+  void scale(int to_w, int to_h, bool keep_aspect);
+  void center(int outer_w, int outer_h);
+  int left() { return x; };
+  int top() { return y; };
+  int width() { return w; };
+  int height() { return h; };
+
+private:
+  int x = 0;
+  int y = 0;
+  int w;
+  int h;
+};
+
 #endif  // !WM_UTIL_HPP