+int DrmDisplayCompositor::QueueComposition(
+ std::unique_ptr<DrmDisplayComposition> composition) {
+ switch (composition->type()) {
+ case DRM_COMPOSITION_TYPE_FRAME:
+ if (!active_)
+ return -ENODEV;
+ break;
+ case DRM_COMPOSITION_TYPE_DPMS:
+ /*
+ * Update the state as soon as we get it so we can start/stop queuing
+ * frames asap.
+ */
+ active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
+ break;
+ case DRM_COMPOSITION_TYPE_MODESET:
+ break;
+ case DRM_COMPOSITION_TYPE_EMPTY:
+ return 0;
+ default:
+ ALOGE("Unknown composition type %d/%d", composition->type(), display_);
+ return -ENOENT;
+ }
+
+ int ret = pthread_mutex_lock(&lock_);
+ if (ret) {
+ ALOGE("Failed to acquire compositor lock %d", ret);
+ return ret;
+ }
+
+ // Block the queue if it gets too large. Otherwise, SurfaceFlinger will start
+ // to eat our buffer handles when we get about 1 second behind.
+ while (composite_queue_.size() >= DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH) {
+ pthread_mutex_unlock(&lock_);
+ sched_yield();
+ pthread_mutex_lock(&lock_);
+ }
+
+ composite_queue_.push(std::move(composition));
+
+ ret = pthread_mutex_unlock(&lock_);
+ if (ret) {
+ ALOGE("Failed to release compositor lock %d", ret);
+ return ret;
+ }
+
+ worker_.Signal();
+ return 0;
+}
+