blob: 5676f1dc116f4784db8406261bf216249121ded4 [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"
21#include "drmcrtc.h"
22#include "drmplane.h"
23#include "drmresources.h"
Zach Reizner713a6782015-07-31 15:12:44 -070024#include "glworker.h"
Sean Paul98e73c82015-06-24 14:38:49 -070025
Zach Reizner713a6782015-07-31 15:12:44 -070026#include <algorithm>
Sean Paul98e73c82015-06-24 14:38:49 -070027#include <pthread.h>
Zach Reiznerd410f042015-07-28 15:33:07 -070028#include <sched.h>
Sean Paul98e73c82015-06-24 14:38:49 -070029#include <sstream>
30#include <stdlib.h>
31#include <time.h>
32#include <vector>
33
Sean Paul1c4c3262015-07-14 15:51:52 -040034#include <drm/drm_mode.h>
Sean Paul98e73c82015-06-24 14:38:49 -070035#include <cutils/log.h>
36#include <sync/sync.h>
37#include <utils/Trace.h>
38
Zach Reiznerd410f042015-07-28 15:33:07 -070039#define DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH 3
40
Sean Paul98e73c82015-06-24 14:38:49 -070041namespace android {
42
43DrmDisplayCompositor::DrmDisplayCompositor()
44 : drm_(NULL),
45 display_(-1),
46 worker_(this),
Sean Paul98e73c82015-06-24 14:38:49 -070047 initialized_(false),
Sean Pauldb7a17d2015-06-24 18:46:05 -070048 active_(false),
Sean Paul57355412015-09-19 09:14:34 -040049 needs_modeset_(false),
Zach Reizner713a6782015-07-31 15:12:44 -070050 framebuffer_index_(0),
Sean Paul98e73c82015-06-24 14:38:49 -070051 dump_frames_composited_(0),
52 dump_last_timestamp_ns_(0) {
53 struct timespec ts;
54 if (clock_gettime(CLOCK_MONOTONIC, &ts))
55 return;
56 dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
57}
58
59DrmDisplayCompositor::~DrmDisplayCompositor() {
60 if (!initialized_)
61 return;
62
63 worker_.Exit();
64
65 int ret = pthread_mutex_lock(&lock_);
66 if (ret)
67 ALOGE("Failed to acquire compositor lock %d", ret);
68
69 while (!composite_queue_.empty()) {
70 composite_queue_.front().reset();
71 composite_queue_.pop();
72 }
73 active_composition_.reset();
74
75 ret = pthread_mutex_unlock(&lock_);
76 if (ret)
77 ALOGE("Failed to acquire compositor lock %d", ret);
78
79 pthread_mutex_destroy(&lock_);
80}
81
82int DrmDisplayCompositor::Init(DrmResources *drm, int display) {
83 drm_ = drm;
84 display_ = display;
85
86 int ret = pthread_mutex_init(&lock_, NULL);
87 if (ret) {
88 ALOGE("Failed to initialize drm compositor lock %d\n", ret);
89 return ret;
90 }
91 ret = worker_.Init();
92 if (ret) {
93 pthread_mutex_destroy(&lock_);
94 ALOGE("Failed to initialize compositor worker %d\n", ret);
95 return ret;
96 }
97
98 initialized_ = true;
99 return 0;
100}
101
102int DrmDisplayCompositor::QueueComposition(
103 std::unique_ptr<DrmDisplayComposition> composition) {
Sean Paulacb2a442015-06-24 18:43:01 -0700104 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700105 case DRM_COMPOSITION_TYPE_FRAME:
106 if (!active_)
107 return -ENODEV;
108 break;
109 case DRM_COMPOSITION_TYPE_DPMS:
110 /*
111 * Update the state as soon as we get it so we can start/stop queuing
112 * frames asap.
113 */
114 active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
115 break;
Sean Paul57355412015-09-19 09:14:34 -0400116 case DRM_COMPOSITION_TYPE_MODESET:
117 break;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700118 case DRM_COMPOSITION_TYPE_EMPTY:
119 return 0;
120 default:
121 ALOGE("Unknown composition type %d/%d", composition->type(), display_);
122 return -ENOENT;
Sean Paulacb2a442015-06-24 18:43:01 -0700123 }
Sean Paul98e73c82015-06-24 14:38:49 -0700124
125 int ret = pthread_mutex_lock(&lock_);
126 if (ret) {
127 ALOGE("Failed to acquire compositor lock %d", ret);
128 return ret;
129 }
130
Zach Reiznerd410f042015-07-28 15:33:07 -0700131 // Block the queue if it gets too large. Otherwise, SurfaceFlinger will start
132 // to eat our buffer handles when we get about 1 second behind.
133 while (composite_queue_.size() >= DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH) {
134 pthread_mutex_unlock(&lock_);
135 sched_yield();
136 pthread_mutex_lock(&lock_);
137 }
138
Sean Paul98e73c82015-06-24 14:38:49 -0700139 composite_queue_.push(std::move(composition));
140
141 ret = pthread_mutex_unlock(&lock_);
142 if (ret) {
143 ALOGE("Failed to release compositor lock %d", ret);
144 return ret;
145 }
146
147 worker_.Signal();
148 return 0;
149}
150
Zach Reizner713a6782015-07-31 15:12:44 -0700151static bool drm_composition_layer_has_plane(
Zach Reizner4a253652015-09-10 18:30:54 -0700152 const DrmCompositionLayer &comp_layer) {
Zach Reizner713a6782015-07-31 15:12:44 -0700153 if (comp_layer.plane != NULL)
154 if (comp_layer.plane->type() == DRM_PLANE_TYPE_OVERLAY ||
155 comp_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY)
156 return true;
157 return false;
158}
159
160static bool drm_composition_layer_has_no_plane(
Zach Reizner4a253652015-09-10 18:30:54 -0700161 const DrmCompositionLayer &comp_layer) {
Zach Reizner713a6782015-07-31 15:12:44 -0700162 return comp_layer.plane == NULL;
163}
164
165int DrmDisplayCompositor::ApplyPreComposite(
166 DrmDisplayComposition *display_comp) {
167 int ret = 0;
Zach Reizner4a253652015-09-10 18:30:54 -0700168 std::vector<DrmCompositionLayer> *layers =
169 display_comp->GetCompositionLayers();
Zach Reizner713a6782015-07-31 15:12:44 -0700170
Zach Reizner713a6782015-07-31 15:12:44 -0700171 DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
172 if (connector == NULL) {
173 ALOGE("Failed to determine display mode: no connector for display %d",
174 display_);
175 return -ENODEV;
176 }
177
178 const DrmMode &mode = connector->active_mode();
179 DrmFramebuffer &fb = framebuffers_[framebuffer_index_];
Sean Pauld106b912015-09-29 00:56:00 -0400180 ret = fb.WaitReleased(fb.kReleaseWaitTimeoutMs);
Zach Reizner713a6782015-07-31 15:12:44 -0700181 if (ret) {
182 ALOGE("Failed to wait for framebuffer release %d", ret);
183 return ret;
184 }
185 fb.set_release_fence_fd(-1);
186 if (!fb.Allocate(mode.h_display(), mode.v_display())) {
187 ALOGE("Failed to allocate framebuffer with size %dx%d", mode.h_display(),
188 mode.v_display());
189 return -ENOMEM;
190 }
191
Zach Reizner4a253652015-09-10 18:30:54 -0700192 std::vector<DrmCompositionLayer> pre_comp_layers;
Zach Reiznerb44fd102015-08-07 16:00:01 -0700193 for (auto &comp_layer : *layers) {
194 if (comp_layer.plane == NULL) {
Zach Reizner4a253652015-09-10 18:30:54 -0700195 pre_comp_layers.emplace_back(std::move(comp_layer));
Zach Reiznerb44fd102015-08-07 16:00:01 -0700196 }
197 }
198
Zach Reizner8d63e7f2015-08-20 14:52:12 -0700199 ret = pre_compositor_->Composite(pre_comp_layers.data(),
200 pre_comp_layers.size(), fb.buffer());
201 pre_compositor_->Finish();
Zach Reiznerb44fd102015-08-07 16:00:01 -0700202
Zach Reizner713a6782015-07-31 15:12:44 -0700203 if (ret) {
204 ALOGE("Failed to composite layers");
205 return ret;
206 }
207
Zach Reizner4a253652015-09-10 18:30:54 -0700208 DrmCompositionLayer &pre_comp_layer =
Zach Reizner09807052015-08-13 14:53:41 -0700209 layers->at(display_comp->pre_composition_layer_index());
Zach Reizner4a253652015-09-10 18:30:54 -0700210 ret = pre_comp_layer.buffer.ImportBuffer(fb.buffer()->handle,
211 display_comp->importer());
Zach Reizner09807052015-08-13 14:53:41 -0700212 if (ret) {
213 ALOGE("Failed to import handle of layer %d", ret);
214 return ret;
215 }
Zach Reizner4a253652015-09-10 18:30:54 -0700216 pre_comp_layer.source_crop = DrmHwcRect<float>(0, 0, fb.buffer()->getWidth(),
217 fb.buffer()->getHeight());
218 pre_comp_layer.display_frame =
219 DrmHwcRect<int>(0, 0, fb.buffer()->getWidth(), fb.buffer()->getHeight());
Zach Reizner713a6782015-07-31 15:12:44 -0700220
Zach Reizner4a253652015-09-10 18:30:54 -0700221 // TODO(zachr) get a release fence
222 // fb.set_release_fence_fd(pre_comp_layer.release_fence.Release());
Zach Reizner713a6782015-07-31 15:12:44 -0700223 framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
224
Zach Reizner09807052015-08-13 14:53:41 -0700225 display_comp->RemoveNoPlaneLayers();
226 display_comp->SignalPreCompositionDone();
Zach Reizner713a6782015-07-31 15:12:44 -0700227 return ret;
228}
229
Sean Paul98e73c82015-06-24 14:38:49 -0700230int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) {
231 int ret = 0;
232
Zach Reizner09807052015-08-13 14:53:41 -0700233 if (display_comp->pre_composition_layer_index() >= 0) {
Zach Reizner713a6782015-07-31 15:12:44 -0700234 ret = ApplyPreComposite(display_comp);
235 if (ret)
236 return ret;
237 }
238
Sean Paul57355412015-09-19 09:14:34 -0400239 DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
240 if (!connector) {
241 ALOGE("Could not locate connector for display %d", display_);
242 return -ENODEV;
243 }
244 DrmCrtc *crtc = drm_->GetCrtcForDisplay(display_);
245 if (!crtc) {
246 ALOGE("Could not locate crtc for display %d", display_);
247 return -ENODEV;
248 }
249
Sean Paul98e73c82015-06-24 14:38:49 -0700250 drmModePropertySetPtr pset = drmModePropertySetAlloc();
251 if (!pset) {
252 ALOGE("Failed to allocate property set");
253 return -ENOMEM;
254 }
255
Sean Paul57355412015-09-19 09:14:34 -0400256 uint32_t blob_id = 0;
257 uint64_t old_blob_id;
258 if (needs_modeset_) {
259 DrmProperty old_mode;
260 ret = drm_->GetCrtcProperty(*crtc, crtc->mode_property().name().c_str(),
261 &old_mode);
262 if (ret) {
263 ALOGE("Failed to get old mode property from crtc %d", crtc->id());
264 drmModePropertySetFree(pset);
265 return ret;
266 }
267 ret = old_mode.value(&old_blob_id);
268 if (ret) {
269 ALOGE("Could not get old blob id value %d", ret);
270 drmModePropertySetFree(pset);
271 return ret;
272 }
273
274 struct drm_mode_modeinfo drm_mode;
275 memset(&drm_mode, 0, sizeof(drm_mode));
276 next_mode_.ToDrmModeModeInfo(&drm_mode);
277
278 ret = drm_->CreatePropertyBlob(&drm_mode, sizeof(struct drm_mode_modeinfo),
279 &blob_id);
280 if (ret) {
281 ALOGE("Failed to create mode property blob %d", ret);
282 drmModePropertySetFree(pset);
283 return ret;
284 }
285
286 ret = drmModePropertySetAdd(pset, crtc->id(), crtc->mode_property().id(),
287 blob_id) ||
288 drmModePropertySetAdd(pset, connector->id(),
289 connector->crtc_id_property().id(), crtc->id());
290 if (ret) {
291 ALOGE("Failed to add blob %d to pset", blob_id);
292 drmModePropertySetFree(pset);
293 drm_->DestroyPropertyBlob(blob_id);
294 return ret;
295 }
296 }
297
Zach Reizner4a253652015-09-10 18:30:54 -0700298 std::vector<DrmCompositionLayer> *layers =
299 display_comp->GetCompositionLayers();
300 for (DrmCompositionLayer &layer : *layers) {
301 int acquire_fence = layer.acquire_fence.get();
302 if (acquire_fence >= 0) {
Sean Pauld106b912015-09-29 00:56:00 -0400303 ret = sync_wait(acquire_fence, kAcquireWaitTimeoutMs);
Sean Paul98e73c82015-06-24 14:38:49 -0700304 if (ret) {
Zach Reizner4a253652015-09-10 18:30:54 -0700305 ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
Sean Paul98e73c82015-06-24 14:38:49 -0700306 drmModePropertySetFree(pset);
Sean Paul57355412015-09-19 09:14:34 -0400307 drm_->DestroyPropertyBlob(blob_id);
Sean Paul98e73c82015-06-24 14:38:49 -0700308 return ret;
309 }
Zach Reizner4a253652015-09-10 18:30:54 -0700310 layer.acquire_fence.Close();
Sean Paul98e73c82015-06-24 14:38:49 -0700311 }
312
Zach Reizner4a253652015-09-10 18:30:54 -0700313 DrmPlane *plane = layer.plane;
Sean Paul2e46fbd2015-07-09 17:22:22 -0400314
315 // Disable the plane if there's no crtc
Sean Paul57355412015-09-19 09:14:34 -0400316 if (!layer.crtc) {
Zach Reizner952f70a2015-07-17 14:10:03 -0700317 ret = drmModePropertySetAdd(pset, plane->id(),
318 plane->crtc_property().id(), 0) ||
319 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
320 0);
Sean Paul2e46fbd2015-07-09 17:22:22 -0400321 if (ret) {
322 ALOGE("Failed to add plane %d disable to pset", plane->id());
323 break;
324 }
325 continue;
326 }
327
Zach Reizner4a253652015-09-10 18:30:54 -0700328 if (!layer.buffer) {
329 ALOGE("Expected a valid framebuffer for pset");
330 ret = -EINVAL;
331 break;
332 }
333
Sean Paul1c4c3262015-07-14 15:51:52 -0400334 uint64_t rotation;
Zach Reizner4a253652015-09-10 18:30:54 -0700335 switch (layer.transform) {
336 case DrmHwcTransform::kFlipH:
Sean Paul1c4c3262015-07-14 15:51:52 -0400337 rotation = 1 << DRM_REFLECT_X;
338 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700339 case DrmHwcTransform::kFlipV:
Sean Paul1c4c3262015-07-14 15:51:52 -0400340 rotation = 1 << DRM_REFLECT_Y;
341 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700342 case DrmHwcTransform::kRotate90:
Sean Paul1c4c3262015-07-14 15:51:52 -0400343 rotation = 1 << DRM_ROTATE_90;
344 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700345 case DrmHwcTransform::kRotate180:
Sean Paul1c4c3262015-07-14 15:51:52 -0400346 rotation = 1 << DRM_ROTATE_180;
347 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700348 case DrmHwcTransform::kRotate270:
Sean Paul1c4c3262015-07-14 15:51:52 -0400349 rotation = 1 << DRM_ROTATE_270;
350 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700351 case DrmHwcTransform::kIdentity:
Sean Paul1c4c3262015-07-14 15:51:52 -0400352 rotation = 0;
353 break;
354 default:
Zach Reizner4a253652015-09-10 18:30:54 -0700355 ALOGE("Invalid transform value 0x%x given", layer.transform);
Sean Paul1c4c3262015-07-14 15:51:52 -0400356 ret = -EINVAL;
357 break;
358 }
Zach Reizner952f70a2015-07-17 14:10:03 -0700359 if (ret)
360 break;
361
Sean Paul1c4c3262015-07-14 15:51:52 -0400362 // TODO: Once we have atomic test, this should fall back to GL
363 if (rotation && plane->rotation_property().id() == 0) {
364 ALOGE("Rotation is not supported on plane %d", plane->id());
365 ret = -EINVAL;
366 break;
367 }
368
Sean Paul98e73c82015-06-24 14:38:49 -0700369 ret =
370 drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
Sean Paul57355412015-09-19 09:14:34 -0400371 layer.crtc->id()) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700372 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700373 layer.buffer->fb_id) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700374 drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700375 layer.display_frame.left) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700376 drmModePropertySetAdd(pset, plane->id(), plane->crtc_y_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700377 layer.display_frame.top) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700378 drmModePropertySetAdd(
379 pset, plane->id(), plane->crtc_w_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700380 layer.display_frame.right - layer.display_frame.left) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700381 drmModePropertySetAdd(
382 pset, plane->id(), plane->crtc_h_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700383 layer.display_frame.bottom - layer.display_frame.top) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700384 drmModePropertySetAdd(pset, plane->id(), plane->src_x_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700385 (int)(layer.source_crop.left) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700386 drmModePropertySetAdd(pset, plane->id(), plane->src_y_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700387 (int)(layer.source_crop.top) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700388 drmModePropertySetAdd(
389 pset, plane->id(), plane->src_w_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700390 (int)(layer.source_crop.right - layer.source_crop.left) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700391 drmModePropertySetAdd(
392 pset, plane->id(), plane->src_h_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700393 (int)(layer.source_crop.bottom - layer.source_crop.top) << 16);
Sean Paul98e73c82015-06-24 14:38:49 -0700394 if (ret) {
395 ALOGE("Failed to add plane %d to set", plane->id());
396 break;
397 }
Sean Paul1c4c3262015-07-14 15:51:52 -0400398
399 if (plane->rotation_property().id()) {
Zach Reizner952f70a2015-07-17 14:10:03 -0700400 ret = drmModePropertySetAdd(pset, plane->id(),
401 plane->rotation_property().id(), rotation);
Sean Paul1c4c3262015-07-14 15:51:52 -0400402 if (ret) {
403 ALOGE("Failed to add rotation property %d to plane %d",
404 plane->rotation_property().id(), plane->id());
405 break;
406 }
407 }
Sean Paul98e73c82015-06-24 14:38:49 -0700408 }
409
410 if (!ret) {
Sean Paul57355412015-09-19 09:14:34 -0400411 ret = drmModePropertySetCommit(drm_->fd(), DRM_MODE_ATOMIC_ALLOW_MODESET,
412 drm_, pset);
413 if (ret) {
Sean Paul98e73c82015-06-24 14:38:49 -0700414 ALOGE("Failed to commit pset ret=%d\n", ret);
Sean Paul57355412015-09-19 09:14:34 -0400415 drmModePropertySetFree(pset);
416 if (needs_modeset_)
417 drm_->DestroyPropertyBlob(blob_id);
418 return ret;
419 }
Sean Paul98e73c82015-06-24 14:38:49 -0700420 }
421 if (pset)
422 drmModePropertySetFree(pset);
423
Sean Paul57355412015-09-19 09:14:34 -0400424 if (needs_modeset_) {
425 ret = drm_->DestroyPropertyBlob(old_blob_id);
426 if (ret) {
427 ALOGE("Failed to destroy old mode property blob %lld/%d", old_blob_id,
428 ret);
429 return ret;
430 }
431
432 /* TODO: Add dpms to the pset when the kernel supports it */
433 ret = ApplyDpms(display_comp);
434 if (ret) {
435 ALOGE("Failed to apply DPMS after modeset %d\n", ret);
436 return ret;
437 }
438
439 connector->set_active_mode(next_mode_);
440 needs_modeset_ = false;
441 }
442
Sean Paul98e73c82015-06-24 14:38:49 -0700443 return ret;
444}
445
Sean Pauldb7a17d2015-06-24 18:46:05 -0700446int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
447 DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
448 if (!conn) {
449 ALOGE("Failed to get DrmConnector for display %d", display_);
450 return -ENODEV;
451 }
452
453 const DrmProperty &prop = conn->dpms_property();
454 int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
455 display_comp->dpms_mode());
456 if (ret) {
457 ALOGE("Failed to set DPMS property for connector %d", conn->id());
458 return ret;
459 }
460 return 0;
461}
462
Sean Paul98e73c82015-06-24 14:38:49 -0700463int DrmDisplayCompositor::Composite() {
464 ATRACE_CALL();
Zach Reizner09807052015-08-13 14:53:41 -0700465
466 if (!pre_compositor_) {
467 pre_compositor_.reset(new GLWorkerCompositor());
468 int ret = pre_compositor_->Init();
469 if (ret) {
470 ALOGE("Failed to initialize OpenGL compositor %d", ret);
471 return ret;
472 }
473 }
474
Sean Paul98e73c82015-06-24 14:38:49 -0700475 int ret = pthread_mutex_lock(&lock_);
476 if (ret) {
477 ALOGE("Failed to acquire compositor lock %d", ret);
478 return ret;
479 }
480 if (composite_queue_.empty()) {
481 ret = pthread_mutex_unlock(&lock_);
482 if (ret)
483 ALOGE("Failed to release compositor lock %d", ret);
484 return ret;
485 }
486
487 std::unique_ptr<DrmDisplayComposition> composition(
488 std::move(composite_queue_.front()));
Zach Reizner4a253652015-09-10 18:30:54 -0700489
Sean Paul98e73c82015-06-24 14:38:49 -0700490 composite_queue_.pop();
491
492 ret = pthread_mutex_unlock(&lock_);
493 if (ret) {
494 ALOGE("Failed to release compositor lock %d", ret);
495 return ret;
496 }
497
Sean Paulacb2a442015-06-24 18:43:01 -0700498 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700499 case DRM_COMPOSITION_TYPE_FRAME:
500 ret = ApplyFrame(composition.get());
501 if (ret) {
502 ALOGE("Composite failed for display %d", display_);
503 return ret;
504 }
505 ++dump_frames_composited_;
506 break;
507 case DRM_COMPOSITION_TYPE_DPMS:
508 ret = ApplyDpms(composition.get());
509 if (ret)
510 ALOGE("Failed to apply dpms for display %d", display_);
Sean Paulacb2a442015-06-24 18:43:01 -0700511 return ret;
Sean Paul57355412015-09-19 09:14:34 -0400512 case DRM_COMPOSITION_TYPE_MODESET:
513 next_mode_ = composition->display_mode();
514 needs_modeset_ = true;
515 return 0;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700516 default:
517 ALOGE("Unknown composition type %d", composition->type());
518 return -EINVAL;
Sean Paul98e73c82015-06-24 14:38:49 -0700519 }
Sean Paul98e73c82015-06-24 14:38:49 -0700520
521 if (active_composition_)
522 active_composition_->FinishComposition();
523
Sean Paulfd37dfe2015-07-13 12:41:37 -0400524 ret = pthread_mutex_lock(&lock_);
525 if (ret)
526 ALOGE("Failed to acquire lock for active_composition swap");
527
Sean Paul98e73c82015-06-24 14:38:49 -0700528 active_composition_.swap(composition);
Sean Paulfd37dfe2015-07-13 12:41:37 -0400529
530 if (!ret)
531 ret = pthread_mutex_unlock(&lock_);
Zach Reizner952f70a2015-07-17 14:10:03 -0700532 if (ret)
533 ALOGE("Failed to release lock for active_composition swap");
Sean Paulfd37dfe2015-07-13 12:41:37 -0400534
Sean Paul98e73c82015-06-24 14:38:49 -0700535 return ret;
536}
537
538bool DrmDisplayCompositor::HaveQueuedComposites() const {
539 int ret = pthread_mutex_lock(&lock_);
540 if (ret) {
541 ALOGE("Failed to acquire compositor lock %d", ret);
542 return false;
543 }
544
545 bool empty_ret = !composite_queue_.empty();
546
547 ret = pthread_mutex_unlock(&lock_);
548 if (ret) {
549 ALOGE("Failed to release compositor lock %d", ret);
550 return false;
551 }
552
553 return empty_ret;
554}
555
Zach Reizner4a253652015-09-10 18:30:54 -0700556struct DrmDumpLayer {
557 int plane_id;
558 int crtc_id;
559 DrmHwcTransform transform;
560 DrmHwcRect<float> source_crop;
561 DrmHwcRect<int> display_frame;
562
563 DrmDumpLayer(DrmCompositionLayer &rhs)
564 : plane_id(rhs.plane->id()),
565 crtc_id(rhs.crtc ? rhs.crtc->id() : -1),
566 transform(rhs.transform),
567 source_crop(rhs.source_crop),
568 display_frame(rhs.display_frame) {
569 }
570};
571
Sean Paul98e73c82015-06-24 14:38:49 -0700572void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
573 uint64_t cur_ts;
574
575 int ret = pthread_mutex_lock(&lock_);
576 if (ret)
577 return;
578
579 uint64_t num_frames = dump_frames_composited_;
580 dump_frames_composited_ = 0;
581
582 struct timespec ts;
583 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
584
Zach Reizner4a253652015-09-10 18:30:54 -0700585 std::vector<DrmCompositionLayer> *input_layers =
586 active_composition_->GetCompositionLayers();
587 std::vector<DrmDumpLayer> layers;
Sean Paulfd37dfe2015-07-13 12:41:37 -0400588 if (active_composition_)
Zach Reizner4a253652015-09-10 18:30:54 -0700589 layers.insert(layers.begin(), input_layers->begin(), input_layers->end());
Sean Paulfd37dfe2015-07-13 12:41:37 -0400590 else
591 ret = -EAGAIN;
592
Sean Paul98e73c82015-06-24 14:38:49 -0700593 ret |= pthread_mutex_unlock(&lock_);
594 if (ret)
595 return;
596
597 cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
598 uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
Stéphane Marchesin83959922015-07-13 12:35:41 -0700599 float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;
Sean Paul98e73c82015-06-24 14:38:49 -0700600
601 *out << "--DrmDisplayCompositor[" << display_
602 << "]: num_frames=" << num_frames << " num_ms=" << num_ms
603 << " fps=" << fps << "\n";
604
605 dump_last_timestamp_ns_ = cur_ts;
Sean Paulfd37dfe2015-07-13 12:41:37 -0400606
607 *out << "---- DrmDisplayCompositor Layers: num=" << layers.size() << "\n";
Zach Reizner4a253652015-09-10 18:30:54 -0700608 for (std::vector<DrmDumpLayer>::iterator iter = layers.begin();
Sean Paulfd37dfe2015-07-13 12:41:37 -0400609 iter != layers.end(); ++iter) {
Zach Reizner4a253652015-09-10 18:30:54 -0700610 *out << "------ DrmDisplayCompositor Layer: plane=" << iter->plane_id
611 << " ";
Sean Paulfd37dfe2015-07-13 12:41:37 -0400612
Zach Reizner4a253652015-09-10 18:30:54 -0700613 if (iter->crtc_id < 0) {
Sean Paulfd37dfe2015-07-13 12:41:37 -0400614 *out << "disabled\n";
615 continue;
616 }
617
Zach Reizner4a253652015-09-10 18:30:54 -0700618 *out << "crtc=" << iter->crtc_id
619 << " crtc[x/y/w/h]=" << iter->display_frame.left << "/"
620 << iter->display_frame.top << "/"
621 << iter->display_frame.right - iter->display_frame.left << "/"
622 << iter->display_frame.bottom - iter->display_frame.top << " "
623 << " src[x/y/w/h]=" << iter->source_crop.left << "/"
624 << iter->source_crop.top << "/"
625 << iter->source_crop.right - iter->source_crop.left << "/"
626 << iter->source_crop.bottom - iter->source_crop.top
627 << " transform=" << (uint32_t)iter->transform << "\n";
Sean Paulfd37dfe2015-07-13 12:41:37 -0400628 }
Sean Paul98e73c82015-06-24 14:38:49 -0700629}
630}