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 "drmcomposition.h" 21 #include "drmframebuffer.h" 22 #include "drmhwcomposer.h" 23 #include "queue_worker.h" 24 #include "separate_rects.h" 25 26 #include <chrono> 27 #include <memory> 28 #include <queue> 29 #include <sstream> 30 #include <tuple> 31 32 #include <hardware/hardware.h> 33 #include <hardware/hwcomposer.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 namespace android { 40 41 class GLWorkerCompositor; 42 43 class SquashState { 44 public: 45 static const unsigned kHistoryLength = 6; // TODO: make this number not magic 46 static const unsigned kMaxLayers = 64; 47 48 struct Region { 49 DrmHwcRect<int> rect; 50 std::bitset<kMaxLayers> layer_refs; 51 std::bitset<kHistoryLength> change_history; 52 bool squashed = false; 53 }; 54 55 bool is_stable(int region_index) const { 56 return valid_history_ >= kHistoryLength && 57 regions_[region_index].change_history.none(); 58 } 59 60 const std::vector<Region> ®ions() const { 61 return regions_; 62 } 63 64 void Init(DrmHwcLayer *layers, size_t num_layers); 65 void GenerateHistory(DrmHwcLayer *layers, size_t num_layers, 66 std::vector<bool> &changed_regions) const; 67 void StableRegionsWithMarginalHistory( 68 const std::vector<bool> &changed_regions, 69 std::vector<bool> &stable_regions) const; 70 void RecordHistory(DrmHwcLayer *layers, size_t num_layers, 71 const std::vector<bool> &changed_regions); 72 bool RecordAndCompareSquashed(const std::vector<bool> &squashed_regions); 73 74 void Dump(std::ostringstream *out) const; 75 76 private: 77 size_t generation_number_ = 0; 78 unsigned valid_history_ = 0; 79 std::vector<buffer_handle_t> last_handles_; 80 81 std::vector<Region> regions_; 82 }; 83 84 class DrmDisplayCompositor : public QueueWorker<DrmDisplayComposition> { 85 public: 86 DrmDisplayCompositor(); 87 ~DrmDisplayCompositor(); 88 89 int Init(DrmResources *drm, int display); 90 91 std::unique_ptr<DrmDisplayComposition> CreateComposition() const; 92 int QueueComposition(std::unique_ptr<DrmDisplayComposition> composition); 93 void ProcessWork(std::unique_ptr<DrmDisplayComposition> composition); 94 void ProcessIdle(); 95 int SquashAll(); 96 void Dump(std::ostringstream *out) const; 97 98 std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution(); 99 100 SquashState *squash_state() { 101 return &squash_state_; 102 } 103 104 private: 105 struct FrameState { 106 FrameState(std::unique_ptr<DrmDisplayComposition> composition, int status) 107 : composition(std::move(composition)), status(status) { 108 } 109 110 std::unique_ptr<DrmDisplayComposition> composition; 111 int status = 0; 112 }; 113 114 class FrameWorker : public QueueWorker<FrameState> { 115 public: 116 FrameWorker(DrmDisplayCompositor *compositor); 117 118 int Init(); 119 void QueueFrame(std::unique_ptr<DrmDisplayComposition> composition, 120 int status); 121 122 mutable uint64_t max_duration_us; 123 124 protected: 125 void ProcessWork(std::unique_ptr<FrameState> frame); 126 127 private: 128 DrmDisplayCompositor *compositor_; 129 }; 130 131 struct ModeState { 132 bool needs_modeset = false; 133 DrmMode mode; 134 uint32_t blob_id = 0; 135 uint32_t old_blob_id = 0; 136 }; 137 138 DrmDisplayCompositor(const DrmDisplayCompositor &) = delete; 139 140 // We'll wait for acquire fences to fire for kAcquireWaitTimeoutMs, 141 // kAcquireWaitTries times, logging a warning in between. 142 static const int kAcquireWaitTries = 5; 143 static const int kAcquireWaitTimeoutMs = 100; 144 145 int PrepareFramebuffer(DrmFramebuffer &fb, 146 DrmDisplayComposition *display_comp); 147 int ApplySquash(DrmDisplayComposition *display_comp); 148 int ApplyPreComposite(DrmDisplayComposition *display_comp); 149 int PrepareFrame(DrmDisplayComposition *display_comp); 150 int CommitFrame(DrmDisplayComposition *display_comp, bool test_only); 151 int SquashFrame(DrmDisplayComposition *src, DrmDisplayComposition *dst); 152 int ApplyDpms(DrmDisplayComposition *display_comp); 153 int DisablePlanes(DrmDisplayComposition *display_comp); 154 155 void ClearDisplay(); 156 void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition, 157 int status); 158 159 std::tuple<int, uint32_t> CreateModeBlob(const DrmMode &mode); 160 161 DrmResources *drm_; 162 int display_; 163 164 FrameWorker frame_worker_; 165 166 std::unique_ptr<DrmDisplayComposition> active_composition_; 167 168 bool active_; 169 bool use_hw_overlays_; 170 171 ModeState mode_; 172 173 int framebuffer_index_; 174 DrmFramebuffer framebuffers_[DRM_DISPLAY_BUFFERS]; 175 std::unique_ptr<GLWorkerCompositor> pre_compositor_; 176 177 SquashState squash_state_; 178 int squash_framebuffer_index_; 179 DrmFramebuffer squash_framebuffers_[2]; 180 181 // mutable since we need to acquire in HaveQueuedComposites 182 mutable std::mutex mutex_; 183 184 // State tracking progress since our last Dump(). These are mutable since 185 // we need to reset them on every Dump() call. 186 mutable uint64_t dump_frames_composited_; 187 mutable uint64_t dump_last_timestamp_ns_; 188 mutable uint64_t max_duration_us; 189 }; 190 } 191 192 #endif // ANDROID_DRM_DISPLAY_COMPOSITOR_H_ 193