| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <hardware/hwcomposer2.h> |
| |
| #include <atomic> |
| #include <optional> |
| #include <sstream> |
| |
| #include "HwcDisplayConfigs.h" |
| #include "compositor/FlatteningController.h" |
| #include "compositor/LayerData.h" |
| #include "drm/DrmAtomicStateManager.h" |
| #include "drm/ResourceManager.h" |
| #include "drm/VSyncWorker.h" |
| #include "hwc2_device/HwcLayer.h" |
| |
| namespace android { |
| |
| class Backend; |
| class DrmHwc; |
| |
| inline constexpr uint32_t kPrimaryDisplay = 0; |
| |
| // NOLINTNEXTLINE |
| class HwcDisplay { |
| public: |
| HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwc *hwc); |
| HwcDisplay(const HwcDisplay &) = delete; |
| ~HwcDisplay(); |
| |
| /* SetPipeline should be carefully used only by DrmHwcTwo hotplug handlers */ |
| void SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline); |
| |
| HWC2::Error CreateComposition(AtomicCommitArgs &a_args); |
| std::vector<HwcLayer *> GetOrderLayersByZPos(); |
| |
| void ClearDisplay(); |
| |
| std::string Dump(); |
| |
| const HwcDisplayConfigs &GetDisplayConfigs() const { |
| return configs_; |
| } |
| |
| // HWC Hooks |
| HWC2::Error AcceptDisplayChanges(); |
| HWC2::Error CreateLayer(hwc2_layer_t *layer); |
| HWC2::Error DestroyLayer(hwc2_layer_t layer); |
| HWC2::Error GetActiveConfig(hwc2_config_t *config) const; |
| HWC2::Error GetChangedCompositionTypes(uint32_t *num_elements, |
| hwc2_layer_t *layers, int32_t *types); |
| HWC2::Error GetClientTargetSupport(uint32_t width, uint32_t height, |
| int32_t format, int32_t dataspace); |
| HWC2::Error GetColorModes(uint32_t *num_modes, int32_t *modes); |
| HWC2::Error GetDisplayAttribute(hwc2_config_t config, int32_t attribute, |
| int32_t *value); |
| HWC2::Error LegacyGetDisplayConfigs(uint32_t *num_configs, |
| hwc2_config_t *configs); |
| HWC2::Error GetDisplayName(uint32_t *size, char *name); |
| HWC2::Error GetDisplayRequests(int32_t *display_requests, |
| uint32_t *num_elements, hwc2_layer_t *layers, |
| int32_t *layer_requests); |
| HWC2::Error GetDisplayType(int32_t *type); |
| #if __ANDROID_API__ > 27 |
| HWC2::Error GetRenderIntents(int32_t mode, uint32_t *outNumIntents, |
| int32_t *outIntents); |
| HWC2::Error SetColorModeWithIntent(int32_t mode, int32_t intent); |
| #endif |
| #if __ANDROID_API__ > 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 |
| #if __ANDROID_API__ > 29 |
| HWC2::Error GetDisplayConnectionType(uint32_t *outType); |
| |
| HWC2::Error SetActiveConfigWithConstraints( |
| hwc2_config_t config, |
| hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, |
| hwc_vsync_period_change_timeline_t *outTimeline); |
| HWC2::Error SetAutoLowLatencyMode(bool on); |
| HWC2::Error GetSupportedContentTypes( |
| uint32_t *outNumSupportedContentTypes, |
| const uint32_t *outSupportedContentTypes); |
| |
| HWC2::Error SetContentType(int32_t contentType); |
| #endif |
| HWC2::Error GetDisplayVsyncPeriod(uint32_t *outVsyncPeriod); |
| |
| HWC2::Error GetDozeSupport(int32_t *support); |
| HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types, |
| float *max_luminance, |
| float *max_average_luminance, |
| float *min_luminance); |
| HWC2::Error GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers, |
| int32_t *fences); |
| HWC2::Error PresentDisplay(int32_t *out_present_fence); |
| HWC2::Error SetActiveConfig(hwc2_config_t config); |
| HWC2::Error ChosePreferredConfig(); |
| HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence, |
| int32_t dataspace, hwc_region_t damage); |
| HWC2::Error SetColorMode(int32_t mode); |
| HWC2::Error SetColorTransform(const float *matrix, int32_t hint); |
| HWC2::Error SetOutputBuffer(buffer_handle_t buffer, int32_t release_fence); |
| HWC2::Error SetPowerMode(int32_t mode); |
| HWC2::Error SetVsyncEnabled(int32_t enabled); |
| HWC2::Error ValidateDisplay(uint32_t *num_types, uint32_t *num_requests); |
| HwcLayer *get_layer(hwc2_layer_t layer) { |
| auto it = layers_.find(layer); |
| if (it == layers_.end()) |
| return nullptr; |
| return &it->second; |
| } |
| |
| /* Statistics */ |
| struct Stats { |
| Stats minus(Stats b) const { |
| 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; |
| void set_backend(std::unique_ptr<Backend> backend); |
| |
| auto GetHwc() { |
| return hwc_; |
| } |
| |
| std::map<hwc2_layer_t, HwcLayer> &layers() { |
| return layers_; |
| } |
| |
| auto &GetPipe() { |
| return *pipeline_; |
| } |
| |
| bool CtmByGpu(); |
| |
| Stats &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 &GetWritebackLayer() { |
| return writeback_layer_; |
| } |
| |
| void SetVirtualDisplayResolution(uint16_t width, uint16_t height) { |
| virtual_disp_width_ = width; |
| virtual_disp_height_ = height; |
| } |
| |
| private: |
| HwcDisplayConfigs configs_; |
| |
| DrmHwc *const hwc_; |
| |
| SharedFd present_fence_; |
| |
| std::optional<DrmMode> staged_mode_; |
| int64_t staged_mode_change_time_{}; |
| uint32_t staged_mode_config_id_{}; |
| |
| std::shared_ptr<DrmDisplayPipeline> pipeline_; |
| |
| std::unique_ptr<Backend> backend_; |
| std::shared_ptr<FlatteningController> flatcon_; |
| |
| std::shared_ptr<VSyncWorker> vsync_worker_; |
| bool vsync_event_en_{}; |
| bool vsync_tracking_en_{}; |
| int64_t last_vsync_ts_{}; |
| |
| const hwc2_display_t handle_; |
| HWC2::DisplayType type_; |
| |
| uint32_t layer_idx_{}; |
| |
| std::map<hwc2_layer_t, HwcLayer> layers_; |
| HwcLayer client_layer_; |
| std::unique_ptr<HwcLayer> writeback_layer_; |
| uint16_t virtual_disp_width_{}; |
| uint16_t virtual_disp_height_{}; |
| int32_t color_mode_{}; |
| static constexpr int kCtmRows = 3; |
| static constexpr int kCtmCols = 3; |
| std::shared_ptr<drm_color_ctm> color_matrix_; |
| android_color_transform_t color_transform_hint_{}; |
| |
| std::shared_ptr<DrmKmsPlan> current_plan_; |
| |
| uint32_t frame_no_ = 0; |
| Stats total_stats_; |
| Stats prev_stats_; |
| std::string DumpDelta(HwcDisplay::Stats delta); |
| |
| void SetColorMarixToIdentity(); |
| |
| HWC2::Error Init(); |
| |
| HWC2::Error SetActiveConfigInternal(uint32_t config, int64_t change_time); |
| }; |
| |
| } // namespace android |