summaryrefslogtreecommitdiff
path: root/drmdisplaycomposition.cpp
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2015-08-13 14:53:41 -0700
committerZach Reizner <zachr@google.com>2015-08-13 15:03:53 -0700
commit098070590ae648ede5f2ef846298de178ccd3637 (patch)
tree0b0ddea80dbdaa89c60c6aa14e463fa2327cd706 /drmdisplaycomposition.cpp
parentc6520e488fa82accb1882381bb5540ea419a0276 (diff)
drm_hwcomposer: enhance stability using various wrapper classes
This commit contains a lot of churn because it changes code to use automatic resource lifetimes as much as possible. As more things get changed, this is essential to maintaining stability. In addition, this change changes how layers are passed through the compositor API. Before each layer was passed down one at a time. Now they are passed in all at once. This is simpler for the implementation because it makes errors more atomic and makes decisions easier for the compositors. Change-Id: Ic3e6b5d0089fb1631ea256adcce9910ed8f38366
Diffstat (limited to 'drmdisplaycomposition.cpp')
-rw-r--r--drmdisplaycomposition.cpp243
1 files changed, 182 insertions, 61 deletions
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index d29b957..c7168c0 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -60,13 +60,11 @@ static void free_buffer_handle(native_handle_t *handle) {
DrmCompositionLayer::DrmCompositionLayer()
: crtc(NULL), plane(NULL), handle(NULL) {
memset(&layer, 0, sizeof(layer));
+ layer.releaseFenceFd = -1;
layer.acquireFenceFd = -1;
memset(&bo, 0, sizeof(bo));
}
-DrmCompositionLayer::~DrmCompositionLayer() {
-}
-
DrmDisplayComposition::DrmDisplayComposition()
: drm_(NULL),
importer_(NULL),
@@ -74,6 +72,8 @@ DrmDisplayComposition::DrmDisplayComposition()
timeline_fd_(-1),
timeline_(0),
timeline_current_(0),
+ timeline_pre_comp_done_(0),
+ pre_composition_layer_index_(-1),
dpms_mode_(DRM_MODE_DPMS_ON) {
}
@@ -99,8 +99,10 @@ DrmDisplayComposition::~DrmDisplayComposition() {
}
}
-int DrmDisplayComposition::Init(DrmResources *drm, Importer *importer) {
+int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
+ Importer *importer) {
drm_ = drm;
+ crtc_ = crtc;
importer_ = importer;
int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
@@ -127,69 +129,190 @@ bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
}
-int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo,
- DrmCrtc *crtc, DrmPlane *plane) {
+static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
+ for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
+ if ((*iter)->GetCrtcSupported(*crtc)) {
+ DrmPlane *plane = *iter;
+ planes->erase(iter);
+ return plane;
+ }
+ }
+ return NULL;
+}
+
+static DrmPlane *TakePlane(DrmCrtc *crtc,
+ std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes) {
+ DrmPlane *plane = TakePlane(crtc, primary_planes);
+ if (plane)
+ return plane;
+ return TakePlane(crtc, overlay_planes);
+}
+
+int DrmDisplayComposition::CreateNextTimelineFence() {
+ ++timeline_;
+ return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
+}
+
+int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
+ int timeline_increase = point - timeline_current_;
+ if (timeline_increase <= 0)
+ return 0;
+
+ int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
+ if (ret)
+ ALOGE("Failed to increment sync timeline %d", ret);
+ else
+ timeline_current_ = point;
+
+ return ret;
+}
+
+int DrmDisplayComposition::SetLayers(hwc_layer_1_t *layers, size_t num_layers,
+ size_t *layer_indices,
+ std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes) {
+ int ret = 0;
if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
return -EINVAL;
- native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
- if (handle_copy == NULL) {
- ALOGE("Failed to duplicate handle");
- return -ENOMEM;
- }
+ for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
+ hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
+ if (layer->transform != 0)
+ return -EINVAL;
- int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
- if (ret) {
- ALOGE("Failed to register buffer handle %d", ret);
- free_buffer_handle(handle_copy);
- return ret;
+ native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
+ if (handle_copy == NULL) {
+ ALOGE("Failed to duplicate handle");
+ return -ENOMEM;
+ }
+
+ int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
+ if (ret) {
+ ALOGE("Failed to register buffer handle %d", ret);
+ free_buffer_handle(handle_copy);
+ return ret;
+ }
+
+ layers_.emplace_back();
+ DrmCompositionLayer_t *c_layer = &layers_.back();
+ c_layer->layer = *layer;
+ c_layer->handle = handle_copy;
+ c_layer->crtc = crtc_;
+
+ ret = importer_->ImportBuffer(layer->handle, &c_layer->bo);
+ if (ret) {
+ ALOGE("Failed to import handle of layer %d", ret);
+ goto fail;
+ }
+
+ if (pre_composition_layer_index_ == -1) {
+ c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
+ if (c_layer->plane == NULL) {
+ if (layers_.size() <= 1) {
+ ALOGE("Failed to match any planes to the crtc of this display");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ layers_.emplace_back();
+ // c_layer's address might have changed when we resized the vector
+ c_layer = &layers_[layers_.size() - 2];
+ DrmCompositionLayer_t &pre_comp_layer = layers_.back();
+ pre_comp_layer.crtc = crtc_;
+ hwc_layer_1_t &pre_comp_output_layer = pre_comp_layer.layer;
+ memset(&pre_comp_output_layer, 0, sizeof(pre_comp_output_layer));
+ pre_comp_output_layer.compositionType = HWC_OVERLAY;
+ pre_comp_output_layer.acquireFenceFd = -1;
+ pre_comp_output_layer.releaseFenceFd = -1;
+ pre_comp_output_layer.planeAlpha = 0xff;
+ pre_comp_output_layer.visibleRegionScreen.numRects = 1;
+ pre_comp_output_layer.visibleRegionScreen.rects =
+ &pre_comp_output_layer.displayFrame;
+
+ pre_composition_layer_index_ = layers_.size() - 1;
+
+ // This is all to fix up the previous layer, which has now become part
+ // of the set of pre-composition layers because we are stealing its
+ // plane.
+ DrmCompositionLayer_t &last_c_layer = layers_[layers_.size() - 3];
+ std::swap(pre_comp_layer.plane, last_c_layer.plane);
+ hwc_layer_1_t *last_layer = &layers[layer_indices[layer_index - 1]];
+ ret = last_layer->releaseFenceFd = CreateNextTimelineFence();
+ if (ret < 0) {
+ ALOGE("Could not create release fence %d", ret);
+ goto fail;
+ }
+ }
+ }
+
+ if (c_layer->plane == NULL) {
+ // Layers to be pre composited all get the earliest release fences as they
+ // will get released soonest.
+ ret = layer->releaseFenceFd = CreateNextTimelineFence();
+ if (ret < 0) {
+ ALOGE("Could not create release fence %d", ret);
+ goto fail;
+ }
+ }
}
- ++timeline_;
- layer->releaseFenceFd =
- sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
- if (layer->releaseFenceFd < 0) {
- free_buffer_handle(handle_copy);
- ALOGE("Could not create release fence %d", layer->releaseFenceFd);
- return layer->releaseFenceFd;
+ timeline_pre_comp_done_ = timeline_;
+
+ for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
+ hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
+ if (layer->releaseFenceFd >= 0)
+ continue;
+
+ ret = layer->releaseFenceFd = CreateNextTimelineFence();
+ if (ret < 0) {
+ ALOGE("Could not create release fence %d", ret);
+ goto fail;
+ }
}
- DrmCompositionLayer_t c_layer;
- c_layer.layer = *layer;
- c_layer.bo = *bo;
- c_layer.crtc = crtc;
- c_layer.plane = plane;
- c_layer.handle = handle_copy;
+ for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
+ hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
+ layer->acquireFenceFd = -1; // We own this now
+ }
- layer->acquireFenceFd = -1; // We own this now
- layers_.push_back(c_layer);
type_ = DRM_COMPOSITION_TYPE_FRAME;
return 0;
-}
-int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, DrmCrtc *crtc,
- DrmPlane *plane) {
- if (layer->transform != 0)
- return -EINVAL;
-
- if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
- return -EINVAL;
+fail:
- hwc_drm_bo_t bo;
- int ret = importer_->ImportBuffer(layer->handle, &bo);
- if (ret) {
- ALOGE("Failed to import handle of layer %d", ret);
- return ret;
+ for (size_t c_layer_index = 0; c_layer_index < layers_.size();
+ c_layer_index++) {
+ DrmCompositionLayer_t &c_layer = layers_[c_layer_index];
+ if (c_layer.handle) {
+ gralloc_->unregisterBuffer(gralloc_, c_layer.handle);
+ free_buffer_handle(c_layer.handle);
+ }
+ if (c_layer.bo.fb_id)
+ importer_->ReleaseBuffer(&c_layer.bo);
+ if (c_layer.plane != NULL) {
+ std::vector<DrmPlane *> *return_to =
+ (c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
+ : overlay_planes;
+ return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
+ }
}
+ layers_.clear();
- ret = AddLayer(layer, &bo, crtc, plane);
- if (ret)
- importer_->ReleaseBuffer(&bo);
+ for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
+ hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
+ if (layer->releaseFenceFd >= 0) {
+ close(layer->releaseFenceFd);
+ layer->releaseFenceFd = -1;
+ }
+ }
+ sw_sync_timeline_inc(timeline_fd_, timeline_ - timeline_current_);
+ timeline_ = timeline_current_;
return ret;
}
-int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) {
+int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
return -EINVAL;
dpms_mode_ = dpms_mode;
@@ -198,10 +321,10 @@ int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) {
}
int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
- DrmCompositionLayer_t c_layer;
+ layers_.emplace_back();
+ DrmCompositionLayer_t &c_layer = layers_.back();
c_layer.crtc = NULL;
c_layer.plane = plane;
- layers_.push_back(c_layer);
return 0;
}
@@ -231,24 +354,22 @@ void DrmDisplayComposition::RemoveNoPlaneLayers() {
layers_.end());
}
-int DrmDisplayComposition::FinishComposition() {
- int timeline_increase = timeline_ - timeline_current_;
- if (timeline_increase <= 0)
- return 0;
-
- int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
- if (ret)
- ALOGE("Failed to increment sync timeline %d", ret);
- else
- timeline_current_ = timeline_;
+int DrmDisplayComposition::SignalPreCompositionDone() {
+ return IncreaseTimelineToPoint(timeline_pre_comp_done_);
+}
- return ret;
+int DrmDisplayComposition::FinishComposition() {
+ return IncreaseTimelineToPoint(timeline_);
}
DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
return &layers_;
}
+int DrmDisplayComposition::pre_composition_layer_index() const {
+ return pre_composition_layer_index_;
+}
+
uint32_t DrmDisplayComposition::dpms_mode() const {
return dpms_mode_;
}