diff --git a/Android.bp b/Android.bp index dd6225d..0de7e1c 100644 --- a/Android.bp +++ b/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", diff --git a/backend/Backend.cpp b/backend/Backend.cpp index f6d9c18..ba0518a 100644 --- a/backend/Backend.cpp +++ b/backend/Backend.cpp @@ -83,9 +83,9 @@ std::tuple 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 &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); } } diff --git a/bufferinfo/BufferInfo.h b/bufferinfo/BufferInfo.h index ab714cf..b2297f9 100644 --- a/bufferinfo/BufferInfo.h +++ b/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; }; diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp index b42838d..fcd0532 100644 --- a/bufferinfo/BufferInfoGetter.cpp +++ b/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, diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h index 4d35faa..667b5c1 100644 --- a/bufferinfo/BufferInfoGetter.h +++ b/bufferinfo/BufferInfoGetter.h @@ -38,8 +38,6 @@ class BufferInfoGetter { virtual auto GetBoInfo(buffer_handle_t handle) -> std::optional = 0; - bool IsHandleUsable(buffer_handle_t handle); - static BufferInfoGetter *GetInstance(); static bool IsDrmFormatRgb(uint32_t drm_format); diff --git a/compositor/DrmKmsPlan.cpp b/compositor/DrmKmsPlan.cpp index 966bd4e..6289b84 100644 --- a/compositor/DrmKmsPlan.cpp +++ b/compositor/DrmKmsPlan.cpp @@ -24,7 +24,7 @@ namespace android { auto DrmKmsPlan::CreateDrmKmsPlan(DrmDisplayPipeline &pipe, - std::vector composition) + std::vector composition) -> std::unique_ptr { auto plan = std::make_unique(); diff --git a/compositor/DrmKmsPlan.h b/compositor/DrmKmsPlan.h index 35e66e9..91f636e 100644 --- a/compositor/DrmKmsPlan.h +++ b/compositor/DrmKmsPlan.h @@ -20,7 +20,7 @@ #include #include -#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> plane; int z_pos; }; @@ -36,7 +36,7 @@ struct DrmKmsPlan { std::vector plan; static auto CreateDrmKmsPlan(DrmDisplayPipeline &pipe, - std::vector composition) + std::vector composition) -> std::unique_ptr; }; diff --git a/compositor/LayerData.h b/compositor/LayerData.h new file mode 100644 index 0000000..d04514d --- /dev/null +++ b/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 +#include + +#include +#include +#include +#include +#include + +#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 bi; + std::shared_ptr fb; + PresentInfo pi; + UniqueFd acquire_fence; +}; + +} // namespace android diff --git a/drm/DrmAtomicStateManager.cpp b/drm/DrmAtomicStateManager.cpp index bca446c..5d2eebd 100644 --- a/drm/DrmAtomicStateManager.cpp +++ b/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 */ diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h index a50a214..b0b85ac 100644 --- a/drm/DrmAtomicStateManager.h +++ b/drm/DrmAtomicStateManager.h @@ -26,10 +26,10 @@ #include #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 { diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp index 12ac44f..329ef1c 100644 --- a/drm/DrmPlane.cpp +++ b/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; } diff --git a/drm/DrmPlane.h b/drm/DrmPlane.h index 65f458f..31f0a33 100644 --- a/drm/DrmPlane.h +++ b/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 { public: @@ -40,7 +40,7 @@ class DrmPlane : public PipelineBindable { -> std::unique_ptr; 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 { 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 { DrmProperty color_encoding_propery_; DrmProperty color_range_property_; - std::map blending_enum_map_; - std::map color_encoding_enum_map_; - std::map color_range_enum_map_; - std::map transform_enum_map_; + std::map blending_enum_map_; + std::map color_encoding_enum_map_; + std::map color_range_enum_map_; + std::map transform_enum_map_; }; } // namespace android diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 7279c02..02df28c 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/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(layer_idx_), HwcLayer()); + layers_.emplace(static_cast(layer_idx_), HwcLayer(this)); *layer = static_cast(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 composition_layers; + std::vector composition_layers; + + /* Import & populate */ + for (std::pair &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 &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(bi->width), diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index cd33ebe..d79efb0 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h @@ -22,10 +22,10 @@ #include #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 { diff --git a/hwc2_device/HwcLayer.cpp b/hwc2_device/HwcLayer.cpp index cc535d7..f57ad9b 100644 --- a/hwc2_device/HwcLayer.cpp +++ b/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(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(l_transform); + layer_data_.pi.transform = static_cast(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 \ No newline at end of file diff --git a/hwc2_device/HwcLayer.h b/hwc2_device/HwcLayer.h index ad94129..92e9476 100644 --- a/hwc2_device/HwcLayer.h +++ b/hwc2_device/HwcLayer.h @@ -19,14 +19,16 @@ #include -#include - -#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 diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h deleted file mode 100644 index 5ddb220..0000000 --- a/include/drmhwcomposer.h +++ /dev/null @@ -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 -#include - -#include -#include -#include -#include - -#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 buffer_info; - std::shared_ptr 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 diff --git a/tests/Android.bp b/tests/Android.bp index e56ff5c..c48c86a 100644 --- a/tests/Android.bp +++ b/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 diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp deleted file mode 100644 index 5aa9a3f..0000000 --- a/utils/hwcutils.cpp +++ /dev/null @@ -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 - -#include - -#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