aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp3
-rw-r--r--backend/backend.cpp136
-rw-r--r--backend/backendmanager.cpp80
-rw-r--r--drm/drmdevice.cpp12
-rw-r--r--drmhwctwo.cpp93
-rw-r--r--include/backend.h38
-rw-r--r--include/backendmanager.h58
-rw-r--r--include/drmdevice.h2
-rw-r--r--include/drmhwctwo.h11
9 files changed, 348 insertions, 85 deletions
diff --git a/Android.bp b/Android.bp
index 8bcd1aa..b4bf8e0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -94,6 +94,9 @@ cc_library_static {
"utils/autolock.cpp",
"utils/hwcutils.cpp",
+
+ "backend/backendmanager.cpp",
+ "backend/backend.cpp",
],
}
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
diff --git a/drm/drmdevice.cpp b/drm/drmdevice.cpp
index d7fd2f2..91fe158 100644
--- a/drm/drmdevice.cpp
+++ b/drm/drmdevice.cpp
@@ -570,4 +570,16 @@ int DrmDevice::GetConnectorProperty(const DrmConnector &connector,
return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name,
property);
}
+
+const std::string DrmDevice::GetName() const {
+ auto ver = drmGetVersion(fd_.get());
+ if (!ver) {
+ ALOGW("Failed to get drm version for fd=%d", fd_.get());
+ return "generic";
+ }
+
+ std::string name(ver->name);
+ drmFreeVersion(ver);
+ return name;
+}
} // namespace android
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp
index a847c35..ffc45ef 100644
--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "hwc-drm-two"
#include "drmhwctwo.h"
+#include "backendmanager.h"
#include "drmdisplaycomposition.h"
#include "drmhwcomposer.h"
#include "platform.h"
@@ -299,6 +300,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) {
return HWC2::Error::BadDisplay;
}
+ ret = BackendManager::GetInstance().SetBackendForDisplay(this);
+ if (ret) {
+ ALOGE("Failed to set backend for d=%d %d\n", display, ret);
+ return HWC2::Error::BadDisplay;
+ }
+
return ChosePreferredConfig();
}
@@ -900,92 +907,8 @@ void DrmHwcTwo::HwcDisplay::MarkValidated(
HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
uint32_t *num_requests) {
supported(__func__);
- *num_types = 0;
- *num_requests = 0;
- size_t avail_planes = primary_planes_.size() + overlay_planes_.size();
-
- /*
- * If more layers then planes, save one plane
- * for client composited layers
- */
- if (avail_planes < 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 : 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 = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0;
-
- int client_start = -1, client_size = 0;
-
- if (compositor_.ShouldFlattenOnClient()) {
- client_start = 0;
- client_size = z_map.size();
- MarkValidated(z_map, client_start, client_size);
- } else {
- for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
- if (!HardwareSupportsLayerType(l.second->sf_type()) ||
- !importer_->CanImportBuffer(l.second->buffer()) ||
- color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY ||
- (l.second->RequireScalingOrPhasing() &&
- resource_manager_->ForcedScalingWithGpu())) {
- if (client_start < 0)
- client_start = l.first;
- client_size = (l.first - client_start) + 1;
- }
- }
-
- 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 = CalcPixOps(z_map, start + i, client_size);
- if (po < gpu_pixops) {
- gpu_pixops = po;
- client_start = start + i;
- }
- }
- }
-
- MarkValidated(z_map, client_start, client_size);
-
- bool testing_needed = !(client_start == 0 && client_size == z_map.size());
-
- if (testing_needed && CreateComposition(true) != HWC2::Error::None) {
- ++total_stats_.failed_kms_validate_;
- gpu_pixops = total_pixops;
- client_size = z_map.size();
- MarkValidated(z_map, 0, client_size);
- }
- }
-
- *num_types = client_size;
-
- total_stats_.frames_flattened_ = compositor_.GetFlattenedFramesCount();
- total_stats_.gpu_pixops_ += gpu_pixops;
- total_stats_.total_pixops_ += total_pixops;
- return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
+ return backend_->ValidateDisplay(this, num_types, num_requests);
}
#if PLATFORM_SDK_VERSION > 28
diff --git a/include/backend.h b/include/backend.h
new file mode 100644
index 0000000..cd9d8cd
--- /dev/null
+++ b/include/backend.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_BACKEND_H
+#define ANDROID_BACKEND_H
+
+#include "drmhwctwo.h"
+
+namespace android {
+
+class Backend {
+ public:
+ virtual ~Backend() = default;
+ virtual HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+ uint32_t *num_types,
+ uint32_t *num_requests);
+ virtual std::tuple<int, int> GetClientLayers(
+ DrmHwcTwo::HwcDisplay *display,
+ const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map);
+ virtual bool IsClientLayer(DrmHwcTwo::HwcDisplay *display,
+ DrmHwcTwo::HwcLayer *layer);
+};
+} // namespace android
+
+#endif
diff --git a/include/backendmanager.h b/include/backendmanager.h
new file mode 100644
index 0000000..d141652
--- /dev/null
+++ b/include/backendmanager.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_BACKEND_MANAGER_H
+#define ANDROID_BACKEND_MANAGER_H
+
+#include "backend.h"
+#include "drmhwctwo.h"
+
+#include <functional>
+#include <map>
+#include <string>
+#include <vector>
+
+#define REGISTER_BACKEND(name_str_, backend_) \
+ static int \
+ backend = BackendManager::GetInstance() \
+ .RegisterBackend(name_str_, \
+ []() -> std::unique_ptr<Backend> { \
+ return std::make_unique<backend_>(); \
+ });
+
+namespace android {
+
+class BackendManager {
+ public:
+ using backend_constructor_t = std::function<std::unique_ptr<Backend>()>;
+ static BackendManager &GetInstance();
+ int RegisterBackend(const std::string &name,
+ backend_constructor_t backend_constructor);
+ int SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display);
+ std::unique_ptr<Backend> GetBackendByName(std::string &name);
+ HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+ uint32_t *num_types, uint32_t *num_requests);
+
+ private:
+ BackendManager() = default;
+
+ static const std::vector<std::string> client_devices_;
+
+ std::map<std::string, backend_constructor_t> available_backends_;
+};
+} // namespace android
+
+#endif
diff --git a/include/drmdevice.h b/include/drmdevice.h
index 91dd38b..1f08f20 100644
--- a/include/drmdevice.h
+++ b/include/drmdevice.h
@@ -70,6 +70,8 @@ class DrmDevice {
int GetConnectorProperty(const DrmConnector &connector, const char *prop_name,
DrmProperty *property);
+ const std::string GetName() const;
+
const std::vector<std::unique_ptr<DrmCrtc>> &crtcs() const;
uint32_t next_mode_id();
diff --git a/include/drmhwctwo.h b/include/drmhwctwo.h
index df75c41..8b1be4b 100644
--- a/include/drmhwctwo.h
+++ b/include/drmhwctwo.h
@@ -31,6 +31,8 @@
namespace android {
+class Backend;
+
class DrmHwcTwo : public hwc2_device_t {
public:
static int HookDevOpen(const struct hw_module_t *module, const char *name,
@@ -256,6 +258,13 @@ class DrmHwcTwo : public hwc2_device_t {
uint32_t frames_flattened_ = 0;
};
+ const Backend *backend() const {
+ return backend_.get();
+ }
+ void set_backend(std::unique_ptr<Backend> backend) {
+ backend_ = std::move(backend);
+ }
+
const std::vector<DrmPlane *> &primary_planes() const {
return primary_planes_;
}
@@ -310,6 +319,8 @@ class DrmHwcTwo : public hwc2_device_t {
std::vector<DrmPlane *> primary_planes_;
std::vector<DrmPlane *> overlay_planes_;
+ std::unique_ptr<Backend> backend_;
+
VSyncWorker vsync_worker_;
DrmConnector *connector_ = NULL;
DrmCrtc *crtc_ = NULL;