Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • D drm-hwcomposer
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 13
    • Issues 13
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 4
    • Merge requests 4
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • drm-hwcomposer
  • drm-hwcomposer
  • Issues
  • #22
Closed
Open
Issue created Jun 04, 2019 by Neil Armstrong@narmstrong

DRM Interlaced and "similar" modes are merged into single modes, leading to selecting the wrong mode

In the process of bringing up the Amlogic Meson G12A for AOSP and drm-hwcomposer, I'm having a very suspicious behavior from the Android Graphics stack and the DRM modes handling.

The initial behavior was:

My 1080p Samsung TV reports the following modes: (using modetest)

  1920x1080 60 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: preferred, driver
  1920x1080 60 1920 2008 2052 2200 1080 1084 1089 1125 148352 flags: phsync, pvsync; type: driver
  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 74250 flags: phsync, pvsync, interlace; type: driver
  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 74176 flags: phsync, pvsync, interlace; type: driver
  1920x1080 50 1920 2448 2492 2640 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: driver
  1920x1080i 50 1920 2448 2492 2640 1080 1084 1094 1125 74250 flags: phsync, pvsync, interlace; type: driver
  1920x1080 30 1920 2008 2052 2200 1080 1084 1089 1125 74250 flags: phsync, pvsync; type: driver
  1920x1080 30 1920 2008 2052 2200 1080 1084 1089 1125 74176 flags: phsync, pvsync; type: driver
  1920x1080 25 1920 2448 2492 2640 1080 1084 1089 1125 74250 flags: phsync, pvsync; type: driver
  1920x1080 24 1920 2558 2602 2750 1080 1084 1089 1125 74250 flags: phsync, pvsync; type: driver
  1920x1080 24 1920 2558 2602 2750 1080 1084 1089 1125 74176 flags: phsync, pvsync; type: driver
  1600x900 60 1600 1624 1704 1800 900 901 904 1000 108000 flags: phsync, pvsync; type: driver
  1280x1024 75 1280 1296 1440 1688 1024 1025 1028 1066 135000 flags: phsync, pvsync; type: driver
  1280x1024 60 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: phsync, pvsync; type: driver
  1366x768 60 1366 1436 1579 1792 768 771 774 798 85500 flags: phsync, pvsync; type: driver
  1152x864 75 1152 1216 1344 1600 864 865 868 900 108000 flags: phsync, pvsync; type: driver
  1280x720 60 1280 1390 1430 1650 720 725 730 750 74250 flags: phsync, pvsync; type: driver
  1280x720 60 1280 1390 1430 1650 720 725 730 750 74176 flags: phsync, pvsync; type: driver
  1280x720 50 1280 1720 1760 1980 720 725 730 750 74250 flags: phsync, pvsync; type: driver
  1024x768 70 1024 1048 1184 1328 768 771 777 806 75000 flags: nhsync, nvsync; type: driver
  800x600 75 800 816 896 1056 600 601 604 625 49500 flags: phsync, pvsync; type: driver
  720x576 50 720 732 796 864 576 581 586 625 27000 flags: nhsync, nvsync; type: driver
  720x480 60 720 736 798 858 480 489 495 525 27000 flags: nhsync, nvsync; type: driver
  640x480 75 640 656 720 840 480 481 484 500 31500 flags: nhsync, nvsync; type: driver
  640x480 73 640 664 704 832 480 489 492 520 31500 flags: nhsync, nvsync; type: driver

Using AOSP master, drm-hwc-two initializes and reports the following modes:

