/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include "HwcDisplayConfigs.h" #include "HwcLayer.h" #include "compositor/DisplayInfo.h" #include "compositor/FlatteningController.h" #include "compositor/LayerData.h" #include "drm/DrmAtomicStateManager.h" #include "drm/ResourceManager.h" #include "drm/VSyncWorker.h" #include "stats/CompositionStats.h" namespace android { using DisplayHandle = int64_t; class Backend; class DrmHwc; class FrontendDisplayBase { public: virtual ~FrontendDisplayBase() = default; }; inline constexpr uint32_t kPrimaryDisplay = 0; // NOLINTNEXTLINE class HwcDisplay { public: enum ConfigError { kNone, kBadConfig, kSeamlessNotAllowed, kSeamlessNotPossible }; enum DisplayType { kInternal, kExternal, kVirtual }; HwcDisplay(DisplayHandle handle, bool is_virtual, DrmHwc *hwc); HwcDisplay(const HwcDisplay &) = delete; ~HwcDisplay(); void SetColorTransformMatrix( const std::array &color_transform_matrix); /* SetPipeline should be carefully used only by DrmHwcTwo hotplug handlers */ void SetPipeline(std::shared_ptr pipeline); bool CreateComposition(AtomicCommitArgs &a_args); std::vector GetOrderLayersByZPos(); std::string Dump(); auto GetDisplayName() -> std::string; const HwcDisplayConfigs &GetDisplayConfigs() const { return configs_; } // Get the config representing the mode that has been committed to KMS. auto GetCurrentConfig() const -> const HwcDisplayConfig *; // Get the config that was last requested through SetActiveConfig and similar // functions. This may differ from the GetCurrentConfig if the config change // is queued up to take effect in the future. auto GetLastRequestedConfig() const -> const HwcDisplayConfig *; // Set a config synchronously. If the requested config fails to be committed, // this will return with an error. Otherwise, the config will have been // committed to the kernel on successful return. ConfigError SetConfig(ConfigId config); // Queue a configuration change to take effect in the future. auto QueueConfig(ConfigId config, int64_t desired_time, bool seamless, QueuedConfigTiming *out_timing) -> ConfigError; // Get the HwcDisplayConfig, or nullptor if none. auto GetConfig(ConfigId config_id) const -> const HwcDisplayConfig *; auto GetDisplayBoundsMm() -> std::pair; // To be called after SetDisplayProperties. Returns an empty vector if the // requested layers have been validated, otherwise the vector describes // the requested composition type changes. using ChangedLayer = std::pair; auto ValidateStagedComposition() -> std::vector; // Mark previously validated properties as ready to present. auto AcceptValidatedComposition() -> void; using ReleaseFence = std::pair; // Present previously staged properties, and return fences to indicate when // the new content has been presented, and when the previous buffers have // been released. If |desired_present_time| is set, ensure that the // composition is presented at the closest vsync to that requested time. // Otherwise, present immediately. auto PresentStagedComposition(std::optional desired_present_time, SharedFd &out_present_fence, std::vector &out_release_fences) -> bool; // Get the edid bytes for this display. Return an empty vector on error. auto GetRawEdid() -> std::vector; // Get the port id that this display is plugged into. auto GetPort() -> uint8_t; auto SetContentType(ContentType content_type) { content_type_ = content_type; } // Physical displays are either internal or external. auto GetDisplayType() -> DisplayType; // Enable or disable vsync callbacks. void SetVsyncCallbacksEnabled(bool enabled); // Enable or disable the display. bool SetDisplayEnabled(bool enabled); auto GetFrontendPrivateData() -> std::shared_ptr { return frontend_private_data_; } auto SetFrontendPrivateData(std::shared_ptr data) { frontend_private_data_ = std::move(data); } auto CreateLayer(ILayerId new_layer_id) -> bool; auto DestroyLayer(ILayerId layer_id) -> bool; auto GetColorModes() -> std::vector; void SetColorMode(ColorMode color_mode); void GetHdrCapabilities(std::vector *types, float *max_luminance, float *max_average_luminance, float *min_luminance); bool IsWritebackSupported(); bool SetWritebackEnabled(bool enabled); SharedFd GetWritebackBufferFence(); HwcLayer *get_layer(ILayerId layer) { auto it = layers_.find(layer); if (it == layers_.end()) return nullptr; return &it->second; } const Backend *backend() const; void set_backend(std::unique_ptr backend); auto GetHwc() { return hwc_; } auto layers() -> std::map & { return layers_; } auto &GetPipe() { return *pipeline_; } bool CtmByGpu(); CompositionStats &total_stats() { return total_stats_; } /* Headless mode required to keep SurfaceFlinger alive when all display are * disconnected, Without headless mode Android will continuously crash. * Only single internal (primary) display is required to be in HEADLESS mode * to prevent the crash. See: * https://source.android.com/devices/graphics/hotplug#handling-common-scenarios */ bool IsInHeadlessMode() { return !pipeline_; } void Deinit(); auto GetFlatCon() { return flatcon_; } auto GetClientLayer() -> HwcLayer & { return client_layer_; } auto &GetWritebackLayer() { return writeback_layer_; } void SetVirtualDisplayResolution(uint16_t width, uint16_t height) { virtual_disp_width_ = width; virtual_disp_height_ = height; } auto getDisplayPhysicalOrientation() -> std::optional; bool NeedsClientLayerUpdate() const; private: AtomicCommitArgs CreateModesetCommit( const HwcDisplayConfig *config, const std::optional &modeset_layer); // Sleep the current thread until |present_time| is closest to the next // expected vsync time. void WaitForPresentTime(int64_t present_time, uint32_t vsync_period_ns); uint32_t GetCurrentVsyncPeriodNs() const; HwcDisplayConfigs configs_; DrmHwc *const hwc_; int64_t staged_mode_change_time_{}; std::optional staged_mode_config_id_{}; std::shared_ptr pipeline_; std::unique_ptr backend_; std::shared_ptr flatcon_; std::unique_ptr vsync_worker_; bool vsync_event_en_{}; const DisplayHandle handle_; bool is_virtual_; std::map layers_; HwcLayer client_layer_; std::unique_ptr writeback_layer_; uint16_t virtual_disp_width_{}; uint16_t virtual_disp_height_{}; std::shared_ptr color_matrix_; std::shared_ptr identity_color_matrix_; bool color_transform_is_identity_{}; bool ctm_has_offset_ = false; ContentType content_type_ = ContentType::kNoData; Colorspace colorspace_{}; int32_t min_bpc_{}; std::shared_ptr hdr_metadata_; std::shared_ptr current_plan_; SharedFd writeback_complete_fence_; uint32_t frame_no_ = 0; CompositionStats total_stats_; void SetColorMatrixToIdentity(); bool Init(); void SetHdrOutputMetadata(ui::Hdr hdrType); void SetOutputType(uint32_t hdr_output_type); auto GetEdid() -> EdidWrapperUnique & { return GetPipe().connector->Get()->GetParsedEdid(); } std::shared_ptr frontend_private_data_; }; } // namespace android