blob: 82da4f264355a690baf126297975d994ee92e020 [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),
Zach Reizner713a6782015-07-31 15:12:44 -070049 framebuffer_index_(0),
Sean Paul98e73c82015-06-24 14:38:49 -070050 dump_frames_composited_(0),
51 dump_last_timestamp_ns_(0) {
52 struct timespec ts;
53 if (clock_gettime(CLOCK_MONOTONIC, &ts))
54 return;
55 dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
56}
57
58DrmDisplayCompositor::~DrmDisplayCompositor() {
59 if (!initialized_)
60 return;
61
62 worker_.Exit();
63
64 int ret = pthread_mutex_lock(&lock_);
65 if (ret)
66 ALOGE("Failed to acquire compositor lock %d", ret);
67
68 while (!composite_queue_.empty()) {
69 composite_queue_.front().reset();
70 composite_queue_.pop();
71 }
72 active_composition_.reset();
73
74 ret = pthread_mutex_unlock(&lock_);
75 if (ret)
76 ALOGE("Failed to acquire compositor lock %d", ret);
77
78 pthread_mutex_destroy(&lock_);
79}
80
81int DrmDisplayCompositor::Init(DrmResources *drm, int display) {
82 drm_ = drm;
83 display_ = display;
84
85 int ret = pthread_mutex_init(&lock_, NULL);
86 if (ret) {
87 ALOGE("Failed to initialize drm compositor lock %d\n", ret);
88 return ret;
89 }
90 ret = worker_.Init();
91 if (ret) {
92 pthread_mutex_destroy(&lock_);
93 ALOGE("Failed to initialize compositor worker %d\n", ret);
94 return ret;
95 }
96
97 initialized_ = true;
98 return 0;
99}
100
101int DrmDisplayCompositor::QueueComposition(
102 std::unique_ptr<DrmDisplayComposition> composition) {
Sean Paulacb2a442015-06-24 18:43:01 -0700103 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700104 case DRM_COMPOSITION_TYPE_FRAME:
105 if (!active_)
106 return -ENODEV;
107 break;
108 case DRM_COMPOSITION_TYPE_DPMS:
109 /*
110 * Update the state as soon as we get it so we can start/stop queuing
111 * frames asap.
112 */
113 active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
114 break;
115 case DRM_COMPOSITION_TYPE_EMPTY:
116 return 0;
117 default:
118 ALOGE("Unknown composition type %d/%d", composition->type(), display_);
119 return -ENOENT;
Sean Paulacb2a442015-06-24 18:43:01 -0700120 }
Sean Paul98e73c82015-06-24 14:38:49 -0700121
122 int ret = pthread_mutex_lock(&lock_);
123 if (ret) {
124 ALOGE("Failed to acquire compositor lock %d", ret);
125 return ret;
126 }
127
Zach Reiznerd410f042015-07-28 15:33:07 -0700128 // Block the queue if it gets too large. Otherwise, SurfaceFlinger will start
129 // to eat our buffer handles when we get about 1 second behind.
130 while (composite_queue_.size() >= DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH) {
131 pthread_mutex_unlock(&lock_);
132 sched_yield();
133 pthread_mutex_lock(&lock_);
134 }
135
Sean Paul98e73c82015-06-24 14:38:49 -0700136 composite_queue_.push(std::move(composition));
137
138 ret = pthread_mutex_unlock(&lock_);
139 if (ret) {
140 ALOGE("Failed to release compositor lock %d", ret);
141 return ret;
142 }
143
144 worker_.Signal();
145 return 0;
146}
147
Zach Reizner713a6782015-07-31 15:12:44 -0700148static bool drm_composition_layer_has_plane(
Zach Reizner4a253652015-09-10 18:30:54 -0700149 const DrmCompositionLayer &comp_layer) {
Zach Reizner713a6782015-07-31 15:12:44 -0700150 if (comp_layer.plane != NULL)
151 if (comp_layer.plane->type() == DRM_PLANE_TYPE_OVERLAY ||
152 comp_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY)
153 return true;
154 return false;
155}
156
157static bool drm_composition_layer_has_no_plane(
Zach Reizner4a253652015-09-10 18:30:54 -0700158 const DrmCompositionLayer &comp_layer) {
Zach Reizner713a6782015-07-31 15:12:44 -0700159 return comp_layer.plane == NULL;
160}
161
162int DrmDisplayCompositor::ApplyPreComposite(
163 DrmDisplayComposition *display_comp) {
164 int ret = 0;
Zach Reizner4a253652015-09-10 18:30:54 -0700165 std::vector<DrmCompositionLayer> *layers =
166 display_comp->GetCompositionLayers();
Zach Reizner713a6782015-07-31 15:12:44 -0700167
Zach Reizner713a6782015-07-31 15:12:44 -0700168 DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
169 if (connector == NULL) {
170 ALOGE("Failed to determine display mode: no connector for display %d",
171 display_);
172 return -ENODEV;
173 }
174
175 const DrmMode &mode = connector->active_mode();
176 DrmFramebuffer &fb = framebuffers_[framebuffer_index_];
Sean Pauld106b912015-09-29 00:56:00 -0400177 ret = fb.WaitReleased(fb.kReleaseWaitTimeoutMs);
Zach Reizner713a6782015-07-31 15:12:44 -0700178 if (ret) {
179 ALOGE("Failed to wait for framebuffer release %d", ret);
180 return ret;
181 }
182 fb.set_release_fence_fd(-1);
183 if (!fb.Allocate(mode.h_display(), mode.v_display())) {
184 ALOGE("Failed to allocate framebuffer with size %dx%d", mode.h_display(),
185 mode.v_display());
186 return -ENOMEM;
187 }
188
Zach Reizner4a253652015-09-10 18:30:54 -0700189 std::vector<DrmCompositionLayer> pre_comp_layers;
Zach Reiznerb44fd102015-08-07 16:00:01 -0700190 for (auto &comp_layer : *layers) {
191 if (comp_layer.plane == NULL) {
Zach Reizner4a253652015-09-10 18:30:54 -0700192 pre_comp_layers.emplace_back(std::move(comp_layer));
Zach Reiznerb44fd102015-08-07 16:00:01 -0700193 }
194 }
195
Zach Reizner8d63e7f2015-08-20 14:52:12 -0700196 ret = pre_compositor_->Composite(pre_comp_layers.data(),
197 pre_comp_layers.size(), fb.buffer());
198 pre_compositor_->Finish();
Zach Reiznerb44fd102015-08-07 16:00:01 -0700199
Zach Reizner713a6782015-07-31 15:12:44 -0700200 if (ret) {
201 ALOGE("Failed to composite layers");
202 return ret;
203 }
204
Zach Reizner4a253652015-09-10 18:30:54 -0700205 DrmCompositionLayer &pre_comp_layer =
Zach Reizner09807052015-08-13 14:53:41 -0700206 layers->at(display_comp->pre_composition_layer_index());
Zach Reizner4a253652015-09-10 18:30:54 -0700207 ret = pre_comp_layer.buffer.ImportBuffer(fb.buffer()->handle,
208 display_comp->importer());
Zach Reizner09807052015-08-13 14:53:41 -0700209 if (ret) {
210 ALOGE("Failed to import handle of layer %d", ret);
211 return ret;
212 }
Zach Reizner4a253652015-09-10 18:30:54 -0700213 pre_comp_layer.source_crop = DrmHwcRect<float>(0, 0, fb.buffer()->getWidth(),
214 fb.buffer()->getHeight());
215 pre_comp_layer.display_frame =
216 DrmHwcRect<int>(0, 0, fb.buffer()->getWidth(), fb.buffer()->getHeight());
Zach Reizner713a6782015-07-31 15:12:44 -0700217
Zach Reizner4a253652015-09-10 18:30:54 -0700218 // TODO(zachr) get a release fence
219 // fb.set_release_fence_fd(pre_comp_layer.release_fence.Release());
Zach Reizner713a6782015-07-31 15:12:44 -0700220 framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
221
Zach Reizner09807052015-08-13 14:53:41 -0700222 display_comp->RemoveNoPlaneLayers();
223 display_comp->SignalPreCompositionDone();
Zach Reizner713a6782015-07-31 15:12:44 -0700224 return ret;
225}
226
Sean Paul98e73c82015-06-24 14:38:49 -0700227int DrmDisplayCompositor::ApplyFrame(DrmDisplayComposition *display_comp) {
228 int ret = 0;
229
Zach Reizner09807052015-08-13 14:53:41 -0700230 if (display_comp->pre_composition_layer_index() >= 0) {
Zach Reizner713a6782015-07-31 15:12:44 -0700231 ret = ApplyPreComposite(display_comp);
232 if (ret)
233 return ret;
234 }
235
Sean Paul98e73c82015-06-24 14:38:49 -0700236 drmModePropertySetPtr pset = drmModePropertySetAlloc();
237 if (!pset) {
238 ALOGE("Failed to allocate property set");
239 return -ENOMEM;
240 }
241
Zach Reizner4a253652015-09-10 18:30:54 -0700242 std::vector<DrmCompositionLayer> *layers =
243 display_comp->GetCompositionLayers();
244 for (DrmCompositionLayer &layer : *layers) {
245 int acquire_fence = layer.acquire_fence.get();
246 if (acquire_fence >= 0) {
Sean Pauld106b912015-09-29 00:56:00 -0400247 ret = sync_wait(acquire_fence, kAcquireWaitTimeoutMs);
Sean Paul98e73c82015-06-24 14:38:49 -0700248 if (ret) {
Zach Reizner4a253652015-09-10 18:30:54 -0700249 ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
Sean Paul98e73c82015-06-24 14:38:49 -0700250 drmModePropertySetFree(pset);
251 return ret;
252 }
Zach Reizner4a253652015-09-10 18:30:54 -0700253 layer.acquire_fence.Close();
Sean Paul98e73c82015-06-24 14:38:49 -0700254 }
255
Zach Reizner4a253652015-09-10 18:30:54 -0700256 DrmPlane *plane = layer.plane;
257 DrmCrtc *crtc = layer.crtc;
Sean Paul2e46fbd2015-07-09 17:22:22 -0400258
259 // Disable the plane if there's no crtc
260 if (!crtc) {
Zach Reizner952f70a2015-07-17 14:10:03 -0700261 ret = drmModePropertySetAdd(pset, plane->id(),
262 plane->crtc_property().id(), 0) ||
263 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
264 0);
Sean Paul2e46fbd2015-07-09 17:22:22 -0400265 if (ret) {
266 ALOGE("Failed to add plane %d disable to pset", plane->id());
267 break;
268 }
269 continue;
270 }
271
Zach Reizner4a253652015-09-10 18:30:54 -0700272 if (!layer.buffer) {
273 ALOGE("Expected a valid framebuffer for pset");
274 ret = -EINVAL;
275 break;
276 }
277
Sean Paul1c4c3262015-07-14 15:51:52 -0400278 uint64_t rotation;
Zach Reizner4a253652015-09-10 18:30:54 -0700279 switch (layer.transform) {
280 case DrmHwcTransform::kFlipH:
Sean Paul1c4c3262015-07-14 15:51:52 -0400281 rotation = 1 << DRM_REFLECT_X;
282 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700283 case DrmHwcTransform::kFlipV:
Sean Paul1c4c3262015-07-14 15:51:52 -0400284 rotation = 1 << DRM_REFLECT_Y;
285 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700286 case DrmHwcTransform::kRotate90:
Sean Paul1c4c3262015-07-14 15:51:52 -0400287 rotation = 1 << DRM_ROTATE_90;
288 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700289 case DrmHwcTransform::kRotate180:
Sean Paul1c4c3262015-07-14 15:51:52 -0400290 rotation = 1 << DRM_ROTATE_180;
291 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700292 case DrmHwcTransform::kRotate270:
Sean Paul1c4c3262015-07-14 15:51:52 -0400293 rotation = 1 << DRM_ROTATE_270;
294 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700295 case DrmHwcTransform::kIdentity:
Sean Paul1c4c3262015-07-14 15:51:52 -0400296 rotation = 0;
297 break;
298 default:
Zach Reizner4a253652015-09-10 18:30:54 -0700299 ALOGE("Invalid transform value 0x%x given", layer.transform);
Sean Paul1c4c3262015-07-14 15:51:52 -0400300 ret = -EINVAL;
301 break;
302 }
Zach Reizner952f70a2015-07-17 14:10:03 -0700303 if (ret)
304 break;
305
Sean Paul1c4c3262015-07-14 15:51:52 -0400306 // TODO: Once we have atomic test, this should fall back to GL
307 if (rotation && plane->rotation_property().id() == 0) {
308 ALOGE("Rotation is not supported on plane %d", plane->id());
309 ret = -EINVAL;
310 break;
311 }
312
Sean Paul98e73c82015-06-24 14:38:49 -0700313 ret =
314 drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
Sean Paul2e46fbd2015-07-09 17:22:22 -0400315 crtc->id()) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700316 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700317 layer.buffer->fb_id) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700318 drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700319 layer.display_frame.left) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700320 drmModePropertySetAdd(pset, plane->id(), plane->crtc_y_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700321 layer.display_frame.top) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700322 drmModePropertySetAdd(
323 pset, plane->id(), plane->crtc_w_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700324 layer.display_frame.right - layer.display_frame.left) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700325 drmModePropertySetAdd(
326 pset, plane->id(), plane->crtc_h_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700327 layer.display_frame.bottom - layer.display_frame.top) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700328 drmModePropertySetAdd(pset, plane->id(), plane->src_x_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700329 (int)(layer.source_crop.left) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700330 drmModePropertySetAdd(pset, plane->id(), plane->src_y_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700331 (int)(layer.source_crop.top) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700332 drmModePropertySetAdd(
333 pset, plane->id(), plane->src_w_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700334 (int)(layer.source_crop.right - layer.source_crop.left) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700335 drmModePropertySetAdd(
336 pset, plane->id(), plane->src_h_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700337 (int)(layer.source_crop.bottom - layer.source_crop.top) << 16);
Sean Paul98e73c82015-06-24 14:38:49 -0700338 if (ret) {
339 ALOGE("Failed to add plane %d to set", plane->id());
340 break;
341 }
Sean Paul1c4c3262015-07-14 15:51:52 -0400342
343 if (plane->rotation_property().id()) {
Zach Reizner952f70a2015-07-17 14:10:03 -0700344 ret = drmModePropertySetAdd(pset, plane->id(),
345 plane->rotation_property().id(), rotation);
Sean Paul1c4c3262015-07-14 15:51:52 -0400346 if (ret) {
347 ALOGE("Failed to add rotation property %d to plane %d",
348 plane->rotation_property().id(), plane->id());
349 break;
350 }
351 }
Sean Paul98e73c82015-06-24 14:38:49 -0700352 }
353
354 if (!ret) {
355 ret = drmModePropertySetCommit(drm_->fd(), 0, drm_, pset);
356 if (ret)
357 ALOGE("Failed to commit pset ret=%d\n", ret);
358 }
359 if (pset)
360 drmModePropertySetFree(pset);
361
362 return ret;
363}
364
Sean Pauldb7a17d2015-06-24 18:46:05 -0700365int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
366 DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
367 if (!conn) {
368 ALOGE("Failed to get DrmConnector for display %d", display_);
369 return -ENODEV;
370 }
371
372 const DrmProperty &prop = conn->dpms_property();
373 int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
374 display_comp->dpms_mode());
375 if (ret) {
376 ALOGE("Failed to set DPMS property for connector %d", conn->id());
377 return ret;
378 }
379 return 0;
380}
381
Sean Paul98e73c82015-06-24 14:38:49 -0700382int DrmDisplayCompositor::Composite() {
383 ATRACE_CALL();
Zach Reizner09807052015-08-13 14:53:41 -0700384
385 if (!pre_compositor_) {
386 pre_compositor_.reset(new GLWorkerCompositor());
387 int ret = pre_compositor_->Init();
388 if (ret) {
389 ALOGE("Failed to initialize OpenGL compositor %d", ret);
390 return ret;
391 }
392 }
393
Sean Paul98e73c82015-06-24 14:38:49 -0700394 int ret = pthread_mutex_lock(&lock_);
395 if (ret) {
396 ALOGE("Failed to acquire compositor lock %d", ret);
397 return ret;
398 }
399 if (composite_queue_.empty()) {
400 ret = pthread_mutex_unlock(&lock_);
401 if (ret)
402 ALOGE("Failed to release compositor lock %d", ret);
403 return ret;
404 }
405
406 std::unique_ptr<DrmDisplayComposition> composition(
407 std::move(composite_queue_.front()));
Zach Reizner4a253652015-09-10 18:30:54 -0700408
Sean Paul98e73c82015-06-24 14:38:49 -0700409 composite_queue_.pop();
410
411 ret = pthread_mutex_unlock(&lock_);
412 if (ret) {
413 ALOGE("Failed to release compositor lock %d", ret);
414 return ret;
415 }
416
Sean Paulacb2a442015-06-24 18:43:01 -0700417 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700418 case DRM_COMPOSITION_TYPE_FRAME:
419 ret = ApplyFrame(composition.get());
420 if (ret) {
421 ALOGE("Composite failed for display %d", display_);
422 return ret;
423 }
424 ++dump_frames_composited_;
425 break;
426 case DRM_COMPOSITION_TYPE_DPMS:
427 ret = ApplyDpms(composition.get());
428 if (ret)
429 ALOGE("Failed to apply dpms for display %d", display_);
Sean Paulacb2a442015-06-24 18:43:01 -0700430 return ret;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700431 default:
432 ALOGE("Unknown composition type %d", composition->type());
433 return -EINVAL;
Sean Paul98e73c82015-06-24 14:38:49 -0700434 }
Sean Paul98e73c82015-06-24 14:38:49 -0700435
436 if (active_composition_)
437 active_composition_->FinishComposition();
438
Sean Paulfd37dfe2015-07-13 12:41:37 -0400439 ret = pthread_mutex_lock(&lock_);
440 if (ret)
441 ALOGE("Failed to acquire lock for active_composition swap");
442
Sean Paul98e73c82015-06-24 14:38:49 -0700443 active_composition_.swap(composition);
Sean Paulfd37dfe2015-07-13 12:41:37 -0400444
445 if (!ret)
446 ret = pthread_mutex_unlock(&lock_);
Zach Reizner952f70a2015-07-17 14:10:03 -0700447 if (ret)
448 ALOGE("Failed to release lock for active_composition swap");
Sean Paulfd37dfe2015-07-13 12:41:37 -0400449
Sean Paul98e73c82015-06-24 14:38:49 -0700450 return ret;
451}
452
453bool DrmDisplayCompositor::HaveQueuedComposites() const {
454 int ret = pthread_mutex_lock(&lock_);
455 if (ret) {
456 ALOGE("Failed to acquire compositor lock %d", ret);
457 return false;
458 }
459
460 bool empty_ret = !composite_queue_.empty();
461
462 ret = pthread_mutex_unlock(&lock_);
463 if (ret) {
464 ALOGE("Failed to release compositor lock %d", ret);
465 return false;
466 }
467
468 return empty_ret;
469}
470
Zach Reizner4a253652015-09-10 18:30:54 -0700471struct DrmDumpLayer {
472 int plane_id;
473 int crtc_id;
474 DrmHwcTransform transform;
475 DrmHwcRect<float> source_crop;
476 DrmHwcRect<int> display_frame;
477
478 DrmDumpLayer(DrmCompositionLayer &rhs)
479 : plane_id(rhs.plane->id()),
480 crtc_id(rhs.crtc ? rhs.crtc->id() : -1),
481 transform(rhs.transform),
482 source_crop(rhs.source_crop),
483 display_frame(rhs.display_frame) {
484 }
485};
486
Sean Paul98e73c82015-06-24 14:38:49 -0700487void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
488 uint64_t cur_ts;
489
490 int ret = pthread_mutex_lock(&lock_);
491 if (ret)
492 return;
493
494 uint64_t num_frames = dump_frames_composited_;
495 dump_frames_composited_ = 0;
496
497 struct timespec ts;
498 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
499
Zach Reizner4a253652015-09-10 18:30:54 -0700500 std::vector<DrmCompositionLayer> *input_layers =
501 active_composition_->GetCompositionLayers();
502 std::vector<DrmDumpLayer> layers;
Sean Paulfd37dfe2015-07-13 12:41:37 -0400503 if (active_composition_)
Zach Reizner4a253652015-09-10 18:30:54 -0700504 layers.insert(layers.begin(), input_layers->begin(), input_layers->end());
Sean Paulfd37dfe2015-07-13 12:41:37 -0400505 else
506 ret = -EAGAIN;
507
Sean Paul98e73c82015-06-24 14:38:49 -0700508 ret |= pthread_mutex_unlock(&lock_);
509 if (ret)
510 return;
511
512 cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
513 uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
Stéphane Marchesin83959922015-07-13 12:35:41 -0700514 float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;
Sean Paul98e73c82015-06-24 14:38:49 -0700515
516 *out << "--DrmDisplayCompositor[" << display_
517 << "]: num_frames=" << num_frames << " num_ms=" << num_ms
518 << " fps=" << fps << "\n";
519
520 dump_last_timestamp_ns_ = cur_ts;
Sean Paulfd37dfe2015-07-13 12:41:37 -0400521
522 *out << "---- DrmDisplayCompositor Layers: num=" << layers.size() << "\n";
Zach Reizner4a253652015-09-10 18:30:54 -0700523 for (std::vector<DrmDumpLayer>::iterator iter = layers.begin();
Sean Paulfd37dfe2015-07-13 12:41:37 -0400524 iter != layers.end(); ++iter) {
Zach Reizner4a253652015-09-10 18:30:54 -0700525 *out << "------ DrmDisplayCompositor Layer: plane=" << iter->plane_id
526 << " ";
Sean Paulfd37dfe2015-07-13 12:41:37 -0400527
Zach Reizner4a253652015-09-10 18:30:54 -0700528 if (iter->crtc_id < 0) {
Sean Paulfd37dfe2015-07-13 12:41:37 -0400529 *out << "disabled\n";
530 continue;
531 }
532
Zach Reizner4a253652015-09-10 18:30:54 -0700533 *out << "crtc=" << iter->crtc_id
534 << " crtc[x/y/w/h]=" << iter->display_frame.left << "/"
535 << iter->display_frame.top << "/"
536 << iter->display_frame.right - iter->display_frame.left << "/"
537 << iter->display_frame.bottom - iter->display_frame.top << " "
538 << " src[x/y/w/h]=" << iter->source_crop.left << "/"
539 << iter->source_crop.top << "/"
540 << iter->source_crop.right - iter->source_crop.left << "/"
541 << iter->source_crop.bottom - iter->source_crop.top
542 << " transform=" << (uint32_t)iter->transform << "\n";
Sean Paulfd37dfe2015-07-13 12:41:37 -0400543 }
Sean Paul98e73c82015-06-24 14:38:49 -0700544}
545}