Merge "hwc2: Check composition type in SetLayerBuffer"
diff --git a/Android.mk b/Android.mk
index 226e8a0..1a285bf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,7 +3,7 @@
ifneq ($(TARGET_IS_HEADLESS), true)
display-hals += libcopybit liblight libmemtrack hdmi_cec \
- $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils
+ $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils libdisplayconfig
endif
ifneq ($(TARGET_USES_GRALLOC1), true)
diff --git a/common.mk b/common.mk
index 88d1aee..18ee72f 100644
--- a/common.mk
+++ b/common.mk
@@ -3,7 +3,7 @@
#Common C flags
common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
-common_flags += -Wconversion -Wall -Werror -std=c++11
+common_flags += -Wconversion -Wall -Werror -std=c++14
ifeq ($(TARGET_IS_HEADLESS), true)
common_flags += -DTARGET_HEADLESS
LOCAL_CLANG := false
@@ -35,6 +35,10 @@
common_flags += -DUSE_GRALLOC1
endif
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+ common_flags += -DUSER_DEBUG
+endif
+
common_includes := system/core/base/include
CHECK_VERSION_LE = $(shell if [ $(1) -le $(2) ] ; then echo true ; else echo false ; fi)
PLATFORM_SDK_NOUGAT = 25
diff --git a/libdisplayconfig/Android.mk b/libdisplayconfig/Android.mk
new file mode 100644
index 0000000..fae7f85
--- /dev/null
+++ b/libdisplayconfig/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libdisplayconfig
+LOCAL_MODULE_TAGS := optional
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_COPY_HEADERS := DisplayConfig.h
+LOCAL_SRC_FILES := DisplayConfig.cpp
+LOCAL_SHARED_LIBRARIES := libhidlbase libhidltransport libutils \
+ vendor.display.config@1.0 android.hidl.base@1.0
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libdisplayconfig/DisplayConfig.cpp b/libdisplayconfig/DisplayConfig.cpp
new file mode 100644
index 0000000..c55715b
--- /dev/null
+++ b/libdisplayconfig/DisplayConfig.cpp
@@ -0,0 +1,363 @@
+/*
+* 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 <vendor/display/config/1.0/IDisplayConfig.h>
+
+#include "DisplayConfig.h"
+
+namespace display {
+
+using vendor::display::config::V1_0::IDisplayConfig;
+
+//=============================================================================
+// The functions below run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
+
+IDisplayConfig::DisplayType MapDisplayType(int dpy) {
+ switch (dpy) {
+ case DISPLAY_PRIMARY:
+ return IDisplayConfig::DisplayType::DISPLAY_PRIMARY;
+
+ case DISPLAY_EXTERNAL:
+ return IDisplayConfig::DisplayType::DISPLAY_EXTERNAL;
+
+ case DISPLAY_VIRTUAL:
+ return IDisplayConfig::DisplayType::DISPLAY_VIRTUAL;
+
+ default:
+ break;
+ }
+
+ return IDisplayConfig::DisplayType::INVALID;
+}
+
+IDisplayConfig::DisplayExternalStatus MapExternalStatus(uint32_t status) {
+ switch (status) {
+ case EXTERNAL_OFFLINE:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE;
+
+ case EXTERNAL_ONLINE:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE;
+
+ case EXTERNAL_PAUSE:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE;
+
+ case EXTERNAL_RESUME:
+ return IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME;
+
+ default:
+ break;
+ }
+
+ return IDisplayConfig::DisplayExternalStatus::INVALID;
+}
+
+IDisplayConfig::DisplayDynRefreshRateOp MapDynRefreshRateOp(uint32_t op) {
+ switch (op) {
+ case DISABLE_METADATA_DYN_REFRESH_RATE:
+ return IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE;
+
+ case ENABLE_METADATA_DYN_REFRESH_RATE:
+ return IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE;
+
+ case SET_BINDER_DYN_REFRESH_RATE:
+ return IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE;
+
+ default:
+ break;
+ }
+
+ return IDisplayConfig::DisplayDynRefreshRateOp::INVALID;
+}
+
+int MapDisplayPortType(IDisplayConfig::DisplayPortType panelType) {
+ switch (panelType) {
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT:
+ return DISPLAY_PORT_DEFAULT;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DSI:
+ return DISPLAY_PORT_DSI;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DTV:
+ return DISPLAY_PORT_DTV;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_WRITEBACK:
+ return DISPLAY_PORT_WRITEBACK;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_LVDS:
+ return DISPLAY_PORT_LVDS;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_EDP:
+ return DISPLAY_PORT_EDP;
+
+ case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DP:
+ return DISPLAY_PORT_DP;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+int isExternalConnected() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return 0;
+ }
+
+ int connected = 0;
+ intf->isDisplayConnected(IDisplayConfig::DisplayType::DISPLAY_EXTERNAL,
+ [&](const auto &tmpError, const auto &tmpStatus) {
+ if (tmpError) {
+ return;
+ }
+
+ connected = tmpStatus;
+ });
+
+ return connected;
+}
+
+int setSecondayDisplayStatus(int dpy, uint32_t status) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setSecondayDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
+}
+
+int configureDynRefeshRate(uint32_t op, uint32_t refreshRate) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->configureDynRefeshRate(MapDynRefreshRateOp(op), refreshRate);
+}
+
+int getConfigCount(int dpy) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ int count = 0;
+ intf->getActiveConfig(MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpCount) {
+ if (tmpError) {
+ return;
+ }
+
+ count = tmpCount;
+ });
+
+ return count;
+}
+
+int getActiveConfig(int dpy) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ int config = 0;
+ intf->getActiveConfig(MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpConfig) {
+ if (tmpError) {
+ return;
+ }
+
+ config = tmpConfig;
+ });
+
+ return config;
+}
+
+int setActiveConfig(int dpy, uint32_t config) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setActiveConfig(MapDisplayType(dpy), config);
+}
+
+DisplayAttributes getDisplayAttributes(uint32_t configIndex, int dpy) {
+ DisplayAttributes attributes;
+
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return attributes;
+ }
+
+ intf->getDisplayAttributes(configIndex, MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpAttributes) {
+ if (tmpError) {
+ return;
+ }
+
+ attributes.vsync_period = tmpAttributes.vsyncPeriod;
+ attributes.xres = tmpAttributes.xRes;
+ attributes.yres = tmpAttributes.yRes;
+ attributes.xdpi = tmpAttributes.xDpi;
+ attributes.ydpi = tmpAttributes.yDpi;
+ attributes.panel_type = MapDisplayPortType(tmpAttributes.panelType);
+ attributes.is_yuv = tmpAttributes.isYuv;
+ });
+
+ return attributes;
+}
+
+int setPanelBrightness(uint32_t level) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setPanelBrightness(level);
+}
+
+uint32_t getPanelBrightness() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return 0;
+ }
+
+ int level = 0;
+ intf->getPanelBrightness(
+ [&](const auto &tmpError, const auto &tmpLevel) {
+ if (tmpError) {
+ return;
+ }
+
+ level = tmpLevel;
+ });
+
+ return level;
+}
+
+int minHdcpEncryptionLevelChanged(int dpy, uint32_t min_enc_level) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->minHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
+}
+
+int refreshScreen() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->refreshScreen();
+}
+
+int controlPartialUpdate(int dpy, bool enable) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->controlPartialUpdate(MapDisplayType(dpy), enable);
+}
+
+int toggleScreenUpdate(uint32_t on) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->toggleScreenUpdate(on == 1);
+}
+
+int setIdleTimeout(uint32_t value) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setIdleTimeout(value);
+}
+
+int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL || caps == NULL) {
+ return -1;
+ }
+
+ int error = -1;
+ intf->getHDRCapabilities(MapDisplayType(dpy),
+ [&](const auto &tmpError, const auto &tmpCaps) {
+ error = tmpError;
+ if (error) {
+ return;
+ }
+
+ caps->supported_hdr_types = tmpCaps.supportedHdrTypes;
+ caps->max_luminance = tmpCaps.maxLuminance;
+ caps->max_avg_luminance = tmpCaps.maxAvgLuminance;
+ caps->min_luminance = tmpCaps.minLuminance;
+ });
+
+ return error;
+}
+
+int setCameraLaunchStatus(uint32_t on) {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return -1;
+ }
+
+ return intf->setCameraLaunchStatus(on);
+}
+
+bool displayBWTransactionPending() {
+ android::sp<IDisplayConfig> intf = IDisplayConfig::getService();
+ if (intf == NULL) {
+ return 0;
+ }
+
+ int status = 0;
+ intf->displayBWTransactionPending(
+ [&](const auto &tmpError, const auto &tmpStatus) {
+ if (tmpError) {
+ return;
+ }
+
+ status = tmpStatus;
+ });
+
+ return status;
+}
+
+} // namespace display
diff --git a/libdisplayconfig/DisplayConfig.h b/libdisplayconfig/DisplayConfig.h
new file mode 100644
index 0000000..69a542a
--- /dev/null
+++ b/libdisplayconfig/DisplayConfig.h
@@ -0,0 +1,110 @@
+/*
+ * Copyight (c) 2017 The Linux Foundation. All ights reserved.
+ *
+ * Redistibution and use in souce and binary forms, with or without
+ * modification, ae pemitted provided that the following conditions are
+ * met:
+ * * Redistibutions of souce code must retain the above copyright
+ * notice, this list of conditions and the following disclaime.
+ * * Redistibutions in binay form must reproduce the above
+ * copyight notice, this list of conditions and the following
+ * disclaime in the documentation and/o other materials provided
+ * with the distibution.
+ * * Neither the name of The Linux Foundation. no the names of its
+ * contibutos may be used to endorse or promote products derived
+ * fom this softwae 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 __DISPLAY_CONFIG_H__
+#define __DISPLAY_CONFIG_H__
+
+#include <stdint.h>
+#include <vector>
+
+// This header is for clients to use to set/get global display configuration.
+
+namespace display {
+
+enum {
+ DISPLAY_PRIMARY = 0,
+ DISPLAY_EXTERNAL,
+ DISPLAY_VIRTUAL,
+};
+
+enum {
+ EXTERNAL_OFFLINE = 0,
+ EXTERNAL_ONLINE,
+ EXTERNAL_PAUSE,
+ EXTERNAL_RESUME,
+};
+
+enum {
+ DISABLE_METADATA_DYN_REFRESH_RATE = 0,
+ ENABLE_METADATA_DYN_REFRESH_RATE,
+ SET_BINDER_DYN_REFRESH_RATE,
+};
+
+enum {
+ DISPLAY_PORT_DEFAULT = 0,
+ DISPLAY_PORT_DSI,
+ DISPLAY_PORT_DTV,
+ DISPLAY_PORT_WRITEBACK,
+ DISPLAY_PORT_LVDS,
+ DISPLAY_PORT_EDP,
+ DISPLAY_PORT_DP,
+};
+
+struct DisplayAttributes {
+ uint32_t vsync_period = 0; //nanoseconds
+ uint32_t xres = 0;
+ uint32_t yres = 0;
+ float xdpi = 0.0f;
+ float ydpi = 0.0f;
+ int panel_type = DISPLAY_PORT_DEFAULT;
+ bool is_yuv = false;
+};
+
+struct DisplayHDRCapabilities {
+ std::vector<int32_t> supported_hdr_types;
+ float max_luminance = 0.0f;
+ float max_avg_luminance = 0.0f;
+ float min_luminance = 0.0f;
+};
+
+//=============================================================================
+// The functions below run in the client pocess and wherever necessary
+// do a binder call to HWC to get/set data.
+
+int isExternalConnected();
+int setSecondayDisplayStatus(int dpy, uint32_t status);
+int configureDynRefeshRate(uint32_t op, uint32_t refreshRate);
+int getConfigCount(int dpy);
+int getActiveConfig(int dpy);
+int setActiveConfig(int dpy, uint32_t config);
+DisplayAttributes getDisplayAttributes(uint32_t configIndex, int dpy);
+int setPanelBrightness(uint32_t level);
+uint32_t getPanelBrightness();
+int minHdcpEncryptionLevelChanged(int dpy, uint32_t min_enc_level);
+int refreshScreen();
+int controlPartialUpdate(int dpy, bool enable);
+int toggleScreenUpdate(uint32_t on);
+int setIdleTimeout(uint32_t value);
+int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps);
+int setCameraLaunchStatus(uint32_t on);
+bool displayBWTransactionPending();
+
+} // namespace display
+
+#endif // __DISPLAY_CONFIG_H__
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 71767e7..97c8ad8 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -125,6 +125,12 @@
*/
PLANE_SET_SCALER_CONFIG,
/*
+ * Op: Sets plane rotation destination rect
+ * Arg: uint32_t - Plane ID
+ * DRMRect - rotator dst Rectangle
+ */
+ PLANE_SET_ROTATION_DST_RECT,
+ /*
* Op: Activate or deactivate a CRTC
* Arg: uint32_t - CRTC ID
* uint32_t - 1 to enable, 0 to disable
@@ -149,19 +155,48 @@
* uint32_t - core_clk
*/
CRTC_SET_CORE_CLK,
- /*
- * Op: Sets overall SDE core average bandwidth
+ /*
+ * Op: Sets MNOC bus average bandwidth
* Arg: uint32_t - CRTC ID
* uint32_t - core_ab
*/
CRTC_SET_CORE_AB,
/*
- * Op: Sets overall SDE core instantaneous bandwidth
+ * Op: Sets MNOC bus instantaneous bandwidth
* Arg: uint32_t - CRTC ID
* uint32_t - core_ib
*/
CRTC_SET_CORE_IB,
/*
+ * Op: Sets LLCC Bus average bandwidth
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - llcc_ab
+ */
+ CRTC_SET_LLCC_AB,
+ /*
+ * Op: Sets LLCC Bus instantaneous bandwidth
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - llcc_ib
+ */
+ CRTC_SET_LLCC_IB,
+ /*
+ * Op: Sets DRAM bus average bandwidth
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - dram_ab
+ */
+ CRTC_SET_DRAM_AB,
+ /*
+ * Op: Sets DRAM bus instantaneous bandwidth
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - dram_ib
+ */
+ CRTC_SET_DRAM_IB,
+ /*
+ * Op: Sets rotator clock for inline rotation
+ * Arg: uint32_t - CRTC ID
+ * uint32_t - rot_clk
+ */
+ CRTC_SET_ROT_CLK, /*
* Op: Returns release fence for this frame. Should be called after Commit() on
* DRMAtomicReqInterface.
* Arg: uint32_t - CRTC ID
@@ -315,17 +350,22 @@
uint32_t max_horizontal_deci;
uint32_t max_vertical_deci;
uint64_t max_pipe_bandwidth;
+ uint32_t cache_size; // cache size in bytes for inline rotation support.
};
// All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
typedef std::vector<std::pair<uint32_t, DRMPlaneTypeInfo>> DRMPlanesInfo;
enum struct DRMTopology {
- UNKNOWN, // To be compat with driver defs in sde_kms.h
+ UNKNOWN, // To be compat with driver defs in sde_rm.h
SINGLE_LM,
+ SINGLE_LM_DSC,
DUAL_LM,
- PPSPLIT,
+ DUAL_LM_DSC,
DUAL_LM_MERGE,
+ DUAL_LM_MERGE_DSC,
+ DUAL_LM_DSCMERGE,
+ PPSPLIT,
};
enum struct DRMPanelMode {
diff --git a/libgralloc1/Android.mk b/libgralloc1/Android.mk
index f4d4ba7..cdb651c 100644
--- a/libgralloc1/Android.mk
+++ b/libgralloc1/Android.mk
@@ -31,7 +31,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_HEADER_LIBRARIES := display_headers
-LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libqdMetaData libdl
+LOCAL_SHARED_LIBRARIES := $(common_libs) libqdMetaData libdl
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"grallocutils\" -Wno-sign-conversion
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
LOCAL_SRC_FILES := gr_utils.cpp gr_adreno_info.cpp
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 7e0ba14..16f5635 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -214,7 +214,9 @@
private_handle_t * handle = const_cast<private_handle_t *>(hnd);
handle->fd = -1;
handle->fd_metadata = -1;
- delete handle;
+ if (!(handle->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED)) {
+ delete handle;
+ }
return GRALLOC1_ERROR_NONE;
}
@@ -277,10 +279,6 @@
}
gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
- if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
- return GRALLOC1_ERROR_NONE;
- }
-
ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
gralloc1_error_t err = GRALLOC1_ERROR_NONE;
std::lock_guard<std::mutex> lock(buffer_lock_);
@@ -302,10 +300,6 @@
}
gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
- if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
- return GRALLOC1_ERROR_NONE;
- }
-
ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
std::lock_guard<std::mutex> lock(buffer_lock_);
auto buf = GetBufferFromHandleLocked(hnd);
@@ -497,14 +491,14 @@
BufferInfo info = GetBufferInfo(descriptor);
GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
size = (bufferSize >= size) ? bufferSize : size;
- size = size * layer_count;
int err = 0;
int flags = 0;
auto page_size = UINT(getpagesize());
AllocData data;
data.align = GetDataAlignment(format, prod_usage, cons_usage);
- data.size = ALIGN(size, data.align);
+ size = ALIGN(size, data.align) * layer_count;
+ data.size = size;
data.handle = (uintptr_t) handle;
data.uncached = allocator_->UseUncached(prod_usage, cons_usage);
@@ -630,9 +624,20 @@
}
BufferDim_t buffer_dim;
+ int interlaced = 0;
if (getMetaData(hnd, GET_BUFFER_GEOMETRY, &buffer_dim) == 0) {
*stride = buffer_dim.sliceWidth;
*height = buffer_dim.sliceHeight;
+ } else if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, &interlaced) == 0) {
+ if (interlaced && IsUBwcFormat(hnd->format)) {
+ unsigned int alignedw = 0, alignedh = 0;
+ // Get re-aligned height for single ubwc interlaced field and
+ // multiple by 2 to get frame height.
+ BufferInfo info(hnd->width, ((hnd->height+1)>>1), hnd->format);
+ GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
+ *stride = static_cast<int>(alignedw);
+ *height = static_cast<int>(alignedh * 2);
+ }
} else {
*stride = hnd->width;
*height = hnd->height;
diff --git a/liblight/Android.mk b/liblight/Android.mk
index f627286..2f2e1ca 100644
--- a/liblight/Android.mk
+++ b/liblight/Android.mk
@@ -22,7 +22,7 @@
LOCAL_SRC_FILES := lights.c lights_prv.cpp
LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SHARED_LIBRARIES := liblog libcutils libsdm-disp-apis
+LOCAL_SHARED_LIBRARIES := liblog libcutils libsdm-disp-vndapis
LOCAL_CFLAGS := -DLOG_TAG=\"qdlights\"
LOCAL_CLANG := true
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 5e327d7..8985dd6 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
@@ -93,6 +93,7 @@
DEBUG_DRIVER_CONFIG,
DEBUG_ROTATOR,
DEBUG_QDCM,
+ DEBUG_SCALAR,
};
enum {
diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h
index fae1153..ce356bf 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -55,6 +55,7 @@
kErrorShutDown, //!< Driver is processing shutdown sequence
kErrorPerfValidation, //!< Bandwidth or Clock requirement validation failure.
kErrorNoAppLayers, //!< No App layer(s) in the draw cycle.
+ kErrorRotatorValidation, //!< Rotator configuration validation failure.
};
/*! @brief This structure is defined for client and library compatibility check purpose only. This
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index cdfec2e..8cf1922 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -38,8 +38,6 @@
const int kMaxSDELayers = 16; // Maximum number of layers that can be handled by MDP5 hardware
// in a given layer stack.
-const int kMaxBlitLayers = 32; // Maximum number of layers that can be handled by MDP3 hardware
- // in a given layer stack.
#define MAX_PLANES 4
#define MAX_DETAIL_ENHANCE_CURVE 3
@@ -205,6 +203,7 @@
uint32_t undersized_prefill_lines = 0;
CompRatioMap comp_ratio_rt_map;
CompRatioMap comp_ratio_nrt_map;
+ uint32_t cache_size = 0; // cache size in bytes
void Reset() { *this = HWResourceInfo(); }
};
@@ -321,6 +320,12 @@
}
};
+enum HWRotatorMode {
+ kRotatorNone,
+ kRotatorOffline,
+ kRotatorInline
+};
+
struct HWRotateInfo {
int pipe_id = -1; // Not actual pipe id, but the relative DMA id
int writeback_id = -1; // Writeback block id, but this is the same as DMA id
@@ -342,6 +347,7 @@
float input_compression = 1.0f;
float output_compression = 1.0f;
bool is_buffer_cached = false;
+ HWRotatorMode mode = kRotatorNone;
};
struct HWScaleLutInfo {
@@ -499,13 +505,22 @@
Handle pvt_data = NULL; // Private data used by sdm extension only.
};
+struct HWQosData {
+ uint64_t core_ab_bps = 0;
+ uint64_t core_ib_bps = 0;
+ uint64_t llcc_ab_bps = 0;
+ uint64_t llcc_ib_bps = 0;
+ uint64_t dram_ab_bps = 0;
+ uint64_t dram_ib_bps = 0;
+ uint32_t clock_hz = 0;
+ uint32_t rot_clock_hz = 0;
+};
+
struct HWLayers {
HWLayersInfo info;
HWLayerConfig config[kMaxSDELayers];
float output_compression = 1.0f;
- uint64_t ab_bps = 0;
- uint64_t ib_bps = 0;
- uint32_t clock_hz = 0;
+ HWQosData qos_data = {};
HWAVRInfo hw_avr_info = {};
};
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index e140c33..f57d760 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -58,8 +58,9 @@
virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst,
bool rotate90, BufferLayout layout,
bool use_rotator_downscale) = 0;
- virtual DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
- int x, int y) = 0;
+ virtual DisplayError ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+ int x, int y,
+ DisplayConfigVariableInfo *fb_config) = 0;
virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
diff --git a/sdm/include/utils/formats.h b/sdm/include/utils/formats.h
index dd819dc..2d43850 100644
--- a/sdm/include/utils/formats.h
+++ b/sdm/include/utils/formats.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
@@ -34,10 +34,28 @@
namespace sdm {
+struct FormatTileSize {
+ /*< Tile width in pixels. For YUV formats this will give only the
+ tile width for Y plane*/
+ uint32_t tile_width = 0;
+ /*< Tile height in pixels. For YUV formats this will give only the
+ tile height for Y plane*/
+ uint32_t tile_height = 0;
+
+ /*< Tile width in pixels. Only valid for YUV formats where this will
+ give tile width for UV plane*/
+ uint32_t uv_tile_width = 0;
+ /*< Tile height in pixels. Only valid for YUV formats where this will
+ give tile height for UV plane*/
+ uint32_t uv_tile_height = 0;
+};
+
bool IsUBWCFormat(LayerBufferFormat format);
bool Is10BitFormat(LayerBufferFormat format);
const char *GetFormatString(const LayerBufferFormat &format);
BufferLayout GetBufferLayout(LayerBufferFormat format);
+DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size);
+float GetBufferFormatBpp(LayerBufferFormat format);
} // namespace sdm
diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h
index ea6edfb..303fc9f 100644
--- a/sdm/include/utils/rect.h
+++ b/sdm/include/utils/rect.h
@@ -60,6 +60,11 @@
void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect,
const LayerTransform &transform, LayerRect *out_rect);
RectOrientation GetOrientation(const LayerRect &in_rect);
+ DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+ bool rotate90, float *crop_width, float *crop_height,
+ float *dst_width, float *dst_height);
+ DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, bool rotate90,
+ float *scale_x, float *scale_y);
} // namespace sdm
#endif // __RECT_H__
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index c5002a9..991cfac 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -49,6 +49,7 @@
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_hdmi_drm.cpp \
$(LOCAL_HW_INTF_PATH_2)/hw_events_drm.cpp \
$(LOCAL_HW_INTF_PATH_2)/hw_scale_drm.cpp \
$(LOCAL_HW_INTF_PATH_2)/hw_virtual_drm.cpp \
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index d18b5b8..f35c1c6 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -121,6 +121,7 @@
registered_displays_[type] = 1;
display_comp_ctx->is_primary_panel = hw_panel_info.is_primary_panel;
display_comp_ctx->display_type = type;
+ display_comp_ctx->fb_config = fb_config;
*display_ctx = display_comp_ctx;
// New non-primary display device has been added, so move the composition mode to safe mode until
// resources for the added display is configured properly.
@@ -207,6 +208,8 @@
}
}
+ // Update new resolution.
+ display_comp_ctx->fb_config = fb_config;
return error;
}
@@ -459,13 +462,13 @@
return resource_intf_->ValidateScaling(crop, dst, rotate90, layout, true);
}
-DisplayError CompManager::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+DisplayError CompManager::ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers,
int x, int y) {
DisplayCompositionContext *display_comp_ctx =
reinterpret_cast<DisplayCompositionContext *>(display_ctx);
Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
-
- return resource_intf_->ValidateCursorPosition(display_resource_ctx, hw_layers, x, y);
+ return resource_intf_->ValidateAndSetCursorPosition(display_resource_ctx, hw_layers, x, y,
+ &display_comp_ctx->fb_config);
}
DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index c6b8972..6cc33cf 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -66,7 +66,7 @@
DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
void ControlPartialUpdate(Handle display_ctx, bool enable);
DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
- DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
+ DisplayError ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
bool SetDisplayState(Handle display_ctx, DisplayState state, DisplayType display_type);
DisplayError SetMaxBandwidthMode(HWBwModes mode);
DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
@@ -97,6 +97,7 @@
// panel parameters for now.
bool is_primary_panel = false;
PUConstraints pu_constraints = {};
+ DisplayConfigVariableInfo fb_config = {};
};
Locker locker_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 618dd2e..b76c3d1 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -590,21 +590,24 @@
char idx[8] = { 0 };
const char *comp_type = GetName(sdm_layer->composition);
const char *buffer_format = GetFormatString(input_buffer->format);
- const char *rotate_split[2] = { "Rot-1", "Rot-2" };
const char *comp_split[2] = { "Comp-1", "Comp-2" };
snprintf(idx, sizeof(idx), "%d", layer_index);
for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
- char writeback_id[8] = { 0 };
+ char writeback_id[8] = { "I" };
HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
LayerRect &src_roi = rotate.src_roi;
LayerRect &dst_roi = rotate.dst_roi;
+ const char *rotate_split[2] = { "Rot-1", "Rot-2" };
+ int pipe_id = 0;
- snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
-
+ if (hw_rotator_session.mode == kRotatorOffline) {
+ snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+ pipe_id = rotate.pipe_id;
+ }
DumpImpl::AppendString(buffer, length, format, idx, comp_type, rotate_split[count],
- writeback_id, rotate.pipe_id, input_buffer->width,
+ writeback_id, pipe_id, input_buffer->width,
input_buffer->height, buffer_format, INT(src_roi.left),
INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
@@ -633,8 +636,11 @@
continue;
}
- LayerRect &src_roi = pipe.src_roi;
+ LayerRect src_roi = pipe.src_roi;
LayerRect &dst_roi = pipe.dst_roi;
+ if (hw_rotator_session.mode == kRotatorInline) {
+ src_roi = hw_rotator_session.hw_rotate_info[count].dst_roi;
+ }
snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
snprintf(flags, sizeof(flags), "0x%08x", hw_layer.flags.flags);
@@ -954,7 +960,8 @@
return kErrorNotSupported;
}
- DisplayError error = comp_manager_->ValidateCursorPosition(display_comp_ctx_, &hw_layers_, x, y);
+ DisplayError error = comp_manager_->ValidateAndSetCursorPosition(display_comp_ctx_, &hw_layers_,
+ x, y);
if (error == kErrorNone) {
return hw_intf_->SetCursorPosition(&hw_layers_, x, y);
}
@@ -1325,10 +1332,6 @@
sdm_layer->input_buffer.release_fence_fd = temp;
}
-
- // Reset the sync fence fds of HWLayer
- hw_layer.input_buffer.acquire_fence_fd = -1;
- hw_layer.input_buffer.release_fence_fd = -1;
}
return;
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index b31ac94..a6c5c47 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -87,7 +87,8 @@
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_intf_,
+ &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 ca09ce3..dfee684 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -55,6 +55,7 @@
virtual void ThermalEvent(int64_t thermal_level) { }
virtual void CECMessage(char *message);
virtual void IdlePowerCollapse() { }
+ virtual void PingPongTimeout() { }
private:
uint32_t GetBestConfig(HWS3DMode s3d_mode);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 53a4fd9..52b71c7 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -70,7 +70,8 @@
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_intf_,
+ &hw_events_intf_);
if (error != kErrorNone) {
DLOGE("Failed to create hardware events interface. Error = %d", error);
DisplayBase::Deinit();
@@ -89,32 +90,6 @@
uint32_t new_mixer_height = 0;
uint32_t display_width = display_attributes_.x_pixels;
uint32_t display_height = display_attributes_.y_pixels;
- bool needs_hv_flip = hw_panel_info_.panel_orientation.flip_horizontal &&
- hw_panel_info_.panel_orientation.flip_vertical;
- LayerRect src_domain = {};
- LayerTransform panel_transform = {};
- DisplayConfigVariableInfo variable_info = {};
-
- if (needs_hv_flip) {
- DisplayBase::GetFrameBufferConfig(&variable_info);
- src_domain.right = variable_info.x_pixels;
- src_domain.bottom = variable_info.y_pixels;
- panel_transform.flip_horizontal = hw_panel_info_.panel_orientation.flip_horizontal;
- panel_transform.flip_vertical = hw_panel_info_.panel_orientation.flip_vertical;
-
- for (Layer *layer : layer_stack->layers) {
- // Modify destination based on panel flip
- TransformHV(src_domain, layer->dst_rect, panel_transform, &layer->dst_rect);
-
- if (layer->flags.solid_fill) {
- continue;
- }
-
- layer->transform.flip_horizontal ^= (hw_panel_info_.panel_orientation.flip_horizontal);
- layer->transform.flip_vertical ^= (hw_panel_info_.panel_orientation.flip_vertical);
- // TODO(user): Check how to handle rotation, if panel has rotation.
- }
- }
if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
error = ReconfigureMixer(new_mixer_width, new_mixer_height);
@@ -310,6 +285,11 @@
comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
}
+void DisplayPrimary::PingPongTimeout() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ hw_intf_->DumpDebugData();
+}
+
void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 314964a..e5aeabc 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -61,12 +61,17 @@
virtual void ThermalEvent(int64_t thermal_level);
virtual void CECMessage(char *message) { }
virtual void IdlePowerCollapse();
+ virtual void PingPongTimeout();
private:
bool NeedsAVREnable();
- std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::EXIT, HWEvent::IDLE_NOTIFY,
- HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL, HWEvent::IDLE_POWER_COLLAPSE };
+ std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::EXIT,
+ HWEvent::IDLE_NOTIFY,
+ HWEvent::SHOW_BLANK_EVENT,
+ HWEvent::THERMAL_LEVEL,
+ HWEvent::IDLE_POWER_COLLAPSE,
+ HWEvent::PINGPONG_TIMEOUT };
bool avr_prop_disabled_ = false;
bool switch_to_cmd_ = false;
bool handle_idle_timeout_ = false;
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index 640a843..3438e77 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -270,9 +270,14 @@
return kErrorParameters;
}
- if (sde_gamut->map_en)
- std::memcpy(mdp_gamut->scale_off, sde_gamut->scale_off_data,
- sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ * GAMUT_3D_SCALE_OFF_TBL_NUM);
+ if (sde_gamut->map_en) {
+ std::memcpy(&mdp_gamut->scale_off[0][0], sde_gamut->scale_off_data[0],
+ sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ);
+ std::memcpy(&mdp_gamut->scale_off[1][0], sde_gamut->scale_off_data[1],
+ sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ);
+ std::memcpy(&mdp_gamut->scale_off[2][0], sde_gamut->scale_off_data[2],
+ sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ);
+ }
for (uint32_t row = 0; row < GAMUT_3D_TBL_NUM; row++) {
for (uint32_t col = 0; col < size; col++) {
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 1028663..9e99361 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -50,6 +50,7 @@
#include <utils/sys.h>
#include <drm/sde_drm.h>
#include <private/color_params.h>
+#include <utils/rect.h>
#include <algorithm>
#include <string>
@@ -225,7 +226,7 @@
HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0];
- if (hw_rotate_info->valid) {
+ if (hw_rotator_session->mode == kRotatorOffline && hw_rotate_info->valid) {
input_buffer = &hw_rotator_session->output_buffer;
}
@@ -355,6 +356,7 @@
}
DisplayError HWDeviceDRM::Deinit() {
+ PowerOff();
delete hw_scale_;
registry_.Clear();
drm_mgr_intf_->DestroyAtomicReq(drm_atomic_intf_);
@@ -414,7 +416,9 @@
display_attributes_.h_total = mode.htotal;
uint32_t h_blanking = mode.htotal - mode.hdisplay;
display_attributes_.is_device_split =
- (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE);
+ (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE ||
+ topology == DRMTopology::DUAL_LM_MERGE_DSC || topology == DRMTopology::DUAL_LM_DSC ||
+ topology == DRMTopology::DUAL_LM_DSCMERGE);
display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
@@ -574,6 +578,11 @@
DisplayError HWDeviceDRM::PowerOn() {
DTRACE_SCOPED();
+ if (!drm_atomic_intf_) {
+ DLOGE("DRM Atomic Interface is null!");
+ return kErrorUndefined;
+ }
+
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
int ret = drm_atomic_intf_->Commit(false /* synchronous */);
@@ -585,6 +594,11 @@
}
DisplayError HWDeviceDRM::PowerOff() {
+ if (!drm_atomic_intf_) {
+ DLOGE("DRM Atomic Interface is null!");
+ return kErrorUndefined;
+ }
+
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
int ret = drm_atomic_intf_->Commit(false /* synchronous */);
@@ -617,6 +631,7 @@
HWLayersInfo &hw_layer_info = hw_layers->info;
uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+ HWQosData &qos_data = hw_layers->qos_data;
// TODO(user): Once destination scalar is enabled we can always send ROIs if driver allows
if (hw_panel_info_.partial_update) {
@@ -652,15 +667,13 @@
HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
- bool needs_rotation = false;
for (uint32_t count = 0; count < 2; count++) {
HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
- if (hw_rotate_info->valid) {
+ if (hw_rotator_session->mode == kRotatorOffline && hw_rotate_info->valid) {
input_buffer = &hw_rotator_session->output_buffer;
- needs_rotation = true;
}
uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd);
@@ -674,21 +687,17 @@
DRMRect src = {};
SetRect(pipe_info->src_roi, &src);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src);
+ DRMRect rot_dst = {0, 0, 0, 0};
+ if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid) {
+ SetRect(hw_rotate_info->dst_roi, &rot_dst);
+ drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION_DST_RECT, pipe_id, rot_dst);
+ }
DRMRect dst = {};
SetRect(pipe_info->dst_roi, &dst);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
uint32_t rot_bit_mask = 0;
- // In case of rotation, rotator handles flips
- if (!needs_rotation) {
- if (layer.transform.flip_horizontal) {
- rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
- }
- if (layer.transform.flip_vertical) {
- rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
- }
- }
-
+ SetRotation(layer.transform, hw_rotator_session->mode, &rot_bit_mask);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id,
pipe_info->horizontal_decimation);
@@ -715,12 +724,20 @@
}
}
- drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_CLK, token_.crtc_id, hw_layers->clock_hz);
- drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_AB, token_.crtc_id, hw_layers->ab_bps);
- drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_IB, token_.crtc_id, hw_layers->ib_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_CLK, token_.crtc_id, qos_data.clock_hz);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_AB, token_.crtc_id, qos_data.core_ab_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_IB, token_.crtc_id, qos_data.core_ib_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_LLCC_AB, token_.crtc_id, qos_data.llcc_ab_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_LLCC_IB, token_.crtc_id, qos_data.llcc_ib_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_AB, token_.crtc_id, qos_data.dram_ab_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_IB, token_.crtc_id, qos_data.dram_ib_bps);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_CLK, token_.crtc_id, qos_data.rot_clock_hz);
- DLOGI_IF(kTagDriverConfig, "System: clock=%d Hz, ab=%llu Bps ib=%llu Bps", hw_layers->clock_hz,
- hw_layers->ab_bps, hw_layers->ib_bps);
+ DLOGI_IF(kTagDriverConfig, "System Clock=%d Hz, Core: AB=%llu Bps, IB=%llu Bps, " \
+ "LLCC: AB=%llu Bps, IB=%llu Bps, DRAM AB=%llu Bps, IB=%llu Bps Rot Clock=%d",
+ qos_data.clock_hz, qos_data.core_ab_bps, qos_data.core_ib_bps, qos_data.llcc_ab_bps,
+ qos_data.llcc_ib_bps, qos_data.dram_ab_bps, qos_data.dram_ib_bps,
+ qos_data.rot_clock_hz);
}
}
@@ -828,7 +845,7 @@
for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) {
Layer &layer = hw_layer_info.hw_layers.at(i);
HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
- if (hw_rotator_session->hw_block_count) {
+ if (hw_rotator_session->mode == kRotatorOffline) {
hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence);
} else {
layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
@@ -874,6 +891,36 @@
target->bottom = UINT32(source.bottom);
}
+void HWDeviceDRM::SetRotation(LayerTransform transform, const HWRotatorMode &mode,
+ uint32_t* rot_bit_mask) {
+ // In offline rotation case, rotator will handle flips set via offline rotator interface.
+ if (mode == kRotatorOffline) {
+ *rot_bit_mask = 0;
+ return;
+ }
+
+ // In no rotation case or inline rotation case, plane will handle flips
+ // In DRM framework rotation is applied in counter-clockwise direction.
+ if (transform.rotation == 90) {
+ // a) rotate 90 clockwise = rotate 270 counter-clockwise in DRM
+ // rotate 270 is translated as hflip + vflip + rotate90
+ // b) rotate 270 clockwise = rotate 90 counter-clockwise in DRM
+ // c) hflip + rotate 90 clockwise = vflip + rotate 90 counter-clockwise in DRM
+ // d) vflip + rotate 90 clockwise = hflip + rotate 90 counter-clockwise in DRM
+ *rot_bit_mask = UINT32(DRMRotation::ROT_90);
+ transform.flip_horizontal = !transform.flip_horizontal;
+ transform.flip_vertical = !transform.flip_vertical;
+ }
+
+ if (transform.flip_horizontal) {
+ *rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
+ }
+
+ if (transform.flip_vertical) {
+ *rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
+ }
+}
+
bool HWDeviceDRM::EnableHotPlugDetection(int enable) {
return true;
}
@@ -1104,6 +1151,11 @@
return kErrorNone;
}
+void HWDeviceDRM::GetDRMDisplayToken(sde_drm::DRMDisplayToken *token) const {
+ token->conn_id = token_.conn_id;
+ token->crtc_id = token_.crtc_id;
+}
+
void HWDeviceDRM::UpdateMixerAttributes() {
mixer_attributes_.width = display_attributes_.x_pixels;
mixer_attributes_.height = display_attributes_.y_pixels;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index ad7a3e3..bbdd69d 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -54,6 +54,7 @@
virtual ~HWDeviceDRM() {}
virtual DisplayError Init();
virtual DisplayError Deinit();
+ void GetDRMDisplayToken(sde_drm::DRMDisplayToken *token) const;
protected:
// From HWInterface
@@ -94,6 +95,7 @@
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
virtual void InitializeConfigs();
+ virtual DisplayError DumpDebugData() { return kErrorNone; }
enum {
kHWEventVSync,
@@ -119,6 +121,7 @@
void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
+ void SetRotation(LayerTransform transform, const HWRotatorMode &mode, uint32_t* rot_bit_mask);
DisplayError DefaultCommit(HWLayers *hw_layers);
DisplayError AtomicCommit(HWLayers *hw_layers);
void SetupAtomic(HWLayers *hw_layers, bool validate);
@@ -149,6 +152,7 @@
protected:
const char *device_name_ = {};
bool deferred_initialize_ = false;
+ bool default_mode_ = false;
sde_drm::DRMDisplayType disp_type_ = {};
HWInfoInterface *hw_info_intf_ = {};
BufferSyncHandler *buffer_sync_handler_ = {};
@@ -167,7 +171,6 @@
private:
bool synchronous_commit_ = false;
HWMixerAttributes mixer_attributes_ = {};
- bool default_mode_ = false;
std::string interface_str_ = "DSI";
HWScaleDRM *hw_scale_ = {};
};
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index cea76fc..7487c8a 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -85,6 +85,7 @@
case HWEvent::SHOW_BLANK_EVENT:
case HWEvent::THERMAL_LEVEL:
case HWEvent::IDLE_POWER_COLLAPSE:
+ case HWEvent::PINGPONG_TIMEOUT:
break;
}
}
@@ -139,10 +140,16 @@
}
DisplayError HWEventsDRM::Init(int display_type, HWEventHandler *event_handler,
- const vector<HWEvent> &event_list) {
+ const vector<HWEvent> &event_list,
+ const HWInterface *hw_intf) {
if (!event_handler)
return kErrorParameters;
+ static_cast<const HWDeviceDRM *>(hw_intf)->GetDRMDisplayToken(&token_);
+
+ DLOGI("Setup event handler for display %d, CRTC %d, Connector %d",
+ display_type, token_.crtc_id, token_.conn_id);
+
event_handler_ = event_handler;
poll_fds_.resize(event_list.size());
event_thread_name_ += " - " + std::to_string(display_type);
@@ -264,6 +271,7 @@
case HWEvent::SHOW_BLANK_EVENT:
case HWEvent::THERMAL_LEVEL:
case HWEvent::IDLE_POWER_COLLAPSE:
+ case HWEvent::PINGPONG_TIMEOUT:
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);
diff --git a/sdm/libs/core/drm/hw_events_drm.h b/sdm/libs/core/drm/hw_events_drm.h
index 41050c7..206751b 100644
--- a/sdm/libs/core/drm/hw_events_drm.h
+++ b/sdm/libs/core/drm/hw_events_drm.h
@@ -30,6 +30,7 @@
#ifndef __HW_EVENTS_DRM_H__
#define __HW_EVENTS_DRM_H__
+#include <drm_interface.h>
#include <sys/poll.h>
#include <map>
#include <string>
@@ -38,6 +39,7 @@
#include "hw_events_interface.h"
#include "hw_interface.h"
+#include "hw_device_drm.h"
namespace sdm {
@@ -46,7 +48,8 @@
class HWEventsDRM : public HWEventsInterface {
public:
virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
- const vector<HWEvent> &event_list);
+ const vector<HWEvent> &event_list,
+ const HWInterface *hw_intf);
virtual DisplayError Deinit();
virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr);
@@ -87,6 +90,7 @@
bool exit_threads_ = false;
uint32_t vsync_index_ = 0;
bool vsync_enabled_ = true;
+ sde_drm::DRMDisplayToken token_ = {};
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_hdmi_drm.cpp b/sdm/libs/core/drm/hw_hdmi_drm.cpp
new file mode 100644
index 0000000..27419c7
--- /dev/null
+++ b/sdm/libs/core/drm/hw_hdmi_drm.cpp
@@ -0,0 +1,163 @@
+/*
+* 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_lib_loader.h>
+#include <drm_master.h>
+#include <drm_res_mgr.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <utils/debug.h>
+#include <utils/sys.h>
+#include <utils/formats.h>
+
+#include <vector>
+#include <map>
+#include <utility>
+
+#include "hw_hdmi_drm.h"
+
+#define __CLASS__ "HWHDMIDRM"
+
+using drm_utils::DRMMaster;
+using drm_utils::DRMResMgr;
+using drm_utils::DRMLibLoader;
+using drm_utils::DRMBuffer;
+using sde_drm::GetDRMManager;
+using sde_drm::DestroyDRMManager;
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMDisplayToken;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMPPFeatureInfo;
+using sde_drm::DRMOps;
+using sde_drm::DRMTopology;
+
+namespace sdm {
+
+HWHDMIDRM::HWHDMIDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ HWInfoInterface *hw_info_intf)
+ : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf),
+ active_config_index_(0) {
+ HWDeviceDRM::device_type_ = kDeviceHDMI;
+ HWDeviceDRM::device_name_ = "HDMI Display Device";
+}
+
+// TODO(user) : split function in base class and avoid code duplicacy
+// by using base implementation for this basic stuff
+DisplayError HWHDMIDRM::Init() {
+ DisplayError error = kErrorNone;
+
+ default_mode_ = (DRMLibLoader::GetInstance()->IsLoaded() == false);
+
+ if (!default_mode_) {
+ DRMMaster *drm_master = {};
+ int dev_fd = -1;
+ DRMMaster::GetInstance(&drm_master);
+ drm_master->GetHandle(&dev_fd);
+ DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
+ if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::TV, &token_)) {
+ DLOGE("RegisterDisplay failed");
+ return kErrorResources;
+ }
+
+ drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
+ drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+ InitializeConfigs();
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, ¤t_mode_);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+
+ if (drm_atomic_intf_->Commit(true /* synchronous */)) {
+ DLOGE("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id, token_.conn_id,
+ device_name_);
+ return kErrorResources;
+ }
+
+ // Reload connector info for updated info after 1st commit
+ drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+ DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
+ }
+
+ PopulateDisplayAttributes();
+ PopulateHWPanelInfo();
+ UpdateMixerAttributes();
+
+ return error;
+}
+
+DisplayError HWHDMIDRM::GetNumDisplayAttributes(uint32_t *count) {
+ *count = connector_info_.num_modes;
+ if (*count <= 0) {
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMIDRM::GetActiveConfig(uint32_t *active_config_index) {
+ *active_config_index = active_config_index_;
+ return kErrorNone;
+}
+
+DisplayError HWHDMIDRM::SetDisplayAttributes(uint32_t index) {
+ DTRACE_SCOPED();
+
+ if (index >= connector_info_.num_modes) {
+ return kErrorNotSupported;
+ }
+
+ active_config_index_ = index;
+
+ // TODO(user): fix this hard coding
+ frame_rate_ = 60;
+
+ // Get the display attributes for current active config index
+ GetDisplayAttributes(active_config_index_, &display_attributes_);
+ UpdateMixerAttributes();
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMIDRM::GetConfigIndex(uint32_t mode, uint32_t *index) {
+ *index = mode;
+
+ return kErrorNone;
+}
+
+DisplayError HWHDMIDRM::Validate(HWLayers *hw_layers) {
+ HWDeviceDRM::ResetDisplayParams();
+
+ return HWDeviceDRM::Validate(hw_layers);
+}
+
+DisplayError HWHDMIDRM::Commit(HWLayers *hw_layers) {
+ return HWDeviceDRM::Commit(hw_layers);
+}
+
+} // namespace sdm
+
diff --git a/sdm/libs/core/drm/hw_hdmi_drm.h b/sdm/libs/core/drm/hw_hdmi_drm.h
new file mode 100644
index 0000000..7e11e5e
--- /dev/null
+++ b/sdm/libs/core/drm/hw_hdmi_drm.h
@@ -0,0 +1,60 @@
+/*
+* 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_HDMI_DRM_H__
+#define __HW_HDMI_DRM_H__
+
+#include <map>
+#include <vector>
+
+#include "hw_device_drm.h"
+
+namespace sdm {
+
+using std::vector;
+
+class HWHDMIDRM : public HWDeviceDRM {
+ public:
+ explicit HWHDMIDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ HWInfoInterface *hw_info_intf);
+
+ protected:
+ virtual DisplayError Init();
+ virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+ // Requirement to call this only after the first config has been explicitly set by client
+ virtual DisplayError GetActiveConfig(uint32_t *active_config);
+ virtual DisplayError SetDisplayAttributes(uint32_t index);
+ virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError Commit(HWLayers *hw_layers);
+
+ private:
+ uint32_t active_config_index_;
+ uint32_t frame_rate_ = 0;
+};
+
+} // namespace sdm
+
+#endif // __HW_HDMI_DRM_H__
+
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 6258d73..8843924 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -332,6 +332,7 @@
hw_resource->max_scale_up = info.max_upscale;
hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1;
hw_resource->max_pipe_bw = info.max_pipe_bandwidth / kKiloUnit;
+ hw_resource->cache_size = info.cache_size;
}
void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
@@ -412,8 +413,7 @@
case SDE_PIX_FMT_RGBX_1010102_UBWC: *sdm_format = kFormatRGBX1010102Ubwc; break;
case SDE_PIX_FMT_Y_CBCR_H2V2_P010: *sdm_format = kFormatYCbCr420P010; break;
case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC: *sdm_format = kFormatYCbCr420TP10Ubwc; break;
- /* TODO(user) : enable when defined in uapi
- case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc; break; */
+ case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc; break;
default: *sdm_format = kFormatInvalid;
}
}
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 5fe1d86..dc2f06f 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -41,7 +41,7 @@
using sde_drm::DRMConnectorInfo;
using sde_drm::DRMRect;
using sde_drm::DRMOps;
-
+using sde_drm::DRMPowerMode;
namespace sdm {
HWVirtualDRM::HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
@@ -146,7 +146,6 @@
return kErrorNone;
}
-
DisplayError HWVirtualDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
if (display_attributes.x_pixels == 0 || display_attributes.y_pixels == 0) {
return kErrorParameters;
@@ -165,6 +164,18 @@
return kErrorNone;
}
+DisplayError HWVirtualDRM::PowerOn() {
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
+ return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::PowerOff() {
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+ return kErrorNone;
+}
+
DisplayError HWVirtualDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
return kErrorNone;
}
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
index b63519a..afa5c71 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.h
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -55,6 +55,8 @@
virtual DisplayError Commit(HWLayers *hw_layers);
virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+ virtual DisplayError PowerOn();
+ virtual DisplayError PowerOff();
void ConfigureWbConnectorFbId(uint32_t fb_id);
void ConfigureWbConnectorDestRect();
void DumpConfigs();
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 773845b..ff19753 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -1141,8 +1141,8 @@
async_layer.pipe_ndx = left_pipe->pipe_id;
async_layer.src.x = UINT32(left_pipe->src_roi.left);
async_layer.src.y = UINT32(left_pipe->src_roi.top);
- async_layer.dst.x = UINT32(x);
- async_layer.dst.y = UINT32(y);
+ async_layer.dst.x = UINT32(left_pipe->dst_roi.left);
+ async_layer.dst.y = UINT32(left_pipe->dst_roi.top);
mdp_position_update pos_update = {};
pos_update.input_layer_cnt = 1;
@@ -1359,5 +1359,33 @@
return kErrorNone;
}
+DisplayError HWDevice::DumpDebugData() {
+ DLOGW("Pingpong timeout occurred in the driver.");
+#ifdef USER_DEBUG
+ // Save the xlogs on ping pong time out
+ std::ofstream dst("/data/vendor/display/mdp_xlog");
+ dst << "+++ MDP:XLOG +++" << std::endl;
+ std::ifstream src("/sys/kernel/debug/mdp/xlog/dump");
+ dst << src.rdbuf() << std::endl;
+ src.close();
+
+ dst << "+++ MDP:REG_XLOG +++" << std::endl;
+ src.open("/sys/kernel/debug/mdp/xlog/reg_xlog");
+ dst << src.rdbuf() << std::endl;
+ src.close();
+
+ dst << "+++ MDP:DBGBUS_XLOG +++" << std::endl;
+ src.open("/sys/kernel/debug/mdp/xlog/dbgbus_xlog");
+ dst << src.rdbuf() << std::endl;
+ src.close();
+
+ dst << "+++ MDP:VBIF_DBGBUS_XLOG +++" << std::endl;
+ src.open("/sys/kernel/debug/mdp/xlog/vbif_dbgbus_xlog");
+ dst << src.rdbuf() << std::endl;
+ src.close();
+#endif
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index 2eea87b..2c0593a 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -97,6 +97,7 @@
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+ virtual DisplayError DumpDebugData();
enum {
kHWEventVSync,
diff --git a/sdm/libs/core/fb/hw_events.cpp b/sdm/libs/core/fb/hw_events.cpp
index c0467f9..d944624 100644
--- a/sdm/libs/core/fb/hw_events.cpp
+++ b/sdm/libs/core/fb/hw_events.cpp
@@ -104,6 +104,9 @@
case HWEvent::IDLE_POWER_COLLAPSE:
event_data->event_parser = &HWEvents::HandleIdlePowerCollapse;
break;
+ case HWEvent::PINGPONG_TIMEOUT:
+ event_data->event_parser = &HWEvents::HandlePingPongTimeout;
+ break;
default:
error = kErrorParameters;
break;
@@ -123,7 +126,8 @@
}
DisplayError HWEvents::Init(int fb_num, HWEventHandler *event_handler,
- const vector<HWEvent> &event_list) {
+ const vector<HWEvent> &event_list,
+ const HWInterface *hw_intf) {
if (!event_handler)
return kErrorParameters;
@@ -132,10 +136,14 @@
event_list_ = event_list;
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"},
- {HWEvent::IDLE_POWER_COLLAPSE, "idle_power_collapse"}};
+ 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"},
+ {HWEvent::IDLE_POWER_COLLAPSE, "idle_power_collapse"},
+ {HWEvent::PINGPONG_TIMEOUT, "pingpong_timeout"}};
PopulateHWEventData();
@@ -223,6 +231,10 @@
event_handler_->IdleTimeout();
}
+void HWEvents::HandlePingPongTimeout(char *data) {
+ event_handler_->PingPongTimeout();
+}
+
void HWEvents::HandleThermal(char *data) {
int64_t thermal_level = 0;
if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
diff --git a/sdm/libs/core/fb/hw_events.h b/sdm/libs/core/fb/hw_events.h
index 3d9cec8..8ffd6d5 100644
--- a/sdm/libs/core/fb/hw_events.h
+++ b/sdm/libs/core/fb/hw_events.h
@@ -42,7 +42,8 @@
class HWEvents : public HWEventsInterface {
public:
virtual DisplayError Init(int fb_num, HWEventHandler *event_handler,
- const vector<HWEvent> &event_list);
+ const vector<HWEvent> &event_list,
+ const HWInterface *hw_intf);
virtual DisplayError Deinit();
virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) {
return kErrorNotSupported;
@@ -67,6 +68,7 @@
void HandleCECMessage(char *data);
void HandleThreadExit(char *data) { }
void HandleIdlePowerCollapse(char *data);
+ void HandlePingPongTimeout(char *data);
void PopulateHWEventData();
DisplayError SetEventParser(HWEvent event_type, HWEventData *event_data);
pollfd InitializePollFd(HWEventData *event_data);
diff --git a/sdm/libs/core/hw_events_interface.cpp b/sdm/libs/core/hw_events_interface.cpp
index ed62b86..5817cdb 100644
--- a/sdm/libs/core/hw_events_interface.cpp
+++ b/sdm/libs/core/hw_events_interface.cpp
@@ -42,7 +42,7 @@
DisplayError HWEventsInterface::Create(int display_type, HWEventHandler *event_handler,
const std::vector<HWEvent> &event_list,
- HWEventsInterface **intf) {
+ const HWInterface *hw_intf, HWEventsInterface **intf) {
DisplayError error = kErrorNone;
HWEventsInterface *hw_events = nullptr;
if (GetDriverType() == DriverType::FB) {
@@ -53,7 +53,7 @@
#endif
}
- error = hw_events->Init(display_type, event_handler, event_list);
+ error = hw_events->Init(display_type, event_handler, event_list, hw_intf);
if (error != kErrorNone) {
delete hw_events;
} else {
diff --git a/sdm/libs/core/hw_events_interface.h b/sdm/libs/core/hw_events_interface.h
index 482e077..090ff71 100644
--- a/sdm/libs/core/hw_events_interface.h
+++ b/sdm/libs/core/hw_events_interface.h
@@ -33,6 +33,7 @@
namespace sdm {
class HWEventHandler;
+class HWInterface;
enum HWEvent {
VSYNC = 0,
@@ -42,17 +43,20 @@
SHOW_BLANK_EVENT,
THERMAL_LEVEL,
IDLE_POWER_COLLAPSE,
+ PINGPONG_TIMEOUT,
};
class HWEventsInterface {
public:
virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
- const std::vector<HWEvent> &event_list) = 0;
+ const std::vector<HWEvent> &event_list,
+ const HWInterface *hw_intf) = 0;
virtual DisplayError Deinit() = 0;
virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) = 0;
static DisplayError Create(int display_type, HWEventHandler *event_handler,
- const std::vector<HWEvent> &event_list, HWEventsInterface **intf);
+ const std::vector<HWEvent> &event_list,
+ const HWInterface *hw_intf, HWEventsInterface **intf);
static DisplayError Destroy(HWEventsInterface *intf);
protected:
diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp
index a7bcabd..f05aa0c 100644
--- a/sdm/libs/core/hw_interface.cpp
+++ b/sdm/libs/core/hw_interface.cpp
@@ -38,6 +38,7 @@
#ifdef COMPILE_DRM
#include "drm/hw_device_drm.h"
#include "drm/hw_virtual_drm.h"
+#include "drm/hw_hdmi_drm.h"
#endif
#define __CLASS__ "HWInterface"
@@ -65,7 +66,9 @@
if (driver_type == DriverType::FB) {
hw = new HWHDMI(buffer_sync_handler, hw_info_intf);
} else {
- return kErrorNotSupported;
+#ifdef COMPILE_DRM
+ hw = new HWHDMIDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+#endif
}
break;
case kVirtual:
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 5dbeb11..616e3fb 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -61,6 +61,7 @@
virtual void ThermalEvent(int64_t thermal_level) = 0;
virtual void CECMessage(char *message) = 0;
virtual void IdlePowerCollapse() = 0;
+ virtual void PingPongTimeout() = 0;
protected:
virtual ~HWEventHandler() { }
@@ -110,6 +111,7 @@
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
+ virtual DisplayError DumpDebugData() = 0;
protected:
virtual ~HWInterface() { }
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 2d74941..8e89784 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -923,8 +923,9 @@
return kErrorNone;
}
-DisplayError ResourceDefault::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
- int x, int y) {
+DisplayError ResourceDefault::ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers,
+ int x, int y,
+ DisplayConfigVariableInfo *fb_config) {
return kErrorNotSupported;
}
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index f835410..76d19f3 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -60,7 +60,8 @@
virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90,
BufferLayout layout, bool use_rotator_downscale);
DisplayError ValidateCursorConfig(Handle display_ctx, const Layer *layer, bool is_top);
- DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
+ DisplayError ValidateAndSetCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y,
+ DisplayConfigVariableInfo *fb_config);
DisplayError SetMaxBandwidthMode(HWBwModes mode);
virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
const DisplayDetailEnhancerData &de_data);
diff --git a/sdm/libs/hwc/hwc_color_manager.h b/sdm/libs/hwc/hwc_color_manager.h
index 0f4247d..20d2b39 100644
--- a/sdm/libs/hwc/hwc_color_manager.h
+++ b/sdm/libs/hwc/hwc_color_manager.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -42,7 +42,7 @@
// This macro defines name for display APIs interface wrapper library.
// This macro shall be used to load library using dlopen().
-#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-apis.so"
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-vndapis.so"
// This macro defines variable name of display color APIs function tables
// This macro shall be used to specify name of the variable in dlsym().
diff --git a/sdm/libs/hwc/hwc_debugger.cpp b/sdm/libs/hwc/hwc_debugger.cpp
index 0cc0501..ffbb5c5 100644
--- a/sdm/libs/hwc/hwc_debugger.cpp
+++ b/sdm/libs/hwc/hwc_debugger.cpp
@@ -98,6 +98,16 @@
}
}
+void HWCDebugHandler::DebugScalar(bool enable, int verbose_level) {
+ if (enable) {
+ debug_flags_[kTagScalar] = 1;
+ verbose_level_ = verbose_level;
+ } else {
+ debug_flags_[kTagScalar] = 0;
+ verbose_level_ = 0;
+ }
+}
+
void HWCDebugHandler::DebugQdcm(bool enable, int verbose_level) {
if (enable) {
debug_flags_[kTagQDCM] = 1;
diff --git a/sdm/libs/hwc/hwc_debugger.h b/sdm/libs/hwc/hwc_debugger.h
index 01319ab..82ff2f2 100644
--- a/sdm/libs/hwc/hwc_debugger.h
+++ b/sdm/libs/hwc/hwc_debugger.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
@@ -43,6 +43,7 @@
class HWCDebugHandler : public DebugHandler {
public:
static inline DebugHandler* Get() { return &debug_handler_; }
+ static const char* DumpDir() { return "/data/vendor/display"; }
static void DebugAll(bool enable, int verbose_level);
static void DebugResources(bool enable, int verbose_level);
@@ -50,6 +51,7 @@
static void DebugCompManager(bool enable, int verbose_level);
static void DebugDriverConfig(bool enable, int verbose_level);
static void DebugRotator(bool enable, int verbose_level);
+ static void DebugScalar(bool enable, int verbose_level);
static void DebugQdcm(bool enable, int verbose_level);
static int GetIdleTimeoutMs();
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 557b55f..9f1f3c7 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -19,14 +19,15 @@
LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \
libutils libcutils libsync libqdutils libqdMetaData libdl \
- libpowermanager libsdmutils libc++ liblog libgrallocutils \
- libui libgpu_tonemapper
+ libsdmutils libc++ liblog libgrallocutils libui libgpu_tonemapper \
+ libhidlbase libhidltransport vendor.display.config@1.0
ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_SHARED_LIBRARIES += libmemalloc
endif
LOCAL_SRC_FILES := hwc_session.cpp \
+ hwc_session_services.cpp \
hwc_display.cpp \
hwc_display_primary.cpp \
hwc_display_external.cpp \
@@ -38,7 +39,8 @@
hwc_callbacks.cpp \
../hwc/cpuhint.cpp \
../hwc/hwc_socket_handler.cpp \
- hwc_tonemapper.cpp
+ hwc_tonemapper.cpp \
+ display_null.cpp
ifneq ($(TARGET_USES_GRALLOC1), true)
LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
new file mode 100644
index 0000000..16f4da6
--- /dev/null
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -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.
+*/
+
+#include "display_null.h"
+
+#define __CLASS__ "DisplayNull"
+
+namespace sdm {
+
+DisplayError DisplayNull::Commit(LayerStack *layer_stack) {
+ for (Layer *layer : layer_stack->layers) {
+ if (layer->composition != kCompositionGPUTarget) {
+ layer->composition = kCompositionSDE;
+ layer->input_buffer.release_fence_fd = -1;
+ }
+ }
+ layer_stack->retire_fence_fd = -1;
+
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetDisplayState(DisplayState *state) {
+ *state = state_;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+ state_ = state;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+ fb_config_ = variable_info;
+ return kErrorNone;
+}
+
+DisplayError DisplayNull::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+ *variable_info = fb_config_;
+ return kErrorNone;
+}
+
+} // namespace sdm
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
new file mode 100644
index 0000000..fa88c28
--- /dev/null
+++ b/sdm/libs/hwc2/display_null.h
@@ -0,0 +1,107 @@
+/*
+* 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 __DISPLAY_NULL_H__
+#define __DISPLAY_NULL_H__
+
+#include <core/display_interface.h>
+#include <string>
+#include <vector>
+
+namespace sdm {
+
+#define MAKE_NO_OP(virtual_method_name) \
+ virtual DisplayError virtual_method_name { return kErrorNone; }
+
+class DisplayNull : public DisplayInterface {
+ public:
+ virtual ~DisplayNull() { }
+ virtual DisplayError Commit(LayerStack *layer_stack);
+ virtual DisplayError GetDisplayState(DisplayState *state);
+ virtual DisplayError SetDisplayState(DisplayState state);
+ virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
+ virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
+ virtual bool IsUnderscanSupported() { return true; }
+ virtual void SetIdleTimeoutMs(uint32_t active_ms) { }
+ virtual bool IsPrimaryDisplay() { return true; }
+
+ void SetActive(bool active) {
+ active_ = active;
+ }
+
+ bool IsActive() {
+ return active_;
+ }
+
+ MAKE_NO_OP(Prepare(LayerStack *))
+ MAKE_NO_OP(Flush())
+ MAKE_NO_OP(GetNumVariableInfoConfigs(uint32_t *))
+ MAKE_NO_OP(GetConfig(uint32_t, DisplayConfigVariableInfo *))
+ MAKE_NO_OP(GetConfig(DisplayConfigFixedInfo *))
+ MAKE_NO_OP(GetActiveConfig(uint32_t *))
+ MAKE_NO_OP(GetVSyncState(bool *))
+ MAKE_NO_OP(SetActiveConfig(uint32_t))
+ MAKE_NO_OP(SetActiveConfig(DisplayConfigVariableInfo *))
+ MAKE_NO_OP(SetMaxMixerStages(uint32_t))
+ MAKE_NO_OP(ControlPartialUpdate(bool, uint32_t *))
+ MAKE_NO_OP(DisablePartialUpdateOneFrame())
+ MAKE_NO_OP(SetDisplayMode(uint32_t))
+ MAKE_NO_OP(SetPanelBrightness(int))
+ MAKE_NO_OP(CachePanelBrightness(int))
+ MAKE_NO_OP(OnMinHdcpEncryptionLevelChange(uint32_t))
+ MAKE_NO_OP(ColorSVCRequestRoute(const PPDisplayAPIPayload &, PPDisplayAPIPayload *,
+ PPPendingParams *))
+ MAKE_NO_OP(GetColorModeCount(uint32_t *))
+ MAKE_NO_OP(GetColorModes(uint32_t *, std::vector<std::string> *))
+ MAKE_NO_OP(GetColorModeAttr(const std::string &, AttrVal *))
+ MAKE_NO_OP(SetColorMode(const std::string &))
+ MAKE_NO_OP(SetColorModeById(int32_t))
+ MAKE_NO_OP(SetColorTransform(const uint32_t, const double *))
+ MAKE_NO_OP(GetDefaultColorMode(std::string *))
+ MAKE_NO_OP(ApplyDefaultDisplayMode())
+ MAKE_NO_OP(SetCursorPosition(int, int))
+ MAKE_NO_OP(GetRefreshRateRange(uint32_t *, uint32_t *))
+ MAKE_NO_OP(SetRefreshRate(uint32_t, bool))
+ MAKE_NO_OP(GetPanelBrightness(int *))
+ MAKE_NO_OP(SetVSyncState(bool))
+ MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
+ MAKE_NO_OP(GetMixerResolution(uint32_t *, uint32_t *))
+ MAKE_NO_OP(SetDetailEnhancerData(const DisplayDetailEnhancerData &))
+ MAKE_NO_OP(GetDisplayPort(DisplayPort *))
+ MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
+
+ private:
+ bool active_ = false;
+ DisplayState state_ = kStateOff;
+ DisplayConfigVariableInfo fb_config_ = {};
+};
+
+} // namespace sdm
+
+#endif // __DISPLAY_NULL_H__
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 9f336a0..afa9a4e 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.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
@@ -28,7 +28,6 @@
*/
#include <dlfcn.h>
-#include <powermanager/IPowerManager.h>
#include <cutils/sockets.h>
#include <cutils/native_handle.h>
#include <utils/String16.h>
@@ -272,7 +271,6 @@
PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
if (de_tuning_cfg_data->cfg_pending == true) {
if (!de_tuning_cfg_data->cfg_en) {
- de_data.override_flags = kOverrideDEEnable;
de_data.enable = 0;
} else {
de_data.override_flags = kOverrideDEEnable;
@@ -386,17 +384,6 @@
// retrieve system GPU idle timeout value for later to recover.
mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
-
- // acquire the binder handle to Android system PowerManager for later use.
- android::sp<android::IBinder> binder =
- android::defaultServiceManager()->checkService(android::String16("power"));
- if (binder == NULL) {
- DLOGW("Application can't connect to power manager service");
- delete mode_mgr;
- mode_mgr = NULL;
- } else {
- mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
- }
}
return mode_mgr;
@@ -407,30 +394,6 @@
::close(socket_fd_);
}
-int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
- int ret = 0;
-
- if (enable) {
- if (wakelock_token_ == NULL) {
- android::sp<android::IBinder> binder = new android::BBinder();
- android::status_t status = power_mgr_->acquireWakeLock(
- (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
- android::String16(kTagName), android::String16(kPackageName));
- if (status == android::NO_ERROR) {
- wakelock_token_ = binder;
- }
- }
- } else {
- if (wakelock_token_ != NULL && power_mgr_ != NULL) {
- power_mgr_->releaseWakeLock(wakelock_token_, 0);
- wakelock_token_.clear();
- wakelock_token_ = NULL;
- }
- }
-
- return ret;
-}
-
int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
bool *was_running) {
@@ -486,7 +449,6 @@
ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
&cabl_was_running_);
- ret = AcquireAndroidWakeLock(enable);
// if enter QDCM mode, disable GPU fallback idle timeout.
if (hwc_display) {
diff --git a/sdm/libs/hwc2/hwc_color_manager.h b/sdm/libs/hwc2/hwc_color_manager.h
index 32f7f5f..f88a5bb 100644
--- a/sdm/libs/hwc2/hwc_color_manager.h
+++ b/sdm/libs/hwc2/hwc_color_manager.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,7 +32,6 @@
#include <stdlib.h>
#include <binder/Parcel.h>
-#include <powermanager/IPowerManager.h>
#include <binder/BinderService.h>
#include <core/sdm_types.h>
#include <utils/locker.h>
@@ -41,7 +40,7 @@
// This macro defines name for display APIs interface wrapper library.
// This macro shall be used to load library using dlopen().
-#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-apis.so"
+#define DISPLAY_API_INTERFACE_LIBRARY_NAME "libsdm-disp-vndapis.so"
// This macro defines variable name of display color APIs function tables
// This macro shall be used to specify name of the variable in dlsym().
@@ -94,7 +93,6 @@
bool cabl_was_running_ = false;
int socket_fd_ = -1;
android::sp<android::IBinder> wakelock_token_ = NULL;
- android::sp<android::IPowerManager> power_mgr_ = NULL;
uint32_t entry_timeout_ = 0;
static const char *const kSocketName;
static const char *const kTagName;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 4f623ce..0331464 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1336,7 +1336,8 @@
return;
}
- snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+ snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_%s", HWCDebugHandler::DumpDir(),
+ GetDisplayString());
if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
@@ -1385,7 +1386,8 @@
void HWCDisplay::DumpOutputBuffer(const BufferInfo &buffer_info, void *base, int fence) {
char dir_path[PATH_MAX];
- snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+ snprintf(dir_path, sizeof(dir_path), "%s/frame_dump_%s", HWCDebugHandler::DumpDir(),
+ GetDisplayString());
if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
@@ -1523,7 +1525,7 @@
*y_pixels = display_config.y_pixels;
}
-int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) {
int status = 0;
switch (display_status) {
@@ -1598,6 +1600,7 @@
auto layer = hwc_layer->GetSDMLayer();
layer->composition = kCompositionSDE;
}
+ validated_ = true;
}
void HWCDisplay::MarkLayersForClientComposition() {
@@ -1726,8 +1729,8 @@
return;
}
-int HWCDisplay::SetActiveDisplayConfig(int config) {
- return display_intf_->SetActiveConfig(UINT32(config)) == kErrorNone ? 0 : -1;
+int HWCDisplay::SetActiveDisplayConfig(uint32_t config) {
+ return display_intf_->SetActiveConfig(config) == kErrorNone ? 0 : -1;
}
int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) {
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 1b04c84..b70f160 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -20,6 +20,7 @@
#ifndef __HWC_DISPLAY_H__
#define __HWC_DISPLAY_H__
+#include <sys/stat.h>
#include <QService.h>
#include <core/core_interface.h>
#include <hardware/hwcomposer.h>
@@ -92,6 +93,14 @@
class HWCDisplay : public DisplayEventHandler {
public:
+ enum DisplayStatus {
+ kDisplayStatusInvalid = -1,
+ kDisplayStatusOffline,
+ kDisplayStatusOnline,
+ kDisplayStatusPause,
+ kDisplayStatusResume,
+ };
+
virtual ~HWCDisplay() {}
virtual int Init();
virtual int Deinit();
@@ -106,7 +115,7 @@
virtual HWC2::PowerMode GetLastPowerMode();
virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
- virtual int SetDisplayStatus(uint32_t display_status);
+ virtual int SetDisplayStatus(DisplayStatus display_status);
virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
virtual int Perform(uint32_t operation, ...);
virtual void SetSecureDisplay(bool secure_display_active);
@@ -132,7 +141,7 @@
}
// Display Configurations
- virtual int SetActiveDisplayConfig(int config);
+ virtual int SetActiveDisplayConfig(uint32_t config);
virtual int GetActiveDisplayConfig(uint32_t *config);
virtual int GetDisplayConfigCount(uint32_t *count);
virtual int GetDisplayAttributesForConfig(int config,
@@ -150,6 +159,9 @@
return INT32(status);
}
+ virtual int SetState(bool connected) {
+ return kErrorNotSupported;
+ }
int SetPanelBrightness(int level);
int GetPanelBrightness(int *level);
int ToggleScreenUpdates(bool enable);
@@ -211,13 +223,6 @@
float* out_min_luminance);
protected:
- enum DisplayStatus {
- kDisplayStatusOffline = 0,
- kDisplayStatusOnline,
- kDisplayStatusPause,
- kDisplayStatusResume,
- };
-
// Maximum number of layers supported by display manager.
static const uint32_t kMaxLayerCount = 32;
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index a8f8480..e89451d 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.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
@@ -64,6 +64,7 @@
error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
if (error != kErrorNone) {
+ Destroy(hwc_display_external);
return -EINVAL;
}
@@ -215,4 +216,65 @@
}
}
+int HWCDisplayExternal::SetState(bool connected) {
+ DisplayError error = kErrorNone;
+ DisplayState state = kStateOff;
+ DisplayConfigVariableInfo fb_config = {};
+
+ if (connected) {
+ if (display_null_.IsActive()) {
+ error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+ if (error != kErrorNone) {
+ DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+ error, type_, this, &display_intf_);
+ return -EINVAL;
+ }
+
+ // Restore HDMI attributes when display is reconnected.
+ // This is to ensure that surfaceflinger & sdm are in sync.
+ display_null_.GetFrameBufferConfig(&fb_config);
+ int status = SetFrameBufferResolution(fb_config.x_pixels, fb_config.y_pixels);
+ if (status) {
+ DLOGW("Set frame buffer config failed. Error = %d", error);
+ return -1;
+ }
+
+ display_null_.GetDisplayState(&state);
+ display_intf_->SetDisplayState(state);
+
+ SetVsyncEnabled(HWC2::Vsync::Enable);
+
+ display_null_.SetActive(false);
+ DLOGI("Display is connected successfully.");
+ } else {
+ DLOGI("Display is already connected.");
+ }
+ } else {
+ if (!display_null_.IsActive()) {
+ // Preserve required attributes of HDMI display that surfaceflinger sees.
+ // Restore HDMI attributes when display is reconnected.
+ display_intf_->GetDisplayState(&state);
+ display_null_.SetDisplayState(state);
+
+ error = display_intf_->GetFrameBufferConfig(&fb_config);
+ if (error != kErrorNone) {
+ DLOGW("Get frame buffer config failed. Error = %d", error);
+ return -1;
+ }
+ display_null_.SetFrameBufferConfig(fb_config);
+
+ SetVsyncEnabled(HWC2::Vsync::Disable);
+ core_intf_->DestroyDisplay(display_intf_);
+ display_intf_ = &display_null_;
+
+ display_null_.SetActive(true);
+ DLOGI("Display is disconnected successfully.");
+ } else {
+ DLOGI("Display is already disconnected.");
+ }
+ }
+
+ return 0;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_external.h b/sdm/libs/hwc2/hwc_display_external.h
index 802a77c..7aa84b2 100644
--- a/sdm/libs/hwc2/hwc_display_external.h
+++ b/sdm/libs/hwc2/hwc_display_external.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
@@ -31,6 +31,7 @@
#define __HWC_DISPLAY_EXTERNAL_H__
#include "hwc_display.h"
+#include "display_null.h"
namespace sdm {
@@ -47,6 +48,7 @@
virtual HWC2::Error Validate(uint32_t *out_num_types, uint32_t *out_num_requests);
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual void SetSecureDisplay(bool secure_display_active);
+ virtual int SetState(bool connected);
private:
HWCDisplayExternal(CoreInterface *core_intf, HWCBufferAllocator *buffer_allocator,
@@ -54,6 +56,8 @@
void ApplyScanAdjustment(hwc_rect_t *display_frame);
static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
uint32_t *virtual_width, uint32_t *virtual_height);
+
+ DisplayNull display_null_;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 2fcf2a9..b82a46e 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -521,12 +521,12 @@
GetPanelResolution(&panel_width, &panel_height);
GetFrameBufferResolution(&fb_width, &fb_height);
- if (post_processed_output && (output_buffer_info_.buffer_config.width < panel_width ||
- output_buffer_info_.buffer_config.height < panel_height)) {
+ if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
+ output_buffer_info.buffer_config.height < panel_height)) {
DLOGE("Buffer dimensions should not be less than panel resolution");
return -1;
- } else if (!post_processed_output && (output_buffer_info_.buffer_config.width < fb_width ||
- output_buffer_info_.buffer_config.height < fb_height)) {
+ } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
+ output_buffer_info.buffer_config.height < fb_height)) {
DLOGE("Buffer dimensions should not be less than FB resolution");
return -1;
}
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index f77e9c9..8ac9be6 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -59,15 +59,15 @@
return status;
}
- status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
+ status = hwc_display_virtual->SetConfig(width, height);
if (status) {
- DLOGW("Failed to set power mode on virtual display");
Destroy(hwc_display_virtual);
return status;
}
- status = hwc_display_virtual->SetConfig(width, height);
+ status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
if (status) {
+ DLOGW("Failed to set power mode on virtual display");
Destroy(hwc_display_virtual);
return status;
}
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index d9857ce..015dc75 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -278,6 +278,17 @@
layer_->transform = layer_transform_;
}
+HWC2::Error HWCLayer::SetCursorPosition(int32_t x, int32_t y) {
+ hwc_rect_t frame = {};
+ frame.left = x;
+ frame.top = y;
+ frame.right = x + INT(layer_->dst_rect.right - layer_->dst_rect.left);
+ frame.bottom = y + INT(layer_->dst_rect.bottom - layer_->dst_rect.top);
+ SetLayerDisplayFrame(frame);
+
+ return HWC2::Error::None;
+}
+
HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
// Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha));
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 82bf466..b42699d 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -69,6 +69,7 @@
HWC2::Error SetLayerCompositionType(HWC2::Composition type);
HWC2::Error SetLayerDataspace(int32_t dataspace);
HWC2::Error SetLayerDisplayFrame(hwc_rect_t frame);
+ HWC2::Error SetCursorPosition(int32_t x, int32_t y);
HWC2::Error SetLayerPlaneAlpha(float alpha);
HWC2::Error SetLayerSourceCrop(hwc_frect_t crop);
HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage);
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 2bf7d4d..87eb56b 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -47,6 +47,7 @@
#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
+#define HWC_UEVENT_DRM_EXT_HOTPLUG "mdss_mdp/drm/card"
static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
@@ -93,9 +94,9 @@
return -EINVAL;
}
- buffer_allocator_ = new HWCBufferAllocator();
+ StartServices();
- DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_,
+ DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
&buffer_sync_handler_, &socket_handler_,
&core_intf_);
if (error != kErrorNone) {
@@ -103,20 +104,31 @@
return -EINVAL;
}
- // Read which display is first, and create it and store it in primary slot
- // TODO(user): This will need to be redone for HWC2 - right now we validate only
- // the primary physical path
- HWDisplayInterfaceInfo hw_disp_info;
+ // If HDMI display is primary display, defer display creation until hotplug event is received.
+ HWDisplayInterfaceInfo hw_disp_info = {};
error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
- if (error == kErrorNone && hw_disp_info.type == kHDMI && hw_disp_info.is_connected) {
- // HDMI is primary display. If already connected, then create it and store in
- // primary display slot. If not connected, create a NULL display for now.
- status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_,
- &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ if (error != kErrorNone) {
+ CoreInterface::DestroyCore();
+ DLOGE("Primary display type not recognized. Error = %d", error);
+ return -EINVAL;
+ }
+
+ if (hw_disp_info.type == kHDMI) {
+ status = 0;
+ hdmi_is_primary_ = true;
+ // Create display if it is connected, else wait for hotplug connect event.
+ if (hw_disp_info.is_connected) {
+ status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_,
+ &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ }
} else {
// Create and power on primary display
- status = HWCDisplayPrimary::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_,
+ status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_,
&hwc_display_[HWC_DISPLAY_PRIMARY]);
+ color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
+ if (!color_mgr_) {
+ DLOGW("Failed to load HWCColorManager.");
+ }
}
if (status) {
@@ -124,19 +136,6 @@
return status;
}
- color_mgr_ = HWCColorManager::CreateColorManager(buffer_allocator_);
- if (!color_mgr_) {
- DLOGW("Failed to load HWCColorManager.");
- }
-
- if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
- DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
- HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
- hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
- CoreInterface::DestroyCore();
- return -errno;
- }
-
struct rlimit fd_limit = {};
getrlimit(RLIMIT_NOFILE, &fd_limit);
fd_limit.rlim_cur = fd_limit.rlim_cur * 2;
@@ -146,31 +145,38 @@
DLOGW("Unable to increase fd limit - err:%d, %s", errno, strerror(errno));
}
}
+
+ std::thread uevent_thread(HWCUeventThread, this);
+ uevent_thread_.swap(uevent_thread);
+
return 0;
}
int HWCSession::Deinit() {
- HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
- hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
+ HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+ if (primary_display) {
+ if (hdmi_is_primary_) {
+ HWCDisplayExternal::Destroy(primary_display);
+ } else {
+ HWCDisplayPrimary::Destroy(primary_display);
+ }
+ }
+ hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr;
+
if (color_mgr_) {
color_mgr_->DestroyColorManager();
}
- uevent_thread_exit_ = true;
+
DLOGD("Terminating uevent thread");
- // TODO(user): on restarting HWC in the same process, the uevent thread does not restart
- // cleanly.
- Sys::pthread_cancel_(uevent_thread_);
+ uevent_thread_exit_ = true;
+ // todo(user): add a local event to interrupt thread execution and join.
+ uevent_thread_.detach();
DisplayError error = CoreInterface::DestroyCore();
if (error != kErrorNone) {
DLOGE("Display core de-initialization failed. Error = %d", error);
}
- if (buffer_allocator_ != nullptr) {
- delete buffer_allocator_;
- }
- buffer_allocator_ = nullptr;
-
return 0;
}
@@ -433,8 +439,13 @@
auto desc = static_cast<HWC2::Callback>(descriptor);
auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
DLOGD("Registering callback: %s", to_string(desc).c_str());
- if (descriptor == HWC2_CALLBACK_HOTPLUG)
- hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
+ if (descriptor == HWC2_CALLBACK_HOTPLUG) {
+ // If primary display (HDMI) is not created yet, wait for it to be hotplugged.
+ if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
+ }
+ }
+
return INT32(error);
}
@@ -468,8 +479,14 @@
static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
int32_t x, int32_t y) {
- return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition, layer, x,
- y);
+ auto status = INT32(HWC2::Error::None);
+ status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition,
+ layer, x, y);
+ if (status == INT32(HWC2::Error::None)) {
+ // Update cursor position
+ HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y);
+ }
+ return status;
}
static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
@@ -716,7 +733,7 @@
if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
return HWC2::Error::NoResources;
}
- auto status = HWCDisplayVirtual::Create(core_intf_, buffer_allocator_, &callbacks_, width,
+ auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, width,
height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]);
// TODO(user): validate width and height support
if (status)
@@ -735,7 +752,7 @@
hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
if (disp == HWC_DISPLAY_EXTERNAL) {
- status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, primary_width,
+ status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, primary_width,
primary_height, qservice_, false, &hwc_display_[disp]);
} else {
DLOGE("Invalid display type");
@@ -769,8 +786,6 @@
// Qclient methods
android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
- SEQUENCE_WAIT_SCOPE_LOCK(locker_);
-
android::status_t status = 0;
switch (command) {
@@ -779,14 +794,11 @@
break;
case qService::IQService::SCREEN_REFRESH:
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ refreshScreen();
break;
case qService::IQService::SET_IDLE_TIMEOUT:
- if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
- uint32_t timeout = UINT32(input_parcel->readInt32());
- hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
- }
+ setIdleTimeout(UINT32(input_parcel->readInt32()));
break;
case qService::IQService::SET_FRAME_DUMP_CONFIG:
@@ -801,8 +813,13 @@
status = SetDisplayMode(input_parcel);
break;
- case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
- status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
+ case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
+ int disp_id = INT(input_parcel->readInt32());
+ HWCDisplay::DisplayStatus disp_status =
+ static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
+ status = SetSecondaryDisplayStatus(disp_id, disp_status);
+ output_parcel->writeInt32(status);
+ }
break;
case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
@@ -812,56 +829,89 @@
case qService::IQService::SET_VIEW_FRAME:
break;
- case qService::IQService::TOGGLE_SCREEN_UPDATES:
- status = ToggleScreenUpdates(input_parcel, output_parcel);
+ case qService::IQService::TOGGLE_SCREEN_UPDATES: {
+ int32_t input = input_parcel->readInt32();
+ status = toggleScreenUpdate(input == 1);
+ output_parcel->writeInt32(status);
+ }
break;
case qService::IQService::QDCM_SVC_CMDS:
status = QdcmCMDHandler(input_parcel, output_parcel);
break;
- case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
- status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
+ case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t min_enc_level = UINT32(input_parcel->readInt32());
+ status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
+ output_parcel->writeInt32(status);
+ }
break;
- case qService::IQService::CONTROL_PARTIAL_UPDATE:
- status = ControlPartialUpdate(input_parcel, output_parcel);
+ case qService::IQService::CONTROL_PARTIAL_UPDATE: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t enable = UINT32(input_parcel->readInt32());
+ status = ControlPartialUpdate(disp_id, enable == 1);
+ output_parcel->writeInt32(status);
+ }
break;
- case qService::IQService::SET_ACTIVE_CONFIG:
- status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
+ case qService::IQService::SET_ACTIVE_CONFIG: {
+ uint32_t config = UINT32(input_parcel->readInt32());
+ int disp_id = input_parcel->readInt32();
+ status = SetActiveConfigIndex(disp_id, config);
+ }
break;
- case qService::IQService::GET_ACTIVE_CONFIG:
- status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
+ case qService::IQService::GET_ACTIVE_CONFIG: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t config = 0;
+ status = GetActiveConfigIndex(disp_id, &config);
+ output_parcel->writeInt32(INT(config));
+ }
break;
- case qService::IQService::GET_CONFIG_COUNT:
- status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
+ case qService::IQService::GET_CONFIG_COUNT: {
+ int disp_id = input_parcel->readInt32();
+ uint32_t count = 0;
+ status = GetConfigCount(disp_id, &count);
+ output_parcel->writeInt32(INT(count));
+ }
break;
case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
break;
- case qService::IQService::GET_PANEL_BRIGHTNESS:
- status = GetPanelBrightness(input_parcel, output_parcel);
+ case qService::IQService::GET_PANEL_BRIGHTNESS: {
+ int level = 0;
+ status = GetPanelBrightness(&level);
+ output_parcel->writeInt32(level);
+ }
break;
- case qService::IQService::SET_PANEL_BRIGHTNESS:
- status = SetPanelBrightness(input_parcel, output_parcel);
+ case qService::IQService::SET_PANEL_BRIGHTNESS: {
+ uint32_t level = UINT32(input_parcel->readInt32());
+ status = setPanelBrightness(level);
+ output_parcel->writeInt32(status);
+ }
break;
case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
status = GetVisibleDisplayRect(input_parcel, output_parcel);
break;
- case qService::IQService::SET_CAMERA_STATUS:
- status = SetDynamicBWForCamera(input_parcel, output_parcel);
+ case qService::IQService::SET_CAMERA_STATUS: {
+ uint32_t camera_status = UINT32(input_parcel->readInt32());
+ status = setCameraLaunchStatus(camera_status);
+ }
break;
- case qService::IQService::GET_BW_TRANSACTION_STATUS:
- status = GetBWTransactionStatus(input_parcel, output_parcel);
+ case qService::IQService::GET_BW_TRANSACTION_STATUS: {
+ bool state = true;
+ status = DisplayBWTransactionPending(&state);
+ output_parcel->writeInt32(state);
+ }
break;
case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
@@ -884,167 +934,11 @@
return status;
}
-android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int input = input_parcel->readInt32();
- int error = android::BAD_VALUE;
-
- if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
- error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
- if (error != 0) {
- DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
- }
- }
- output_parcel->writeInt32(error);
-
- return error;
-}
-
-android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int level = input_parcel->readInt32();
- int error = android::BAD_VALUE;
-
- if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
- error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
- if (error != 0) {
- DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
- }
- }
- output_parcel->writeInt32(error);
-
- return error;
-}
-
-android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int error = android::BAD_VALUE;
- int ret = error;
-
- if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
- error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
- if (error != 0) {
- ret = error;
- DLOGE("Failed to get the panel brightness. Error = %d", error);
- }
- }
- output_parcel->writeInt32(ret);
-
- return error;
-}
-
-android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
- android::Parcel *out) {
- DisplayError error = kErrorNone;
- int ret = 0;
- uint32_t disp_id = UINT32(input_parcel->readInt32());
- uint32_t enable = UINT32(input_parcel->readInt32());
-
- if (disp_id != HWC_DISPLAY_PRIMARY) {
- DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
- ret = -EINVAL;
- out->writeInt32(ret);
- return ret;
- }
-
- if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
- DLOGE("primary display object is not instantiated");
- ret = -EINVAL;
- out->writeInt32(ret);
- return ret;
- }
-
- uint32_t pending = 0;
- error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
-
- if (error == kErrorNone) {
- if (!pending) {
- out->writeInt32(ret);
- return ret;
- }
- } else if (error == kErrorNotSupported) {
- out->writeInt32(ret);
- return ret;
- } else {
- ret = -EINVAL;
- out->writeInt32(ret);
- return ret;
- }
-
- // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
-
- // Wait until partial update control is complete
- ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
-
- out->writeInt32(ret);
-
- return ret;
-}
-
-android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int config = input_parcel->readInt32();
- int dpy = input_parcel->readInt32();
- int error = android::BAD_VALUE;
-
- if (dpy > HWC_DISPLAY_VIRTUAL) {
- return android::BAD_VALUE;
- }
-
- if (hwc_display_[dpy]) {
- error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
- if (error == 0) {
- callbacks_.Refresh(0);
- }
- }
-
- return error;
-}
-
-android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int dpy = input_parcel->readInt32();
- int error = android::BAD_VALUE;
-
- if (dpy > HWC_DISPLAY_VIRTUAL) {
- return android::BAD_VALUE;
- }
-
- if (hwc_display_[dpy]) {
- uint32_t config = 0;
- error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
- if (error == 0) {
- output_parcel->writeInt32(INT(config));
- }
- }
-
- return error;
-}
-
-android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int dpy = input_parcel->readInt32();
- int error = android::BAD_VALUE;
-
- if (dpy > HWC_DISPLAY_VIRTUAL) {
- return android::BAD_VALUE;
- }
-
- uint32_t count = 0;
- if (hwc_display_[dpy]) {
- error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
- if (error == 0) {
- output_parcel->writeInt32(INT(count));
- }
- }
-
- return error;
-}
-
android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
*input_parcel,
android::Parcel *output_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
int config = input_parcel->readInt32();
int dpy = input_parcel->readInt32();
int error = android::BAD_VALUE;
@@ -1069,44 +963,24 @@
return error;
}
-android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int ret = -EINVAL;
-
- uint32_t display_id = UINT32(input_parcel->readInt32());
- uint32_t display_status = UINT32(input_parcel->readInt32());
-
- DLOGI("Display = %d, Status = %d", display_id, display_status);
-
- if (display_id >= HWC_NUM_DISPLAY_TYPES) {
- DLOGE("Invalid display_id");
- } else if (display_id == HWC_DISPLAY_PRIMARY) {
- DLOGE("Not supported for this display");
- } else if (!hwc_display_[display_id]) {
- DLOGW("Display is not connected");
- } else {
- ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
- }
-
- output_parcel->writeInt32(ret);
-
- return ret;
-}
-
android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
uint32_t operation = UINT32(input_parcel->readInt32());
+ HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+
switch (operation) {
case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
- return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
- HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+
case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
- return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
- HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+
case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
uint32_t refresh_rate = UINT32(input_parcel->readInt32());
- return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
- HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
+ return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
}
+
default:
DLOGW("Invalid operation %d", operation);
return -EINVAL;
@@ -1116,11 +990,15 @@
}
android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
uint32_t mode = UINT32(input_parcel->readInt32());
return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
}
android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
DisplayError error = kErrorNone;
std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
@@ -1155,42 +1033,9 @@
return 0;
}
-android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- DisplayError error = kErrorNone;
- uint32_t camera_status = UINT32(input_parcel->readInt32());
- HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
-
- // trigger invalidate to apply new bw caps.
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
-
- error = core_intf_->SetMaxBandwidthMode(mode);
- if (error != kErrorNone) {
- return -EINVAL;
- }
-
- new_bw_mode_ = true;
- need_invalidate_ = true;
-
- return 0;
-}
-
-android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- bool state = true;
-
- if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
- if (sync_wait(bw_mode_release_fd_, 0) < 0) {
- DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
- state = false;
- }
- output_parcel->writeInt32(state);
- }
-
- return 0;
-}
-
void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
@@ -1215,6 +1060,8 @@
}
android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
DisplayError error = kErrorNone;
uint32_t dpy = UINT32(input_parcel->readInt32());
@@ -1240,6 +1087,8 @@
}
android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
auto device = static_cast<hwc2_device_t *>(this);
@@ -1260,6 +1109,8 @@
}
void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
int type = input_parcel->readInt32();
bool enable = (input_parcel->readInt32() > 0);
DLOGI("type = %d enable = %d", type, enable);
@@ -1293,6 +1144,10 @@
HWCDebugHandler::DebugQdcm(enable, verbose_level);
break;
+ case qService::IQService::DEBUG_SCALAR:
+ HWCDebugHandler::DebugScalar(enable, verbose_level);
+ break;
+
default:
DLOGW("type = %d is not supported", type);
}
@@ -1300,6 +1155,8 @@
android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
int ret = 0;
int32_t *brightness_value = NULL;
uint32_t display_id(0);
@@ -1391,29 +1248,6 @@
return (ret ? -EINVAL : 0);
}
-android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
- int ret = -EINVAL;
- uint32_t display_id = UINT32(input_parcel->readInt32());
- uint32_t min_enc_level = UINT32(input_parcel->readInt32());
-
- DLOGI("Display %d", display_id);
-
- if (display_id >= HWC_NUM_DISPLAY_TYPES) {
- DLOGE("Invalid display_id");
- } else if (display_id != HWC_DISPLAY_EXTERNAL) {
- DLOGE("Not supported for display");
- } else if (!hwc_display_[display_id]) {
- DLOGW("Display is not connected");
- } else {
- ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
- }
-
- output_parcel->writeInt32(ret);
-
- return ret;
-}
-
void *HWCSession::HWCUeventThread(void *context) {
if (context) {
return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
@@ -1453,6 +1287,8 @@
callbacks_.Refresh(0);
reset_panel_ = true;
}
+ } else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
+ HandleExtHPD(uevent_data, length);
}
}
pthread_exit(0);
@@ -1460,6 +1296,29 @@
return NULL;
}
+void HWCSession::HandleExtHPD(const char *uevent_data, int length) {
+ const char *iterator_str = uevent_data;
+ const char *event_info = "status=";
+ const char *pstr = NULL;
+ while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+ pstr = strstr(iterator_str, event_info);
+ if (pstr != NULL) {
+ break;
+ }
+ iterator_str += strlen(iterator_str) + 1;
+ }
+
+ if (pstr) {
+ bool connected = false;
+ if (strcmp(pstr+strlen(event_info), "connected") == 0) {
+ connected = true;
+ }
+
+ DLOGI("Recived Ext HPD, connected:%d status=%s", connected, pstr+strlen(event_info));
+ HotPlugHandler(connected);
+ }
+}
+
int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
const char *iterator_str = uevent_data;
while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
@@ -1500,34 +1359,35 @@
int HWCSession::HotPlugHandler(bool connected) {
int status = 0;
bool notify_hotplug = false;
- bool hdmi_primary = false;
// To prevent sending events to client while a lock is held, acquire scope locks only within
// below scope so that those get automatically unlocked after the scope ends.
- {
+ do {
SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+ // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger.
+ // if it is already created, but got disconnected/connected again,
+ // just toggle display status and do not notify surfaceflinger.
+ // If HDMI is not primary, create/destroy external display normally.
+ if (hdmi_is_primary_) {
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected);
+ } else {
+ status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_,
+ qservice_, &hwc_display_[HWC_DISPLAY_PRIMARY]);
+ notify_hotplug = true;
+ }
+
+ break;
+ }
+
+ // Primary display must be connected for HDMI as secondary cases.
if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
DLOGE("Primary display is not connected.");
return -1;
}
- HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
- HWCDisplay *external_display = NULL;
-
- if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
- external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
- hdmi_primary = true;
- }
-
- // If primary display connected is a NULL display, then replace it with the external display
if (connected) {
- // If we are in HDMI as primary and the primary display just got plugged in
- if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- DLOGE("HDMI is already connected");
- return -1;
- }
-
// Connect external display if virtual display is not connected.
// Else, defer external display connection and process it when virtual display
// tears down; Do not notify SurfaceFlinger since connection is deferred now.
@@ -1545,39 +1405,28 @@
// Do not return error if external display is not in connected status.
// Due to virtual display concurrency, external display connection might be still pending
// but hdmi got disconnected before pending connection could be processed.
-
- if (hdmi_primary) {
- assert(external_display != NULL);
- uint32_t x_res, y_res;
- external_display->GetFrameBufferResolution(&x_res, &y_res);
- // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
- // for HDMI as primary
- external_display->SetVsyncEnabled(HWC2::Vsync::Disable);
- HWCDisplayExternal::Destroy(external_display);
-
- // In HWC2, primary displays can be hotplugged out
+ if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
+ status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
notify_hotplug = true;
- } else {
- if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
- status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
- notify_hotplug = true;
- }
- external_pending_connect_ = false;
}
+ external_pending_connect_ = false;
+ }
+ } while (0);
+
+ if (connected) {
+ callbacks_.Refresh(0);
+
+ if (!hdmi_is_primary_) {
+ // wait for sufficient time to ensure sufficient resources are available to process new
+ // new display connection.
+ uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
+ usleep(vsync_period * 2 / 1000);
}
}
- if (connected && notify_hotplug) {
- // trigger screen refresh to ensure sufficient resources are available to process new
- // new display connection.
- callbacks_.Refresh(0);
- uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
- usleep(vsync_period * 2 / 1000);
- }
// notify client
- // Handle HDMI as primary here
if (notify_hotplug) {
- callbacks_.Hotplug(HWC_DISPLAY_EXTERNAL,
+ callbacks_.Hotplug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
}
@@ -1601,6 +1450,8 @@
android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
int dpy = input_parcel->readInt32();
if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 7d31a3a..cd9831d 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,8 +20,10 @@
#ifndef __HWC_SESSION_H__
#define __HWC_SESSION_H__
+#include <vendor/display/config/1.0/IDisplayConfig.h>
#include <core/core_interface.h>
#include <utils/locker.h>
+#include <thread>
#include "hwc_callbacks.h"
#include "hwc_layers.h"
@@ -34,7 +36,10 @@
namespace sdm {
-class HWCSession : hwc2_device_t, public qClient::BnQClient {
+using ::vendor::display::config::V1_0::IDisplayConfig;
+using ::android::hardware::Return;
+
+class HWCSession : hwc2_device_t, public IDisplayConfig, public qClient::BnQClient {
public:
struct HWCModuleMethods : public hw_module_methods_t {
HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
@@ -119,11 +124,50 @@
static void *HWCUeventThread(void *context);
void *HWCUeventThreadHandler();
int GetEventValue(const char *uevent_data, int length, const char *event_info);
+ void HandleExtHPD(const char *uevent_data, int length);
int HotPlugHandler(bool connected);
void ResetPanel();
int32_t ConnectDisplay(int disp);
int DisconnectDisplay(int disp);
int GetVsyncPeriod(int disp);
+ int32_t GetConfigCount(int disp_id, uint32_t *count);
+ int32_t GetActiveConfigIndex(int disp_id, uint32_t *config);
+ int32_t SetActiveConfigIndex(int disp_id, uint32_t config);
+ int32_t ControlPartialUpdate(int dpy, bool enable);
+ int32_t DisplayBWTransactionPending(bool *status);
+ int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status);
+ int32_t GetPanelBrightness(int *level);
+ int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level);
+
+ // service methods
+ void StartServices();
+
+ // Methods from ::android::hardware::display::config::V1_0::IDisplayConfig follow.
+ Return<void> isDisplayConnected(IDisplayConfig::DisplayType dpy,
+ isDisplayConnected_cb _hidl_cb) override;
+ Return<int32_t> setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
+ IDisplayConfig::DisplayExternalStatus status) override;
+ Return<int32_t> configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
+ uint32_t refreshRate) override;
+ Return<void> getConfigCount(IDisplayConfig::DisplayType dpy,
+ getConfigCount_cb _hidl_cb) override;
+ Return<void> getActiveConfig(IDisplayConfig::DisplayType dpy,
+ getActiveConfig_cb _hidl_cb) override;
+ Return<int32_t> setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) override;
+ Return<void> getDisplayAttributes(uint32_t configIndex, IDisplayConfig::DisplayType dpy,
+ getDisplayAttributes_cb _hidl_cb) override;
+ Return<int32_t> setPanelBrightness(uint32_t level) override;
+ Return<void> getPanelBrightness(getPanelBrightness_cb _hidl_cb) override;
+ Return<int32_t> minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
+ uint32_t min_enc_level) override;
+ Return<int32_t> refreshScreen() override;
+ Return<int32_t> controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) override;
+ Return<int32_t> toggleScreenUpdate(bool on) override;
+ Return<int32_t> setIdleTimeout(uint32_t value) override;
+ Return<void> getHDRCapabilities(IDisplayConfig::DisplayType dpy,
+ getHDRCapabilities_cb _hidl_cb) override;
+ Return<int32_t> setCameraLaunchStatus(uint32_t on) override;
+ Return<void> displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) override;
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -132,60 +176,37 @@
void SetFrameDumpConfig(const android::Parcel *input_parcel);
android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
android::status_t SetDisplayMode(const android::Parcel *input_parcel);
- android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
- android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
- android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- android::status_t GetPanelBrightness(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- // These functions return the actual display config info as opposed to FB
- android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
-
- android::status_t SetDynamicBWForCamera(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
- android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
- android::Parcel *output_parcel);
android::status_t SetMixerResolution(const android::Parcel *input_parcel);
-
android::status_t SetColorModeOverride(const android::Parcel *input_parcel);
android::status_t SetColorModeById(const android::Parcel *input_parcel);
static Locker locker_;
- CoreInterface *core_intf_ = NULL;
- HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {NULL};
+ CoreInterface *core_intf_ = nullptr;
+ HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
HWCCallbacks callbacks_;
- pthread_t uevent_thread_;
+ std::thread uevent_thread_;
bool uevent_thread_exit_ = false;
const char *uevent_thread_name_ = "HWC_UeventThread";
- HWCBufferAllocator *buffer_allocator_;
+ HWCBufferAllocator buffer_allocator_;
HWCBufferSyncHandler buffer_sync_handler_;
- HWCColorManager *color_mgr_ = NULL;
+ HWCColorManager *color_mgr_ = nullptr;
bool reset_panel_ = false;
bool secure_display_active_ = false;
bool external_pending_connect_ = false;
bool new_bw_mode_ = false;
bool need_invalidate_ = false;
int bw_mode_release_fd_ = -1;
- qService::QService *qservice_ = NULL;
+ qService::QService *qservice_ = nullptr;
HWCSocketHandler socket_handler_;
+ bool hdmi_is_primary_ = false;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
new file mode 100644
index 0000000..4b5374f
--- /dev/null
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -0,0 +1,483 @@
+/*
+* 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 <core/buffer_allocator.h>
+#include <utils/debug.h>
+#include <sync/sync.h>
+#include <profiler.h>
+
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+
+#define __CLASS__ "HWCSession"
+
+namespace sdm {
+
+using ::android::hardware::Void;
+
+void HWCSession::StartServices() {
+ status_t status = IDisplayConfig::registerAsService();
+ if (status != OK) {
+ DLOGW("Could not register IDisplayConfig as service (%d).", status);
+ } else {
+ DLOGI("IDisplayConfig service registration completed.");
+ }
+}
+
+int MapDisplayType(IDisplayConfig::DisplayType dpy) {
+ switch (dpy) {
+ case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
+ return HWC_DISPLAY_PRIMARY;
+
+ case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
+ return HWC_DISPLAY_EXTERNAL;
+
+ case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
+ return HWC_DISPLAY_VIRTUAL;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatus status) {
+ switch (status) {
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE:
+ return HWCDisplay::kDisplayStatusOffline;
+
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE:
+ return HWCDisplay::kDisplayStatusOnline;
+
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE:
+ return HWCDisplay::kDisplayStatusPause;
+
+ case IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME:
+ return HWCDisplay::kDisplayStatusResume;
+
+ default:
+ break;
+ }
+
+ return HWCDisplay::kDisplayStatusInvalid;
+}
+
+// Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
+Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
+ isDisplayConnected_cb _hidl_cb) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ int32_t error = -EINVAL;
+ bool connected = false;
+
+ int disp_id = MapDisplayType(dpy);
+ if (disp_id >= 0) {
+ connected = hwc_display_[disp_id];
+ error = 0;
+ }
+
+ _hidl_cb(error, connected);
+
+ return Void();
+}
+
+int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ DLOGI("Display = %d, Status = %d", disp_id, status);
+
+ if (disp_id == HWC_DISPLAY_PRIMARY) {
+ DLOGE("Not supported for this display");
+ } else if (!hwc_display_[disp_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ return hwc_display_[disp_id]->SetDisplayStatus(status);
+ }
+
+ return -EINVAL;
+}
+
+Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
+ IDisplayConfig::DisplayExternalStatus status) {
+ return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
+}
+
+Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
+ uint32_t refreshRate) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+
+ switch (op) {
+ case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
+
+ case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
+
+ case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
+ return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
+
+ default:
+ DLOGW("Invalid operation %d", op);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (disp_id >= 0 && hwc_display_[disp_id]) {
+ return hwc_display_[disp_id]->GetDisplayConfigCount(count);
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
+ getConfigCount_cb _hidl_cb) {
+ uint32_t count = 0;
+ int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &count);
+
+ _hidl_cb(error, count);
+
+ return Void();
+}
+
+int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (disp_id >= 0 && hwc_display_[disp_id]) {
+ return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy,
+ getActiveConfig_cb _hidl_cb) {
+ uint32_t config = 0;
+ int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &config);
+
+ _hidl_cb(error, config);
+
+ return Void();
+}
+
+int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ int32_t error = -EINVAL;
+ if (hwc_display_[disp_id]) {
+ error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
+ if (!error) {
+ callbacks_.Refresh(0);
+ }
+ }
+
+ return error;
+}
+
+Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) {
+ return SetActiveConfigIndex(MapDisplayType(dpy), config);
+}
+
+Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
+ IDisplayConfig::DisplayType dpy,
+ getDisplayAttributes_cb _hidl_cb) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ int32_t error = -EINVAL;
+ IDisplayConfig::DisplayAttributes display_attributes = {};
+
+ int disp_id = MapDisplayType(dpy);
+ if (disp_id >= 0 && hwc_display_[disp_id]) {
+ DisplayConfigVariableInfo hwc_display_attributes;
+ error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
+ &hwc_display_attributes);
+ if (!error) {
+ display_attributes.vsyncPeriod = hwc_display_attributes.vsync_period_ns;
+ display_attributes.xRes = hwc_display_attributes.x_pixels;
+ display_attributes.yRes = hwc_display_attributes.y_pixels;
+ display_attributes.xDpi = hwc_display_attributes.x_dpi;
+ display_attributes.yDpi = hwc_display_attributes.y_dpi;
+ display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
+ display_attributes.isYuv = hwc_display_attributes.is_yuv;
+ }
+ }
+
+ return Void();
+}
+
+Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ int32_t error = -EINVAL;
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
+ if (error) {
+ DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
+ }
+ }
+
+ return error;
+}
+
+int32_t HWCSession::GetPanelBrightness(int *level) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ int32_t error = -EINVAL;
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(level);
+ if (error) {
+ DLOGE("Failed to get the panel brightness. Error = %d", error);
+ }
+ }
+
+ return error;
+}
+
+Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
+ int level = 0;
+ int32_t error = GetPanelBrightness(&level);
+
+ _hidl_cb(error, static_cast<uint32_t>(level));
+
+ return Void();
+}
+
+int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ DLOGI("Display %d", disp_id);
+
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ if (disp_id != HWC_DISPLAY_EXTERNAL) {
+ DLOGE("Not supported for display");
+ } else if (!hwc_display_[disp_id]) {
+ DLOGW("Display is not connected");
+ } else {
+ return hwc_display_[disp_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
+ }
+
+ return -EINVAL;
+}
+
+Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
+ uint32_t min_enc_level) {
+ return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
+}
+
+Return<int32_t> HWCSession::refreshScreen() {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+
+ return 0;
+}
+
+int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (disp_id < 0) {
+ return -EINVAL;
+ }
+
+ if (disp_id != HWC_DISPLAY_PRIMARY) {
+ DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
+ return -EINVAL;
+ }
+
+ HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
+ if (!hwc_display) {
+ DLOGE("primary display object is not instantiated");
+ return -EINVAL;
+ }
+
+ uint32_t pending = 0;
+ DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
+
+ if (hwc_error == kErrorNone) {
+ if (!pending) {
+ return 0;
+ }
+ } else if (hwc_error == kErrorNotSupported) {
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+
+ // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
+ callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+
+ // Wait until partial update control is complete
+ int32_t error = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
+
+ return error;
+}
+
+Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
+ return ControlPartialUpdate(MapDisplayType(dpy), enable);
+}
+
+Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ int32_t error = -EINVAL;
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
+ if (error) {
+ DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
+ }
+ }
+
+ return error;
+}
+
+Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
+ getHDRCapabilities_cb _hidl_cb) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ int32_t error = -EINVAL;
+ IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
+
+ do {
+ int disp_id = MapDisplayType(dpy);
+ if (disp_id < 0) {
+ DLOGE("Invalid display id = %d", disp_id);
+ break;
+ }
+
+ HWCDisplay *hwc_display = hwc_display_[disp_id];
+ if (!hwc_display) {
+ DLOGE("Display = %d is not connected.", disp_id);
+ break;
+ }
+
+ // query number of hdr types
+ uint32_t out_num_types = 0;
+ if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, nullptr, nullptr, nullptr)
+ != HWC2::Error::None) {
+ break;
+ }
+
+ if (!out_num_types) {
+ error = 0;
+ break;
+ }
+
+ // query hdr caps
+ hdr_caps.supportedHdrTypes.resize(out_num_types);
+
+ float out_max_luminance = 0.0f;
+ float out_max_average_luminance = 0.0f;
+ float out_min_luminance = 0.0f;
+ if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
+ &out_max_luminance, &out_max_average_luminance,
+ &out_min_luminance)
+ == HWC2::Error::None) {
+ error = 0;
+ }
+ } while (false);
+
+ _hidl_cb(error, hdr_caps);
+
+ return Void();
+}
+
+Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
+
+ // trigger invalidate to apply new bw caps.
+ callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+
+ if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
+ return -EINVAL;
+ }
+
+ new_bw_mode_ = true;
+ need_invalidate_ = true;
+
+ return 0;
+}
+
+int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+ if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ if (sync_wait(bw_mode_release_fd_, 0) < 0) {
+ DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
+ *status = false;
+ }
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
+ bool status = true;
+
+ int32_t error = DisplayBWTransactionPending(&status);
+
+ _hidl_cb(error, status);
+
+ return Void();
+}
+
+} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
index 7bda725..3086fb4 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -49,18 +49,57 @@
namespace sdm {
-ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator) :
- buffer_allocator_(buffer_allocator) {
+ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator)
+ : tone_map_task_(*this), buffer_allocator_(buffer_allocator) {
buffer_info_.resize(kNumIntermediateBuffers);
}
ToneMapSession::~ToneMapSession() {
- delete gpu_tone_mapper_;
- gpu_tone_mapper_ = nullptr;
+ tone_map_task_.PerformTask(ToneMapTaskCode::kCodeDestroy, nullptr);
FreeIntermediateBuffers();
buffer_info_.clear();
}
+void ToneMapSession::OnTask(const ToneMapTaskCode &task_code,
+ SyncTask<ToneMapTaskCode>::TaskContext *task_context) {
+ switch (task_code) {
+ case ToneMapTaskCode::kCodeGetInstance: {
+ ToneMapGetInstanceContext *ctx = static_cast<ToneMapGetInstanceContext *>(task_context);
+ Lut3d &lut_3d = ctx->layer->lut_3d;
+ Color10Bit *grid_entries = NULL;
+ int grid_size = 0;
+ if (lut_3d.validGridEntries) {
+ grid_entries = lut_3d.gridEntries;
+ grid_size = INT(lut_3d.gridSize);
+ }
+ gpu_tone_mapper_ = TonemapperFactory_GetInstance(tone_map_config_.type,
+ lut_3d.lutEntries, lut_3d.dim,
+ grid_entries, grid_size,
+ tone_map_config_.secure);
+ }
+ break;
+
+ case ToneMapTaskCode::kCodeBlit: {
+ ToneMapBlitContext *ctx = static_cast<ToneMapBlitContext *>(task_context);
+ uint8_t buffer_index = current_buffer_index_;
+ const void *dst_hnd = reinterpret_cast<const void *>
+ (buffer_info_[buffer_index].private_data);
+ const void *src_hnd = reinterpret_cast<const void *>
+ (ctx->layer->input_buffer.buffer_id);
+ ctx->fence_fd = gpu_tone_mapper_->blit(dst_hnd, src_hnd, ctx->merged_fd);
+ }
+ break;
+
+ case ToneMapTaskCode::kCodeDestroy: {
+ delete gpu_tone_mapper_;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
DisplayError error = kErrorNone;
for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
@@ -180,35 +219,30 @@
}
void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
- int fence_fd = -1;
- int acquire_fd = -1;
- int merged_fd = -1;
+ ToneMapBlitContext ctx = {};
+ ctx.layer = layer;
uint8_t buffer_index = session->current_buffer_index_;
- const private_handle_t *dst_hnd = static_cast<private_handle_t *>
- (session->buffer_info_[buffer_index].private_data);
- const private_handle_t *src_hnd = reinterpret_cast<const private_handle_t *>
- (layer->input_buffer.buffer_id);
+ int &release_fence_fd = session->release_fence_fd_[buffer_index];
// use and close the layer->input_buffer acquire fence fd.
- acquire_fd = layer->input_buffer.acquire_fence_fd;
- buffer_sync_handler_.SyncMerge(session->release_fence_fd_[buffer_index], acquire_fd, &merged_fd);
+ int acquire_fd = layer->input_buffer.acquire_fence_fd;
+ buffer_sync_handler_.SyncMerge(release_fence_fd, acquire_fd, &ctx.merged_fd);
if (acquire_fd >= 0) {
CloseFd(&acquire_fd);
}
- if (session->release_fence_fd_[buffer_index] >= 0) {
- CloseFd(&session->release_fence_fd_[buffer_index]);
+ if (release_fence_fd >= 0) {
+ CloseFd(&release_fence_fd);
}
DTRACE_BEGIN("GPU_TM_BLIT");
- fence_fd = session->gpu_tone_mapper_->blit(reinterpret_cast<const void *>(dst_hnd),
- reinterpret_cast<const void *>(src_hnd), merged_fd);
+ session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeBlit, &ctx);
DTRACE_END();
- DumpToneMapOutput(session, &fence_fd);
- session->UpdateBuffer(fence_fd, &layer->input_buffer);
+ DumpToneMapOutput(session, &ctx.fence_fd);
+ session->UpdateBuffer(ctx.fence_fd, &layer->input_buffer);
}
void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
@@ -265,9 +299,9 @@
size_t result = 0;
char dump_file_name[PATH_MAX];
- snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
- "/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height,
- dump_frame_index_);
+ snprintf(dump_file_name, sizeof(dump_file_name), "%s/frame_dump_primary"
+ "/tonemap_%dx%d_frame%d.raw", HWCDebugHandler::DumpDir(), target_buffer->width,
+ target_buffer->height, dump_frame_index_);
FILE* fp = fopen(dump_file_name, "w+");
if (fp) {
@@ -281,14 +315,6 @@
}
DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
- Color10Bit *grid_entries = NULL;
- int grid_size = 0;
-
- if (layer->lut_3d.validGridEntries) {
- grid_entries = layer->lut_3d.gridEntries;
- grid_size = INT(layer->lut_3d.gridSize);
- }
-
// When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
// the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
// for Tonemapping.
@@ -311,13 +337,15 @@
}
ToneMapSession *session = new ToneMapSession(buffer_allocator_);
+ if (!session) {
+ return kErrorMemory;
+ }
session->SetToneMapConfig(layer);
- session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type,
- layer->lut_3d.lutEntries,
- layer->lut_3d.dim,
- grid_entries, grid_size,
- session->tone_map_config_.secure);
+
+ ToneMapGetInstanceContext ctx;
+ ctx.layer = layer;
+ session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeGetInstance, &ctx);
if (session->gpu_tone_mapper_ == NULL) {
DLOGE("Get Tonemapper failed!");
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
index 8367c3e..e2c8ef4 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.h
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -37,6 +37,7 @@
#include <core/layer_stack.h>
#include <utils/sys.h>
+#include <utils/sync_task.h>
#include <vector>
#include "hwc_buffer_sync_handler.h"
#include "hwc_buffer_allocator.h"
@@ -45,6 +46,22 @@
namespace sdm {
+enum class ToneMapTaskCode : int32_t {
+ kCodeGetInstance,
+ kCodeBlit,
+ kCodeDestroy,
+};
+
+struct ToneMapGetInstanceContext : public SyncTask<ToneMapTaskCode>::TaskContext {
+ Layer *layer = nullptr;
+};
+
+struct ToneMapBlitContext : public SyncTask<ToneMapTaskCode>::TaskContext {
+ Layer *layer = nullptr;
+ int merged_fd = -1;
+ int fence_fd = -1;
+};
+
struct ToneMapConfig {
int type = 0;
ColorPrimaries colorPrimaries = ColorPrimaries_Max;
@@ -53,7 +70,7 @@
bool secure = false;
};
-class ToneMapSession {
+class ToneMapSession : public SyncTask<ToneMapTaskCode>::TaskHandler {
public:
explicit ToneMapSession(HWCBufferAllocator *buffer_allocator);
~ToneMapSession();
@@ -64,7 +81,12 @@
void SetToneMapConfig(Layer *layer);
bool IsSameToneMapConfig(Layer *layer);
+ // TaskHandler methods implementation.
+ virtual void OnTask(const ToneMapTaskCode &task_code,
+ SyncTask<ToneMapTaskCode>::TaskContext *task_context);
+
static const uint8_t kNumIntermediateBuffers = 2;
+ SyncTask<ToneMapTaskCode> tone_map_task_;
Tonemapper *gpu_tone_mapper_ = nullptr;
HWCBufferAllocator *buffer_allocator_ = nullptr;
ToneMapConfig tone_map_config_ = {};
diff --git a/sdm/libs/utils/formats.cpp b/sdm/libs/utils/formats.cpp
index b7deb18..4b7190b 100644
--- a/sdm/libs/utils/formats.cpp
+++ b/sdm/libs/utils/formats.cpp
@@ -127,5 +127,87 @@
}
}
+float GetBufferFormatBpp(LayerBufferFormat format) {
+ float bpp = 0.0f;
+ switch (format) {
+ case kFormatARGB8888:
+ case kFormatRGBA8888:
+ case kFormatBGRA8888:
+ case kFormatXRGB8888:
+ case kFormatRGBX8888:
+ case kFormatBGRX8888:
+ case kFormatRGBA8888Ubwc:
+ case kFormatRGBX8888Ubwc:
+ case kFormatRGBA1010102:
+ case kFormatARGB2101010:
+ case kFormatRGBX1010102:
+ case kFormatXRGB2101010:
+ case kFormatBGRA1010102:
+ case kFormatABGR2101010:
+ case kFormatBGRX1010102:
+ case kFormatXBGR2101010:
+ case kFormatRGBA1010102Ubwc:
+ case kFormatRGBX1010102Ubwc:
+ return 4.0f;
+ case kFormatRGB888:
+ case kFormatBGR888:
+ case kFormatYCbCr420P010:
+ case kFormatYCbCr420P010Ubwc:
+ return 3.0f;
+ case kFormatRGB565:
+ case kFormatBGR565:
+ case kFormatRGBA5551:
+ case kFormatRGBA4444:
+ case kFormatBGR565Ubwc:
+ case kFormatYCbCr422H2V1Packed:
+ case kFormatCbYCrY422H2V1Packed:
+ case kFormatYCrCb422H2V1SemiPlanar:
+ case kFormatYCbCr422H2V1SemiPlanar:
+ case kFormatYCbCr420TP10Ubwc:
+ case kFormatYCbCr422H1V2SemiPlanar:
+ case kFormatYCrCb422H1V2SemiPlanar:
+ return 2.0f;
+ case kFormatYCbCr420Planar:
+ case kFormatYCrCb420Planar:
+ case kFormatYCrCb420PlanarStride16:
+ case kFormatYCbCr420SemiPlanar:
+ case kFormatYCrCb420SemiPlanar:
+ case kFormatYCbCr420SemiPlanarVenus:
+ case kFormatYCrCb420SemiPlanarVenus:
+ case kFormatYCbCr420SPVenusUbwc:
+ return 1.5f;
+ default:
+ return 0.0f;
+ }
+
+ return bpp;
+}
+
+DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size) {
+ switch (format) {
+ case kFormatYCbCr420SPVenusUbwc:
+ tile_size->tile_width = 32;
+ tile_size->tile_height = 8;
+ tile_size->uv_tile_width = 16;
+ tile_size->uv_tile_height = 8;
+ break;
+ case kFormatYCbCr420TP10Ubwc:
+ tile_size->tile_width = 48;
+ tile_size->tile_height = 4;
+ tile_size->uv_tile_width = 24;
+ tile_size->uv_tile_height = 4;
+ break;
+ case kFormatYCbCr420P010Ubwc:
+ tile_size->tile_width = 32;
+ tile_size->tile_height = 4;
+ tile_size->uv_tile_width = 16;
+ tile_size->uv_tile_height = 4;
+ break;
+ default:
+ return kErrorNotSupported;
+ }
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index b0cd536..c227cb3 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -261,5 +261,47 @@
return kOrientationLandscape;
}
+DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+ const bool rotated90, float *crop_width,
+ float *crop_height, float *dst_width,
+ float *dst_height) {
+ if (!IsValid(crop)) {
+ Log(kTagResources, "Invalid crop rect", crop);
+ return kErrorNotSupported;
+ }
+
+ if (!IsValid(dst)) {
+ Log(kTagResources, "Invalid dst rect", dst);
+ return kErrorNotSupported;
+ }
+
+ *crop_width = crop.right - crop.left;
+ *crop_height = crop.bottom - crop.top;
+ if (rotated90) {
+ std::swap(*crop_width, *crop_height);
+ }
+
+ *dst_width = dst.right - dst.left;
+ *dst_height = dst.bottom - dst.top;
+
+ return kErrorNone;
+}
+
+DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
+ bool rotated90, float *scale_x, float *scale_y) {
+ float crop_width = 1.0f, crop_height = 1.0f, dst_width = 1.0f, dst_height = 1.0f;
+
+ DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height,
+ &dst_width, &dst_height);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ *scale_x = crop_width / dst_width;
+ *scale_y = crop_height / dst_height;
+
+ return kErrorNone;
+}
+
} // namespace sdm