blob: 642a1c7d1c47cf2096596ef42284924e9b8be6c7 [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(),
Rob Clark90f92d82016-10-19 10:48:14 -0400378 regions.data(), regions.size(), fb.buffer(),
379 display_comp->importer());
Zach Reizner5757e822015-10-16 19:06:31 -0700380 pre_compositor_->Finish();
381
382 if (ret) {
383 ALOGE("Failed to squash layers");
384 return ret;
385 }
386
387 ret = display_comp->CreateNextTimelineFence();
388 if (ret <= 0) {
389 ALOGE("Failed to create squash framebuffer release fence %d", ret);
390 return ret;
391 }
392
393 fb.set_release_fence_fd(ret);
394 display_comp->SignalSquashDone();
395
396 return 0;
397}
398
Zach Reizner713a6782015-07-31 15:12:44 -0700399int DrmDisplayCompositor::ApplyPreComposite(
400 DrmDisplayComposition *display_comp) {
401 int ret = 0;
Zach Reizner713a6782015-07-31 15:12:44 -0700402
Zach Reizner713a6782015-07-31 15:12:44 -0700403 DrmFramebuffer &fb = framebuffers_[framebuffer_index_];
Zach Reizner92f8e632015-10-12 17:47:13 -0700404 ret = PrepareFramebuffer(fb, display_comp);
Zach Reizner713a6782015-07-31 15:12:44 -0700405 if (ret) {
Zach Reizner5757e822015-10-16 19:06:31 -0700406 ALOGE("Failed to prepare framebuffer for pre-composite %d", ret);
Zach Reizner713a6782015-07-31 15:12:44 -0700407 return ret;
408 }
Zach Reizner713a6782015-07-31 15:12:44 -0700409
Zach Reizner92f8e632015-10-12 17:47:13 -0700410 std::vector<DrmCompositionRegion> &regions = display_comp->pre_comp_regions();
411 ret = pre_compositor_->Composite(display_comp->layers().data(),
Rob Clark90f92d82016-10-19 10:48:14 -0400412 regions.data(), regions.size(), fb.buffer(),
413 display_comp->importer());
Zach Reizner8d63e7f2015-08-20 14:52:12 -0700414 pre_compositor_->Finish();
Zach Reiznerb44fd102015-08-07 16:00:01 -0700415
Zach Reizner713a6782015-07-31 15:12:44 -0700416 if (ret) {
Zach Reizner5757e822015-10-16 19:06:31 -0700417 ALOGE("Failed to pre-composite layers");
Zach Reizner713a6782015-07-31 15:12:44 -0700418 return ret;
419 }
420
Zach Reizner92f8e632015-10-12 17:47:13 -0700421 ret = display_comp->CreateNextTimelineFence();
422 if (ret <= 0) {
Zach Reizner5757e822015-10-16 19:06:31 -0700423 ALOGE("Failed to create pre-composite framebuffer release fence %d", ret);
Zach Reizner09807052015-08-13 14:53:41 -0700424 return ret;
425 }
Zach Reizner713a6782015-07-31 15:12:44 -0700426
Zach Reizner92f8e632015-10-12 17:47:13 -0700427 fb.set_release_fence_fd(ret);
428 display_comp->SignalPreCompDone();
Zach Reizner713a6782015-07-31 15:12:44 -0700429
Zach Reizner92f8e632015-10-12 17:47:13 -0700430 return 0;
Zach Reizner713a6782015-07-31 15:12:44 -0700431}
432
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400433int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) {
Rob Herringb02d8582016-02-04 14:01:24 -0600434 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400435 if (!pset) {
436 ALOGE("Failed to allocate property set");
437 return -ENOMEM;
438 }
439
440 int ret;
Zach Reizner92f8e632015-10-12 17:47:13 -0700441 std::vector<DrmCompositionPlane> &comp_planes =
442 display_comp->composition_planes();
443 for (DrmCompositionPlane &comp_plane : comp_planes) {
Sean Paul9b707172016-05-11 16:29:45 -0400444 DrmPlane *plane = comp_plane.plane();
Rob Herringb02d8582016-02-04 14:01:24 -0600445 ret = drmModeAtomicAddProperty(pset, plane->id(),
446 plane->crtc_property().id(), 0) < 0 ||
447 drmModeAtomicAddProperty(pset, plane->id(), plane->fb_property().id(),
448 0) < 0;
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400449 if (ret) {
450 ALOGE("Failed to add plane %d disable to pset", plane->id());
Rob Herringb02d8582016-02-04 14:01:24 -0600451 drmModeAtomicFree(pset);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400452 return ret;
453 }
454 }
455
Rob Herringb02d8582016-02-04 14:01:24 -0600456 ret = drmModeAtomicCommit(drm_->fd(), pset, 0, drm_);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400457 if (ret) {
458 ALOGE("Failed to commit pset ret=%d\n", ret);
Rob Herringb02d8582016-02-04 14:01:24 -0600459 drmModeAtomicFree(pset);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400460 return ret;
461 }
462
Rob Herringb02d8582016-02-04 14:01:24 -0600463 drmModeAtomicFree(pset);
Sean Paul7b1e4bc2015-10-13 15:47:22 -0400464 return 0;
465}
466
Haixia Shidda2fab2015-10-22 18:12:49 -0700467int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) {
Sean Paul98e73c82015-06-24 14:38:49 -0700468 int ret = 0;
469
Zach Reizner92f8e632015-10-12 17:47:13 -0700470 std::vector<DrmHwcLayer> &layers = display_comp->layers();
471 std::vector<DrmCompositionPlane> &comp_planes =
472 display_comp->composition_planes();
Zach Reizner5757e822015-10-16 19:06:31 -0700473 std::vector<DrmCompositionRegion> &squash_regions =
474 display_comp->squash_regions();
Zach Reizner92f8e632015-10-12 17:47:13 -0700475 std::vector<DrmCompositionRegion> &pre_comp_regions =
476 display_comp->pre_comp_regions();
477
Zach Reizner5757e822015-10-16 19:06:31 -0700478 int squash_layer_index = -1;
479 if (squash_regions.size() > 0) {
480 squash_framebuffer_index_ = (squash_framebuffer_index_ + 1) % 2;
481 ret = ApplySquash(display_comp);
482 if (ret)
483 return ret;
Zach Reizner92f8e632015-10-12 17:47:13 -0700484
Zach Reizner5757e822015-10-16 19:06:31 -0700485 squash_layer_index = layers.size() - 1;
486 } else {
487 if (UsesSquash(comp_planes)) {
488 DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_];
489 layers.emplace_back();
490 squash_layer_index = layers.size() - 1;
491 DrmHwcLayer &squash_layer = layers.back();
492 ret = squash_layer.buffer.ImportBuffer(fb.buffer()->handle,
493 display_comp->importer());
494 if (ret) {
495 ALOGE("Failed to import old squashed framebuffer %d", ret);
496 return ret;
497 }
498 squash_layer.sf_handle = fb.buffer()->handle;
Haixia Shi0c7da1e2015-11-23 11:34:36 -0800499 squash_layer.blending = DrmHwcBlending::kPreMult;
Zach Reizner5757e822015-10-16 19:06:31 -0700500 squash_layer.source_crop = DrmHwcRect<float>(
501 0, 0, squash_layer.buffer->width, squash_layer.buffer->height);
502 squash_layer.display_frame = DrmHwcRect<int>(
503 0, 0, squash_layer.buffer->width, squash_layer.buffer->height);
504 ret = display_comp->CreateNextTimelineFence();
505
506 if (ret <= 0) {
507 ALOGE("Failed to create squash framebuffer release fence %d", ret);
508 return ret;
509 }
510
511 fb.set_release_fence_fd(ret);
512 ret = 0;
513 }
514 }
515
516 bool do_pre_comp = pre_comp_regions.size() > 0;
517 int pre_comp_layer_index = -1;
Zach Reizner92f8e632015-10-12 17:47:13 -0700518 if (do_pre_comp) {
Zach Reizner713a6782015-07-31 15:12:44 -0700519 ret = ApplyPreComposite(display_comp);
520 if (ret)
521 return ret;
Zach Reizner92f8e632015-10-12 17:47:13 -0700522
523 pre_comp_layer_index = layers.size() - 1;
524 framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
Zach Reizner713a6782015-07-31 15:12:44 -0700525 }
526
Haixia Shidda2fab2015-10-22 18:12:49 -0700527 for (DrmCompositionPlane &comp_plane : comp_planes) {
Sean Paul9b707172016-05-11 16:29:45 -0400528 std::vector<size_t> &source_layers = comp_plane.source_layers();
529 switch (comp_plane.type()) {
Sean Paul7379ecd2016-05-11 16:57:26 -0400530 case DrmCompositionPlane::Type::kSquash:
Sean Paul9b707172016-05-11 16:29:45 -0400531 if (source_layers.size())
532 ALOGE("Squash source_layers is expected to be empty (%zu/%d)",
533 source_layers[0], squash_layer_index);
534 source_layers.push_back(squash_layer_index);
Haixia Shidda2fab2015-10-22 18:12:49 -0700535 break;
Sean Paul7379ecd2016-05-11 16:57:26 -0400536 case DrmCompositionPlane::Type::kPrecomp:
Haixia Shidda2fab2015-10-22 18:12:49 -0700537 if (!do_pre_comp) {
538 ALOGE(
539 "Can not use pre composite framebuffer with no pre composite "
540 "regions");
541 return -EINVAL;
542 }
Sean Paul9b707172016-05-11 16:29:45 -0400543 // Replace source_layers with the output of the precomposite
544 source_layers.clear();
545 source_layers.push_back(pre_comp_layer_index);
Haixia Shidda2fab2015-10-22 18:12:49 -0700546 break;
547 default:
548 break;
549 }
550 }
551
552 return ret;
553}
554
Sean Paulc07b2112015-11-17 16:38:10 -0500555int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
556 bool test_only) {
Haixia Shi3979f7d2015-10-29 14:33:37 -0700557 ATRACE_CALL();
558
Haixia Shidda2fab2015-10-22 18:12:49 -0700559 int ret = 0;
560
561 std::vector<DrmHwcLayer> &layers = display_comp->layers();
562 std::vector<DrmCompositionPlane> &comp_planes =
563 display_comp->composition_planes();
564 std::vector<DrmCompositionRegion> &pre_comp_regions =
565 display_comp->pre_comp_regions();
566
Sean Paul57355412015-09-19 09:14:34 -0400567 DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
568 if (!connector) {
569 ALOGE("Could not locate connector for display %d", display_);
570 return -ENODEV;
571 }
572 DrmCrtc *crtc = drm_->GetCrtcForDisplay(display_);
573 if (!crtc) {
574 ALOGE("Could not locate crtc for display %d", display_);
575 return -ENODEV;
576 }
577
Rob Herringb02d8582016-02-04 14:01:24 -0600578 drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
Sean Paul98e73c82015-06-24 14:38:49 -0700579 if (!pset) {
580 ALOGE("Failed to allocate property set");
581 return -ENOMEM;
582 }
583
Sean Paul35301f42015-11-17 14:46:56 -0500584 if (mode_.needs_modeset) {
Rob Herringb02d8582016-02-04 14:01:24 -0600585 ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->mode_property().id(),
586 mode_.blob_id) < 0 ||
587 drmModeAtomicAddProperty(pset, connector->id(),
588 connector->crtc_id_property().id(),
589 crtc->id()) < 0;
Sean Paul57355412015-09-19 09:14:34 -0400590 if (ret) {
Sean Paul35301f42015-11-17 14:46:56 -0500591 ALOGE("Failed to add blob %d to pset", mode_.blob_id);
Rob Herringb02d8582016-02-04 14:01:24 -0600592 drmModeAtomicFree(pset);
Sean Paul57355412015-09-19 09:14:34 -0400593 return ret;
594 }
595 }
596
Zach Reizner92f8e632015-10-12 17:47:13 -0700597 for (DrmCompositionPlane &comp_plane : comp_planes) {
Sean Paul9b707172016-05-11 16:29:45 -0400598 DrmPlane *plane = comp_plane.plane();
599 DrmCrtc *crtc = comp_plane.crtc();
600 std::vector<size_t> &source_layers = comp_plane.source_layers();
Zach Reizner92f8e632015-10-12 17:47:13 -0700601
602 int fb_id = -1;
603 DrmHwcRect<int> display_frame;
604 DrmHwcRect<float> source_crop;
605 uint64_t rotation = 0;
Sean Pauld8aefb62015-10-15 15:17:31 -0400606 uint64_t alpha = 0xFF;
Sean Paul04b47ea2015-11-19 21:46:11 -0500607
Sean Paul7379ecd2016-05-11 16:57:26 -0400608 if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
Sean Paul9b707172016-05-11 16:29:45 -0400609 if (source_layers.size() > 1) {
610 ALOGE("Can't handle more than one source layer sz=%zu type=%d",
611 source_layers.size(), comp_plane.type());
612 continue;
613 }
614
615 if (source_layers.empty() || source_layers.front() >= layers.size()) {
616 ALOGE("Source layer index %zu out of bounds %zu type=%d",
617 source_layers.front(), layers.size(), comp_plane.type());
Sean Paul07aa8cc2016-05-11 13:50:28 -0400618 break;
Sean Paul98e73c82015-06-24 14:38:49 -0700619 }
Sean Paul9b707172016-05-11 16:29:45 -0400620 DrmHwcLayer &layer = layers[source_layers.front()];
Sean Paul07aa8cc2016-05-11 13:50:28 -0400621 if (!test_only && layer.acquire_fence.get() >= 0) {
622 int acquire_fence = layer.acquire_fence.get();
623 int total_fence_timeout = 0;
624 for (int i = 0; i < kAcquireWaitTries; ++i) {
625 int fence_timeout = kAcquireWaitTimeoutMs * (1 << i);
626 total_fence_timeout += fence_timeout;
627 ret = sync_wait(acquire_fence, fence_timeout);
628 if (ret)
629 ALOGW("Acquire fence %d wait %d failed (%d). Total time %d",
630 acquire_fence, i, ret, total_fence_timeout);
Sean Pauld4a0a3d2016-03-10 15:18:42 -0500631 else
632 break;
Sean Paul07aa8cc2016-05-11 13:50:28 -0400633 }
634 if (ret) {
635 ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
636 break;
637 }
638 layer.acquire_fence.Close();
639 }
640 if (!layer.buffer) {
641 ALOGE("Expected a valid framebuffer for pset");
642 break;
643 }
644 fb_id = layer.buffer->fb_id;
645 display_frame = layer.display_frame;
646 source_crop = layer.source_crop;
647 if (layer.blending == DrmHwcBlending::kPreMult)
648 alpha = layer.alpha;
Sean Paul98e73c82015-06-24 14:38:49 -0700649
Sean Paul07aa8cc2016-05-11 13:50:28 -0400650 rotation = 0;
651 if (layer.transform & DrmHwcTransform::kFlipH)
652 rotation |= 1 << DRM_REFLECT_X;
653 if (layer.transform & DrmHwcTransform::kFlipV)
654 rotation |= 1 << DRM_REFLECT_Y;
655 if (layer.transform & DrmHwcTransform::kRotate90)
656 rotation |= 1 << DRM_ROTATE_90;
657 else if (layer.transform & DrmHwcTransform::kRotate180)
658 rotation |= 1 << DRM_ROTATE_180;
659 else if (layer.transform & DrmHwcTransform::kRotate270)
660 rotation |= 1 << DRM_ROTATE_270;
661 }
Zach Reizner92f8e632015-10-12 17:47:13 -0700662 // Disable the plane if there's no framebuffer
663 if (fb_id < 0) {
Rob Herringb02d8582016-02-04 14:01:24 -0600664 ret = drmModeAtomicAddProperty(pset, plane->id(),
665 plane->crtc_property().id(), 0) < 0 ||
666 drmModeAtomicAddProperty(pset, plane->id(),
667 plane->fb_property().id(), 0) < 0;
Sean Paul2e46fbd2015-07-09 17:22:22 -0400668 if (ret) {
669 ALOGE("Failed to add plane %d disable to pset", plane->id());
670 break;
671 }
672 continue;
673 }
674
Sean Paul1c4c3262015-07-14 15:51:52 -0400675 // TODO: Once we have atomic test, this should fall back to GL
676 if (rotation && plane->rotation_property().id() == 0) {
677 ALOGE("Rotation is not supported on plane %d", plane->id());
678 ret = -EINVAL;
679 break;
680 }
681
Sean Pauld8aefb62015-10-15 15:17:31 -0400682 // TODO: Once we have atomic test, this should fall back to GL
683 if (alpha != 0xFF && plane->alpha_property().id() == 0) {
684 ALOGE("Alpha is not supported on plane %d", plane->id());
685 ret = -EINVAL;
686 break;
687 }
688
Rob Herringb02d8582016-02-04 14:01:24 -0600689 ret = drmModeAtomicAddProperty(pset, plane->id(),
690 plane->crtc_property().id(), crtc->id()) < 0;
691 ret |= drmModeAtomicAddProperty(pset, plane->id(),
692 plane->fb_property().id(), fb_id) < 0;
693 ret |= drmModeAtomicAddProperty(pset, plane->id(),
694 plane->crtc_x_property().id(),
695 display_frame.left) < 0;
696 ret |= drmModeAtomicAddProperty(pset, plane->id(),
697 plane->crtc_y_property().id(),
698 display_frame.top) < 0;
699 ret |= drmModeAtomicAddProperty(
700 pset, plane->id(), plane->crtc_w_property().id(),
701 display_frame.right - display_frame.left) < 0;
702 ret |= drmModeAtomicAddProperty(
703 pset, plane->id(), plane->crtc_h_property().id(),
704 display_frame.bottom - display_frame.top) < 0;
705 ret |= drmModeAtomicAddProperty(pset, plane->id(),
706 plane->src_x_property().id(),
707 (int)(source_crop.left) << 16) < 0;
708 ret |= drmModeAtomicAddProperty(pset, plane->id(),
709 plane->src_y_property().id(),
710 (int)(source_crop.top) << 16) < 0;
711 ret |= drmModeAtomicAddProperty(
712 pset, plane->id(), plane->src_w_property().id(),
713 (int)(source_crop.right - source_crop.left) << 16) < 0;
714 ret |= drmModeAtomicAddProperty(
715 pset, plane->id(), plane->src_h_property().id(),
716 (int)(source_crop.bottom - source_crop.top) << 16) < 0;
Sean Paul98e73c82015-06-24 14:38:49 -0700717 if (ret) {
718 ALOGE("Failed to add plane %d to set", plane->id());
719 break;
720 }
Sean Paul1c4c3262015-07-14 15:51:52 -0400721
722 if (plane->rotation_property().id()) {
Rob Herringb02d8582016-02-04 14:01:24 -0600723 ret = drmModeAtomicAddProperty(pset, plane->id(),
724 plane->rotation_property().id(),
725 rotation) < 0;
Sean Paul1c4c3262015-07-14 15:51:52 -0400726 if (ret) {
727 ALOGE("Failed to add rotation property %d to plane %d",
728 plane->rotation_property().id(), plane->id());
729 break;
730 }
731 }
Sean Pauld8aefb62015-10-15 15:17:31 -0400732
733 if (plane->alpha_property().id()) {
Rob Herringb02d8582016-02-04 14:01:24 -0600734 ret = drmModeAtomicAddProperty(pset, plane->id(),
735 plane->alpha_property().id(),
736 alpha) < 0;
Sean Pauld8aefb62015-10-15 15:17:31 -0400737 if (ret) {
738 ALOGE("Failed to add alpha property %d to plane %d",
739 plane->alpha_property().id(), plane->id());
740 break;
741 }
742 }
Sean Paul98e73c82015-06-24 14:38:49 -0700743 }
744
Zach Reizner92f8e632015-10-12 17:47:13 -0700745out:
Sean Paul98e73c82015-06-24 14:38:49 -0700746 if (!ret) {
Sean Paulc07b2112015-11-17 16:38:10 -0500747 uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
748 if (test_only)
749 flags |= DRM_MODE_ATOMIC_TEST_ONLY;
750
Rob Herringb02d8582016-02-04 14:01:24 -0600751 ret = drmModeAtomicCommit(drm_->fd(), pset, flags, drm_);
Sean Paul57355412015-09-19 09:14:34 -0400752 if (ret) {
Sean Paulc07b2112015-11-17 16:38:10 -0500753 if (test_only)
754 ALOGI("Commit test pset failed ret=%d\n", ret);
755 else
756 ALOGE("Failed to commit pset ret=%d\n", ret);
Rob Herringb02d8582016-02-04 14:01:24 -0600757 drmModeAtomicFree(pset);
Sean Paul57355412015-09-19 09:14:34 -0400758 return ret;
759 }
Sean Paul98e73c82015-06-24 14:38:49 -0700760 }
761 if (pset)
Rob Herringb02d8582016-02-04 14:01:24 -0600762 drmModeAtomicFree(pset);
Sean Paul98e73c82015-06-24 14:38:49 -0700763
Sean Paulc07b2112015-11-17 16:38:10 -0500764 if (!test_only && mode_.needs_modeset) {
Sean Paul35301f42015-11-17 14:46:56 -0500765 ret = drm_->DestroyPropertyBlob(mode_.old_blob_id);
Sean Paul57355412015-09-19 09:14:34 -0400766 if (ret) {
Sean Paul717a44b2016-05-11 13:49:38 -0400767 ALOGE("Failed to destroy old mode property blob %" PRIu32 "/%d",
Sean Paul35301f42015-11-17 14:46:56 -0500768 mode_.old_blob_id, ret);
Sean Paul57355412015-09-19 09:14:34 -0400769 return ret;
770 }
771
772 /* TODO: Add dpms to the pset when the kernel supports it */
773 ret = ApplyDpms(display_comp);
774 if (ret) {
775 ALOGE("Failed to apply DPMS after modeset %d\n", ret);
776 return ret;
777 }
778
Sean Paul35301f42015-11-17 14:46:56 -0500779 connector->set_active_mode(mode_.mode);
780 mode_.old_blob_id = mode_.blob_id;
781 mode_.blob_id = 0;
782 mode_.needs_modeset = false;
Sean Paul57355412015-09-19 09:14:34 -0400783 }
784
Sean Paul98e73c82015-06-24 14:38:49 -0700785 return ret;
786}
787
Sean Pauldb7a17d2015-06-24 18:46:05 -0700788int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
789 DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
790 if (!conn) {
791 ALOGE("Failed to get DrmConnector for display %d", display_);
792 return -ENODEV;
793 }
794
795 const DrmProperty &prop = conn->dpms_property();
796 int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
797 display_comp->dpms_mode());
798 if (ret) {
799 ALOGE("Failed to set DPMS property for connector %d", conn->id());
800 return ret;
801 }
802 return 0;
803}
804
Sean Paul35301f42015-11-17 14:46:56 -0500805std::tuple<int, uint32_t> DrmDisplayCompositor::CreateModeBlob(
806 const DrmMode &mode) {
807 struct drm_mode_modeinfo drm_mode;
808 memset(&drm_mode, 0, sizeof(drm_mode));
809 mode.ToDrmModeModeInfo(&drm_mode);
810
811 uint32_t id = 0;
812 int ret = drm_->CreatePropertyBlob(&drm_mode,
813 sizeof(struct drm_mode_modeinfo), &id);
814 if (ret) {
815 ALOGE("Failed to create mode property blob %d", ret);
816 return std::make_tuple(ret, 0);
817 }
Sean Paul717a44b2016-05-11 13:49:38 -0400818 ALOGE("Create blob_id %" PRIu32 "\n", id);
Sean Paul35301f42015-11-17 14:46:56 -0500819 return std::make_tuple(ret, id);
820}
821
Sean Paulb4cf01b2016-06-22 22:48:22 -0400822void DrmDisplayCompositor::ClearDisplay() {
Adrian Salido0e892682017-03-01 14:57:39 -0800823 std::lock_guard<std::mutex> lk(mutex_);
Sean Paulb4cf01b2016-06-22 22:48:22 -0400824 if (!active_composition_)
825 return;
826
827 if (DisablePlanes(active_composition_.get()))
828 return;
829
830 active_composition_->SignalCompositionDone();
831
832 active_composition_.reset(NULL);
833}
834
Haixia Shidda2fab2015-10-22 18:12:49 -0700835void DrmDisplayCompositor::ApplyFrame(
836 std::unique_ptr<DrmDisplayComposition> composition, int status) {
837 int ret = status;
838
839 if (!ret)
Sean Paulc07b2112015-11-17 16:38:10 -0500840 ret = CommitFrame(composition.get(), false);
Haixia Shidda2fab2015-10-22 18:12:49 -0700841
842 if (ret) {
843 ALOGE("Composite failed for display %d", display_);
Haixia Shidda2fab2015-10-22 18:12:49 -0700844 // Disable the hw used by the last active composition. This allows us to
845 // signal the release fences from that composition to avoid hanging.
Sean Paulb4cf01b2016-06-22 22:48:22 -0400846 ClearDisplay();
847 return;
Haixia Shidda2fab2015-10-22 18:12:49 -0700848 }
849 ++dump_frames_composited_;
850
851 if (active_composition_)
852 active_composition_->SignalCompositionDone();
853
Adrian Salido0e892682017-03-01 14:57:39 -0800854 std::lock_guard<std::mutex> lk(mutex_);
Haixia Shidda2fab2015-10-22 18:12:49 -0700855 active_composition_.swap(composition);
Haixia Shidda2fab2015-10-22 18:12:49 -0700856}
857
Adrian Salido0e892682017-03-01 14:57:39 -0800858void DrmDisplayCompositor::ProcessWork(
859 std::unique_ptr<DrmDisplayComposition> composition) {
Sean Paul98e73c82015-06-24 14:38:49 -0700860 ATRACE_CALL();
Zach Reizner09807052015-08-13 14:53:41 -0700861
862 if (!pre_compositor_) {
863 pre_compositor_.reset(new GLWorkerCompositor());
864 int ret = pre_compositor_->Init();
865 if (ret) {
866 ALOGE("Failed to initialize OpenGL compositor %d", ret);
Adrian Salido0e892682017-03-01 14:57:39 -0800867 return;
Zach Reizner09807052015-08-13 14:53:41 -0700868 }
869 }
870
Adrian Salido0e892682017-03-01 14:57:39 -0800871 int ret;
Sean Paulacb2a442015-06-24 18:43:01 -0700872 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700873 case DRM_COMPOSITION_TYPE_FRAME:
Sean Paule3141c62015-11-30 14:35:45 -0500874 ret = PrepareFrame(composition.get());
875 if (ret) {
876 ALOGE("Failed to prepare frame for display %d", display_);
Adrian Salido0e892682017-03-01 14:57:39 -0800877 return;
Sean Paul647beb22015-11-19 13:55:48 -0500878 }
Haixia Shi6afbb6a2015-11-24 12:42:45 -0800879 if (composition->geometry_changed()) {
880 // Send the composition to the kernel to ensure we can commit it. This
881 // is just a test, it won't actually commit the frame. If rejected,
882 // squash the frame into one layer and use the squashed composition
883 ret = CommitFrame(composition.get(), true);
Sean Paul6c18b3b2015-11-25 11:04:25 -0500884 if (ret)
Haixia Shi6afbb6a2015-11-24 12:42:45 -0800885 ALOGI("Commit test failed, squashing frame for display %d", display_);
Sean Paul6c18b3b2015-11-25 11:04:25 -0500886 use_hw_overlays_ = !ret;
887 }
888
889 // If use_hw_overlays_ is false, we can't use hardware to composite the
890 // frame. So squash all layers into a single composition and queue that
891 // instead.
892 if (!use_hw_overlays_) {
893 std::unique_ptr<DrmDisplayComposition> squashed = CreateComposition();
894 ret = SquashFrame(composition.get(), squashed.get());
895 if (!ret) {
896 composition = std::move(squashed);
897 } else {
898 ALOGE("Failed to squash frame for display %d", display_);
Sean Paulb4cf01b2016-06-22 22:48:22 -0400899 // Disable the hw used by the last active composition. This allows us
900 // to signal the release fences from that composition to avoid
901 // hanging.
902 ClearDisplay();
Adrian Salido0e892682017-03-01 14:57:39 -0800903 return;
Sean Paul647beb22015-11-19 13:55:48 -0500904 }
905 }
Haixia Shidda2fab2015-10-22 18:12:49 -0700906 frame_worker_.QueueFrame(std::move(composition), ret);
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700907 break;
908 case DRM_COMPOSITION_TYPE_DPMS:
909 ret = ApplyDpms(composition.get());
910 if (ret)
911 ALOGE("Failed to apply dpms for display %d", display_);
Adrian Salido0e892682017-03-01 14:57:39 -0800912 break;
Sean Paul57355412015-09-19 09:14:34 -0400913 case DRM_COMPOSITION_TYPE_MODESET:
Sean Paul35301f42015-11-17 14:46:56 -0500914 mode_.mode = composition->display_mode();
915 if (mode_.blob_id)
916 drm_->DestroyPropertyBlob(mode_.blob_id);
917 std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode);
918 if (ret) {
919 ALOGE("Failed to create mode blob for display %d", display_);
Adrian Salido0e892682017-03-01 14:57:39 -0800920 return;
Sean Paul35301f42015-11-17 14:46:56 -0500921 }
922 mode_.needs_modeset = true;
Adrian Salido0e892682017-03-01 14:57:39 -0800923 break;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700924 default:
925 ALOGE("Unknown composition type %d", composition->type());
Adrian Salido0e892682017-03-01 14:57:39 -0800926 break;
Sean Paul98e73c82015-06-24 14:38:49 -0700927 }
Sean Paul98e73c82015-06-24 14:38:49 -0700928}
929
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800930int DrmDisplayCompositor::SquashAll() {
Adrian Salido0e892682017-03-01 14:57:39 -0800931 std::unique_lock<std::mutex> lk(mutex_);
932 int ret;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800933
934 if (!active_composition_)
935 return 0;
936
Sean Pauld51c7612015-11-18 14:12:51 -0500937 std::unique_ptr<DrmDisplayComposition> comp = CreateComposition();
938 ret = SquashFrame(active_composition_.get(), comp.get());
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800939
Sean Pauld51c7612015-11-18 14:12:51 -0500940 // ApplyFrame needs the lock
Adrian Salido0e892682017-03-01 14:57:39 -0800941 lk.unlock();
Sean Pauld51c7612015-11-18 14:12:51 -0500942
943 if (!ret)
944 ApplyFrame(std::move(comp), 0);
945
946 return ret;
947}
948
949// Returns:
950// - 0 if src is successfully squashed into dst
951// - -EALREADY if the src is already squashed
952// - Appropriate error if the squash fails
953int DrmDisplayCompositor::SquashFrame(DrmDisplayComposition *src,
954 DrmDisplayComposition *dst) {
955 if (src->type() != DRM_COMPOSITION_TYPE_FRAME)
956 return -ENOTSUP;
957
958 std::vector<DrmCompositionPlane> &src_planes = src->composition_planes();
959 std::vector<DrmHwcLayer> &src_layers = src->layers();
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800960
961 // Make sure there is more than one layer to squash.
Sean Pauld51c7612015-11-18 14:12:51 -0500962 size_t src_planes_with_layer = std::count_if(
963 src_planes.begin(), src_planes.end(), [](DrmCompositionPlane &p) {
Sean Paulc74c8b92016-06-22 23:26:29 -0400964 return p.type() != DrmCompositionPlane::Type::kDisable;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800965 });
Sean Pauld51c7612015-11-18 14:12:51 -0500966 if (src_planes_with_layer <= 1)
967 return -EALREADY;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800968
969 int pre_comp_layer_index;
970
Sean Paul8cc4e2a2016-05-12 14:28:05 -0400971 int ret = dst->Init(drm_, src->crtc(), src->importer(), src->planner(),
972 src->frame_no());
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800973 if (ret) {
974 ALOGE("Failed to init squash all composition %d", ret);
975 return ret;
976 }
977
Sean Paul8eb85ff2016-05-03 16:40:59 -0700978 DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kPrecomp, NULL,
979 src->crtc());
Sean Pauld51c7612015-11-18 14:12:51 -0500980 std::vector<DrmHwcLayer> dst_layers;
981 for (DrmCompositionPlane &comp_plane : src_planes) {
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800982 // Composition planes without DRM planes should never happen
Sean Paul9b707172016-05-11 16:29:45 -0400983 if (comp_plane.plane() == NULL) {
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800984 ALOGE("Skipping squash all because of NULL plane");
Sean Pauld51c7612015-11-18 14:12:51 -0500985 ret = -EINVAL;
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800986 goto move_layers_back;
987 }
988
Sean Paul8cc4e2a2016-05-12 14:28:05 -0400989 if (comp_plane.type() == DrmCompositionPlane::Type::kDisable) {
990 dst->AddPlaneDisable(comp_plane.plane());
Zach Reizner2b4b1ee2015-11-18 13:54:31 -0800991 continue;
Sean Paul8cc4e2a2016-05-12 14:28:05 -0400992 }
Zach Reizner2b4b1ee2015-11-18 13:54:31 -0800993
Sean Paul9b707172016-05-11 16:29:45 -0400994 for (auto i : comp_plane.source_layers()) {
995 DrmHwcLayer &layer = src_layers[i];
Zach Reiznerbff33ac2015-11-16 11:08:46 -0800996
Sean Paul9b707172016-05-11 16:29:45 -0400997 // Squashing protected layers is impossible.
998 if (layer.protected_usage()) {
999 ret = -ENOTSUP;
1000 goto move_layers_back;
1001 }
1002
1003 // The OutputFds point to freed memory after hwc_set returns. They are
1004 // returned to the default to prevent DrmDisplayComposition::Plan from
1005 // filling the OutputFds.
1006 layer.release_fence = OutputFd();
1007 dst_layers.emplace_back(std::move(layer));
Sean Paul8eb85ff2016-05-03 16:40:59 -07001008 squashed_comp.source_layers().push_back(
1009 squashed_comp.source_layers().size());
Sean Pauld51c7612015-11-18 14:12:51 -05001010 }
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001011
Sean Paul8eb85ff2016-05-03 16:40:59 -07001012 if (comp_plane.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
1013 squashed_comp.set_plane(comp_plane.plane());
Zach Reiznerbff33ac2015-11-16 11:08:46 -08001014 else
Sean Paul9b707172016-05-11 16:29:45 -04001015 dst->AddPlaneDisable(comp_plane.plane());
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}