Преглед на файлове

drm_hwcomposer: Reorganize struct DrmHwcLayer

1. Move BlendMode, ColorSpace, SampleRange fields to the struct BufferInfo,
   allowing extraction of the data from native_handle using Metadata@4 API.
   Use it when data from HWC2 API can't be used (Currently it's a BlendMode
   case for CLIENT layer)

2. Rename DrmHwcLayer to LayerData and move it to compositor/ directory.
   (I was confused in the past because of similarity of names DrmHwcLayer
    vs HwcLayer, so this step should meke it easier for newcomers to
    understand the code)

3. Allow clonning of the LayerData to propagate it through the composition
   pipeline. Thus LayerData can be used by both HwcLayer to track state
   and by the compositor.

Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
Roman Stratiienko преди 2 години
родител
ревизия
4b2cc484f9

+ 2 - 10
Android.bp

@@ -20,10 +20,7 @@ cc_library_static {
 
     srcs: ["utils/Worker.cpp"],
 
-    include_dirs: [
-        "external/drm_hwcomposer",
-        "external/drm_hwcomposer/include",
-    ],
+    include_dirs: ["external/drm_hwcomposer"],
 
     cflags: [
         "-Wall",
@@ -51,10 +48,7 @@ cc_defaults {
         "libutils",
     ],
 
-    include_dirs: [
-        "external/drm_hwcomposer",
-        "external/drm_hwcomposer/include",
-    ],
+    include_dirs: ["external/drm_hwcomposer"],
 
     static_libs: ["libdrmhwc_utils"],
 
@@ -101,8 +95,6 @@ filegroup {
         "drm/UEventListener.cpp",
         "drm/VSyncWorker.cpp",
 
-        "utils/hwcutils.cpp",
-
         "backend/Backend.cpp",
         "backend/BackendClient.cpp",
         "backend/BackendManager.cpp",

+ 3 - 3
backend/Backend.cpp

@@ -83,9 +83,9 @@ std::tuple<int, size_t> Backend::GetClientLayers(
 
 bool Backend::IsClientLayer(HwcDisplay *display, HwcLayer *layer) {
   return !HardwareSupportsLayerType(layer->GetSfType()) ||
-         !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->GetBuffer()) ||
+         !layer->IsLayerUsableAsDevice() ||
          display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY ||
-         (layer->RequireScalingOrPhasing() &&
+         (layer->GetLayerData().pi.RequireScalingOrPhasing() &&
           display->GetHwc2()->GetResMan().ForcedScalingWithGpu());
 }
 
@@ -99,7 +99,7 @@ uint32_t Backend::CalcPixOps(const std::vector<HwcLayer *> &layers,
   uint32_t pixops = 0;
   for (size_t z_order = 0; z_order < layers.size(); ++z_order) {
     if (z_order >= first_z && z_order < first_z + size) {
-      hwc_rect_t df = layers[z_order]->GetDisplayFrame();
+      hwc_rect_t &df = layers[z_order]->GetLayerData().pi.display_frame;
       pixops += (df.right - df.left) * (df.bottom - df.top);
     }
   }

+ 24 - 0
bufferinfo/BufferInfo.h

@@ -20,6 +20,26 @@
 
 constexpr int kBufferMaxPlanes = 4;
 
+enum class BufferColorSpace : int32_t {
+  kUndefined,
+  kItuRec601,
+  kItuRec709,
+  kItuRec2020,
+};
+
+enum class BufferSampleRange : int32_t {
+  kUndefined,
+  kFullRange,
+  kLimitedRange,
+};
+
+enum class BufferBlendMode : int32_t {
+  kUndefined,
+  kNone,
+  kPreMult,
+  kCoverage,
+};
+
 struct BufferInfo {
   uint32_t width;
   uint32_t height;
@@ -30,4 +50,8 @@ struct BufferInfo {
   uint32_t sizes[kBufferMaxPlanes];
   int prime_fds[kBufferMaxPlanes];
   uint64_t modifiers[kBufferMaxPlanes];
+
+  BufferColorSpace color_space;
+  BufferSampleRange sample_range;
+  BufferBlendMode blend_mode;
 };

+ 0 - 6
bufferinfo/BufferInfoGetter.cpp

@@ -48,12 +48,6 @@ BufferInfoGetter *BufferInfoGetter::GetInstance() {
   return inst.get();
 }
 
-bool BufferInfoGetter::IsHandleUsable(buffer_handle_t handle) {
-  auto bo = GetBoInfo(handle);
-
-  return bo && bo->prime_fds[0] != 0;
-}
-
 int LegacyBufferInfoGetter::Init() {
   int ret = hw_get_module(
       GRALLOC_HARDWARE_MODULE_ID,

+ 0 - 2
bufferinfo/BufferInfoGetter.h

@@ -38,8 +38,6 @@ class BufferInfoGetter {
   virtual auto GetBoInfo(buffer_handle_t handle)
       -> std::optional<BufferInfo> = 0;
 
-  bool IsHandleUsable(buffer_handle_t handle);
-
   static BufferInfoGetter *GetInstance();
 
   static bool IsDrmFormatRgb(uint32_t drm_format);

+ 1 - 1
compositor/DrmKmsPlan.cpp

@@ -24,7 +24,7 @@
 
 namespace android {
 auto DrmKmsPlan::CreateDrmKmsPlan(DrmDisplayPipeline &pipe,
-                                  std::vector<DrmHwcLayer> composition)
+                                  std::vector<LayerData> composition)
     -> std::unique_ptr<DrmKmsPlan> {
   auto plan = std::make_unique<DrmKmsPlan>();
 

+ 3 - 3
compositor/DrmKmsPlan.h

@@ -20,7 +20,7 @@
 #include <memory>
 #include <vector>
 
-#include "drmhwcomposer.h"
+#include "LayerData.h"
 
 namespace android {
 
@@ -28,7 +28,7 @@ class DrmDevice;
 
 struct DrmKmsPlan {
   struct LayerToPlaneJoining {
-    DrmHwcLayer layer;
+    LayerData layer;
     std::shared_ptr<BindingOwner<DrmPlane>> plane;
     int z_pos;
   };
@@ -36,7 +36,7 @@ struct DrmKmsPlan {
   std::vector<LayerToPlaneJoining> plan;
 
   static auto CreateDrmKmsPlan(DrmDisplayPipeline &pipe,
-                               std::vector<DrmHwcLayer> composition)
+                               std::vector<LayerData> composition)
       -> std::unique_ptr<DrmKmsPlan>;
 };
 

+ 81 - 0
compositor/LayerData.h

@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+
+#include <cmath>
+#include <cstdbool>
+#include <cstdint>
+#include <optional>
+#include <vector>
+
+#include "bufferinfo/BufferInfo.h"
+#include "drm/DrmFbImporter.h"
+#include "utils/UniqueFd.h"
+
+namespace android {
+
+class DrmFbIdHandle;
+
+enum LayerTransform : uint32_t {
+  kIdentity = 0,
+  kFlipH = 1 << 0,
+  kFlipV = 1 << 1,
+  kRotate90 = 1 << 2,
+  kRotate180 = 1 << 3,
+  kRotate270 = 1 << 4,
+};
+
+struct PresentInfo {
+  LayerTransform transform{};
+  uint16_t alpha = UINT16_MAX;
+  hwc_frect_t source_crop{};
+  hwc_rect_t display_frame{};
+
+  bool RequireScalingOrPhasing() const {
+    float src_width = source_crop.right - source_crop.left;
+    float src_height = source_crop.bottom - source_crop.top;
+
+    auto dest_width = float(display_frame.right - display_frame.left);
+    auto dest_height = float(display_frame.bottom - display_frame.top);
+
+    bool scaling = src_width != dest_width || src_height != dest_height;
+    bool phasing = (source_crop.left - std::floor(source_crop.left) != 0) ||
+                   (source_crop.top - std::floor(source_crop.top) != 0);
+    return scaling || phasing;
+  }
+};
+
+struct LayerData {
+  auto Clone() {
+    LayerData clonned;
+    clonned.bi = bi;
+    clonned.fb = fb;
+    clonned.pi = pi;
+    clonned.acquire_fence = std::move(acquire_fence);
+    return clonned;
+  }
+
+  std::optional<BufferInfo> bi;
+  std::shared_ptr<DrmFbIdHandle> fb;
+  PresentInfo pi;
+  UniqueFd acquire_fence;
+};
+
+}  // namespace android

+ 2 - 2
drm/DrmAtomicStateManager.cpp

@@ -109,9 +109,9 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
 
     for (auto &joining : args.composition->plan) {
       DrmPlane *plane = joining.plane->Get();
-      DrmHwcLayer &layer = joining.layer;
+      LayerData &layer = joining.layer;
 
-      new_frame_state.used_framebuffers.emplace_back(layer.fb_id_handle);
+      new_frame_state.used_framebuffers.emplace_back(layer.fb);
       new_frame_state.used_planes.emplace_back(joining.plane);
 
       /* Remove from 'unused' list, since plane is re-used */

+ 1 - 1
drm/DrmAtomicStateManager.h

@@ -26,10 +26,10 @@
 #include <tuple>
 
 #include "compositor/DrmKmsPlan.h"
+#include "compositor/LayerData.h"
 #include "drm/DrmPlane.h"
 #include "drm/ResourceManager.h"
 #include "drm/VSyncWorker.h"
-#include "drmhwcomposer.h"
 
 namespace android {
 

+ 50 - 51
drm/DrmPlane.cpp

@@ -91,17 +91,17 @@ int DrmPlane::Init() {
   GetPlaneProperty("zpos", zpos_property_, Presence::kOptional);
 
   if (GetPlaneProperty("rotation", rotation_property_, Presence::kOptional)) {
-    rotation_property_.AddEnumToMap("rotate-0", DrmHwcTransform::kIdentity,
+    rotation_property_.AddEnumToMap("rotate-0", LayerTransform::kIdentity,
                                     transform_enum_map_);
-    rotation_property_.AddEnumToMap("rotate-90", DrmHwcTransform::kRotate90,
+    rotation_property_.AddEnumToMap("rotate-90", LayerTransform::kRotate90,
                                     transform_enum_map_);
-    rotation_property_.AddEnumToMap("rotate-180", DrmHwcTransform::kRotate180,
+    rotation_property_.AddEnumToMap("rotate-180", LayerTransform::kRotate180,
                                     transform_enum_map_);
-    rotation_property_.AddEnumToMap("rotate-270", DrmHwcTransform::kRotate270,
+    rotation_property_.AddEnumToMap("rotate-270", LayerTransform::kRotate270,
                                     transform_enum_map_);
-    rotation_property_.AddEnumToMap("reflect-x", DrmHwcTransform::kFlipH,
+    rotation_property_.AddEnumToMap("reflect-x", LayerTransform::kFlipH,
                                     transform_enum_map_);
-    rotation_property_.AddEnumToMap("reflect-y", DrmHwcTransform::kFlipV,
+    rotation_property_.AddEnumToMap("reflect-y", LayerTransform::kFlipV,
                                     transform_enum_map_);
   }
 
@@ -109,11 +109,11 @@ int DrmPlane::Init() {
 
   if (GetPlaneProperty("pixel blend mode", blend_property_,
                        Presence::kOptional)) {
-    blend_property_.AddEnumToMap("Pre-multiplied", DrmHwcBlending::kPreMult,
+    blend_property_.AddEnumToMap("Pre-multiplied", BufferBlendMode::kPreMult,
                                  blending_enum_map_);
-    blend_property_.AddEnumToMap("Coverage", DrmHwcBlending::kCoverage,
+    blend_property_.AddEnumToMap("Coverage", BufferBlendMode::kCoverage,
                                  blending_enum_map_);
-    blend_property_.AddEnumToMap("None", DrmHwcBlending::kNone,
+    blend_property_.AddEnumToMap("None", BufferBlendMode::kNone,
                                  blending_enum_map_);
   }
 
@@ -123,23 +123,23 @@ int DrmPlane::Init() {
     if (GetPlaneProperty("COLOR_ENCODING", color_encoding_propery_,
                          Presence::kOptional)) {
       color_encoding_propery_.AddEnumToMap("ITU-R BT.709 YCbCr",
-                                           DrmHwcColorSpace::kItuRec709,
+                                           BufferColorSpace::kItuRec709,
                                            color_encoding_enum_map_);
       color_encoding_propery_.AddEnumToMap("ITU-R BT.601 YCbCr",
-                                           DrmHwcColorSpace::kItuRec601,
+                                           BufferColorSpace::kItuRec601,
                                            color_encoding_enum_map_);
       color_encoding_propery_.AddEnumToMap("ITU-R BT.2020 YCbCr",
-                                           DrmHwcColorSpace::kItuRec2020,
+                                           BufferColorSpace::kItuRec2020,
                                            color_encoding_enum_map_);
     }
 
     if (GetPlaneProperty("COLOR_RANGE", color_range_property_,
                          Presence::kOptional)) {
       color_range_property_.AddEnumToMap("YCbCr full range",
-                                         DrmHwcSampleRange::kFullRange,
+                                         BufferSampleRange::kFullRange,
                                          color_range_enum_map_);
       color_range_property_.AddEnumToMap("YCbCr limited range",
-                                         DrmHwcSampleRange::kLimitedRange,
+                                         BufferSampleRange::kLimitedRange,
                                          color_range_enum_map_);
     }
   }
@@ -151,32 +151,32 @@ bool DrmPlane::IsCrtcSupported(const DrmCrtc &crtc) const {
   return ((1 << crtc.GetIndexInResArray()) & plane_->possible_crtcs) != 0;
 }
 
-bool DrmPlane::IsValidForLayer(DrmHwcLayer *layer) {
+bool DrmPlane::IsValidForLayer(LayerData *layer) {
   if (!rotation_property_) {
-    if (layer->transform != DrmHwcTransform::kIdentity) {
+    if (layer->pi.transform != LayerTransform::kIdentity) {
       ALOGV("No rotation property on plane %d", GetId());
       return false;
     }
   } else {
-    if (transform_enum_map_.count(layer->transform) == 0) {
+    if (transform_enum_map_.count(layer->pi.transform) == 0) {
       ALOGV("Transform is not supported on plane %d", GetId());
       return false;
     }
   }
 
-  if (alpha_property_.id() == 0 && layer->alpha != UINT16_MAX) {
+  if (alpha_property_.id() == 0 && layer->pi.alpha != UINT16_MAX) {
     ALOGV("Alpha is not supported on plane %d", GetId());
     return false;
   }
 
-  if (blending_enum_map_.count(layer->blending) == 0 &&
-      layer->blending != DrmHwcBlending::kNone &&
-      layer->blending != DrmHwcBlending::kPreMult) {
+  if (blending_enum_map_.count(layer->bi->blend_mode) == 0 &&
+      layer->bi->blend_mode != BufferBlendMode::kNone &&
+      layer->bi->blend_mode != BufferBlendMode::kPreMult) {
     ALOGV("Blending is not supported on plane %d", GetId());
     return false;
   }
 
-  uint32_t format = layer->buffer_info->format;
+  uint32_t format = layer->bi->format;
   if (!IsFormatSupported(format)) {
     ALOGV("Plane %d does not supports %c%c%c%c format", GetId(), format,
           format >> 8, format >> 16, format >> 24);
@@ -198,17 +198,17 @@ bool DrmPlane::HasNonRgbFormat() const {
                           }) != std::end(formats_);
 }
 
-static uint64_t ToDrmRotation(DrmHwcTransform transform) {
+static uint64_t ToDrmRotation(LayerTransform transform) {
   uint64_t rotation = 0;
-  if ((transform & DrmHwcTransform::kFlipH) != 0)
+  if ((transform & LayerTransform::kFlipH) != 0)
     rotation |= DRM_MODE_REFLECT_X;
-  if ((transform & DrmHwcTransform::kFlipV) != 0)
+  if ((transform & LayerTransform::kFlipV) != 0)
     rotation |= DRM_MODE_REFLECT_Y;
-  if ((transform & DrmHwcTransform::kRotate90) != 0)
+  if ((transform & LayerTransform::kRotate90) != 0)
     rotation |= DRM_MODE_ROTATE_90;
-  else if ((transform & DrmHwcTransform::kRotate180) != 0)
+  else if ((transform & LayerTransform::kRotate180) != 0)
     rotation |= DRM_MODE_ROTATE_180;
-  else if ((transform & DrmHwcTransform::kRotate270) != 0)
+  else if ((transform & LayerTransform::kRotate270) != 0)
     rotation |= DRM_MODE_ROTATE_270;
   else
     rotation |= DRM_MODE_ROTATE_0;
@@ -222,9 +222,9 @@ static int To1616FixPt(float in) {
   return int(in * (1 << kBitShift));
 }
 
-auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer,
+auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, LayerData &layer,
                               uint32_t zpos, uint32_t crtc_id) -> int {
-  if (!layer.fb_id_handle) {
+  if (!layer.fb) {
     ALOGE("Expected a valid framebuffer for pset");
     return -EINVAL;
   }
@@ -245,46 +245,45 @@ auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer,
     return -EINVAL;
   }
 
+  auto &disp = layer.pi.display_frame;
+  auto &src = layer.pi.source_crop;
   if (!crtc_property_.AtomicSet(pset, crtc_id) ||
-      !fb_property_.AtomicSet(pset, layer.fb_id_handle->GetFbId()) ||
-      !crtc_x_property_.AtomicSet(pset, layer.display_frame.left) ||
-      !crtc_y_property_.AtomicSet(pset, layer.display_frame.top) ||
-      !crtc_w_property_.AtomicSet(pset, layer.display_frame.right -
-                                            layer.display_frame.left) ||
-      !crtc_h_property_.AtomicSet(pset, layer.display_frame.bottom -
-                                            layer.display_frame.top) ||
-      !src_x_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.left)) ||
-      !src_y_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.top)) ||
-      !src_w_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.right -
-                                                   layer.source_crop.left)) ||
-      !src_h_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.bottom -
-                                                   layer.source_crop.top))) {
+      !fb_property_.AtomicSet(pset, layer.fb->GetFbId()) ||
+      !crtc_x_property_.AtomicSet(pset, disp.left) ||
+      !crtc_y_property_.AtomicSet(pset, disp.top) ||
+      !crtc_w_property_.AtomicSet(pset, disp.right - disp.left) ||
+      !crtc_h_property_.AtomicSet(pset, disp.bottom - disp.top) ||
+      !src_x_property_.AtomicSet(pset, To1616FixPt(src.left)) ||
+      !src_y_property_.AtomicSet(pset, To1616FixPt(src.top)) ||
+      !src_w_property_.AtomicSet(pset, To1616FixPt(src.right - src.left)) ||
+      !src_h_property_.AtomicSet(pset, To1616FixPt(src.bottom - src.top))) {
     return -EINVAL;
   }
 
   if (rotation_property_ &&
-      !rotation_property_.AtomicSet(pset, ToDrmRotation(layer.transform))) {
+      !rotation_property_.AtomicSet(pset, ToDrmRotation(layer.pi.transform))) {
     return -EINVAL;
   }
 
-  if (alpha_property_ && !alpha_property_.AtomicSet(pset, layer.alpha)) {
+  if (alpha_property_ && !alpha_property_.AtomicSet(pset, layer.pi.alpha)) {
     return -EINVAL;
   }
 
-  if (blending_enum_map_.count(layer.blending) != 0 &&
-      !blend_property_.AtomicSet(pset, blending_enum_map_[layer.blending])) {
+  if (blending_enum_map_.count(layer.bi->blend_mode) != 0 &&
+      !blend_property_.AtomicSet(pset,
+                                 blending_enum_map_[layer.bi->blend_mode])) {
     return -EINVAL;
   }
 
-  if (color_encoding_enum_map_.count(layer.color_space) != 0 &&
+  if (color_encoding_enum_map_.count(layer.bi->color_space) != 0 &&
       !color_encoding_propery_
-           .AtomicSet(pset, color_encoding_enum_map_[layer.color_space])) {
+           .AtomicSet(pset, color_encoding_enum_map_[layer.bi->color_space])) {
     return -EINVAL;
   }
 
-  if (color_range_enum_map_.count(layer.sample_range) != 0 &&
+  if (color_range_enum_map_.count(layer.bi->sample_range) != 0 &&
       !color_range_property_
-           .AtomicSet(pset, color_range_enum_map_[layer.sample_range])) {
+           .AtomicSet(pset, color_range_enum_map_[layer.bi->sample_range])) {
     return -EINVAL;
   }
 

+ 8 - 8
drm/DrmPlane.h

@@ -24,12 +24,12 @@
 
 #include "DrmCrtc.h"
 #include "DrmProperty.h"
-#include "drmhwcomposer.h"
+#include "compositor/LayerData.h"
 
 namespace android {
 
 class DrmDevice;
-struct DrmHwcLayer;
+struct LayerData;
 
 class DrmPlane : public PipelineBindable<DrmPlane> {
  public:
@@ -40,7 +40,7 @@ class DrmPlane : public PipelineBindable<DrmPlane> {
       -> std::unique_ptr<DrmPlane>;
 
   bool IsCrtcSupported(const DrmCrtc &crtc) const;
-  bool IsValidForLayer(DrmHwcLayer *layer);
+  bool IsValidForLayer(LayerData *layer);
 
   auto GetType() const {
     return type_;
@@ -49,7 +49,7 @@ class DrmPlane : public PipelineBindable<DrmPlane> {
   bool IsFormatSupported(uint32_t format) const;
   bool HasNonRgbFormat() const;
 
-  auto AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer, uint32_t zpos,
+  auto AtomicSetState(drmModeAtomicReq &pset, LayerData &layer, uint32_t zpos,
                       uint32_t crtc_id) -> int;
   auto AtomicDisablePlane(drmModeAtomicReq &pset) -> int;
   auto &GetZPosProperty() const {
@@ -94,10 +94,10 @@ class DrmPlane : public PipelineBindable<DrmPlane> {
   DrmProperty color_encoding_propery_;
   DrmProperty color_range_property_;
 
-  std::map<DrmHwcBlending, uint64_t> blending_enum_map_;
-  std::map<DrmHwcColorSpace, uint64_t> color_encoding_enum_map_;
-  std::map<DrmHwcSampleRange, uint64_t> color_range_enum_map_;
-  std::map<DrmHwcTransform, uint64_t> transform_enum_map_;
+  std::map<BufferBlendMode, uint64_t> blending_enum_map_;
+  std::map<BufferColorSpace, uint64_t> color_encoding_enum_map_;
+  std::map<BufferSampleRange, uint64_t> color_range_enum_map_;
+  std::map<LayerTransform, uint64_t> transform_enum_map_;
 };
 }  // namespace android
 

+ 23 - 15
hwc2_device/HwcDisplay.cpp

@@ -90,6 +90,7 @@ HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type,
     : hwc2_(hwc2),
       handle_(handle),
       type_(type),
+      client_layer_(this),
       color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
   // clang-format off
   color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0,
@@ -188,7 +189,7 @@ HWC2::Error HwcDisplay::AcceptDisplayChanges() {
 }
 
 HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
-  layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer());
+  layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer(this));
   *layer = static_cast<hwc2_layer_t>(layer_idx_);
   ++layer_idx_;
   return HWC2::Error::None;
@@ -478,18 +479,26 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
   if (z_map.empty())
     return HWC2::Error::BadLayer;
 
-  std::vector<DrmHwcLayer> composition_layers;
+  std::vector<LayerData> composition_layers;
+
+  /* Import & populate */
+  for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
+    l.second->PopulateLayerData(a_args.test_only);
+  }
 
   // now that they're ordered by z, add them to the composition
   for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
-    DrmHwcLayer layer;
-    l.second->PopulateDrmLayer(&layer);
-    int ret = layer.ImportBuffer(GetPipe().device);
-    if (ret) {
-      ALOGE("Failed to import layer, ret=%d", ret);
-      return HWC2::Error::NoResources;
+    if (!l.second->IsLayerUsableAsDevice()) {
+      /* This will be normally triggered on validation of the first frame
+       * containing CLIENT layer. At this moment client buffer is not yet
+       * provided by the CLIENT.
+       * This may be triggered once in HwcLayer lifecycle in case FB can't be
+       * imported. For example when non-contiguous buffer is imported into
+       * contiguous-only DRM/KMS driver.
+       */
+      return HWC2::Error::BadLayer;
     }
-    composition_layers.emplace_back(std::move(layer));
+    composition_layers.emplace_back(l.second->GetLayerData().Clone());
   }
 
   /* Store plan to ensure shared planes won't be stolen by other display
@@ -596,14 +605,13 @@ HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target,
     return HWC2::Error::None;
   }
 
-  /* TODO: Do not update source_crop every call.
-   * It makes sense to do it once after every hotplug event. */
-  auto bi = BufferInfoGetter::GetInstance()->GetBoInfo(target);
-
-  if (!bi) {
-    return HWC2::Error::BadParameter;
+  client_layer_.PopulateLayerData(/*test = */ true);
+  if (!client_layer_.IsLayerUsableAsDevice()) {
+    ALOGE("Client layer must be always usable by DRM/KMS");
+    return HWC2::Error::BadLayer;
   }
 
+  auto &bi = client_layer_.GetLayerData().bi;
   hwc_frect_t source_crop = {.left = 0.0F,
                              .top = 0.0F,
                              .right = static_cast<float>(bi->width),

+ 1 - 1
hwc2_device/HwcDisplay.h

@@ -22,10 +22,10 @@
 #include <optional>
 
 #include "HwcDisplayConfigs.h"
+#include "compositor/LayerData.h"
 #include "drm/DrmAtomicStateManager.h"
 #include "drm/ResourceManager.h"
 #include "drm/VSyncWorker.h"
-#include "drmhwcomposer.h"
 #include "hwc2_device/HwcLayer.h"
 
 namespace android {

+ 70 - 34
hwc2_device/HwcLayer.cpp

@@ -18,6 +18,8 @@
 
 #include "HwcLayer.h"
 
+#include "HwcDisplay.h"
+#include "bufferinfo/BufferInfoGetter.h"
 #include "utils/log.h"
 
 namespace android {
@@ -30,17 +32,17 @@ HWC2::Error HwcLayer::SetCursorPosition(int32_t /*x*/, int32_t /*y*/) {
 HWC2::Error HwcLayer::SetLayerBlendMode(int32_t mode) {
   switch (static_cast<HWC2::BlendMode>(mode)) {
     case HWC2::BlendMode::None:
-      blending_ = DrmHwcBlending::kNone;
+      blend_mode_ = BufferBlendMode::kNone;
       break;
     case HWC2::BlendMode::Premultiplied:
-      blending_ = DrmHwcBlending::kPreMult;
+      blend_mode_ = BufferBlendMode::kPreMult;
       break;
     case HWC2::BlendMode::Coverage:
-      blending_ = DrmHwcBlending::kCoverage;
+      blend_mode_ = BufferBlendMode::kCoverage;
       break;
     default:
-      ALOGE("Unknown blending mode b=%d", blending_);
-      blending_ = DrmHwcBlending::kNone;
+      ALOGE("Unknown blending mode b=%d", blend_mode_);
+      blend_mode_ = BufferBlendMode::kUndefined;
       break;
   }
   return HWC2::Error::None;
@@ -51,8 +53,10 @@ HWC2::Error HwcLayer::SetLayerBlendMode(int32_t mode) {
  */
 HWC2::Error HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
                                      int32_t acquire_fence) {
-  buffer_ = buffer;
   acquire_fence_ = UniqueFd(acquire_fence);
+  buffer_handle_ = buffer;
+  buffer_handle_updated_ = true;
+
   return HWC2::Error::None;
 }
 
@@ -70,54 +74,54 @@ HWC2::Error HwcLayer::SetLayerCompositionType(int32_t type) {
 HWC2::Error HwcLayer::SetLayerDataspace(int32_t dataspace) {
   switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
     case HAL_DATASPACE_STANDARD_BT709:
-      color_space_ = DrmHwcColorSpace::kItuRec709;
+      color_space_ = BufferColorSpace::kItuRec709;
       break;
     case HAL_DATASPACE_STANDARD_BT601_625:
     case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
     case HAL_DATASPACE_STANDARD_BT601_525:
     case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
-      color_space_ = DrmHwcColorSpace::kItuRec601;
+      color_space_ = BufferColorSpace::kItuRec601;
       break;
     case HAL_DATASPACE_STANDARD_BT2020:
     case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
-      color_space_ = DrmHwcColorSpace::kItuRec2020;
+      color_space_ = BufferColorSpace::kItuRec2020;
       break;
     default:
-      color_space_ = DrmHwcColorSpace::kUndefined;
+      color_space_ = BufferColorSpace::kUndefined;
   }
 
   switch (dataspace & HAL_DATASPACE_RANGE_MASK) {
     case HAL_DATASPACE_RANGE_FULL:
-      sample_range_ = DrmHwcSampleRange::kFullRange;
+      sample_range_ = BufferSampleRange::kFullRange;
       break;
     case HAL_DATASPACE_RANGE_LIMITED:
-      sample_range_ = DrmHwcSampleRange::kLimitedRange;
+      sample_range_ = BufferSampleRange::kLimitedRange;
       break;
     default:
-      sample_range_ = DrmHwcSampleRange::kUndefined;
+      sample_range_ = BufferSampleRange::kUndefined;
   }
   return HWC2::Error::None;
 }
 
 HWC2::Error HwcLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
-  display_frame_ = frame;
+  layer_data_.pi.display_frame = frame;
   return HWC2::Error::None;
 }
 
 HWC2::Error HwcLayer::SetLayerPlaneAlpha(float alpha) {
-  alpha_ = alpha;
+  layer_data_.pi.alpha = std::lround(alpha * UINT16_MAX);
   return HWC2::Error::None;
 }
 
 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
 HWC2::Error HwcLayer::SetLayerSidebandStream(
-    const native_handle_t * /*stream*/) {
+    const native_handle_t* /*stream*/) {
   // TODO(nobody): We don't support sideband
   return HWC2::Error::Unsupported;
 }
 
 HWC2::Error HwcLayer::SetLayerSourceCrop(hwc_frect_t crop) {
-  source_crop_ = crop;
+  layer_data_.pi.source_crop = crop;
   return HWC2::Error::None;
 }
 
@@ -135,19 +139,19 @@ HWC2::Error HwcLayer::SetLayerTransform(int32_t transform) {
   // redundant in this case. 90* rotation can be combined with either horizontal
   // flip or vertical flip, so treat it differently
   if (transform == HWC_TRANSFORM_ROT_270) {
-    l_transform = DrmHwcTransform::kRotate270;
+    l_transform = LayerTransform::kRotate270;
   } else if (transform == HWC_TRANSFORM_ROT_180) {
-    l_transform = DrmHwcTransform::kRotate180;
+    l_transform = LayerTransform::kRotate180;
   } else {
     if ((transform & HWC_TRANSFORM_FLIP_H) != 0)
-      l_transform |= DrmHwcTransform::kFlipH;
+      l_transform |= LayerTransform::kFlipH;
     if ((transform & HWC_TRANSFORM_FLIP_V) != 0)
-      l_transform |= DrmHwcTransform::kFlipV;
+      l_transform |= LayerTransform::kFlipV;
     if ((transform & HWC_TRANSFORM_ROT_90) != 0)
-      l_transform |= DrmHwcTransform::kRotate90;
+      l_transform |= LayerTransform::kRotate90;
   }
 
-  transform_ = static_cast<DrmHwcTransform>(l_transform);
+  layer_data_.pi.transform = static_cast<LayerTransform>(l_transform);
   return HWC2::Error::None;
 }
 
@@ -162,17 +166,49 @@ HWC2::Error HwcLayer::SetLayerZOrder(uint32_t order) {
   return HWC2::Error::None;
 }
 
-void HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) {
-  layer->sf_handle = buffer_;
-  // TODO(rsglobal): Avoid extra fd duplication
-  layer->acquire_fence = UniqueFd::Dup(acquire_fence_.Get());
-  layer->display_frame = display_frame_;
-  layer->alpha = std::lround(alpha_ * UINT16_MAX);
-  layer->blending = blending_;
-  layer->source_crop = source_crop_;
-  layer->transform = transform_;
-  layer->color_space = color_space_;
-  layer->sample_range = sample_range_;
+void HwcLayer::ImportFb() {
+  if (!IsLayerUsableAsDevice() || !buffer_handle_updated_) {
+    return;
+  }
+  buffer_handle_updated_ = false;
+
+  layer_data_.fb = {};
+
+  layer_data_.bi = BufferInfoGetter::GetInstance()->GetBoInfo(buffer_handle_);
+  if (!layer_data_.bi) {
+    ALOGW("Unable to get buffer information (0x%p)", buffer_handle_);
+    bi_get_failed_ = true;
+    return;
+  }
+
+  layer_data_
+      .fb = parent_->GetPipe().device->GetDrmFbImporter().GetOrCreateFbId(
+      &layer_data_.bi.value());
+
+  if (!layer_data_.fb) {
+    ALOGV("Unable to create framebuffer object for buffer 0x%p",
+          buffer_handle_);
+    fb_import_failed_ = true;
+    return;
+  }
+}
+
+void HwcLayer::PopulateLayerData(bool test) {
+  ImportFb();
+
+  if (blend_mode_ != BufferBlendMode::kUndefined) {
+    layer_data_.bi->blend_mode = blend_mode_;
+  }
+  if (color_space_ != BufferColorSpace::kUndefined) {
+    layer_data_.bi->color_space = color_space_;
+  }
+  if (sample_range_ != BufferSampleRange::kUndefined) {
+    layer_data_.bi->sample_range = sample_range_;
+  }
+
+  if (!test) {
+    layer_data_.acquire_fence = std::move(acquire_fence_);
+  }
 }
 
 }  // namespace android

+ 38 - 34
hwc2_device/HwcLayer.h

@@ -19,14 +19,16 @@
 
 #include <hardware/hwcomposer2.h>
 
-#include <cmath>
-
-#include "drmhwcomposer.h"
+#include "compositor/LayerData.h"
 
 namespace android {
 
+class HwcDisplay;
+
 class HwcLayer {
  public:
+  explicit HwcLayer(HwcDisplay *parent_display) : parent_(parent_display){};
+
   HWC2::Composition GetSfType() const {
     return sf_type_;
   }
@@ -55,27 +57,8 @@ class HwcLayer {
     return z_order_;
   }
 
-  buffer_handle_t GetBuffer() {
-    return buffer_;
-  }
-
-  hwc_rect_t GetDisplayFrame() {
-    return display_frame_;
-  }
-
-  void PopulateDrmLayer(DrmHwcLayer *layer);
-
-  bool RequireScalingOrPhasing() const {
-    float src_width = source_crop_.right - source_crop_.left;
-    float src_height = source_crop_.bottom - source_crop_.top;
-
-    auto dest_width = float(display_frame_.right - display_frame_.left);
-    auto dest_height = float(display_frame_.bottom - display_frame_.top);
-
-    bool scaling = src_width != dest_width || src_height != dest_height;
-    bool phasing = (source_crop_.left - std::floor(source_crop_.left) != 0) ||
-                   (source_crop_.top - std::floor(source_crop_.top) != 0);
-    return scaling || phasing;
+  auto &GetLayerData() {
+    return layer_data_;
   }
 
   // Layer hooks
@@ -100,20 +83,41 @@ class HwcLayer {
   HWC2::Composition sf_type_ = HWC2::Composition::Invalid;
   HWC2::Composition validated_type_ = HWC2::Composition::Invalid;
 
-  buffer_handle_t buffer_ = nullptr;
-  hwc_rect_t display_frame_;
-  static constexpr float kOpaqueFloat = 1.0F;
-  float alpha_ = kOpaqueFloat;
-  hwc_frect_t source_crop_;
-  DrmHwcTransform transform_ = DrmHwcTransform::kIdentity;
   uint32_t z_order_ = 0;
-  DrmHwcBlending blending_ = DrmHwcBlending::kNone;
-  DrmHwcColorSpace color_space_ = DrmHwcColorSpace::kUndefined;
-  DrmHwcSampleRange sample_range_ = DrmHwcSampleRange::kUndefined;
+  LayerData layer_data_;
+
+  /* Should be populated to layer_data_.acquire_fence only before presenting */
+  UniqueFd acquire_fence_;
+
+  /* The following buffer data can have 2 sources:
+   * 1 - Mapper@4 metadata API
+   * 2 - HWC@2 API
+   * We keep ability to have 2 sources in drm_hwc. It may be useful for CLIENT
+   * layer, at this moment HWC@2 API can't specify blending mode for this layer,
+   * but Mapper@4 can do that
+   */
+  BufferColorSpace color_space_{};
+  BufferSampleRange sample_range_{};
+  BufferBlendMode blend_mode_{};
+  buffer_handle_t buffer_handle_{};
+  bool buffer_handle_updated_{};
 
   bool prior_buffer_scanout_flag_{};
 
-  UniqueFd acquire_fence_;
+  HwcDisplay *const parent_;
+
+  /* Layer state */
+ public:
+  void PopulateLayerData(bool test);
+
+  bool IsLayerUsableAsDevice() const {
+    return !bi_get_failed_ && !fb_import_failed_ && buffer_handle_ != nullptr;
+  }
+
+ private:
+  void ImportFb();
+  bool bi_get_failed_{};
+  bool fb_import_failed_{};
 };
 
 }  // namespace android

+ 0 - 84
include/drmhwcomposer.h

@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_DRM_HWCOMPOSER_H_
-#define ANDROID_DRM_HWCOMPOSER_H_
-
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
-
-#include <cstdbool>
-#include <cstdint>
-#include <optional>
-#include <vector>
-
-#include "bufferinfo/BufferInfo.h"
-#include "drm/DrmFbImporter.h"
-#include "utils/UniqueFd.h"
-
-namespace android {
-
-class DrmFbIdHandle;
-
-enum class DrmHwcColorSpace : int32_t {
-  kUndefined,
-  kItuRec601,
-  kItuRec709,
-  kItuRec2020,
-};
-
-enum class DrmHwcSampleRange : int32_t {
-  kUndefined,
-  kFullRange,
-  kLimitedRange,
-};
-
-enum DrmHwcTransform : uint32_t {
-  kIdentity = 0,
-  kFlipH = 1 << 0,
-  kFlipV = 1 << 1,
-  kRotate90 = 1 << 2,
-  kRotate180 = 1 << 3,
-  kRotate270 = 1 << 4,
-};
-
-enum class DrmHwcBlending : int32_t {
-  kNone,
-  kPreMult,
-  kCoverage,
-};
-
-struct DrmHwcLayer {
-  buffer_handle_t sf_handle = nullptr;
-  std::optional<BufferInfo> buffer_info;
-  std::shared_ptr<DrmFbIdHandle> fb_id_handle;
-
-  DrmHwcTransform transform{};
-  DrmHwcBlending blending = DrmHwcBlending::kNone;
-  uint16_t alpha = UINT16_MAX;
-  hwc_frect_t source_crop;
-  hwc_rect_t display_frame;
-  DrmHwcColorSpace color_space;
-  DrmHwcSampleRange sample_range;
-
-  UniqueFd acquire_fence;
-
-  int ImportBuffer(DrmDevice *drm_device);
-};
-
-}  // namespace android
-
-#endif

+ 1 - 4
tests/Android.bp

@@ -28,10 +28,7 @@ cc_test {
     header_libs: ["libhardware_headers"],
     static_libs: ["libdrmhwc_utils"],
     shared_libs: ["hwcomposer.drm"],
-    include_dirs: [
-        "external/drm_hwcomposer",
-        "external/drm_hwcomposer/include",
-    ],
+    include_dirs: ["external/drm_hwcomposer"],
 }
 
 // Tool for listening and dumping uevents

+ 0 - 48
utils/hwcutils.cpp

@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#define LOG_TAG "hwc-drm-utils"
-
-#include <utils/log.h>
-
-#include <cerrno>
-
-#include "bufferinfo/BufferInfoGetter.h"
-#include "drm/DrmFbImporter.h"
-#include "drmhwcomposer.h"
-
-namespace android {
-
-int DrmHwcLayer::ImportBuffer(DrmDevice *drm_device) {
-  buffer_info = BufferInfoGetter::GetInstance()->GetBoInfo(sf_handle);
-
-  if (!buffer_info) {
-    ALOGE("Failed to convert buffer info");
-    return -EINVAL;
-  }
-
-  fb_id_handle = drm_device->GetDrmFbImporter().GetOrCreateFbId(
-      &(*buffer_info));
-  if (!fb_id_handle) {
-    ALOGE("Failed to import buffer");
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
-}  // namespace android