blob: 457fb5a51fbf1d945cba3bb85dfa1baac7208313 [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 LOG_TAG "hwc-drm-display-composition"
18
19#include "drmdisplaycomposition.h"
20#include "drmcrtc.h"
21#include "drmplane.h"
22#include "drmresources.h"
23
24#include <stdlib.h>
25
26#include <cutils/log.h>
27#include <sw_sync.h>
28#include <sync/sync.h>
Sean Pauldb7a17d2015-06-24 18:46:05 -070029#include <xf86drmMode.h>
Sean Paul98e73c82015-06-24 14:38:49 -070030
31namespace android {
32
Zach Reizner4a253652015-09-10 18:30:54 -070033DrmCompositionLayer::DrmCompositionLayer(DrmCrtc *crtc, DrmHwcLayer &&l)
34 : crtc(crtc),
35 sf_handle(l.sf_handle),
36 buffer(std::move(l.buffer)),
37 handle(std::move(l.handle)),
38 transform(l.transform),
39 blending(l.blending),
40 alpha(l.alpha),
41 source_crop(l.source_crop),
42 display_frame(l.display_frame),
43 source_damage(l.source_damage),
44 acquire_fence(std::move(l.acquire_fence)) {
Sean Paul98e73c82015-06-24 14:38:49 -070045}
46
Sean Paul98e73c82015-06-24 14:38:49 -070047DrmDisplayComposition::DrmDisplayComposition()
Sean Paulacb2a442015-06-24 18:43:01 -070048 : drm_(NULL),
49 importer_(NULL),
50 type_(DRM_COMPOSITION_TYPE_EMPTY),
51 timeline_fd_(-1),
Sean Pauldb7a17d2015-06-24 18:46:05 -070052 timeline_(0),
Zach Reiznerece04892015-07-17 14:13:28 -070053 timeline_current_(0),
Zach Reizner09807052015-08-13 14:53:41 -070054 timeline_pre_comp_done_(0),
55 pre_composition_layer_index_(-1),
Sean Paulbdc67bf2015-09-21 10:04:02 -040056 dpms_mode_(DRM_MODE_DPMS_ON),
57 frame_no_(0) {
Sean Paul98e73c82015-06-24 14:38:49 -070058}
59
60DrmDisplayComposition::~DrmDisplayComposition() {
Zach Reiznerece04892015-07-17 14:13:28 -070061 if (timeline_fd_ >= 0) {
62 FinishComposition();
Sean Paul98e73c82015-06-24 14:38:49 -070063 close(timeline_fd_);
Zach Reiznerece04892015-07-17 14:13:28 -070064 timeline_fd_ = -1;
65 }
Sean Paul98e73c82015-06-24 14:38:49 -070066}
67
Zach Reizner09807052015-08-13 14:53:41 -070068int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
Sean Paulbdc67bf2015-09-21 10:04:02 -040069 Importer *importer, uint64_t frame_no) {
Sean Paul98e73c82015-06-24 14:38:49 -070070 drm_ = drm;
Zach Reizner4a253652015-09-10 18:30:54 -070071 crtc_ = crtc; // Can be NULL if we haven't modeset yet
Sean Paul98e73c82015-06-24 14:38:49 -070072 importer_ = importer;
Sean Paulbdc67bf2015-09-21 10:04:02 -040073 frame_no_ = frame_no;
Sean Paul98e73c82015-06-24 14:38:49 -070074
Zach Reizner4a253652015-09-10 18:30:54 -070075 int ret = sw_sync_timeline_create();
Sean Paul98e73c82015-06-24 14:38:49 -070076 if (ret < 0) {
77 ALOGE("Failed to create sw sync timeline %d", ret);
78 return ret;
79 }
80 timeline_fd_ = ret;
81 return 0;
82}
83
Sean Paulacb2a442015-06-24 18:43:01 -070084DrmCompositionType DrmDisplayComposition::type() const {
85 return type_;
86}
87
88bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
89 return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
90}
91
Zach Reizner09807052015-08-13 14:53:41 -070092static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
93 for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
94 if ((*iter)->GetCrtcSupported(*crtc)) {
95 DrmPlane *plane = *iter;
96 planes->erase(iter);
97 return plane;
98 }
Zach Reiznerb44fd102015-08-07 16:00:01 -070099 }
Zach Reizner09807052015-08-13 14:53:41 -0700100 return NULL;
Sean Paul98e73c82015-06-24 14:38:49 -0700101}
102
Zach Reizner09807052015-08-13 14:53:41 -0700103static DrmPlane *TakePlane(DrmCrtc *crtc,
104 std::vector<DrmPlane *> *primary_planes,
105 std::vector<DrmPlane *> *overlay_planes) {
106 DrmPlane *plane = TakePlane(crtc, primary_planes);
107 if (plane)
108 return plane;
109 return TakePlane(crtc, overlay_planes);
110}
Zach Reizner713a6782015-07-31 15:12:44 -0700111
Zach Reizner09807052015-08-13 14:53:41 -0700112int DrmDisplayComposition::CreateNextTimelineFence() {
113 ++timeline_;
114 return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
115}
Zach Reizner713a6782015-07-31 15:12:44 -0700116
Zach Reizner09807052015-08-13 14:53:41 -0700117int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
118 int timeline_increase = point - timeline_current_;
119 if (timeline_increase <= 0)
120 return 0;
Zach Reizner713a6782015-07-31 15:12:44 -0700121
Zach Reizner09807052015-08-13 14:53:41 -0700122 int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
Zach Reizner713a6782015-07-31 15:12:44 -0700123 if (ret)
Zach Reizner09807052015-08-13 14:53:41 -0700124 ALOGE("Failed to increment sync timeline %d", ret);
125 else
126 timeline_current_ = point;
Zach Reizner713a6782015-07-31 15:12:44 -0700127
128 return ret;
129}
130
Zach Reizner4a253652015-09-10 18:30:54 -0700131int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
Zach Reizner09807052015-08-13 14:53:41 -0700132 std::vector<DrmPlane *> *primary_planes,
133 std::vector<DrmPlane *> *overlay_planes) {
134 int ret = 0;
135 if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
136 return -EINVAL;
137
138 for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
Zach Reizner4a253652015-09-10 18:30:54 -0700139 DrmHwcLayer *layer = &layers[layer_index];
Zach Reizner09807052015-08-13 14:53:41 -0700140
Zach Reizner4a253652015-09-10 18:30:54 -0700141 layers_.emplace_back(crtc_, std::move(*layer));
142 DrmCompositionLayer *c_layer = &layers_.back();
Zach Reizner09807052015-08-13 14:53:41 -0700143
144 if (pre_composition_layer_index_ == -1) {
145 c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
146 if (c_layer->plane == NULL) {
147 if (layers_.size() <= 1) {
148 ALOGE("Failed to match any planes to the crtc of this display");
149 ret = -ENODEV;
150 goto fail;
151 }
152
153 layers_.emplace_back();
154 // c_layer's address might have changed when we resized the vector
155 c_layer = &layers_[layers_.size() - 2];
Zach Reizner4a253652015-09-10 18:30:54 -0700156 DrmCompositionLayer &pre_comp_layer = layers_.back();
Zach Reizner09807052015-08-13 14:53:41 -0700157 pre_comp_layer.crtc = crtc_;
Zach Reizner09807052015-08-13 14:53:41 -0700158
159 pre_composition_layer_index_ = layers_.size() - 1;
160
161 // This is all to fix up the previous layer, which has now become part
162 // of the set of pre-composition layers because we are stealing its
163 // plane.
Zach Reizner4a253652015-09-10 18:30:54 -0700164 DrmCompositionLayer &last_c_layer = layers_[layers_.size() - 3];
Zach Reizner09807052015-08-13 14:53:41 -0700165 std::swap(pre_comp_layer.plane, last_c_layer.plane);
Zach Reizner4a253652015-09-10 18:30:54 -0700166 OutputFd &last_release_fence = layers[layer_index - 1].release_fence;
167 last_release_fence.Set(CreateNextTimelineFence());
168 ret = last_release_fence.get();
Zach Reizner09807052015-08-13 14:53:41 -0700169 if (ret < 0) {
170 ALOGE("Could not create release fence %d", ret);
171 goto fail;
172 }
173 }
174 }
175
176 if (c_layer->plane == NULL) {
177 // Layers to be pre composited all get the earliest release fences as they
178 // will get released soonest.
Zach Reizner4a253652015-09-10 18:30:54 -0700179 layer->release_fence.Set(CreateNextTimelineFence());
180 ret = layer->release_fence.get();
Zach Reizner09807052015-08-13 14:53:41 -0700181 if (ret < 0) {
182 ALOGE("Could not create release fence %d", ret);
183 goto fail;
184 }
185 }
186 }
187
188 timeline_pre_comp_done_ = timeline_;
189
190 for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
Zach Reizner4a253652015-09-10 18:30:54 -0700191 DrmHwcLayer *layer = &layers[layer_index];
192 if (layer->release_fence.get() >= 0)
Zach Reizner09807052015-08-13 14:53:41 -0700193 continue;
194
Zach Reizner4a253652015-09-10 18:30:54 -0700195 ret = layer->release_fence.Set(CreateNextTimelineFence());
Zach Reizner09807052015-08-13 14:53:41 -0700196 if (ret < 0) {
197 ALOGE("Could not create release fence %d", ret);
198 goto fail;
199 }
200 }
201
Zach Reizner09807052015-08-13 14:53:41 -0700202 type_ = DRM_COMPOSITION_TYPE_FRAME;
203 return 0;
204
205fail:
206
207 for (size_t c_layer_index = 0; c_layer_index < layers_.size();
208 c_layer_index++) {
Zach Reizner4a253652015-09-10 18:30:54 -0700209 DrmCompositionLayer &c_layer = layers_[c_layer_index];
Zach Reizner09807052015-08-13 14:53:41 -0700210 if (c_layer.plane != NULL) {
211 std::vector<DrmPlane *> *return_to =
212 (c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
213 : overlay_planes;
214 return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
215 }
216 }
Zach Reizner4a253652015-09-10 18:30:54 -0700217
Zach Reizner09807052015-08-13 14:53:41 -0700218 layers_.clear();
219
Zach Reizner09807052015-08-13 14:53:41 -0700220 sw_sync_timeline_inc(timeline_fd_, timeline_ - timeline_current_);
221
222 timeline_ = timeline_current_;
223 return ret;
224}
225
226int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
Sean Pauldb7a17d2015-06-24 18:46:05 -0700227 if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
228 return -EINVAL;
229 dpms_mode_ = dpms_mode;
230 type_ = DRM_COMPOSITION_TYPE_DPMS;
231 return 0;
232}
233
Sean Paul2e46fbd2015-07-09 17:22:22 -0400234int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
Zach Reizner09807052015-08-13 14:53:41 -0700235 layers_.emplace_back();
Zach Reizner4a253652015-09-10 18:30:54 -0700236 DrmCompositionLayer &c_layer = layers_.back();
Sean Paul2e46fbd2015-07-09 17:22:22 -0400237 c_layer.crtc = NULL;
238 c_layer.plane = plane;
Sean Paul2e46fbd2015-07-09 17:22:22 -0400239 return 0;
240}
241
Zach Reiznerb44fd102015-08-07 16:00:01 -0700242void DrmDisplayComposition::RemoveNoPlaneLayers() {
Zach Reiznerb44fd102015-08-07 16:00:01 -0700243 layers_.erase(
244 std::remove_if(layers_.begin(), layers_.end(),
Zach Reizner4a253652015-09-10 18:30:54 -0700245 [](DrmCompositionLayer &l) { return l.plane == NULL; }),
Zach Reiznerb44fd102015-08-07 16:00:01 -0700246 layers_.end());
247}
248
Zach Reizner09807052015-08-13 14:53:41 -0700249int DrmDisplayComposition::SignalPreCompositionDone() {
250 return IncreaseTimelineToPoint(timeline_pre_comp_done_);
251}
252
Sean Paul98e73c82015-06-24 14:38:49 -0700253int DrmDisplayComposition::FinishComposition() {
Zach Reizner09807052015-08-13 14:53:41 -0700254 return IncreaseTimelineToPoint(timeline_);
Sean Paul98e73c82015-06-24 14:38:49 -0700255}
256
Zach Reizner4a253652015-09-10 18:30:54 -0700257std::vector<DrmCompositionLayer>
258 *DrmDisplayComposition::GetCompositionLayers() {
Sean Paul98e73c82015-06-24 14:38:49 -0700259 return &layers_;
260}
Sean Pauldb7a17d2015-06-24 18:46:05 -0700261
Zach Reizner09807052015-08-13 14:53:41 -0700262int DrmDisplayComposition::pre_composition_layer_index() const {
263 return pre_composition_layer_index_;
264}
265
Sean Pauldb7a17d2015-06-24 18:46:05 -0700266uint32_t DrmDisplayComposition::dpms_mode() const {
267 return dpms_mode_;
268}
Zach Reizner46ddd452015-07-30 08:10:14 -0700269
Sean Paulbdc67bf2015-09-21 10:04:02 -0400270uint64_t DrmDisplayComposition::frame_no() const {
271 return frame_no_;
272}
273
Zach Reizner46ddd452015-07-30 08:10:14 -0700274Importer *DrmDisplayComposition::importer() const {
275 return importer_;
276}
Sean Paul98e73c82015-06-24 14:38:49 -0700277}