Merge remote-tracking branch 'aosp/upstream-main' into uprev am: 39c1270fad am: 233765d00b

Original change: undetermined

Change-Id: I8729463cc790f34001c0ea4a8bac110e1c26539c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.ci/.gitlab-ci-checkcommit.sh b/.ci/.gitlab-ci-checkcommit.sh
index f821595..3f597c3 100755
--- a/.ci/.gitlab-ci-checkcommit.sh
+++ b/.ci/.gitlab-ci-checkcommit.sh
@@ -42,7 +42,7 @@
 
 git log --pretty='%h' FETCH_HEAD..HEAD | while read h; do
 	subject=$(git show -s --pretty='%s' "$h")
-	if [[ $subject != drm_hwcomposer:* ]]; then
+	if [[ $subject != drm_hwcomposer:* ]] && [[ $subject != Revert* ]]; then
 		echoerr "Invalid subject prefix: $subject"
 		exit 1
 	fi
diff --git a/Android.bp b/Android.bp
index 6be50d6..7ff063d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -72,6 +72,8 @@
         "-DHWC2_USE_CPP11",
     ],
 
+    cpp_std: "gnu++17",
+
     relative_install_path: "hw",
     vendor: true,
 }
diff --git a/compositor/ColorInfo.h b/compositor/DisplayInfo.h
similarity index 81%
rename from compositor/ColorInfo.h
rename to compositor/DisplayInfo.h
index 1afda07..bbcbff8 100644
--- a/compositor/ColorInfo.h
+++ b/compositor/DisplayInfo.h
@@ -36,3 +36,13 @@
   kRgbWideFloat,
   kBt601Ycc,
 };
+
+/**
+ * Display panel orientation property values.
+ */
+enum PanelOrientation {
+  kModePanelOrientationNormal = 0,
+  kModePanelOrientationBottomUp,
+  kModePanelOrientationLeftUp,
+  kModePanelOrientationRightUp
+};
diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h
index c8736f2..20896ed 100644
--- a/drm/DrmAtomicStateManager.h
+++ b/drm/DrmAtomicStateManager.h
@@ -21,7 +21,7 @@
 #include <memory>
 #include <optional>
 
-#include "compositor/ColorInfo.h"
+#include "compositor/DisplayInfo.h"
 #include "compositor/DrmKmsPlan.h"
 #include "compositor/LayerData.h"
 #include "drm/DrmPlane.h"
diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp
index 5371513..eeec3b1 100644
--- a/drm/DrmConnector.cpp
+++ b/drm/DrmConnector.cpp
@@ -23,10 +23,12 @@
 
 #include <array>
 #include <cerrno>
+#include <cinttypes>
 #include <cstdint>
 #include <sstream>
 
 #include "DrmDevice.h"
+#include "compositor/DisplayInfo.h"
 #include "utils/log.h"
 
 #ifndef DRM_MODE_CONNECTOR_SPI
@@ -136,6 +138,26 @@
   GetConnectorProperty("content type", &content_type_property_,
                        /*is_optional=*/true);
 
+  if (GetConnectorProperty("panel orientation", &panel_orientation_,
+                           /*is_optional=*/true)) {
+    panel_orientation_
+        .AddEnumToMapReverse("Normal",
+                             PanelOrientation::kModePanelOrientationNormal,
+                             panel_orientation_enum_map_);
+    panel_orientation_
+        .AddEnumToMapReverse("Upside Down",
+                             PanelOrientation::kModePanelOrientationBottomUp,
+                             panel_orientation_enum_map_);
+    panel_orientation_
+        .AddEnumToMapReverse("Left Side Up",
+                             PanelOrientation::kModePanelOrientationLeftUp,
+                             panel_orientation_enum_map_);
+    panel_orientation_
+        .AddEnumToMapReverse("Right Side Up",
+                             PanelOrientation::kModePanelOrientationRightUp,
+                             panel_orientation_enum_map_);
+  }
+
   return true;
 }
 
@@ -241,4 +263,26 @@
 
   return true;
 }
