blob: 14b87aa96bfdaf5b0bd87f0e88e7382d112584e7 [file] [log] [blame]
Sean Paul98e73c82015-06-24 14:38:49 -07001/*
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#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18#define LOG_TAG "hwc-drm-display-compositor"
19
20#include "drmdisplaycompositor.h"
Zach Reiznerbff33ac2015-11-16 11:08:46 -080021
Zach Reiznerbff33ac2015-11-16 11:08:46 -080022#include <sched.h>
23#include <stdlib.h>
24#include <time.h>
Adrian Salido0e892682017-03-01 14:57:39 -080025#include <algorithm>
26#include <bitset>
27#include <cinttypes>
28#include <mutex>
Zach Reiznerbff33ac2015-11-16 11:08:46 -080029#include <sstream>
30#include <vector>
31
32#include <cutils/log.h>
33#include <drm/drm_mode.h>
34#include <sync/sync.h>
35#include <utils/Trace.h>
36
Sean Paul98e73c82015-06-24 14:38:49 -070037#include "drmcrtc.h"
38#include "drmplane.h"
39#include "drmresources.h"
Zach Reizner713a6782015-07-31 15:12:44 -070040#include "glworker.h"
Sean Paul98e73c82015-06-24 14:38:49 -070041
Haixia Shidda2fab2015-10-22 18:12:49 -070042#define DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH 2
Zach Reiznerd410f042015-07-28 15:33:07 -070043
Sean Paul98e73c82015-06-24 14:38:49 -070044namespace android {
45
Adrian Salido0e892682017-03-01 14:57:39 -080046static const int64_t kSquashWait = 500LL;
47
Zach Reizner92f8e632015-10-12 17:47:13 -070048void SquashState::Init(DrmHwcLayer *layers, size_t num_layers) {
49 generation_number_++;
50 valid_history_ = 0;
51 regions_.clear();
52 last_handles_.clear();
53
54 std::vector<DrmHwcRect<int>> in_rects;
55 for (size_t i = 0; i < num_layers; i++) {
56 DrmHwcLayer *layer = &layers[i];
57 in_rects.emplace_back(layer->display_frame);
58 last_handles_.push_back(layer->sf_handle);
59 }
60
Haixia Shiaa2f4a52015-11-02 10:54:29 -080061 std::vector<separate_rects::RectSet<uint64_t, int>> out_regions;
62 separate_rects::separate_rects_64(in_rects, &out_regions);
Zach Reizner92f8e632015-10-12 17:47:13 -070063
Haixia Shiaa2f4a52015-11-02 10:54:29 -080064 for (const separate_rects::RectSet<uint64_t, int> &out_region : out_regions) {
Zach Reizner92f8e632015-10-12 17:47:13 -070065 regions_.emplace_back();
66 Region &region = regions_.back();
67 region.rect = out_region.rect;
68 region.layer_refs = out_region.id_set.getBits();
69 }
70}
71
Zach Reizner5757e822015-10-16 19:06:31 -070072void SquashState::GenerateHistory(DrmHwcLayer *layers, size_t num_layers,
Zach Reizner92f8e632015-10-12 17:47:13 -070073 std::vector<bool> &changed_regions) const {
Zach Reizner5757e822015-10-16 19:06:31 -070074 changed_regions.resize(regions_.size());
75 if (num_layers != last_handles_.size()) {
76 ALOGE("SquashState::GenerateHistory expected %zu layers but got %zu layers",
77 last_handles_.size(), num_layers);
78 return;
79 }
Zach Reizner92f8e632015-10-12 17:47:13 -070080 std::bitset<kMaxLayers> changed_layers;
81 for (size_t i = 0; i < last_handles_.size(); i++) {
82 DrmHwcLayer *layer = &layers[i];
Zach Reiznerdb81fce2015-10-27 16:18:06 -070083 // Protected layers can't be squashed so we treat them as constantly
84 // changing.
85 if (layer->protected_usage() || last_handles_[i] != layer->sf_handle)
Zach Reizner92f8e632015-10-12 17:47:13 -070086 changed_layers.set(i);
Zach Reizner92f8e632015-10-12 17:47:13 -070087 }
88
Zach Reizner92f8e632015-10-12 17:47:13 -070089 for (size_t i = 0; i < regions_.size(); i++) {
90 changed_regions[i] = (regions_[i].layer_refs & changed_layers).any();
91 }
92}
93
94void SquashState::StableRegionsWithMarginalHistory(
95 const std::vector<bool> &changed_regions,
96 std::vector<bool> &stable_regions) const {
97 stable_regions.resize(regions_.size());
98 for (size_t i = 0; i < regions_.size(); i++) {
99 stable_regions[i] = !changed_regions[i] && is_stable(i);
100 }
101}
102
Zach Reizner5757e822015-10-16 19:06:31 -0700103void SquashState::RecordHistory(DrmHwcLayer *layers, size_t num_layers,
Zach Reizner92f8e632015-10-12 17:47:13 -0700104 const std::vector<bool> &changed_regions) {
Zach Reizner5757e822015-10-16 19:06:31 -0700105 if (num_layers != last_handles_.size()) {
106 ALOGE("SquashState::RecordHistory expected %zu layers but got %zu layers",
107 last_handles_.size(), num_layers);
108 return;
109 }
110 if (changed_regions.size() != regions_.size()) {
111 ALOGE("SquashState::RecordHistory expected %zu regions but got %zu regions",
112 regions_.size(), changed_regions.size());
113 return;
114 }
115
Zach Reizner92f8e632015-10-12 17:47:13 -0700116 for (size_t i = 0; i < last_handles_.size(); i++) {
117 DrmHwcLayer *layer = &layers[i];
118 last_handles_[i] = layer->sf_handle;
119 }
120
121 for (size_t i = 0; i < regions_.size(); i++) {
122 regions_[i].change_history <<= 1;
123 regions_[i].change_history.set(/* LSB */ 0, changed_regions[i]);
124 }
125
126 valid_history_++;
127}
128
Zach Reizner5757e822015-10-16 19:06:31 -0700129bool SquashState::RecordAndCompareSquashed(
130 const std::vector<bool> &squashed_regions) {
131 if (squashed_regions.size() != regions_.size()) {
132 ALOGE(
133 "SquashState::RecordAndCompareSquashed expected %zu regions but got "
134 "%zu regions",
135 regions_.size(), squashed_regions.size());
136 return false;
Zach Reizner92f8e632015-10-12 17:47:13 -0700137 }
Zach Reizner5757e822015-10-16 19:06:31 -0700138 bool changed = false;
139 for (size_t i = 0; i < regions_.size(); i++) {
140 if (regions_[i].squashed != squashed_regions[i]) {
141 regions_[i].squashed = squashed_regions[i];
142 changed = true;
143 }
144 }
145 return changed;
Zach Reizner92f8e632015-10-12 17:47:13 -0700146}
147
Zach Reiznerfd6dc332015-10-13 21:12:48 -0700148void SquashState::Dump(std::ostringstream *out) const {
149 *out << "----SquashState generation=" << generation_number_
150 << " history=" << valid_history_ << "\n"
151 << " Regions: count=" << regions_.size() << "\n";
152 for (size_t i = 0; i < regions_.size(); i++) {
153 const Region &region = regions_[i];
154 *out << " [" << i << "]"
155 << " history=" << region.change_history << " rect";
156 region.rect.Dump(out);
157 *out << " layers=(";
158 bool first = true;
159 for (size_t layer_index = 0; layer_index < kMaxLayers; layer_index++) {
160 if ((region.layer_refs &
161 std::bitset<kMaxLayers>((size_t)1 << layer_index))
162 .any()) {
163 if (!first)
164 *out << " ";
165 first = false;
166 *out << layer_index;
167 }
168 }
169 *out << ")";
170 if (region.squashed)
171 *out << " squashed";
172 *out << "\n";
173 }
174}
175
Zach Reizner5757e822015-10-16 19:06:31 -0700176static bool UsesSquash(const std::vector<DrmCompositionPlane> &comp_planes) {
177 return std::any_of(comp_planes.begin(), comp_planes.end(),
178 [](const DrmCompositionPlane &plane) {
Sean Paul7379ecd2016-05-11 16:57:26 -0400179 return plane.type() == DrmCompositionPlane::Type::kSquash;
Sean Paul07aa8cc2016-05-11 13:50:28 -0400180 });
Zach Reizner5757e822015-10-16 19:06:31 -0700181}
182
Haixia Shidda2fab2015-10-22 18:12:49 -0700183DrmDisplayCompositor::FrameWorker::FrameWorker(DrmDisplayCompositor *compositor)
Adrian Salido0e892682017-03-01 14:57:39 -0800184 : QueueWorker("frame-worker", HAL_PRIORITY_URGENT_DISPLAY),
Haixia Shidda2fab2015-10-22 18:12:49 -0700185 compositor_(compositor) {
186}
187
Haixia Shidda2fab2015-10-22 18:12:49 -0700188int DrmDisplayCompositor::FrameWorker::Init() {
Adrian Salido0e892682017-03-01 14:57:39 -0800189 set_max_queue_size(DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH);
Haixia Shidda2fab2015-10-22 18:12:49 -0700190 return InitWorker();
191}
192
193void DrmDisplayCompositor::FrameWorker::QueueFrame(
194 std::unique_ptr<DrmDisplayComposition> composition, int status) {
Adrian Salido0e892682017-03-01 14:57:39 -0800195 std::unique_ptr<FrameState> frame(
196 new FrameState(std::move(composition), status));
Adrian Salidoff717ff2016-09-30 14:32:00 -0700197
Adrian Salido0e892682017-03-01 14:57:39 -0800198 auto start = std::chrono::high_resolution_clock::now();
199 int ret = QueueWork(std::move(frame));
200 if (ret) {
201 ALOGE("Unable to queue frame work (%d)", ret);
202 // TODO: error handling (timeout or exit)
203 return;
Adrian Salidoff717ff2016-09-30 14:32:00 -0700204 }
Adrian Salido0e892682017-03-01 14:57:39 -0800205 auto end = std::chrono::high_resolution_clock::now();
Adrian Salidoff717ff2016-09-30 14:32:00 -0700206
Adrian Salido0e892682017-03-01 14:57:39 -0800207 uint64_t duration_us =
208 std::chrono::duration_cast<std::chrono::microseconds>(end - start)
209 .count();
210 if (duration_us > max_duration_us)
211 max_duration_us = duration_us;
Haixia Shidda2fab2015-10-22 18:12:49 -0700212}
213
Adrian Salido0e892682017-03-01 14:57:39 -0800214void DrmDisplayCompositor::FrameWorker::ProcessWork(
215 std::unique_ptr<FrameState> frame) {
216 compositor_->ApplyFrame(std::move(frame->composition), frame->status);
Haixia Shidda2fab2015-10-22 18:12:49 -0700217}
218
Sean Paul98e73c82015-06-24 14:38:49 -0700219DrmDisplayCompositor::DrmDisplayCompositor()
Adrian Salido0e892682017-03-01 14:57:39 -0800220 : QueueWorker("drm-compositor", HAL_PRIORITY_URGENT_DISPLAY),
221 drm_(NULL),
Sean Paul98e73c82015-06-24 14:38:49 -0700222 display_(-1),
Haixia Shidda2fab2015-10-22 18:12:49 -0700223 frame_worker_(this),
Sean Pauldb7a17d2015-06-24 18:46:05 -0700224 active_(false),
Sean Paul6c18b3b2015-11-25 11:04:25 -0500225 use_hw_overlays_(true),
Zach Reizner713a6782015-07-31 15:12:44 -0700226 framebuffer_index_(0),
Zach Reizner5757e822015-10-16 19:06:31 -0700227 squash_framebuffer_index_(0),
Sean Paul98e73c82015-06-24 14:38:49 -0700228 dump_frames_composited_(0),
Adrian Salido0e892682017-03-01 14:57:39 -0800229 dump_last_timestamp_ns_(0),
230 max_duration_us(0) {
Sean Paul98e73c82015-06-24 14:38:49 -0700231 struct timespec ts;
232 if (clock_gettime(CLOCK_MONOTONIC, &ts))
233 return;
234 dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
235}
236
237DrmDisplayCompositor::~DrmDisplayCompositor() {
Adrian Salido0e892682017-03-01 14:57:39 -0800238 if (!initialized())
Sean Paul98e73c82015-06-24 14:38:49 -0700239 return;
240
Haixia Shidda2fab2015-10-22 18:12:49 -0700241 frame_worker_.Exit();
Adrian Salido0e892682017-03-01 14:57:39 -0800242 Exit();
Sean Paul98e73c82015-06-24 14:38:49 -0700243
Adrian Salido0e892682017-03-01 14:57:39 -0800244 std::lock_guard<std::mutex> lk(mutex_);
Sean Paul98e73c82015-06-24 14:38:49 -0700245
Sean Paul35301f42015-11-17 14:46:56 -0500246 if (mode_.blob_id)
247 drm_->DestroyPropertyBlob(mode_.blob_id);
248 if (mode_.old_blob_id)
249 drm_->DestroyPropertyBlob(mode_.old_blob_id);
250
Sean Paul98e73c82015-06-24 14:38:49 -0700251 active_composition_.reset();
Sean Paul98e73c82015-06-24 14:38:49 -0700252}
253
254int DrmDisplayCompositor::Init(DrmResources *drm, int display) {
255 drm_ = drm;
256 display_ = display;
257
Adrian Salido0e892682017-03-01 14:57:39 -0800258 frame_worker_.Init();
Sean Paul98e73c82015-06-24 14:38:49 -0700259
Adrian Salido0e892682017-03-01 14:57:39 -0800260 set_max_queue_size(DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH);
261 set_idle_timeout(kSquashWait);
262
263 return InitWorker();
Sean Paul98e73c82015-06-24 14:38:49 -0700264}
265
Zach Reizner92f8e632015-10-12 17:47:13 -0700266std::unique_ptr<DrmDisplayComposition> DrmDisplayCompositor::CreateComposition()
267 const {
268 return std::unique_ptr<DrmDisplayComposition>(new DrmDisplayComposition());
269}
270
Sean Paul98e73c82015-06-24 14:38:49 -0700271int DrmDisplayCompositor::QueueComposition(
272 std::unique_ptr<DrmDisplayComposition> composition) {
Sean Paulacb2a442015-06-24 18:43:01 -0700273 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700274 case DRM_COMPOSITION_TYPE_FRAME:
275 if (!active_)
276 return -ENODEV;
277 break;
278 case DRM_COMPOSITION_TYPE_DPMS:
279 /*
280 * Update the state as soon as we get it so we can start/stop queuing
281 * frames asap.
282 */
283 active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
284 break;
Sean Paul57355412015-09-19 09:14:34 -0400285 case DRM_COMPOSITION_TYPE_MODESET:
286 break;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700287 case DRM_COMPOSITION_TYPE_EMPTY:
288 return 0;
289 default:
290 ALOGE("Unknown composition type %d/%d", composition->type(), display_);
291 return -ENOENT;
Sean Paulacb2a442015-06-24 18:43:01 -0700292 }
Sean Paul98e73c82015-06-24 14:38:49 -0700293
Adrian Salido0e892682017-03-01 14:57:39 -0800294 auto start = std::chrono::high_resolution_clock::now();
295
296 int ret = QueueWork(std::move(composition));
Sean Paul98e73c82015-06-24 14:38:49 -0700297 if (ret) {
Adrian Salido0e892682017-03-01 14:57:39 -0800298 ALOGE("Unable to queue work (%d)", ret);
299 // TODO: error handling (timeout or exit)
Sean Paul98e73c82015-06-24 14:38:49 -0700300 return ret;
301 }
302
Adrian Salido0e892682017-03-01 14:57:39 -0800303 auto end = std::chrono::high_resolution_clock::now();
Zach Reiznerd410f042015-07-28 15:33:07 -0700304
Adrian Salido0e892682017-03-01 14:57:39 -0800305 uint64_t duration_us =
306 std::chrono::duration_cast<std::chrono::microseconds>(end - start)
307 .count();
308 if (duration_us > max_duration_us)
309 max_duration_us = duration_us;
Sean Paul98e73c82015-06-24 14:38:49 -0700310
Sean Paul98e73c82015-06-24 14:38:49 -0700311 return 0;
312}
313
Zach Reizner92f8e632015-10-12 17:47:13 -0700314std::tuple<uint32_t, uint32_t, int>
315DrmDisplayCompositor::GetActiveModeResolution() {
316 DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
317 if (connector == NULL) {
318 ALOGE("Failed to determine display mode: no connector for display %d",
319 display_);
320 return std::make_tuple(0, 0, -ENODEV);
321 }
322
323 const DrmMode &mode = connector->active_mode();
324 return std::make_tuple(mode.h_display(), mode.v_display(), 0);
Zach Reizner713a6782015-07-31 15:12:44 -0700325}
326
Zach Reizner92f8e632015-10-12 17:47:13 -0700327int DrmDisplayCompositor::PrepareFramebuffer(
328 DrmFramebuffer &fb, DrmDisplayComposition *display_comp) {
329 int ret = fb.WaitReleased(-1);
330 if (ret) {
331 ALOGE("Failed to wait for framebuffer release %d", ret);
332 return ret;
333 }
334 uint32_t width, height;
335 std::tie(width, height, ret) = GetActiveModeResolution();
336 if (ret) {
337 ALOGE(
338 "Failed to allocate framebuffer because the display resolution could "
339 "not be determined %d",
340 ret);
341 return ret;
342 }
343
344 fb.set_release_fence_fd(-1);
345 if (!fb.Allocate(width, height)) {
346 ALOGE("Failed to allocate framebuffer with size %dx%d", width, height);
347 return -ENOMEM;
348 }
349
350 display_comp->layers().emplace_back();
351 DrmHwcLayer &pre_comp_layer = display_comp->layers().back();
352 pre_comp_layer.sf_handle = fb.buffer()->handle;
Haixia Shi0c7da1e2015-11-23 11:34:36 -0800353 pre_comp_layer.blending = DrmHwcBlending::kPreMult;
Zach Reizner92f8e632015-10-12 17:47:13 -0700354 pre_comp_layer.source_crop = DrmHwcRect<float>(0, 0, width, height);
355 pre_comp_layer.display_frame = DrmHwcRect<int>(0, 0, width, height);
356 ret = pre_comp_layer.buffer.ImportBuffer(fb.buffer()->handle,
357 display_comp->importer());
358 if (ret) {
359 ALOGE("Failed to import framebuffer for display %d", ret);
360 return ret;
361 }
362
363 return ret;
Zach Reizner713a6782015-07-31 15:12:44 -0700364}
365
Zach Reizner5757e822015-10-16 19:06:31 -0700366int DrmDisplayCompositor::ApplySquash(DrmDisplayComposition *display_comp) {
367 int ret = 0;
368
369 DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_];
370 ret = PrepareFramebuffer(fb, display_comp);
371 if (ret) {
372 ALOGE("Failed to prepare framebuffer for squash %d", ret);
373 return ret;
374 }
375
376 std::vector<DrmCompositionRegion> &regions = display_comp->squash_regions();
377 ret = pre_compositor_->Composite(display_comp->layers().data(),
Adrian Salido9cc83932017-08-21 16:14:57 -0700378 regions.data(), regions.size(), fb.buffer());
Zach Reizner5757e822015-10-16 19:06:31 -0700379 pre_compositor_->Finish();
380
381 if (ret) {
382 ALOGE("Failed to squash layers");
383 return ret;
384 }
385
386 ret = display_comp->CreateNextTimelineFence();
387 if (ret <= 0) {
388 ALOGE("Failed to create squash framebuffer release fence %d", ret);
389 return ret;
390 }
391
392 fb.set_release_fence_fd(ret);
393 display_comp->SignalSquashDone();
394
395 return 0;
396}
397
Zach Reizner713a6782015-07-31 15:12:44 -0700398int DrmDisplayCompositor::ApplyPreComposite(
399 DrmDisplayComposition *display_comp) {
400 int ret = 0;
Zach Reizner713a6782015-07-31 15:12:44 -0700401
Zach Reizner713a6782015-07-31 15:12:44 -0700402 DrmFramebuffer &fb = framebuffers_[framebuffer_index_];
Zach Reizner92f8e632015-10-12 17:47:13 -0700403 ret = PrepareFramebuffer(fb, display_comp);
Zach Reizner713a6782015-07-31 15:12:44 -0700404 if (ret) {
Zach Reizner5757e822015-10-16 19:06:31 -0700405 ALOGE("Failed to prepare framebuffer for pre-composite %d", ret);
Zach Reizner713a6782015-07-31 15:12:44 -0700406 return ret;
407 }
Zach Reizner713a6782015-07-31 15:12:44 -0700408
Zach Reizner92f8e632015-10-12 17:47:13 -0700409 std::vector<DrmCompositionRegion> &regions = display_comp->pre_comp_regions();
410 ret = pre_compositor_->Composite(display_comp->layers().data(),
Adrian Salido9cc83932017-08-21 16:14:57 -0700411 regions.data(), regions.size(), fb.buffer());
Zach Reizner8d63e7f2015-08-20 14:52:12 -0700412 pre_compositor_->Finish();
Zach Reiznerb44fd102015-08-07 16:00:01 -0700413
Zach Reizner713a6782015-07-31 15:12:44 -0700414 if (ret) {
Zach Reizner5757e822015-10-16 19:06:31 -0700415 ALOGE("Failed to pre-composite layers");
Zach Reizner713a6782015-07-31 15:12:44 -0700416 return ret;
417 }
418
Zach Reizner92f8e632015-10-12 17:47:13 -0700419 ret = display_comp->CreateNextTimelineFence();
420 if (ret <= 0) {
Zach Reizner5757e822015-10-16 19:06:31 -0700421 ALOGE("Failed to create pre-composite framebuffer release fence %d", ret);
Zach Reizner09807052015-08-13 14:53:41 -0700422 return ret;
423 }
Zach Reizner713a6782015-07-31 15:12:44 -0700424
Zach Reizner92f8e632015-10-12 17:47:13 -0700425 fb.set_release_fence_fd(ret);
426 display_comp->SignalPreCompDone();
Zach Reizner713a6782015-07-31 15:12:44 -0700427
Zach Reizner92f8e632015-10-12 17:47:13 -0700428 return 0;
Zach Reizner713a6782015-07-31 15:12:44 -0700429}
430
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400431int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) {
Rob Herringb02d8582016-02-04 14:01:24 -0600432 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400433 if (!pset) {
434 ALOGE("Failed to allocate property set");
435 return -ENOMEM;
436 }
437
438 int ret;
Zach Reizner92f8e632015-10-12 17:47:13 -0700439 std::vector<DrmCompositionPlane> &comp_planes =
440 display_comp->composition_planes();
441 for (DrmCompositionPlane &comp_plane : comp_planes) {
Sean Paul9b707172016-05-11 16:29:45 -0400442 DrmPlane *plane = comp_plane.plane();
Rob Herringb02d8582016-02-04 14:01:24 -0600443 ret = drmModeAtomicAddProperty(pset, plane->id(),
444 plane->crtc_property().id(), 0) < 0 ||
445 drmModeAtomicAddProperty(pset, plane->id(), plane->fb_property().id(),
446 0) < 0;
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400447 if (ret) {
448 ALOGE("Failed to add plane %d disable to pset", plane->id());
Rob Herringb02d8582016-02-04 14:01:24 -0600449 drmModeAtomicFree(pset);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400450 return ret;
451 }
452 }
453
Rob Herringb02d8582016-02-04 14:01:24 -0600454 ret = drmModeAtomicCommit(drm_->fd(), pset, 0, drm_);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400455 if (ret) {
456 ALOGE("Failed to commit pset ret=%d\n", ret);
Rob Herringb02d8582016-02-04 14:01:24 -0600457 drmModeAtomicFree(pset);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400458 return ret;
459 }
460
Rob Herringb02d8582016-02-04 14:01:24 -0600461 drmModeAtomicFree(pset);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400462 return 0;
463}
464
Haixia Shidda2fab2015-10-22 18:12:49 -0700465int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) {
Sean Paul98e73c82015-06-24 14:38:49 -0700466 int ret = 0;
467
Zach Reizner92f8e632015-10-12 17:47:13 -0700468 std::vector<DrmHwcLayer> &layers = display_comp->layers();
469 std::vector<DrmCompositionPlane> &comp_planes =
470 display_comp->composition_planes();
Zach Reizner5757e822015-10-16 19:06:31 -0700471 std::vector<DrmCompositionRegion> &squash_regions =
472 display_comp->squash_regions();
Zach Reizner92f8e632015-10-12 17:47:13 -0700473 std::vector<DrmCompositionRegion> &pre_comp_regions =
474 display_comp->pre_comp_regions();
475
Zach Reizner5757e822015-10-16 19:06:31 -0700476 int squash_layer_index = -1;
477 if (squash_regions.size() > 0) {
478 squash_framebuffer_index_ = (squash_framebuffer_index_ + 1) % 2;
479 ret = ApplySquash(display_comp);
480 if (ret)
481 return ret;
Zach Reizner92f8e632015-10-12 17:47:13 -0700482
Zach Reizner5757e822015-10-16 19:06:31 -0700483 squash_layer_index = layers.size() - 1;
484 } else {
485 if (UsesSquash(comp_planes)) {
486 DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_];
487 layers.emplace_back();
488 squash_layer_index = layers.size() - 1;
489 DrmHwcLayer &squash_layer = layers.back();
490 ret = squash_layer.buffer.ImportBuffer(fb.buffer()->handle,
491 display_comp->importer());
492 if (ret) {
493 ALOGE("Failed to import old squashed framebuffer %d", ret);
494 return ret;
495 }
496 squash_layer.sf_handle = fb.buffer()->handle;
Haixia Shi0c7da1e2015-11-23 11:34:36 -0800497 squash_layer.blending = DrmHwcBlending::kPreMult;
Zach Reizner5757e822015-10-16 19:06:31 -0700498 squash_layer.source_crop = DrmHwcRect<float>(
499 0, 0, squash_layer.buffer->width, squash_layer.buffer->height);
500 squash_layer.display_frame = DrmHwcRect<int>(
501 0, 0, squash_layer.buffer->width, squash_layer.buffer->height);
502 ret = display_comp->CreateNextTimelineFence();
503
504 if (ret <= 0) {
505 ALOGE("Failed to create squash framebuffer release fence %d", ret);
506 return ret;
507 }
508
509 fb.set_release_fence_fd(ret);
510 ret = 0;
511 }
512 }
513
514 bool do_pre_comp = pre_comp_regions.size() > 0;
515 int pre_comp_layer_index = -1;
Zach Reizner92f8e632015-10-12 17:47:13 -0700516 if (do_pre_comp) {
Zach Reizner713a6782015-07-31 15:12:44 -0700517 ret = ApplyPreComposite(display_comp);
518 if (ret)
519 return ret;
Zach Reizner92f8e632015-10-12 17:47:13 -0700520
521 pre_comp_layer_index = layers.size() - 1;
522 framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
Zach Reizner713a6782015-07-31 15:12:44 -0700523 }
524
Haixia Shidda2fab2015-10-22 18:12:49 -0700525 for (DrmCompositionPlane &comp_plane : comp_planes) {
Sean Paul9b707172016-05-11 16:29:45 -0400526 std::vector<size_t> &source_layers = comp_plane.source_layers();
527 switch (comp_plane.type()) {
Sean Paul7379ecd2016-05-11 16:57:26 -0400528 case DrmCompositionPlane::Type::kSquash:
Sean Paul9b707172016-05-11 16:29:45 -0400529 if (source_layers.size())
530 ALOGE("Squash source_layers is expected to be empty (%zu/%d)",
531 source_layers[0], squash_layer_index);
532 source_layers.push_back(squash_layer_index);
Haixia Shidda2fab2015-10-22 18:12:49 -0700533 break;
Sean Paul7379ecd2016-05-11 16:57:26 -0400534 case DrmCompositionPlane::Type::kPrecomp:
Haixia Shidda2fab2015-10-22 18:12:49 -0700535 if (!do_pre_comp) {
536 ALOGE(
537 "Can not use pre composite framebuffer with no pre composite "
538 "regions");
539 return -EINVAL;
540 }
Sean Paul9b707172016-05-11 16:29:45 -0400541 // Replace source_layers with the output of the precomposite
542 source_layers.clear();
543 source_layers.push_back(pre_comp_layer_index);
Haixia Shidda2fab2015-10-22 18:12:49 -0700544 break;
545 default:
546 break;
547 }
548 }
549
550 return ret;
551}
552
Sean Paulc07b2112015-11-17 16:38:10 -0500553int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
554 bool test_only) {
Haixia Shi3979f7d2015-10-29 14:33:37 -0700555 ATRACE_CALL();
556
Haixia Shidda2fab2015-10-22 18:12:49 -0700557 int ret = 0;
558
559 std::vector<DrmHwcLayer> &layers = display_comp->layers();
560 std::vector<DrmCompositionPlane> &comp_planes =
561 display_comp->composition_planes();
562 std::vector<DrmCompositionRegion> &pre_comp_regions =
563 display_comp->pre_comp_regions();
564
Sean Paul57355412015-09-19 09:14:34 -0400565 DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
566 if (!connector) {
567 ALOGE("Could not locate connector for display %d", display_);
568 return -ENODEV;
569 }
570 DrmCrtc *crtc = drm_->GetCrtcForDisplay(display_);
571 if (!crtc) {
572 ALOGE("Could not locate crtc for display %d", display_);
573 return -ENODEV;
574 }
575
Rob Herringb02d8582016-02-04 14:01:24 -0600576 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
Sean Paul98e73c82015-06-24 14:38:49 -0700577 if (!pset) {
578 ALOGE("Failed to allocate property set");
579 return -ENOMEM;
580 }
581
Sean Paul35301f42015-11-17 14:46:56 -0500582 if (mode_.needs_modeset) {
Rob Herringb02d8582016-02-04 14:01:24 -0600583 ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->mode_property().id(),
584 mode_.blob_id) < 0 ||
585 drmModeAtomicAddProperty(pset, connector->id(),
586 connector->crtc_id_property().id(),
587 crtc->id()) < 0;
Sean Paul57355412015-09-19 09:14:34 -0400588 if (ret) {
Sean Paul35301f42015-11-17 14:46:56 -0500589 ALOGE("Failed to add blob %d to pset", mode_.blob_id);
Rob Herringb02d8582016-02-04 14:01:24 -0600590 drmModeAtomicFree(pset);
Sean Paul57355412015-09-19 09:14:34 -0400591 return ret;
592 }
593 }
594
Zach Reizner92f8e632015-10-12 17:47:13 -0700595 for (DrmCompositionPlane &comp_plane : comp_planes) {
Sean Paul9b707172016-05-11 16:29:45 -0400596 DrmPlane *plane = comp_plane.plane();
597 DrmCrtc *crtc = comp_plane.crtc();
598 std::vector<size_t> &source_layers = comp_plane.source_layers();
Zach Reizner92f8e632015-10-12 17:47:13 -0700599
600 int fb_id = -1;
601 DrmHwcRect<int> display_frame;
602 DrmHwcRect<float> source_crop;
603 uint64_t rotation = 0;
Sean Pauld8aefb62015-10-15 15:17:31 -0400604 uint64_t alpha = 0xFF;
Sean Paul04b47ea2015-11-19 21:46:11 -0500605
Sean Paul7379ecd2016-05-11 16:57:26 -0400606 if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
Sean Paul9b707172016-05-11 16:29:45 -0400607 if (source_layers.size() > 1) {
608 ALOGE("Can't handle more than one source layer sz=%zu type=%d",
609 source_layers.size(), comp_plane.type());
610 continue;
611 }
612
613 if (source_layers.empty() || source_layers.front() >= layers.size()) {
614 ALOGE("Source layer index %zu out of bounds %zu type=%d",
615 source_layers.front(), layers.size(), comp_plane.type());
Sean Paul07aa8cc2016-05-11 13:50:28 -0400616 break;
Sean Paul98e73c82015-06-24 14:38:49 -0700617 }
Sean Paul9b707172016-05-11 16:29:45 -0400618 DrmHwcLayer &layer = layers[source_layers.front()];
Sean Paul07aa8cc2016-05-11 13:50:28 -0400619 if (!test_only && layer.acquire_fence.get() >= 0) {
620 int acquire_fence = layer.acquire_fence.get();
621 int total_fence_timeout = 0;
622 for (int i = 0; i < kAcquireWaitTries; ++i) {
623 int fence_timeout = kAcquireWaitTimeoutMs * (1 << i);
624 total_fence_timeout += fence_timeout;
625 ret = sync_wait(acquire_fence, fence_timeout);
626 if (ret)
627 ALOGW("Acquire fence %d wait %d failed (%d). Total time %d",
628 acquire_fence, i, ret, total_fence_timeout);
629 }
630 if (ret) {
631 ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
632 break;
633 }
634 layer.acquire_fence.Close();
635 }
636 if (!layer.buffer) {
637 ALOGE("Expected a valid framebuffer for pset");
638 break;
639 }
640 fb_id = layer.buffer->fb_id;
641 display_frame = layer.display_frame;
642 source_crop = layer.source_crop;
643 if (layer.blending == DrmHwcBlending::kPreMult)
644 alpha = layer.alpha;
Sean Paul98e73c82015-06-24 14:38:49 -0700645
Sean Paul07aa8cc2016-05-11 13:50:28 -0400646 rotation = 0;
647 if (layer.transform & DrmHwcTransform::kFlipH)
648 rotation |= 1 << DRM_REFLECT_X;
649 if (layer.transform & DrmHwcTransform::kFlipV)
650 rotation |= 1 << DRM_REFLECT_Y;
651 if (layer.transform & DrmHwcTransform::kRotate90)
652 rotation |= 1 << DRM_ROTATE_90;
653 else if (layer.transform & DrmHwcTransform::kRotate180)
654 rotation |= 1 << DRM_ROTATE_180;
655 else if (layer.transform & DrmHwcTransform::kRotate270)
656 rotation |= 1 << DRM_ROTATE_270;
657 }
Zach Reizner92f8e632015-10-12 17:47:13 -0700658 // Disable the plane if there's no framebuffer
659 if (fb_id < 0) {
Rob Herringb02d8582016-02-04 14:01:24 -0600660 ret = drmModeAtomicAddProperty(pset, plane->id(),
661 plane->crtc_property().id(), 0) < 0 ||
662 drmModeAtomicAddProperty(pset, plane->id(),
663 plane->fb_property().id(), 0) < 0;
Sean Paul2e46fbd2015-07-09 17:22:22 -0400664 if (ret) {
665 ALOGE("Failed to add plane %d disable to pset", plane->id());
666 break;
667 }
668 continue;
669 }
670
Sean Paul1c4c3262015-07-14 15:51:52 -0400671 // TODO: Once we have atomic test, this should fall back to GL
672 if (rotation && plane->rotation_property().id() == 0) {
673 ALOGE("Rotation is not supported on plane %d", plane->id());
674 ret = -EINVAL;
675 break;
676 }
677
Sean Pauld8aefb62015-10-15 15:17:31 -0400678 // TODO: Once we have atomic test, this should fall back to GL
679 if (alpha != 0xFF && plane->alpha_property().id() == 0) {
680 ALOGE("Alpha is not supported on plane %d", plane->id());
681 ret = -EINVAL;
682 break;
683 }
684
Rob Herringb02d8582016-02-04 14:01:24 -0600685 ret = drmModeAtomicAddProperty(pset, plane->id(),
686 plane->crtc_property().id(), crtc->id()) < 0;
687 ret |= drmModeAtomicAddProperty(pset, plane->id(),
688 plane->fb_property().id(), fb_id) < 0;
689 ret |= drmModeAtomicAddProperty(pset, plane->id(),
690 plane->crtc_x_property().id(),
691 display_frame.left) < 0;
692 ret |= drmModeAtomicAddProperty(pset, plane->id(),
693 plane->crtc_y_property().id(),
694 display_frame.top) < 0;
695 ret |= drmModeAtomicAddProperty(
696 pset, plane->id(), plane->crtc_w_property().id(),
697 display_frame.right - display_frame.left) < 0;
698 ret |= drmModeAtomicAddProperty(
699 pset, plane->id(), plane->crtc_h_property().id(),
700 display_frame.bottom - display_frame.top) < 0;
701 ret |= drmModeAtomicAddProperty(pset, plane->id(),
702 plane->src_x_property().id(),
703 (int)(source_crop.left) << 16) < 0;
704 ret |= drmModeAtomicAddProperty(pset, plane->id(),
705 plane->src_y_property().id(),
706 (int)(source_crop.top) << 16) < 0;
707 ret |= drmModeAtomicAddProperty(
708 pset, plane->id(), plane->src_w_property().id(),
709 (int)(source_crop.right - source_crop.left) << 16) < 0;
710 ret |= drmModeAtomicAddProperty(
711 pset, plane->id(), plane->src_h_property().id(),
712 (int)(source_crop.bottom - source_crop.top) << 16) < 0;
Sean Paul98e73c82015-06-24 14:38:49 -0700713 if (ret) {
714 ALOGE("Failed to add plane %d to set", plane->id());
715 break;
716 }
Sean Paul1c4c3262015-07-14 15:51:52 -0400717
718 if (plane->rotation_property().id()) {
Rob Herringb02d8582016-02-04 14:01:24 -0600719 ret = drmModeAtomicAddProperty(pset, plane->id(),
720 plane->rotation_property().id(),
721 rotation) < 0;
Sean Paul1c4c3262015-07-14 15:51:52 -0400722 if (ret) {
723 ALOGE("Failed to add rotation property %d to plane %d",
724 plane->rotation_property().id(), plane->id());
725 break;
726 }
727 }
Sean Pauld8aefb62015-10-15 15:17:31 -0400728
729 if (plane->alpha_property().id()) {
Rob Herringb02d8582016-02-04 14:01:24 -0600730 ret = drmModeAtomicAddProperty(pset, plane->id(),
731 plane->alpha_property().id(),
732 alpha) < 0;
Sean Pauld8aefb62015-10-15 15:17:31 -0400733 if (ret) {
734 ALOGE("Failed to add alpha property %d to plane %d",
735 plane->alpha_property().id(), plane->id());
736 break;
737 }
738 }
Sean Paul98e73c82015-06-24 14:38:49 -0700739 }
740
Zach Reizner92f8e632015-10-12 17:47:13 -0700741out:
Sean Paul98e73c82015-06-24 14:38:49 -0700742 if (!ret) {
Sean Paulc07b2112015-11-17 16:38:10 -0500743 uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
744 if (test_only)
745 flags |= DRM_MODE_ATOMIC_TEST_ONLY;
746
Rob Herringb02d8582016-02-04 14:01:24 -0600747 ret = drmModeAtomicCommit(drm_->fd(), pset, flags, drm_);
Sean Paul57355412015-09-19 09:14:34 -0400748 if (ret) {
Sean Paulc07b2112015-11-17 16:38:10 -0500749 if (test_only)
750 ALOGI("Commit test pset failed ret=%d\n", ret);
751 else
752 ALOGE("Failed to commit pset ret=%d\n", ret);
Rob Herringb02d8582016-02-04 14:01:24 -0600753 drmModeAtomicFree(pset);
Sean Paul57355412015-09-19 09:14:34 -0400754 return ret;
755 }
Sean Paul98e73c82015-06-24 14:38:49 -0700756 }
757 if (pset)
Rob Herringb02d8582016-02-04 14:01:24 -0600758 drmModeAtomicFree(pset);
Sean Paul98e73c82015-06-24 14:38:49 -0700759
Sean Paulc07b2112015-11-17 16:38:10 -0500760 if (!test_only && mode_.needs_modeset) {
Sean Paul35301f42015-11-17 14:46:56 -0500761 ret = drm_->DestroyPropertyBlob(mode_.old_blob_id);
Sean Paul57355412015-09-19 09:14:34 -0400762 if (ret) {
Sean Paul717a44b2016-05-11 13:49:38 -0400763 ALOGE("Failed to destroy old mode property blob %" PRIu32 "/%d",
Sean Paul35301f42015-11-17 14:46:56 -0500764 mode_.old_blob_id, ret);
Sean Paul57355412015-09-19 09:14:34 -0400765 return ret;
766 }
767
768 /* TODO: Add dpms to the pset when the kernel supports it */
769 ret = ApplyDpms(display_comp);
770 if (ret) {
771 ALOGE("Failed to apply DPMS after modeset %d\n", ret);
772 return ret;
773 }
774
Sean Paul35301f42015-11-17 14:46:56 -0500775 connector->set_active_mode(mode_.mode);
776 mode_.old_blob_id = mode_.blob_id;
777 mode_.blob_id = 0;
778 mode_.needs_modeset = false;
Sean Paul57355412015-09-19 09:14:34 -0400779 }
780
Sean Paul98e73c82015-06-24 14:38:49 -0700781 return ret;
782}
783
Sean Pauldb7a17d2015-06-24 18:46:05 -0700784int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
785 DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
786 if (!conn) {
787 ALOGE("Failed to get DrmConnector for display %d", display_);
788 return -ENODEV;
789 }
790
791 const DrmProperty &prop = conn->dpms_property();
792 int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
793 display_comp->dpms_mode());
794 if (ret) {
795 ALOGE("Failed to set DPMS property for connector %d", conn->id());
796 return ret;
797 }
798 return 0;
799}
800
Sean Paul35301f42015-11-17 14:46:56 -0500801std::tuple<int, uint32_t> DrmDisplayCompositor::CreateModeBlob(
802 const DrmMode &mode) {
803 struct drm_mode_modeinfo drm_mode;
804 memset(&drm_mode, 0, sizeof(drm_mode));
805 mode.ToDrmModeModeInfo(&drm_mode);
806
807 uint32_t id = 0;
808 int ret = drm_->CreatePropertyBlob(&drm_mode,
809 sizeof(struct drm_mode_modeinfo), &id);
810 if (ret) {
811 ALOGE("Failed to create mode property blob %d", ret);
812 return std::make_tuple(ret, 0);
813 }
Sean Paul717a44b2016-05-11 13:49:38 -0400814 ALOGE("Create blob_id %" PRIu32 "\n", id);
Sean Paul35301f42015-11-17 14:46:56 -0500815 return std::make_tuple(ret, id);
816}
817
Sean Paulb4cf01b2016-06-22 22:48:22 -0400818void DrmDisplayCompositor::ClearDisplay() {
Adrian Salido0e892682017-03-01 14:57:39 -0800819 std::lock_guard<std::mutex> lk(mutex_);
Sean Paulb4cf01b2016-06-22 22:48:22 -0400820 if (!active_composition_)
821 return;
822
823 if (DisablePlanes(active_composition_.get()))
824 return;
825
826 active_composition_->SignalCompositionDone();
827
828 active_composition_.reset(NULL);
829}
830
Haixia Shidda2fab2015-10-22 18:12:49 -0700831void DrmDisplayCompositor::ApplyFrame(
832 std::unique_ptr<DrmDisplayComposition> composition, int status) {
833 int ret = status;
834
835 if (!ret)
Sean Paulc07b2112015-11-17 16:38:10 -0500836 ret = CommitFrame(composition.get(), false);
Haixia Shidda2fab2015-10-22 18:12:49 -0700837
838 if (ret) {
839 ALOGE("Composite failed for display %d", display_);
Haixia Shidda2fab2015-10-22 18:12:49 -0700840 // Disable the hw used by the last active composition. This allows us to
841 // signal the release fences from that composition to avoid hanging.
Sean Paulb4cf01b2016-06-22 22:48:22 -0400842 ClearDisplay();
843 return;
Haixia Shidda2fab2015-10-22 18:12:49 -0700844 }
845 ++dump_frames_composited_;
846
847 if (active_composition_)
848 active_composition_->SignalCompositionDone();
849
Adrian Salido0e892682017-03-01 14:57:39 -0800850 std::lock_guard<std::mutex> lk(mutex_);
Haixia Shidda2fab2015-10-22 18:12:49 -0700851 active_composition_.swap(composition);
Haixia Shidda2fab2015-10-22 18:12:49 -0700852}
853
Adrian Salido0e892682017-03-01 14:57:39 -0800854void DrmDisplayCompositor::ProcessWork(
855 std::unique_ptr<DrmDisplayComposition> composition) {
Sean Paul98e73c82015-06-24 14:38:49 -0700856 ATRACE_CALL();
Zach Reizner09807052015-08-13 14:53:41 -0700857
858 if (!pre_compositor_) {
859 pre_compositor_.reset(new GLWorkerCompositor());
860 int ret = pre_compositor_->Init();
861 if (ret) {
862 ALOGE("Failed to initialize OpenGL compositor %d", ret);
Adrian Salido0e892682017-03-01 14:57:39 -0800863 return;
Zach Reizner09807052015-08-13 14:53:41 -0700864 }
865 }
866
Adrian Salido0e892682017-03-01 14:57:39 -0800867 int ret;
Sean Paulacb2a442015-06-24 18:43:01 -0700868 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700869 case DRM_COMPOSITION_TYPE_FRAME:
Sean Paule3141c62015-11-30 14:35:45 -0500870 ret = PrepareFrame(composition.get());
871 if (ret) {
872 ALOGE("Failed to prepare frame for display %d", display_);
Adrian Salido0e892682017-03-01 14:57:39 -0800873 return;
Sean Paul647beb22015-11-19 13:55:48 -0500874 }
Haixia Shi6afbb6a2015-11-24 12:42:45 -0800875 if (composition->geometry_changed()) {
876 // Send the composition to the kernel to ensure we can commit it. This
877 // is just a test, it won't actually commit the frame. If rejected,
878 // squash the frame into one layer and use the squashed composition
879 ret = CommitFrame(composition.get(), true);
Sean Paul6c18b3b2015-11-25 11:04:25 -0500880 if (ret)
Haixia Shi6afbb6a2015-11-24 12:42:45 -0800881 ALOGI("Commit test failed, squashing frame for display %d", display_);
Sean Paul6c18b3b2015-11-25 11:04:25 -0500882 use_hw_overlays_ = !ret;
883 }
884
885 // If use_hw_overlays_ is false, we can't use hardware to composite the
886 // frame. So squash all layers into a single composition and queue that
887 // instead.
888 if (!use_hw_overlays_) {
889 std::unique_ptr<DrmDisplayComposition> squashed = CreateComposition();
890 ret = SquashFrame(composition.get(), squashed.get());
891 if (!ret) {
892 composition = std::move(squashed);
893 } else {
894 ALOGE("Failed to squash frame for display %d", display_);
Sean Paulb4cf01b2016-06-22 22:48:22 -0400895 // Disable the hw used by the last active composition. This allows us
896 // to signal the release fences from that composition to avoid
897 // hanging.
898 ClearDisplay();
Adrian Salido0e892682017-03-01 14:57:39 -0800899 return;
Sean Paul647beb22015-11-19 13:55:48 -0500900 }
901 }
Haixia Shidda2fab2015-10-22 18:12:49 -0700902 frame_worker_.QueueFrame(std::move(composition), ret);
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700903 break;
904 case DRM_COMPOSITION_TYPE_DPMS:
905 ret = ApplyDpms(composition.get());
906 if (ret)
907 ALOGE("Failed to apply dpms for display %d", display_);
Adrian Salido0e892682017-03-01 14:57:39 -0800908 break;
Sean Paul57355412015-09-19 09:14:34 -0400909 case DRM_COMPOSITION_TYPE_MODESET:
Sean Paul35301f42015-11-17 14:46:56 -0500910 mode_.mode = composition->display_mode();
911 if (mode_.blob_id)
912 drm_->DestroyPropertyBlob(mode_.blob_id);
913 std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode);
914 if (ret) {
915 ALOGE("Failed to create mode blob for display %d", display_);
Adrian Salido0e892682017-03-01 14:57:39 -0800916 return;
Sean Paul35301f42015-11-17 14:46:56 -0500917 }
918 mode_.needs_modeset = true;
Adrian Salido0e892682017-03-01 14:57:39 -0800919 break;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700920 default:
921 ALOGE("Unknown composition type %d", composition->type());
Adrian Salido0e892682017-03-01 14:57:39 -0800922 break;
Sean Paul98e73c82015-06-24 14:38:49 -0700923 }
Sean Paul98e73c82015-06-24 14:38:49 -0700924}
925
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800926int DrmDisplayCompositor::SquashAll() {
Adrian Salido0e892682017-03-01 14:57:39 -0800927 std::unique_lock<std::mutex> lk(mutex_);
928 int ret;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800929
930 if (!active_composition_)
931 return 0;
932
Sean Pauld51c7612015-11-18 14:12:51 -0500933 std::unique_ptr<DrmDisplayComposition> comp = CreateComposition();
934 ret = SquashFrame(active_composition_.get(), comp.get());
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800935
Sean Pauld51c7612015-11-18 14:12:51 -0500936 // ApplyFrame needs the lock
Adrian Salido0e892682017-03-01 14:57:39 -0800937 lk.unlock();
Sean Pauld51c7612015-11-18 14:12:51 -0500938
939 if (!ret)
940 ApplyFrame(std::move(comp), 0);
941
942 return ret;
943}
944
945// Returns:
946// - 0 if src is successfully squashed into dst
947// - -EALREADY if the src is already squashed
948// - Appropriate error if the squash fails
949int DrmDisplayCompositor::SquashFrame(DrmDisplayComposition *src,
950 DrmDisplayComposition *dst) {
951 if (src->type() != DRM_COMPOSITION_TYPE_FRAME)
952 return -ENOTSUP;
953
954 std::vector<DrmCompositionPlane> &src_planes = src->composition_planes();
955 std::vector<DrmHwcLayer> &src_layers = src->layers();
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800956
957 // Make sure there is more than one layer to squash.
Sean Pauld51c7612015-11-18 14:12:51 -0500958 size_t src_planes_with_layer = std::count_if(
959 src_planes.begin(), src_planes.end(), [](DrmCompositionPlane &p) {
Sean Paulc74c8b92016-06-22 23:26:29 -0400960 return p.type() != DrmCompositionPlane::Type::kDisable;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800961 });
Sean Pauld51c7612015-11-18 14:12:51 -0500962 if (src_planes_with_layer <= 1)
963 return -EALREADY;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800964
965 int pre_comp_layer_index;
966
Sean Paul8cc4e2a2016-05-12 14:28:05 -0400967 int ret = dst->Init(drm_, src->crtc(), src->importer(), src->planner(),
968 src->frame_no());
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800969 if (ret) {
970 ALOGE("Failed to init squash all composition %d", ret);
971 return ret;
972 }
973
Sean Paul8eb85ff2016-05-03 16:40:59 -0700974 DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kPrecomp, NULL,
975 src->crtc());
Sean Pauld51c7612015-11-18 14:12:51 -0500976 std::vector<DrmHwcLayer> dst_layers;
977 for (DrmCompositionPlane &comp_plane : src_planes) {
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800978 // Composition planes without DRM planes should never happen
Sean Paul9b707172016-05-11 16:29:45 -0400979 if (comp_plane.plane() == NULL) {
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800980 ALOGE("Skipping squash all because of NULL plane");
Sean Pauld51c7612015-11-18 14:12:51 -0500981 ret = -EINVAL;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800982 goto move_layers_back;
983 }
984
Adrian Salido556f56c2017-10-02 11:18:37 -0700985 if (comp_plane.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
986 squashed_comp.set_plane(comp_plane.plane());
987 else
Sean Paul8cc4e2a2016-05-12 14:28:05 -0400988 dst->AddPlaneDisable(comp_plane.plane());
Adrian Salido556f56c2017-10-02 11:18:37 -0700989
990 if (comp_plane.type() == DrmCompositionPlane::Type::kDisable)
Zach Reizner2b4b1ee2015-11-18 13:54:31 -0800991 continue;
992
Sean Paul9b707172016-05-11 16:29:45 -0400993 for (auto i : comp_plane.source_layers()) {
994 DrmHwcLayer &layer = src_layers[i];
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800995
Sean Paul9b707172016-05-11 16:29:45 -0400996 // Squashing protected layers is impossible.
997 if (layer.protected_usage()) {
998 ret = -ENOTSUP;
999 goto move_layers_back;
1000 }
1001
1002 // The OutputFds point to freed memory after hwc_set returns. They are
1003 // returned to the default to prevent DrmDisplayComposition::Plan from
1004 // filling the OutputFds.
1005 layer.release_fence = OutputFd();
1006 dst_layers.emplace_back(std::move(layer));
Sean Paul8eb85ff2016-05-03 16:40:59 -07001007 squashed_comp.source_layers().push_back(
1008 squashed_comp.source_layers().size());
Sean Pauld51c7612015-11-18 14:12:51 -05001009 }
Adrian Salido556f56c2017-10-02 11:18:37 -07001010 }
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001011
Adrian Salido556f56c2017-10-02 11:18:37 -07001012 if (squashed_comp.plane() == NULL) {
1013 ALOGE("Primary plane not found for squash");
1014 ret = -ENOTSUP;
1015 goto move_layers_back;
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001016 }
1017
Sean Pauld51c7612015-11-18 14:12:51 -05001018 ret = dst->SetLayers(dst_layers.data(), dst_layers.size(), false);
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001019 if (ret) {
1020 ALOGE("Failed to set layers for squash all composition %d", ret);
1021 goto move_layers_back;
1022 }
1023
Sean Paul8eb85ff2016-05-03 16:40:59 -07001024 ret = dst->AddPlaneComposition(std::move(squashed_comp));
1025 if (ret) {
1026 ALOGE("Failed to add squashed plane composition %d", ret);
1027 goto move_layers_back;
1028 }
1029
1030 ret = dst->FinalizeComposition();
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001031 if (ret) {
1032 ALOGE("Failed to plan for squash all composition %d", ret);
1033 goto move_layers_back;
1034 }
1035
Sean Pauld51c7612015-11-18 14:12:51 -05001036 ret = ApplyPreComposite(dst);
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001037 if (ret) {
1038 ALOGE("Failed to pre-composite for squash all composition %d", ret);
1039 goto move_layers_back;
1040 }
1041
Sean Pauld51c7612015-11-18 14:12:51 -05001042 pre_comp_layer_index = dst->layers().size() - 1;
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001043 framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
1044
Sean Paul9b707172016-05-11 16:29:45 -04001045 for (DrmCompositionPlane &plane : dst->composition_planes()) {
Sean Paul7379ecd2016-05-11 16:57:26 -04001046 if (plane.type() == DrmCompositionPlane::Type::kPrecomp) {
Sean Paul9b707172016-05-11 16:29:45 -04001047 // Replace source_layers with the output of the precomposite
1048 plane.source_layers().clear();
1049 plane.source_layers().push_back(pre_comp_layer_index);
1050 break;
1051 }
1052 }
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001053
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001054 return 0;
1055
1056// TODO(zachr): think of a better way to transfer ownership back to the active
1057// composition.
1058move_layers_back:
1059 for (size_t plane_index = 0;
Sean Paul9b707172016-05-11 16:29:45 -04001060 plane_index < src_planes.size() && plane_index < dst_layers.size();) {
1061 if (src_planes[plane_index].source_layers().empty()) {
1062 plane_index++;
1063 continue;
1064 }
1065 for (auto i : src_planes[plane_index].source_layers())
1066 src_layers[i] = std::move(dst_layers[plane_index++]);
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001067 }
1068
1069 return ret;
1070}
1071
Sean Paul98e73c82015-06-24 14:38:49 -07001072void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
Adrian Salido0e892682017-03-01 14:57:39 -08001073 std::lock_guard<std::mutex> lk(mutex_);
Zach Reiznerfd6dc332015-10-13 21:12:48 -07001074 uint64_t num_frames = dump_frames_composited_;
1075 dump_frames_composited_ = 0;
1076
1077 struct timespec ts;
Adrian Salido0e892682017-03-01 14:57:39 -08001078 int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
Zach Reiznerfd6dc332015-10-13 21:12:48 -07001079 if (ret) {
Zach Reiznerfd6dc332015-10-13 21:12:48 -07001080 return;
1081 }
1082
1083 uint64_t cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
1084 uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
1085 float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;
1086
1087 *out << "--DrmDisplayCompositor[" << display_
1088 << "]: num_frames=" << num_frames << " num_ms=" << num_ms
1089 << " fps=" << fps << "\n";
1090
1091 dump_last_timestamp_ns_ = cur_ts;
1092
Adrian Salido0e892682017-03-01 14:57:39 -08001093 *out << "----Jank Stats: "
1094 << " compositor_max_q_wait_us=" << max_duration_us
1095 << " frameworker_max_q_wait_us=" << frame_worker_.max_duration_us
1096 << "\n";
1097
1098 max_duration_us = 0;
1099 frame_worker_.max_duration_us = 0;
1100
Zach Reiznerfd6dc332015-10-13 21:12:48 -07001101 if (active_composition_)
1102 active_composition_->Dump(out);
1103
Zach Reizner5757e822015-10-16 19:06:31 -07001104 squash_state_.Dump(out);
Adrian Salido0e892682017-03-01 14:57:39 -08001105}
Zach Reizner5757e822015-10-16 19:06:31 -07001106
Adrian Salido0e892682017-03-01 14:57:39 -08001107void DrmDisplayCompositor::ProcessIdle() {
1108 SquashAll();
Sean Paul98e73c82015-06-24 14:38:49 -07001109}
1110}