1 /*
2  * Copyright (C) 2015 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 #ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_
18 #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_
19 
20 #include <hardware/hardware.h>
21 #include <hardware/hwcomposer.h>
22 #include <pthread.h>
23 
24 #include <memory>
25 #include <sstream>
26 #include <tuple>
27 
28 #include "DrmDisplayComposition.h"
29 #include "DrmFramebuffer.h"
30 #include "Planner.h"
31 #include "drm/ResourceManager.h"
32 #include "drm/VSyncWorker.h"
33 #include "drmhwcomposer.h"
34 
35 // One for the front, one for the back, and one for cases where we need to
36 // squash a frame that the hw can't display with hw overlays.
37 #define DRM_DISPLAY_BUFFERS 3
38 
39 // If a scene is still for this number of vblanks flatten it to reduce power
40 // consumption.
41 #define FLATTEN_COUNTDOWN_INIT 60
42 
43 namespace android {
44 
45 enum class FlatteningState {
46   kNone,
47   kNotNeeded,
48   kClientRequested,
49   kClientDone,
50   kSerial,
51   kConcurrent
52 };
53 
54 std::ostream &operator<<(std::ostream &str, FlatteningState state);
55 
56 class DrmDisplayCompositor {
57  public:
58   DrmDisplayCompositor();
59   ~DrmDisplayCompositor();
60 
61   int Init(ResourceManager *resource_manager, int display);
62 
63   hwc2_callback_data_t refresh_callback_data_ = NULL;
64   HWC2_PFN_REFRESH refresh_callback_hook_ = NULL;
65   std::mutex refresh_callback_lock;
66 
SetRefreshCallback(hwc2_callback_data_t data,hwc2_function_pointer_t hook)67   void SetRefreshCallback(hwc2_callback_data_t data,
68                           hwc2_function_pointer_t hook) {
69     const std::lock_guard<std::mutex> lock(refresh_callback_lock);
70     refresh_callback_data_ = data;
71     refresh_callback_hook_ = reinterpret_cast<HWC2_PFN_REFRESH>(hook);
72   }
73 
74   std::unique_ptr<DrmDisplayComposition> CreateComposition() const;
75   std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const;
76   int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition);
77   int TestComposition(DrmDisplayComposition *composition);
78   int Composite();
79   void Dump(std::ostringstream *out) const;
80   void Vsync(int display, int64_t timestamp);
81   void ClearDisplay();
TakeOutFence()82   int TakeOutFence() {
83     if (!active_composition_)
84       return -1;
85     return active_composition_->take_out_fence();
86   }
87 
88   FlatteningState GetFlatteningState() const;
89   uint32_t GetFlattenedFramesCount() const;
90   bool ShouldFlattenOnClient() const;
91 
92   std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
93 
94  private:
95   struct ModeState {
96     bool needs_modeset = false;
97     DrmMode mode;
98     uint32_t blob_id = 0;
99     uint32_t old_blob_id = 0;
100   };
101 
102   DrmDisplayCompositor(const DrmDisplayCompositor &) = delete;
103 
104   // We'll wait for acquire fences to fire for kAcquireWaitTimeoutMs,
105   // kAcquireWaitTries times, logging a warning in between.
106   static const int kAcquireWaitTries = 5;
107   static const int kAcquireWaitTimeoutMs = 100;
108 
109   int CommitFrame(DrmDisplayComposition *display_comp, bool test_only,
110                   DrmConnector *writeback_conn = NULL,
111                   DrmHwcBuffer *writeback_buffer = NULL);
112   int SetupWritebackCommit(drmModeAtomicReqPtr pset, uint32_t crtc_id,
113                            DrmConnector *writeback_conn,
114                            DrmHwcBuffer *writeback_buffer);
115   int ApplyDpms(DrmDisplayComposition *display_comp);
116   int DisablePlanes(DrmDisplayComposition *display_comp);
117 
118   void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
119                   int status, bool writeback = false);
120 
121   void SetFlattening(FlatteningState new_state);
122   bool IsFlatteningNeeded() const;
123   int FlattenActiveComposition();
124   int FlattenOnClient();
125   int FlattenSerial(DrmConnector *writeback_conn);
126   int FlattenConcurrent(DrmConnector *writeback_conn);
127   int FlattenOnDisplay(std::unique_ptr<DrmDisplayComposition> &src,
128                        DrmConnector *writeback_conn, DrmMode &src_mode,
129                        DrmHwcLayer *writeback_layer);
130 
131   bool CountdownExpired() const;
132 
133   std::tuple<int, uint32_t> CreateModeBlob(const DrmMode &mode);
134 
135   ResourceManager *resource_manager_;
136   int display_;
137 
138   std::unique_ptr<DrmDisplayComposition> active_composition_;
139 
140   bool initialized_;
141   bool active_;
142   bool use_hw_overlays_;
143 
144   ModeState mode_;
145 
146   int framebuffer_index_;
147   DrmFramebuffer framebuffers_[DRM_DISPLAY_BUFFERS];
148 
149   // mutable since we need to acquire in Dump()
150   mutable pthread_mutex_t lock_;
151 
152   // State tracking progress since our last Dump(). These are mutable since
153   // we need to reset them on every Dump() call.
154   mutable uint64_t dump_frames_composited_;
155   mutable uint64_t dump_last_timestamp_ns_;
156   VSyncWorker vsync_worker_;
157   int64_t flatten_countdown_;
158   std::unique_ptr<Planner> planner_;
159   int writeback_fence_;
160 
161   FlatteningState flattening_state_;
162   uint32_t frames_flattened_;
163 
164   std::function<void(int)> refresh_display_cb_;
165 };
166 }  // namespace android
167 
168 #endif  // ANDROID_DRM_DISPLAY_COMPOSITOR_H_
169