aboutsummaryrefslogtreecommitdiff
path: root/compositor/DrmDisplayComposition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compositor/DrmDisplayComposition.cpp')
-rw-r--r--compositor/DrmDisplayComposition.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/compositor/DrmDisplayComposition.cpp b/compositor/DrmDisplayComposition.cpp
new file mode 100644
index 0000000..4d2e19a
--- /dev/null
+++ b/compositor/DrmDisplayComposition.cpp
@@ -0,0 +1,297 @@
+/*
+ * 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 <log/log.h>
+#include <stdlib.h>
+#include <sync/sync.h>
+#include <xf86drmMode.h>
+
+#include <algorithm>
+#include <unordered_set>
+
+#include "DrmDisplayCompositor.h"
+#include "Planner.h"
+#include "drm/DrmDevice.h"
+
+namespace android {
+
+DrmDisplayComposition::~DrmDisplayComposition() {
+}
+
+int DrmDisplayComposition::Init(DrmDevice *drm, DrmCrtc *crtc,
+ Importer *importer, Planner *planner,
+ uint64_t frame_no) {
+ drm_ = drm;
+ crtc_ = crtc; // Can be NULL if we haven't modeset yet
+ importer_ = importer;
+ planner_ = planner;
+ frame_no_ = frame_no;
+
+ return 0;
+}
+
+bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
+ return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
+}
+
+int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
+ bool geometry_changed) {
+ if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
+ return -EINVAL;
+
+ geometry_changed_ = geometry_changed;
+
+ for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
+ layers_.emplace_back(std::move(layers[layer_index]));
+ }
+
+ type_ = DRM_COMPOSITION_TYPE_FRAME;
+ return 0;
+}
+
+int DrmDisplayComposition::SetDpmsMode(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::SetDisplayMode(const DrmMode &display_mode) {
+ if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET))
+ return -EINVAL;
+ display_mode_ = display_mode;
+ dpms_mode_ = DRM_MODE_DPMS_ON;
+ type_ = DRM_COMPOSITION_TYPE_MODESET;
+ return 0;
+}
+
+int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
+ composition_planes_.emplace_back(DrmCompositionPlane::Type::kDisable, plane,
+ crtc_);
+ return 0;
+}
+
+int DrmDisplayComposition::AddPlaneComposition(DrmCompositionPlane plane) {
+ composition_planes_.emplace_back(std::move(plane));
+ return 0;
+}
+
+int DrmDisplayComposition::Plan(std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes) {
+ if (type_ != DRM_COMPOSITION_TYPE_FRAME)
+ return 0;
+
+ std::map<size_t, DrmHwcLayer *> to_composite;
+
+ for (size_t i = 0; i < layers_.size(); ++i)
+ to_composite.emplace(std::make_pair(i, &layers_[i]));
+
+ int ret;
+ std::tie(ret,
+ composition_planes_) = planner_->ProvisionPlanes(to_composite, crtc_,
+ primary_planes,
+ overlay_planes);
+ if (ret) {
+ ALOGE("Planner failed provisioning planes ret=%d", ret);
+ return ret;
+ }
+
+ // Remove the planes we used from the pool before returning. This ensures they
+ // won't be reused by another display in the composition.
+ for (auto &i : composition_planes_) {
+ if (!i.plane())
+ continue;
+
+ // make sure that source layers are ordered based on zorder
+ std::sort(i.source_layers().begin(), i.source_layers().end());
+
+ std::vector<DrmPlane *> *container;
+ if (i.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
+ container = primary_planes;
+ else
+ container = overlay_planes;
+ for (auto j = container->begin(); j != container->end(); ++j) {
+ if (*j == i.plane()) {
+ container->erase(j);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static const char *DrmCompositionTypeToString(DrmCompositionType type) {
+ switch (type) {
+ case DRM_COMPOSITION_TYPE_EMPTY:
+ return "EMPTY";
+ case DRM_COMPOSITION_TYPE_FRAME:
+ return "FRAME";
+ case DRM_COMPOSITION_TYPE_DPMS:
+ return "DPMS";
+ case DRM_COMPOSITION_TYPE_MODESET:
+ return "MODESET";
+ default:
+ return "<invalid>";
+ }
+}
+
+static const char *DPMSModeToString(int dpms_mode) {
+ switch (dpms_mode) {
+ case DRM_MODE_DPMS_ON:
+ return "ON";
+ case DRM_MODE_DPMS_OFF:
+ return "OFF";
+ default:
+ return "<invalid>";
+ }
+}
+
+static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
+ if (!buffer) {
+ *out << "buffer=<invalid>";
+ return;
+ }
+
+ *out << "buffer[w/h/format]=";
+ *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
+}
+
+static void DumpTransform(uint32_t transform, std::ostringstream *out) {
+ *out << "[";
+
+ if (transform == 0)
+ *out << "IDENTITY";
+
+ bool separator = false;
+ if (transform & DrmHwcTransform::kFlipH) {
+ *out << "FLIPH";
+ separator = true;
+ }
+ if (transform & DrmHwcTransform::kFlipV) {
+ if (separator)
+ *out << "|";
+ *out << "FLIPV";
+ separator = true;
+ }
+ if (transform & DrmHwcTransform::kRotate90) {
+ if (separator)
+ *out << "|";
+ *out << "ROTATE90";
+ separator = true;
+ }
+ if (transform & DrmHwcTransform::kRotate180) {
+ if (separator)
+ *out << "|";
+ *out << "ROTATE180";
+ separator = true;
+ }
+ if (transform & DrmHwcTransform::kRotate270) {
+ if (separator)
+ *out << "|";
+ *out << "ROTATE270";
+ separator = true;
+ }
+
+ uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipH |
+ DrmHwcTransform::kRotate90 |
+ DrmHwcTransform::kRotate180 |
+ DrmHwcTransform::kRotate270;
+ if (transform & ~valid_bits) {
+ if (separator)
+ *out << "|";
+ *out << "INVALID";
+ }
+ *out << "]";
+}
+
+static const char *BlendingToString(DrmHwcBlending blending) {
+ switch (blending) {
+ case DrmHwcBlending::kNone:
+ return "NONE";
+ case DrmHwcBlending::kPreMult:
+ return "PREMULT";
+ case DrmHwcBlending::kCoverage:
+ return "COVERAGE";
+ default:
+ return "<invalid>";
+ }
+}
+
+void DrmDisplayComposition::Dump(std::ostringstream *out) const {
+ *out << "----DrmDisplayComposition"
+ << " crtc=" << (crtc_ ? crtc_->id() : -1)
+ << " type=" << DrmCompositionTypeToString(type_);
+
+ switch (type_) {
+ case DRM_COMPOSITION_TYPE_DPMS:
+ *out << " dpms_mode=" << DPMSModeToString(dpms_mode_);
+ break;
+ case DRM_COMPOSITION_TYPE_MODESET:
+ *out << " display_mode=" << display_mode_.h_display() << "x"
+ << display_mode_.v_display();
+ break;
+ default:
+ break;
+ }
+
+ *out << " Layers: count=" << layers_.size() << "\n";
+ for (size_t i = 0; i < layers_.size(); i++) {
+ const DrmHwcLayer &layer = layers_[i];
+ *out << " [" << i << "] ";
+
+ DumpBuffer(layer.buffer, out);
+
+ if (layer.protected_usage())
+ *out << " protected";
+
+ *out << " transform=";
+ DumpTransform(layer.transform, out);
+ *out << " blending[a=" << (int)layer.alpha
+ << "]=" << BlendingToString(layer.blending) << "\n";
+ }
+
+ *out << " Planes: count=" << composition_planes_.size() << "\n";
+ for (size_t i = 0; i < composition_planes_.size(); i++) {
+ const DrmCompositionPlane &comp_plane = composition_planes_[i];
+ *out << " [" << i << "]"
+ << " plane=" << (comp_plane.plane() ? comp_plane.plane()->id() : -1)
+ << " type=";
+ switch (comp_plane.type()) {
+ case DrmCompositionPlane::Type::kDisable:
+ *out << "DISABLE";
+ break;
+ case DrmCompositionPlane::Type::kLayer:
+ *out << "LAYER";
+ break;
+ default:
+ *out << "<invalid>";
+ break;
+ }
+
+ *out << " source_layer=";
+ for (auto i : comp_plane.source_layers()) {
+ *out << i << " ";
+ }
+ *out << "\n";
+ }
+}
+} // namespace android