OSDN Git Service

83f97618f96b9fc4ba7e67cd1631649cfc3ea5b4
[android-x86/external-IA-Hardware-Composer.git] / common / compositor / compositor.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
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 #include "compositor.h"
18
19 #include <xf86drmMode.h>
20
21 #include <algorithm>
22
23 #include "disjoint_layers.h"
24 #include "displayplanestate.h"
25 #include "hwctrace.h"
26 #include "nativegpuresource.h"
27 #include "nativesurface.h"
28 #include "overlaylayer.h"
29 #include "renderer.h"
30 #include "hwcutils.h"
31
32 namespace hwcomposer {
33
34 Compositor::Compositor() {
35 }
36
37 Compositor::~Compositor() {
38 }
39
40 void Compositor::Init(DisplayPlaneManager *plane_manager) {
41   if (!thread_)
42     thread_.reset(new CompositorThread());
43
44   thread_->Initialize(plane_manager);
45 }
46
47 void Compositor::EnsureTasksAreDone() {
48   thread_->EnsureTasksAreDone();
49 }
50
51 bool Compositor::BeginFrame(bool disable_explicit_sync) {
52   thread_->SetExplicitSyncSupport(disable_explicit_sync);
53   return true;
54 }
55
56 void Compositor::Reset() {
57   thread_->ExitThread();
58 }
59
60 bool Compositor::Draw(DisplayPlaneStateList &comp_planes,
61                       std::vector<OverlayLayer> &layers,
62                       const std::vector<HwcRect<int>> &display_frame) {
63   CTRACE();
64   const DisplayPlaneState *comp = NULL;
65   std::vector<size_t> dedicated_layers;
66   std::vector<DrawState> draw_state;
67
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) {
75       comp = &plane;
76       std::vector<CompositionRegion> &comp_regions =
77           plane.GetCompositionRegion();
78       if (comp_regions.empty()) {
79         SeparateLayers(dedicated_layers, comp->source_layers(), display_frame,
80                        comp_regions);
81       }
82
83       std::vector<size_t>().swap(dedicated_layers);
84       if (comp_regions.empty())
85         continue;
86
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.");
95         return false;
96       }
97
98       if (state.states_.empty()) {
99         draw_state.pop_back();
100       }
101     }
102   }
103
104   if (draw_state.empty())
105     return true;
106
107   thread_->Draw(draw_state, layers);
108   return true;
109 }
110
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,
120                  comp_regions);
121   if (comp_regions.empty()) {
122     ETRACE(
123         "Failed to prepare offscreen buffer. "
124         "error: %s",
125         PRINTERROR());
126     return false;
127   }
128
129   NativeSurface *surface = CreateBackBuffer(width, height);
130   surface->InitializeForOffScreenRendering(buffer_handler, output_handle);
131   std::vector<DrawState> draw;
132   draw.emplace_back();
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.");
141     return false;
142   }
143
144   if (draw_state.states_.empty()) {
145     return true;
146   }
147
148   if (acquire_fence > 0) {
149     draw_state.acquire_fences_.emplace_back(acquire_fence);
150   }
151
152   thread_->Draw(draw, layers);
153   *retire_fence = draw_state.retire_fence_;
154
155   return true;
156 }
157
158 void Compositor::FreeResources(bool all_resources) {
159   thread_->FreeResources(all_resources);
160 }
161
162 bool Compositor::CalculateRenderState(
163     std::vector<OverlayLayer> &layers,
164     const std::vector<CompositionRegion> &comp_regions, DrawState &draw_state) {
165   CTRACE();
166   size_t num_regions = comp_regions.size();
167   for (size_t region_index = 0; region_index < num_regions; region_index++) {
168     const CompositionRegion &region = comp_regions.at(region_index);
169     RenderState state;
170     state.ConstructState(layers, region,
171                          draw_state.surface_->GetSurfaceDamage(),
172                          draw_state.clear_surface_);
173     if (state.layer_state_.empty()) {
174       continue;
175     }
176
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();
182       if (fence > 0) {
183         draw_state.acquire_fences_.emplace_back(fence);
184       }
185     }
186   }
187
188   return true;
189 }
190
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)
198     if (in & mask)
199       out.emplace_back(index_map[i]);
200   return out;
201 }
202
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) {
207   CTRACE();
208   if (source_layers.size() > 64) {
209     ETRACE("Failed to separate layers because there are more than 64");
210     return;
211   }
212
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) {
217     WTRACE(
218         "Exclusion rectangles are being truncated to make the rectangle count "
219         "fit into 64");
220     num_exclude_rects = 64 - source_layers.size() - dedicated_layers.size();
221   }
222
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);
229   std::transform(
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];
236   });
237
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;
243
244   for (RectSet<int> &region : separate_regions) {
245     if (region.id_set.getBits() & exclude_mask)
246       continue;
247
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
252     // be occluded.
253     uint64_t dedicated_intersect = region.id_set.getBits() & dedicated_mask;
254     for (size_t i = 0; dedicated_intersect && i < dedicated_layers.size();
255          ++i) {
256       // Only exclude layers if they intersect this particular dedicated layer
257       if (!(dedicated_intersect & (1 << (i + num_exclude_rects))))
258         continue;
259
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);
263       }
264     }
265     if (!(region.id_set.getBits() >> layer_offset))
266       continue;
267
268     comp_regions.emplace_back(CompositionRegion{
269         region.rect, SetBitsToVector(region.id_set.getBits() >> layer_offset,
270                                      source_layers)});
271   }
272 }
273
274 }  // namespace hwcomposer