+
+std::optional<PanelOrientation> DrmConnector::GetPanelOrientation() {
+  if (!panel_orientation_.GetValue().has_value()) {
+    ALOGW("No panel orientation property available.");
+    return {};
+  }
+
+  /* The value_or(0) satisfies the compiler warning. However,
+   * panel_orientation_.GetValue() is guaranteed to have a value since we check
+   * has_value() and return early otherwise.
+   */
+  uint64_t panel_orientation_value = panel_orientation_.GetValue().value_or(0);
+
+  if (panel_orientation_enum_map_.count(panel_orientation_value) == 1) {
+    return panel_orientation_enum_map_[panel_orientation_value];
+  }
+
+  ALOGE("Unknown panel orientation: panel_orientation = %" PRIu64,
+        panel_orientation_value);
+  return {};
+}
+
 }  // namespace android
diff --git a/drm/DrmConnector.h b/drm/DrmConnector.h
index 9186f07..be84ae3 100644
--- a/drm/DrmConnector.h
+++ b/drm/DrmConnector.h
@@ -26,8 +26,7 @@
 #include "DrmMode.h"
 #include "DrmProperty.h"
 #include "DrmUnique.h"
-
-#include "compositor/ColorInfo.h"
+#include "compositor/DisplayInfo.h"
 
 namespace android {
 
@@ -118,6 +117,10 @@
     return writeback_out_fence_;
   }
 
+  auto &GetPanelOrientationProperty() const {
+    return panel_orientation_;
+  }
+
   auto IsConnected() const {
     return connector_->connection == DRM_MODE_CONNECTED;
   }
@@ -130,11 +133,13 @@
     return connector_->mmHeight;
   };
 
+  auto GetPanelOrientation() -> std::optional<PanelOrientation>;
+
  private:
   DrmConnector(DrmModeConnectorUnique connector, DrmDevice *drm, uint32_t index)
       : connector_(std::move(connector)),
         drm_(drm),
-        index_in_res_array_(index){};
+        index_in_res_array_(index) {};
 
   DrmModeConnectorUnique connector_;
   DrmDevice *const drm_;
@@ -157,7 +162,9 @@
   DrmProperty writeback_pixel_formats_;
   DrmProperty writeback_fb_id_;
   DrmProperty writeback_out_fence_;
+  DrmProperty panel_orientation_;
 
   std::map<Colorspace, uint64_t> colorspace_enum_map_;
+  std::map<uint64_t, PanelOrientation> panel_orientation_enum_map_;
 };
 }  // namespace android
diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp
index 310e67b..dbb5ad6 100644
--- a/drm/DrmPlane.cpp
+++ b/drm/DrmPlane.cpp
@@ -155,14 +155,11 @@
   if (crtc_prop_val != 0 && crtc_prop_val != crtc.GetId() &&
       GetType() == DRM_PLANE_TYPE_PRIMARY) {
     // Some DRM driver such as omap_drm allows sharing primary plane between
-    // CRTCs, but the primay plane could not be shared if it has been used by
+    // CRTCs, but the primary plane could not be shared if it has been used by
     // any CRTC already, which is protected by the plane_switching_crtc function
     // in the kernel drivers/gpu/drm/drm_atomic.c file.
     // The current drm_hwc design is not ready to support such scenario yet,
     // so adding the CRTC status check here to workaorund for now.
-    ALOGW("%s: This Plane(id=%d) is activated for Crtc(id=%" PRIu64
-          "), could not be used for Crtc (id=%d)",
-          __FUNCTION__, GetId(), crtc_prop_val, crtc.GetId());
     return false;
   }
 
diff --git a/drm/DrmProperty.cpp b/drm/DrmProperty.cpp
index 031918a..dbd307e 100644
--- a/drm/DrmProperty.cpp
+++ b/drm/DrmProperty.cpp
@@ -22,6 +22,7 @@
 #include <xf86drmMode.h>
 
 #include <cerrno>
+#include <cinttypes>
 #include <cstdint>
 #include <string>
 
@@ -125,4 +126,22 @@
   return true;
 }
 
