diff options
Diffstat (limited to 'drm/ResourceManager.cpp')
-rw-r--r-- | drm/ResourceManager.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp new file mode 100644 index 0000000..67ef7f8 --- /dev/null +++ b/drm/ResourceManager.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2018 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-resource-manager" + +#include "ResourceManager.h" + +#include <cutils/properties.h> +#include <log/log.h> +#include <sys/stat.h> + +#include <sstream> + +namespace android { + +ResourceManager::ResourceManager() : num_displays_(0), gralloc_(NULL) { +} + +int ResourceManager::Init() { + char path_pattern[PROPERTY_VALUE_MAX]; + // Could be a valid path or it can have at the end of it the wildcard % + // which means that it will try open all devices until an error is met. + int path_len = property_get("vendor.hwc.drm.device", path_pattern, + "/dev/dri/card%"); + int ret = 0; + if (path_pattern[path_len - 1] != '%') { + ret = AddDrmDevice(std::string(path_pattern)); + } else { + path_pattern[path_len - 1] = '\0'; + for (int idx = 0; !ret; ++idx) { + std::ostringstream path; + path << path_pattern << idx; + + struct stat buf; + if (stat(path.str().c_str(), &buf)) { + break; + } else if (IsKMSDev(path.str().c_str())) { + ret = AddDrmDevice(path.str()); + } + } + } + + if (!num_displays_) { + ALOGE("Failed to initialize any displays"); + return ret ? -EINVAL : ret; + } + + char scale_with_gpu[PROPERTY_VALUE_MAX]; + property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0"); + scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1)); + + return hw_get_module(GRALLOC_HARDWARE_MODULE_ID, + (const hw_module_t **)&gralloc_); +} + +int ResourceManager::AddDrmDevice(std::string path) { + std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>(); + int displays_added, ret; + std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_); + if (ret) + return ret; + std::shared_ptr<Importer> importer; + importer.reset(Importer::CreateInstance(drm.get())); + if (!importer) { + ALOGE("Failed to create importer instance"); + return -ENODEV; + } + importers_.push_back(importer); + drms_.push_back(std::move(drm)); + num_displays_ += displays_added; + return ret; +} + +DrmConnector *ResourceManager::AvailableWritebackConnector(int display) { + DrmDevice *drm_device = GetDrmDevice(display); + DrmConnector *writeback_conn = NULL; + if (drm_device) { + writeback_conn = drm_device->AvailableWritebackConnector(display); + if (writeback_conn) + return writeback_conn; + } + for (auto &drm : drms_) { + if (drm.get() == drm_device) + continue; + writeback_conn = drm->AvailableWritebackConnector(display); + if (writeback_conn) + return writeback_conn; + } + return writeback_conn; +} + +bool ResourceManager::IsKMSDev(const char *path) { + int fd = open(path, O_RDWR | O_CLOEXEC); + if (fd < 0) + return false; + + auto res = drmModeGetResources(fd); + if (!res) { + close(fd); + return false; + } + + bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 && + res->count_encoders > 0; + + drmModeFreeResources(res); + close(fd); + + return is_kms; +} + +DrmDevice *ResourceManager::GetDrmDevice(int display) { + for (auto &drm : drms_) { + if (drm->HandlesDisplay(display)) + return drm.get(); + } + return NULL; +} + +std::shared_ptr<Importer> ResourceManager::GetImporter(int display) { + for (unsigned int i = 0; i < drms_.size(); i++) { + if (drms_[i]->HandlesDisplay(display)) + return importers_[i]; + } + return NULL; +} + +const gralloc_module_t *ResourceManager::gralloc() { + return gralloc_; +} +} // namespace android |