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
39namespace android {
40
41class GLWorkerCompositor;
42
43class 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> &regions() 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
84class 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