aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorMatvii Zorin <matvii.zorin@globallogic.com>2020-08-11 15:15:44 +0300
committerMatvii Zorin <matvii.zorin@globallogic.com>2020-08-26 14:43:23 +0300
commitef3c797daff14f3df798fe78f2843c41f549c6c5 (patch)
tree3457a4612e5a5925af2bd62b812e7b0484bcc1cc /backend
parent373de710a96450cb1bfcb678fcab0bee1078941d (diff)
downloaddrm_hwcomposer-ef3c797daff14f3df798fe78f2843c41f549c6c5.tar.gz
drm_hwcomposer: Add backend-dependent validation for HwcDisplay class
Different DRM/KMS backends have a variable set of limitations, which is not always exposed via DRM ioctls. This implementation of backend-dependent validation provides a register of platform-specific inherited backend class to the map by BackendManager class. ValidateDisplay function is moved to generic backend implementantion and separated into 2 additional methods. The map key is a string that contains the corresponding DRM driver name. During DrmHwcTwo class initialization the vendor.hwc.backend_override system property and driver name will be checked and a backend will be set for the appropriate display. If the map does not have any backend for the named driver, the generic backend will be used. Signed-off-by: Matvii Zorin <matvii.zorin@globallogic.com>
Diffstat (limited to 'backend')
-rw-r--r--backend/backend.cpp136
-rw-r--r--backend/backendmanager.cpp80
2 files changed, 216 insertions, 0 deletions
diff --git a/backend/backend.cpp b/backend/backend.cpp
new file mode 100644
index 0000000..08ee5a7
--- /dev/null
+++ b/backend/backend.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "backend.h"
+#include "backendmanager.h"
+#include "drmhwctwo.h"
+
+namespace android {
+
+HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+ uint32_t *num_types,
+ uint32_t *num_requests) {
+ *num_types = 0;
+ *num_requests = 0;
+ size_t avail_planes = display->primary_planes().size() +
+ display->overlay_planes().size();
+
+ /*
+ * If more layers then planes, save one plane
+ * for client composited layers
+ */
+ if (avail_planes < display->layers().size())
+ avail_planes--;
+
+ std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map, z_map_tmp;
+ uint32_t z_index = 0;
+ // First create a map of layers and z_order values
+ for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l :
+ display->layers())
+ z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second));
+ // normalise the map so that the lowest z_order layer has key 0
+ for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map_tmp)
+ z_map.emplace(std::make_pair(z_index++, l.second));
+
+ uint32_t total_pixops = display->CalcPixOps(z_map, 0, z_map.size());
+ uint32_t gpu_pixops = 0;
+
+ int client_start = -1, client_size = 0;
+
+ if (display->compositor().ShouldFlattenOnClient()) {
+ client_start = 0;
+ client_size = z_map.size();
+ display->MarkValidated(z_map, client_start, client_size);
+ } else {
+ std::tie(client_start, client_size) = GetClientLayers(display, z_map);
+
+ int extra_client = (z_map.size() - client_size) - avail_planes;
+ if (extra_client > 0) {
+ int start = 0, steps;
+ if (client_size != 0) {
+ int prepend = std::min(client_start, extra_client);
+ int append = std::min(int(z_map.size() - (client_start + client_size)),
+ extra_client);
+ start = client_start - prepend;
+ client_size += extra_client;
+ steps = 1 + std::min(std::min(append, prepend),
+ int(z_map.size()) - (start + client_size));
+ } else {
+ client_size = extra_client;
+ steps = 1 + z_map.size() - extra_client;
+ }
+
+ gpu_pixops = INT_MAX;
+ for (int i = 0; i < steps; i++) {
+ uint32_t po = display->CalcPixOps(z_map, start + i, client_size);
+ if (po < gpu_pixops) {
+ gpu_pixops = po;
+ client_start = start + i;
+ }
+ }
+ }
+
+ display->MarkValidated(z_map, client_start, client_size);
+
+ bool testing_needed = !(client_start == 0 && client_size == z_map.size());
+
+ if (testing_needed &&
+ display->CreateComposition(true) != HWC2::Error::None) {
+ ++display->total_stats().failed_kms_validate_;
+ gpu_pixops = total_pixops;
+ client_size = z_map.size();
+ display->MarkValidated(z_map, 0, client_size);
+ }
+ }
+
+ *num_types = client_size;
+
+ display->total_stats().frames_flattened_ = display->compositor()
+ .GetFlattenedFramesCount();
+ display->total_stats().gpu_pixops_ += gpu_pixops;
+ display->total_stats().total_pixops_ += total_pixops;
+
+ return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
+}
+
+std::tuple<int, int> Backend::GetClientLayers(
+ DrmHwcTwo::HwcDisplay *display,
+ const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map) {
+ int client_start = -1, client_size = 0;
+
+ for (auto & [ z_order, layer ] : z_map) {
+ if (IsClientLayer(display, layer)) {
+ if (client_start < 0)
+ client_start = z_order;
+ client_size = (z_order - client_start) + 1;
+ }
+ }
+
+ return std::make_tuple(client_start, client_size);
+}
+
+bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display,
+ DrmHwcTwo::HwcLayer *layer) {
+ return !display->HardwareSupportsLayerType(layer->sf_type()) ||
+ !display->importer()->CanImportBuffer(layer->buffer()) ||
+ display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY ||
+ (layer->RequireScalingOrPhasing() &&
+ display->resource_manager()->ForcedScalingWithGpu());
+}
+
+REGISTER_BACKEND("generic", Backend);
+
+} // namespace android
diff --git a/backend/backendmanager.cpp b/backend/backendmanager.cpp
new file mode 100644
index 0000000..80ec827
--- /dev/null
+++ b/backend/backendmanager.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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-backend"
+
+#include "backendmanager.h"
+#include "backend.h"
+#include "drmhwctwo.h"
+
+#include <cutils/properties.h>
+#include <log/log.h>
+
+namespace android {
+
+const std::vector<std::string> BackendManager::client_devices_ = {
+ "kirin",
+};
+
+BackendManager &BackendManager::GetInstance() {
+ static BackendManager backend_manager;
+
+ return backend_manager;
+}
+
+int BackendManager::RegisterBackend(const std::string &name,
+ backend_constructor_t backend_constructor) {
+ available_backends_[name] = std::move(backend_constructor);
+ return 0;
+}
+
+int BackendManager::SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display) {
+ std::string driver_name(display->drm()->GetName());
+ char backend_override[PROPERTY_VALUE_MAX];
+ property_get("vendor.hwc.backend_override", backend_override,
+ driver_name.c_str());
+ std::string backend_name(std::move(backend_override));
+
+ display->set_backend(GetBackendByName(backend_name));
+ if (!display->backend()) {
+ ALOGE("Failed to set backend '%s' for '%s' and driver '%s'",
+ backend_name.c_str(), display->connector()->name().c_str(),
+ driver_name.c_str());
+ return -EINVAL;
+ }
+
+ ALOGI("Backend '%s' for '%s' and driver '%s' was successfully set",
+ backend_name.c_str(), display->connector()->name().c_str(),
+ driver_name.c_str());
+
+ return 0;
+}
+
+std::unique_ptr<Backend> BackendManager::GetBackendByName(std::string &name) {
+ if (!available_backends_.size()) {
+ ALOGE("No backends are specified");
+ return nullptr;
+ }
+
+ auto it = available_backends_.find(name);
+ if (it == available_backends_.end()) {
+ auto it = std::find(client_devices_.begin(), client_devices_.end(), name);
+ name = it == client_devices_.end() ? "generic" : "client";
+ }
+
+ return available_backends_[name]();
+}
+} // namespace android