Use visible size when filling frame buffer

The buffer pixel area is based on nominal framebuffer size rather than
visible area.  On systems like Link, the internal panel size is greater
than the external display size, but the nominal framebuffer size is the
latter.  This means the amount of memory mapping covers a smaller area
than what is actually needed to fill the internal panel.

This patch updates the fill frame buffer code to use the visible area,
which correctly reflects the size of the internal panel.

BUG=chrome-os-partner:16363
TEST=Boot link and daisy with external monitor attached. make sure the
splash screen is fully white.

Change-Id: I6cacef64dfc4542fab7c87ae6613d78929f497a9
Signed-off-by: Simon Que <sque@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/38655
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/src/ply-frame-buffer.c b/src/ply-frame-buffer.c
index 0b2609c..5be9fff 100644
--- a/src/ply-frame-buffer.c
+++ b/src/ply-frame-buffer.c
@@ -44,6 +44,7 @@
 #include <linux/fb.h>
 
 #include "ply-list.h"
+#include "ply-monitor.h"
 #include "ply-utils.h"
 
 #ifndef PLY_FRAME_BUFFER_DEFAULT_FB_DEVICE_NAME
@@ -215,6 +216,7 @@
   buffer->area.height = variable_screen_info.yres;
   buffer->area.visible_width = variable_screen_info.xres;
   buffer->area.visible_height = variable_screen_info.yres;
+  ply_monitor_setup(buffer);
 
   buffer->red_bit_position = variable_screen_info.red.offset;
   buffer->bits_for_red = variable_screen_info.red.length;
@@ -230,7 +232,7 @@
 
   buffer->bytes_per_pixel = variable_screen_info.bits_per_pixel >> 3;
   buffer->row_stride = fixed_screen_info.line_length / buffer->bytes_per_pixel;
-  buffer->size = buffer->area.height * buffer->row_stride *
+  buffer->size = buffer->area.visible_height * buffer->row_stride *
       buffer->bytes_per_pixel;
   
   buffer->dither_red = 0;
@@ -581,8 +583,10 @@
 
 void ply_frame_buffer_clear(ply_frame_buffer_t *buffer,
                             uint32_t clear_color) {
-  int i;
-  int fb_size = buffer->row_stride * buffer->area.height;
+  int i, j;
+  int fb_width = buffer->area.visible_width;
+  int fb_height = buffer->area.visible_height;
+  int fb_stride = buffer->row_stride;
   uint32_t fb_clear_color;
   assert(buffer != NULL);
   assert(ply_frame_buffer_device_is_open(buffer));
@@ -594,14 +598,22 @@
   switch (buffer->bytes_per_pixel) {
     case 4: {
       uint32_t* ptr = (uint32_t*) buffer->map_address;
-      for (i = 0; i < fb_size; i++)
-        *ptr++ = fb_clear_color;
+      uint32_t* curr_ptr;
+      for (j = 0; j < fb_height; j++) {
+        curr_ptr = ptr + j * fb_stride;
+        for (i = 0; i < fb_width; i++)
+          *curr_ptr++ = fb_clear_color;
+      }
       break;
     }
     case 2: {
       uint16_t* ptr = (uint16_t*) buffer->map_address;
-      for (i = 0; i < fb_size; i++)
-        *ptr++ = fb_clear_color;
+      uint16_t* curr_ptr;
+      for (j = 0; j < fb_height; j++) {
+        curr_ptr = ptr + j * fb_stride;
+        for (i = 0; i < fb_width; i++)
+          *curr_ptr++ = fb_clear_color;
+      }
       break;
     }
     default:
diff --git a/src/ply-image.c b/src/ply-image.c
index e348d22..663fb7e 100644
--- a/src/ply-image.c
+++ b/src/ply-image.c
@@ -455,7 +455,6 @@
   bool location_assigned = false;
   bool offset_assigned = false;
   bool print_resolution = false;
-  bool set_monitors = true;
   ply_frame_buffer_t *buffer;
 
   /*
@@ -513,7 +512,7 @@
     }
 
     if (c == FLAG_NO_SET_MONITORS) {
-      set_monitors = false;
+      ply_monitor_set_monitors = false;
       continue;
     }
 
@@ -544,7 +543,6 @@
   }
 
   ply_frame_buffer_area_t fb_area;
-  ply_monitor_setup(buffer, set_monitors);
   ply_frame_buffer_get_size(buffer, &fb_area);
 
   if (print_resolution) {
diff --git a/src/ply-monitor.c b/src/ply-monitor.c
index 6e09e1f..badc39a 100644
--- a/src/ply-monitor.c
+++ b/src/ply-monitor.c
@@ -30,6 +30,8 @@
 #include "ply-kms.h"
 #include "ply-utils.h"
 
+bool ply_monitor_set_monitors = true;
+
 static drmModeCrtc *find_crtc_for_connector(int fd,
                                             drmModeRes *resources,
                                             drmModeConnector *connector) {
@@ -180,7 +182,7 @@
   }
 }
 
-bool ply_monitor_setup(ply_frame_buffer_t *buffer, bool do_setup) {
+bool ply_monitor_setup(ply_frame_buffer_t *buffer) {
   int fd = ply_kms_open();
   ply_frame_buffer_area_t *area = &buffer->area;
 
@@ -207,7 +209,7 @@
     return false;
   }
 
-  if (do_setup)
+  if (ply_monitor_set_monitors)
     disable_non_main_connectors(fd, resources, main_monitor_connector);
 
   drmModeCrtc *crtc = find_crtc_for_connector(fd, resources, main_monitor_connector);
diff --git a/src/ply-monitor.h b/src/ply-monitor.h
index 6cd066d..64e2762 100644
--- a/src/ply-monitor.h
+++ b/src/ply-monitor.h
@@ -24,12 +24,15 @@
 
 #include <stdbool.h>
 
+/* Set this flag if ply_monitor_setup should disable non-main outputs. */
+extern bool ply_monitor_set_monitors;
+
 /*
  * Configures the monitors using KMS. This function will find the main monitor
  * (by looking for a connected output, by order of priority: LVDS, eDP,
  * any other), and then will turn off all the other monitors.
  */
-bool ply_monitor_setup(ply_frame_buffer_t *area, bool do_setup);
+bool ply_monitor_setup(ply_frame_buffer_t *area);
 
 #endif /* PLY_MONITOR_H */