summaryrefslogtreecommitdiff
path: root/drmdisplaycomposition.cpp
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2015-06-24 14:38:49 -0700
committerSean Paul <seanpaul@chromium.org>2015-07-13 11:57:56 -0400
commit98e73c89a683a92f44c99fb8dc85e51bdda243ba (patch)
tree80a9f44b9720622cb9fab3ec6f133a5bf5fbfe3b /drmdisplaycomposition.cpp
parentd20b3190c28329914ad0c21c508cb3c9bb83ee02 (diff)
downloaddrm_hwcomposer-98e73c89a683a92f44c99fb8dc85e51bdda243ba.tar.gz
drm_hwcomposer-98e73c89a683a92f44c99fb8dc85e51bdda243ba.tar.xz
drm_hwcomposer: Split the drm compositor into per-display threads
This patch splits out the current single drm compositor with per-display compositors, each with their own thread. The per-display compositors are hidden behind a singleton drm compositor. This allows us to maintain a whole-world view of all displays involved in a frame. This becomes useful if we start switching up crtcs/encoders for the displays. This also allows us to issue one DrmComposition when the frame is being assembled. The single DrmComposition handles the plane allocation (since they might switch between displays), and contains per-display compositions which are used to store the layer->plane/crtc information for each frame. The display compositors use the per-display compositions to display the frame on their output. Each display compositor receives a shared pointer to the frame's DrmComposition on QueueComposition. As a result, both the composition, and the per-display compositions, live for as long as any one display is still using it. While this is sub-optimal (since a display might never update again), this is probably fine for now. Finally, splitting things up per-display will allow us to inject non-compositing jobs into the composite queue. An example would be turning the display off, or setting the mode. This ensures that all frames in the composite queue are displayed before the mode changes or the display is disabled. Signed-off-by: Sean Paul <seanpaul@chromium.org> Change-Id: I8a233ea64710b238f70acbcde1f6d771e297b069
Diffstat (limited to 'drmdisplaycomposition.cpp')
-rw-r--r--drmdisplaycomposition.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
new file mode 100644
index 0000000..75046fb
--- /dev/null
+++ b/drmdisplaycomposition.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-drm-display-composition"
+
+#include "drmdisplaycomposition.h"
+#include "drmcrtc.h"
+#include "drmplane.h"
+#include "drmresources.h"
+
+#include <stdlib.h>
+
+#include <cutils/log.h>
+#include <sw_sync.h>
+#include <sync/sync.h>
+
+namespace android {
+
+DrmCompositionLayer::DrmCompositionLayer() : crtc(NULL), plane(NULL) {
+ memset(&layer, 0, sizeof(layer));
+ layer.acquireFenceFd = -1;
+ memset(&bo, 0, sizeof(bo));
+}
+
+DrmCompositionLayer::~DrmCompositionLayer() {
+}
+
+DrmDisplayComposition::DrmDisplayComposition()
+ : drm_(NULL), importer_(NULL), timeline_fd_(-1), timeline_(0) {
+}
+
+DrmDisplayComposition::~DrmDisplayComposition() {
+ for (DrmCompositionLayerVector_t::iterator iter = layers_.begin();
+ iter != layers_.end(); ++iter) {
+ if (importer_)
+ importer_->ReleaseBuffer(&iter->bo);
+
+ if (iter->layer.acquireFenceFd >= 0)
+ close(iter->layer.acquireFenceFd);
+ }
+
+ if (timeline_fd_ >= 0)
+ close(timeline_fd_);
+}
+
+int DrmDisplayComposition::Init(DrmResources *drm, Importer *importer) {
+ drm_ = drm;
+ importer_ = importer;
+
+ int ret = sw_sync_timeline_create();
+ if (ret < 0) {
+ ALOGE("Failed to create sw sync timeline %d", ret);
+ return ret;
+ }
+ timeline_fd_ = ret;
+ return 0;
+}
+
+int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo,
+ DrmCrtc *crtc, DrmPlane *plane) {
+ if (layer->transform != 0)
+ return -EINVAL;
+
+ ++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;
+ }
+
+ DrmCompositionLayer_t c_layer;
+ c_layer.layer = *layer;
+ c_layer.bo = *bo;
+ c_layer.crtc = crtc;
+ c_layer.plane = plane;
+
+ layer->acquireFenceFd = -1; // We own this now
+ layers_.push_back(c_layer);
+ return 0;
+}
+
+int DrmDisplayComposition::FinishComposition() {
+ int ret = sw_sync_timeline_inc(timeline_fd_, timeline_);
+ if (ret)
+ ALOGE("Failed to increment sync timeline %d", ret);
+
+ return ret;
+}
+
+DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
+ return &layers_;
+}
+}