• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <hardware/hwcomposer2.h>
20 
21 #include <atomic>
22 #include <optional>
23 #include <sstream>
24 
25 #include <ui/GraphicTypes.h>
26 
27 #include "HwcDisplayConfigs.h"
28 #include "compositor/DisplayInfo.h"
29 #include "compositor/FlatteningController.h"
30 #include "compositor/LayerData.h"
31 #include "drm/DrmAtomicStateManager.h"
32 #include "drm/ResourceManager.h"
33 #include "drm/VSyncWorker.h"
34 #include "hwc2_device/HwcLayer.h"
35 
36 namespace android {
37 
38 class Backend;
39 class DrmHwc;
40 
41 class FrontendDisplayBase {
42  public:
43   virtual ~FrontendDisplayBase() = default;
44 };
45 
46 inline constexpr uint32_t kPrimaryDisplay = 0;
47 
48 // NOLINTNEXTLINE
49 class HwcDisplay {
50  public:
51   enum ConfigError {
52     kNone,
53     kBadConfig,
54     kSeamlessNotAllowed,
55     kSeamlessNotPossible,
56     kConfigFailed,
57   };
58 
59   HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwc *hwc);
60   HwcDisplay(const HwcDisplay &) = delete;
61   ~HwcDisplay();
62 
63   void SetColorTransformMatrix(
64       const std::array<float, 16> &color_transform_matrix);
65 
66   /* SetPipeline should be carefully used only by DrmHwcTwo hotplug handlers */
67   void SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline);
68 
69   HWC2::Error CreateComposition(AtomicCommitArgs &a_args);
70   std::vector<HwcLayer *> GetOrderLayersByZPos();
71 
72   void ClearDisplay();
73 
74   std::string Dump();
75 
GetDisplayConfigs()76   const HwcDisplayConfigs &GetDisplayConfigs() const {
77     return configs_;
78   }
79 
80   // Get the config representing the mode that has been committed to KMS.
81   auto GetCurrentConfig() const -> const HwcDisplayConfig *;
82 
83   // Get the config that was last requested through SetActiveConfig and similar
84   // functions. This may differ from the GetCurrentConfig if the config change
85   // is queued up to take effect in the future.
86   auto GetLastRequestedConfig() const -> const HwcDisplayConfig *;
87 
88   // Set a config synchronously. If the requested config fails to be committed,
89   // this will return with an error. Otherwise, the config will have been
90   // committed to the kernel on successful return.
91   ConfigError SetConfig(hwc2_config_t config);
92 
93   // Queue a configuration change to take effect in the future.
94   auto QueueConfig(hwc2_config_t config, int64_t desired_time, bool seamless,
95                    QueuedConfigTiming *out_timing) -> ConfigError;
96 
97   // Get the HwcDisplayConfig, or nullptor if none.
98   auto GetConfig(hwc2_config_t config_id) const -> const HwcDisplayConfig *;
99 
100   auto GetDisplayBoundsMm() -> std::pair<int32_t, int32_t>;
101 
102   // To be called after SetDisplayProperties. Returns an empty vector if the
103   // requested layers have been validated, otherwise the vector describes
104   // the requested composition type changes.
105   using ChangedLayer = std::pair<ILayerId, HWC2::Composition>;
106   auto ValidateStagedComposition() -> std::vector<ChangedLayer>;
107 
108   // Mark previously validated properties as ready to present.
109   auto AcceptValidatedComposition() -> void;
110 
111   using ReleaseFence = std::pair<ILayerId, SharedFd>;
112   // Present previously staged properties, and return fences to indicate when
113   // the new content has been presented, and when the previous buffers have
114   // been released. If |desired_present_time| is set, ensure that the
115   // composition is presented at the closest vsync to that requested time.
116   // Otherwise, present immediately.
117   auto PresentStagedComposition(std::optional<int64_t> desired_present_time,
118                                 SharedFd &out_present_fence,
119                                 std::vector<ReleaseFence> &out_release_fences)
120       -> bool;
121 
122   auto GetFrontendPrivateData() -> std::shared_ptr<FrontendDisplayBase> {
123     return frontend_private_data_;
124   }
125 
SetFrontendPrivateData(std::shared_ptr<FrontendDisplayBase> data)126   auto SetFrontendPrivateData(std::shared_ptr<FrontendDisplayBase> data) {
127     frontend_private_data_ = std::move(data);
128   }
129 
130   auto CreateLayer(ILayerId new_layer_id) -> bool;
131   auto DestroyLayer(ILayerId layer_id) -> bool;
132 
133   // HWC2 Hooks - these should not be used outside of the hwc2 device.
134   HWC2::Error GetActiveConfig(hwc2_config_t *config) const;
135   HWC2::Error GetColorModes(uint32_t *num_modes, int32_t *modes);
136   HWC2::Error GetDisplayAttribute(hwc2_config_t config, int32_t attribute,
137                                   int32_t *value);
138   HWC2::Error LegacyGetDisplayConfigs(uint32_t *num_configs,
139                                       hwc2_config_t *configs);
140   HWC2::Error GetDisplayName(uint32_t *size, char *name);
141   HWC2::Error GetDisplayType(int32_t *type);
142 #if __ANDROID_API__ > 27
143   HWC2::Error GetRenderIntents(int32_t mode, uint32_t *outNumIntents,
144                                int32_t *outIntents);
145   HWC2::Error SetColorModeWithIntent(int32_t mode, int32_t intent);
146 #endif
147 #if __ANDROID_API__ > 28
148   HWC2::Error GetDisplayIdentificationData(uint8_t *outPort,
149                                            uint32_t *outDataSize,
150                                            uint8_t *outData);
151   HWC2::Error GetDisplayCapabilities(uint32_t *outNumCapabilities,
152                                      uint32_t *outCapabilities);
153 #endif
154 #if __ANDROID_API__ > 29
155   HWC2::Error GetDisplayConnectionType(uint32_t *outType);
156 
157   HWC2::Error SetActiveConfigWithConstraints(
158       hwc2_config_t config,
159       hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
160       hwc_vsync_period_change_timeline_t *outTimeline);
161 
162   HWC2::Error SetContentType(int32_t contentType);
163 #endif
164   HWC2::Error GetDisplayVsyncPeriod(uint32_t *outVsyncPeriod);
165 
166   HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
167                                  float *max_luminance,
168                                  float *max_average_luminance,
169                                  float *min_luminance);
170   HWC2::Error SetActiveConfig(hwc2_config_t config);
171   HWC2::Error ChosePreferredConfig();
172   HWC2::Error SetColorMode(int32_t mode);
173   HWC2::Error SetColorTransform(const float *matrix, int32_t hint);
174   HWC2::Error SetPowerMode(int32_t mode);
175   HWC2::Error SetVsyncEnabled(int32_t enabled);
get_layer(ILayerId layer)176   HwcLayer *get_layer(ILayerId layer) {
177     auto it = layers_.find(layer);
178     if (it == layers_.end())
179       return nullptr;
180     return &it->second;
181   }
182 
183   /* Statistics */
184   struct Stats {
minusStats185     Stats minus(Stats b) const {
186       return {total_frames_ - b.total_frames_,
187               total_pixops_ - b.total_pixops_,
188               gpu_pixops_ - b.gpu_pixops_,
189               failed_kms_validate_ - b.failed_kms_validate_,
190               failed_kms_present_ - b.failed_kms_present_,
191               frames_flattened_ - b.frames_flattened_};
192     }
193 
194     uint32_t total_frames_ = 0;
195     uint64_t total_pixops_ = 0;
196     uint64_t gpu_pixops_ = 0;
197     uint32_t failed_kms_validate_ = 0;
198     uint32_t failed_kms_present_ = 0;
199     uint32_t frames_flattened_ = 0;
200   };
201 
202   const Backend *backend() const;
203   void set_backend(std::unique_ptr<Backend> backend);
204 
GetHwc()205   auto GetHwc() {
206     return hwc_;
207   }
208 
209   auto layers() -> std::map<ILayerId, HwcLayer> & {
210     return layers_;
211   }
212 
GetPipe()213   auto &GetPipe() {
214     return *pipeline_;
215   }
216 
217   bool CtmByGpu();
218 
total_stats()219   Stats &total_stats() {
220     return total_stats_;
221   }
222 
223   /* Headless mode required to keep SurfaceFlinger alive when all display are
224    * disconnected, Without headless mode Android will continuously crash.
225    * Only single internal (primary) display is required to be in HEADLESS mode
226    * to prevent the crash. See:
227    * https://source.android.com/devices/graphics/hotplug#handling-common-scenarios
228    */
IsInHeadlessMode()229   bool IsInHeadlessMode() {
230     return !pipeline_;
231   }
232 
233   void Deinit();
234 
GetFlatCon()235   auto GetFlatCon() {
236     return flatcon_;
237   }
238 
239   auto GetClientLayer() -> HwcLayer & {
240     return client_layer_;
241   }
242 
GetWritebackLayer()243   auto &GetWritebackLayer() {
244     return writeback_layer_;
245   }
246 
SetVirtualDisplayResolution(uint16_t width,uint16_t height)247   void SetVirtualDisplayResolution(uint16_t width, uint16_t height) {
248     virtual_disp_width_ = width;
249     virtual_disp_height_ = height;
250   }
251 
252   auto getDisplayPhysicalOrientation() -> std::optional<PanelOrientation>;
253 
254   bool NeedsClientLayerUpdate() const;
255 
256  private:
257   AtomicCommitArgs CreateModesetCommit(
258       const HwcDisplayConfig *config,
259       const std::optional<LayerData> &modeset_layer);
260 
261   // Sleep the current thread until |present_time| is closest to the next
262   // expected vsync time.
263   void WaitForPresentTime(int64_t present_time, uint32_t vsync_period_ns);
264 
265   HwcDisplayConfigs configs_;
266 
267   DrmHwc *const hwc_;
268 
269   int64_t staged_mode_change_time_{};
270   std::optional<uint32_t> staged_mode_config_id_{};
271 
272   std::shared_ptr<DrmDisplayPipeline> pipeline_;
273 
274   std::unique_ptr<Backend> backend_;
275   std::shared_ptr<FlatteningController> flatcon_;
276 
277   std::unique_ptr<VSyncWorker> vsync_worker_;
278   bool vsync_event_en_{};
279 
280   const hwc2_display_t handle_;
281   HWC2::DisplayType type_;
282 
283   std::map<ILayerId, HwcLayer> layers_;
284   HwcLayer client_layer_;
285   std::unique_ptr<HwcLayer> writeback_layer_;
286   uint16_t virtual_disp_width_{};
287   uint16_t virtual_disp_height_{};
288   int32_t color_mode_{};
289   std::shared_ptr<drm_color_ctm> color_matrix_;
290   std::shared_ptr<drm_color_ctm> identity_color_matrix_;
291   android_color_transform_t color_transform_hint_{};
292   bool ctm_has_offset_ = false;
293   int32_t content_type_{};
294   Colorspace colorspace_{};
295   int32_t min_bpc_{};
296   std::shared_ptr<hdr_output_metadata> hdr_metadata_;
297 
298   std::shared_ptr<DrmKmsPlan> current_plan_;
299 
300   uint32_t frame_no_ = 0;
301   Stats total_stats_;
302   Stats prev_stats_;
303   std::string DumpDelta(HwcDisplay::Stats delta);
304 
305   void SetColorMatrixToIdentity();
306 
307   HWC2::Error Init();
308 
309   HWC2::Error SetActiveConfigInternal(uint32_t config, int64_t change_time);
310   HWC2::Error SetHdrOutputMetadata(ui::Hdr hdrType);
311   HWC2::Error SetOutputType(uint32_t hdr_output_type);
312 
313   auto GetEdid() -> EdidWrapperUnique & {
314     return GetPipe().connector->Get()->GetParsedEdid();
315   }
316 
317   std::shared_ptr<FrontendDisplayBase> frontend_private_data_;
318 };
319 
320 }  // namespace android
321