diff options
Diffstat (limited to 'compositor/DrmDisplayComposition.cpp')
-rw-r--r-- | compositor/DrmDisplayComposition.cpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/compositor/DrmDisplayComposition.cpp b/compositor/DrmDisplayComposition.cpp new file mode 100644 index 0000000..79dd470 --- /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 "drm/DrmDevice.h" +#include "platform/platform.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 |