2 // Copyright (c) 2016 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "compositor.h"
19 #include <xf86drmMode.h>
23 #include "disjoint_layers.h"
24 #include "displayplanestate.h"
26 #include "nativegpuresource.h"
27 #include "nativesurface.h"
28 #include "overlaylayer.h"
32 namespace hwcomposer {
34 Compositor::Compositor() {
37 Compositor::~Compositor() {
40 void Compositor::Init(DisplayPlaneManager *plane_manager) {
42 thread_.reset(new CompositorThread());
44 thread_->Initialize(plane_manager);
47 void Compositor::EnsureTasksAreDone() {
48 thread_->EnsureTasksAreDone();
51 bool Compositor::BeginFrame(bool disable_explicit_sync) {
52 thread_->SetExplicitSyncSupport(disable_explicit_sync);
56 void Compositor::Reset() {
57 thread_->ExitThread();
60 bool Compositor::Draw(DisplayPlaneStateList &comp_planes,
61 std::vector<OverlayLayer> &layers,
62 const std::vector<HwcRect<int>> &display_frame) {
64 const DisplayPlaneState *comp = NULL;
65 std::vector<size_t> dedicated_layers;
66 std::vector<DrawState> draw_state;
68 for (DisplayPlaneState &plane : comp_planes) {
69 if (plane.GetCompositionState() == DisplayPlaneState::State::kScanout) {
70 dedicated_layers.insert(dedicated_layers.end(),
71 plane.source_layers().begin(),
72 plane.source_layers().end());
73 } else if (plane.GetCompositionState() ==
74 DisplayPlaneState::State::kRender) {
76 std::vector<CompositionRegion> &comp_regions =
77 plane.GetCompositionRegion();
78 if (comp_regions.empty()) {
79 SeparateLayers(dedicated_layers, comp->source_layers(), display_frame,
83 std::vector<size_t>().swap(dedicated_layers);
84 if (comp_regions.empty())
87 draw_state.emplace_back();
88 DrawState &state = draw_state.back();
89 state.clear_surface_ = plane.ClearSurface();
90 state.surface_ = plane.GetOffScreenTarget();
91 size_t num_regions = comp_regions.size();
92 state.states_.reserve(num_regions);
93 if (!CalculateRenderState(layers, comp_regions, state)) {
94 ETRACE("Failed to calculate Render state.");
98 if (state.states_.empty()) {
99 draw_state.pop_back();
104 if (draw_state.empty())
107 thread_->Draw(draw_state, layers);
111 bool Compositor::DrawOffscreen(std::vector<OverlayLayer> &layers,
112 const std::vector<HwcRect<int>> &display_frame,
113 const std::vector<size_t> &source_layers,
114 NativeBufferHandler *buffer_handler,
115 uint32_t width, uint32_t height,
116 HWCNativeHandle output_handle,
117 int32_t acquire_fence, int32_t *retire_fence) {
118 std::vector<CompositionRegion> comp_regions;
119 SeparateLayers(std::vector<size_t>(), source_layers, display_frame,
121 if (comp_regions.empty()) {
123 "Failed to prepare offscreen buffer. "
129 NativeSurface *surface = CreateBackBuffer(width, height);
130 surface->InitializeForOffScreenRendering(buffer_handler, output_handle);
131 std::vector<DrawState> draw;
133 DrawState &draw_state = draw.back();
134 draw_state.clear_surface_ = true;
135 draw_state.destroy_surface_ = true;
136 draw_state.surface_ = surface;
137 size_t num_regions = comp_regions.size();
138 draw_state.states_.reserve(num_regions);
139 if (!CalculateRenderState(layers, comp_regions, draw_state)) {
140 ETRACE("Failed to calculate render state.");
144 if (draw_state.states_.empty()) {
148 if (acquire_fence > 0) {
149 draw_state.acquire_fences_.emplace_back(acquire_fence);
152 thread_->Draw(draw, layers);
153 *retire_fence = draw_state.retire_fence_;
158 void Compositor::FreeResources(bool all_resources) {
159 thread_->FreeResources(all_resources);
162 bool Compositor::CalculateRenderState(
163 std::vector<OverlayLayer> &layers,
164 const std::vector<CompositionRegion> &comp_regions, DrawState &draw_state) {
166 size_t num_regions = comp_regions.size();
167 for (size_t region_index = 0; region_index < num_regions; region_index++) {
168 const CompositionRegion ®ion = comp_regions.at(region_index);
170 state.ConstructState(layers, region,
171 draw_state.surface_->GetSurfaceDamage(),
172 draw_state.clear_surface_);
173 if (state.layer_state_.empty()) {
177 draw_state.states_.emplace(draw_state.states_.begin(), state);
178 const std::vector<size_t> &source = region.source_layers;
179 for (size_t texture_index : source) {
180 OverlayLayer &layer = layers.at(texture_index);
181 int32_t fence = layer.ReleaseAcquireFence();
183 draw_state.acquire_fences_.emplace_back(fence);
191 // Below code is taken from drm_hwcomposer adopted to our needs.
192 static std::vector<size_t> SetBitsToVector(
193 uint64_t in, const std::vector<size_t> &index_map) {
194 std::vector<size_t> out;
195 size_t msb = sizeof(in) * 8 - 1;
196 uint64_t mask = (uint64_t)1 << msb;
197 for (size_t i = msb; mask != (uint64_t)0; i--, mask >>= 1)
199 out.emplace_back(index_map[i]);
203 void Compositor::SeparateLayers(const std::vector<size_t> &dedicated_layers,
204 const std::vector<size_t> &source_layers,
205 const std::vector<HwcRect<int>> &display_frame,
206 std::vector<CompositionRegion> &comp_regions) {
208 if (source_layers.size() > 64) {
209 ETRACE("Failed to separate layers because there are more than 64");
213 size_t num_exclude_rects = 0;
214 // Index at which the actual layers begin
215 size_t layer_offset = dedicated_layers.size();
216 if (source_layers.size() + layer_offset > 64) {
218 "Exclusion rectangles are being truncated to make the rectangle count "
220 num_exclude_rects = 64 - source_layers.size() - dedicated_layers.size();
223 // We inject all the exclude rects into the rects list. Any resulting rect
224 // that includes ANY of the first num_exclude_rects is rejected. After the
225 // exclude rects, we add the lower layers. The rects that intersect with
226 // these layers will be inspected and only those which are to be composited
227 // above the layer will be included in the composition regions.
228 std::vector<HwcRect<int>> layer_rects(source_layers.size() + layer_offset);
230 dedicated_layers.begin(), dedicated_layers.end(),
231 layer_rects.begin() + num_exclude_rects,
232 [=](size_t layer_index) { return display_frame[layer_index]; });
233 std::transform(source_layers.begin(), source_layers.end(),
234 layer_rects.begin() + layer_offset, [=](size_t layer_index) {
235 return display_frame[layer_index];
238 std::vector<RectSet<int>> separate_regions;
239 get_draw_regions(layer_rects, &separate_regions);
240 uint64_t exclude_mask = ((uint64_t)1 << num_exclude_rects) - 1;
241 uint64_t dedicated_mask = (((uint64_t)1 << dedicated_layers.size()) - 1)
242 << num_exclude_rects;
244 for (RectSet<int> ®ion : separate_regions) {
245 if (region.id_set.getBits() & exclude_mask)
248 // If a rect intersects one of the dedicated layers, we need to remove the
249 // layers from the composition region which appear *below* the dedicated
250 // layer. This effectively punches a hole through the composition layer such
251 // that the dedicated layer can be placed below the composition and not
253 uint64_t dedicated_intersect = region.id_set.getBits() & dedicated_mask;
254 for (size_t i = 0; dedicated_intersect && i < dedicated_layers.size();
256 // Only exclude layers if they intersect this particular dedicated layer
257 if (!(dedicated_intersect & (1 << (i + num_exclude_rects))))
260 for (size_t j = 0; j < source_layers.size(); ++j) {
261 if (source_layers[j] < dedicated_layers[i])
262 region.id_set.subtract(j + layer_offset);
265 if (!(region.id_set.getBits() >> layer_offset))
268 comp_regions.emplace_back(CompositionRegion{
269 region.rect, SetBitsToVector(region.id_set.getBits() >> layer_offset,
274 } // namespace hwcomposer