+std::optional<std::string> DrmProperty::GetEnumNameFromValue(
+    uint64_t value) const {
+  if (enums_.empty()) {
+    ALOGE("No enum values for property: %s", name_.c_str());
+    return {};
+  }
+
+  for (const auto &it : enums_) {
+    if (it.value == value) {
+      return it.name;
+    }
+  }
+
+  ALOGE("Property '%s' has no matching enum for value: %" PRIu64, name_.c_str(),
+        value);
+  return {};
+}
+
 }  // namespace android
diff --git a/drm/DrmProperty.h b/drm/DrmProperty.h
index 516518b..2683ad8 100644
--- a/drm/DrmProperty.h
+++ b/drm/DrmProperty.h
@@ -64,10 +64,16 @@
   auto AddEnumToMap(const std::string &name, E key, std::map<E, uint64_t> &map)
       -> bool;
 
+  template <class E>
+  auto AddEnumToMapReverse(const std::string &name, E value,
+                           std::map<uint64_t, E> &map) -> bool;
+
   explicit operator bool() const {
     return id_ != 0;
   }
 
+  auto GetEnumNameFromValue(uint64_t value) const -> std::optional<std::string>;
+
  private:
   class DrmPropertyEnum {
    public:
@@ -104,4 +110,18 @@
   return false;
 }
 