01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 0 mode.id=1 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 1 mode.id=2 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 2 mode.id=3 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 3 mode.id=7 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 4 mode.id=10 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 5 mode.id=11 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 6 mode.id=12 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 7 mode.id=13 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 8 mode.id=14 => 1920x1080
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 9 mode.id=15 => 1600x900
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 10 mode.id=16 => 1280x1024
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 11 mode.id=17 => 1280x1024
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 12 mode.id=18 => 1366x768
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 13 mode.id=19 => 1152x864
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 14 mode.id=20 => 1280x720
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 15 mode.id=21 => 1280x720
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 16 mode.id=22 => 1280x720
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 17 mode.id=23 => 1280x720
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 18 mode.id=24 => 1280x720
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 19 mode.id=25 => 1024x768
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 20 mode.id=26 => 800x600
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 21 mode.id=27 => 720x576
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 22 mode.id=28 => 720x480
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 23 mode.id=29 => 640x480
01-01 00:00:10.469  2364  2364 E hwc-drm-two: GetDisplayConfigs() 24 mode.id=30 => 640x480

The reported configs are:

DisplayManagerService: Display device added: DisplayDeviceInfo{"Built-in Screen": uniqueId="local:0", 1920 x 1080, modeId 18, defaultModeId 18, supportedModes [{id=1, width=640, height=480, fps=73.0}, {id=2, width=640, height=480, fps=75.0}, {id=3, width=720, height=480, fps=60.0}, {id=4, width=720, height=576, fps=50.0}, {id=5, width=800, height=600, fps=75.0}, {id=6, width=1024, height=768, fps=70.0}, {id=7, width=1280, height=720, fps=50.0}, {id=8, width=1280, height=720, fps=60.0}, {id=9, width=1152, height=864, fps=75.0}, {id=10, width=1366, height=768, fps=60.0}, {id=11, width=1280, height=1024, fps=60.0}, {id=12, width=1280, height=1024, fps=75.0}, {id=13, width=1600, height=900, fps=60.0}, {id=14, width=1920, height=1080, fps=24.0}, {id=15, width=1920, height=1080, fps=25.0}, {id=16, width=1920, height=1080, fps=30.0}, {id=17, width=1920, height=1080, fps=50.0}, {id=18, width=1920, height=1080, fps=60.0}], colorMode 0, supportedColorModes [0], HdrCapabilities android.view.Display$HdrCapabilities@40f16308, density 102, 101.6 x 101.6 dpi, appVsyncOff 1000000, presDeadline 16666667, touch INTERNAL, rotation 0, type BUILT_IN, state UNKNOWN, FLAG_DEFAULT_DISPLAY, FLAG_ROTATES_WITH_CONTENT, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}

We can see most of the mode have been "merged", and looking at the following behavior, only the "higher" drm-hwc-two internal ID has been kept.

Then bootanim starts and drm-hwcomposer selects the correct EDID preferred mode (1):

01-01 00:00:11.787  2378  2378 I SurfaceFlinger: Enter boot animation
01-01 00:00:12.037  2365  2365 E hwc-drm-two: GetActiveConfig() mode.id=1

Then bootanim stops, and the UI takes over, but strangely, the mode 6 (1920x1080i) is selected:

06-04 12:16:02.568  2364  2364 E hwc-drm-two: SetActiveConfig(6)
06-04 12:36:32.450  2377  2377 D SurfaceFlinger: Set active config mode=24, type=0 flinger=0xfc1d07049000
06-04 12:16:02.568  2364  2364 E hwc-drm-display-compositor: Create blob_id 45
06-04 12:16:02.782  2364  2364 E hwc-drm-two: GetActiveConfig() mode.id=6

Here 6 is mode.id=12 => 1920x1080, it can be explained because the 6 first modes were "merged" in a single 1920x1080 mode, keeping only the last mode id (6).

My findings are:

  • Interlaced modes are not handled at all, so dropping them should be the ultimate solution until handled in the uppper layers
  • vrefresh is used from the integer format reported by the kernel, but in our case, the TV reports some 1000/1001 US modes, and HWC2 and upper does some mode merging and these modes are mixed with the standard modes, but keeping the worst/wrong DRM-HWC mode id

With the following changes, things are better:

--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -399,17 +399,18 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
     }
   }
 
