drm_hwcomposer: Add blocking SetConfig

Config changes within the same config group are intended to change
the refresh rate and are expected to be seamless, and as such are queued
up to be applied along with other frame updates such as pageflips. These
commits ought not to result in a full modeset.

For config changes that go between config groups, there might be visible
artifacts (modesets).

Introduce HwcDisplay::SetConfig to implement support for changing
between config groups. Config changes that are expected to be seamless
and not introduce jank or other visual artifacts should continue to go
through HwcDisplay::QueueConfig.

Since there may not be an appropriate client buffer available for the
initial SetConfig, allocate a CPU-writable buffer for scanout that can
be used for the first commit. The buffer can be destroyed after the
next frame is presented.

Change-Id: I48a87a070130dd2328f415719032486d9659c5b6
Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index 7cc1bee..ecca514 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -74,6 +74,11 @@
   // is queued up to take effect in the future.
   auto GetLastRequestedConfig() const -> const HwcDisplayConfig *;
 
+  // Set a config synchronously. If the requested config fails to be committed,
+  // this will return with an error. Otherwise, the config will have been
+  // committed to the kernel on successful return.
+  ConfigError SetConfig(hwc2_config_t config);
+
   // Queue a configuration change to take effect in the future.
   auto QueueConfig(hwc2_config_t config, int64_t desired_time, bool seamless,
                    QueuedConfigTiming *out_timing) -> ConfigError;
@@ -223,6 +228,10 @@
   auto getDisplayPhysicalOrientation() -> std::optional<PanelOrientation>;
 
  private:
+  AtomicCommitArgs CreateModesetCommit(
+      const HwcDisplayConfig *config,
+      const std::optional<LayerData> &modeset_layer);
+
   HwcDisplayConfigs configs_;
 
   DrmHwc *const hwc_;