+template <class E>
+auto DrmProperty::AddEnumToMapReverse(const std::string &name, E value,
+                                      std::map<uint64_t, E> &map) -> bool {
+  uint64_t enum_value = UINT64_MAX;
+  int err = 0;
+  std::tie(enum_value, err) = GetEnumValueWithName(name);
+  if (err == 0) {
+    map[enum_value] = value;
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace android
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index 7f65e65..6797c56 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -24,10 +24,15 @@
 #include "backend/Backend.h"
 #include "backend/BackendManager.h"
 #include "bufferinfo/BufferInfoGetter.h"
+#include "compositor/DisplayInfo.h"
+#include "drm/DrmConnector.h"
+#include "drm/DrmDisplayPipeline.h"
 #include "drm/DrmHwc.h"
 #include "utils/log.h"
 #include "utils/properties.h"
 
+using ::android::DrmDisplayPipeline;
+
 namespace android {
 
 std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) {
@@ -196,6 +201,23 @@
   return HWC2::Error::None;
 }
 
+std::optional<PanelOrientation> HwcDisplay::getDisplayPhysicalOrientation() {
+  if (IsInHeadlessMode()) {
+    // The pipeline can be nullptr in headless mode, so return the default
+    // "normal" mode.
+    return PanelOrientation::kModePanelOrientationNormal;
+  }
+
+  DrmDisplayPipeline &pipeline = GetPipe();
+  if (pipeline.connector == nullptr || pipeline.connector->Get() == nullptr) {
+    ALOGW(
+        "No display pipeline present to query the panel orientation property.");
+    return {};
+  }
+
+  return pipeline.connector->Get()->GetPanelOrientation();
+}
+
 HWC2::Error HwcDisplay::ChosePreferredConfig() {
   HWC2::Error err{};
   if (type_ == HWC2::DisplayType::Virtual) {
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index c568a73..4680ca9 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -23,7 +23,7 @@
 #include <sstream>
 
 #include "HwcDisplayConfigs.h"
-#include "compositor/ColorInfo.h"
+#include "compositor/DisplayInfo.h"
 #include "compositor/FlatteningController.h"
 #include "compositor/LayerData.h"
 #include "drm/DrmAtomicStateManager.h"
@@ -198,6 +198,8 @@
     virtual_disp_height_ = height;
   }
 
+  auto getDisplayPhysicalOrientation() -> std::optional<PanelOrientation>;
+
  private:
   HwcDisplayConfigs configs_;
 
diff --git a/hwc2_device/HwcLayer.cpp b/hwc2_device/HwcLayer.cpp
index cd2a319..cb18fdd 100644
--- a/hwc2_device/HwcLayer.cpp
+++ b/hwc2_device/HwcLayer.cpp
@@ -25,6 +25,11 @@
 namespace android {
 
 void HwcLayer::SetLayerProperties(const LayerProperties& layer_properties) {
+  if (layer_properties.buffer) {
+    layer_data_.acquire_fence = layer_properties.buffer->acquire_fence;
+    buffer_handle_ = layer_properties.buffer->buffer_handle;
+    buffer_handle_updated_ = true;
+  }
   if (layer_properties.blend_mode) {
     blend_mode_ = layer_properties.blend_mode.value();
   }
diff --git a/hwc2_device/HwcLayer.h b/hwc2_device/HwcLayer.h
index b8fb959..e1d62b7 100644
--- a/hwc2_device/HwcLayer.h
+++ b/hwc2_device/HwcLayer.h
@@ -28,8 +28,13 @@
 
 class HwcLayer {
  public:
+  struct Buffer {
+    buffer_handle_t buffer_handle;
+    SharedFd acquire_fence;
+  };
   // A set of properties to be validated.
   struct LayerProperties {
+    std::optional<Buffer> buffer;
     std::optional<BufferBlendMode> blend_mode;
     std::optional<BufferColorSpace> color_space;
     std::optional<BufferSampleRange> sample_range;
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp
index c980eac..ebe9a1c 100644
--- a/hwc3/ComposerClient.cpp
+++ b/hwc3/ComposerClient.cpp
@@ -43,6 +43,7 @@
 #include <hardware/hwcomposer_defs.h>
 
 #include "bufferinfo/BufferInfo.h"
+#include "compositor/DisplayInfo.h"
 #include "hwc2_device/HwcDisplay.h"
 #include "hwc2_device/HwcDisplayConfigs.h"
 #include "hwc2_device/HwcLayer.h"
@@ -191,6 +192,28 @@
   }
 }
 
+#if __ANDROID_API__ < 35
+
+class DisplayConfiguration {
+ public:
+  class Dpi {
+   public:
+    float x = 0.000000F;
+    float y = 0.000000F;
+  };
+  // NOLINTNEXTLINE(readability-identifier-naming)
+  int32_t configId = 0;
+  int32_t width = 0;
+  int32_t height = 0;
+  std::optional<Dpi> dpi;
+  // NOLINTNEXTLINE(readability-identifier-naming)
+  int32_t configGroup = 0;
+  // NOLINTNEXTLINE(readability-identifier-naming)
+  int32_t vsyncPeriod = 0;
+};
+
+#endif
+
 DisplayConfiguration HwcDisplayConfigToAidlConfiguration(
     const HwcDisplayConfigs& configs, const HwcDisplayConfig& config) {
   DisplayConfiguration aidl_configuration =
@@ -528,12 +551,20 @@
     return;
   }
 
-  HwcLayerWrapper layer_wrapper{command.layer, layer};
+  HwcLayer::LayerProperties properties;
   if (command.buffer) {
-    ExecuteSetLayerBuffer(display_id, layer_wrapper, *command.buffer);
+    HwcLayer::Buffer buffer;
+    auto err = ImportLayerBuffer(display_id, command.layer, *command.buffer,
+                                 &buffer.buffer_handle);
+    if (err != hwc3::Error::kNone) {
+      cmd_result_writer_->AddError(err);
+      return;
+    }
+    buffer.acquire_fence = ::android::MakeSharedFd(
+        command.buffer->fence.dup().release());
+    properties.buffer.emplace(buffer);
   }
 
-  HwcLayer::LayerProperties properties;
   properties.blend_mode = AidlToBlendMode(command.blendMode);
   properties.color_space = AidlToColorSpace(command.dataspace);
   properties.sample_range = AidlToSampleRange(command.dataspace);
@@ -576,9 +607,7 @@
     DispatchLayerCommand(command.display, layer_cmd);
   }
 
-  if (command.brightness) {
-    ExecuteSetDisplayBrightness(command.display, *command.brightness);
-  }
+  // TODO: Implement support for display brightness.
   if (command.colorTransformMatrix) {
     ExecuteSetDisplayColorTransform(command.display,
                                     *command.colorTransformMatrix);
@@ -885,13 +914,40 @@
 ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(
     int64_t display_id, common::Transform* orientation) {
   DEBUG_FUNC();
+
+  if (orientation == nullptr) {
+    ALOGE("Invalid 'orientation' pointer.");
+    return ToBinderStatus(hwc3::Error::kBadParameter);
+  }
+
   const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
   HwcDisplay* display = GetDisplay(display_id);
   if (display == nullptr) {
     return ToBinderStatus(hwc3::Error::kBadDisplay);
   }
 
-  *orientation = common::Transform::NONE;
+  PanelOrientation
+      drm_orientation = display->getDisplayPhysicalOrientation().value_or(
+          PanelOrientation::kModePanelOrientationNormal);
+
+  switch (drm_orientation) {
+    case PanelOrientation::kModePanelOrientationNormal:
+      *orientation = common::Transform::NONE;
+      break;
+    case PanelOrientation::kModePanelOrientationBottomUp:
+      *orientation = common::Transform::ROT_180;
+      break;
+    case PanelOrientation::kModePanelOrientationLeftUp:
+      *orientation = common::Transform::ROT_270;
+      break;
+    case PanelOrientation::kModePanelOrientationRightUp:
+      *orientation = common::Transform::ROT_90;
+      break;
+    default:
+      ALOGE("Unknown panel orientation value: %d", drm_orientation);
+      return ToBinderStatus(hwc3::Error::kBadDisplay);
+  }
+
   return ndk::ScopedAStatus::ok();
 }
 
@@ -1177,6 +1233,8 @@
   return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
+#if __ANDROID_API__ >= 35
+
 ndk::ScopedAStatus ComposerClient::getDisplayConfigurations(
     int64_t display_id, int32_t /*max_frame_interval_ns*/,
     std::vector<DisplayConfiguration>* configurations) {
@@ -1201,6 +1259,8 @@
   return ToBinderStatus(hwc3::Error::kUnsupported);
 }
 
+#endif
+
 std::string ComposerClient::Dump() {
   uint32_t size = 0;
   hwc_->Dump(&size, nullptr);
@@ -1216,43 +1276,18 @@
   return binder;
 }
 
-void ComposerClient::ExecuteSetLayerBuffer(int64_t display_id,
-                                           HwcLayerWrapper& layer,
-                                           const Buffer& buffer) {
-  buffer_handle_t imported_buffer = nullptr;
+hwc3::Error ComposerClient::ImportLayerBuffer(
+    int64_t display_id, int64_t layer_id, const Buffer& buffer,
+    buffer_handle_t* out_imported_buffer) {
+  *out_imported_buffer = nullptr;
 
   auto releaser = composer_resources_->CreateResourceReleaser(true);
-  auto err = composer_resources_->GetLayerBuffer(display_id, layer.layer_id,
-                                                 buffer, &imported_buffer,
+  auto err = composer_resources_->GetLayerBuffer(display_id, layer_id, buffer,
+                                                 out_imported_buffer,
                                                  releaser.get());
-  if (err != hwc3::Error::kNone) {
-    cmd_result_writer_->AddError(err);
-    return;
-  }
-
-  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
-  auto fence_fd = const_cast<ndk::ScopedFileDescriptor&>(buffer.fence)
-                      .release();
-  err = Hwc2toHwc3Error(layer.layer->SetLayerBuffer(imported_buffer, fence_fd));
-  if (err != hwc3::Error::kNone) {
-    cmd_result_writer_->AddError(err);
-  }
+  return err;
 }
 
-void ComposerClient::ExecuteSetDisplayBrightness(
-    uint64_t display_id, const DisplayBrightness& command) {
-  auto* display = GetDisplay(display_id);
-  if (display == nullptr) {
-    cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
-    return;
-  }
-
-  auto error = Hwc2toHwc3Error(
-      display->SetDisplayBrightness(command.brightness));
-  if (error != hwc3::Error::kNone) {
-    cmd_result_writer_->AddError(error);
-  }
-}
 void ComposerClient::ExecuteSetDisplayColorTransform(
     uint64_t display_id, const std::vector<float>& matrix) {
   auto* display = GetDisplay(display_id);
diff --git a/hwc3/ComposerClient.h b/hwc3/ComposerClient.h
index 5e4949e..91a0be0 100644
--- a/hwc3/ComposerClient.h
+++ b/hwc3/ComposerClient.h
@@ -39,11 +39,6 @@
 
 class DrmHwcThree;
 
-struct HwcLayerWrapper {
-  int64_t layer_id;
-  ::android::HwcLayer* layer;
-};
-
 class ComposerClient : public BnComposerClient {
  public:
   ComposerClient();
@@ -145,6 +140,9 @@
       common::Hdr* out_hdr) override;
   ndk::ScopedAStatus setRefreshRateChangedCallbackDebugEnabled(
       int64_t display, bool enabled) override;
+
+#if __ANDROID_API__ >= 35
+
   ndk::ScopedAStatus getDisplayConfigurations(
       int64_t display, int32_t max_frame_interval_ns,
       std::vector<DisplayConfiguration>* configurations) override;
@@ -152,19 +150,21 @@
       int64_t display, const ClockMonotonicTimestamp& expected_present_time,
       int32_t frame_interval_ns) override;
 
+#endif
+
  protected:
   ::ndk::SpAIBinder createBinder() override;
 
  private:
+  hwc3::Error ImportLayerBuffer(int64_t display_id, int64_t layer_id,
+                                const Buffer& buffer,
+                                buffer_handle_t* out_imported_buffer);
+
   // Layer commands
   void DispatchLayerCommand(int64_t display_id, const LayerCommand& command);
-  void ExecuteSetLayerBuffer(int64_t display_id, HwcLayerWrapper& layer_id,
-                             const Buffer& buffer);
 
   // Display commands
   void ExecuteDisplayCommand(const DisplayCommand& command);
-  void ExecuteSetDisplayBrightness(uint64_t display_id,
-                                   const DisplayBrightness& command);
   void ExecuteSetDisplayColorTransform(uint64_t display_id,
                                        const std::vector<float>& matrix);
   void ExecuteSetDisplayClientTarget(uint64_t display_id,
diff --git a/hwc3/DrmHwcThree.cpp b/hwc3/DrmHwcThree.cpp
index 2ac307c..fb14bc9 100644
--- a/hwc3/DrmHwcThree.cpp
+++ b/hwc3/DrmHwcThree.cpp
@@ -22,7 +22,9 @@
 
 #include "Utils.h"
 #include "aidl/android/hardware/graphics/common/Dataspace.h"
+#if __ANDROID_API__ >= 35
 #include "aidl/android/hardware/graphics/common/DisplayHotplugEvent.h"
+#endif
 
 namespace aidl::android::hardware::graphics::composer3::impl {
 
@@ -61,6 +63,8 @@
                               static_cast<int32_t>(vsync_period));
 }
 
+#if __ANDROID_API__ >= 35
+
 void DrmHwcThree::SendHotplugEventToClient(
     hwc2_display_t display_id, DrmHwc::DisplayStatus display_status) {
   common::DisplayHotplugEvent event = common::DisplayHotplugEvent::DISCONNECTED;
@@ -80,6 +84,17 @@
   composer_callback_->onHotplugEvent(static_cast<int64_t>(display_id), event);
 }
 
+#else
+
+void DrmHwcThree::SendHotplugEventToClient(
+    hwc2_display_t display_id, DrmHwc::DisplayStatus display_status) {
+  bool connected = display_status != DrmHwc::kDisconnected;
+  HandleDisplayHotplugEvent(static_cast<uint64_t>(display_id), connected);
+  composer_callback_->onHotplug(static_cast<int64_t>(display_id), connected);
+}
+
+#endif
+
 void DrmHwcThree::CleanDisplayResources(uint64_t display_id) {
   DEBUG_FUNC();
   HwcDisplay* display = GetDisplay(display_id);
diff --git a/hwc3/meson.build b/hwc3/meson.build
index 2486212..291c71a 100644
--- a/hwc3/meson.build
+++ b/hwc3/meson.build
@@ -14,7 +14,7 @@
     cpp_args : common_cpp_flags + hwc2_cpp_flags,
     dependencies : deps,
     install : true,
-    link_with: [drmhwc_common, drmhwc_hwc2_common],
+    link_whole: [drmhwc_common, drmhwc_hwc2_common],
     install_dir : get_option('bindir') / 'hw',
     include_directories: inc_include,
 )