#include <stdlib.h>
#include <cutils/log.h>
+#include <cutils/properties.h>
#include <sw_sync.h>
#include <sync/sync.h>
namespace android {
-static const bool kUseOverlayPlanes = false;
-
-DrmCompositionLayer::DrmCompositionLayer() : crtc(NULL), plane(NULL) {
- memset(&layer, 0, sizeof(layer));
- layer.acquireFenceFd = -1;
- memset(&bo, 0, sizeof(bo));
-}
-
-DrmCompositionLayer::~DrmCompositionLayer() {
-}
-
-DrmComposition::DrmComposition(DrmResources *drm, Importer *importer,
- uint64_t frame_no)
- : drm_(drm),
- importer_(importer),
- frame_no_(frame_no),
- timeline_fd_(-1),
- timeline_(0) {
- for (DrmResources::PlaneIter iter = drm_->begin_planes();
- iter != drm_->end_planes(); ++iter) {
- if ((*iter)->type() == DRM_PLANE_TYPE_PRIMARY)
- primary_planes_.push_back(*iter);
- else if (kUseOverlayPlanes && (*iter)->type() == DRM_PLANE_TYPE_OVERLAY)
- overlay_planes_.push_back(*iter);
+DrmComposition::DrmComposition(DrmResources *drm, Importer *importer)
+ : drm_(drm), importer_(importer) {
+ char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
+ property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1");
+ bool use_overlay_planes = atoi(use_overlay_planes_prop);
+
+ for (auto &plane : drm->planes()) {
+ if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
+ primary_planes_.push_back(plane.get());
+ else if (use_overlay_planes && plane->type() == DRM_PLANE_TYPE_OVERLAY)
+ overlay_planes_.push_back(plane.get());
}
}
-DrmComposition::~DrmComposition() {
- for (DrmCompositionLayerMap_t::iterator iter = composition_map_.begin();
- iter != composition_map_.end(); ++iter) {
- importer_->ReleaseBuffer(&iter->second.bo);
-
- if (iter->second.layer.acquireFenceFd >= 0)
- close(iter->second.layer.acquireFenceFd);
- }
+int DrmComposition::Init(uint64_t frame_no) {
+ for (auto &conn : drm_->connectors()) {
+ int display = conn->display();
+ composition_map_[display].reset(new DrmDisplayComposition());
+ if (!composition_map_[display]) {
+ ALOGE("Failed to allocate new display composition\n");
+ return -ENOMEM;
+ }
- if (timeline_fd_ >= 0)
- close(timeline_fd_);
-}
+ // If the display hasn't been modeset yet, this will be NULL
+ DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
-int DrmComposition::Init() {
- int ret = sw_sync_timeline_create();
- if (ret < 0) {
- ALOGE("Failed to create sw sync timeline %d", ret);
- return ret;
+ int ret = composition_map_[display]->Init(drm_, crtc, importer_, frame_no);
+ if (ret) {
+ ALOGE("Failed to init display composition for %d", display);
+ return ret;
+ }
}
- timeline_fd_ = ret;
return 0;
}
-unsigned DrmComposition::GetRemainingLayers(int display,
- unsigned num_needed) const {
- DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
- if (!crtc) {
- ALOGW("Failed to find crtc for display %d", display);
- return 0;
- }
+int DrmComposition::SetLayers(size_t num_displays,
+ DrmCompositionDisplayLayersMap *maps) {
+ int ret = 0;
+ for (size_t display_index = 0; display_index < num_displays;
+ display_index++) {
+ DrmCompositionDisplayLayersMap &map = maps[display_index];
+ int display = map.display;
+
+ if (!drm_->GetConnectorForDisplay(display)) {
+ ALOGE("Invalid display given to SetLayers %d", display);
+ continue;
+ }
- unsigned num_planes = 0;
- for (std::vector<DrmPlane *>::const_iterator iter = primary_planes_.begin();
- iter != primary_planes_.end(); ++iter) {
- if ((*iter)->GetCrtcSupported(*crtc))
- ++num_planes;
- }
- for (std::deque<DrmPlane *>::const_iterator iter = overlay_planes_.begin();
- iter != overlay_planes_.end(); ++iter) {
- if ((*iter)->GetCrtcSupported(*crtc))
- ++num_planes;
+ ret = composition_map_[display]->SetLayers(
+ map.layers.data(), map.layers.size(), map.geometry_changed);
+ if (ret)
+ return ret;
}
- return std::min(num_planes, num_needed);
+
+ return 0;
}
-int DrmComposition::AddLayer(int display, hwc_layer_1_t *layer,
- hwc_drm_bo *bo) {
- if (layer->transform != 0)
- return -EINVAL;
+int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) {
+ return composition_map_[display]->SetDpmsMode(dpms_mode);
+}
- DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
- if (!crtc) {
- ALOGE("Could not find crtc for display %d", display);
- return -ENODEV;
- }
+int DrmComposition::SetDisplayMode(int display, const DrmMode &display_mode) {
+ return composition_map_[display]->SetDisplayMode(display_mode);
+}
- ++timeline_;
- layer->releaseFenceFd =
- sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
- if (layer->releaseFenceFd < 0) {
- ALOGE("Could not create release fence %d", layer->releaseFenceFd);
- return layer->releaseFenceFd;
- }
+std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
+ int display) {
+ return std::move(composition_map_[display]);
+}
- DrmCompositionLayer_t c_layer;
- c_layer.layer = *layer;
- c_layer.bo = *bo;
- c_layer.crtc = crtc;
-
- // First try to find a primary plane for the layer, then fallback on overlays
- for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
- iter != primary_planes_.end(); ++iter) {
- if ((*iter)->GetCrtcSupported(*crtc)) {
- c_layer.plane = (*iter);
- primary_planes_.erase(iter);
- break;
- }
- }
- for (std::deque<DrmPlane *>::iterator iter = overlay_planes_.begin();
- !c_layer.plane && iter != overlay_planes_.end(); ++iter) {
- if ((*iter)->GetCrtcSupported(*crtc)) {
- c_layer.plane = (*iter);
- overlay_planes_.erase(iter);
- break;
+int DrmComposition::Plan(std::map<int, DrmDisplayCompositor> &compositor_map) {
+ int ret = 0;
+ for (auto &conn : drm_->connectors()) {
+ int display = conn->display();
+ DrmDisplayComposition *comp = GetDisplayComposition(display);
+ ret = comp->Plan(compositor_map[display].squash_state(), &primary_planes_,
+ &overlay_planes_);
+ if (ret) {
+ ALOGE("Failed to plan composition for dislay %d", display);
+ return ret;
}
}
- if (!c_layer.plane) {
- close(layer->releaseFenceFd);
- layer->releaseFenceFd = -1;
- return -ENOENT;
- }
- layer->acquireFenceFd = -1; // We own this now
- composition_map_.insert(DrmCompositionLayerPair_t(display, c_layer));
return 0;
}
-int DrmComposition::FinishComposition() {
- int ret = sw_sync_timeline_inc(timeline_fd_, timeline_);
- if (ret)
- ALOGE("Failed to increment sync timeline %d", ret);
+int DrmComposition::DisableUnusedPlanes() {
+ for (auto &conn : drm_->connectors()) {
+ int display = conn->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 ||
+ comp->type() == DRM_COMPOSITION_TYPE_MODESET)
+ continue;
+
+ DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
+ if (!crtc) {
+ ALOGE("Failed to find crtc for display %d", display);
+ continue;
+ }
- return ret;
+ 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;
}
-DrmCompositionLayerMap_t *DrmComposition::GetCompositionMap() {
- return &composition_map_;
+DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) {
+ return composition_map_[display].get();
}
}