diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-15 01:57:54 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-15 01:57:54 +0000 |
commit | c860942c49b88529556ab49e77c6e55a86effabc (patch) | |
tree | 2831c37bc978d98ce5e2beaaa59c8a47c4ea462a | |
parent | e6aedbde1d66fb03c078726fcb8eda55983bdb75 (diff) | |
parent | f38e2635ad1c83e03e8c305e44c7a3c7f1e31329 (diff) | |
download | drm_hwcomposer-android-mainline-12.0.0_r32.tar.gz |
Snap for 7550930 from f38e2635ad1c83e03e8c305e44c7a3c7f1e31329 to mainline-networkstack-releaseandroid-mainline-12.0.0_r32android-mainline-12.0.0_r14
Change-Id: I53f540014d68b36d8790794f3eebe09141765620
-rw-r--r-- | Android.bp | 107 | ||||
-rw-r--r-- | DrmHwcTwo.cpp (renamed from drmhwctwo.cpp) | 274 | ||||
-rw-r--r-- | DrmHwcTwo.h (renamed from include/drmhwctwo.h) | 172 | ||||
-rw-r--r-- | METADATA | 3 | ||||
-rw-r--r-- | OWNERS | 1 | ||||
-rw-r--r-- | backend/Backend.cpp | 137 | ||||
-rw-r--r-- | backend/Backend.h | 38 | ||||
-rw-r--r-- | backend/BackendClient.cpp | 35 | ||||
-rw-r--r-- | backend/BackendClient.h | 32 | ||||
-rw-r--r-- | backend/BackendManager.cpp | 79 | ||||
-rw-r--r-- | backend/BackendManager.h | 57 | ||||
-rw-r--r-- | backend/BackendRCarDu.cpp | 45 | ||||
-rw-r--r-- | backend/BackendRCarDu.h | 31 | ||||
-rw-r--r-- | bufferinfo/BufferInfoGetter.cpp | 118 | ||||
-rw-r--r-- | bufferinfo/BufferInfoGetter.h | 76 | ||||
-rw-r--r-- | bufferinfo/BufferInfoMapperMetadata.cpp | 146 | ||||
-rw-r--r-- | bufferinfo/BufferInfoMapperMetadata.h | 36 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoImagination.cpp (renamed from platform/platformimagination.cpp) | 45 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoImagination.h | 34 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoLibdrm.cpp | 195 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoLibdrm.h | 37 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMaliHisi.cpp | 128 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMaliHisi.h (renamed from platform/platformhisi.h) | 20 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMaliMediatek.cpp | 58 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMaliMediatek.h | 34 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMaliMeson.cpp (renamed from platform/platformmeson.cpp) | 41 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMaliMeson.h (renamed from platform/platformmeson.h) | 17 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMinigbm.cpp (renamed from platform/platformminigbm.cpp) | 34 | ||||
-rw-r--r-- | bufferinfo/legacy/BufferInfoMinigbm.h (renamed from platform/platformminigbm.h) | 14 | ||||
-rw-r--r-- | compositor/DrmDisplayComposition.cpp (renamed from compositor/drmdisplaycomposition.cpp) | 16 | ||||
-rw-r--r-- | compositor/DrmDisplayComposition.h (renamed from include/drmdisplaycomposition.h) | 10 | ||||
-rw-r--r-- | compositor/DrmDisplayCompositor.cpp (renamed from compositor/drmdisplaycompositor.cpp) | 113 | ||||
-rw-r--r-- | compositor/DrmDisplayCompositor.h (renamed from include/drmdisplaycompositor.h) | 52 | ||||
-rw-r--r-- | compositor/Planner.cpp (renamed from platform/platform.cpp) | 18 | ||||
-rw-r--r-- | compositor/Planner.h (renamed from include/platform.h) | 33 | ||||
-rw-r--r-- | drm/DrmConnector.cpp (renamed from drm/drmconnector.cpp) | 37 | ||||
-rw-r--r-- | drm/DrmConnector.h (renamed from include/drmconnector.h) | 13 | ||||
-rw-r--r-- | drm/DrmCrtc.cpp (renamed from drm/drmcrtc.cpp) | 6 | ||||
-rw-r--r-- | drm/DrmCrtc.h (renamed from include/drmcrtc.h) | 6 | ||||
-rw-r--r-- | drm/DrmDevice.cpp (renamed from drm/drmdevice.cpp) | 37 | ||||
-rw-r--r-- | drm/DrmDevice.h (renamed from include/drmdevice.h) | 17 | ||||
-rw-r--r-- | drm/DrmEncoder.cpp (renamed from drm/drmencoder.cpp) | 6 | ||||
-rw-r--r-- | drm/DrmEncoder.h (renamed from include/drmencoder.h) | 5 | ||||
-rw-r--r-- | drm/DrmEventListener.cpp (renamed from drm/drmeventlistener.cpp) | 14 | ||||
-rw-r--r-- | drm/DrmEventListener.h (renamed from include/drmeventlistener.h) | 2 | ||||
-rw-r--r-- | drm/DrmGenericImporter.cpp | 137 | ||||
-rw-r--r-- | drm/DrmGenericImporter.h (renamed from platform/platformdrmgeneric.h) | 43 | ||||
-rw-r--r-- | drm/DrmMode.cpp (renamed from drm/drmmode.cpp) | 7 | ||||
-rw-r--r-- | drm/DrmMode.h (renamed from include/drmmode.h) | 1 | ||||
-rw-r--r-- | drm/DrmPlane.cpp (renamed from drm/drmplane.cpp) | 18 | ||||
-rw-r--r-- | drm/DrmPlane.h (renamed from include/drmplane.h) | 11 | ||||
-rw-r--r-- | drm/DrmProperty.cpp (renamed from drm/drmproperty.cpp) | 7 | ||||
-rw-r--r-- | drm/DrmProperty.h (renamed from include/drmproperty.h) | 1 | ||||
-rw-r--r-- | drm/ResourceManager.cpp (renamed from drm/resourcemanager.cpp) | 49 | ||||
-rw-r--r-- | drm/ResourceManager.h (renamed from include/resourcemanager.h) | 12 | ||||
-rw-r--r-- | drm/VSyncWorker.cpp (renamed from drm/vsyncworker.cpp) | 51 | ||||
-rw-r--r-- | drm/VSyncWorker.h (renamed from include/vsyncworker.h) | 16 | ||||
-rw-r--r-- | include/DrmFramebuffer.h (renamed from include/drmframebuffer.h) | 2 | ||||
-rw-r--r-- | include/drmhwcgralloc.h | 1 | ||||
-rw-r--r-- | include/drmhwcomposer.h | 3 | ||||
-rw-r--r-- | platform/platformdrmgeneric.cpp | 252 | ||||
-rw-r--r-- | platform/platformhisi.cpp | 197 | ||||
-rw-r--r-- | platform/platformimagination.h | 22 | ||||
-rw-r--r-- | tests/Android.bp | 14 | ||||
-rw-r--r-- | tests/worker_test.cpp | 4 | ||||
-rw-r--r-- | utils/Worker.cpp (renamed from utils/worker.cpp) | 2 | ||||
-rw-r--r-- | utils/Worker.h (renamed from include/worker.h) | 2 | ||||
-rw-r--r-- | utils/autolock.h (renamed from include/autolock.h) | 0 | ||||
-rw-r--r-- | utils/hwcutils.cpp | 50 |
69 files changed, 2322 insertions, 1009 deletions
@@ -15,12 +15,32 @@ // ===================== // libdrmhwc_utils.a // ===================== +package { + default_applicable_licenses: ["external_drm_hwcomposer_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "external_drm_hwcomposer_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_static { name: "libdrmhwc_utils", - srcs: ["utils/worker.cpp"], + srcs: ["utils/Worker.cpp"], - include_dirs: ["external/drm_hwcomposer/include"], + include_dirs: [ + "external/drm_hwcomposer/include", + "external/drm_hwcomposer", + ], cflags: [ "-Wall", @@ -41,13 +61,17 @@ cc_defaults { "libcutils", "libdrm", "libhardware", + "libhidlbase", "liblog", "libsync", "libui", "libutils", ], - include_dirs: ["external/drm_hwcomposer/include"], + include_dirs: [ + "external/drm_hwcomposer/include", + "external/drm_hwcomposer", + ], static_libs: ["libdrmhwc_utils"], @@ -61,6 +85,12 @@ cc_defaults { "-DHWC2_INCLUDE_STRINGIFICATION", ], + product_variables: { + platform_sdk_version: { + cflags: ["-DPLATFORM_SDK_VERSION=%d"], + }, + }, + relative_install_path: "hw", vendor: true, } @@ -68,26 +98,34 @@ cc_library_static { name: "drm_hwcomposer", defaults: ["hwcomposer.drm_defaults"], srcs: [ - "drmhwctwo.cpp", - - "compositor/drmdisplaycomposition.cpp", - "compositor/drmdisplaycompositor.cpp", - - "drm/drmconnector.cpp", - "drm/drmcrtc.cpp", - "drm/drmdevice.cpp", - "drm/drmencoder.cpp", - "drm/drmeventlistener.cpp", - "drm/drmmode.cpp", - "drm/drmplane.cpp", - "drm/drmproperty.cpp", - "drm/resourcemanager.cpp", - "drm/vsyncworker.cpp", - - "platform/platform.cpp", + "DrmHwcTwo.cpp", + + "bufferinfo/BufferInfoGetter.cpp", + "bufferinfo/BufferInfoMapperMetadata.cpp", + + "compositor/DrmDisplayComposition.cpp", + "compositor/DrmDisplayCompositor.cpp", + "compositor/Planner.cpp", + + "drm/DrmConnector.cpp", + "drm/DrmCrtc.cpp", + "drm/DrmDevice.cpp", + "drm/DrmEncoder.cpp", + "drm/DrmEventListener.cpp", + "drm/DrmGenericImporter.cpp", + "drm/DrmMode.cpp", + "drm/DrmPlane.cpp", + "drm/DrmProperty.cpp", + "drm/ResourceManager.cpp", + "drm/VSyncWorker.cpp", "utils/autolock.cpp", "utils/hwcutils.cpp", + + "backend/BackendManager.cpp", + "backend/Backend.cpp", + "backend/BackendClient.cpp", + "backend/BackendRCarDu.cpp", ], } @@ -95,44 +133,37 @@ cc_library_shared { name: "hwcomposer.drm", defaults: ["hwcomposer.drm_defaults"], whole_static_libs: ["drm_hwcomposer"], - srcs: ["platform/platformdrmgeneric.cpp"], - cppflags: ["-DUSE_DRM_GENERIC_IMPORTER"], + srcs: ["bufferinfo/legacy/BufferInfoLibdrm.cpp"], } cc_library_shared { name: "hwcomposer.drm_minigbm", defaults: ["hwcomposer.drm_defaults"], whole_static_libs: ["drm_hwcomposer"], - srcs: [ - "platform/platformdrmgeneric.cpp", - "platform/platformminigbm.cpp", - ], + srcs: ["bufferinfo/legacy/BufferInfoMinigbm.cpp"], include_dirs: ["external/minigbm/cros_gralloc"], } // Used by hwcomposer.drm_imagination filegroup { name: "drm_hwcomposer_platformimagination", - srcs: [ - "platform/platformdrmgeneric.cpp", - "platform/platformimagination.cpp", - ], + srcs: ["bufferinfo/legacy/BufferInfoImagination.cpp"], } // Used by hwcomposer.drm_hikey and hwcomposer.drm_hikey960 filegroup { name: "drm_hwcomposer_platformhisi", - srcs: [ - "platform/platformdrmgeneric.cpp", - "platform/platformhisi.cpp", - ], + srcs: ["bufferinfo/legacy/BufferInfoMaliHisi.cpp"], } // Used by hwcomposer.drm_meson filegroup { name: "drm_hwcomposer_platformmeson", - srcs: [ - "platform/platformdrmgeneric.cpp", - "platform/platformmeson.cpp", - ], + srcs: ["bufferinfo/legacy/BufferInfoMaliMeson.cpp"], +} + +// Used by hwcomposer.drm_mediatek +filegroup { + name: "drm_hwcomposer_platformmediatek", + srcs: ["bufferinfo/legacy/BufferInfoMaliMediatek.cpp"], } diff --git a/drmhwctwo.cpp b/DrmHwcTwo.cpp index ab39144..93b6fa7 100644 --- a/drmhwctwo.cpp +++ b/DrmHwcTwo.cpp @@ -17,37 +17,21 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #define LOG_TAG "hwc-drm-two" -#include "drmhwctwo.h" -#include "drmdisplaycomposition.h" -#include "drmhwcomposer.h" -#include "platform.h" -#include "vsyncworker.h" - -#include <inttypes.h> -#include <string> +#include "DrmHwcTwo.h" #include <cutils/properties.h> #include <hardware/hardware.h> #include <hardware/hwcomposer2.h> +#include <inttypes.h> #include <log/log.h> -namespace android { - -class DrmVsyncCallback : public VsyncCallback { - public: - DrmVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook) - : data_(data), hook_(hook) { - } +#include <string> - void Callback(int display, int64_t timestamp) { - auto hook = reinterpret_cast<HWC2_PFN_VSYNC>(hook_); - hook(data_, display, timestamp); - } +#include "backend/BackendManager.h" +#include "bufferinfo/BufferInfoGetter.h" +#include "compositor/DrmDisplayComposition.h" - private: - hwc2_callback_data_t data_; - hwc2_function_pointer_t hook_; -}; +namespace android { DrmHwcTwo::DrmHwcTwo() { common.tag = HARDWARE_DEVICE_TAG; @@ -142,6 +126,7 @@ std::string DrmHwcTwo::HwcDisplay::DumpDelta( << ((delta.failed_kms_present_ > 0) ? " !!! Internal failure, FIX it please\n" : "") + << " Flattened frames: " << delta.frames_flattened_ << "\n" << " Pixel operations (free units)" << " : [TOTAL: " << delta.total_pixops_ << " / GPU: " << delta.gpu_pixops_ << "]\n" @@ -152,6 +137,8 @@ std::string DrmHwcTwo::HwcDisplay::DumpDelta( std::string DrmHwcTwo::HwcDisplay::Dump() { auto out = (std::stringstream() << "- Display on: " << connector_->name() << "\n" + << " Flattening state: " << compositor_.GetFlatteningState() + << "\n" << "Statistics since system boot:\n" << DumpDelta(total_stats_) << "\n\n" << "Statistics since last dumpsys request:\n" @@ -192,22 +179,21 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, hwc2_callback_data_t data, hwc2_function_pointer_t function) { supported(__func__); - auto callback = static_cast<HWC2::Callback>(descriptor); - if (!function) { - callbacks_.erase(callback); - return HWC2::Error::None; - } - - callbacks_.emplace(callback, HwcCallback(data, function)); - - switch (callback) { + switch (static_cast<HWC2::Callback>(descriptor)) { case HWC2::Callback::Hotplug: { + SetHotplugCallback(data, function); auto &drmDevices = resource_manager_.getDrmDevices(); for (auto &device : drmDevices) HandleInitialHotplugState(device.get()); break; } + case HWC2::Callback::Refresh: { + for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d : + displays_) + d.second.RegisterRefreshCallback(data, function); + break; + } case HWC2::Callback::Vsync: { for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d : displays_) @@ -262,7 +248,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) { // Split up the given display planes into primary and overlay to properly // interface with the composition char use_overlay_planes_prop[PROPERTY_VALUE_MAX]; - property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1"); + property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop, + "1"); bool use_overlay_planes = atoi(use_overlay_planes_prop); for (auto &plane : *planes) { if (plane->type() == DRM_PLANE_TYPE_PRIMARY) @@ -289,6 +276,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) { return HWC2::Error::BadDisplay; } + ret = BackendManager::GetInstance().SetBackendForDisplay(this); + if (ret) { + ALOGE("Failed to set backend for d=%d %d\n", display, ret); + return HWC2::Error::BadDisplay; + } + return ChosePreferredConfig(); } @@ -302,12 +295,16 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ChosePreferredConfig() { return SetActiveConfig(connector_->get_preferred_mode_id()); } -HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( +void DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( hwc2_callback_data_t data, hwc2_function_pointer_t func) { supported(__func__); - auto callback = std::make_shared<DrmVsyncCallback>(data, func); - vsync_worker_.RegisterCallback(std::move(callback)); - return HWC2::Error::None; + vsync_worker_.RegisterClientCallback(data, func); +} + +void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback( + hwc2_callback_data_t data, hwc2_function_pointer_t func) { + supported(__func__); + compositor_.SetRefreshCallback(data, func); } HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() { @@ -761,11 +758,6 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { .right = static_cast<int>(mode->h_display()), .bottom = static_cast<int>(mode->v_display())}; client_layer_.SetLayerDisplayFrame(display_frame); - hwc_frect_t source_crop = {.left = 0.0f, - .top = 0.0f, - .right = mode->h_display() + 0.0f, - .bottom = mode->v_display() + 0.0f}; - client_layer_.SetLayerSourceCrop(source_crop); return HWC2::Error::None; } @@ -780,15 +772,30 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target, client_layer_.set_buffer(target); client_layer_.set_acquire_fence(uf.get()); client_layer_.SetLayerDataspace(dataspace); + + /* TODO: Do not update source_crop every call. + * It makes sense to do it once after every hotplug event. */ + hwc_drm_bo bo{}; + BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo); + + hwc_frect_t source_crop = {.left = 0.0f, + .top = 0.0f, + .right = bo.width + 0.0f, + .bottom = bo.height + 0.0f}; + client_layer_.SetLayerSourceCrop(source_crop); + return HWC2::Error::None; } HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) { supported(__func__); - if (mode != HAL_COLOR_MODE_NATIVE) + if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG) return HWC2::Error::BadParameter; + if (mode != HAL_COLOR_MODE_NATIVE) + return HWC2::Error::Unsupported; + color_mode_ = mode; return HWC2::Error::None; } @@ -881,78 +888,98 @@ void DrmHwcTwo::HwcDisplay::MarkValidated( HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types, uint32_t *num_requests) { supported(__func__); - *num_types = 0; - *num_requests = 0; - size_t avail_planes = primary_planes_.size() + overlay_planes_.size(); - /* - * If more layers then planes, save one plane - * for client composited layers - */ - if (avail_planes < layers_.size()) - avail_planes--; + return backend_->ValidateDisplay(this, num_types, num_requests); +} - std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map; - for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) - z_map.emplace(std::make_pair(l.second.z_order(), &l.second)); +#if PLATFORM_SDK_VERSION > 28 +HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData( + uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) { + supported(__func__); - uint32_t total_pixops = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0; + drmModePropertyBlobPtr blob; - int client_start = -1, client_size = 0; + if (connector_->GetEdidBlob(blob)) { + ALOGE("Failed to get edid property value."); + return HWC2::Error::Unsupported; + } - for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) { - if (!HardwareSupportsLayerType(l.second->sf_type()) || - !importer_->CanImportBuffer(l.second->buffer()) || - color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY) { - if (client_start < 0) - client_start = l.first; - client_size = (l.first - client_start) + 1; - } + if (outData) { + *outDataSize = std::min(*outDataSize, blob->length); + memcpy(outData, blob->data, *outDataSize); + } else { + *outDataSize = blob->length; } + *outPort = connector_->id(); - int extra_client = (z_map.size() - client_size) - avail_planes; - if (extra_client > 0) { - int start = 0, steps; - if (client_size != 0) { - int prepend = std::min(client_start, extra_client); - int append = std::min(int(z_map.size() - (client_start + client_size)), - extra_client); - start = client_start - prepend; - client_size += extra_client; - steps = 1 + std::min(std::min(append, prepend), - int(z_map.size()) - (start + client_size)); - } else { - client_size = extra_client; - steps = 1 + z_map.size() - extra_client; - } + return HWC2::Error::None; +} - gpu_pixops = INT_MAX; - for (int i = 0; i < steps; i++) { - uint32_t po = CalcPixOps(z_map, start + i, client_size); - if (po < gpu_pixops) { - gpu_pixops = po; - client_start = start + i; - } - } +HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayCapabilities( + uint32_t *outNumCapabilities, uint32_t *outCapabilities) { + unsupported(__func__, outCapabilities); + + if (outNumCapabilities == NULL) { + return HWC2::Error::BadParameter; } - MarkValidated(z_map, client_start, client_size); + *outNumCapabilities = 0; + + return HWC2::Error::None; +} + +HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayBrightnessSupport( + bool *supported) { + *supported = false; + return HWC2::Error::None; +} + +HWC2::Error DrmHwcTwo::HwcDisplay::SetDisplayBrightness( + float /* brightness */) { + return HWC2::Error::Unsupported; +} + +#endif /* PLATFORM_SDK_VERSION > 28 */ - if (CreateComposition(true) != HWC2::Error::None) { - ++total_stats_.failed_kms_validate_; - gpu_pixops = total_pixops; - client_size = z_map.size(); - MarkValidated(z_map, 0, client_size); +#if PLATFORM_SDK_VERSION > 27 + +HWC2::Error DrmHwcTwo::HwcDisplay::GetRenderIntents( + int32_t mode, uint32_t *outNumIntents, + int32_t * /*android_render_intent_v1_1_t*/ outIntents) { + if (mode != HAL_COLOR_MODE_NATIVE) { + return HWC2::Error::BadParameter; + } + + if (outIntents == nullptr) { + *outNumIntents = 1; + return HWC2::Error::None; } + *outNumIntents = 1; + outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC; + return HWC2::Error::None; +} + +HWC2::Error DrmHwcTwo::HwcDisplay::SetColorModeWithIntent(int32_t mode, + int32_t intent) { + if (intent < HAL_RENDER_INTENT_COLORIMETRIC || + intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE) + return HWC2::Error::BadParameter; + + if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG) + return HWC2::Error::BadParameter; - *num_types = client_size; + if (mode != HAL_COLOR_MODE_NATIVE) + return HWC2::Error::Unsupported; - total_stats_.gpu_pixops_ += gpu_pixops; - total_stats_.total_pixops_ += total_pixops; + if (intent != HAL_RENDER_INTENT_COLORIMETRIC) + return HWC2::Error::Unsupported; - return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; + color_mode_ = mode; + return HWC2::Error::None; } +#endif /* PLATFORM_SDK_VERSION > 27 */ + HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) { supported(__func__); cursor_x_ = x; @@ -971,12 +998,6 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer, supported(__func__); UniqueFd uf(acquire_fence); - // The buffer and acquire_fence are handled elsewhere - if (sf_type_ == HWC2::Composition::Client || - sf_type_ == HWC2::Composition::Sideband || - sf_type_ == HWC2::Composition::SolidColor) - return HWC2::Error::None; - set_buffer(buffer); set_acquire_fence(uf.get()); return HWC2::Error::None; @@ -1081,14 +1102,13 @@ void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { } void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { - auto cb = callbacks_.find(HWC2::Callback::Hotplug); - if (cb == callbacks_.end()) - return; + const std::lock_guard<std::mutex> lock(hotplug_callback_lock); - auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(cb->second.func); - hotplug(cb->second.data, displayid, - (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED - : HWC2_CONNECTION_DISCONNECTED)); + if (hotplug_callback_hook_ && hotplug_callback_data_) + hotplug_callback_hook_(hotplug_callback_data_, displayid, + state == DRM_MODE_CONNECTED + ? HWC2_CONNECTION_CONNECTED + : HWC2_CONNECTION_DISCONNECTED); } void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { @@ -1275,7 +1295,37 @@ hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction( return ToHook<HWC2_PFN_VALIDATE_DISPLAY>( DisplayHook<decltype(&HwcDisplay::ValidateDisplay), &HwcDisplay::ValidateDisplay, uint32_t *, uint32_t *>); - +#if PLATFORM_SDK_VERSION > 27 + case HWC2::FunctionDescriptor::GetRenderIntents: + return ToHook<HWC2_PFN_GET_RENDER_INTENTS>( + DisplayHook<decltype(&HwcDisplay::GetRenderIntents), + &HwcDisplay::GetRenderIntents, int32_t, uint32_t *, + int32_t *>); + case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent: + return ToHook<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>( + DisplayHook<decltype(&HwcDisplay::SetColorModeWithIntent), + &HwcDisplay::SetColorModeWithIntent, int32_t, int32_t>); +#endif +#if PLATFORM_SDK_VERSION > 28 + case HWC2::FunctionDescriptor::GetDisplayIdentificationData: + return ToHook<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>( + DisplayHook<decltype(&HwcDisplay::GetDisplayIdentificationData), + &HwcDisplay::GetDisplayIdentificationData, uint8_t *, + uint32_t *, uint8_t *>); + case HWC2::FunctionDescriptor::GetDisplayCapabilities: + return ToHook<HWC2_PFN_GET_DISPLAY_CAPABILITIES>( + DisplayHook<decltype(&HwcDisplay::GetDisplayCapabilities), + &HwcDisplay::GetDisplayCapabilities, uint32_t *, + uint32_t *>); + case HWC2::FunctionDescriptor::GetDisplayBrightnessSupport: + return ToHook<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>( + DisplayHook<decltype(&HwcDisplay::GetDisplayBrightnessSupport), + &HwcDisplay::GetDisplayBrightnessSupport, bool *>); + case HWC2::FunctionDescriptor::SetDisplayBrightness: + return ToHook<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>( + DisplayHook<decltype(&HwcDisplay::SetDisplayBrightness), + &HwcDisplay::SetDisplayBrightness, float>); +#endif /* PLATFORM_SDK_VERSION > 28 */ // Layer functions case HWC2::FunctionDescriptor::SetCursorPosition: return ToHook<HWC2_PFN_SET_CURSOR_POSITION>( diff --git a/include/drmhwctwo.h b/DrmHwcTwo.h index babe000..d489113 100644 --- a/include/drmhwctwo.h +++ b/DrmHwcTwo.h @@ -14,19 +14,26 @@ * limitations under the License. */ -#include "drmdisplaycompositor.h" -#include "drmhwcomposer.h" -#include "platform.h" -#include "resourcemanager.h" -#include "vsyncworker.h" +#ifndef ANDROID_DRM_HWC_TWO_H_ +#define ANDROID_DRM_HWC_TWO_H_ #include <hardware/hwcomposer2.h> +#include <math.h> #include <array> #include <map> +#include "compositor/DrmDisplayCompositor.h" +#include "compositor/Planner.h" +#include "drm/DrmGenericImporter.h" +#include "drm/ResourceManager.h" +#include "drm/VSyncWorker.h" +#include "drmhwcomposer.h" + namespace android { +class Backend; + class DrmHwcTwo : public hwc2_device_t { public: static int HookDevOpen(const struct hw_module_t *module, const char *name, @@ -36,7 +43,17 @@ class DrmHwcTwo : public hwc2_device_t { HWC2::Error Init(); - private: + hwc2_callback_data_t hotplug_callback_data_ = NULL; + HWC2_PFN_HOTPLUG hotplug_callback_hook_ = NULL; + std::mutex hotplug_callback_lock; + + void SetHotplugCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t hook) { + const std::lock_guard<std::mutex> lock(hotplug_callback_lock); + hotplug_callback_data_ = data; + hotplug_callback_hook_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(hook); + } + class HwcLayer { public: HWC2::Composition sf_type() const { @@ -93,6 +110,19 @@ class DrmHwcTwo : public hwc2_device_t { void PopulateDrmLayer(DrmHwcLayer *layer); + bool RequireScalingOrPhasing() { + float src_width = source_crop_.right - source_crop_.left; + float src_height = source_crop_.bottom - source_crop_.top; + + float dest_width = display_frame_.right - display_frame_.left; + float dest_height = display_frame_.bottom - display_frame_.top; + + bool scaling = src_width != dest_width || src_height != dest_height; + bool phasing = (source_crop_.left - floor(source_crop_.left) != 0) || + (source_crop_.top - floor(source_crop_.top) != 0); + return scaling || phasing; + } + // Layer hooks HWC2::Error SetCursorPosition(int32_t x, int32_t y); HWC2::Error SetLayerBlendMode(int32_t mode); @@ -131,14 +161,6 @@ class DrmHwcTwo : public hwc2_device_t { android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN; }; - struct HwcCallback { - HwcCallback(hwc2_callback_data_t d, hwc2_function_pointer_t f) - : data(d), func(f) { - } - hwc2_callback_data_t data; - hwc2_function_pointer_t func; - }; - class HwcDisplay { public: HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, @@ -147,8 +169,17 @@ class DrmHwcTwo : public hwc2_device_t { HwcDisplay(const HwcDisplay &) = delete; HWC2::Error Init(std::vector<DrmPlane *> *planes); - HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data, - hwc2_function_pointer_t func); + void RegisterVsyncCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t func); + void RegisterRefreshCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t func); + HWC2::Error CreateComposition(bool test); + bool HardwareSupportsLayerType(HWC2::Composition comp_type); + uint32_t CalcPixOps(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, + size_t first_z, size_t size); + void MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, + size_t client_first_z, size_t client_size); + void ClearDisplay(); std::string Dump(); @@ -173,6 +204,20 @@ class DrmHwcTwo : public hwc2_device_t { uint32_t *num_elements, hwc2_layer_t *layers, int32_t *layer_requests); HWC2::Error GetDisplayType(int32_t *type); +#if PLATFORM_SDK_VERSION > 27 + HWC2::Error GetRenderIntents(int32_t mode, uint32_t *outNumIntents, + int32_t *outIntents); + HWC2::Error SetColorModeWithIntent(int32_t mode, int32_t intent); +#endif +#if PLATFORM_SDK_VERSION > 28 + HWC2::Error GetDisplayIdentificationData(uint8_t *outPort, + uint32_t *outDataSize, + uint8_t *outData); + HWC2::Error GetDisplayCapabilities(uint32_t *outNumCapabilities, + uint32_t *outCapabilities); + HWC2::Error GetDisplayBrightnessSupport(bool *supported); + HWC2::Error SetDisplayBrightness(float); +#endif HWC2::Error GetDozeSupport(int32_t *support); HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types, float *max_luminance, @@ -198,14 +243,74 @@ class DrmHwcTwo : public hwc2_device_t { return &it->second; } + /* Statistics */ + struct Stats { + Stats minus(Stats b) { + return {total_frames_ - b.total_frames_, + total_pixops_ - b.total_pixops_, + gpu_pixops_ - b.gpu_pixops_, + failed_kms_validate_ - b.failed_kms_validate_, + failed_kms_present_ - b.failed_kms_present_, + frames_flattened_ - b.frames_flattened_}; + } + + uint32_t total_frames_ = 0; + uint64_t total_pixops_ = 0; + uint64_t gpu_pixops_ = 0; + uint32_t failed_kms_validate_ = 0; + uint32_t failed_kms_present_ = 0; + uint32_t frames_flattened_ = 0; + }; + + const Backend *backend() const { + return backend_.get(); + } + void set_backend(std::unique_ptr<Backend> backend) { + backend_ = std::move(backend); + } + + const std::vector<DrmPlane *> &primary_planes() const { + return primary_planes_; + } + + const std::vector<DrmPlane *> &overlay_planes() const { + return overlay_planes_; + } + + std::map<hwc2_layer_t, HwcLayer> &layers() { + return layers_; + } + + const DrmDisplayCompositor &compositor() const { + return compositor_; + } + + const DrmDevice *drm() const { + return drm_; + } + + const DrmConnector *connector() const { + return connector_; + } + + const std::shared_ptr<Importer> &importer() const { + return importer_; + } + + ResourceManager *resource_manager() const { + return resource_manager_; + } + + android_color_transform_t &color_transform_hint() { + return color_transform_hint_; + } + + Stats &total_stats() { + return total_stats_; + } + private: - HWC2::Error CreateComposition(bool test); void AddFenceToPresentFence(int fd); - bool HardwareSupportsLayerType(HWC2::Composition comp_type); - uint32_t CalcPixOps(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, - size_t first_z, size_t size); - void MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, - size_t client_first_z, size_t client_size); constexpr static size_t MATRIX_SIZE = 16; @@ -218,6 +323,8 @@ class DrmHwcTwo : public hwc2_device_t { std::vector<DrmPlane *> primary_planes_; std::vector<DrmPlane *> overlay_planes_; + std::unique_ptr<Backend> backend_; + VSyncWorker vsync_worker_; DrmConnector *connector_ = NULL; DrmCrtc *crtc_ = NULL; @@ -232,21 +339,8 @@ class DrmHwcTwo : public hwc2_device_t { android_color_transform_t color_transform_hint_; uint32_t frame_no_ = 0; - /* Statistics */ - struct Stats { - Stats minus(Stats b) { - return {total_frames_ - b.total_frames_, - total_pixops_ - b.total_pixops_, gpu_pixops_ - b.gpu_pixops_, - failed_kms_validate_ - b.failed_kms_validate_, - failed_kms_present_ - b.failed_kms_present_}; - } - - uint32_t total_frames_ = 0; - uint64_t total_pixops_ = 0; - uint64_t gpu_pixops_ = 0; - uint32_t failed_kms_validate_ = 0; - uint32_t failed_kms_present_ = 0; - } total_stats_, prev_stats_; + Stats total_stats_; + Stats prev_stats_; std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta); }; @@ -262,6 +356,7 @@ class DrmHwcTwo : public hwc2_device_t { DrmDevice *drm_; }; + private: static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) { return static_cast<DrmHwcTwo *>(dev); } @@ -331,8 +426,9 @@ class DrmHwcTwo : public hwc2_device_t { ResourceManager resource_manager_; std::map<hwc2_display_t, HwcDisplay> displays_; - std::map<HWC2::Callback, HwcCallback> callbacks_; std::string mDumpString; }; } // namespace android + +#endif diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..d97975c --- /dev/null +++ b/METADATA @@ -0,0 +1,3 @@ +third_party { + license_type: NOTICE +} @@ -1,6 +1,5 @@ adelva@google.com john.stultz@linaro.org marcheu@google.com -marissaw@google.com seanpaul@google.com zachr@google.com diff --git a/backend/Backend.cpp b/backend/Backend.cpp new file mode 100644 index 0000000..887eb0e --- /dev/null +++ b/backend/Backend.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "Backend.h" + +#include "BackendManager.h" +#include "bufferinfo/BufferInfoGetter.h" + +namespace android { + +HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, + uint32_t *num_types, + uint32_t *num_requests) { + *num_types = 0; + *num_requests = 0; + size_t avail_planes = display->primary_planes().size() + + display->overlay_planes().size(); + + /* + * If more layers then planes, save one plane + * for client composited layers + */ + if (avail_planes < display->layers().size()) + avail_planes--; + + std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map, z_map_tmp; + uint32_t z_index = 0; + // First create a map of layers and z_order values + for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : + display->layers()) + z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second)); + // normalise the map so that the lowest z_order layer has key 0 + for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map_tmp) + z_map.emplace(std::make_pair(z_index++, l.second)); + + uint32_t total_pixops = display->CalcPixOps(z_map, 0, z_map.size()); + uint32_t gpu_pixops = 0; + + int client_start = -1, client_size = 0; + + if (display->compositor().ShouldFlattenOnClient()) { + client_start = 0; + client_size = z_map.size(); + display->MarkValidated(z_map, client_start, client_size); + } else { + std::tie(client_start, client_size) = GetClientLayers(display, z_map); + + int extra_client = (z_map.size() - client_size) - avail_planes; + if (extra_client > 0) { + int start = 0, steps; + if (client_size != 0) { + int prepend = std::min(client_start, extra_client); + int append = std::min(int(z_map.size() - (client_start + client_size)), + extra_client); + start = client_start - prepend; + client_size += extra_client; + steps = 1 + std::min(std::min(append, prepend), + int(z_map.size()) - (start + client_size)); + } else { + client_size = extra_client; + steps = 1 + z_map.size() - extra_client; + } + + gpu_pixops = INT_MAX; + for (int i = 0; i < steps; i++) { + uint32_t po = display->CalcPixOps(z_map, start + i, client_size); + if (po < gpu_pixops) { + gpu_pixops = po; + client_start = start + i; + } + } + } + + display->MarkValidated(z_map, client_start, client_size); + + bool testing_needed = !(client_start == 0 && client_size == z_map.size()); + + if (testing_needed && + display->CreateComposition(true) != HWC2::Error::None) { + ++display->total_stats().failed_kms_validate_; + gpu_pixops = total_pixops; + client_size = z_map.size(); + display->MarkValidated(z_map, 0, client_size); + } + } + + *num_types = client_size; + + display->total_stats().frames_flattened_ = display->compositor() + .GetFlattenedFramesCount(); + display->total_stats().gpu_pixops_ += gpu_pixops; + display->total_stats().total_pixops_ += total_pixops; + + return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; +} + +std::tuple<int, int> Backend::GetClientLayers( + DrmHwcTwo::HwcDisplay *display, + const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map) { + int client_start = -1, client_size = 0; + + for (auto & [ z_order, layer ] : z_map) { + if (IsClientLayer(display, layer)) { + if (client_start < 0) + client_start = z_order; + client_size = (z_order - client_start) + 1; + } + } + + return std::make_tuple(client_start, client_size); +} + +bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display, + DrmHwcTwo::HwcLayer *layer) { + return !display->HardwareSupportsLayerType(layer->sf_type()) || + !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) || + display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY || + (layer->RequireScalingOrPhasing() && + display->resource_manager()->ForcedScalingWithGpu()); +} + +REGISTER_BACKEND("generic", Backend); + +} // namespace android diff --git a/backend/Backend.h b/backend/Backend.h new file mode 100644 index 0000000..898fece --- /dev/null +++ b/backend/Backend.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 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_BACKEND_H +#define ANDROID_BACKEND_H + +#include "DrmHwcTwo.h" + +namespace android { + +class Backend { + public: + virtual ~Backend() = default; + virtual HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, + uint32_t *num_types, + uint32_t *num_requests); + virtual std::tuple<int, int> GetClientLayers( + DrmHwcTwo::HwcDisplay *display, + const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map); + virtual bool IsClientLayer(DrmHwcTwo::HwcDisplay *display, + DrmHwcTwo::HwcLayer *layer); +}; +} // namespace android + +#endif diff --git a/backend/BackendClient.cpp b/backend/BackendClient.cpp new file mode 100644 index 0000000..033a35c --- /dev/null +++ b/backend/BackendClient.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "BackendClient.h" + +#include "BackendManager.h" + +namespace android { + +HWC2::Error BackendClient::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, + uint32_t *num_types, + uint32_t * /*num_requests*/) { + for (auto & [ layer_handle, layer ] : display->layers()) { + layer.set_validated_type(HWC2::Composition::Client); + ++*num_types; + } + return HWC2::Error::HasChanges; +} + +REGISTER_BACKEND("client", BackendClient); + +} // namespace android diff --git a/backend/BackendClient.h b/backend/BackendClient.h new file mode 100644 index 0000000..13543f1 --- /dev/null +++ b/backend/BackendClient.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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_BACKEND_CLIENT_H +#define ANDROID_BACKEND_CLIENT_H + +#include "Backend.h" + +namespace android { + +class BackendClient : public Backend { + public: + HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, + uint32_t *num_types, + uint32_t *num_requests) override; +}; +} // namespace android + +#endif diff --git a/backend/BackendManager.cpp b/backend/BackendManager.cpp new file mode 100644 index 0000000..0bacdcd --- /dev/null +++ b/backend/BackendManager.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-backend" + +#include "BackendManager.h" + +#include <cutils/properties.h> +#include <log/log.h> + +namespace android { + +const std::vector<std::string> BackendManager::client_devices_ = { + "kirin", + "mediatek-drm", +}; + +BackendManager &BackendManager::GetInstance() { + static BackendManager backend_manager; + + return backend_manager; +} + +int BackendManager::RegisterBackend(const std::string &name, + backend_constructor_t backend_constructor) { + available_backends_[name] = std::move(backend_constructor); + return 0; +} + +int BackendManager::SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display) { + std::string driver_name(display->drm()->GetName()); + char backend_override[PROPERTY_VALUE_MAX]; + property_get("vendor.hwc.backend_override", backend_override, + driver_name.c_str()); + std::string backend_name(std::move(backend_override)); + + display->set_backend(GetBackendByName(backend_name)); + if (!display->backend()) { + ALOGE("Failed to set backend '%s' for '%s' and driver '%s'", + backend_name.c_str(), display->connector()->name().c_str(), + driver_name.c_str()); + return -EINVAL; + } + + ALOGI("Backend '%s' for '%s' and driver '%s' was successfully set", + backend_name.c_str(), display->connector()->name().c_str(), + driver_name.c_str()); + + return 0; +} + +std::unique_ptr<Backend> BackendManager::GetBackendByName(std::string &name) { + if (!available_backends_.size()) { + ALOGE("No backends are specified"); + return nullptr; + } + + auto it = available_backends_.find(name); + if (it == available_backends_.end()) { + auto it = std::find(client_devices_.begin(), client_devices_.end(), name); + name = it == client_devices_.end() ? "generic" : "client"; + } + + return available_backends_[name](); +} +} // namespace android diff --git a/backend/BackendManager.h b/backend/BackendManager.h new file mode 100644 index 0000000..e86c098 --- /dev/null +++ b/backend/BackendManager.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 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_BACKEND_MANAGER_H +#define ANDROID_BACKEND_MANAGER_H + +#include <functional> +#include <map> +#include <string> +#include <vector> + +#include "Backend.h" + +#define REGISTER_BACKEND(name_str_, backend_) \ + static int \ + backend = BackendManager::GetInstance() \ + .RegisterBackend(name_str_, \ + []() -> std::unique_ptr<Backend> { \ + return std::make_unique<backend_>(); \ + }); + +namespace android { + +class BackendManager { + public: + using backend_constructor_t = std::function<std::unique_ptr<Backend>()>; + static BackendManager &GetInstance(); + int RegisterBackend(const std::string &name, + backend_constructor_t backend_constructor); + int SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display); + std::unique_ptr<Backend> GetBackendByName(std::string &name); + HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, + uint32_t *num_types, uint32_t *num_requests); + + private: + BackendManager() = default; + + static const std::vector<std::string> client_devices_; + + std::map<std::string, backend_constructor_t> available_backends_; +}; +} // namespace android + +#endif diff --git a/backend/BackendRCarDu.cpp b/backend/BackendRCarDu.cpp new file mode 100644 index 0000000..e85fa71 --- /dev/null +++ b/backend/BackendRCarDu.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "BackendRCarDu.h" + +#include "BackendManager.h" +#include "bufferinfo/BufferInfoGetter.h" +#include "drm_fourcc.h" + +namespace android { + +bool BackendRCarDu::IsClientLayer(DrmHwcTwo::HwcDisplay *display, + DrmHwcTwo::HwcLayer *layer) { + hwc_drm_bo_t bo; + + int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(layer->buffer(), + &bo); + if (ret) + return true; + + if (bo.format == DRM_FORMAT_ABGR8888) + return true; + + if (layer->RequireScalingOrPhasing()) + return true; + + return Backend::IsClientLayer(display, layer); +} + +REGISTER_BACKEND("rcar-du", BackendRCarDu); + +} // namespace android
\ No newline at end of file diff --git a/backend/BackendRCarDu.h b/backend/BackendRCarDu.h new file mode 100644 index 0000000..8a1011a --- /dev/null +++ b/backend/BackendRCarDu.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 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 HWC_DISPLAY_BACKEND_RCAR_DU_H +#define HWC_DISPLAY_BACKEND_RCAR_DU_H + +#include "Backend.h" + +namespace android { + +class BackendRCarDu : public Backend { + public: + bool IsClientLayer(DrmHwcTwo::HwcDisplay *display, + DrmHwcTwo::HwcLayer *layer) override; +}; +} // namespace android + +#endif diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp new file mode 100644 index 0000000..afdc50e --- /dev/null +++ b/bufferinfo/BufferInfoGetter.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-buffer-info-getter" + +#include "BufferInfoGetter.h" + +#if PLATFORM_SDK_VERSION >= 30 +#include "BufferInfoMapperMetadata.h" +#endif + +#include <cutils/properties.h> +#include <gralloc_handle.h> +#include <hardware/gralloc.h> +#include <log/log.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +namespace android { + +BufferInfoGetter *BufferInfoGetter::GetInstance() { + static std::unique_ptr<BufferInfoGetter> inst; + if (inst == nullptr) { +#if PLATFORM_SDK_VERSION >= 30 + inst.reset(BufferInfoMapperMetadata::CreateInstance()); + if (inst == nullptr) { + ALOGW( + "Generic buffer getter is not available. Falling back to legacy..."); +#endif + inst.reset(LegacyBufferInfoGetter::CreateInstance()); +#if PLATFORM_SDK_VERSION >= 30 + } +#endif + } + + return inst.get(); +} + +bool BufferInfoGetter::IsHandleUsable(buffer_handle_t handle) { + hwc_drm_bo_t bo; + memset(&bo, 0, sizeof(hwc_drm_bo_t)); + + if (ConvertBoInfo(handle, &bo) != 0) + return false; + + if (bo.prime_fds[0] == 0) + return false; + + return true; +} + +int LegacyBufferInfoGetter::Init() { + int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, + (const hw_module_t **)&gralloc_); + if (ret) { + ALOGE("Failed to open gralloc module"); + return ret; + } + + ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name, + gralloc_->common.author); + + return 0; +} + +uint32_t LegacyBufferInfoGetter::ConvertHalFormatToDrm(uint32_t hal_format) { + switch (hal_format) { + case HAL_PIXEL_FORMAT_RGB_888: + return DRM_FORMAT_BGR888; + case HAL_PIXEL_FORMAT_BGRA_8888: + return DRM_FORMAT_ARGB8888; + case HAL_PIXEL_FORMAT_RGBX_8888: + return DRM_FORMAT_XBGR8888; + case HAL_PIXEL_FORMAT_RGBA_8888: + return DRM_FORMAT_ABGR8888; + case HAL_PIXEL_FORMAT_RGB_565: + return DRM_FORMAT_BGR565; + case HAL_PIXEL_FORMAT_YV12: + return DRM_FORMAT_YVU420; + default: + ALOGE("Cannot convert hal format to drm format %u", hal_format); + return DRM_FORMAT_INVALID; + } +} + +bool BufferInfoGetter::IsDrmFormatRgb(uint32_t drm_format) { + switch (drm_format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_BGR888: + case DRM_FORMAT_BGR565: + return true; + default: + return false; + } +} + +__attribute__((weak)) LegacyBufferInfoGetter * +LegacyBufferInfoGetter::CreateInstance() { + ALOGE("No legacy buffer info getters available"); + return nullptr; +} + +} // namespace android diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h new file mode 100644 index 0000000..fad3d16 --- /dev/null +++ b/bufferinfo/BufferInfoGetter.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 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_BUFFERINFOGETTER_H_ +#define ANDROID_BUFFERINFOGETTER_H_ + +#include <drm/drm_fourcc.h> +#include <hardware/gralloc.h> + +#include "drm/DrmDevice.h" +#include "drmhwcgralloc.h" + +#ifndef DRM_FORMAT_INVALID +#define DRM_FORMAT_INVALID 0 +#endif + +namespace android { + +class BufferInfoGetter { + public: + virtual ~BufferInfoGetter() { + } + + virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; + + bool IsHandleUsable(buffer_handle_t handle); + + static BufferInfoGetter *GetInstance(); + + static bool IsDrmFormatRgb(uint32_t drm_format); +}; + +class LegacyBufferInfoGetter : public BufferInfoGetter { + public: + using BufferInfoGetter::BufferInfoGetter; + + int Init(); + + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override = 0; + + static LegacyBufferInfoGetter *CreateInstance(); + + static uint32_t ConvertHalFormatToDrm(uint32_t hal_format); + const gralloc_module_t *gralloc_; +}; + +#define LEGACY_BUFFER_INFO_GETTER(getter_) \ + LegacyBufferInfoGetter *LegacyBufferInfoGetter::CreateInstance() { \ + auto *instance = new getter_(); \ + if (!instance) \ + return NULL; \ + \ + int ret = instance->Init(); \ + if (ret) { \ + ALOGE("Failed to initialize the " #getter_ " getter %d", ret); \ + delete instance; \ + return NULL; \ + } \ + return instance; \ + } + +} // namespace android +#endif diff --git a/bufferinfo/BufferInfoMapperMetadata.cpp b/bufferinfo/BufferInfoMapperMetadata.cpp new file mode 100644 index 0000000..3aabeb5 --- /dev/null +++ b/bufferinfo/BufferInfoMapperMetadata.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020 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. + */ + +#if PLATFORM_SDK_VERSION >= 30 + +#define LOG_TAG "hwc-bufferinfo-mappermetadata" + +#include "BufferInfoMapperMetadata.h" + +#include <drm/drm_fourcc.h> +#include <inttypes.h> +#include <log/log.h> +#include <ui/GraphicBufferMapper.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +using android::hardware::graphics::common::V1_1::BufferUsage; + +namespace android { + +BufferInfoGetter *BufferInfoMapperMetadata::CreateInstance() { + if (GraphicBufferMapper::getInstance().getMapperVersion() < + GraphicBufferMapper::GRALLOC_4) + return nullptr; + + return new BufferInfoMapperMetadata(); +} + +/* The implementation below makes assumptions on the order and number of file + * descriptors that Gralloc places in the native_handle_t and as such it very + * likely needs to be adapted to match the particular Gralloc implementation + * used in the system. For this reason it is been declared as a weak symbol, + * so that it can be overridden. + */ +int __attribute__((weak)) +BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) { + int num_fds = handle->numFds; + + if (num_fds >= 1 && num_fds <= 2) { + if (IsDrmFormatRgb(bo->format)) { + bo->prime_fds[0] = handle->data[0]; + } else { + bo->prime_fds[0] = bo->prime_fds[1] = bo->prime_fds[2] = handle->data[0]; + } + if (bo->prime_fds[0] <= 0) { + ALOGE("Encountered invalid fd %d", bo->prime_fds[0]); + return android::BAD_VALUE; + } + + } else if (num_fds >= 3) { + bo->prime_fds[0] = handle->data[0]; + bo->prime_fds[1] = handle->data[1]; + bo->prime_fds[2] = handle->data[2]; + for (int i = 0; i < 3; i++) { + if (bo->prime_fds[i] <= 0) { + ALOGE("Encountered invalid fd %d", bo->prime_fds[i]); + return android::BAD_VALUE; + } + } + } + return 0; +} + +int BufferInfoMapperMetadata::ConvertBoInfo(buffer_handle_t handle, + hwc_drm_bo_t *bo) { + GraphicBufferMapper &mapper = GraphicBufferMapper::getInstance(); + if (!handle) + return -EINVAL; + + uint64_t usage = 0; + int err = mapper.getUsage(handle, &usage); + if (err) { + ALOGE("Failed to get usage err=%d", err); + return err; + } + bo->usage = static_cast<uint32_t>(usage); + + ui::PixelFormat hal_format; + err = mapper.getPixelFormatRequested(handle, &hal_format); + if (err) { + ALOGE("Failed to get HAL Pixel Format err=%d", err); + return err; + } + bo->hal_format = static_cast<uint32_t>(hal_format); + + err = mapper.getPixelFormatFourCC(handle, &bo->format); + if (err) { + ALOGE("Failed to get FourCC format err=%d", err); + return err; + } + + err = mapper.getPixelFormatModifier(handle, &bo->modifiers[0]); + if (err) { + ALOGE("Failed to get DRM Modifier err=%d", err); + return err; + } + bo->with_modifiers = true; + + uint64_t width = 0; + err = mapper.getWidth(handle, &width); + if (err) { + ALOGE("Failed to get Width err=%d", err); + return err; + } + bo->width = static_cast<uint32_t>(width); + + uint64_t height = 0; + err = mapper.getHeight(handle, &height); + if (err) { + ALOGE("Failed to get Height err=%d", err); + return err; + } + bo->height = static_cast<uint32_t>(height); + + std::vector<ui::PlaneLayout> layouts; + err = mapper.getPlaneLayouts(handle, &layouts); + if (err) { + ALOGE("Failed to get Plane Layouts err=%d", err); + return err; + } + + for (uint32_t i = 0; i < layouts.size(); i++) { + bo->modifiers[i] = bo->modifiers[0]; + bo->pitches[i] = layouts[i].strideInBytes; + bo->offsets[i] = layouts[i].offsetInBytes; + } + + return GetFds(handle, bo); +} + +} // namespace android + +#endif diff --git a/bufferinfo/BufferInfoMapperMetadata.h b/bufferinfo/BufferInfoMapperMetadata.h new file mode 100644 index 0000000..d335705 --- /dev/null +++ b/bufferinfo/BufferInfoMapperMetadata.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 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 PLATFORMIMAGINATION_H +#define PLATFORMIMAGINATION_H + +#include "bufferinfo/BufferInfoGetter.h" + +namespace android { + +class BufferInfoMapperMetadata : public BufferInfoGetter { + public: + using BufferInfoGetter::BufferInfoGetter; + + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + + int GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo); + + static BufferInfoGetter *CreateInstance(); +}; +} // namespace android + +#endif // PLATFORMIMAGINATION_H diff --git a/platform/platformimagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp index ea34ecc..84c177e 100644 --- a/platform/platformimagination.cpp +++ b/bufferinfo/legacy/BufferInfoImagination.cpp @@ -1,6 +1,23 @@ -#define LOG_TAG "hwc-platform-imagination" +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-imagination" + +#include "BufferInfoImagination.h" -#include "platformimagination.h" #include <log/log.h> #include <xf86drm.h> @@ -8,22 +25,10 @@ namespace android { -Importer *Importer::CreateInstance(DrmDevice *drm) { - ImaginationImporter *importer = new ImaginationImporter(drm); - if (!importer) - return NULL; - - int ret = importer->Init(); - if (ret) { - ALOGE("Failed to initialize the Imagination importer %d", ret); - delete importer; - return NULL; - } - return importer; -} +LEGACY_BUFFER_INFO_GETTER(BufferInfoImagination); -int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +int BufferInfoImagination::ConvertBoInfo(buffer_handle_t handle, + hwc_drm_bo_t *bo) { IMG_native_handle_t *hnd = (IMG_native_handle_t *)handle; if (!hnd) return -EINVAL; @@ -39,6 +44,7 @@ int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, bo->usage = hnd->usage; bo->prime_fds[0] = hnd->fd[0]; bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3; + bo->hal_format = hnd->iFormat; switch (hnd->iFormat) { #ifdef HAL_PIXEL_FORMAT_BGRX_8888 @@ -57,9 +63,4 @@ int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, return 0; } -std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) { - std::unique_ptr<Planner> planner(new Planner); - planner->AddStage<PlanStageGreedy>(); - return planner; -} } // namespace android diff --git a/bufferinfo/legacy/BufferInfoImagination.h b/bufferinfo/legacy/BufferInfoImagination.h new file mode 100644 index 0000000..765b279 --- /dev/null +++ b/bufferinfo/legacy/BufferInfoImagination.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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 BUFFERINFOIMAGINATION_H +#define BUFFERINFOIMAGINATION_H + +#include <hardware/gralloc.h> + +#include "bufferinfo/BufferInfoGetter.h" + +namespace android { + +class BufferInfoImagination : public LegacyBufferInfoGetter { + public: + using LegacyBufferInfoGetter::LegacyBufferInfoGetter; + + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; +}; +} // namespace android + +#endif // PLATFORMIMAGINATION_H diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp new file mode 100644 index 0000000..3f6a6fd --- /dev/null +++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-libdrm" + +#include "BufferInfoLibdrm.h" + +#include <cutils/properties.h> +#include <gralloc_handle.h> +#include <hardware/gralloc.h> +#include <log/log.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +namespace android { + +LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm); + +enum chroma_order { + YCbCr, + YCrCb, +}; + +struct droid_yuv_format { + /* Lookup keys */ + int native; /* HAL_PIXEL_FORMAT_ */ + enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */ + int chroma_step; /* Distance in bytes between subsequent chroma pixels. */ + + /* Result */ + int fourcc; /* DRM_FORMAT_ */ +}; + +/* The following table is used to look up a DRI image FourCC based + * on native format and information contained in android_ycbcr struct. */ +static const struct droid_yuv_format droid_yuv_formats[] = { + /* Native format, YCrCb, Chroma step, DRI image FourCC */ + {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12}, + {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420}, + {HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420}, + {HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420}, + /* HACK: See droid_create_image_from_prime_fds() and + * https://issuetracker.google.com/32077885. */ + {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12}, + {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420}, + {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420}, + {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV}, + {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888}, +}; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +static int get_fourcc_yuv(int native, enum chroma_order chroma_order, + int chroma_step) { + for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) + if (droid_yuv_formats[i].native == native && + droid_yuv_formats[i].chroma_order == chroma_order && + droid_yuv_formats[i].chroma_step == chroma_step) + return droid_yuv_formats[i].fourcc; + + return -1; +} + +static bool is_yuv(int native) { + for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) + if (droid_yuv_formats[i].native == native) + return true; + + return false; +} + +bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, + hwc_drm_bo_t *bo) { + struct android_ycbcr ycbcr; + enum chroma_order chroma_order; + int ret; + + if (!gralloc_->lock_ycbcr) { + static std::once_flag once; + std::call_once(once, + []() { ALOGW("Gralloc does not support lock_ycbcr()"); }); + return false; + } + + memset(&ycbcr, 0, sizeof(ycbcr)); + ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr); + if (ret) { + ALOGW("gralloc->lock_ycbcr failed: %d", ret); + return false; + } + gralloc_->unlock(gralloc_, handle); + + /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags + * it will return the .y/.cb/.cr pointers based on a NULL pointer, + * so they can be interpreted as offsets. */ + bo->offsets[0] = (size_t)ycbcr.y; + /* We assume here that all the planes are located in one DMA-buf. */ + if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) { + chroma_order = YCrCb; + bo->offsets[1] = (size_t)ycbcr.cr; + bo->offsets[2] = (size_t)ycbcr.cb; + } else { + chroma_order = YCbCr; + bo->offsets[1] = (size_t)ycbcr.cb; + bo->offsets[2] = (size_t)ycbcr.cr; + } + + /* .ystride is the line length (in bytes) of the Y plane, + * .cstride is the line length (in bytes) of any of the remaining + * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully + * planar formats. */ + bo->pitches[0] = ycbcr.ystride; + bo->pitches[1] = bo->pitches[2] = ycbcr.cstride; + + /* .chroma_step is the byte distance between the same chroma channel + * values of subsequent pixels, assumed to be the same for Cb and Cr. */ + bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step); + if (bo->format == -1) { + ALOGW( + "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = " + "%d", + bo->hal_format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", + (int)ycbcr.chroma_step); + return false; + } + + /* + * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that + * the single-fd case cannot happen. So handle eithe single + * fd or fd-per-plane case: + */ + if (num_fds == 1) { + bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0]; + } else { + int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3; + if (num_fds != expected_planes) + return false; + } + + return true; +} + +int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { + gralloc_handle_t *gr_handle = gralloc_handle(handle); + if (!gr_handle) + return -EINVAL; + + bo->width = gr_handle->width; + bo->height = gr_handle->height; + bo->hal_format = gr_handle->format; + +#if GRALLOC_HANDLE_VERSION < 4 + static std::once_flag once; + std::call_once(once, []() { + ALOGE( + "libdrm < v2.4.97 has broken gralloc_handle structure. Please update."); + }); +#endif +#if GRALLOC_HANDLE_VERSION == 4 + bo->modifiers[0] = gr_handle->modifier; + bo->with_modifiers = gr_handle->modifier != DRM_FORMAT_MOD_NONE && + gr_handle->modifier != DRM_FORMAT_MOD_INVALID; +#endif + + bo->usage = gr_handle->usage; + bo->prime_fds[0] = gr_handle->prime_fd; + + if (is_yuv(gr_handle->format)) { + if (!GetYuvPlaneInfo(handle->numFds, handle, bo)) + return -EINVAL; + } else { + bo->pitches[0] = gr_handle->stride; + bo->offsets[0] = 0; + bo->format = ConvertHalFormatToDrm(gr_handle->format); + if (bo->format == DRM_FORMAT_INVALID) + return -EINVAL; + } + + return 0; +} + +} // namespace android diff --git a/bufferinfo/legacy/BufferInfoLibdrm.h b/bufferinfo/legacy/BufferInfoLibdrm.h new file mode 100644 index 0000000..4d37d00 --- /dev/null +++ b/bufferinfo/legacy/BufferInfoLibdrm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 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 BUFFERINFOLIBDRM_H_ +#define BUFFERINFOLIBDRM_H_ + +#include <hardware/gralloc.h> + +#include "bufferinfo/BufferInfoGetter.h" + +namespace android { + +class BufferInfoLibdrm : public LegacyBufferInfoGetter { + public: + using LegacyBufferInfoGetter::LegacyBufferInfoGetter; + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + + private: + bool GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, hwc_drm_bo_t *bo); +}; + +} // namespace android + +#endif diff --git a/bufferinfo/legacy/BufferInfoMaliHisi.cpp b/bufferinfo/legacy/BufferInfoMaliHisi.cpp new file mode 100644 index 0000000..ab5579c --- /dev/null +++ b/bufferinfo/legacy/BufferInfoMaliHisi.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-mali-hisi" + +#include "BufferInfoMaliHisi.h" + +#include <log/log.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include <cinttypes> + +#include "gralloc_priv.h" + +#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) + +namespace android { + +LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliHisi); + +#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ + defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) +uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers(uint64_t flags, + bool is_rgb) { + uint64_t features = 0UL; + + if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) + features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16; + + if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) + features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE); + + if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) + features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8; + + if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) + features |= AFBC_FORMAT_MOD_TILED; + + if (features) { + if (is_rgb) + features |= AFBC_FORMAT_MOD_YTR; + + return DRM_FORMAT_MOD_ARM_AFBC(features); + } + + return 0; +} +#else +uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers( + uint64_t /* flags */, bool /* is_rgb */) { + return 0; +} +#endif + +int BufferInfoMaliHisi::ConvertBoInfo(buffer_handle_t handle, + hwc_drm_bo_t *bo) { + bool is_rgb; + + private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>( + handle); + if (!hnd) + return -EINVAL; + + if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) + return -EINVAL; + + uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); + if (fmt == DRM_FORMAT_INVALID) + return -EINVAL; + + is_rgb = IsDrmFormatRgb(fmt); + bo->modifiers[0] = ConvertGrallocFormatToDrmModifiers(hnd->internal_format, + is_rgb); + + bo->width = hnd->width; + bo->height = hnd->height; + bo->hal_format = hnd->req_format; + bo->format = fmt; + bo->usage = hnd->usage; + bo->pitches[0] = hnd->byte_stride; + bo->prime_fds[0] = hnd->share_fd; + bo->offsets[0] = 0; + + switch (fmt) { + case DRM_FORMAT_YVU420: { + int align = 128; + if (hnd->usage & + (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) + align = 16; + int adjusted_height = MALI_ALIGN(hnd->height, 2); + int y_size = adjusted_height * hnd->byte_stride; + int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align); + int v_size = vu_stride * (adjusted_height / 2); + + /* V plane*/ + bo->prime_fds[1] = hnd->share_fd; + bo->pitches[1] = vu_stride; + bo->offsets[1] = y_size; + /* U plane */ + bo->prime_fds[2] = hnd->share_fd; + bo->pitches[2] = vu_stride; + bo->offsets[2] = y_size + v_size; + break; + } + default: + break; + } + + bo->with_modifiers = true; + + return 0; +} + +} // namespace android diff --git a/platform/platformhisi.h b/bufferinfo/legacy/BufferInfoMaliHisi.h index f127bdb..698a0d3 100644 --- a/platform/platformhisi.h +++ b/bufferinfo/legacy/BufferInfoMaliHisi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2020 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. @@ -14,29 +14,23 @@ * limitations under the License. */ -#ifndef ANDROID_PLATFORM_HISI_H_ -#define ANDROID_PLATFORM_HISI_H_ - -#include "drmdevice.h" -#include "platform.h" -#include "platformdrmgeneric.h" - -#include <stdatomic.h> +#ifndef BUFFERINFOMALIHISI_H_ +#define BUFFERINFOMALIHISI_H_ #include <hardware/gralloc.h> +#include "bufferinfo/BufferInfoGetter.h" + namespace android { -class HisiImporter : public DrmGenericImporter { +class BufferInfoMaliHisi : public LegacyBufferInfoGetter { public: - using DrmGenericImporter::DrmGenericImporter; + using LegacyBufferInfoGetter::LegacyBufferInfoGetter; int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; private: uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags, bool is_rgb); - - bool IsDrmFormatRgb(uint32_t drm_format); }; } // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.cpp b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp new file mode 100644 index 0000000..ce47343 --- /dev/null +++ b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-mali-mediatek" + +#include "BufferInfoMaliMediatek.h" + +#include <hardware/gralloc.h> +#include <log/log.h> +#include <stdatomic.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include <cinttypes> + +#include "gralloc_priv.h" + +namespace android { + +LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMediatek); + +int BufferInfoMaliMediatek::ConvertBoInfo(buffer_handle_t handle, + hwc_drm_bo_t *bo) { + private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>( + handle); + if (!hnd) + return -EINVAL; + + uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); + if (fmt == DRM_FORMAT_INVALID) + return -EINVAL; + + bo->width = hnd->width; + bo->height = hnd->height; + bo->hal_format = hnd->req_format; + bo->format = fmt; + bo->usage = hnd->consumer_usage | hnd->producer_usage; + bo->prime_fds[0] = hnd->share_fd; + bo->pitches[0] = hnd->byte_stride; + bo->offsets[0] = 0; + + return 0; +} + +} // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.h b/bufferinfo/legacy/BufferInfoMaliMediatek.h new file mode 100644 index 0000000..1204818 --- /dev/null +++ b/bufferinfo/legacy/BufferInfoMaliMediatek.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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 BUFFERINFOMALIMTK_H_ +#define BUFFERINFOMALIMTK_H_ + +#include <hardware/gralloc.h> + +#include "bufferinfo/BufferInfoGetter.h" + +namespace android { + +class BufferInfoMaliMediatek : public LegacyBufferInfoGetter { + public: + using LegacyBufferInfoGetter::LegacyBufferInfoGetter; + + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; +}; +} // namespace android + +#endif diff --git a/platform/platformmeson.cpp b/bufferinfo/legacy/BufferInfoMaliMeson.cpp index ad3aff1..b6896e1 100644 --- a/platform/platformmeson.cpp +++ b/bufferinfo/legacy/BufferInfoMaliMeson.cpp @@ -14,40 +14,26 @@ * limitations under the License. */ -#define LOG_TAG "hwc-platform-meson" +#define LOG_TAG "hwc-bufferinfo-mali-meson" -#include "platformmeson.h" -#include "drmdevice.h" -#include "platform.h" +#include "BufferInfoMaliMeson.h" -#include <stdatomic.h> +#include <log/log.h> #include <xf86drm.h> #include <xf86drmMode.h> + #include <cinttypes> -#include <hardware/gralloc.h> -#include <log/log.h> #include "gralloc_priv.h" namespace android { -Importer *Importer::CreateInstance(DrmDevice *drm) { - MesonImporter *importer = new MesonImporter(drm); - if (!importer) - return NULL; - - int ret = importer->Init(); - if (ret) { - ALOGE("Failed to initialize the meson importer %d", ret); - delete importer; - return NULL; - } - return importer; -} +LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMeson); #if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) -uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) { +uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( + uint64_t flags) { uint64_t features = 0UL; if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) { @@ -69,13 +55,14 @@ uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) { return 0; } #else -uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers( +uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( uint64_t /* flags */) { return 0; } #endif -int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { +int BufferInfoMaliMeson::ConvertBoInfo(buffer_handle_t handle, + hwc_drm_bo_t *bo) { private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>( handle); if (!hnd) @@ -88,7 +75,7 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { if (fmt == DRM_FORMAT_INVALID) return -EINVAL; - bo->modifiers[0] = MesonImporter::ConvertGrallocFormatToDrmModifiers( + bo->modifiers[0] = BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( hnd->internal_format); bo->width = hnd->width; @@ -96,7 +83,6 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { bo->hal_format = hnd->req_format; bo->format = fmt; bo->usage = hnd->usage; - bo->pixel_stride = hnd->stride; bo->prime_fds[0] = hnd->share_fd; bo->pitches[0] = hnd->byte_stride; bo->offsets[0] = 0; @@ -106,9 +92,4 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { return 0; } -std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) { - std::unique_ptr<Planner> planner(new Planner); - planner->AddStage<PlanStageGreedy>(); - return planner; -} } // namespace android diff --git a/platform/platformmeson.h b/bufferinfo/legacy/BufferInfoMaliMeson.h index f29b796..ce5d3f9 100644 --- a/platform/platformmeson.h +++ b/bufferinfo/legacy/BufferInfoMaliMeson.h @@ -14,23 +14,18 @@ * limitations under the License. */ -#ifndef ANDROID_PLATFORM_HISI_H_ -#define ANDROID_PLATFORM_HISI_H_ - -#include "drmdevice.h" -#include "platform.h" -#include "platformdrmgeneric.h" - -#include <stdatomic.h> +#ifndef BUFFERINFOMALIHISI_H_ +#define BUFFERINFOMALIHISI_H_ #include <hardware/gralloc.h> +#include "bufferinfo/BufferInfoGetter.h" + namespace android { -class MesonImporter : public DrmGenericImporter { +class BufferInfoMaliMeson : public LegacyBufferInfoGetter { public: - using DrmGenericImporter::DrmGenericImporter; - + using LegacyBufferInfoGetter::LegacyBufferInfoGetter; int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; private: diff --git a/platform/platformminigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp index df195d3..860de08 100644 --- a/platform/platformminigbm.cpp +++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp @@ -14,38 +14,21 @@ * limitations under the License. */ -#define LOG_TAG "hwc-platform-drm-minigbm" +#define LOG_TAG "hwc-bufferinfo-minigbm" -#include "platformminigbm.h" -#include "drmdevice.h" -#include "platform.h" +#include "BufferInfoMinigbm.h" +#include <log/log.h> #include <xf86drm.h> #include <xf86drmMode.h> -#include <hardware/gralloc.h> -#include <log/log.h> - #include "cros_gralloc_handle.h" namespace android { -Importer *Importer::CreateInstance(DrmDevice *drm) { - DrmMinigbmImporter *importer = new DrmMinigbmImporter(drm); - if (!importer) - return NULL; +LEGACY_BUFFER_INFO_GETTER(BufferInfoMinigbm); - int ret = importer->Init(); - if (ret) { - ALOGE("Failed to initialize the minigbm importer %d", ret); - delete importer; - return NULL; - } - return importer; -} - -int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle; if (!gr_handle) return -EINVAL; @@ -55,7 +38,6 @@ int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle, bo->hal_format = gr_handle->droid_format; bo->format = gr_handle->format; bo->usage = gr_handle->usage; - bo->pixel_stride = gr_handle->pixel_stride; bo->prime_fds[0] = gr_handle->fds[0]; bo->pitches[0] = gr_handle->strides[0]; bo->offsets[0] = gr_handle->offsets[0]; @@ -63,10 +45,4 @@ int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle, return 0; } -std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) { - std::unique_ptr<Planner> planner(new Planner); - planner->AddStage<PlanStageGreedy>(); - return planner; -} - } // namespace android diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoMinigbm.h index 053b2aa..bff9d74 100644 --- a/platform/platformminigbm.h +++ b/bufferinfo/legacy/BufferInfoMinigbm.h @@ -14,20 +14,18 @@ * limitations under the License. */ -#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_ -#define ANDROID_PLATFORM_DRM_MINIGBM_H_ - -#include "drmdevice.h" -#include "platform.h" -#include "platformdrmgeneric.h" +#ifndef BUFFERINFOMINIGBM_H_ +#define BUFFERINFOMINIGBM_H_ #include <hardware/gralloc.h> +#include "bufferinfo/BufferInfoGetter.h" + namespace android { -class DrmMinigbmImporter : public DrmGenericImporter { +class BufferInfoMinigbm : public LegacyBufferInfoGetter { public: - using DrmGenericImporter::DrmGenericImporter; + using LegacyBufferInfoGetter::LegacyBufferInfoGetter; int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; }; diff --git a/compositor/drmdisplaycomposition.cpp b/compositor/DrmDisplayComposition.cpp index b710fe1..4d2e19a 100644 --- a/compositor/drmdisplaycomposition.cpp +++ b/compositor/DrmDisplayComposition.cpp @@ -16,21 +16,19 @@ #define LOG_TAG "hwc-drm-display-composition" -#include "drmdisplaycomposition.h" -#include "drmcrtc.h" -#include "drmdevice.h" -#include "drmdisplaycompositor.h" -#include "drmplane.h" -#include "platform.h" +#include "DrmDisplayComposition.h" +#include <log/log.h> #include <stdlib.h> +#include <sync/sync.h> +#include <xf86drmMode.h> #include <algorithm> #include <unordered_set> -#include <log/log.h> -#include <sync/sync.h> -#include <xf86drmMode.h> +#include "DrmDisplayCompositor.h" +#include "Planner.h" +#include "drm/DrmDevice.h" namespace android { diff --git a/include/drmdisplaycomposition.h b/compositor/DrmDisplayComposition.h index 2a5b1a4..73a9024 100644 --- a/include/drmdisplaycomposition.h +++ b/compositor/DrmDisplayComposition.h @@ -17,15 +17,15 @@ #ifndef ANDROID_DRM_DISPLAY_COMPOSITION_H_ #define ANDROID_DRM_DISPLAY_COMPOSITION_H_ -#include "drmcrtc.h" -#include "drmhwcomposer.h" -#include "drmplane.h" +#include <hardware/hardware.h> +#include <hardware/hwcomposer.h> #include <sstream> #include <vector> -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> +#include "drm/DrmCrtc.h" +#include "drm/DrmPlane.h" +#include "drmhwcomposer.h" namespace android { diff --git a/compositor/drmdisplaycompositor.cpp b/compositor/DrmDisplayCompositor.cpp index e6f6922..ba0d56b 100644 --- a/compositor/drmdisplaycompositor.cpp +++ b/compositor/DrmDisplayCompositor.cpp @@ -17,29 +17,39 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #define LOG_TAG "hwc-drm-display-compositor" -#include "drmdisplaycompositor.h" +#include "DrmDisplayCompositor.h" +#include <drm/drm_mode.h> +#include <log/log.h> #include <pthread.h> #include <sched.h> #include <stdlib.h> +#include <sync/sync.h> #include <time.h> +#include <utils/Trace.h> + +#include <array> #include <sstream> #include <vector> -#include <drm/drm_mode.h> -#include <log/log.h> -#include <sync/sync.h> -#include <utils/Trace.h> - -#include "autolock.h" -#include "drmcrtc.h" -#include "drmdevice.h" -#include "drmplane.h" +#include "drm/DrmCrtc.h" +#include "drm/DrmDevice.h" +#include "drm/DrmPlane.h" +#include "utils/autolock.h" static const uint32_t kWaitWritebackFence = 100; // ms namespace android { +std::ostream &operator<<(std::ostream &str, FlatteningState state) { + std::array<const char *, 6> flattenting_state_str = { + "None", "Not needed", "SF Requested", "Squashed by GPU", + "Serial", "Concurrent", + }; + + return str << flattenting_state_str[static_cast<int>(state)]; +} + class CompositorVsyncCallback : public VsyncCallback { public: CompositorVsyncCallback(DrmDisplayCompositor *compositor) @@ -63,7 +73,9 @@ DrmDisplayCompositor::DrmDisplayCompositor() dump_frames_composited_(0), dump_last_timestamp_ns_(0), flatten_countdown_(FLATTEN_COUNTDOWN_INIT), - writeback_fence_(-1) { + writeback_fence_(-1), + flattening_state_(FlatteningState::kNone), + frames_flattened_(0) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) return; @@ -143,6 +155,19 @@ DrmDisplayCompositor::CreateInitializedComposition() const { return comp; } +FlatteningState DrmDisplayCompositor::GetFlatteningState() const { + return flattening_state_; +} + +uint32_t DrmDisplayCompositor::GetFlattenedFramesCount() const { + return frames_flattened_; +} + +bool DrmDisplayCompositor::ShouldFlattenOnClient() const { + return flattening_state_ == FlatteningState::kClientRequested || + flattening_state_ == FlatteningState::kClientDone; +} + std::tuple<uint32_t, uint32_t, int> DrmDisplayCompositor::GetActiveModeResolution() { DrmDevice *drm = resource_manager_->GetDrmDevice(display_); @@ -605,6 +630,11 @@ void DrmDisplayCompositor::ApplyFrame( active_composition_.swap(composition); flatten_countdown_ = FLATTEN_COUNTDOWN_INIT; + if (flattening_state_ != FlatteningState::kClientRequested) { + SetFlattening(FlatteningState::kNone); + } else { + SetFlattening(FlatteningState::kClientDone); + } vsync_worker_.VSyncControl(!writeback); } @@ -761,6 +791,54 @@ int DrmDisplayCompositor::FlattenOnDisplay( return 0; } +void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) { + if (flattening_state_ != new_state) { + switch (flattening_state_) { + case FlatteningState::kClientDone: + case FlatteningState::kConcurrent: + case FlatteningState::kSerial: + ++frames_flattened_; + break; + case FlatteningState::kClientRequested: + case FlatteningState::kNone: + case FlatteningState::kNotNeeded: + break; + } + } + flattening_state_ = new_state; +} + +bool DrmDisplayCompositor::IsFlatteningNeeded() const { + return CountdownExpired() && active_composition_->layers().size() >= 2; +} + +int DrmDisplayCompositor::FlattenOnClient() { + const std::lock_guard<std::mutex> lock(refresh_callback_lock); + + if (refresh_callback_hook_ && refresh_callback_data_) { + { + AutoLock lock(&lock_, __func__); + if (!IsFlatteningNeeded()) { + if (flattening_state_ != FlatteningState::kClientDone) { + ALOGV("Flattening is not needed"); + SetFlattening(FlatteningState::kNotNeeded); + } + return -EALREADY; + } + } + + ALOGV( + "No writeback connector available, " + "falling back to client composition"); + SetFlattening(FlatteningState::kClientRequested); + refresh_callback_hook_(refresh_callback_data_, display_); + return 0; + } else { + ALOGV("No writeback connector available"); + return -EINVAL; + } +} + // Flatten a scene by enabling the writeback connector attached // to the same CRTC as the one driving the display. int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) { @@ -776,8 +854,9 @@ int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) { int ret = lock.Lock(); if (ret) return ret; - if (!CountdownExpired() || active_composition_->layers().size() < 2) { + if (!IsFlatteningNeeded()) { ALOGV("Flattening is not needed"); + SetFlattening(FlatteningState::kNotNeeded); return -EALREADY; } @@ -884,8 +963,9 @@ int DrmDisplayCompositor::FlattenConcurrent(DrmConnector *writeback_conn) { ret = lock.Lock(); if (ret) return ret; - if (!CountdownExpired() || active_composition_->layers().size() < 2) { + if (!IsFlatteningNeeded()) { ALOGV("Flattening is not needed"); + SetFlattening(FlatteningState::kNotNeeded); return -EALREADY; } DrmCrtc *crtc = active_composition_->crtc(); @@ -955,13 +1035,16 @@ int DrmDisplayCompositor::FlattenActiveComposition() { DrmConnector *writeback_conn = resource_manager_->AvailableWritebackConnector( display_); if (!active_composition_ || !writeback_conn) { - ALOGV("No writeback connector available"); - return -EINVAL; + // Try to fallback to GPU composition on client, since it is more + // power-efficient than composition on device side + return FlattenOnClient(); } if (writeback_conn->display() != display_) { + SetFlattening(FlatteningState::kConcurrent); return FlattenConcurrent(writeback_conn); } else { + SetFlattening(FlatteningState::kSerial); return FlattenSerial(writeback_conn); } diff --git a/include/drmdisplaycompositor.h b/compositor/DrmDisplayCompositor.h index 477f226..ab3f867 100644 --- a/include/drmdisplaycompositor.h +++ b/compositor/DrmDisplayCompositor.h @@ -17,19 +17,20 @@ #ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_ #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_ -#include "drmdisplaycomposition.h" -#include "drmframebuffer.h" -#include "drmhwcomposer.h" -#include "resourcemanager.h" -#include "vsyncworker.h" - +#include <hardware/hardware.h> +#include <hardware/hwcomposer.h> #include <pthread.h> + #include <memory> #include <sstream> #include <tuple> -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> +#include "DrmDisplayComposition.h" +#include "DrmFramebuffer.h" +#include "Planner.h" +#include "drm/ResourceManager.h" +#include "drm/VSyncWorker.h" +#include "drmhwcomposer.h" // One for the front, one for the back, and one for cases where we need to // squash a frame that the hw can't display with hw overlays. @@ -41,6 +42,17 @@ namespace android { +enum class FlatteningState { + kNone, + kNotNeeded, + kClientRequested, + kClientDone, + kSerial, + kConcurrent +}; + +std::ostream &operator<<(std::ostream &str, FlatteningState state); + class DrmDisplayCompositor { public: DrmDisplayCompositor(); @@ -48,6 +60,17 @@ class DrmDisplayCompositor { int Init(ResourceManager *resource_manager, int display); + hwc2_callback_data_t refresh_callback_data_ = NULL; + HWC2_PFN_REFRESH refresh_callback_hook_ = NULL; + std::mutex refresh_callback_lock; + + void SetRefreshCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t hook) { + const std::lock_guard<std::mutex> lock(refresh_callback_lock); + refresh_callback_data_ = data; + refresh_callback_hook_ = reinterpret_cast<HWC2_PFN_REFRESH>(hook); + } + std::unique_ptr<DrmDisplayComposition> CreateComposition() const; std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const; int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition); @@ -62,6 +85,10 @@ class DrmDisplayCompositor { return active_composition_->take_out_fence(); } + FlatteningState GetFlatteningState() const; + uint32_t GetFlattenedFramesCount() const; + bool ShouldFlattenOnClient() const; + std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution(); private: @@ -90,7 +117,11 @@ class DrmDisplayCompositor { void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition, int status, bool writeback = false); + + void SetFlattening(FlatteningState new_state); + bool IsFlatteningNeeded() const; int FlattenActiveComposition(); + int FlattenOnClient(); int FlattenSerial(DrmConnector *writeback_conn); int FlattenConcurrent(DrmConnector *writeback_conn); int FlattenOnDisplay(std::unique_ptr<DrmDisplayComposition> &src, @@ -126,6 +157,11 @@ class DrmDisplayCompositor { int64_t flatten_countdown_; std::unique_ptr<Planner> planner_; int writeback_fence_; + + FlatteningState flattening_state_; + uint32_t frames_flattened_; + + std::function<void(int)> refresh_display_cb_; }; } // namespace android diff --git a/platform/platform.cpp b/compositor/Planner.cpp index b7a47c7..f4b5c51 100644 --- a/platform/platform.cpp +++ b/compositor/Planner.cpp @@ -16,13 +16,20 @@ #define LOG_TAG "hwc-platform" -#include "platform.h" -#include "drmdevice.h" +#include "Planner.h" #include <log/log.h> +#include "drm/DrmDevice.h" + namespace android { +std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) { + std::unique_ptr<Planner> planner(new Planner); + planner->AddStage<PlanStageGreedy>(); + return planner; +} + std::vector<DrmPlane *> Planner::GetUsablePlanes( DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, std::vector<DrmPlane *> *overlay_planes) { @@ -77,6 +84,13 @@ int Planner::PlanStage::ValidatePlane(DrmPlane *plane, DrmHwcLayer *layer) { ALOGE("Expected a valid blend mode on plane %d", plane->id()); } + uint32_t format = layer->buffer->format; + if (!plane->IsFormatSupported(format)) { + ALOGE("Plane %d does not supports %c%c%c%c format", plane->id(), format, + format >> 8, format >> 16, format >> 24); + return -EINVAL; + } + return ret; } diff --git a/include/platform.h b/compositor/Planner.h index 6775e29..09034ff 100644 --- a/include/platform.h +++ b/compositor/Planner.h @@ -17,46 +17,19 @@ #ifndef ANDROID_DRM_PLATFORM_H_ #define ANDROID_DRM_PLATFORM_H_ -#include "drmdisplaycomposition.h" -#include "drmhwcomposer.h" - #include <hardware/hardware.h> #include <hardware/hwcomposer.h> #include <map> #include <vector> +#include "compositor/DrmDisplayComposition.h" +#include "drmhwcomposer.h" + namespace android { class DrmDevice; -class Importer { - public: - virtual ~Importer() { - } - - // Creates a platform-specific importer instance - static Importer *CreateInstance(DrmDevice *drm); - - // Imports the buffer referred to by handle into bo. - // - // Note: This can be called from a different thread than ReleaseBuffer. The - // implementation is responsible for ensuring thread safety. - virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; - - // Releases the buffer object (ie: does the inverse of ImportBuffer) - // - // Note: This can be called from a different thread than ImportBuffer. The - // implementation is responsible for ensuring thread safety. - virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; - - // Checks if importer can import the buffer. - virtual bool CanImportBuffer(buffer_handle_t handle) = 0; - - // Convert platform-dependent buffer format to drm_hwc internal format. - virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; -}; - class Planner { public: class PlanStage { diff --git a/drm/drmconnector.cpp b/drm/DrmConnector.cpp index 7cde7cd..f1b6c1b 100644 --- a/drm/drmconnector.cpp +++ b/drm/DrmConnector.cpp @@ -16,17 +16,17 @@ #define LOG_TAG "hwc-drm-connector" -#include "drmconnector.h" -#include "drmdevice.h" +#include "DrmConnector.h" #include <errno.h> +#include <log/log.h> #include <stdint.h> +#include <xf86drmMode.h> #include <array> #include <sstream> -#include <log/log.h> -#include <xf86drmMode.h> +#include "DrmDevice.h" namespace android { @@ -58,6 +58,7 @@ int DrmConnector::Init() { ALOGE("Could not get CRTC_ID property\n"); return ret; } + ret = UpdateEdidProperty(); if (writeback()) { ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS", &writeback_pixel_formats_); @@ -81,6 +82,30 @@ int DrmConnector::Init() { return 0; } +int DrmConnector::UpdateEdidProperty() { + int ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_); + if (ret) { + ALOGW("Could not get EDID property\n"); + } + return ret; +} + +int DrmConnector::GetEdidBlob(drmModePropertyBlobPtr &blob) { + uint64_t blob_id; + int ret = UpdateEdidProperty(); + if (ret) { + return ret; + } + + std::tie(ret, blob_id) = edid_property().value(); + if (ret) { + return ret; + } + + blob = drmModeGetPropertyBlob(drm_->fd(), blob_id); + return !blob; +} + uint32_t DrmConnector::id() const { return id_; } @@ -191,6 +216,10 @@ const DrmProperty &DrmConnector::crtc_id_property() const { return crtc_id_property_; } +const DrmProperty &DrmConnector::edid_property() const { + return edid_property_; +} + const DrmProperty &DrmConnector::writeback_pixel_formats() const { return writeback_pixel_formats_; } diff --git a/include/drmconnector.h b/drm/DrmConnector.h index c9fd7ab..8533af8 100644 --- a/include/drmconnector.h +++ b/drm/DrmConnector.h @@ -17,15 +17,16 @@ #ifndef ANDROID_DRM_CONNECTOR_H_ #define ANDROID_DRM_CONNECTOR_H_ -#include "drmencoder.h" -#include "drmmode.h" -#include "drmproperty.h" - #include <stdint.h> #include <xf86drmMode.h> + #include <string> #include <vector> +#include "DrmEncoder.h" +#include "DrmMode.h" +#include "DrmProperty.h" + namespace android { class DrmDevice; @@ -39,6 +40,8 @@ class DrmConnector { DrmConnector &operator=(const DrmProperty &) = delete; int Init(); + int UpdateEdidProperty(); + int GetEdidBlob(drmModePropertyBlobPtr &blob); uint32_t id() const; @@ -62,6 +65,7 @@ class DrmConnector { const DrmProperty &dpms_property() const; const DrmProperty &crtc_id_property() const; + const DrmProperty &edid_property() const; const DrmProperty &writeback_pixel_formats() const; const DrmProperty &writeback_fb_id() const; const DrmProperty &writeback_out_fence() const; @@ -100,6 +104,7 @@ class DrmConnector { DrmProperty dpms_property_; DrmProperty crtc_id_property_; + DrmProperty edid_property_; DrmProperty writeback_pixel_formats_; DrmProperty writeback_fb_id_; DrmProperty writeback_out_fence_; diff --git a/drm/drmcrtc.cpp b/drm/DrmCrtc.cpp index b627291..4ce8cfc 100644 --- a/drm/drmcrtc.cpp +++ b/drm/DrmCrtc.cpp @@ -16,13 +16,13 @@ #define LOG_TAG "hwc-drm-crtc" -#include "drmcrtc.h" -#include "drmdevice.h" +#include "DrmCrtc.h" +#include <log/log.h> #include <stdint.h> #include <xf86drmMode.h> -#include <log/log.h> +#include "DrmDevice.h" namespace android { diff --git a/include/drmcrtc.h b/drm/DrmCrtc.h index 3075f9b..7972bef 100644 --- a/include/drmcrtc.h +++ b/drm/DrmCrtc.h @@ -17,12 +17,12 @@ #ifndef ANDROID_DRM_CRTC_H_ #define ANDROID_DRM_CRTC_H_ -#include "drmmode.h" -#include "drmproperty.h" - #include <stdint.h> #include <xf86drmMode.h> +#include "DrmMode.h" +#include "DrmProperty.h" + namespace android { class DrmDevice; diff --git a/drm/drmdevice.cpp b/drm/DrmDevice.cpp index bcb9ddd..bf1a5e2 100644 --- a/drm/drmdevice.cpp +++ b/drm/DrmDevice.cpp @@ -16,27 +16,22 @@ #define LOG_TAG "hwc-drm-device" -#include "drmdevice.h" -#include "drmconnector.h" -#include "drmcrtc.h" -#include "drmencoder.h" -#include "drmeventlistener.h" -#include "drmplane.h" +#include "DrmDevice.h" +#include <cutils/properties.h> #include <errno.h> #include <fcntl.h> +#include <log/log.h> #include <stdint.h> #include <xf86drm.h> #include <xf86drmMode.h> -#include <cinttypes> #include <algorithm> #include <array> +#include <cinttypes> +#include <sstream> #include <string> -#include <cutils/properties.h> -#include <log/log.h> - static void trim_left(std::string &str) { str.erase(std::begin(str), std::find_if(std::begin(str), std::end(str), @@ -59,7 +54,7 @@ namespace android { static std::vector<std::string> read_primary_display_order_prop() { std::array<char, PROPERTY_VALUE_MAX> display_order_buf; - property_get("hwc.drm.primary_display_order", display_order_buf.data(), + property_get("vendor.hwc.drm.primary_display_order", display_order_buf.data(), "..."); std::vector<std::string> display_order; @@ -126,7 +121,7 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { /* TODO: Use drmOpenControl here instead */ fd_.Set(open(path, O_RDWR)); if (fd() < 0) { - ALOGE("Failed to open dri- %s", strerror(-errno)); + ALOGE("Failed to open dri %s: %s", path, strerror(errno)); return std::make_tuple(-ENODEV, 0); } @@ -254,7 +249,7 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { } // Primary display priority: - // 1) hwc.drm.primary_display_order property + // 1) vendor.hwc.drm.primary_display_order property // 2) internal connectors // 3) anything else std::vector<DrmConnector *> @@ -267,8 +262,8 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) { found_primary = true; } else { ALOGE( - "Failed to find primary display from \"hwc.drm.primary_display_order\" " - "property"); + "Failed to find primary display from " + "\"vendor.hwc.drm.primary_display_order\" property"); } // If no priority display were found then pick first available as primary and @@ -570,4 +565,16 @@ int DrmDevice::GetConnectorProperty(const DrmConnector &connector, return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name, property); } + +const std::string DrmDevice::GetName() const { + auto ver = drmGetVersion(fd_.get()); + if (!ver) { + ALOGW("Failed to get drm version for fd=%d", fd_.get()); + return "generic"; + } + + std::string name(ver->name); + drmFreeVersion(ver); + return name; +} } // namespace android diff --git a/include/drmdevice.h b/drm/DrmDevice.h index 91dd38b..be68aa6 100644 --- a/include/drmdevice.h +++ b/drm/DrmDevice.h @@ -17,16 +17,17 @@ #ifndef ANDROID_DRM_H_ #define ANDROID_DRM_H_ -#include "drmconnector.h" -#include "drmcrtc.h" -#include "drmencoder.h" -#include "drmeventlistener.h" -#include "drmplane.h" -#include "platform.h" - #include <stdint.h> + +#include <map> #include <tuple> +#include "DrmConnector.h" +#include "DrmCrtc.h" +#include "DrmEncoder.h" +#include "DrmEventListener.h" +#include "DrmPlane.h" + namespace android { class DrmDevice { @@ -70,6 +71,8 @@ class DrmDevice { int GetConnectorProperty(const DrmConnector &connector, const char *prop_name, DrmProperty *property); + const std::string GetName() const; + const std::vector<std::unique_ptr<DrmCrtc>> &crtcs() const; uint32_t next_mode_id(); diff --git a/drm/drmencoder.cpp b/drm/DrmEncoder.cpp index c36fca1..bcf0926 100644 --- a/drm/drmencoder.cpp +++ b/drm/DrmEncoder.cpp @@ -14,13 +14,13 @@ * limitations under the License. */ -#include "drmencoder.h" -#include "drmcrtc.h" -#include "drmdevice.h" +#include "DrmEncoder.h" #include <stdint.h> #include <xf86drmMode.h> +#include "DrmDevice.h" + namespace android { DrmEncoder::DrmEncoder(drmModeEncoderPtr e, DrmCrtc *current_crtc, diff --git a/include/drmencoder.h b/drm/DrmEncoder.h index 8a7f682..f4464d0 100644 --- a/include/drmencoder.h +++ b/drm/DrmEncoder.h @@ -17,13 +17,14 @@ #ifndef ANDROID_DRM_ENCODER_H_ #define ANDROID_DRM_ENCODER_H_ -#include "drmcrtc.h" - #include <stdint.h> #include <xf86drmMode.h> + #include <set> #include <vector> +#include "DrmCrtc.h" + namespace android { class DrmEncoder { diff --git a/drm/drmeventlistener.cpp b/drm/DrmEventListener.cpp index 8f655a7..3d95e28 100644 --- a/drm/drmeventlistener.cpp +++ b/drm/DrmEventListener.cpp @@ -16,19 +16,19 @@ #define LOG_TAG "hwc-drm-event-listener" -#include "drmeventlistener.h" -#include "drmdevice.h" +#include "DrmEventListener.h" #include <assert.h> #include <errno.h> -#include <linux/netlink.h> -#include <sys/socket.h> - #include <hardware/hardware.h> #include <hardware/hwcomposer.h> +#include <linux/netlink.h> #include <log/log.h> +#include <sys/socket.h> #include <xf86drm.h> +#include "DrmDevice.h" + namespace android { DrmEventListener::DrmEventListener(DrmDevice *drm) @@ -38,7 +38,7 @@ DrmEventListener::DrmEventListener(DrmDevice *drm) int DrmEventListener::Init() { uevent_fd_.Set(socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)); if (uevent_fd_.get() < 0) { - ALOGE("Failed to open uevent socket %d", uevent_fd_.get()); + ALOGE("Failed to open uevent socket: %s", strerror(errno)); return uevent_fd_.get(); } @@ -50,7 +50,7 @@ int DrmEventListener::Init() { int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr)); if (ret) { - ALOGE("Failed to bind uevent socket %d", -errno); + ALOGE("Failed to bind uevent socket: %s", strerror(errno)); return -errno; } diff --git a/include/drmeventlistener.h b/drm/DrmEventListener.h index 95672ee..9f9a4ba 100644 --- a/include/drmeventlistener.h +++ b/drm/DrmEventListener.h @@ -18,7 +18,7 @@ #define ANDROID_DRM_EVENT_LISTENER_H_ #include "autofd.h" -#include "worker.h" +#include "utils/Worker.h" namespace android { diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp new file mode 100644 index 0000000..8ab4fe5 --- /dev/null +++ b/drm/DrmGenericImporter.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2020 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 LOG_TAG "hwc-platform-drm-generic" + +#include "DrmGenericImporter.h" + +#include <cutils/properties.h> +#include <gralloc_handle.h> +#include <hardware/gralloc.h> +#include <inttypes.h> +#include <log/log.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +namespace android { + +DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) { + uint64_t cap_value = 0; + if (drmGetCap(drm_->fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) { + ALOGE("drmGetCap failed. Fallback to no modifier support."); + cap_value = 0; + } + has_modifier_support_ = cap_value; +} + +DrmGenericImporter::~DrmGenericImporter() { +} + +int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) { + int ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], + &bo->gem_handles[0]); + if (ret) { + ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret); + return ret; + } + + for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) { + int fd = bo->prime_fds[i]; + if (fd != 0) { + if (fd != bo->prime_fds[0]) { + ALOGE("Multiplanar FBs are not supported by this version of composer"); + return -ENOTSUP; + } + bo->gem_handles[i] = bo->gem_handles[0]; + } + } + + if (!has_modifier_support_ && bo->modifiers[0]) { + ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64, + bo->modifiers[0]); + return -EINVAL; + } + + if (!bo->with_modifiers) + ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format, + bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, + 0); + else + ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height, + bo->format, bo->gem_handles, bo->pitches, + bo->offsets, bo->modifiers, &bo->fb_id, + bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS + : 0); + + if (ret) { + ALOGE("could not create drm fb %d", ret); + return ret; + } + + ImportHandle(bo->gem_handles[0]); + + return ret; +} + +int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) { + if (bo->fb_id) + if (drmModeRmFB(drm_->fd(), bo->fb_id)) + ALOGE("Failed to rm fb"); + + for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { + if (!bo->gem_handles[i]) + continue; + + if (ReleaseHandle(bo->gem_handles[i])) { + ALOGE("Failed to release gem handle %d", bo->gem_handles[i]); + } else { + for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++) + if (bo->gem_handles[j] == bo->gem_handles[i]) + bo->gem_handles[j] = 0; + bo->gem_handles[i] = 0; + } + } + return 0; +} + +int DrmGenericImporter::ImportHandle(uint32_t gem_handle) { + gem_refcount_[gem_handle]++; + + return 0; +} + +int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) { + if (--gem_refcount_[gem_handle]) + return 0; + + gem_refcount_.erase(gem_handle); + + return CloseHandle(gem_handle); +} + +int DrmGenericImporter::CloseHandle(uint32_t gem_handle) { + struct drm_gem_close gem_close; + + memset(&gem_close, 0, sizeof(gem_close)); + + gem_close.handle = gem_handle; + int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); + if (ret) + ALOGE("Failed to close gem handle %d %d", gem_handle, ret); + + return ret; +} +} // namespace android diff --git a/platform/platformdrmgeneric.h b/drm/DrmGenericImporter.h index f9d923f..ca53762 100644 --- a/platform/platformdrmgeneric.h +++ b/drm/DrmGenericImporter.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2020 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. @@ -17,13 +17,13 @@ #ifndef ANDROID_PLATFORM_DRM_GENERIC_H_ #define ANDROID_PLATFORM_DRM_GENERIC_H_ -#include "drmdevice.h" -#include "platform.h" - +#include <drm/drm_fourcc.h> #include <hardware/gralloc.h> + #include <map> -#include <drm/drm_fourcc.h> +#include "drm/DrmDevice.h" +#include "drmhwcgralloc.h" #ifndef DRM_FORMAT_INVALID #define DRM_FORMAT_INVALID 0 @@ -31,34 +31,43 @@ namespace android { +class Importer { + public: + virtual ~Importer() { + } + + // Imports the buffer referred to by handle into bo. + // + // Note: This can be called from a different thread than ReleaseBuffer. The + // implementation is responsible for ensuring thread safety. + virtual int ImportBuffer(hwc_drm_bo_t *bo) = 0; + + // Releases the buffer object (ie: does the inverse of ImportBuffer) + // + // Note: This can be called from a different thread than ImportBuffer. The + // implementation is responsible for ensuring thread safety. + virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; +}; + class DrmGenericImporter : public Importer { public: DrmGenericImporter(DrmDevice *drm); ~DrmGenericImporter() override; - int Init(); - - int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + int ImportBuffer(hwc_drm_bo_t *bo) override; int ReleaseBuffer(hwc_drm_bo_t *bo) override; - bool CanImportBuffer(buffer_handle_t handle) override; int ImportHandle(uint32_t gem_handle); int ReleaseHandle(uint32_t gem_handle); - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; - - uint32_t ConvertHalFormatToDrm(uint32_t hal_format); - uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format); - protected: DrmDevice *drm_; private: - const gralloc_module_t *gralloc_; - bool exclude_non_hwfb_; - int CloseHandle(uint32_t gem_handle); std::map<uint32_t, int> gem_refcount_; + bool has_modifier_support_; }; + } // namespace android #endif diff --git a/drm/drmmode.cpp b/drm/DrmMode.cpp index c3ab385..6de671a 100644 --- a/drm/drmmode.cpp +++ b/drm/DrmMode.cpp @@ -14,12 +14,9 @@ * limitations under the License. */ -#include "drmmode.h" -#include "drmdevice.h" +#include "DrmMode.h" -#include <stdint.h> -#include <xf86drmMode.h> -#include <string> +#include "DrmDevice.h" namespace android { diff --git a/include/drmmode.h b/drm/DrmMode.h index 4cc06b1..313a8ea 100644 --- a/include/drmmode.h +++ b/drm/DrmMode.h @@ -19,6 +19,7 @@ #include <stdint.h> #include <xf86drmMode.h> + #include <string> namespace android { diff --git a/drm/drmplane.cpp b/drm/DrmPlane.cpp index 6f1bf9b..f994252 100644 --- a/drm/drmplane.cpp +++ b/drm/DrmPlane.cpp @@ -16,20 +16,23 @@ #define LOG_TAG "hwc-drm-plane" -#include "drmplane.h" -#include "drmdevice.h" +#include "DrmPlane.h" #include <errno.h> +#include <log/log.h> #include <stdint.h> + #include <cinttypes> -#include <log/log.h> -#include <xf86drmMode.h> +#include "DrmDevice.h" namespace android { DrmPlane::DrmPlane(DrmDevice *drm, drmModePlanePtr p) - : drm_(drm), id_(p->plane_id), possible_crtc_mask_(p->possible_crtcs) { + : drm_(drm), + id_(p->plane_id), + possible_crtc_mask_(p->possible_crtcs), + formats_(p->formats, p->formats + p->count_formats) { } int DrmPlane::Init() { @@ -153,6 +156,11 @@ uint32_t DrmPlane::type() const { return type_; } +bool DrmPlane::IsFormatSupported(uint32_t format) const { + return std::find(std::begin(formats_), std::end(formats_), format) != + std::end(formats_); +} + const DrmProperty &DrmPlane::crtc_property() const { return crtc_property_; } diff --git a/include/drmplane.h b/drm/DrmPlane.h index 43e0e8a..16731a8 100644 --- a/include/drmplane.h +++ b/drm/DrmPlane.h @@ -17,13 +17,14 @@ #ifndef ANDROID_DRM_PLANE_H_ #define ANDROID_DRM_PLANE_H_ -#include "drmcrtc.h" -#include "drmproperty.h" - #include <stdint.h> #include <xf86drmMode.h> + #include <vector> +#include "DrmCrtc.h" +#include "DrmProperty.h" + namespace android { class DrmDevice; @@ -42,6 +43,8 @@ class DrmPlane { uint32_t type() const; + bool IsFormatSupported(uint32_t format) const; + const DrmProperty &crtc_property() const; const DrmProperty &fb_property() const; const DrmProperty &crtc_x_property() const; @@ -66,6 +69,8 @@ class DrmPlane { uint32_t type_; + std::vector<uint32_t> formats_; + DrmProperty crtc_property_; DrmProperty fb_property_; DrmProperty crtc_x_property_; diff --git a/drm/drmproperty.cpp b/drm/DrmProperty.cpp index 3aeed13..b60a76e 100644 --- a/drm/drmproperty.cpp +++ b/drm/DrmProperty.cpp @@ -14,14 +14,15 @@ * limitations under the License. */ -#include "drmproperty.h" -#include "drmdevice.h" +#include "DrmProperty.h" #include <errno.h> #include <stdint.h> +#include <xf86drmMode.h> + #include <string> -#include <xf86drmMode.h> +#include "DrmDevice.h" namespace android { diff --git a/include/drmproperty.h b/drm/DrmProperty.h index 2d92ca1..d293da3 100644 --- a/include/drmproperty.h +++ b/drm/DrmProperty.h @@ -19,6 +19,7 @@ #include <stdint.h> #include <xf86drmMode.h> + #include <string> #include <vector> diff --git a/drm/resourcemanager.cpp b/drm/ResourceManager.cpp index 6e23561..fc24aea 100644 --- a/drm/resourcemanager.cpp +++ b/drm/ResourceManager.cpp @@ -16,12 +16,15 @@ #define LOG_TAG "hwc-resource-manager" -#include "resourcemanager.h" +#include "ResourceManager.h" #include <cutils/properties.h> #include <log/log.h> +#include <sys/stat.h> + #include <sstream> -#include <string> + +#include "bufferinfo/BufferInfoGetter.h" namespace android { @@ -32,7 +35,8 @@ int ResourceManager::Init() { char path_pattern[PROPERTY_VALUE_MAX]; // Could be a valid path or it can have at the end of it the wildcard % // which means that it will try open all devices until an error is met. - int path_len = property_get("hwc.drm.device", path_pattern, "/dev/dri/card0"); + int path_len = property_get("vendor.hwc.drm.device", path_pattern, + "/dev/dri/card%"); int ret = 0; if (path_pattern[path_len - 1] != '%') { ret = AddDrmDevice(std::string(path_pattern)); @@ -41,7 +45,13 @@ int ResourceManager::Init() { for (int idx = 0; !ret; ++idx) { std::ostringstream path; path << path_pattern << idx; - ret = AddDrmDevice(path.str()); + + struct stat buf; + if (stat(path.str().c_str(), &buf)) { + break; + } else if (IsKMSDev(path.str().c_str())) { + ret = AddDrmDevice(path.str()); + } } } @@ -50,6 +60,15 @@ int ResourceManager::Init() { return ret ? -EINVAL : ret; } + char scale_with_gpu[PROPERTY_VALUE_MAX]; + property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0"); + scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1)); + + if (!BufferInfoGetter::GetInstance()) { + ALOGE("Failed to initialize BufferInfoGetter"); + return -EINVAL; + } + return hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&gralloc_); } @@ -61,7 +80,7 @@ int ResourceManager::AddDrmDevice(std::string path) { if (ret) return ret; std::shared_ptr<Importer> importer; - importer.reset(Importer::CreateInstance(drm.get())); + importer.reset(new DrmGenericImporter(drm.get())); if (!importer) { ALOGE("Failed to create importer instance"); return -ENODEV; @@ -90,6 +109,26 @@ DrmConnector *ResourceManager::AvailableWritebackConnector(int display) { return writeback_conn; } +bool ResourceManager::IsKMSDev(const char *path) { + int fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) + return false; + + auto res = drmModeGetResources(fd); + if (!res) { + close(fd); + return false; + } + + bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 && + res->count_encoders > 0; + + drmModeFreeResources(res); + close(fd); + + return is_kms; +} + DrmDevice *ResourceManager::GetDrmDevice(int display) { for (auto &drm : drms_) { if (drm->HandlesDisplay(display)) diff --git a/include/resourcemanager.h b/drm/ResourceManager.h index f10af45..7102cea 100644 --- a/include/resourcemanager.h +++ b/drm/ResourceManager.h @@ -17,11 +17,11 @@ #ifndef RESOURCEMANAGER_H #define RESOURCEMANAGER_H -#include "drmdevice.h" -#include "platform.h" - #include <string.h> +#include "DrmDevice.h" +#include "DrmGenericImporter.h" + namespace android { class ResourceManager { @@ -40,14 +40,20 @@ class ResourceManager { int getDisplayCount() const { return num_displays_; } + bool ForcedScalingWithGpu() { + return scale_with_gpu_; + } private: int AddDrmDevice(std::string path); + static bool IsKMSDev(const char *path); int num_displays_; std::vector<std::unique_ptr<DrmDevice>> drms_; std::vector<std::shared_ptr<Importer>> importers_; const gralloc_module_t *gralloc_; + + bool scale_with_gpu_; }; } // namespace android diff --git a/drm/vsyncworker.cpp b/drm/VSyncWorker.cpp index 08ab301..b2f7e5f 100644 --- a/drm/vsyncworker.cpp +++ b/drm/VSyncWorker.cpp @@ -16,18 +16,13 @@ #define LOG_TAG "hwc-vsync-worker" -#include "vsyncworker.h" -#include "drmdevice.h" -#include "worker.h" +#include "VSyncWorker.h" +#include <log/log.h> #include <stdlib.h> #include <time.h> #include <xf86drm.h> #include <xf86drmMode.h> -#include <map> - -#include <hardware/hardware.h> -#include <log/log.h> namespace android { @@ -55,6 +50,14 @@ void VSyncWorker::RegisterCallback(std::shared_ptr<VsyncCallback> callback) { Unlock(); } +void VSyncWorker::RegisterClientCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t hook) { + Lock(); + vsync_callback_data_ = data; + vsync_callback_hook_ = reinterpret_cast<HWC2_PFN_VSYNC>(hook); + Unlock(); +} + void VSyncWorker::VSyncControl(bool enabled) { Lock(); enabled_ = enabled; @@ -156,37 +159,17 @@ void VSyncWorker::Routine() { (int64_t)vblank.reply.tval_usec * 1000; } - /* - * VSync could be disabled during routine execution so it could potentially - * lead to crash since callback's inner hook could be invalid anymore. We have - * no control over lifetime of this hook, therefore we can't rely that it'll - * be valid after vsync disabling. - * - * Blocking VSyncControl to wait until routine - * will finish execution is logically correct way to fix this issue, but it - * creates visible lags and stutters, so we have to resort to other ways of - * mitigating this issue. - * - * Doing check before attempt to invoke callback drastically shortens the - * window when such situation could happen and that allows us to practically - * avoid this issue. - * - * Please note that issue described below is different one and it is related - * to RegisterCallback, not to disabling vsync via VSyncControl. - */ if (!enabled_) return; - /* - * There's a race here where a change in callback_ will not take effect until - * the next subsequent requested vsync. This is unavoidable since we can't - * call the vsync hook while holding the thread lock. - * - * We could shorten the race window by caching callback_ right before calling - * the hook. However, in practice, callback_ is only updated once, so it's not - * worth the overhead. - */ + if (callback) callback->Callback(display, timestamp); + + Lock(); + if (enabled_ && vsync_callback_hook_ && vsync_callback_data_) + vsync_callback_hook_(vsync_callback_data_, display, timestamp); + Unlock(); + last_timestamp_ = timestamp; } } // namespace android diff --git a/include/vsyncworker.h b/drm/VSyncWorker.h index 96f7432..7454b51 100644 --- a/include/vsyncworker.h +++ b/drm/VSyncWorker.h @@ -17,14 +17,15 @@ #ifndef ANDROID_EVENT_WORKER_H_ #define ANDROID_EVENT_WORKER_H_ -#include "drmdevice.h" -#include "worker.h" - +#include <hardware/hardware.h> +#include <hardware/hwcomposer.h> +#include <hardware/hwcomposer2.h> #include <stdint.h> + #include <map> -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> +#include "DrmDevice.h" +#include "utils/Worker.h" namespace android { @@ -42,6 +43,8 @@ class VSyncWorker : public Worker { int Init(DrmDevice *drm, int display); void RegisterCallback(std::shared_ptr<VsyncCallback> callback); + void RegisterClientCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t hook); void VSyncControl(bool enabled); @@ -62,6 +65,9 @@ class VSyncWorker : public Worker { int display_; std::atomic_bool enabled_; int64_t last_timestamp_; + + hwc2_callback_data_t vsync_callback_data_ = NULL; + HWC2_PFN_VSYNC vsync_callback_hook_ = NULL; }; } // namespace android diff --git a/include/drmframebuffer.h b/include/DrmFramebuffer.h index 9032d3a..33ca0db 100644 --- a/include/drmframebuffer.h +++ b/include/DrmFramebuffer.h @@ -18,9 +18,7 @@ #define ANDROID_DRM_FRAMEBUFFER_ #include <stdint.h> - #include <sync/sync.h> - #include <ui/GraphicBuffer.h> namespace android { diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h index b959714..fc0af64 100644 --- a/include/drmhwcgralloc.h +++ b/include/drmhwcgralloc.h @@ -26,7 +26,6 @@ typedef struct hwc_drm_bo { uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */ uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */ uint32_t usage; - uint32_t pixel_stride; uint32_t pitches[HWC_DRM_BO_MAX_PLANES]; uint32_t offsets[HWC_DRM_BO_MAX_PLANES]; uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES]; diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h index 69313d9..0706ae5 100644 --- a/include/drmhwcomposer.h +++ b/include/drmhwcomposer.h @@ -99,8 +99,7 @@ class DrmHwcNativeHandle { return *this; } - int CopyBufferHandle(buffer_handle_t handle, int width, int height, - int layerCount, int format, int usage, int stride); + int CopyBufferHandle(buffer_handle_t handle); void Clear(); diff --git a/platform/platformdrmgeneric.cpp b/platform/platformdrmgeneric.cpp deleted file mode 100644 index 1aa8160..0000000 --- a/platform/platformdrmgeneric.cpp +++ /dev/null @@ -1,252 +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. - */ - -#define LOG_TAG "hwc-platform-drm-generic" - -#include "platformdrmgeneric.h" -#include "drmdevice.h" -#include "platform.h" - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include <cutils/properties.h> -#include <gralloc_handle.h> -#include <hardware/gralloc.h> -#include <log/log.h> - -namespace android { - -#ifdef USE_DRM_GENERIC_IMPORTER -// static -Importer *Importer::CreateInstance(DrmDevice *drm) { - DrmGenericImporter *importer = new DrmGenericImporter(drm); - if (!importer) - return NULL; - - int ret = importer->Init(); - if (ret) { - ALOGE("Failed to initialize the nv importer %d", ret); - delete importer; - return NULL; - } - return importer; -} -#endif - -DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) - : drm_(drm), exclude_non_hwfb_(false) { -} - -DrmGenericImporter::~DrmGenericImporter() { -} - -int DrmGenericImporter::Init() { - int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, - (const hw_module_t **)&gralloc_); - if (ret) { - ALOGE("Failed to open gralloc module"); - return ret; - } - - ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name, - gralloc_->common.author); - - char exclude_non_hwfb_prop[PROPERTY_VALUE_MAX]; - property_get("hwc.drm.exclude_non_hwfb_imports", exclude_non_hwfb_prop, "0"); - exclude_non_hwfb_ = static_cast<bool>(strncmp(exclude_non_hwfb_prop, "0", 1)); - - return 0; -} - -uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) { - switch (hal_format) { - case HAL_PIXEL_FORMAT_RGB_888: - return DRM_FORMAT_BGR888; - case HAL_PIXEL_FORMAT_BGRA_8888: - return DRM_FORMAT_ARGB8888; - case HAL_PIXEL_FORMAT_RGBX_8888: - return DRM_FORMAT_XBGR8888; - case HAL_PIXEL_FORMAT_RGBA_8888: - return DRM_FORMAT_ABGR8888; - case HAL_PIXEL_FORMAT_RGB_565: - return DRM_FORMAT_BGR565; - case HAL_PIXEL_FORMAT_YV12: - return DRM_FORMAT_YVU420; - default: - ALOGE("Cannot convert hal format to drm format %u", hal_format); - return DRM_FORMAT_INVALID; - } -} - -uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) { - switch (drm_format) { - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ABGR8888: - return 32; - case DRM_FORMAT_BGR888: - return 24; - case DRM_FORMAT_BGR565: - return 16; - case DRM_FORMAT_YVU420: - return 12; - default: - ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format); - return 32; - } -} - -int DrmGenericImporter::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { - gralloc_handle_t *gr_handle = gralloc_handle(handle); - if (!gr_handle) - return -EINVAL; - - bo->width = gr_handle->width; - bo->height = gr_handle->height; - bo->hal_format = gr_handle->format; - bo->format = ConvertHalFormatToDrm(gr_handle->format); - if (bo->format == DRM_FORMAT_INVALID) - return -EINVAL; - bo->usage = gr_handle->usage; - bo->pixel_stride = (gr_handle->stride * 8) / - DrmFormatToBitsPerPixel(bo->format); - bo->prime_fds[0] = gr_handle->prime_fd; - bo->pitches[0] = gr_handle->stride; - bo->offsets[0] = 0; - - return 0; -} - -int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { - memset(bo, 0, sizeof(hwc_drm_bo_t)); - - int ret = ConvertBoInfo(handle, bo); - if (ret) - return ret; - - ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &bo->gem_handles[0]); - if (ret) { - ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret); - return ret; - } - - for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) { - int fd = bo->prime_fds[i]; - if (fd != 0) { - if (fd != bo->prime_fds[0]) { - ALOGE("Multiplanar FBs are not supported by this version of composer"); - return -ENOTSUP; - } - bo->gem_handles[i] = bo->gem_handles[0]; - } - } - - if (!bo->with_modifiers) - ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format, - bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, - 0); - else - ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height, - bo->format, bo->gem_handles, bo->pitches, - bo->offsets, bo->modifiers, &bo->fb_id, - bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS - : 0); - - if (ret) { - ALOGE("could not create drm fb %d", ret); - return ret; - } - - ImportHandle(bo->gem_handles[0]); - - return ret; -} - -int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) { - if (bo->fb_id) - if (drmModeRmFB(drm_->fd(), bo->fb_id)) - ALOGE("Failed to rm fb"); - - for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { - if (!bo->gem_handles[i]) - continue; - - if (ReleaseHandle(bo->gem_handles[i])) { - ALOGE("Failed to release gem handle %d", bo->gem_handles[i]); - } else { - for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++) - if (bo->gem_handles[j] == bo->gem_handles[i]) - bo->gem_handles[j] = 0; - bo->gem_handles[i] = 0; - } - } - return 0; -} - -bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) { - hwc_drm_bo_t bo; - - int ret = ConvertBoInfo(handle, &bo); - if (ret) - return false; - - if (bo.prime_fds[0] == 0) - return false; - - if (exclude_non_hwfb_ && !(bo.usage & GRALLOC_USAGE_HW_FB)) - return false; - - return true; -} - -#ifdef USE_DRM_GENERIC_IMPORTER -std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) { - std::unique_ptr<Planner> planner(new Planner); - planner->AddStage<PlanStageGreedy>(); - return planner; -} -#endif - -int DrmGenericImporter::ImportHandle(uint32_t gem_handle) { - gem_refcount_[gem_handle]++; - - return 0; -} - -int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) { - if (--gem_refcount_[gem_handle]) - return 0; - - gem_refcount_.erase(gem_handle); - - return CloseHandle(gem_handle); -} - -int DrmGenericImporter::CloseHandle(uint32_t gem_handle) { - struct drm_gem_close gem_close; - - memset(&gem_close, 0, sizeof(gem_close)); - - gem_close.handle = gem_handle; - int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); - if (ret) - ALOGE("Failed to close gem handle %d %d", gem_handle, ret); - - return ret; -} -} diff --git a/platform/platformhisi.cpp b/platform/platformhisi.cpp deleted file mode 100644 index 1f1478f..0000000 --- a/platform/platformhisi.cpp +++ /dev/null @@ -1,197 +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. - */ - -#define LOG_TAG "hwc-platform-hisi" - -#include "platformhisi.h" -#include "drmdevice.h" -#include "platform.h" - -#include <stdatomic.h> -#include <xf86drm.h> -#include <xf86drmMode.h> -#include <cinttypes> - -#include <hardware/gralloc.h> -#include <log/log.h> -#include "gralloc_priv.h" - -#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) - -namespace android { - -Importer *Importer::CreateInstance(DrmDevice *drm) { - HisiImporter *importer = new HisiImporter(drm); - if (!importer) - return NULL; - - int ret = importer->Init(); - if (ret) { - ALOGE("Failed to initialize the hisi importer %d", ret); - delete importer; - return NULL; - } - return importer; -} - -#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ - defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) -uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags, - bool is_rgb) { - uint64_t features = 0UL; - - if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) - features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16; - - if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) - features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE); - - if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) - features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8; - - if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) - features |= AFBC_FORMAT_MOD_TILED; - - if (features) { - if (is_rgb) - features |= AFBC_FORMAT_MOD_YTR; - - return DRM_FORMAT_MOD_ARM_AFBC(features); - } - - return 0; -} -#else -uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t /* flags */, - bool /* is_rgb */) { - return 0; -} -#endif - -bool HisiImporter::IsDrmFormatRgb(uint32_t drm_format) { - switch (drm_format) { - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_BGR888: - case DRM_FORMAT_BGR565: - return true; - case DRM_FORMAT_YVU420: - return false; - default: - ALOGV("Unsupported format %u assuming rgb?", drm_format); - return true; - } -} - -int HisiImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { - bool is_rgb; - - private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>( - handle); - if (!hnd) - return -EINVAL; - - if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) - return -EINVAL; - - uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); - if (fmt == DRM_FORMAT_INVALID) - return -EINVAL; - - is_rgb = HisiImporter::IsDrmFormatRgb(fmt); - bo->modifiers[0] = HisiImporter:: - ConvertGrallocFormatToDrmModifiers(hnd->internal_format, is_rgb); - - bo->width = hnd->width; - bo->height = hnd->height; - bo->hal_format = hnd->req_format; - bo->format = fmt; - bo->usage = hnd->usage; - bo->pixel_stride = hnd->stride; - bo->pitches[0] = hnd->byte_stride; - bo->prime_fds[0] = hnd->share_fd; - bo->offsets[0] = 0; - - switch (fmt) { - case DRM_FORMAT_YVU420: { - int align = 128; - if (hnd->usage & - (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) - align = 16; - int adjusted_height = MALI_ALIGN(hnd->height, 2); - int y_size = adjusted_height * hnd->byte_stride; - int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align); - int v_size = vu_stride * (adjusted_height / 2); - - /* V plane*/ - bo->prime_fds[1] = hnd->share_fd; - bo->pitches[1] = vu_stride; - bo->offsets[1] = y_size; - /* U plane */ - bo->prime_fds[2] = hnd->share_fd; - bo->pitches[2] = vu_stride; - bo->offsets[2] = y_size + v_size; - break; - } - default: - break; - } - - bo->with_modifiers = true; - - return 0; -} - -class PlanStageHiSi : public Planner::PlanStage { - public: - int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, - std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, - std::vector<DrmPlane *> *planes) { - int layers_added = 0; - // Fill up as many DRM planes as we can with buffers that have HW_FB usage. - // Buffers without HW_FB should have been filtered out with - // CanImportBuffer(), if we meet one here, just skip it. - for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) { - if (!(i->second->gralloc_buffer_usage & GRALLOC_USAGE_HW_FB)) - continue; - - int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, - crtc, std::make_pair(i->first, i->second)); - layers_added++; - // We don't have any planes left - if (ret == -ENOENT) - break; - else if (ret) { - ALOGE("Failed to emplace layer %zu, dropping it", i->first); - return ret; - } - } - // If we didn't emplace anything, return an error to ensure we force client - // compositing. - if (!layers_added) - return -EINVAL; - - return 0; - } -}; - -std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) { - std::unique_ptr<Planner> planner(new Planner); - planner->AddStage<PlanStageHiSi>(); - return planner; -} -} // namespace android diff --git a/platform/platformimagination.h b/platform/platformimagination.h deleted file mode 100644 index f2a7cb7..0000000 --- a/platform/platformimagination.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef PLATFORMIMAGINATION_H -#define PLATFORMIMAGINATION_H - -#include "drmdevice.h" -#include "platform.h" -#include "platformdrmgeneric.h" - -#include <stdatomic.h> - -#include <hardware/gralloc.h> - -namespace android { - -class ImaginationImporter : public DrmGenericImporter { - public: - using DrmGenericImporter::DrmGenericImporter; - - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -}; -} // namespace android - -#endif // PLATFORMIMAGINATION_H diff --git a/tests/Android.bp b/tests/Android.bp index 7e550ff..6ffb364 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -1,5 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "external_drm_hwcomposer_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["external_drm_hwcomposer_license"], +} + cc_test { name: "hwc-drm-tests", @@ -9,5 +18,8 @@ cc_test { header_libs: ["libhardware_headers"], static_libs: ["libdrmhwc_utils"], shared_libs: ["hwcomposer.drm"], - include_dirs: ["external/drm_hwcomposer/include"], + include_dirs: [ + "external/drm_hwcomposer/include", + "external/drm_hwcomposer", + ], } diff --git a/tests/worker_test.cpp b/tests/worker_test.cpp index 82523f0..cb6275e 100644 --- a/tests/worker_test.cpp +++ b/tests/worker_test.cpp @@ -1,10 +1,10 @@ +#include "utils/Worker.h" + #include <gtest/gtest.h> #include <hardware/hardware.h> #include <chrono> -#include "worker.h" - using android::Worker; struct TestWorker : public Worker { diff --git a/utils/worker.cpp b/utils/Worker.cpp index 0dceb16..1f30588 100644 --- a/utils/worker.cpp +++ b/utils/Worker.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "worker.h" +#include "Worker.h" #include <sys/prctl.h> #include <sys/resource.h> diff --git a/include/worker.h b/utils/Worker.h index 7909038..73a80da 100644 --- a/include/worker.h +++ b/utils/Worker.h @@ -19,10 +19,10 @@ #include <stdint.h> #include <stdlib.h> -#include <string> #include <condition_variable> #include <mutex> +#include <string> #include <thread> namespace android { diff --git a/include/autolock.h b/utils/autolock.h index 006406a..006406a 100644 --- a/include/autolock.h +++ b/utils/autolock.h diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp index 87e3c42..322efce 100644 --- a/utils/hwcutils.cpp +++ b/utils/hwcutils.cpp @@ -17,12 +17,14 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #define LOG_TAG "hwc-drm-utils" -#include "drmhwcomposer.h" -#include "platform.h" - #include <log/log.h> +#include <ui/Gralloc.h> #include <ui/GraphicBufferMapper.h> +#include "bufferinfo/BufferInfoGetter.h" +#include "drm/DrmGenericImporter.h" +#include "drmhwcomposer.h" + #define UNUSED(x) (void)(x) namespace android { @@ -44,11 +46,19 @@ void DrmHwcBuffer::Clear() { } int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { - hwc_drm_bo tmp_bo; + hwc_drm_bo tmp_bo{}; - int ret = importer->ImportBuffer(handle, &tmp_bo); - if (ret) + int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(handle, &tmp_bo); + if (ret) { + ALOGE("Failed to convert buffer info %d", ret); return ret; + } + + ret = importer->ImportBuffer(&tmp_bo); + if (ret) { + ALOGE("Failed to import buffer %d", ret); + return ret; + } if (importer_ != NULL) { importer_->ReleaseBuffer(&bo_); @@ -61,25 +71,15 @@ int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { return 0; } -int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, int width, - int height, int layerCount, int format, - int usage, int stride) { +int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle) { native_handle_t *handle_copy; GraphicBufferMapper &gm(GraphicBufferMapper::get()); int ret; -#ifdef HWC2_USE_OLD_GB_IMPORT - UNUSED(width); - UNUSED(height); - UNUSED(layerCount); - UNUSED(format); - UNUSED(usage); - UNUSED(stride); - ret = gm.importBuffer(handle, const_cast<buffer_handle_t *>(&handle_copy)); -#else - ret = gm.importBuffer(handle, width, height, layerCount, format, usage, - stride, const_cast<buffer_handle_t *>(&handle_copy)); -#endif + ret = gm.getGrallocMapper().importBuffer(handle, + const_cast<buffer_handle_t *>( + &handle_copy)); + if (ret) { ALOGE("Failed to import buffer handle %d", ret); return ret; @@ -114,13 +114,7 @@ int DrmHwcLayer::ImportBuffer(Importer *importer) { const hwc_drm_bo *bo = buffer.operator->(); - unsigned int layer_count; - for (layer_count = 0; layer_count < HWC_DRM_BO_MAX_PLANES; ++layer_count) - if (bo->gem_handles[layer_count] == 0) - break; - - ret = handle.CopyBufferHandle(sf_handle, bo->width, bo->height, layer_count, - bo->hal_format, bo->usage, bo->pixel_stride); + ret = handle.CopyBufferHandle(sf_handle); if (ret) return ret; |