diff options
author | Saurabh Shah <saurshah@codeaurora.org> | 2016-06-27 16:40:58 -0700 |
---|---|---|
committer | Saurabh Shah <saurshah@codeaurora.org> | 2017-02-07 14:37:24 -0800 |
commit | 7d476edfb3059ad2d5f2afc5bd0320f4f8c05405 (patch) | |
tree | a28d9be1f707743af1f34785db3fba33231005a0 | |
parent | e37bdceb5724a5288519eed7798a940808a52c1b (diff) | |
download | android_hardware_qcom_sdm710_display-7d476edfb3059ad2d5f2afc5bd0320f4f8c05405.tar.gz android_hardware_qcom_sdm710_display-7d476edfb3059ad2d5f2afc5bd0320f4f8c05405.tar.bz2 android_hardware_qcom_sdm710_display-7d476edfb3059ad2d5f2afc5bd0320f4f8c05405.zip |
sdm: drm: Add support for default non-atomic mode
Add support for booting up with default non-atomic mode
Add libdrmutils that currently has:
DRMMaster:
Creates a master DRM session
Converts ION handles to DRM FB_ID
DRMResMgr:
Enables a default display path by providing APIs for
connector id, crtc id, mode etc
Change-Id: I1dc697d2cc5e3fa744c99e2c9ddd57bf06e78c4f
CRs-fixed: 1114808
47 files changed, 2861 insertions, 323 deletions
@@ -3,7 +3,7 @@ display-hals := include libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/cor ifneq ($(TARGET_IS_HEADLESS), true) display-hals += libcopybit liblight libmemtrack hdmi_cec \ - $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper + $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils endif ifneq ($(TARGET_USES_GRALLOC1), true) @@ -4,6 +4,9 @@ display_top := $(call my-dir) #Common C flags common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers common_flags += -Wconversion -Wall -Werror -std=c++11 +ifneq ($(TARGET_IS_HEADLESS), true) + common_flags += -DCOMPILE_DRM +endif ifeq ($(TARGET_USES_COLOR_METADATA), true) common_flags += -DUSE_COLOR_METADATA @@ -28,6 +31,7 @@ common_includes += $(display_top)/libqservice common_includes += $(display_top)/gpu_tonemapper ifneq ($(TARGET_IS_HEADLESS), true) common_includes += $(display_top)/libcopybit + common_includes += $(display_top)/libdrmutils endif common_includes += $(display_top)/include diff --git a/libdrmutils/Android.mk b/libdrmutils/Android.mk new file mode 100644 index 00000000..2f7ae4a9 --- /dev/null +++ b/libdrmutils/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libdrmutils +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \ + external/libdrm +LOCAL_SHARED_LIBRARIES := libdrm +LOCAL_CFLAGS := -DLOG_TAG=\"DRMUTILS\" -Wall -std=c++11 -Werror +LOCAL_CLANG := true +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +LOCAL_SRC_FILES := drm_master.cpp drm_res_mgr.cpp +LOCAL_COPY_HEADERS_TO := qcom/display +LOCAL_COPY_HEADERS := drm_master.h drm_res_mgr.h +include $(BUILD_SHARED_LIBRARY) diff --git a/libdrmutils/drm_logger.h b/libdrmutils/drm_logger.h new file mode 100644 index 00000000..b332ea04 --- /dev/null +++ b/libdrmutils/drm_logger.h @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __DRM_LOGGER_H__ +#define __DRM_LOGGER_H__ + +#include <utility> + +namespace drm_utils { + +class DRMLogger { + public: + virtual ~DRMLogger() {} + virtual void Error(const char *format, ...) = 0; + virtual void Info(const char *format, ...) = 0; + virtual void Debug(const char *format, ...) = 0; + + static void Set(DRMLogger *logger) { s_instance = logger; } + static DRMLogger *Get() { return s_instance; } + + private: + static DRMLogger *s_instance; +}; + +template <typename... T> +void DRM_LOGE(const char *format, T&&... args) { + if (DRMLogger::Get()) { + DRMLogger::Get()->Error(format, std::forward<T>(args)...); + } +} + +template <typename... T> +void DRM_LOGI(const char *format, T&&... args) { + if (DRMLogger::Get()) { + DRMLogger::Get()->Info(format, std::forward<T>(args)...); + } +} + +template <typename... T> +void DRM_LOGD_IF(bool pred, const char *format, T&&... args) { + if (pred && DRMLogger::Get()) { + DRMLogger::Get()->Debug(format, std::forward<T>(args)...); + } +} + +} // namespace drm_utils + +#endif // __DRM_LOGGER_H__ + diff --git a/libdrmutils/drm_master.cpp b/libdrmutils/drm_master.cpp new file mode 100644 index 00000000..f6a2e41f --- /dev/null +++ b/libdrmutils/drm_master.cpp @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <xf86drm.h> +#include <xf86drmMode.h> +#include <drm/drm_fourcc.h> + +#include <algorithm> +#include <iterator> + +#include "drm_master.h" + +#define __CLASS__ "DRMMaster" + +using std::mutex; +using std::lock_guard; +using std::begin; +using std::copy; +using std::end; +using std::fill; + +namespace drm_utils { + +DRMLogger *DRMLogger::s_instance = nullptr; +DRMMaster *DRMMaster::s_instance = nullptr; +mutex DRMMaster::s_lock; + +int DRMMaster::GetInstance(DRMMaster **master) { + lock_guard<mutex> obj(s_lock); + + if (!s_instance) { + s_instance = new DRMMaster(); + if (s_instance->Init() < 0) { + delete s_instance; + s_instance = nullptr; + return -ENODEV; + } + } + + *master = s_instance; + return 0; +} + +int DRMMaster::Init() { + dev_fd_ = drmOpen("msm_drm", nullptr); + if (dev_fd_ < 0) { + DRM_LOGE("%s::%s: drmOpen failed with error %d", __CLASS__, __FUNCTION__, dev_fd_); + return -ENODEV; + } + + return 0; +} + +DRMMaster::~DRMMaster() { + drmClose(dev_fd_); + dev_fd_ = -1; +} + +int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *gem_handle, uint32_t *fb_id) { + int ret = drmPrimeFDToHandle(dev_fd_, drm_buffer.fd, gem_handle); + if (ret) { + DRM_LOGE("%s::%s: drmPrimeFDToHandle failed with error %d", __CLASS__, __FUNCTION__, ret); + return ret; + } + + uint32_t gem_handles[4] = {0}; + uint32_t pitches[4] = {0}; + uint32_t offsets[4] = {0}; + uint64_t modifier[4] = {0}; + + fill(begin(gem_handles), begin(gem_handles) + drm_buffer.num_planes, *gem_handle); + copy(begin(drm_buffer.stride), end(drm_buffer.stride), begin(pitches)); + copy(begin(drm_buffer.offset), end(drm_buffer.offset), begin(offsets)); + fill(begin(modifier), begin(modifier) + drm_buffer.num_planes, drm_buffer.drm_format_modifier); + + ret = drmModeAddFB3(dev_fd_, drm_buffer.width, drm_buffer.height, drm_buffer.drm_format, + gem_handles, pitches, offsets, modifier, fb_id, DRM_MODE_FB_MODIFIERS); + if (ret) { + DRM_LOGE("%s::%s: drmModeAddFB3 failed with error %d", __CLASS__, __FUNCTION__, ret); + struct drm_gem_close gem_close = {}; + gem_close.handle = *gem_handle; + int ret1 = drmIoctl(dev_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close); + if (ret1) { + DRM_LOGE("drmIoctl::DRM_IOCTL_GEM_CLOSE failed with error %d", ret1); + } + } + + return ret; +} + +int DRMMaster::RemoveFbId(uint32_t gem_handle, uint32_t fb_id) { + int ret = drmModeRmFB(dev_fd_, fb_id); + if (ret) { + DRM_LOGE("%s::%s: drmModeRmFB failed with error %d", __CLASS__, __FUNCTION__, ret); + } + + struct drm_gem_close gem_close = {}; + gem_close.handle = gem_handle; + ret = drmIoctl(dev_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close); + if (ret) { + DRM_LOGE("drmIoctl::DRM_IOCTL_GEM_CLOSE failed with error %d", ret); + } + + return ret; +} + +} // namespace drm_utils diff --git a/libdrmutils/drm_master.h b/libdrmutils/drm_master.h new file mode 100644 index 00000000..8c32a1b9 --- /dev/null +++ b/libdrmutils/drm_master.h @@ -0,0 +1,94 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __DRM_MASTER_H__ +#define __DRM_MASTER_H__ + +#include <mutex> + +#include "drm_logger.h" + +namespace drm_utils { + +struct DRMBuffer { + int fd = -1; + uint32_t width = 0; + uint32_t height = 0; + uint32_t drm_format = 0; + uint64_t drm_format_modifier = 0; + uint32_t stride[4] = {}; + uint32_t offset[4] = {}; + uint32_t num_planes = 1; +}; + +class DRMMaster { + public: + ~DRMMaster(); + /* Converts from ION fd --> Prime Handle --> FB_ID. + * Input: + * drm_buffer: A DRMBuffer obj that packages description of buffer + * Output: + * fb_id: Pointer to store DRM framebuffer id into + * Returns: + * ioctl error code + */ + int CreateFbId(const DRMBuffer &drm_buffer, uint32_t *gem_handle, uint32_t *fb_id); + /* Removes the fb_id from DRM + * Input: + * fb_id: DRM FB to be removed + * Returns: + * ioctl error code + */ + int RemoveFbId(uint32_t gem_handle, uint32_t fb_id); + /* Poplulates master DRM fd + * Input: + * fd: Pointer to store master fd into + */ + void GetHandle(int *fd) { *fd = dev_fd_; } + + /* Creates an instance of DRMMaster if it doesn't exist and initializes it. Threadsafe. + * Input: + * master: Pointer to store a pointer to the instance + * Returns: + * -ENODEV if device cannot be opened or initilization fails + */ + static int GetInstance(DRMMaster **master); + + private: + DRMMaster() {} + int Init(); + + int dev_fd_ = -1; // Master fd for DRM + static DRMMaster *s_instance; // Singleton instance + static std::mutex s_lock; +}; + +} // namespace drm_utils + +#endif // __DRM_MASTER_H__ diff --git a/libdrmutils/drm_res_mgr.cpp b/libdrmutils/drm_res_mgr.cpp new file mode 100644 index 00000000..61d25c44 --- /dev/null +++ b/libdrmutils/drm_res_mgr.cpp @@ -0,0 +1,149 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <errno.h> + +#include "drm_master.h" +#include "drm_res_mgr.h" + +#define DEBUG 0 +#define __CLASS__ "DRMResMgr" + +using std::mutex; +using std::lock_guard; + +namespace drm_utils { + +DRMResMgr *DRMResMgr::s_instance = nullptr; +mutex DRMResMgr::s_lock; + +static bool GetConnector(int dev_fd, drmModeRes *res, drmModeConnector **connector) { + for (auto i = 0; i < res->count_connectors; i++) { + drmModeConnector *conn = drmModeGetConnector(dev_fd, res->connectors[i]); + if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI && conn->count_modes && + conn->connection == DRM_MODE_CONNECTED) { + *connector = conn; + DRM_LOGI("drm_utils::%s found connector %d", __FUNCTION__, conn->connector_id); + return true; + } + } + + return false; +} + +static bool GetEncoder(int dev_fd, drmModeConnector *conn, drmModeEncoder **encoder) { + for (auto i = 0; i < conn->count_encoders; i++) { + drmModeEncoder *enc = drmModeGetEncoder(dev_fd, conn->encoders[i]); + if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) { + *encoder = enc; + DRM_LOGI("drm_utils::%s found encoder %d", __FUNCTION__, enc->encoder_id); + return true; + } + } + return false; +} + +static bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrtc **crtc) { + for (auto i = 0; i < res->count_crtcs; i++) { + if (enc->possible_crtcs & (1 << i)) { + drmModeCrtc *c = drmModeGetCrtc(dev_fd, res->crtcs[i]); + if (c) { + *crtc = c; + DRM_LOGI("drm_utils::%s found crtc %d", __FUNCTION__, c->crtc_id); + return true; + } + } + } + + return false; +} + +int DRMResMgr::GetInstance(DRMResMgr **res_mgr) { + lock_guard<mutex> obj(s_lock); + + if (!s_instance) { + s_instance = new DRMResMgr(); + if (s_instance->Init() < 0) { + delete s_instance; + s_instance = nullptr; + return -ENODEV; + } + } + + *res_mgr = s_instance; + return 0; +} + +int DRMResMgr::Init() { + DRMMaster *master = nullptr; + int dev_fd = -1; + + int ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + return ret; + } + + master->GetHandle(&dev_fd); + drmModeRes *res = drmModeGetResources(dev_fd); + if (res == nullptr) { + DRM_LOGE("%s::%s: drmModeGetResources failed", __CLASS__, __FUNCTION__); + return -ENODEV; + } + + drmModeConnector *conn = nullptr; + if (!GetConnector(dev_fd, res, &conn)) { + DRM_LOGE("%s::%s: Failed to find a connector", __CLASS__, __FUNCTION__); + return -ENODEV; + } + + drmModeEncoder *enc = nullptr; + if (!GetEncoder(dev_fd, conn, &enc)) { + DRM_LOGE("%s::%s: Failed to find an encoder", __CLASS__, __FUNCTION__); + drmModeFreeConnector(conn); + return -ENODEV; + } + + drmModeCrtc *crtc = nullptr; + if (!GetCrtc(dev_fd, res, enc, &crtc)) { + DRM_LOGE("%s::%s: Failed to find a crtc", __CLASS__, __FUNCTION__); + drmModeFreeEncoder(enc); + drmModeFreeConnector(conn); + drmModeFreeResources(res); + return -ENODEV; + } + + res_ = res; + conn_ = conn; + enc_ = enc; + crtc_ = crtc; + + return 0; +} + +} // namespace drm_utils diff --git a/libdrmutils/drm_res_mgr.h b/libdrmutils/drm_res_mgr.h new file mode 100644 index 00000000..3a8378c5 --- /dev/null +++ b/libdrmutils/drm_res_mgr.h @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __DRM_RES_MGR_H__ +#define __DRM_RES_MGR_H__ + +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include <mutex> + +namespace drm_utils { + +class DRMResMgr { + public: + /* Returns the default connector id for primary panel */ + void GetConnectorId(uint32_t *id) { *id = conn_->connector_id; } + /* Returns the default crtc id for primary pipeline */ + void GetCrtcId(uint32_t *id) { *id = crtc_->crtc_id; } + /* Returns the default mode currently used by the connector */ + void GetMode(drmModeModeInfo *mode) { *mode = conn_->modes[0]; } + /* Returns the panel dimensions in mm */ + void GetDisplayDimInMM(uint32_t *w, uint32_t *h) { + *w = conn_->mmWidth; + *h = conn_->mmHeight; + } + + /* Creates and initializes an instance of DRMResMgr. On success, returns a pointer to it, on + * failure returns -ENODEV */ + static int GetInstance(DRMResMgr **res_mgr); + + private: + int Init(); + + drmModeRes *res_ = nullptr; + drmModeConnector *conn_ = nullptr; + drmModeEncoder *enc_ = nullptr; + drmModeCrtc *crtc_ = nullptr; + + static DRMResMgr *s_instance; + static std::mutex s_lock; +}; + +} // namespace drm_utils + +#endif // __DRM_RES_MGR_H__ diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk index c1d4d79b..6a0f868c 100644 --- a/libgralloc/Android.mk +++ b/libgralloc/Android.mk @@ -23,7 +23,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc libqdMetaData libqdutils ifneq ($(TARGET_IS_HEADLESS), true) -LOCAL_SHARED_LIBRARIES += libGLESv1_CM +LOCAL_SHARED_LIBRARIES += libGLESv1_CM libdrmutils endif LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps) diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp index a0339b4c..848c741e 100644 --- a/libgralloc/gpu.cpp +++ b/libgralloc/gpu.cpp @@ -20,16 +20,216 @@ #include <fcntl.h> #include <cutils/properties.h> #include <sys/mman.h> +#include <linux/msm_ion.h> +#ifdef COMPILE_DRM +#include <drm/drm_fourcc.h> +#include <drm_master.h> +#endif +#include <qdMetaData.h> +#include <qd_utils.h> + +#include <algorithm> #include "gr.h" #include "gpu.h" #include "memalloc.h" #include "alloc_controller.h" -#include <qdMetaData.h> -#include <linux/msm_ion.h> + +#ifdef COMPILE_DRM +#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED +#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) +#endif +#endif using namespace gralloc; +#ifdef COMPILE_DRM +using namespace drm_utils; + +static int getPlaneStrideOffset(private_handle_t *hnd, uint32_t *stride, + uint32_t *offset, uint32_t *num_planes) { + struct android_ycbcr yuvInfo = {}; + *num_planes = 1; + + switch (hnd->format) { + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_BGR_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + stride[0] = hnd->width * 2; + break; + case HAL_PIXEL_FORMAT_RGB_888: + stride[0] = hnd->width * 3; + break; + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRX_8888: + case HAL_PIXEL_FORMAT_RGBA_1010102: + case HAL_PIXEL_FORMAT_ARGB_2101010: + case HAL_PIXEL_FORMAT_RGBX_1010102: + case HAL_PIXEL_FORMAT_XRGB_2101010: + case HAL_PIXEL_FORMAT_BGRA_1010102: + case HAL_PIXEL_FORMAT_ABGR_2101010: + case HAL_PIXEL_FORMAT_BGRX_1010102: + case HAL_PIXEL_FORMAT_XBGR_2101010: + stride[0] = hnd->width * 4; + break; + } + + // Format is RGB + if (stride[0]) { + return 0; + } + + (*num_planes)++; + int ret = getYUVPlaneInfo(hnd, &yuvInfo); + if (ret < 0) { + ALOGE("%s failed", __FUNCTION__); + return ret; + } + + stride[0] = static_cast<uint32_t>(yuvInfo.ystride); + offset[0] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base); + stride[1] = static_cast<uint32_t>(yuvInfo.cstride); + switch (hnd->format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + case HAL_PIXEL_FORMAT_YCbCr_420_P010: + case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: + offset[1] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base); + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + offset[1] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base); + break; + case HAL_PIXEL_FORMAT_YV12: + offset[1] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base); + stride[2] = static_cast<uint32_t>(yuvInfo.cstride); + offset[2] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base); + (*num_planes)++; + break; + default: + ALOGW("%s: Unsupported format %s", __FUNCTION__, + qdutils::GetHALPixelFormatString(hnd->format)); + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { + std::fill(offset, offset + 4, 0); + } + + return 0; +} + +static void getDRMFormat(int hal_format, int flags, uint32_t *drm_format, + uint64_t *drm_format_modifier) { + + if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { + *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED; + } + + switch (hal_format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + *drm_format = DRM_FORMAT_RGBA8888; + break; + case HAL_PIXEL_FORMAT_RGBA_5551: + *drm_format = DRM_FORMAT_RGBA5551; + break; + case HAL_PIXEL_FORMAT_RGBA_4444: + *drm_format = DRM_FORMAT_RGBA4444; + break; + case HAL_PIXEL_FORMAT_BGRA_8888: + *drm_format = DRM_FORMAT_BGRA8888; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + *drm_format = DRM_FORMAT_RGBX8888; + break; + case HAL_PIXEL_FORMAT_BGRX_8888: + *drm_format = DRM_FORMAT_BGRX8888; + break; + case HAL_PIXEL_FORMAT_RGB_888: + *drm_format = DRM_FORMAT_RGB888; + break; + case HAL_PIXEL_FORMAT_RGB_565: + *drm_format = DRM_FORMAT_RGB565; + break; + case HAL_PIXEL_FORMAT_BGR_565: + *drm_format = DRM_FORMAT_BGR565; + break; + case HAL_PIXEL_FORMAT_RGBA_1010102: + *drm_format = DRM_FORMAT_RGBA1010102; + break; + case HAL_PIXEL_FORMAT_ARGB_2101010: + *drm_format = DRM_FORMAT_ARGB2101010; + break; + case HAL_PIXEL_FORMAT_RGBX_1010102: + *drm_format = DRM_FORMAT_RGBX1010102; + break; + case HAL_PIXEL_FORMAT_XRGB_2101010: + *drm_format = DRM_FORMAT_XRGB2101010; + break; + case HAL_PIXEL_FORMAT_BGRA_1010102: + *drm_format = DRM_FORMAT_BGRA1010102; + break; + case HAL_PIXEL_FORMAT_ABGR_2101010: + *drm_format = DRM_FORMAT_ABGR2101010; + break; + case HAL_PIXEL_FORMAT_BGRX_1010102: + *drm_format = DRM_FORMAT_BGRX1010102; + break; + case HAL_PIXEL_FORMAT_XBGR_2101010: + *drm_format = DRM_FORMAT_XBGR2101010; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + *drm_format = DRM_FORMAT_NV12; + break; + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + *drm_format = DRM_FORMAT_NV12; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + *drm_format = DRM_FORMAT_NV12; + *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED; + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + *drm_format = DRM_FORMAT_NV21; + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + *drm_format = DRM_FORMAT_NV21; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_P010: + // TODO *drm_format = DRM_FORMAT_P010; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: + // TODO *drm_format = DRM_FORMAT_P010; + // *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED | + // DRM_FORMAT_MOD_QCOM_TIGHT; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + *drm_format = DRM_FORMAT_NV16; + break; + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + *drm_format = DRM_FORMAT_NV61; + break; + case HAL_PIXEL_FORMAT_YV12: + *drm_format = DRM_FORMAT_YVU420; + break; + default: + ALOGW("%s: Unsupported format %s", __FUNCTION__, + qdutils::GetHALPixelFormatString(hal_format)); + } +} +#endif + gpu_context_t::gpu_context_t(const private_module_t* module, IAllocController* alloc_ctrl ) : mAllocCtrl(alloc_ctrl) @@ -169,11 +369,46 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage, ColorSpace_t colorSpace = ITU_R_601; setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace); +#ifdef COMPILE_DRM + if (qdutils::getDriverType() == qdutils::DriverType::DRM && + usage & GRALLOC_USAGE_HW_COMPOSER) { + DRMBuffer buf = {}; + int ret = getPlaneStrideOffset(hnd, buf.stride, buf.offset, + &buf.num_planes); + if (ret < 0) { + ALOGE("%s failed", __FUNCTION__); + return ret; + } + + buf.fd = hnd->fd; + buf.width = hnd->width; + buf.height = hnd->height; + getDRMFormat(hnd->format, flags, &buf.drm_format, + &buf.drm_format_modifier); + + DRMMaster *master = nullptr; + ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + ALOGE("%s Failed to acquire DRMMaster instance", __FUNCTION__); + return ret; + } + + ret = master->CreateFbId(buf, &hnd->gem_handle, &hnd->fb_id); + if (ret < 0) { + ALOGE("%s: CreateFbId failed. width %d, height %d, " \ + "format: %s, stride %u, error %d", __FUNCTION__, + buf.width, buf.height, + qdutils::GetHALPixelFormatString(hnd->format), + buf.stride[0], errno); + return ret; + } + } +#endif + *pHandle = hnd; } ALOGE_IF(err, "gralloc failed err=%s", strerror(-err)); - return err; } @@ -369,6 +604,23 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { if (err) return err; } + +#ifdef COMPILE_DRM + if (hnd->fb_id) { + DRMMaster *master = nullptr; + int ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + ALOGE("%s Failed to acquire DRMMaster instance", __FUNCTION__); + return ret; + } + ret = master->RemoveFbId(hnd->gem_handle, hnd->fb_id); + if (ret < 0) { + ALOGE("%s: Removing fb_id %d failed with error %d", __FUNCTION__, + hnd->fb_id, errno); + } + } +#endif + delete hnd; return 0; } diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h index 5797546a..57821800 100644 --- a/libgralloc/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2011 - 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2011 - 2017, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -247,6 +247,8 @@ struct private_handle_t : public native_handle { uint64_t base_metadata __attribute__((aligned(8))); int unaligned_width; // holds width client asked to allocate int unaligned_height; // holds height client asked to allocate + unsigned int gem_handle; + unsigned int fb_id; #ifdef __cplusplus static const int sNumFds = 2; @@ -263,7 +265,7 @@ struct private_handle_t : public native_handle { base(0), offset_metadata(0), gpuaddr(0), format(format), width(width), height(height), base_metadata(0), unaligned_width(width), - unaligned_height(height) + unaligned_height(height), gem_handle(0), fb_id(0) { version = (int) sizeof(native_handle); numInts = sNumInts(); diff --git a/libgralloc1/Android.mk b/libgralloc1/Android.mk index b66a027c..fb8c74a4 100644 --- a/libgralloc1/Android.mk +++ b/libgralloc1/Android.mk @@ -10,6 +10,9 @@ LOCAL_C_INCLUDES := $(common_includes) \ external/libcxx/include/ LOCAL_SHARED_LIBRARIES := $(common_libs) libqdMetaData libsync libqdutils +ifneq ($(TARGET_IS_HEADLESS), true) +LOCAL_SHARED_LIBRARIES += libdrmutils +endif LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wall -std=c++11 -Werror LOCAL_CFLAGS += -isystem $(kernel_includes) LOCAL_CLANG := true diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp index cea8ac9a..c2d8598b 100644 --- a/libgralloc1/gr_buf_mgr.cpp +++ b/libgralloc1/gr_buf_mgr.cpp @@ -17,6 +17,9 @@ * limitations under the License. */ +#include <drm/drm_fourcc.h> +#include <drm_master.h> + #include <utility> #include "qd_utils.h" @@ -28,6 +31,192 @@ namespace gralloc1 { +using namespace drm_utils; + +static int getPlaneStrideOffset(private_handle_t *hnd, uint32_t *stride, + uint32_t *offset, uint32_t *num_planes) { + struct android_ycbcr yuvInfo = {}; + *num_planes = 1; + + switch (hnd->format) { + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_BGR_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + stride[0] = hnd->width * 2; + break; + case HAL_PIXEL_FORMAT_RGB_888: + stride[0] = hnd->width * 3; + break; + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRX_8888: + case HAL_PIXEL_FORMAT_RGBA_1010102: + case HAL_PIXEL_FORMAT_ARGB_2101010: + case HAL_PIXEL_FORMAT_RGBX_1010102: + case HAL_PIXEL_FORMAT_XRGB_2101010: + case HAL_PIXEL_FORMAT_BGRA_1010102: + case HAL_PIXEL_FORMAT_ABGR_2101010: + case HAL_PIXEL_FORMAT_BGRX_1010102: + case HAL_PIXEL_FORMAT_XBGR_2101010: + stride[0] = hnd->width * 4; + break; + } + + // Format is RGB + if (stride[0]) { + return 0; + } + + (*num_planes)++; + int ret = getYUVPlaneInfo(hnd, &yuvInfo); + if (ret < 0) { + ALOGE("%s failed", __FUNCTION__); + return ret; + } + + stride[0] = static_cast<uint32_t>(yuvInfo.ystride); + offset[0] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base); + stride[1] = static_cast<uint32_t>(yuvInfo.cstride); + switch (hnd->format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + case HAL_PIXEL_FORMAT_YCbCr_420_P010: + case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: + offset[1] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base); + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + offset[1] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base); + break; + case HAL_PIXEL_FORMAT_YV12: + offset[1] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base); + stride[2] = static_cast<uint32_t>(yuvInfo.cstride); + offset[2] = static_cast<uint32_t>( + reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base); + (*num_planes)++; + break; + default: + ALOGW("%s: Unsupported format %s", __FUNCTION__, + qdutils::GetHALPixelFormatString(hnd->format)); + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { + std::fill(offset, offset + 4, 0); + } + + return 0; +} + +static void getDRMFormat(int hal_format, int flags, uint32_t *drm_format, + uint64_t *drm_format_modifier) { + + if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) { + *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED; + } + + switch (hal_format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + *drm_format = DRM_FORMAT_RGBA8888; + break; + case HAL_PIXEL_FORMAT_RGBA_5551: + *drm_format = DRM_FORMAT_RGBA5551; + break; + case HAL_PIXEL_FORMAT_RGBA_4444: + *drm_format = DRM_FORMAT_RGBA4444; + break; + case HAL_PIXEL_FORMAT_BGRA_8888: + *drm_format = DRM_FORMAT_BGRA8888; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + *drm_format = DRM_FORMAT_RGBX8888; + break; + case HAL_PIXEL_FORMAT_BGRX_8888: + *drm_format = DRM_FORMAT_BGRX8888; + break; + case HAL_PIXEL_FORMAT_RGB_888: + *drm_format = DRM_FORMAT_RGB888; + break; + case HAL_PIXEL_FORMAT_RGB_565: + *drm_format = DRM_FORMAT_RGB565; + break; + case HAL_PIXEL_FORMAT_BGR_565: + *drm_format = DRM_FORMAT_BGR565; + break; + case HAL_PIXEL_FORMAT_RGBA_1010102: + *drm_format = DRM_FORMAT_RGBA1010102; + break; + case HAL_PIXEL_FORMAT_ARGB_2101010: + *drm_format = DRM_FORMAT_ARGB2101010; + break; + case HAL_PIXEL_FORMAT_RGBX_1010102: + *drm_format = DRM_FORMAT_RGBX1010102; + break; + case HAL_PIXEL_FORMAT_XRGB_2101010: + *drm_format = DRM_FORMAT_XRGB2101010; + break; + case HAL_PIXEL_FORMAT_BGRA_1010102: + *drm_format = DRM_FORMAT_BGRA1010102; + break; + case HAL_PIXEL_FORMAT_ABGR_2101010: + *drm_format = DRM_FORMAT_ABGR2101010; + break; + case HAL_PIXEL_FORMAT_BGRX_1010102: + *drm_format = DRM_FORMAT_BGRX1010102; + break; + case HAL_PIXEL_FORMAT_XBGR_2101010: + *drm_format = DRM_FORMAT_XBGR2101010; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + *drm_format = DRM_FORMAT_NV12; + break; + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + *drm_format = DRM_FORMAT_NV12; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + *drm_format = DRM_FORMAT_NV12; + *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED; + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + *drm_format = DRM_FORMAT_NV21; + break; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + *drm_format = DRM_FORMAT_NV21; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_P010: + // TODO *drm_format = DRM_FORMAT_P010; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: + // TODO *drm_format = DRM_FORMAT_P010; + // *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED | + // DRM_FORMAT_MOD_QCOM_TIGHT; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + *drm_format = DRM_FORMAT_NV16; + break; + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + *drm_format = DRM_FORMAT_NV61; + break; + case HAL_PIXEL_FORMAT_YV12: + *drm_format = DRM_FORMAT_YVU420; + break; + default: + ALOGW("%s: Unsupported format %s", __FUNCTION__, + qdutils::GetHALPixelFormatString(hal_format)); + + } +} + BufferManager::BufferManager() { char property[PROPERTY_VALUE_MAX]; @@ -139,6 +328,8 @@ void BufferManager::CreateSharedHandle(buffer_handle_t inbuffer, const BufferDes descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetProducerUsage(), descriptor.GetConsumerUsage()); + // TODO(user): Not sure what to do for fb_id. Use duped fd and new dimensions? + *outbuffer = out_hnd; } @@ -156,6 +347,19 @@ gralloc1_error_t BufferManager::FreeBuffer(private_handle_t const *hnd) { // delete handle also private_handle_t *handle = const_cast<private_handle_t *>(hnd); + if (handle->fb_id) { + int ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + ALOGE("%s Failed to acquire DRMMaster instance", __FUNCTION__); + return ret; + } + ret = master->RemoveFbId(hnd->gem_handle, hnd->fb_id); + if (ret < 0) { + ALOGE("%s: Removing fb_id %d failed with error %d", __FUNCTION__, + hnd->fb_id, errno); + } + } + delete handle; return GRALLOC1_ERROR_NONE; @@ -409,6 +613,39 @@ int BufferManager::AllocateBuffer(unsigned int size, int aligned_w, int aligned_ hnd->gpuaddr = 0; setMetaData(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace)); + if (qdutils::getDriverType() == qdutils::DriverType::DRM && + cons_usage & GRALLOC_USAGE_HW_COMPOSER) { + DRMBuffer buf = {}; + int ret = getPlaneStrideOffset(hnd, buf.stride, buf.offset, + &buf.num_planes); + if (ret < 0) { + ALOGE("%s failed", __FUNCTION__); + return ret; + } + + buf.fd = hnd->fd; + buf.width = hnd->width; + buf.height = hnd->height; + getDRMFormat(hnd->format, flags, &buf.drm_format, + &buf.drm_format_modifier); + + DRMMaster *master = nullptr; + ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + ALOGE("%s Failed to acquire DRMMaster instance", __FUNCTION__); + return ret; + } + + ret = master->CreateFbId(buf, &hnd->gem_handle, &hnd->fb_id); + if (ret < 0) { + ALOGE("%s: CreateFbId failed. width %d, height %d, " \ + "format: %s, stride %u, error %d", __FUNCTION__, + buf.width, buf.height, + qdutils::GetHALPixelFormatString(hnd->format), + buf.stride[0], errno); + return ret; + } + } *handle = hnd; diff --git a/libgralloc1/gr_priv_handle.h b/libgralloc1/gr_priv_handle.h index ee38b4dc..8a01d387 100644 --- a/libgralloc1/gr_priv_handle.h +++ b/libgralloc1/gr_priv_handle.h @@ -84,6 +84,7 @@ struct private_handle_t : public native_handle_t { int stride; uint64_t base_metadata __attribute__((aligned(8))); + unsigned int fb_id; // added for gralloc1 int unaligned_width; // holds width client asked to allocate @@ -117,7 +118,8 @@ struct private_handle_t : public native_handle_t { unaligned_width(width), unaligned_height(height), producer_usage(GRALLOC1_PRODUCER_USAGE_NONE), - consumer_usage(GRALLOC1_CONSUMER_USAGE_NONE) { + consumer_usage(GRALLOC1_CONSUMER_USAGE_NONE), + fb_id(0) { version = static_cast<int>(sizeof(native_handle)); numInts = NumInts(); numFds = kNumFds; diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp index 170b1d87..10ac90b2 100644 --- a/libqdutils/qd_utils.cpp +++ b/libqdutils/qd_utils.cpp @@ -28,6 +28,7 @@ */ #include <unistd.h> +#include <gralloc_priv.h> #include "qd_utils.h" namespace qdutils { @@ -281,4 +282,79 @@ DriverType getDriverType() { return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB; } +const char *GetHALPixelFormatString(int format) { + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + return "RGBA_8888"; + case HAL_PIXEL_FORMAT_RGBX_8888: + return "RGBX_8888"; + case HAL_PIXEL_FORMAT_RGB_888: + return "RGB_888"; + case HAL_PIXEL_FORMAT_RGB_565: + return "RGB_565"; + case HAL_PIXEL_FORMAT_BGR_565: + return "BGR_565"; + case HAL_PIXEL_FORMAT_BGRA_8888: + return "BGRA_8888"; + case HAL_PIXEL_FORMAT_RGBA_5551: + return "RGBA_5551"; + case HAL_PIXEL_FORMAT_RGBA_4444: + return "RGBA_4444"; + case HAL_PIXEL_FORMAT_YV12: + return "YV12"; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + return "YCbCr_422_SP_NV16"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return "YCrCb_420_SP_NV21"; + case HAL_PIXEL_FORMAT_YCbCr_422_I: + return "YCbCr_422_I_YUY2"; + case HAL_PIXEL_FORMAT_YCrCb_422_I: + return "YCrCb_422_I_YVYU"; + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + return "NV12_ENCODEABLE"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + return "YCbCr_420_SP_TILED_TILE_4x2"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return "YCbCr_420_SP"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: + return "YCrCb_420_SP_ADRENO"; + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + return "YCrCb_422_SP"; + case HAL_PIXEL_FORMAT_R_8: + return "R_8"; + case HAL_PIXEL_FORMAT_RG_88: + return "RG_88"; + case HAL_PIXEL_FORMAT_INTERLACE: + return "INTERLACE"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + return "YCbCr_420_SP_VENUS"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + return "YCrCb_420_SP_VENUS"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + return "YCbCr_420_SP_VENUS_UBWC"; + case HAL_PIXEL_FORMAT_RGBA_1010102: + return "RGBA_1010102"; + case HAL_PIXEL_FORMAT_ARGB_2101010: + return "ARGB_2101010"; + case HAL_PIXEL_FORMAT_RGBX_1010102: + return "RGBX_1010102"; + case HAL_PIXEL_FORMAT_XRGB_2101010: + return "XRGB_2101010"; + case HAL_PIXEL_FORMAT_BGRA_1010102: + return "BGRA_1010102"; + case HAL_PIXEL_FORMAT_ABGR_2101010: + return "ABGR_2101010"; + case HAL_PIXEL_FORMAT_BGRX_1010102: + return "BGRX_1010102"; + case HAL_PIXEL_FORMAT_XBGR_2101010: + return "XBGR_2101010"; + case HAL_PIXEL_FORMAT_YCbCr_420_P010: + return "YCbCr_420_P010"; + case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: + return "YCbCr_420_TP10_UBWC"; + default: + return "Unknown_format"; + } +} + }; //namespace qdutils diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h index 7b3ae40a..f3b0c042 100644 --- a/libqdutils/qd_utils.h +++ b/libqdutils/qd_utils.h @@ -69,6 +69,7 @@ enum class DriverType { DRM, }; DriverType getDriverType(); +const char *GetHALPixelFormatString(int format); }; //namespace qdutils #endif diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h index 0a8a4734..636982ca 100644 --- a/sdm/include/core/layer_buffer.h +++ b/sdm/include/core/layer_buffer.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -266,6 +266,7 @@ struct LayerBuffer { //!< could be modified by both client and SDM. uint64_t buffer_id __attribute__((aligned(8))) = 0; //!< Specifies the buffer id. + uint32_t fb_id = 0; // DRM f/w registered framebuffer id }; // This enum represents buffer layout types. diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h index 657d4ac1..03b5eabc 100644 --- a/sdm/include/private/hw_info_types.h +++ b/sdm/include/private/hw_info_types.h @@ -483,6 +483,7 @@ struct HWDisplayAttributes : DisplayConfigVariableInfo { uint32_t v_back_porch = 0; //!< Vertical back porch of panel uint32_t v_pulse_width = 0; //!< Vertical pulse width of panel uint32_t h_total = 0; //!< Total width of panel (hActive + hFP + hBP + hPulseWidth) + uint32_t v_total = 0; //!< Total height of panel (vActive + vFP + vBP + vPulseWidth) std::bitset<32> s3d_config; //!< Stores the bit mask of S3D modes void Reset() { *this = HWDisplayAttributes(); } @@ -498,6 +499,7 @@ struct HWDisplayAttributes : DisplayConfigVariableInfo { (v_front_porch != display_attributes.v_front_porch) || (v_back_porch != display_attributes.v_back_porch) || (v_pulse_width != display_attributes.v_pulse_width) || + (h_total != display_attributes.h_total) || (is_yuv != display_attributes.is_yuv)); } diff --git a/sdm/include/utils/utils.h b/sdm/include/utils/utils.h index ed2c6aec..b1c55c41 100644 --- a/sdm/include/utils/utils.h +++ b/sdm/include/utils/utils.h @@ -36,6 +36,13 @@ float gcd(float a, float b); float lcm(float a, float b); void CloseFd(int *fd); +enum class DriverType { + FB = 0, + DRM, +}; + +DriverType GetDriverType(); + } // namespace sdm #endif // __UTILS_H__ diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk index 50f087d8..10d06aba 100644 --- a/sdm/libs/core/Android.mk +++ b/sdm/libs/core/Android.mk @@ -5,9 +5,17 @@ include $(LOCAL_PATH)/../../../common.mk LOCAL_MODULE := libsdmcore LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) $(common_header_export_path) -LOCAL_CFLAGS := -Wno-unused-parameter -DLOG_TAG=\"SDM\" $(common_flags) -LOCAL_HW_INTF_PATH := fb +LOCAL_CFLAGS := -Wno-unused-parameter -DLOG_TAG=\"SDM\" \ + $(common_flags) +LOCAL_HW_INTF_PATH_1 := fb LOCAL_SHARED_LIBRARIES := libdl libsdmutils + +ifneq ($(TARGET_IS_HEADLESS), true) + LOCAL_CFLAGS += -isystem external/libdrm + LOCAL_SHARED_LIBRARIES += libdrm libdrmutils + LOCAL_HW_INTF_PATH_2 := drm +endif + LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps) LOCAL_SRC_FILES := core_interface.cpp \ core_impl.cpp \ @@ -20,14 +28,23 @@ LOCAL_SRC_FILES := core_interface.cpp \ resource_default.cpp \ dump_impl.cpp \ color_manager.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_info.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_device.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_primary.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_hdmi.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_virtual.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_color_manager.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_scale.cpp \ - $(LOCAL_HW_INTF_PATH)/hw_events.cpp + hw_events_interface.cpp \ + hw_info_interface.cpp \ + hw_interface.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_info.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_device.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_primary.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_hdmi.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_virtual.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_color_manager.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_scale.cpp \ + $(LOCAL_HW_INTF_PATH_1)/hw_events.cpp + +ifneq ($(TARGET_IS_HEADLESS), true) + LOCAL_SRC_FILES += $(LOCAL_HW_INTF_PATH_2)/hw_info_drm.cpp \ + $(LOCAL_HW_INTF_PATH_2)/hw_device_drm.cpp \ + $(LOCAL_HW_INTF_PATH_2)/hw_events_drm.cpp +endif include $(BUILD_SHARED_LIBRARY) diff --git a/sdm/libs/core/Makefile.am b/sdm/libs/core/Makefile.am index 9041394a..2b45d8e3 100644 --- a/sdm/libs/core/Makefile.am +++ b/sdm/libs/core/Makefile.am @@ -11,6 +11,9 @@ c_sources = core_interface.cpp \ resource_default.cpp \ dump_impl.cpp \ color_manager.cpp \ + hw_interface.cpp \ + hw_info_interface.cpp \ + hw_events_interface.cpp \ fb/hw_info.cpp \ fb/hw_device.cpp \ fb/hw_primary.cpp \ @@ -41,4 +44,4 @@ libsdmcore_la_SOURCES = $(c_sources) libsdmcore_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\" libsdmcore_la_CPPFLAGS = $(AM_CPPFLAGS) libsdmcore_la_LIBADD = ../utils/libsdmutils.la -libsdmcore_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file +libsdmcore_la_LDFLAGS = -shared -avoid-version diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp index 4a31a0fb..d751ecb2 100644 --- a/sdm/libs/core/display_base.cpp +++ b/sdm/libs/core/display_base.cpp @@ -1102,6 +1102,7 @@ void DisplayBase::CommitLayerParams(LayerStack *layer_stack) { hw_layer.input_buffer.planes[0].stride = sdm_layer->input_buffer.planes[0].stride; hw_layer.input_buffer.size = sdm_layer->input_buffer.size; hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd; + hw_layer.input_buffer.fb_id = sdm_layer->input_buffer.fb_id; } return; diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp index 46d1a207..783cad94 100644 --- a/sdm/libs/core/display_hdmi.cpp +++ b/sdm/libs/core/display_hdmi.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -86,7 +86,7 @@ DisplayError DisplayHDMI::Init() { s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode> (kS3dFormatFramePacking, kS3DModeFP)); - error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_); + error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_); if (error != kErrorNone) { DisplayBase::Deinit(); HWInterface::Destroy(hw_intf_); diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h index 868b141f..6db23046 100644 --- a/sdm/libs/core/display_hdmi.h +++ b/sdm/libs/core/display_hdmi.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -30,6 +30,7 @@ #include "display_base.h" #include "dump_impl.h" +#include "hw_events_interface.h" namespace sdm { @@ -61,11 +62,10 @@ class DisplayHDMI : public DisplayBase, HWEventHandler { bool underscan_supported_ = false; HWScanSupport scan_support_; std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_; - std::vector<const char *> event_list_ = {"vsync_event", "idle_notify", "cec/rd_msg", - "thread_exit"}; + std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::IDLE_NOTIFY, HWEvent::EXIT, + HWEvent::CEC_READ_MESSAGE }; }; } // namespace sdm #endif // __DISPLAY_HDMI_H__ - diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp index 99aa3d52..3a1541e2 100644 --- a/sdm/libs/core/display_primary.cpp +++ b/sdm/libs/core/display_primary.cpp @@ -71,7 +71,7 @@ DisplayError DisplayPrimary::Init() { avr_prop_disabled_ = Debug::IsAVRDisabled(); - error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_); + error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_); if (error != kErrorNone) { DLOGE("Failed to create hardware events interface. Error = %d", error); DisplayBase::Deinit(); diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h index 74718997..70c938ed 100644 --- a/sdm/libs/core/display_primary.h +++ b/sdm/libs/core/display_primary.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -29,6 +29,7 @@ #include "display_base.h" #include "dump_impl.h" +#include "hw_events_interface.h" namespace sdm { @@ -62,8 +63,8 @@ class DisplayPrimary : public DisplayBase, HWEventHandler { bool NeedsAVREnable(); uint32_t idle_timeout_ms_ = 0; - std::vector<const char *> event_list_ = {"vsync_event", "show_blank_event", "idle_notify", - "msm_fb_thermal_level", "thread_exit"}; + std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::EXIT, HWEvent::IDLE_NOTIFY, + HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL }; bool avr_prop_disabled_ = false; bool switch_to_cmd_ = false; }; diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp new file mode 100644 index 00000000..3b7c3157 --- /dev/null +++ b/sdm/libs/core/drm/hw_device_drm.cpp @@ -0,0 +1,510 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define __STDC_FORMAT_MACROS + +#include <stdio.h> +#include <ctype.h> +#include <math.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/fb.h> +#include <utils/constants.h> +#include <utils/debug.h> +#include <utils/sys.h> +#include <drm_master.h> +#include <drm_res_mgr.h> + +#include <algorithm> +#include <string> +#include <utility> +#include <vector> + +#include "hw_device_drm.h" +#include "hw_info_interface.h" + +#define __CLASS__ "HWDeviceDRM" + +using std::string; +using std::to_string; +using std::fstream; +using drm_utils::DRMMaster; +using drm_utils::DRMResMgr; +using drm_utils::DRMLogger; + +namespace sdm { + +class DRMLoggerDAL : public DRMLogger { + public: +#define PRIV_LOG(suffix) { \ + char buf[1024]; \ + va_list list; \ + va_start(list, str); \ + vsnprintf(buf, sizeof(buf), str, list); \ + va_end(list); \ + DLOG##suffix("%s", buf); \ +} + void Error(const char *str, ...) { + PRIV_LOG(E); + } + void Info(const char *str, ...) { + PRIV_LOG(I); + } + void Debug(const char *str, ...) { + PRIV_LOG(D); + } +}; + +HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf) + : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler) { + DRMLogger::Set(new DRMLoggerDAL()); +} + +DisplayError HWDeviceDRM::Init() { + // Populate Panel Info (Used for Partial Update) + PopulateHWPanelInfo(); + // Populate HW Capabilities + hw_resource_ = HWResourceInfo(); + hw_info_intf_->GetHWResourceInfo(&hw_resource_); + + DRMResMgr *res_mgr = nullptr; + int ret = DRMResMgr::GetInstance(&res_mgr); + if (ret < 0) { + DLOGE("Failed to acquire DRMResMgr instance"); + return kErrorResources; + } + + // TODO(user): check if default mode enabled + drmModeModeInfo mode; + res_mgr->GetMode(&mode); + + uint32_t mm_width = 0; + uint32_t mm_height = 0; + res_mgr->GetDisplayDimInMM(&mm_width, &mm_height); + + display_attributes_.x_pixels = mode.hdisplay; + display_attributes_.y_pixels = mode.vdisplay; + display_attributes_.fps = mode.vrefresh; + display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps); + + /* + Active Front Sync Back + Region Porch Porch + <-----------------------><----------------><-------------><--------------> + <----- [hv]display -----> + <------------- [hv]sync_start ------------> + <--------------------- [hv]sync_end ---------------------> + <-------------------------------- [hv]total -----------------------------> + */ + + display_attributes_.v_front_porch = mode.vsync_start - mode.vdisplay; + display_attributes_.v_pulse_width = mode.vsync_end - mode.vsync_start; + display_attributes_.v_back_porch = mode.vtotal - mode.vsync_end; + display_attributes_.v_total = mode.vtotal; + + display_attributes_.h_total = mode.htotal; + uint32_t h_blanking = mode.htotal - mode.hdisplay; + display_attributes_.is_device_split = true; + display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0; + + display_attributes_.x_dpi = + (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width); + display_attributes_.y_dpi = + (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height); + + return kErrorNone; +} + +DisplayError HWDeviceDRM::Deinit() { + return kErrorNone; +} + +DisplayError HWDeviceDRM::GetActiveConfig(uint32_t *active_config) { + *active_config = 0; + return kErrorNone; +} + +DisplayError HWDeviceDRM::GetNumDisplayAttributes(uint32_t *count) { + *count = 1; + return kErrorNone; +} + +DisplayError HWDeviceDRM::GetDisplayAttributes(uint32_t index, + HWDisplayAttributes *display_attributes) { + *display_attributes = display_attributes_; + return kErrorNone; +} + +DisplayError HWDeviceDRM::GetHWPanelInfo(HWPanelInfo *panel_info) { + *panel_info = hw_panel_info_; + return kErrorNone; +} + +DisplayError HWDeviceDRM::SetDisplayAttributes(uint32_t index) { + return kErrorNone; +} + +DisplayError HWDeviceDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::GetConfigIndex(uint32_t mode, uint32_t *index) { + return kErrorNone; +} + +DisplayError HWDeviceDRM::PowerOn() { + DTRACE_SCOPED(); + return kErrorNone; +} + +DisplayError HWDeviceDRM::PowerOff() { + return kErrorNone; +} + +DisplayError HWDeviceDRM::Doze() { + return kErrorNone; +} + +DisplayError HWDeviceDRM::DozeSuspend() { + return kErrorNone; +} + +DisplayError HWDeviceDRM::Standby() { + return kErrorNone; +} + +DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) { + DTRACE_SCOPED(); + return kErrorNone; +} + +DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) { + DTRACE_SCOPED(); + + HWLayersInfo &hw_layer_info = hw_layers->info; + LayerStack *stack = hw_layer_info.stack; + + stack->retire_fence_fd = -1; + for (Layer &layer : hw_layer_info.hw_layers) { + layer.input_buffer.release_fence_fd = -1; + } + + DRMMaster *master = nullptr; + int ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + DLOGE("Failed to acquire DRMMaster instance"); + return kErrorResources; + } + + DRMResMgr *res_mgr = nullptr; + ret = DRMResMgr::GetInstance(&res_mgr); + if (ret < 0) { + DLOGE("Failed to acquire DRMResMgr instance"); + return kErrorResources; + } + + int dev_fd = -1; + master->GetHandle(&dev_fd); + + uint32_t connector_id = 0; + res_mgr->GetConnectorId(&connector_id); + + uint32_t crtc_id = 0; + res_mgr->GetCrtcId(&crtc_id); + + drmModeModeInfo mode; + res_mgr->GetMode(&mode); + + LayerBuffer &input_buffer = hw_layer_info.hw_layers.at(0).input_buffer; + ret = drmModeSetCrtc(dev_fd, crtc_id, input_buffer.fb_id, 0 /* x */, 0 /* y */, &connector_id, + 1 /* num_connectors */, &mode); + if (ret < 0) { + DLOGE("drmModeSetCrtc failed dev fd %d, fb_id %d, crtc id %d, connector id %d, %s", dev_fd, + input_buffer.fb_id, crtc_id, connector_id, strerror(errno)); + return kErrorHardware; + } + + return kErrorNone; +} + +DisplayError HWDeviceDRM::Flush() { + return kErrorNone; +} + +void HWDeviceDRM::PopulateHWPanelInfo() { + hw_panel_info_ = HWPanelInfo(); + GetHWPanelInfoByNode(0 /* Primary */, &hw_panel_info_); + DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d", + device_type_, hw_panel_info_.port, hw_panel_info_.mode, 0 /* primary */, + hw_panel_info_.is_primary_panel); + DLOGI("Partial Update = %d, Dynamic FPS = %d", + hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps); + DLOGI("Align: left = %d, width = %d, top = %d, height = %d", + hw_panel_info_.left_align, hw_panel_info_.width_align, + hw_panel_info_.top_align, hw_panel_info_.height_align); + DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d", + hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height, + hw_panel_info_.needs_roi_merge); + DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps); + DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split, + hw_panel_info_.split_info.right_split); +} + +void HWDeviceDRM::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) { + snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", + "Dual SHARP video mode dsi panel"); +} + +void HWDeviceDRM::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) { + panel_info->partial_update = 0; + panel_info->left_align = 0; + panel_info->width_align = 0; + panel_info->top_align = 0; + panel_info->height_align = 0; + panel_info->min_roi_width = 0; + panel_info->min_roi_height = 0; + panel_info->needs_roi_merge = 0; + panel_info->dynamic_fps = 0; + panel_info->min_fps = 60; + panel_info->max_fps = 60; + panel_info->is_primary_panel = 1; + panel_info->is_pluggable = 0; + + GetHWDisplayPortAndMode(device_node, panel_info); + GetSplitInfo(device_node, panel_info); + GetHWPanelNameByNode(device_node, panel_info); + GetHWPanelMaxBrightnessFromNode(panel_info); +} + +void HWDeviceDRM::GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info) { + DisplayPort *port = &panel_info->port; + HWDisplayMode *mode = &panel_info->mode; + + *port = kPortDefault; + *mode = kModeDefault; + + string line = "mipi dsi video panel"; + + if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) { + *port = kPortDSI; + *mode = kModeCommand; + } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) { + *port = kPortDSI; + *mode = kModeVideo; + } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) { + *port = kPortLVDS; + *mode = kModeVideo; + } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) { + *port = kPortEDP; + *mode = kModeVideo; + } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) { + *port = kPortDTV; + *mode = kModeVideo; + } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) { + *port = kPortWriteBack; + *mode = kModeCommand; + } + + return; +} + +void HWDeviceDRM::GetSplitInfo(int device_node, HWPanelInfo *panel_info) { + if (display_attributes_.is_device_split) { + panel_info->split_info.left_split = panel_info->split_info.right_split = + display_attributes_.x_pixels / 2; + } +} + +void HWDeviceDRM::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) { + char brightness[kMaxStringLength] = { 0 }; + char kMaxBrightnessNode[64] = { 0 }; + + snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s", + "/sys/class/leds/lcd-backlight/max_brightness"); + + panel_info->panel_max_brightness = 0; + int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY); + if (fd < 0) { + DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode, + strerror(errno)); + return; + } + + if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) { + panel_info->panel_max_brightness = atoi(brightness); + DLOGI("Max brightness level = %d", panel_info->panel_max_brightness); + } else { + DLOGW("Failed to read max brightness level. error = %s", strerror(errno)); + } + Sys::close_(fd); + + panel_info->panel_max_brightness = 255; +} + +bool HWDeviceDRM::EnableHotPlugDetection(int enable) { + return true; +} + +void HWDeviceDRM::ResetDisplayParams() { +} + +DisplayError HWDeviceDRM::SetCursorPosition(HWLayers *hw_layers, int x, int y) { + DTRACE_SCOPED(); + return kErrorNone; +} + +DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::SetPPFeatures(PPFeaturesConfig *feature_list) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::SetVSyncState(bool enable) { + return kErrorNone; +} + +void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) { +} + +DisplayError HWDeviceDRM::SetDisplayMode(const HWDisplayMode hw_display_mode) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::SetRefreshRate(uint32_t refresh_rate) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::SetPanelBrightness(int level) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::GetHWScanInfo(HWScanInfo *scan_info) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::GetVideoFormat(uint32_t config_index, uint32_t *video_format) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::GetMaxCEAFormat(uint32_t *max_cea_format) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::GetPanelBrightness(int *level) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::SetS3DMode(HWS3DMode s3d_mode) { + return kErrorNotSupported; +} + +DisplayError HWDeviceDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) { + return kErrorNone; +} + +DisplayError HWDeviceDRM::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) { + if (!hw_resource_.hw_dest_scalar_info.count) { + return kErrorNotSupported; + } + + if (mixer_attributes.width > display_attributes_.x_pixels || + mixer_attributes.height > display_attributes_.y_pixels) { + DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d", + mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels, + display_attributes_.y_pixels); + return kErrorNotSupported; + } + + uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width; + if (display_attributes_.is_device_split) { + max_input_width *= 2; + } + + if (mixer_attributes.width > max_input_width) { + DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width, + max_input_width); + return kErrorNotSupported; + } + + float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height); + float display_aspect_ratio = + FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels); + + if (display_aspect_ratio != mixer_aspect_ratio) { + DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width, + mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels); + return kErrorNotSupported; + } + + float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width); + float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height); + float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up; + if (scale_x > max_scale_up || scale_y > max_scale_up) { + DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \ + "max_scale_up %f", scale_x, scale_y, max_scale_up); + return kErrorNotSupported; + } + + float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width); + + mixer_attributes_ = mixer_attributes; + mixer_attributes_.split_left = mixer_attributes_.width; + if (display_attributes_.is_device_split) { + mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio); + } + + return kErrorNone; +} + +DisplayError HWDeviceDRM::GetMixerAttributes(HWMixerAttributes *mixer_attributes) { + if (!mixer_attributes) { + return kErrorParameters; + } + + mixer_attributes_.width = display_attributes_.x_pixels; + mixer_attributes_.height = display_attributes_.y_pixels; + mixer_attributes_.split_left = display_attributes_.is_device_split ? + hw_panel_info_.split_info.left_split : mixer_attributes_.width; + *mixer_attributes = mixer_attributes_; + + return kErrorNone; +} + +} // namespace sdm diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h new file mode 100644 index 00000000..d4b984d1 --- /dev/null +++ b/sdm/libs/core/drm/hw_device_drm.h @@ -0,0 +1,126 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __HW_DEVICE_DRM_H__ +#define __HW_DEVICE_DRM_H__ + +#include <errno.h> +#include <pthread.h> +#include <xf86drmMode.h> +#include <vector> + +#include "hw_interface.h" + +#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \ + type, errno, strerror(errno)) + +namespace sdm { +class HWInfoInterface; + +class HWDeviceDRM : public HWInterface { + public: + explicit HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf); + virtual ~HWDeviceDRM() {} + virtual DisplayError Init(); + virtual DisplayError Deinit(); + + protected: + // From HWInterface + virtual DisplayError GetActiveConfig(uint32_t *active_config); + virtual DisplayError GetNumDisplayAttributes(uint32_t *count); + virtual DisplayError GetDisplayAttributes(uint32_t index, + HWDisplayAttributes *display_attributes); + virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info); + virtual DisplayError SetDisplayAttributes(uint32_t index); + virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes); + virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index); + virtual DisplayError PowerOn(); + virtual DisplayError PowerOff(); + virtual DisplayError Doze(); + virtual DisplayError DozeSuspend(); + virtual DisplayError Standby(); + virtual DisplayError Validate(HWLayers *hw_layers); + virtual DisplayError Commit(HWLayers *hw_layers); + virtual DisplayError Flush(); + virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers); + virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list); + virtual DisplayError SetVSyncState(bool enable); + virtual void SetIdleTimeoutMs(uint32_t timeout_ms); + virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode); + virtual DisplayError SetRefreshRate(uint32_t refresh_rate); + virtual DisplayError SetPanelBrightness(int level); + virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info); + virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format); + virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format); + virtual DisplayError SetCursorPosition(HWLayers *hw_layers, int x, int y); + virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level); + virtual DisplayError GetPanelBrightness(int *level); + virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; } + virtual DisplayError SetS3DMode(HWS3DMode s3d_mode); + virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info); + virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes); + virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes); + + enum { + kHWEventVSync, + kHWEventBlank, + }; + + static const int kMaxStringLength = 1024; + static const int kNumPhysicalDisplays = 2; + + DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target); + DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format, + uint32_t width, uint32_t *target); + void PopulateHWPanelInfo(); + void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info); + void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info); + void GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info); + void GetSplitInfo(int device_node, HWPanelInfo *panel_info); + void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info); + int ParseLine(const char *input, char *tokens[], const uint32_t max_token, uint32_t *count); + int ParseLine(const char *input, const char *delim, char *tokens[], + const uint32_t max_token, uint32_t *count); + void ResetDisplayParams(); + bool EnableHotPlugDetection(int enable); + + HWResourceInfo hw_resource_; + HWPanelInfo hw_panel_info_; + HWInfoInterface *hw_info_intf_; + BufferSyncHandler *buffer_sync_handler_; + HWDeviceType device_type_; + const char *device_name_; + bool synchronous_commit_ = false; + HWDisplayAttributes display_attributes_ = {}; + HWMixerAttributes mixer_attributes_ = {}; +}; + +} // namespace sdm + +#endif // __HW_DEVICE_DRM_H__ diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp new file mode 100644 index 00000000..81384e41 --- /dev/null +++ b/sdm/libs/core/drm/hw_events_drm.cpp @@ -0,0 +1,298 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <drm_master.h> +#include <errno.h> +#include <fcntl.h> +#include <math.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/prctl.h> +#include <sys/resource.h> +#include <sys/types.h> +#include <utils/debug.h> +#include <utils/sys.h> +#include <xf86drm.h> + +#include <algorithm> +#include <map> +#include <utility> +#include <vector> + +#include "hw_events_drm.h" + +#define __CLASS__ "HWEventsDRM" + +namespace sdm { + +using drm_utils::DRMMaster; + +DisplayError HWEventsDRM::InitializePollFd() { + for (uint32_t i = 0; i < event_data_list_.size(); i++) { + char data[kMaxStringLength]{}; + HWEventData &event_data = event_data_list_[i]; + poll_fds_[i].fd = -1; + + switch (event_data.event_type) { + case HWEvent::VSYNC: { + poll_fds_[i].events = POLLIN | POLLPRI | POLLERR; + DRMMaster *master = nullptr; + int ret = DRMMaster::GetInstance(&master); + if (ret < 0) { + DLOGE("Failed to acquire DRMMaster instance"); + return kErrorNotSupported; + } + master->GetHandle(&poll_fds_[i].fd); + vsync_index_ = i; + } break; + case HWEvent::EXIT: { + // Create an eventfd to be used to unblock the poll system call when + // a thread is exiting. + poll_fds_[i].fd = Sys::eventfd_(0, 0); + poll_fds_[i].events |= POLLIN; + // Clear any existing data + Sys::pread_(poll_fds_[i].fd, data, kMaxStringLength, 0); + } break; + case HWEvent::IDLE_NOTIFY: + case HWEvent::CEC_READ_MESSAGE: + case HWEvent::SHOW_BLANK_EVENT: + case HWEvent::THERMAL_LEVEL: + break; + } + } + + return kErrorNone; +} + +DisplayError HWEventsDRM::SetEventParser() { + DisplayError error = kErrorNone; + + for (auto &event_data : event_data_list_) { + switch (event_data.event_type) { + case HWEvent::VSYNC: + event_data.event_parser = &HWEventsDRM::HandleVSync; + break; + case HWEvent::IDLE_NOTIFY: + event_data.event_parser = &HWEventsDRM::HandleIdleTimeout; + break; + case HWEvent::CEC_READ_MESSAGE: + event_data.event_parser = &HWEventsDRM::HandleCECMessage; + break; + case HWEvent::EXIT: + event_data.event_parser = &HWEventsDRM::HandleThreadExit; + break; + case HWEvent::SHOW_BLANK_EVENT: + event_data.event_parser = &HWEventsDRM::HandleBlank; + break; + case HWEvent::THERMAL_LEVEL: + event_data.event_parser = &HWEventsDRM::HandleThermal; + break; + default: + error = kErrorParameters; + break; + } + } + + return error; +} + +void HWEventsDRM::PopulateHWEventData(const vector<HWEvent> &event_list) { + for (auto &event : event_list) { + HWEventData event_data; + event_data.event_type = event; + event_data_list_.push_back(std::move(event_data)); + } + + SetEventParser(); + InitializePollFd(); +} + +DisplayError HWEventsDRM::Init(int display_type, HWEventHandler *event_handler, + const vector<HWEvent> &event_list) { + if (!event_handler) + return kErrorParameters; + + event_handler_ = event_handler; + poll_fds_.resize(event_list.size()); + event_thread_name_ += " - " + std::to_string(display_type); + + PopulateHWEventData(event_list); + + if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) { + DLOGE("Failed to start %s, error = %s", event_thread_name_.c_str()); + return kErrorResources; + } + + return kErrorNone; +} + +DisplayError HWEventsDRM::Deinit() { + exit_threads_ = true; + Sys::pthread_cancel_(event_thread_); + + for (uint32_t i = 0; i < event_data_list_.size(); i++) { + if (event_data_list_[i].event_type == HWEvent::EXIT) { + uint64_t exit_value = 1; + ssize_t write_size = Sys::write_(poll_fds_[i].fd, &exit_value, sizeof(uint64_t)); + if (write_size != sizeof(uint64_t)) { + DLOGW("Error triggering exit fd (%d). write size = %d, error = %s", poll_fds_[i].fd, + write_size, strerror(errno)); + } + } + } + + pthread_join(event_thread_, NULL); + CloseFds(); + + return kErrorNone; +} + +DisplayError HWEventsDRM::CloseFds() { + for (uint32_t i = 0; i < event_data_list_.size(); i++) { + switch (event_data_list_[i].event_type) { + case HWEvent::VSYNC: + poll_fds_[i].fd = -1; + break; + case HWEvent::EXIT: + Sys::close_(poll_fds_[i].fd); + poll_fds_[i].fd = -1; + break; + case HWEvent::IDLE_NOTIFY: + case HWEvent::CEC_READ_MESSAGE: + case HWEvent::SHOW_BLANK_EVENT: + case HWEvent::THERMAL_LEVEL: + break; + default: + return kErrorNotSupported; + } + } + + return kErrorNone; +} + +void *HWEventsDRM::DisplayEventThread(void *context) { + if (context) { + return reinterpret_cast<HWEventsDRM *>(context)->DisplayEventHandler(); + } + + return NULL; +} + +void *HWEventsDRM::DisplayEventHandler() { + char data[kMaxStringLength]{}; + + prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0); + setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent); + + while (!exit_threads_) { + if (RegisterVSync() != kErrorNone) { + pthread_exit(0); + return nullptr; + } + + int error = Sys::poll_(poll_fds_.data(), UINT32(poll_fds_.size()), -1); + if (error <= 0) { + DLOGW("poll failed. error = %s", strerror(errno)); + continue; + } + + for (uint32_t i = 0; i < event_data_list_.size(); i++) { + pollfd &poll_fd = poll_fds_[i]; + switch (event_data_list_[i].event_type) { + case HWEvent::VSYNC: + (this->*(event_data_list_[i]).event_parser)(nullptr); + break; + case HWEvent::EXIT: + if ((poll_fd.revents & POLLIN) && + (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) { + (this->*(event_data_list_[i]).event_parser)(data); + } + break; + case HWEvent::IDLE_NOTIFY: + case HWEvent::CEC_READ_MESSAGE: + case HWEvent::SHOW_BLANK_EVENT: + case HWEvent::THERMAL_LEVEL: + if (poll_fd.fd >= 0 && (poll_fd.revents & POLLPRI) && + (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) { + (this->*(event_data_list_[i]).event_parser)(data); + } + break; + } + } + } + + pthread_exit(0); + + return nullptr; +} + +DisplayError HWEventsDRM::RegisterVSync() { + drmVBlank vblank{}; + vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT); + vblank.request.sequence = 1; + // DRM hack to pass in context to unused field signal. Driver will write this to the node being + // polled on, and will be read as part of drm event handling and sent to handler + vblank.request.signal = reinterpret_cast<unsigned long>(this); // NOLINT + int error = drmWaitVBlank(poll_fds_[vsync_index_].fd, &vblank); + if (error < 0) { + DLOGE("drmWaitVBlank failed with err %d", errno); + return kErrorResources; + } + + return kErrorNone; +} + +void HWEventsDRM::HandleVSync(char *data) { + if (poll_fds_[vsync_index_].revents & (POLLIN | POLLPRI)) { + drmEventContext event = {}; + event.version = DRM_EVENT_CONTEXT_VERSION; + event.vblank_handler = &HWEventsDRM::VSyncHandlerCallback; + int error = drmHandleEvent(poll_fds_[vsync_index_].fd, &event); + if (error != 0) { + DLOGE("drmHandleEvent failed: %i", error); + } + } +} + +void HWEventsDRM::VSyncHandlerCallback(int fd, unsigned int sequence, unsigned int tv_sec, + unsigned int tv_usec, void *data) { + int64_t timestamp = (int64_t)(tv_sec)*1000000000 + (int64_t)(tv_usec)*1000; + reinterpret_cast<HWEventsDRM *>(data)->event_handler_->VSync(timestamp); +} + +void HWEventsDRM::HandleIdleTimeout(char *data) { + event_handler_->IdleTimeout(); +} + +void HWEventsDRM::HandleCECMessage(char *data) { + event_handler_->CECMessage(data); +} + +} // namespace sdm diff --git a/sdm/libs/core/drm/hw_events_drm.h b/sdm/libs/core/drm/hw_events_drm.h new file mode 100644 index 00000000..9f8dc38a --- /dev/null +++ b/sdm/libs/core/drm/hw_events_drm.h @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __HW_EVENTS_DRM_H__ +#define __HW_EVENTS_DRM_H__ + +#include <sys/poll.h> +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "hw_events_interface.h" +#include "hw_interface.h" + +namespace sdm { + +using std::vector; + +class HWEventsDRM : public HWEventsInterface { + public: + virtual DisplayError Init(int display_type, HWEventHandler *event_handler, + const vector<HWEvent> &event_list); + virtual DisplayError Deinit(); + + private: + static const int kMaxStringLength = 1024; + + typedef void (HWEventsDRM::*EventParser)(char *); + + struct HWEventData { + HWEvent event_type {}; + EventParser event_parser {}; + }; + + static void *DisplayEventThread(void *context); + static void VSyncHandlerCallback(int fd, unsigned int sequence, unsigned int tv_sec, + unsigned int tv_usec, void *data); + + void *DisplayEventHandler(); + void HandleVSync(char *data); + void HandleIdleTimeout(char *data); + void HandleCECMessage(char *data); + void HandleThreadExit(char *data) {} + void HandleThermal(char *data) {} + void HandleBlank(char *data) {} + void PopulateHWEventData(const vector<HWEvent> &event_list); + DisplayError SetEventParser(); + DisplayError InitializePollFd(); + DisplayError CloseFds(); + DisplayError RegisterVSync(); + + HWEventHandler *event_handler_{}; + vector<HWEventData> event_data_list_{}; + vector<pollfd> poll_fds_{}; + pthread_t event_thread_{}; + std::string event_thread_name_ = "SDM_EventThread"; + bool exit_threads_ = false; + uint32_t vsync_index_ = 0; +}; + +} // namespace sdm + +#endif // __HW_EVENTS_DRM_H__ diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp new file mode 100644 index 00000000..78b598ed --- /dev/null +++ b/sdm/libs/core/drm/hw_info_drm.cpp @@ -0,0 +1,257 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <utils/constants.h> +#include <utils/debug.h> +#include <utils/sys.h> +#include <dlfcn.h> +#include <drm/drm_fourcc.h> + +#include <algorithm> +#include <iostream> +#include <fstream> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "hw_info_drm.h" + +#define __CLASS__ "HWInfoDRM" + +using std::vector; +using std::map; +using std::string; +using std::fstream; +using std::to_string; + +namespace sdm { + +int HWInfoDRM::ParseString(const char *input, char *tokens[], const uint32_t max_token, + const char *delim, uint32_t *count) { + char *tmp_token = NULL; + char *temp_ptr; + uint32_t index = 0; + if (!input) { + return -1; + } + tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr); + while (tmp_token && index < max_token) { + tokens[index++] = tmp_token; + tmp_token = strtok_r(NULL, delim, &temp_ptr); + } + *count = index; + + return 0; +} + +DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) { + HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info; + for (int index = 0; index < kBwModeMax; index++) { + bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low); + bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw; + } + + return kErrorNone; +} + +DisplayError HWInfoDRM::GetHWResourceInfo(HWResourceInfo *hw_resource) { + InitSupportedFormatMap(hw_resource); + hw_resource->hw_version = kHWMdssVersion5; + hw_resource->hw_revision = 268894210; // HW Rev, v1/v2 + hw_resource->num_blending_stages = 7; + hw_resource->max_scale_down = 4; + hw_resource->max_scale_up = 20; + hw_resource->max_bandwidth_low = 9600000; + hw_resource->max_bandwidth_high = 9600000; + hw_resource->max_mixer_width = 2560; + hw_resource->max_pipe_width = 2560; + hw_resource->max_cursor_size = 128; + hw_resource->max_pipe_bw = 4500000; + hw_resource->max_sde_clk = 412500000; + hw_resource->clk_fudge_factor = FLOAT(105) / FLOAT(100); + hw_resource->macrotile_nv12_factor = 8; + hw_resource->macrotile_factor = 4; + hw_resource->linear_factor = 1; + hw_resource->scale_factor = 1; + hw_resource->extra_fudge_factor = 2; + hw_resource->amortizable_threshold = 0; + hw_resource->system_overhead_lines = 0; + hw_resource->writeback_index = 2; + hw_resource->hw_dest_scalar_info.count = 0; + hw_resource->hw_dest_scalar_info.max_scale_up = 0; + hw_resource->hw_dest_scalar_info.max_input_width = 0; + hw_resource->hw_dest_scalar_info.max_output_width = 0; + hw_resource->has_bwc = false; + hw_resource->has_ubwc = true; + hw_resource->has_decimation = true; + hw_resource->has_macrotile = true; + hw_resource->is_src_split = true; + hw_resource->has_non_scalar_rgb = false; + hw_resource->perf_calc = false; + hw_resource->has_dyn_bw_support = false; + hw_resource->separate_rotator = true; + hw_resource->has_qseed3 = false; + hw_resource->has_concurrent_writeback = false; + hw_resource->num_vig_pipe = 0; + hw_resource->num_dma_pipe = 0; + hw_resource->num_cursor_pipe = 0; + uint32_t pipe_count = 2; + for (uint32_t i = 0; i < pipe_count; i++) { + HWPipeCaps pipe_caps; + pipe_caps.type = kPipeTypeUnused; + pipe_caps.type = kPipeTypeRGB; + hw_resource->num_rgb_pipe++; + pipe_caps.id = UINT32(0x8 << i); + pipe_caps.max_rects = 1; + hw_resource->hw_pipes.push_back(pipe_caps); + } + + // Disable destination scalar count to 0 if extension library is not present + DynLib extension_lib; + if (!extension_lib.Open("libsdmextension.so")) { + hw_resource->hw_dest_scalar_info.count = 0; + } + + DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d", + hw_resource->hw_version, hw_resource->hw_revision, hw_resource->num_rgb_pipe, + hw_resource->num_vig_pipe, hw_resource->num_dma_pipe, hw_resource->num_cursor_pipe); + DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource->max_scale_up, + hw_resource->max_scale_down, hw_resource->num_blending_stages); + DLOGI("SourceSplit = %d QSEED3 = %d", hw_resource->is_src_split, hw_resource->has_qseed3); + DLOGI("BWC = %d, UBWC = %d, Decimation = %d, Tile Format = %d Concurrent Writeback = %d", + hw_resource->has_bwc, hw_resource->has_ubwc, hw_resource->has_decimation, + hw_resource->has_macrotile, hw_resource->has_concurrent_writeback); + DLOGI("MaxLowBw = %" PRIu64 " , MaxHighBw = % " PRIu64 "", hw_resource->max_bandwidth_low, + hw_resource->max_bandwidth_high); + DLOGI("MaxPipeBw = %" PRIu64 " KBps, MaxSDEClock = % " PRIu64 " Hz, ClockFudgeFactor = %f", + hw_resource->max_pipe_bw, hw_resource->max_sde_clk, hw_resource->clk_fudge_factor); + DLOGI("Prefill factors: Tiled_NV12 = %d, Tiled = %d, Linear = %d, Scale = %d, Fudge_factor = %d", + hw_resource->macrotile_nv12_factor, hw_resource->macrotile_factor, + hw_resource->linear_factor, hw_resource->scale_factor, hw_resource->extra_fudge_factor); + + if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) { + GetHWRotatorInfo(hw_resource); + } + + // If the driver doesn't spell out the wb index, assume it to be the number of rotators, + // based on legacy implementation. + if (hw_resource->writeback_index == kHWBlockMax) { + hw_resource->writeback_index = hw_resource->hw_rot_info.num_rotator; + } + + if (hw_resource->has_dyn_bw_support) { + DisplayError ret = GetDynamicBWLimits(hw_resource); + if (ret != kErrorNone) { + DLOGE("Failed to read dynamic band width info"); + return ret; + } + + DLOGI("Has Support for multiple bw limits shown below"); + for (int index = 0; index < kBwModeMax; index++) { + DLOGI("Mode-index=%d total_bw_limit=%d and pipe_bw_limit=%d", + index, hw_resource->dyn_bw_info.total_bw_limit[index], + hw_resource->dyn_bw_info.pipe_bw_limit[index]); + } + } + + return kErrorNone; +} + +DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) { + const uint32_t kMaxV4L2Nodes = 64; + bool found = false; + + for (uint32_t i = 0; (i < kMaxV4L2Nodes) && (false == found); i++) { + string path = "/sys/class/video4linux/video" + to_string(i) + "/name"; + Sys::fstream fs(path, fstream::in); + if (!fs.is_open()) { + continue; + } + + string line; + if (Sys::getline_(fs, line) && + (!strncmp(line.c_str(), "sde_rotator", strlen("sde_rotator")))) { + hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i)); + hw_resource->hw_rot_info.num_rotator++; + hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2; + hw_resource->hw_rot_info.has_downscale = true; + // We support only 1 rotator + found = true; + } + } + + DLOGI("V4L2 Rotator: Count = %d, Downscale = %d", hw_resource->hw_rot_info.num_rotator, + hw_resource->hw_rot_info.has_downscale); + + return kErrorNone; +} + +LayerBufferFormat HWInfoDRM::GetSDMFormat(uint32_t drm_format, uint32_t drm_format_modifier) { + switch (drm_format) { + case DRM_FORMAT_RGBA8888: return kFormatRGBA8888; + default: return kFormatInvalid; + } +} + +void HWInfoDRM::InitSupportedFormatMap(HWResourceInfo *hw_resource) { + hw_resource->supported_formats_map.clear(); + + for (int sub_blk_type = INT(kHWVIGPipe); sub_blk_type < INT(kHWSubBlockMax); sub_blk_type++) { + PopulateSupportedFormatMap((HWSubBlockType)sub_blk_type, hw_resource); + } +} + +void HWInfoDRM::PopulateSupportedFormatMap(HWSubBlockType sub_blk_type, + HWResourceInfo *hw_resource) { + vector <LayerBufferFormat> supported_sdm_formats; + LayerBufferFormat sdm_format = kFormatRGBA8888; // GetSDMFormat(INT(mdp_format)); + if (sdm_format != kFormatInvalid) { + supported_sdm_formats.push_back(sdm_format); + } + + hw_resource->supported_formats_map.erase(sub_blk_type); + hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats)); +} + +DisplayError HWInfoDRM::GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info) { + hw_disp_info->type = kPrimary; + hw_disp_info->is_connected = true; + + return kErrorNone; +} + +} // namespace sdm diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h new file mode 100644 index 00000000..51560935 --- /dev/null +++ b/sdm/libs/core/drm/hw_info_drm.h @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __HW_INFO_DRM_H__ +#define __HW_INFO_DRM_H__ + +#include <core/sdm_types.h> +#include <core/core_interface.h> +#include <private/hw_info_types.h> +#include <bitset> + +#include "hw_info_interface.h" + +namespace sdm { + +class HWInfoDRM: public HWInfoInterface { + public: + virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource); + virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info); + + private: + virtual DisplayError GetHWRotatorInfo(HWResourceInfo *hw_resource); + + // TODO(user): Read Mdss version from the driver + static const int kHWMdssVersion5 = 500; // MDSS_V5 + static const int kMaxStringLength = 1024; + // MDP Capabilities are replicated across all frame buffer devices. + // However, we rely on reading the capabalities from fbO since this + // is guaranteed to be available. + static const int kHWCapabilitiesNode = 0; + + static int ParseString(const char *input, char *tokens[], const uint32_t max_token, + const char *delim, uint32_t *count); + DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource); + LayerBufferFormat GetSDMFormat(uint32_t drm_format, uint32_t drm_format_modifier); + void InitSupportedFormatMap(HWResourceInfo *hw_resource); + void PopulateSupportedFormatMap(HWSubBlockType sub_blk_type, HWResourceInfo *hw_resource); +}; + +} // namespace sdm + +#endif // __HW_INFO_DRM_H__ diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp index 7d97d528..10ff6fbd 100644 --- a/sdm/libs/core/fb/hw_device.cpp +++ b/sdm/libs/core/fb/hw_device.cpp @@ -61,46 +61,6 @@ using std::fstream; namespace sdm { -DisplayError HWInterface::Create(DisplayType type, HWInfoInterface *hw_info_intf, - BufferSyncHandler *buffer_sync_handler, - HWInterface **intf) { - DisplayError error = kErrorNone; - HWDevice *hw = nullptr; - - switch (type) { - case kPrimary: - hw = new HWPrimary(buffer_sync_handler, hw_info_intf); - break; - case kHDMI: - hw = new HWHDMI(buffer_sync_handler, hw_info_intf); - break; - case kVirtual: - hw = new HWVirtual(buffer_sync_handler, hw_info_intf); - break; - default: - DLOGE("Undefined display type"); - return kErrorUndefined; - } - - error = hw->Init(); - if (error != kErrorNone) { - delete hw; - DLOGE("Init on HW Intf type %d failed", type); - return error; - } - *intf = hw; - - return error; -} - -DisplayError HWInterface::Destroy(HWInterface *intf) { - HWDevice *hw = static_cast<HWDevice *>(intf); - hw->Deinit(); - delete hw; - - return kErrorNone; -} - HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler) : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"), buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) { diff --git a/sdm/libs/core/fb/hw_events.cpp b/sdm/libs/core/fb/hw_events.cpp index 4015796f..ea8034ff 100644 --- a/sdm/libs/core/fb/hw_events.cpp +++ b/sdm/libs/core/fb/hw_events.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -49,55 +49,28 @@ namespace sdm { -DisplayError HWEventsInterface::Create(int fb_num, HWEventHandler *event_handler, - std::vector<const char *> *event_list, - HWEventsInterface **intf) { - DisplayError error = kErrorNone; - HWEvents *hw_events = NULL; - - hw_events = new HWEvents(); - error = hw_events->Init(fb_num, event_handler, event_list); - if (error != kErrorNone) { - delete hw_events; - } else { - *intf = hw_events; - } - - return error; -} - -DisplayError HWEventsInterface::Destroy(HWEventsInterface *intf) { - HWEvents *hw_events = static_cast<HWEvents *>(intf); - - if (hw_events) { - hw_events->Deinit(); - delete hw_events; - } - - return kErrorNone; -} - pollfd HWEvents::InitializePollFd(HWEventData *event_data) { char node_path[kMaxStringLength] = {0}; char data[kMaxStringLength] = {0}; pollfd poll_fd = {0}; poll_fd.fd = -1; - if (!strncmp(event_data->event_name, "thread_exit", strlen("thread_exit"))) { + if (event_data->event_type == HWEvent::EXIT) { // Create an eventfd to be used to unblock the poll system call when // a thread is exiting. poll_fd.fd = Sys::eventfd_(0, 0); poll_fd.events |= POLLIN; exit_fd_ = poll_fd.fd; } else { - snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_num_, event_data->event_name); + snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_num_, + map_event_to_node_[event_data->event_type]); poll_fd.fd = Sys::open_(node_path, O_RDONLY); poll_fd.events |= POLLPRI | POLLERR; } if (poll_fd.fd < 0) { - DLOGW("open failed for display=%d event=%s, error=%s", fb_num_, event_data->event_name, - strerror(errno)); + DLOGW("open failed for display=%d event=%s, error=%s", fb_num_, + map_event_to_node_[event_data->event_type], strerror(errno)); return poll_fd; } @@ -107,49 +80,58 @@ pollfd HWEvents::InitializePollFd(HWEventData *event_data) { return poll_fd; } -DisplayError HWEvents::SetEventParser(const char *event_name, HWEventData *event_data) { +DisplayError HWEvents::SetEventParser(HWEvent event_type, HWEventData *event_data) { DisplayError error = kErrorNone; - - if (!strncmp(event_name, "vsync_event", strlen("vsync_event"))) { - event_data->event_parser = &HWEvents::HandleVSync; - } else if (!strncmp(event_name, "show_blank_event", strlen("show_blank_event"))) { - event_data->event_parser = &HWEvents::HandleBlank; - } else if (!strncmp(event_name, "idle_notify", strlen("idle_notify"))) { - event_data->event_parser = &HWEvents::HandleIdleTimeout; - } else if (!strncmp(event_name, "msm_fb_thermal_level", strlen("msm_fb_thermal_level"))) { - event_data->event_parser = &HWEvents::HandleThermal; - } else if (!strncmp(event_name, "cec/rd_msg", strlen("cec/rd_msg"))) { - event_data->event_parser = &HWEvents::HandleCECMessage; - } else if (!strncmp(event_name, "thread_exit", strlen("thread_exit"))) { - event_data->event_parser = &HWEvents::HandleThreadExit; - } else { - error = kErrorParameters; + switch (event_type) { + case HWEvent::VSYNC: + event_data->event_parser = &HWEvents::HandleVSync; + break; + case HWEvent::IDLE_NOTIFY: + event_data->event_parser = &HWEvents::HandleIdleTimeout; + break; + case HWEvent::CEC_READ_MESSAGE: + event_data->event_parser = &HWEvents::HandleCECMessage; + break; + case HWEvent::EXIT: + event_data->event_parser = &HWEvents::HandleThreadExit; + break; + case HWEvent::SHOW_BLANK_EVENT: + event_data->event_parser = &HWEvents::HandleBlank; + break; + case HWEvent::THERMAL_LEVEL: + event_data->event_parser = &HWEvents::HandleThermal; + break; + default: + error = kErrorParameters; + break; } return error; } void HWEvents::PopulateHWEventData() { - for (uint32_t i = 0; i < event_list_->size(); i++) { - const char *event_name = event_list_->at(i); + for (uint32_t i = 0; i < event_list_.size(); i++) { HWEventData event_data; - event_data.event_name = event_name; - SetEventParser(event_name, &event_data); + event_data.event_type = event_list_[i]; + SetEventParser(event_list_[i], &event_data); poll_fds_[i] = InitializePollFd(&event_data); event_data_list_.push_back(event_data); } } DisplayError HWEvents::Init(int fb_num, HWEventHandler *event_handler, - vector<const char *> *event_list) { + const vector<HWEvent> &event_list) { if (!event_handler) return kErrorParameters; event_handler_ = event_handler; fb_num_ = fb_num; event_list_ = event_list; - poll_fds_.resize(event_list_->size()); + poll_fds_.resize(event_list_.size()); event_thread_name_ += " - " + std::to_string(fb_num_); + map_event_to_node_ = {{HWEvent::VSYNC, "vsync_event"}, {HWEvent::EXIT, "thread_exit"}, + {HWEvent::IDLE_NOTIFY, "idle_notify"}, {HWEvent::SHOW_BLANK_EVENT, "show_blank_event"}, + {HWEvent::CEC_READ_MESSAGE, "cec/rd_msg"}, {HWEvent::THERMAL_LEVEL, "msm_fb_thermal_level"}}; PopulateHWEventData(); @@ -173,7 +155,7 @@ DisplayError HWEvents::Deinit() { pthread_join(event_thread_, NULL); - for (uint32_t i = 0; i < event_list_->size(); i++) { + for (uint32_t i = 0; i < event_list_.size(); i++) { Sys::close_(poll_fds_[i].fd); poll_fds_[i].fd = -1; } @@ -196,17 +178,17 @@ void* HWEvents::DisplayEventHandler() { setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent); while (!exit_threads_) { - int error = Sys::poll_(poll_fds_.data(), UINT32(event_list_->size()), -1); + int error = Sys::poll_(poll_fds_.data(), UINT32(event_list_.size()), -1); if (error <= 0) { DLOGW("poll failed. error = %s", strerror(errno)); continue; } - for (uint32_t event = 0; event < event_list_->size(); event++) { + for (uint32_t event = 0; event < event_list_.size(); event++) { pollfd &poll_fd = poll_fds_[event]; - if (!strncmp(event_list_->at(event), "thread_exit", strlen("thread_exit"))) { + if (event_list_.at(event) == HWEvent::EXIT) { if ((poll_fd.revents & POLLIN) && (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) { (this->*(event_data_list_[event]).event_parser)(data); } @@ -253,4 +235,3 @@ void HWEvents::HandleCECMessage(char *data) { } } // namespace sdm - diff --git a/sdm/libs/core/fb/hw_events.h b/sdm/libs/core/fb/hw_events.h index bcc5ef69..e0249244 100644 --- a/sdm/libs/core/fb/hw_events.h +++ b/sdm/libs/core/fb/hw_events.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -37,12 +37,13 @@ namespace sdm { using std::vector; +using std::map; class HWEvents : public HWEventsInterface { public: - DisplayError Init(int fb_num, HWEventHandler *event_handler, - vector<const char *> *event_list); - DisplayError Deinit(); + virtual DisplayError Init(int fb_num, HWEventHandler *event_handler, + const vector<HWEvent> &event_list); + virtual DisplayError Deinit(); private: static const int kMaxStringLength = 1024; @@ -50,8 +51,8 @@ class HWEvents : public HWEventsInterface { typedef void (HWEvents::*EventParser)(char *); struct HWEventData { - const char* event_name = NULL; - EventParser event_parser = NULL; + HWEvent event_type {}; + EventParser event_parser {}; }; static void* DisplayEventThread(void *context); @@ -63,14 +64,15 @@ class HWEvents : public HWEventsInterface { void HandleCECMessage(char *data); void HandleThreadExit(char *data) { } void PopulateHWEventData(); - DisplayError SetEventParser(const char *event_name, HWEventData *event_data); + DisplayError SetEventParser(HWEvent event_type, HWEventData *event_data); pollfd InitializePollFd(HWEventData *event_data); - HWEventHandler *event_handler_ = NULL; - vector<const char *> *event_list_ = NULL; + HWEventHandler *event_handler_ = {}; + vector<HWEvent> event_list_ = {}; vector<HWEventData> event_data_list_ = {}; - vector<pollfd> poll_fds_; - pthread_t event_thread_; + vector<pollfd> poll_fds_ = {}; + map<HWEvent, const char *> map_event_to_node_ = {}; + pthread_t event_thread_ = {}; std::string event_thread_name_ = "SDM_EventThread"; bool exit_threads_ = false; const char* fb_path_ = "/sys/devices/virtual/graphics/fb"; diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp index 29316380..d898cd22 100644 --- a/sdm/libs/core/fb/hw_info.cpp +++ b/sdm/libs/core/fb/hw_info.cpp @@ -86,27 +86,6 @@ int HWInfo::ParseString(const char *input, char *tokens[], const uint32_t max_to return 0; } -DisplayError HWInfoInterface::Create(HWInfoInterface **intf) { - DisplayError error = kErrorNone; - HWInfo *hw_info = NULL; - - hw_info = new HWInfo(); - if (!hw_info) { - error = kErrorMemory; - } else { - *intf = hw_info; - } - - return error; -} - -DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) { - HWInfo *hw_info = static_cast<HWInfo *>(intf); - delete hw_info; - - return kErrorNone; -} - DisplayError HWInfo::GetDynamicBWLimits(HWResourceInfo *hw_resource) { Sys::fstream fs(kBWModeBitmap, fstream::in); if (!fs.is_open()) { diff --git a/sdm/libs/core/hw_events_interface.cpp b/sdm/libs/core/hw_events_interface.cpp new file mode 100644 index 00000000..ed62b86b --- /dev/null +++ b/sdm/libs/core/hw_events_interface.cpp @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <utils/utils.h> +#include <vector> + +#include "hw_events_interface.h" +#include "fb/hw_events.h" +#ifdef COMPILE_DRM +#include "drm/hw_events_drm.h" +#endif + +#define __CLASS__ "HWEventsInterface" + +namespace sdm { + +DisplayError HWEventsInterface::Create(int display_type, HWEventHandler *event_handler, + const std::vector<HWEvent> &event_list, + HWEventsInterface **intf) { + DisplayError error = kErrorNone; + HWEventsInterface *hw_events = nullptr; + if (GetDriverType() == DriverType::FB) { + hw_events = new HWEvents(); + } else { +#ifdef COMPILE_DRM + hw_events = new HWEventsDRM(); +#endif + } + + error = hw_events->Init(display_type, event_handler, event_list); + if (error != kErrorNone) { + delete hw_events; + } else { + *intf = hw_events; + } + + return error; +} + +DisplayError HWEventsInterface::Destroy(HWEventsInterface *intf) { + if (intf) { + intf->Deinit(); + delete intf; + } + + return kErrorNone; +} + +} // namespace sdm diff --git a/sdm/libs/core/hw_events_interface.h b/sdm/libs/core/hw_events_interface.h index a133a3a6..bcb7d43a 100644 --- a/sdm/libs/core/hw_events_interface.h +++ b/sdm/libs/core/hw_events_interface.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -32,10 +32,25 @@ namespace sdm { +class HWEventHandler; + +enum HWEvent { + VSYNC = 0, + EXIT, + IDLE_NOTIFY, + CEC_READ_MESSAGE, + SHOW_BLANK_EVENT, + THERMAL_LEVEL, +}; + class HWEventsInterface { public: - static DisplayError Create(int fb_num, HWEventHandler *event_handler, - std::vector<const char *> *event_list, HWEventsInterface **intf); + virtual DisplayError Init(int display_type, HWEventHandler *event_handler, + const std::vector<HWEvent> &event_list) = 0; + virtual DisplayError Deinit() = 0; + + static DisplayError Create(int display_type, HWEventHandler *event_handler, + const std::vector<HWEvent> &event_list, HWEventsInterface **intf); static DisplayError Destroy(HWEventsInterface *intf); protected: diff --git a/sdm/libs/core/hw_info_interface.cpp b/sdm/libs/core/hw_info_interface.cpp new file mode 100644 index 00000000..1773fe52 --- /dev/null +++ b/sdm/libs/core/hw_info_interface.cpp @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <utils/utils.h> + +#include "hw_info_interface.h" +#include "fb/hw_info.h" +#ifdef COMPILE_DRM +#include "drm/hw_info_drm.h" +#endif + +#define __CLASS__ "HWInfoInterface" + +namespace sdm { + +DisplayError HWInfoInterface::Create(HWInfoInterface **intf) { + if (GetDriverType() == DriverType::FB) { + *intf = new HWInfo(); + } else { +#ifdef COMPILE_DRM + *intf = new HWInfoDRM(); +#endif + } + + return kErrorNone; +} + +DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) { + if (intf) { + delete intf; + } + + return kErrorNone; +} + +} // namespace sdm diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp new file mode 100644 index 00000000..b328831c --- /dev/null +++ b/sdm/libs/core/hw_interface.cpp @@ -0,0 +1,102 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <utils/debug.h> +#include <utils/utils.h> + +#include "hw_interface.h" +#include "fb/hw_device.h" +#include "fb/hw_primary.h" +#include "fb/hw_hdmi.h" +#include "fb/hw_virtual.h" +#ifdef COMPILE_DRM +#include "drm/hw_device_drm.h" +#endif + +#define __CLASS__ "HWInterface" + +namespace sdm { + +DisplayError HWInterface::Create(DisplayType type, HWInfoInterface *hw_info_intf, + BufferSyncHandler *buffer_sync_handler, + HWInterface **intf) { + DisplayError error = kErrorNone; + HWInterface *hw = nullptr; + DriverType driver_type = GetDriverType(); + + switch (type) { + case kPrimary: + if (driver_type == DriverType::FB) { + hw = new HWPrimary(buffer_sync_handler, hw_info_intf); + } else { +#ifdef COMPILE_DRM + hw = new HWDeviceDRM(buffer_sync_handler, hw_info_intf); +#endif + } + break; + case kHDMI: + if (driver_type == DriverType::FB) { + hw = new HWHDMI(buffer_sync_handler, hw_info_intf); + } else { + return kErrorNotSupported; + } + break; + case kVirtual: + if (driver_type == DriverType::FB) { + hw = new HWVirtual(buffer_sync_handler, hw_info_intf); + } else { + return kErrorNotSupported; + } + break; + default: + DLOGE("Undefined display type"); + return kErrorUndefined; + } + + error = hw->Init(); + if (error != kErrorNone) { + delete hw; + DLOGE("Init on HW Intf type %d failed", type); + return error; + } + *intf = hw; + + return error; +} + +DisplayError HWInterface::Destroy(HWInterface *intf) { + if (intf) { + intf->Deinit(); + delete intf; + } + + return kErrorNone; +} + +} // namespace sdm diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h index da3ac4de..2e082ae6 100644 --- a/sdm/libs/core/hw_interface.h +++ b/sdm/libs/core/hw_interface.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: @@ -70,6 +70,8 @@ class HWInterface { BufferSyncHandler *buffer_sync_handler, HWInterface **intf); static DisplayError Destroy(HWInterface *intf); + virtual DisplayError Init() = 0; + virtual DisplayError Deinit() = 0; virtual DisplayError GetActiveConfig(uint32_t *active_config) = 0; virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0; virtual DisplayError GetDisplayAttributes(uint32_t index, diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp index 4962c388..aff6bbfb 100644 --- a/sdm/libs/hwc/hwc_display.cpp +++ b/sdm/libs/hwc/hwc_display.cpp @@ -37,6 +37,7 @@ #include <utils/debug.h> #include <sync/sync.h> #include <cutils/properties.h> +#include <qd_utils.h> #include <map> #include <utility> #include <vector> @@ -517,6 +518,7 @@ void HWCDisplay::CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer) { layer_buffer.planes[0].offset = pvt_handle->offset; layer_buffer.planes[0].stride = UINT32(pvt_handle->width); layer_buffer.size = pvt_handle->size; + layer_buffer.fb_id = pvt_handle->fb_id; } // if swapinterval property is set to 0 then close and reset the acquireFd @@ -1072,7 +1074,7 @@ void HWCDisplay::DumpInputBuffers(hwc_display_contents_1_t *content_list) { snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw", dir_path, i, pvt_handle->width, pvt_handle->height, - GetHALPixelFormatString(pvt_handle->format), dump_frame_index_); + qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_); FILE* fp = fopen(dump_file_name, "w+"); if (fp) { @@ -1128,81 +1130,6 @@ void HWCDisplay::DumpOutputBuffer(const BufferInfo& buffer_info, void *base, int } } -const char *HWCDisplay::GetHALPixelFormatString(int format) { - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - return "RGBA_8888"; - case HAL_PIXEL_FORMAT_RGBX_8888: - return "RGBX_8888"; - case HAL_PIXEL_FORMAT_RGB_888: - return "RGB_888"; - case HAL_PIXEL_FORMAT_RGB_565: - return "RGB_565"; - case HAL_PIXEL_FORMAT_BGR_565: - return "BGR_565"; - case HAL_PIXEL_FORMAT_BGRA_8888: - return "BGRA_8888"; - case HAL_PIXEL_FORMAT_RGBA_5551: - return "RGBA_5551"; - case HAL_PIXEL_FORMAT_RGBA_4444: - return "RGBA_4444"; - case HAL_PIXEL_FORMAT_YV12: - return "YV12"; - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - return "YCbCr_422_SP_NV16"; - case HAL_PIXEL_FORMAT_YCrCb_420_SP: - return "YCrCb_420_SP_NV21"; - case HAL_PIXEL_FORMAT_YCbCr_422_I: - return "YCbCr_422_I_YUY2"; - case HAL_PIXEL_FORMAT_YCrCb_422_I: - return "YCrCb_422_I_YVYU"; - case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: - return "NV12_ENCODEABLE"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: - return "YCbCr_420_SP_TILED_TILE_4x2"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - return "YCbCr_420_SP"; - case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: - return "YCrCb_420_SP_ADRENO"; - case HAL_PIXEL_FORMAT_YCrCb_422_SP: - return "YCrCb_422_SP"; - case HAL_PIXEL_FORMAT_R_8: - return "R_8"; - case HAL_PIXEL_FORMAT_RG_88: - return "RG_88"; - case HAL_PIXEL_FORMAT_INTERLACE: - return "INTERLACE"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: - return "YCbCr_420_SP_VENUS"; - case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: - return "YCrCb_420_SP_VENUS"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: - return "YCbCr_420_SP_VENUS_UBWC"; - case HAL_PIXEL_FORMAT_RGBA_1010102: - return "RGBA_1010102"; - case HAL_PIXEL_FORMAT_ARGB_2101010: - return "ARGB_2101010"; - case HAL_PIXEL_FORMAT_RGBX_1010102: - return "RGBX_1010102"; - case HAL_PIXEL_FORMAT_XRGB_2101010: - return "XRGB_2101010"; - case HAL_PIXEL_FORMAT_BGRA_1010102: - return "BGRA_1010102"; - case HAL_PIXEL_FORMAT_ABGR_2101010: - return "ABGR_2101010"; - case HAL_PIXEL_FORMAT_BGRX_1010102: - return "BGRX_1010102"; - case HAL_PIXEL_FORMAT_XBGR_2101010: - return "XBGR_2101010"; - case HAL_PIXEL_FORMAT_YCbCr_420_P010: - return "YCbCr_420_P010"; - case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: - return "YCbCr_420_TP10_UBWC"; - default: - return "Unknown_format"; - } -} - const char *HWCDisplay::GetDisplayString() { switch (type_) { case kPrimary: diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h index 8da85169..56529962 100644 --- a/sdm/libs/hwc/hwc_display.h +++ b/sdm/libs/hwc/hwc_display.h @@ -192,7 +192,6 @@ class HWCDisplay : public DisplayEventHandler { int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target); void SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target); LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags); - const char *GetHALPixelFormatString(int format); const char *GetDisplayString(); void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list); virtual void ApplyScanAdjustment(hwc_rect_t *display_frame); diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp index 3b0015dc..382e234f 100644 --- a/sdm/libs/hwc2/hwc_display.cpp +++ b/sdm/libs/hwc2/hwc_display.cpp @@ -27,6 +27,7 @@ #include <utils/debug.h> #include <utils/formats.h> #include <utils/rect.h> +#include <qd_utils.h> #include <algorithm> #include <map> @@ -1164,7 +1165,7 @@ void HWCDisplay::DumpInputBuffers() { snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw", dir_path, i, pvt_handle->width, pvt_handle->height, - GetHALPixelFormatString(pvt_handle->format), dump_frame_index_); + qdutils::GetHALPixelFormatString(pvt_handle->format), dump_frame_index_); FILE *fp = fopen(dump_file_name, "w+"); if (fp) { @@ -1219,81 +1220,6 @@ void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int } } -const char *HWCDisplay::GetHALPixelFormatString(int format) { - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - return "RGBA_8888"; - case HAL_PIXEL_FORMAT_RGBX_8888: - return "RGBX_8888"; - case HAL_PIXEL_FORMAT_RGB_888: - return "RGB_888"; - case HAL_PIXEL_FORMAT_RGB_565: - return "RGB_565"; - case HAL_PIXEL_FORMAT_BGR_565: - return "BGR_565"; - case HAL_PIXEL_FORMAT_BGRA_8888: - return "BGRA_8888"; - case HAL_PIXEL_FORMAT_RGBA_5551: - return "RGBA_5551"; - case HAL_PIXEL_FORMAT_RGBA_4444: - return "RGBA_4444"; - case HAL_PIXEL_FORMAT_YV12: - return "YV12"; - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - return "YCbCr_422_SP_NV16"; - case HAL_PIXEL_FORMAT_YCrCb_420_SP: - return "YCrCb_420_SP_NV21"; - case HAL_PIXEL_FORMAT_YCbCr_422_I: - return "YCbCr_422_I_YUY2"; - case HAL_PIXEL_FORMAT_YCrCb_422_I: - return "YCrCb_422_I_YVYU"; - case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: - return "NV12_ENCODEABLE"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: - return "YCbCr_420_SP_TILED_TILE_4x2"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - return "YCbCr_420_SP"; - case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: - return "YCrCb_420_SP_ADRENO"; - case HAL_PIXEL_FORMAT_YCrCb_422_SP: - return "YCrCb_422_SP"; - case HAL_PIXEL_FORMAT_R_8: - return "R_8"; - case HAL_PIXEL_FORMAT_RG_88: - return "RG_88"; - case HAL_PIXEL_FORMAT_INTERLACE: - return "INTERLACE"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: - return "YCbCr_420_SP_VENUS"; - case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: - return "YCrCb_420_SP_VENUS"; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: - return "YCbCr_420_SP_VENUS_UBWC"; - case HAL_PIXEL_FORMAT_RGBA_1010102: - return "RGBA_1010102"; - case HAL_PIXEL_FORMAT_ARGB_2101010: - return "ARGB_2101010"; - case HAL_PIXEL_FORMAT_RGBX_1010102: - return "RGBX_1010102"; - case HAL_PIXEL_FORMAT_XRGB_2101010: - return "XRGB_2101010"; - case HAL_PIXEL_FORMAT_BGRA_1010102: - return "BGRA_1010102"; - case HAL_PIXEL_FORMAT_ABGR_2101010: - return "ABGR_2101010"; - case HAL_PIXEL_FORMAT_BGRX_1010102: - return "BGRX_1010102"; - case HAL_PIXEL_FORMAT_XBGR_2101010: - return "XBGR_2101010"; - case HAL_PIXEL_FORMAT_YCbCr_420_P010: - return "YCbCr_420_P010"; - case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: - return "YCbCr_420_TP10_UBWC"; - default: - return "Unknown_format"; - } -} - const char *HWCDisplay::GetDisplayString() { switch (type_) { case kPrimary: diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h index 165e2c34..bc3c929f 100644 --- a/sdm/libs/hwc2/hwc_display.h +++ b/sdm/libs/hwc2/hwc_display.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright 2015 The Android Open Source Project @@ -212,7 +212,6 @@ class HWCDisplay : public DisplayEventHandler { return kErrorNotSupported; } LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags); - const char *GetHALPixelFormatString(int format); const char *GetDisplayString(); void MarkLayersForGPUBypass(void); void MarkLayersForClientComposition(void); diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp index 2ed21df1..c8fd1638 100644 --- a/sdm/libs/hwc2/hwc_layers.cpp +++ b/sdm/libs/hwc2/hwc_layers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright 2015 The Android Open Source Project @@ -143,6 +143,7 @@ HWC2::Error HWCLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fen layer_buffer->acquire_fence_fd = acquire_fence; layer_buffer->size = handle->size; layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle); + layer_buffer->fb_id = handle->fb_id; return HWC2::Error::None; } diff --git a/sdm/libs/utils/utils.cpp b/sdm/libs/utils/utils.cpp index 2ca9039f..07211a1a 100644 --- a/sdm/libs/utils/utils.cpp +++ b/sdm/libs/utils/utils.cpp @@ -27,8 +27,11 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <utils/sys.h> +#include <unistd.h> #include <math.h> +#include <utils/sys.h> +#include <utils/utils.h> + #include <algorithm> #define __CLASS__ "Utils" @@ -60,4 +63,9 @@ void CloseFd(int *fd) { } } +DriverType GetDriverType() { + const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps"; + // 0 - File exists + return Sys::access_(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB; +} } // namespace sdm |