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 "drmhwcomposer.h" 21 #include "drmcomposition.h" 22 #include "drmcompositorworker.h" 23 #include "drmframebuffer.h" 24 #include "separate_rects.h" 25 26 #include <pthread.h> 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 is_stable(int region_index)55 bool is_stable(int region_index) const { 56 return valid_history_ >= kHistoryLength && 57 regions_[region_index].change_history.none(); 58 } 59 regions()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 { 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 int Composite(); 94 int SquashAll(); 95 void Dump(std::ostringstream *out) const; 96 97 std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution(); 98 99 bool HaveQueuedComposites() const; 100 squash_state()101 SquashState *squash_state() { 102 return &squash_state_; 103 } 104 105 private: 106 struct FrameState { 107 std::unique_ptr<DrmDisplayComposition> composition; 108 int status = 0; 109 }; 110 111 class FrameWorker : public Worker { 112 public: 113 FrameWorker(DrmDisplayCompositor *compositor); 114 ~FrameWorker() override; 115 116 int Init(); 117 void QueueFrame(std::unique_ptr<DrmDisplayComposition> composition, 118 int status); 119 120 protected: 121 void Routine() override; 122 123 private: 124 DrmDisplayCompositor *compositor_; 125 std::queue<FrameState> frame_queue_; 126 }; 127 128 struct ModeState { 129 bool needs_modeset = false; 130 DrmMode mode; 131 uint32_t blob_id = 0; 132 uint32_t old_blob_id = 0; 133 }; 134 135 DrmDisplayCompositor(const DrmDisplayCompositor &) = delete; 136 137 // We'll wait for acquire fences to fire for kAcquireWaitTimeoutMs, 138 // kAcquireWaitTries times, logging a warning in between. 139 static const int kAcquireWaitTries = 5; 140 static const int kAcquireWaitTimeoutMs = 100; 141 142 int PrepareFramebuffer(DrmFramebuffer &fb, 143 DrmDisplayComposition *display_comp); 144 int ApplySquash(DrmDisplayComposition *display_comp); 145 int ApplyPreComposite(DrmDisplayComposition *display_comp); 146 int PrepareFrame(DrmDisplayComposition *display_comp); 147 int CommitFrame(DrmDisplayComposition *display_comp, bool test_only); 148 int SquashFrame(DrmDisplayComposition *src, DrmDisplayComposition *dst); 149 int ApplyDpms(DrmDisplayComposition *display_comp); 150 int DisablePlanes(DrmDisplayComposition *display_comp); 151 152 void ClearDisplay(); 153 void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition, 154 int status); 155 156 std::tuple<int, uint32_t> CreateModeBlob(const DrmMode &mode); 157 158 DrmResources *drm_; 159 int display_; 160 161 DrmCompositorWorker worker_; 162 FrameWorker frame_worker_; 163 164 std::queue<std::unique_ptr<DrmDisplayComposition>> composite_queue_; 165 std::unique_ptr<DrmDisplayComposition> active_composition_; 166 167 bool initialized_; 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 pthread_mutex_t lock_; 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 }; 189 } 190 191 #endif // ANDROID_DRM_DISPLAY_COMPOSITOR_H_ 192