-  auto num_modes = static_cast<uint32_t>(connector_->modes().size());
-  if (!configs) {
-    *num_configs = num_modes;
-    return HWC2::Error::None;
-  }
-
   uint32_t idx = 0;
   for (const DrmMode &mode : connector_->modes()) {
-    if (idx >= *num_configs)
+    if (configs && idx >= *num_configs)
       break;
-    configs[idx++] = mode.id();
+    /* Drop interlaced modes */
+    if (mode.flags() & DRM_MODE_FLAG_INTERLACE)
+      continue;
+    if (configs) {
+      configs[idx++] = mode.id();
+    } else {
+      idx++;
+    }
   }
   *num_configs = idx;
   return HWC2::Error::None;

and

--- a/drmmode.cpp
+++ b/drmmode.cpp
@@ -122,8 +122,8 @@ uint32_t DrmMode::v_scan() const {
 }
 
 float DrmMode::v_refresh() const {
-  return v_refresh_ ? v_refresh_ * 1.0f
-                    : clock_ / (float)(v_total_ * h_total_) * 1000.0f;
+  // Always recalculate refresh to report correct float rate
+  return clock_ / (float)(v_total_ * h_total_) * 1000.0f;
 }
 
 uint32_t DrmMode::flags() const {

Then we get:

DisplayManagerService: Display device added: DisplayDeviceInfo{"Built-in Screen": uniqueId="local:0", 1920 x 1080, modeId 21, defaultModeId 21, supportedModes [{id=1, width=640, height=480, fps=72.8088}, {id=2, width=640, height=480, fps=75.0}, {id=3, width=720, height=480, fps=59.94006}, {id=4, width=720, height=576, fps=50.0}, {id=5, width=1280, height=720, fps=50.0}, {id=6, width=1280, height=720, fps=59.9402}, {id=7, width=1280, height=720, fps=60.0}, {id=8, width=1152, height=864, fps=75.0}, {id=9, width=1366, height=768, fps=59.789543}, {id=10, width=1280, height=1024, fps=60.019737}, {id=11, width=1280, height=1024, fps=75.02467}, {id=12, width=1600, height=900, fps=60.0}, {id=13, width=1920, height=1080, fps=29.9701}, {id=14, width=1920, height=1080, fps=30.0}, {id=15, width=1920, height=1080, fps=23.97608}, {id=16, width=800, height=600, fps=75.0}, {id=17, width=1920, height=1080, fps=59.9402}, {id=18, width=1920, height=1080, fps=50.0}, {id=19, width=1920, height=1080, fps=24.0}, {id=20, width=1024, height=768, fps=70.06936}, {id=21, width=1920, height=1080, fps=60.0}, {id=22, width=1920, height=1080, fps=25.0}], colorMode 0, supportedColorModes [0], HdrCapabilities android.view.Display$HdrCapabilities@40f16308, density 102, 101.6 x 101.6 dpi, appVsyncOff 1000000, presDeadline 16666667, touch INTERNAL, rotation 0, type BUILT_IN, state UNKNOWN, FLAG_DEFAULT_DISPLAY, FLAG_ROTATES_WITH_CONTENT, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}

Now refresh rates are correctly reported, and modes are less "merged", interlaced modes are no more present.

But still, the preferred mode is still not selected:

06-04 12:50:51.551  2373  2373 D SurfaceFlinger: Set active config mode=23, type=0 flinger=0xfb5400e49000
06-04 12:50:51.551  2364  2395 E hwc-drm-two: SetActiveConfig(2)
06-04 12:50:51.551  2364  2395 E hwc-drm-display-compositor: Create blob_id 45

since the mode "1" is the HDMI preferred mode, and the mode "2" is the legacy EDID timings, but "1" should be selected.

Using a 4k UHD TV with 4:4:4 modes, these modes are merged with the 4:2:0 modes and the 4:4:4 preferred mode is never used after the bootanim.

Maybe at some point, the uppers layers should keep all the different modes ?

Assignee
Assign to
Time tracking