am 1abf5c3f: (-s ours) drm_hwcomposer: Add composition type to DrmComposition
* commit '1abf5c3fd61c1698e1ef7f9794cac5e22609a58c':
drm_hwcomposer: Add composition type to DrmComposition
diff --git a/compositor.h b/compositor.h
index e148416..b424b37 100644
--- a/compositor.h
+++ b/compositor.h
@@ -90,6 +90,8 @@
// Starts a fresh composition.
virtual Composition *CreateComposition(Importer *importer) = 0;
+ // Transfers ownership of composition to the Compositor (whether or not this
+ // call returns success) for compositing.
// On success returns a syncpoint fd that will be signaled when composition is
// complete or -1 if compositing was completed by this method's return. On
// error returns an integer less than -1. The composition is invalid after
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index 37e3bad..805fd26 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -77,7 +77,7 @@
if ((*iter)->GetCrtcSupported(*crtc))
++num_planes;
}
- for (std::deque<DrmPlane *>::const_iterator iter = overlay_planes_.begin();
+ for (std::vector<DrmPlane *>::const_iterator iter = overlay_planes_.begin();
iter != overlay_planes_.end(); ++iter) {
if ((*iter)->GetCrtcSupported(*crtc))
++num_planes;
@@ -103,7 +103,7 @@
break;
}
}
- for (std::deque<DrmPlane *>::iterator iter = overlay_planes_.begin();
+ for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
!plane && iter != overlay_planes_.end(); ++iter) {
if ((*iter)->GetCrtcSupported(*crtc)) {
plane = *iter;
@@ -118,8 +118,57 @@
return composition_map_[display]->AddLayer(layer, bo, crtc, plane);
}
+int DrmComposition::AddDpmsMode(int display, uint32_t dpms_mode) {
+ return composition_map_[display]->AddDpmsMode(dpms_mode);
+}
+
std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
int display) {
return std::move(composition_map_[display]);
}
+
+int DrmComposition::DisableUnusedPlanes() {
+ for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
+ iter != drm_->end_connectors(); ++iter) {
+ int display = (*iter)->display();
+ DrmDisplayComposition *comp = GetDisplayComposition(display);
+
+ /*
+ * Leave empty compositions alone
+ * TODO: re-visit this and potentially disable leftover planes after the
+ * active compositions have gobbled up all they can
+ */
+ if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY)
+ continue;
+
+ DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
+ if (!crtc) {
+ ALOGE("Failed to find crtc for display %d", display);
+ continue;
+ }
+
+ for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
+ iter != primary_planes_.end(); ++iter) {
+ if ((*iter)->GetCrtcSupported(*crtc)) {
+ comp->AddPlaneDisable(*iter);
+ primary_planes_.erase(iter);
+ break;
+ }
+ }
+ for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
+ iter != overlay_planes_.end();) {
+ if ((*iter)->GetCrtcSupported(*crtc)) {
+ comp->AddPlaneDisable(*iter);
+ iter = overlay_planes_.erase(iter);
+ } else {
+ iter++;
+ }
+ }
+ }
+ return 0;
+}
+
+DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) {
+ return composition_map_[display].get();
+}
}
diff --git a/drmcomposition.h b/drmcomposition.h
index a8f9836..06af71d 100644
--- a/drmcomposition.h
+++ b/drmcomposition.h
@@ -41,8 +41,12 @@
virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const;
virtual int AddLayer(int display, hwc_layer_1_t *layer, hwc_drm_bo_t *bo);
+ int AddDpmsMode(int display, uint32_t dpms_mode);
+
+ int DisableUnusedPlanes();
std::unique_ptr<DrmDisplayComposition> TakeDisplayComposition(int display);
+ DrmDisplayComposition *GetDisplayComposition(int display);
private:
DrmComposition(const DrmComposition &) = delete;
@@ -51,7 +55,7 @@
Importer *importer_;
std::vector<DrmPlane *> primary_planes_;
- std::deque<DrmPlane *> overlay_planes_;
+ std::vector<DrmPlane *> overlay_planes_;
/*
* This _must_ be read-only after it's passed to QueueComposition. Otherwise
diff --git a/drmcompositor.cpp b/drmcompositor.cpp
index 4268ab5..3bab93f 100644
--- a/drmcompositor.cpp
+++ b/drmcompositor.cpp
@@ -64,6 +64,13 @@
int DrmCompositor::QueueComposition(Composition *composition) {
DrmComposition *drm_composition = (DrmComposition *)composition;
+
+ int ret = drm_composition->DisableUnusedPlanes();
+ if (ret) {
+ ALOGE("Failed to disable unused planes %d", ret);
+ return ret;
+ }
+
for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
iter != drm_->end_connectors(); ++iter) {
int display = (*iter)->display();
@@ -71,6 +78,7 @@
drm_composition->TakeDisplayComposition(display));
if (ret) {
ALOGE("Failed to queue composition for display %d", display);
+ delete composition;
return ret;
}
}
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index f049f2d..364a64e 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -26,6 +26,7 @@
#include <cutils/log.h>
#include <sw_sync.h>
#include <sync/sync.h>
+#include <xf86drmMode.h>
namespace android {
@@ -43,13 +44,14 @@
importer_(NULL),
type_(DRM_COMPOSITION_TYPE_EMPTY),
timeline_fd_(-1),
- timeline_(0) {
+ timeline_(0),
+ dpms_mode_(DRM_MODE_DPMS_ON) {
}
DrmDisplayComposition::~DrmDisplayComposition() {
for (DrmCompositionLayerVector_t::iterator iter = layers_.begin();
iter != layers_.end(); ++iter) {
- if (importer_)
+ if (importer_ && iter->bo.fb_id)
importer_->ReleaseBuffer(&iter->bo);
if (iter->layer.acquireFenceFd >= 0)
@@ -109,6 +111,22 @@
return 0;
}
+int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) {
+ if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
+ return -EINVAL;
+ dpms_mode_ = dpms_mode;
+ type_ = DRM_COMPOSITION_TYPE_DPMS;
+ return 0;
+}
+
+int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
+ DrmCompositionLayer_t c_layer;
+ c_layer.crtc = NULL;
+ c_layer.plane = plane;
+ layers_.push_back(c_layer);
+ return 0;
+}
+
int DrmDisplayComposition::FinishComposition() {
int ret = sw_sync_timeline_inc(timeline_fd_, timeline_);
if (ret)
@@ -120,4 +138,8 @@
DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
return &layers_;
}
+
+uint32_t DrmDisplayComposition::dpms_mode() const {
+ return dpms_mode_;
+}
}
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index bc8cf2e..09ad3ff 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -31,6 +31,7 @@
enum DrmCompositionType {
DRM_COMPOSITION_TYPE_EMPTY,
DRM_COMPOSITION_TYPE_FRAME,
+ DRM_COMPOSITION_TYPE_DPMS,
};
typedef struct DrmCompositionLayer {
@@ -55,10 +56,13 @@
int AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo, DrmCrtc *crtc,
DrmPlane *plane);
+ int AddPlaneDisable(DrmPlane *plane);
+ int AddDpmsMode(uint32_t dpms_mode);
int FinishComposition();
DrmCompositionLayerVector_t *GetCompositionLayers();
+ uint32_t dpms_mode() const;
private:
DrmDisplayComposition(const DrmDisplayComposition &) = delete;
@@ -74,6 +78,7 @@
int timeline_;
DrmCompositionLayerVector_t layers_;
+ uint32_t dpms_mode_;
};
}
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 2a11ee7..8168e1a 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -40,6 +40,7 @@
worker_(this),
frame_no_(0),
initialized_(false),
+ active_(false),
dump_frames_composited_(0),
dump_last_timestamp_ns_(0) {
struct timespec ts;
@@ -95,6 +96,15 @@
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_EMPTY:
return 0;
@@ -147,9 +157,25 @@
}
DrmPlane *plane = iter->plane;
+ DrmCrtc *crtc = iter->crtc;
+
+ // Disable the plane if there's no crtc
+ if (!crtc) {
+ ret =
+ drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
+ 0) ||
+ drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
+ 0);
+ if (ret) {
+ ALOGE("Failed to add plane %d disable to pset", plane->id());
+ break;
+ }
+ continue;
+ }
+
ret =
drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
- iter->crtc->id()) ||
+ crtc->id()) ||
drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
iter->bo.fb_id) ||
drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
@@ -189,6 +215,23 @@
return ret;
}
+int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
+ DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
+ if (!conn) {
+ ALOGE("Failed to get DrmConnector for display %d", display_);
+ return -ENODEV;
+ }
+
+ const DrmProperty &prop = conn->dpms_property();
+ int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
+ display_comp->dpms_mode());
+ if (ret) {
+ ALOGE("Failed to set DPMS property for connector %d", conn->id());
+ return ret;
+ }
+ return 0;
+}
+
int DrmDisplayCompositor::Composite() {
ATRACE_CALL();
int ret = pthread_mutex_lock(&lock_);
@@ -222,6 +265,11 @@
}
++dump_frames_composited_;
break;
+ case DRM_COMPOSITION_TYPE_DPMS:
+ ret = ApplyDpms(composition.get());
+ if (ret)
+ ALOGE("Failed to apply dpms for display %d", display_);
+ return ret;
default:
ALOGE("Unknown composition type %d", composition->type());
return -EINVAL;
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 928ce46..9f50664 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -47,6 +47,7 @@
DrmDisplayCompositor(const DrmDisplayCompositor &) = delete;
int ApplyFrame(DrmDisplayComposition *display_comp);
+ int ApplyDpms(DrmDisplayComposition *display_comp);
DrmResources *drm_;
int display_;
@@ -59,6 +60,7 @@
uint64_t frame_no_;
bool initialized_;
+ bool active_;
// mutable since we need to acquire in HaveQueuedComposites
mutable pthread_mutex_t lock_;
diff --git a/drmresources.cpp b/drmresources.cpp
index 2cda217..9be990f 100644
--- a/drmresources.cpp
+++ b/drmresources.cpp
@@ -467,19 +467,22 @@
return -EINVAL;
}
- DrmConnector *c = GetConnectorForDisplay(display);
- if (!c) {
- ALOGE("Failed to get DrmConnector for display %d", display);
- return -ENODEV;
+ DrmComposition *comp = (DrmComposition *)compositor_.CreateComposition(NULL);
+ if (!comp) {
+ ALOGE("Failed to create composition for dpms on %d", display);
+ return -ENOMEM;
}
-
- const DrmProperty &prop = c->dpms_property();
- int ret = drmModeConnectorSetProperty(fd_, c->id(), prop.id(), mode);
+ int ret = comp->AddDpmsMode(display, mode);
if (ret) {
- ALOGE("Failed to set DPMS property for connector %d", c->id());
+ ALOGE("Failed to add dpms %ld to composition on %d %d", mode, display, ret);
+ delete comp;
return ret;
}
-
+ ret = compositor_.QueueComposition((Composition *)comp);
+ if (ret) {
+ ALOGE("Failed to queue dpms composition on %d %d", display, ret);
+ return ret;
+ }
return 0;
}
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 02c13af..b4fb340 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -407,9 +407,10 @@
}
ret = ctx->drm.compositor()->QueueComposition(composition);
+ composition = NULL;
if (ret) {
ALOGE("Failed to queue the composition");
- hwc_set_cleanup(num_displays, display_contents, composition);
+ hwc_set_cleanup(num_displays, display_contents, NULL);
return ret;
}
hwc_set_cleanup(num_displays, display_contents, NULL);