blob: 3b3deef7a3329cf08177b410aff697317ebca96f [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 Paul971be152015-10-13 15:44:45 -0400303 for (int i = 0; i < kAcquireWaitTries; ++i) {
304 ret = sync_wait(acquire_fence, kAcquireWaitTimeoutMs);
305 if (ret)
306 ALOGW("Acquire fence %d wait %d failed (%d). Total time %d",
307 acquire_fence, i, ret, (i + 1) * kAcquireWaitTimeoutMs);
308 }
Sean Paul98e73c82015-06-24 14:38:49 -0700309 if (ret) {
Zach Reizner4a253652015-09-10 18:30:54 -0700310 ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
Sean Paul98e73c82015-06-24 14:38:49 -0700311 drmModePropertySetFree(pset);
Sean Paul57355412015-09-19 09:14:34 -0400312 drm_->DestroyPropertyBlob(blob_id);
Sean Paul98e73c82015-06-24 14:38:49 -0700313 return ret;
314 }
Zach Reizner4a253652015-09-10 18:30:54 -0700315 layer.acquire_fence.Close();
Sean Paul98e73c82015-06-24 14:38:49 -0700316 }
317
Zach Reizner4a253652015-09-10 18:30:54 -0700318 DrmPlane *plane = layer.plane;
Sean Paul2e46fbd2015-07-09 17:22:22 -0400319
320 // Disable the plane if there's no crtc
Sean Paul57355412015-09-19 09:14:34 -0400321 if (!layer.crtc) {
Zach Reizner952f70a2015-07-17 14:10:03 -0700322 ret = drmModePropertySetAdd(pset, plane->id(),
323 plane->crtc_property().id(), 0) ||
324 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
325 0);
Sean Paul2e46fbd2015-07-09 17:22:22 -0400326 if (ret) {
327 ALOGE("Failed to add plane %d disable to pset", plane->id());
328 break;
329 }
330 continue;
331 }
332
Zach Reizner4a253652015-09-10 18:30:54 -0700333 if (!layer.buffer) {
334 ALOGE("Expected a valid framebuffer for pset");
335 ret = -EINVAL;
336 break;
337 }
338
Sean Paul1c4c3262015-07-14 15:51:52 -0400339 uint64_t rotation;
Zach Reizner4a253652015-09-10 18:30:54 -0700340 switch (layer.transform) {
341 case DrmHwcTransform::kFlipH:
Sean Paul1c4c3262015-07-14 15:51:52 -0400342 rotation = 1 << DRM_REFLECT_X;
343 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700344 case DrmHwcTransform::kFlipV:
Sean Paul1c4c3262015-07-14 15:51:52 -0400345 rotation = 1 << DRM_REFLECT_Y;
346 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700347 case DrmHwcTransform::kRotate90:
Sean Paul1c4c3262015-07-14 15:51:52 -0400348 rotation = 1 << DRM_ROTATE_90;
349 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700350 case DrmHwcTransform::kRotate180:
Sean Paul1c4c3262015-07-14 15:51:52 -0400351 rotation = 1 << DRM_ROTATE_180;
352 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700353 case DrmHwcTransform::kRotate270:
Sean Paul1c4c3262015-07-14 15:51:52 -0400354 rotation = 1 << DRM_ROTATE_270;
355 break;
Zach Reizner4a253652015-09-10 18:30:54 -0700356 case DrmHwcTransform::kIdentity:
Sean Paul1c4c3262015-07-14 15:51:52 -0400357 rotation = 0;
358 break;
359 default:
Zach Reizner4a253652015-09-10 18:30:54 -0700360 ALOGE("Invalid transform value 0x%x given", layer.transform);
Sean Paul1c4c3262015-07-14 15:51:52 -0400361 ret = -EINVAL;
362 break;
363 }
Zach Reizner952f70a2015-07-17 14:10:03 -0700364 if (ret)
365 break;
366
Sean Paul1c4c3262015-07-14 15:51:52 -0400367 // TODO: Once we have atomic test, this should fall back to GL
368 if (rotation && plane->rotation_property().id() == 0) {
369 ALOGE("Rotation is not supported on plane %d", plane->id());
370 ret = -EINVAL;
371 break;
372 }
373
Sean Paul98e73c82015-06-24 14:38:49 -0700374 ret =
375 drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
Sean Paul57355412015-09-19 09:14:34 -0400376 layer.crtc->id()) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700377 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700378 layer.buffer->fb_id) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700379 drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700380 layer.display_frame.left) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700381 drmModePropertySetAdd(pset, plane->id(), plane->crtc_y_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700382 layer.display_frame.top) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700383 drmModePropertySetAdd(
384 pset, plane->id(), plane->crtc_w_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700385 layer.display_frame.right - layer.display_frame.left) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700386 drmModePropertySetAdd(
387 pset, plane->id(), plane->crtc_h_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700388 layer.display_frame.bottom - layer.display_frame.top) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700389 drmModePropertySetAdd(pset, plane->id(), plane->src_x_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700390 (int)(layer.source_crop.left) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700391 drmModePropertySetAdd(pset, plane->id(), plane->src_y_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700392 (int)(layer.source_crop.top) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700393 drmModePropertySetAdd(
394 pset, plane->id(), plane->src_w_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700395 (int)(layer.source_crop.right - layer.source_crop.left) << 16) ||
Sean Paul98e73c82015-06-24 14:38:49 -0700396 drmModePropertySetAdd(
397 pset, plane->id(), plane->src_h_property().id(),
Zach Reizner4a253652015-09-10 18:30:54 -0700398 (int)(layer.source_crop.bottom - layer.source_crop.top) << 16);
Sean Paul98e73c82015-06-24 14:38:49 -0700399 if (ret) {
400 ALOGE("Failed to add plane %d to set", plane->id());
401 break;
402 }
Sean Paul1c4c3262015-07-14 15:51:52 -0400403
404 if (plane->rotation_property().id()) {
Zach Reizner952f70a2015-07-17 14:10:03 -0700405 ret = drmModePropertySetAdd(pset, plane->id(),
406 plane->rotation_property().id(), rotation);
Sean Paul1c4c3262015-07-14 15:51:52 -0400407 if (ret) {
408 ALOGE("Failed to add rotation property %d to plane %d",
409 plane->rotation_property().id(), plane->id());
410 break;
411 }
412 }
Sean Paul98e73c82015-06-24 14:38:49 -0700413 }
414
415 if (!ret) {
Sean Paul57355412015-09-19 09:14:34 -0400416 ret = drmModePropertySetCommit(drm_->fd(), DRM_MODE_ATOMIC_ALLOW_MODESET,
417 drm_, pset);
418 if (ret) {
Sean Paul98e73c82015-06-24 14:38:49 -0700419 ALOGE("Failed to commit pset ret=%d\n", ret);
Sean Paul57355412015-09-19 09:14:34 -0400420 drmModePropertySetFree(pset);
421 if (needs_modeset_)
422 drm_->DestroyPropertyBlob(blob_id);
423 return ret;
424 }
Sean Paul98e73c82015-06-24 14:38:49 -0700425 }
426 if (pset)
427 drmModePropertySetFree(pset);
428
Sean Paul57355412015-09-19 09:14:34 -0400429 if (needs_modeset_) {
430 ret = drm_->DestroyPropertyBlob(old_blob_id);
431 if (ret) {
432 ALOGE("Failed to destroy old mode property blob %lld/%d", old_blob_id,
433 ret);
434 return ret;
435 }
436
437 /* TODO: Add dpms to the pset when the kernel supports it */
438 ret = ApplyDpms(display_comp);
439 if (ret) {
440 ALOGE("Failed to apply DPMS after modeset %d\n", ret);
441 return ret;
442 }
443
444 connector->set_active_mode(next_mode_);
445 needs_modeset_ = false;
446 }
447
Sean Paul98e73c82015-06-24 14:38:49 -0700448 return ret;
449}
450
Sean Pauldb7a17d2015-06-24 18:46:05 -0700451int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
452 DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
453 if (!conn) {
454 ALOGE("Failed to get DrmConnector for display %d", display_);
455 return -ENODEV;
456 }
457
458 const DrmProperty &prop = conn->dpms_property();
459 int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
460 display_comp->dpms_mode());
461 if (ret) {
462 ALOGE("Failed to set DPMS property for connector %d", conn->id());
463 return ret;
464 }
465 return 0;
466}
467
Sean Paul98e73c82015-06-24 14:38:49 -0700468int DrmDisplayCompositor::Composite() {
469 ATRACE_CALL();
Zach Reizner09807052015-08-13 14:53:41 -0700470
471 if (!pre_compositor_) {
472 pre_compositor_.reset(new GLWorkerCompositor());
473 int ret = pre_compositor_->Init();
474 if (ret) {
475 ALOGE("Failed to initialize OpenGL compositor %d", ret);
476 return ret;
477 }
478 }
479
Sean Paul98e73c82015-06-24 14:38:49 -0700480 int ret = pthread_mutex_lock(&lock_);
481 if (ret) {
482 ALOGE("Failed to acquire compositor lock %d", ret);
483 return ret;
484 }
485 if (composite_queue_.empty()) {
486 ret = pthread_mutex_unlock(&lock_);
487 if (ret)
488 ALOGE("Failed to release compositor lock %d", ret);
489 return ret;
490 }
491
492 std::unique_ptr<DrmDisplayComposition> composition(
493 std::move(composite_queue_.front()));
Zach Reizner4a253652015-09-10 18:30:54 -0700494
Sean Paul98e73c82015-06-24 14:38:49 -0700495 composite_queue_.pop();
496
497 ret = pthread_mutex_unlock(&lock_);
498 if (ret) {
499 ALOGE("Failed to release compositor lock %d", ret);
500 return ret;
501 }
502
Sean Paulacb2a442015-06-24 18:43:01 -0700503 switch (composition->type()) {
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700504 case DRM_COMPOSITION_TYPE_FRAME:
505 ret = ApplyFrame(composition.get());
506 if (ret) {
507 ALOGE("Composite failed for display %d", display_);
508 return ret;
509 }
510 ++dump_frames_composited_;
511 break;
512 case DRM_COMPOSITION_TYPE_DPMS:
513 ret = ApplyDpms(composition.get());
514 if (ret)
515 ALOGE("Failed to apply dpms for display %d", display_);
Sean Paulacb2a442015-06-24 18:43:01 -0700516 return ret;
Sean Paul57355412015-09-19 09:14:34 -0400517 case DRM_COMPOSITION_TYPE_MODESET:
518 next_mode_ = composition->display_mode();
519 needs_modeset_ = true;
520 return 0;
Zach Reiznerb4a9aef2015-07-16 09:45:59 -0700521 default:
522 ALOGE("Unknown composition type %d", composition->type());
523 return -EINVAL;
Sean Paul98e73c82015-06-24 14:38:49 -0700524 }
Sean Paul98e73c82015-06-24 14:38:49 -0700525
526 if (active_composition_)
527 active_composition_->FinishComposition();
528
Sean Paulfd37dfe2015-07-13 12:41:37 -0400529 ret = pthread_mutex_lock(&lock_);
530 if (ret)
531 ALOGE("Failed to acquire lock for active_composition swap");
532
Sean Paul98e73c82015-06-24 14:38:49 -0700533 active_composition_.swap(composition);
Sean Paulfd37dfe2015-07-13 12:41:37 -0400534
535 if (!ret)
536 ret = pthread_mutex_unlock(&lock_);
Zach Reizner952f70a2015-07-17 14:10:03 -0700537 if (ret)
538 ALOGE("Failed to release lock for active_composition swap");
Sean Paulfd37dfe2015-07-13 12:41:37 -0400539
Sean Paul98e73c82015-06-24 14:38:49 -0700540 return ret;
541}
542
543bool DrmDisplayCompositor::HaveQueuedComposites() const {
544 int ret = pthread_mutex_lock(&lock_);
545 if (ret) {
546 ALOGE("Failed to acquire compositor lock %d", ret);
547 return false;
548 }
549
550 bool empty_ret = !composite_queue_.empty();
551
552 ret = pthread_mutex_unlock(&lock_);
553 if (ret) {
554 ALOGE("Failed to release compositor lock %d", ret);
555 return false;
556 }
557
558 return empty_ret;
559}
560
Zach Reizner4a253652015-09-10 18:30:54 -0700561struct DrmDumpLayer {
562 int plane_id;
563 int crtc_id;
564 DrmHwcTransform transform;
565 DrmHwcRect<float> source_crop;
566 DrmHwcRect<int> display_frame;
567
568 DrmDumpLayer(DrmCompositionLayer &rhs)
569 : plane_id(rhs.plane->id()),
570 crtc_id(rhs.crtc ? rhs.crtc->id() : -1),
571 transform(rhs.transform),
572 source_crop(rhs.source_crop),
573 display_frame(rhs.display_frame) {
574 }
575};
576
Sean Paul98e73c82015-06-24 14:38:49 -0700577void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
578 uint64_t cur_ts;
579
580 int ret = pthread_mutex_lock(&lock_);
581 if (ret)
582 return;
583
584 uint64_t num_frames = dump_frames_composited_;
585 dump_frames_composited_ = 0;
586
587 struct timespec ts;
588 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
589
Zach Reizner4a253652015-09-10 18:30:54 -0700590 std::vector<DrmCompositionLayer> *input_layers =
591 active_composition_->GetCompositionLayers();
592 std::vector<DrmDumpLayer> layers;
Sean Paulfd37dfe2015-07-13 12:41:37 -0400593 if (active_composition_)
Zach Reizner4a253652015-09-10 18:30:54 -0700594 layers.insert(layers.begin(), input_layers->begin(), input_layers->end());
Sean Paulfd37dfe2015-07-13 12:41:37 -0400595 else
596 ret = -EAGAIN;
597
Sean Paul98e73c82015-06-24 14:38:49 -0700598 ret |= pthread_mutex_unlock(&lock_);
599 if (ret)
600 return;
601
602 cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
603 uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
Stéphane Marchesin83959922015-07-13 12:35:41 -0700604 float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;
Sean Paul98e73c82015-06-24 14:38:49 -0700605
606 *out << "--DrmDisplayCompositor[" << display_
607 << "]: num_frames=" << num_frames << " num_ms=" << num_ms
608 << " fps=" << fps << "\n";
609
610 dump_last_timestamp_ns_ = cur_ts;
Sean Paulfd37dfe2015-07-13 12:41:37 -0400611
612 *out << "---- DrmDisplayCompositor Layers: num=" << layers.size() << "\n";
Zach Reizner4a253652015-09-10 18:30:54 -0700613 for (std::vector<DrmDumpLayer>::iterator iter = layers.begin();
Sean Paulfd37dfe2015-07-13 12:41:37 -0400614 iter != layers.end(); ++iter) {
Zach Reizner4a253652015-09-10 18:30:54 -0700615 *out << "------ DrmDisplayCompositor Layer: plane=" << iter->plane_id
616 << " ";
Sean Paulfd37dfe2015-07-13 12:41:37 -0400617
Zach Reizner4a253652015-09-10 18:30:54 -0700618 if (iter->crtc_id < 0) {
Sean Paulfd37dfe2015-07-13 12:41:37 -0400619 *out << "disabled\n";
620 continue;
621 }
622
Zach Reizner4a253652015-09-10 18:30:54 -0700623 *out << "crtc=" << iter->crtc_id
624 << " crtc[x/y/w/h]=" << iter->display_frame.left << "/"
625 << iter->display_frame.top << "/"
626 << iter->display_frame.right - iter->display_frame.left << "/"
627 << iter->display_frame.bottom - iter->display_frame.top << " "
628 << " src[x/y/w/h]=" << iter->source_crop.left << "/"
629 << iter->source_crop.top << "/"
630 << iter->source_crop.right - iter->source_crop.left << "/"
631 << iter->source_crop.bottom - iter->source_crop.top
632 << " transform=" << (uint32_t)iter->transform << "\n";
Sean Paulfd37dfe2015-07-13 12:41:37 -0400633 }
Sean Paul98e73c82015-06-24 14:38:49 -0700634}
635}