Merge "sdm:drm: Get DRM display token info at event handler"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 46ab782..866ade6 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
@@ -218,6 +224,7 @@
enum struct DRMRotation {
FLIP_H = 0x1,
FLIP_V = 0x2,
+ ROT_180 = FLIP_H | FLIP_V,
ROT_90 = 0x4,
};
@@ -314,17 +321,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 {
@@ -358,6 +370,7 @@
int wmin;
int hmin;
bool roi_merge;
+ DRMRotation panel_orientation;
};
/* Identifier token for a display */
diff --git a/libgralloc/Makefile.am b/libgralloc/Makefile.am
index d57ad32..3cf3960 100644
--- a/libgralloc/Makefile.am
+++ b/libgralloc/Makefile.am
@@ -1,11 +1,12 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/include
h_sources = alloc_controller.h \
memalloc.h
cpp_sources = ionalloc.cpp \
alloc_controller.cpp
-library_includedir = $(pkgincludedir)
-library_include_HEADERS = $(h_sources)
+memalloc_includedir = $(pkgincludedir)
+memalloc_include_HEADERS = $(h_sources)
lib_LTLIBRARIES = libmemalloc.la
libmemalloc_la_CC = @CC@
@@ -17,7 +18,9 @@
libmemalloc_la_LDFLAGS = -shared -avoid-version
header_sources = gralloc_priv.h \
- gr.h
+ gr.h \
+ adreno_utils.h \
+ $(HEADER_PATH)/color_metadata.h
c_sources = gpu.cpp \
gralloc.cpp \
@@ -36,4 +39,4 @@
libgralloc_la_LIBADD += ../libqdutils/libqdMetaData.la
libgralloc_la_LIBADD += -lhardware -lcutils -llog -lutils -lbinder
libgralloc_la_LIBADD += libmemalloc.la
-libgralloc_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
+libgralloc_la_LDFLAGS = -shared -avoid-version
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 1779312..d2a522e 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -247,6 +247,8 @@
aligned_w = ALIGN(width, alignment);
break;
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_Y8:
aligned_w = ALIGN(width, 16);
break;
case HAL_PIXEL_FORMAT_RAW12:
@@ -564,6 +566,7 @@
case HAL_PIXEL_FORMAT_RGBA_5551:
case HAL_PIXEL_FORMAT_RGBA_4444:
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
size = alignedw * alignedh * 2;
break;
case HAL_PIXEL_FORMAT_RAW12:
@@ -573,6 +576,7 @@
size = ALIGN(alignedw * alignedh, 4096);
break;
case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
size = alignedw * alignedh;
break;
// adreno formats
@@ -815,9 +819,11 @@
case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV21_ZSL:
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
case HAL_PIXEL_FORMAT_RAW12:
case HAL_PIXEL_FORMAT_RAW10:
case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
getYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
std::swap(ycbcr->cb, ycbcr->cr);
break;
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 4c3f7d4..7e0ba14 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -211,11 +211,10 @@
return GRALLOC1_ERROR_BAD_HANDLE;
}
- // TODO(user): delete handle once framework bug around this is confirmed
- // to be resolved. This is tracked in bug 36355756
private_handle_t * handle = const_cast<private_handle_t *>(hnd);
handle->fd = -1;
handle->fd_metadata = -1;
+ delete handle;
return GRALLOC1_ERROR_NONE;
}
@@ -278,6 +277,10 @@
}
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_);
@@ -299,6 +302,10 @@
}
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);
@@ -327,16 +334,16 @@
return GRALLOC1_ERROR_BAD_VALUE;
}
- if (hnd->base == 0) {
- // we need to map for real
- err = MapBuffer(hnd);
- }
-
auto buf = GetBufferFromHandleLocked(hnd);
if (buf == nullptr) {
return GRALLOC1_ERROR_BAD_HANDLE;
}
+ if (hnd->base == 0) {
+ // we need to map for real
+ err = MapBuffer(hnd);
+ }
+
// Invalidate if CPU reads in software and there are non-CPU
// writers. No need to do this for the metadata buffer as it is
// only read/written in software.
@@ -764,6 +771,17 @@
AllocateBuffer(descriptor, hnd, size);
} break;
+ case GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG: {
+ private_handle_t *hnd = va_arg(args, private_handle_t *);
+ int *flag = va_arg(args, int *);
+ if (private_handle_t::validate(hnd) != 0) {
+ return GRALLOC1_ERROR_BAD_HANDLE;
+ }
+ if (getMetaData(hnd, GET_PP_PARAM_INTERLACED, flag) != 0) {
+ *flag = 0;
+ }
+ } break;
+
default:
break;
}
@@ -782,9 +800,11 @@
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
case HAL_PIXEL_FORMAT_NV21_ZSL:
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
case HAL_PIXEL_FORMAT_RAW12:
case HAL_PIXEL_FORMAT_RAW10:
case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_Y8:
return true;
default:
return false;
diff --git a/libgralloc1/gr_device_impl.cpp b/libgralloc1/gr_device_impl.cpp
index b955e19..ee90090 100644
--- a/libgralloc1/gr_device_impl.cpp
+++ b/libgralloc1/gr_device_impl.cpp
@@ -106,11 +106,12 @@
void GrallocImpl::GetCapabilities(struct gralloc1_device *device, uint32_t *out_count,
int32_t /*gralloc1_capability_t*/ *out_capabilities) {
if (device != nullptr) {
- if (out_capabilities != nullptr && *out_count >= 2) {
+ if (out_capabilities != nullptr && *out_count >= 3) {
out_capabilities[0] = GRALLOC1_CAPABILITY_TEST_ALLOCATE;
out_capabilities[1] = GRALLOC1_CAPABILITY_LAYERED_BUFFERS;
+ out_capabilities[2] = GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE;
}
- *out_count = 2;
+ *out_count = 3;
}
return;
}
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 28fe4f6..b3056e1 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -201,6 +201,7 @@
// Below switch should be for only YUV/custom formats
switch (format) {
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
size = alignedw * alignedh * 2;
break;
case HAL_PIXEL_FORMAT_RAW10:
@@ -208,6 +209,7 @@
size = ALIGN(alignedw * alignedh, SIZE_4K);
break;
case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
size = alignedw * alignedh * 1;
break;
@@ -309,6 +311,28 @@
ycbcr->cstride = VENUS_UV_STRIDE(color_format, INT(width));
}
+void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+ int color_format, struct android_ycbcr *ycbcr) {
+ unsigned int uv_stride, uv_height, uv_size;
+ unsigned int alignment = 4096;
+ uint64_t field_base;
+
+ // UBWC interlaced has top-bottom field layout with each field as
+ // 4-plane NV12_UBWC with width = image_width & height = image_height / 2.
+ // Client passed ycbcr argument is ptr to struct android_ycbcr[2].
+ // Plane info to be filled for each field separately.
+ height = (height + 1) >> 1;
+ uv_stride = VENUS_UV_STRIDE(color_format, INT(width));
+ uv_height = VENUS_UV_SCANLINES(color_format, INT(height));
+ uv_size = ALIGN((uv_stride * uv_height), alignment);
+
+ field_base = base;
+ GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[0]);
+
+ field_base = reinterpret_cast<uint64_t>(ycbcr[0].cb) + uv_size;
+ GetYuvUbwcSPPlaneInfo(field_base, width, height, COLOR_FMT_NV12_UBWC, &ycbcr[1]);
+}
+
void GetYuvSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, uint32_t bpp,
struct android_ycbcr *ycbcr) {
unsigned int ystride, cstride;
@@ -330,6 +354,7 @@
gralloc1_producer_usage_t prod_usage = hnd->GetProducerUsage();
gralloc1_consumer_usage_t cons_usage = hnd->GetConsumerUsage();
unsigned int ystride, cstride;
+ bool interlaced = false;
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
MetaData_t *metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
@@ -352,6 +377,11 @@
GetAlignedWidthAndHeight(info, &width, &height);
}
+ // Check metadata for interlaced content.
+ if (metadata && (metadata->operation & PP_PARAM_INTERLACED)) {
+ interlaced = metadata->interlaced ? true : false;
+ }
+
// Get the chroma offsets from the handle width/height. We take advantage
// of the fact the width _is_ the stride
switch (format) {
@@ -369,7 +399,11 @@
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
- GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+ if (!interlaced) {
+ GetYuvUbwcSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+ } else {
+ GetYuvUbwcInterlacedSPPlaneInfo(hnd->base, width, height, COLOR_FMT_NV12_UBWC, ycbcr);
+ }
ycbcr->chroma_step = 2;
break;
@@ -389,8 +423,10 @@
case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
case HAL_PIXEL_FORMAT_NV21_ZSL:
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
case HAL_PIXEL_FORMAT_RAW10:
case HAL_PIXEL_FORMAT_RAW8:
+ case HAL_PIXEL_FORMAT_Y8:
GetYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
std::swap(ycbcr->cb, ycbcr->cr);
break;
@@ -669,6 +705,8 @@
aligned_w = ALIGN(width, alignment);
break;
case HAL_PIXEL_FORMAT_RAW16:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_Y8:
aligned_w = ALIGN(width, 16);
break;
case HAL_PIXEL_FORMAT_RAW12:
diff --git a/libgralloc1/gr_utils.h b/libgralloc1/gr_utils.h
index aa66fd0..2a08539 100644
--- a/libgralloc1/gr_utils.h
+++ b/libgralloc1/gr_utils.h
@@ -83,6 +83,8 @@
struct android_ycbcr *ycbcr);
void GetYuvUbwcSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height, int color_format,
struct android_ycbcr *ycbcr);
+void GetYuvUbwcInterlacedSPPlaneInfo(uint64_t base, uint32_t width, uint32_t height,
+ int color_format, struct android_ycbcr *ycbcr);
void GetRgbUBwcBlockSize(uint32_t bpp, int *block_width, int *block_height);
unsigned int GetRgbUBwcMetaBufferSize(int width, int height, uint32_t bpp);
unsigned int GetUBwcSize(int width, int height, int format, unsigned int alignedw,
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index ba156b6..1839d2f 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -97,6 +97,7 @@
#define GRALLOC_MODULE_PERFORM_SET_SINGLE_BUFFER_MODE 13
#define GRALLOC1_MODULE_PERFORM_GET_BUFFER_SIZE_AND_DIMENSIONS 14
#define GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER 15
+#define GRALLOC1_MODULE_PERFORM_GET_INTERLACE_FLAG 16
// OEM specific HAL formats
#define HAL_PIXEL_FORMAT_RGBA_5551 6
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index 7afd00f..60efb3a 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -20,12 +20,12 @@
include $(CLEAR_VARS)
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
-LOCAL_COPY_HEADERS := qdMetaData.h
+LOCAL_COPY_HEADERS := qdMetaData.h qd_utils.h
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_C_INCLUDES := $(common_includes)
LOCAL_HEADER_LIBRARIES := display_headers
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES := qdMetaData.cpp
+LOCAL_SRC_FILES := qdMetaData.cpp qd_utils.cpp
LOCAL_CFLAGS := $(common_flags) -Wno-sign-conversion
LOCAL_CFLAGS += -DLOG_TAG=\"DisplayMetaData\"
@@ -34,3 +34,18 @@
LOCAL_VENDOR_MODULE := true
include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_C_INCLUDES := $(common_includes)
+LOCAL_HEADER_LIBRARIES := display_headers
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES := qdMetaData.cpp qd_utils.cpp
+LOCAL_CFLAGS := $(common_flags) -Wno-sign-conversion
+LOCAL_CFLAGS += -DLOG_TAG=\"DisplayMetaData\"
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libqdMetaData.system
+
+include $(BUILD_SHARED_LIBRARY)
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/color_params.h b/sdm/include/private/color_params.h
index 0a53832..08895ee 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -578,9 +578,13 @@
// from ColorManager, containing all physical features to be programmed and also compute
// metadata/populate into T.
inline DisplayError AddFeature(uint32_t feature_id, PPFeatureInfo *feature) {
- if (feature_id < kMaxNumPPFeatures)
+ if (feature_id < kMaxNumPPFeatures) {
+ if (feature_[feature_id]) {
+ delete feature_[feature_id];
+ feature_[feature_id] = NULL;
+ }
feature_[feature_id] = feature;
-
+ }
return kErrorNone;
}
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index cdfec2e..64e8454 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -205,6 +205,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 +322,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 +349,7 @@
float input_compression = 1.0f;
float output_compression = 1.0f;
bool is_buffer_cached = false;
+ HWRotatorMode mode = kRotatorNone;
};
struct HWScaleLutInfo {
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/include/utils/sync_task.h b/sdm/include/utils/sync_task.h
new file mode 100644
index 0000000..725460a
--- /dev/null
+++ b/sdm/include/utils/sync_task.h
@@ -0,0 +1,143 @@
+/*
+* 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 __SYNC_TASK_H__
+#define __SYNC_TASK_H__
+
+#include <thread>
+#include <mutex>
+#include <condition_variable> // NOLINT
+
+namespace sdm {
+
+template <class TaskCode>
+class SyncTask {
+ public:
+ // This class need to be overridden by caller to pass on a task context.
+ class TaskContext {
+ public:
+ virtual ~TaskContext() { }
+ };
+
+ // Methods to callback into caller for command codes executions in worker thread.
+ class TaskHandler {
+ public:
+ virtual ~TaskHandler() { }
+ virtual void OnTask(const TaskCode &task_code, TaskContext *task_context) = 0;
+ };
+
+ explicit SyncTask(TaskHandler &task_handler) : task_handler_(task_handler) {
+ // Block caller thread until worker thread has started and ready to listen to task commands.
+ // Worker thread will signal as soon as callback is received in the new thread.
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+ std::thread worker_thread(SyncTaskThread, this);
+ worker_thread_.swap(worker_thread);
+ caller_cv_.wait(caller_lock);
+ }
+
+ ~SyncTask() {
+ // Task code does not matter here.
+ PerformTask(task_code_, nullptr, true);
+ worker_thread_.join();
+ }
+
+ void PerformTask(const TaskCode &task_code, TaskContext *task_context) {
+ PerformTask(task_code, task_context, false);
+ }
+
+ private:
+ void PerformTask(const TaskCode &task_code, TaskContext *task_context, bool terminate) {
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+
+ // New scope to limit scope of worker lock to this block.
+ {
+ // Set task command code and notify worker thread.
+ std::unique_lock<std::mutex> worker_lock(worker_mutex_);
+ task_code_ = task_code;
+ task_context_ = task_context;
+ worker_thread_exit_ = terminate;
+ pending_code_ = true;
+ worker_cv_.notify_one();
+ }
+
+ // Wait for worker thread to finish and signal.
+ caller_cv_.wait(caller_lock);
+ }
+
+ static void SyncTaskThread(SyncTask *sync_task) {
+ if (sync_task) {
+ sync_task->OnThreadCallback();
+ }
+ }
+
+ void OnThreadCallback() {
+ // Acquire worker lock and start waiting for events.
+ // Wait must start before caller thread can post events, otherwise posted events will be lost.
+ // Caller thread will be blocked until worker thread signals readiness.
+ std::unique_lock<std::mutex> worker_lock(worker_mutex_);
+
+ // New scope to limit scope of caller lock to this block.
+ {
+ // Signal caller thread that worker thread is ready to listen to events.
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+ caller_cv_.notify_one();
+ }
+
+ while (!worker_thread_exit_) {
+ // Add predicate to handle spurious interrupts.
+ // Wait for caller thread to signal new command codes.
+ worker_cv_.wait(worker_lock, [this] { return pending_code_; });
+
+ // Call task handler which is implemented by the caller.
+ if (!worker_thread_exit_) {
+ task_handler_.OnTask(task_code_, task_context_);
+ }
+
+ pending_code_ = false;
+ // Notify completion of current task to the caller thread which is blocked.
+ std::unique_lock<std::mutex> caller_lock(caller_mutex_);
+ caller_cv_.notify_one();
+ }
+ }
+
+ TaskHandler &task_handler_;
+ TaskCode task_code_;
+ TaskContext *task_context_ = nullptr;
+ std::thread worker_thread_;
+ std::mutex caller_mutex_;
+ std::mutex worker_mutex_;
+ std::condition_variable caller_cv_;
+ std::condition_variable worker_cv_;
+ bool worker_thread_exit_ = false;
+ bool pending_code_ = false;
+};
+
+} // namespace sdm
+
+#endif // __SYNC_TASK_H__
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 1d55d96..c5002a9 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -7,7 +7,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_HEADER_LIBRARIES := display_headers
-LOCAL_CFLAGS := -Wno-unused-parameter -DLOG_TAG=\"SDM\" \
+LOCAL_CFLAGS := -fno-operator-names -Wno-unused-parameter -DLOG_TAG=\"SDM\" \
$(common_flags)
LOCAL_HW_INTF_PATH_1 := fb
LOCAL_SHARED_LIBRARIES := libdl libsdmutils
@@ -51,6 +51,7 @@
$(LOCAL_HW_INTF_PATH_2)/hw_device_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 \
$(LOCAL_HW_INTF_PATH_2)/hw_color_manager_drm.cpp
endif
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 618dd2e..f6540cd 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);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 79d09bd..a6ed929 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>
@@ -216,14 +217,6 @@
}
void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) {
- DRMMaster *master = nullptr;
- DRMMaster::GetInstance(&master);
-
- if (!master) {
- DLOGE("Failed to acquire DRM Master instance");
- return;
- }
-
HWLayersInfo &hw_layer_info = hw_layers->info;
uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
@@ -233,32 +226,45 @@
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;
}
- int fd = input_buffer->planes[0].fd;
- if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
- AllocatedBufferInfo buf_info {};
- DRMBuffer layout {};
- buf_info.fd = layout.fd = fd;
- buf_info.aligned_width = layout.width = input_buffer->width;
- buf_info.aligned_height = layout.height = input_buffer->height;
- buf_info.format = input_buffer->format;
- GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
- buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
- &layout.num_planes);
- uint32_t fb_id = 0;
- int ret = master->CreateFbId(layout, &fb_id);
- if (ret < 0) {
- DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
- layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
- errno);
- } else {
- hashmap_[current_index_][fd] = fb_id;
- }
+ MapBufferToFbId(input_buffer);
+ }
+}
+
+void HWDeviceDRM::Registry::MapBufferToFbId(LayerBuffer* buffer) {
+ int fd = buffer->planes[0].fd;
+ DRMMaster *master = nullptr;
+ DRMMaster::GetInstance(&master);
+
+ if (!master) {
+ DLOGE("Failed to acquire DRM Master instance");
+ return;
+ }
+
+ if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
+ AllocatedBufferInfo buf_info{};
+ DRMBuffer layout{};
+ buf_info.fd = layout.fd = fd;
+ buf_info.aligned_width = layout.width = buffer->width;
+ buf_info.aligned_height = layout.height = buffer->height;
+ buf_info.format = buffer->format;
+ GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
+ buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
+ &layout.num_planes);
+ uint32_t fb_id = 0;
+ int ret = master->CreateFbId(layout, &fb_id);
+ if (ret < 0) {
+ DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
+ layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
+ errno);
+ } else {
+ hashmap_[current_index_][fd] = fb_id;
}
}
+ return;
}
void HWDeviceDRM::Registry::UnregisterNext() {
@@ -300,6 +306,7 @@
: hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
registry_(buffer_allocator) {
device_type_ = kDevicePrimary;
+ disp_type_ = DRMDisplayType::PERIPHERAL;
device_name_ = "Peripheral Display";
hw_info_intf_ = hw_info_intf;
}
@@ -309,15 +316,13 @@
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::PERIPHERAL, &token_)) {
- DLOGE("RegisterDisplay failed");
+ drm_master->GetHandle(&dev_fd_);
+ DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd_, &drm_mgr_intf_);
+ if (drm_mgr_intf_->RegisterDisplay(disp_type_, &token_)) {
+ DLOGE("RegisterDisplay failed for display %d", disp_type_);
return kErrorResources;
}
-
drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
InitializeConfigs();
@@ -325,17 +330,18 @@
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
// Commit to setup pipeline with mode, which then tells us the topology etc
- 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;
+
+ if (!deferred_initialize_) {
+ if (drm_atomic_intf_->Commit(true /* synchronous */)) {
+ DRM_LOGI("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_);
}
-
- // 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();
@@ -409,7 +415,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);
@@ -445,6 +453,15 @@
hw_panel_info_.is_primary_panel = connector_info_.is_primary;
hw_panel_info_.is_pluggable = 0;
+ // no supprt for 90 rotation only flips or 180 supported
+ hw_panel_info_.panel_orientation.rotation = 0;
+ hw_panel_info_.panel_orientation.flip_horizontal =
+ (connector_info_.panel_orientation == DRMRotation::FLIP_H) ||
+ (connector_info_.panel_orientation == DRMRotation::ROT_180);
+ hw_panel_info_.panel_orientation.flip_vertical =
+ (connector_info_.panel_orientation == DRMRotation::FLIP_V) ||
+ (connector_info_.panel_orientation == DRMRotation::ROT_180);
+
GetHWDisplayPortAndMode();
GetHWPanelMaxBrightness();
@@ -560,18 +577,19 @@
DisplayError HWDeviceDRM::PowerOn() {
DTRACE_SCOPED();
-/*
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 */);
+ if (ret) {
+ DLOGE("%s failed with error %d", __FUNCTION__, ret);
+ return kErrorHardware;
+ }
return kErrorNone;
}
DisplayError HWDeviceDRM::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);
-*/
int ret = drm_atomic_intf_->Commit(false /* synchronous */);
if (ret) {
DLOGE("%s failed with error %d", __FUNCTION__, ret);
@@ -637,15 +655,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);
@@ -659,21 +675,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);
@@ -796,7 +808,7 @@
int ret = drm_atomic_intf_->Commit(false /* synchronous */);
if (ret) {
- DLOGE("%s failed with error %d", __FUNCTION__, ret);
+ DLOGE("%s failed with error %d crtc %d", __FUNCTION__, ret, token_.crtc_id);
return kErrorHardware;
}
@@ -813,7 +825,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);
@@ -859,6 +871,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;
}
@@ -872,7 +914,6 @@
DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
struct DRMPPFeatureInfo info = {};
-
for (uint32_t i = 0; i < kMaxNumPPFeatures; i++) {
memset(&info, 0, sizeof(struct DRMPPFeatureInfo));
info.id = HWColorManagerDrm::ToDrmFeatureId(i);
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index d318786..2199426 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -49,7 +49,7 @@
class HWDeviceDRM : public HWInterface {
public:
- explicit HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+ HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
HWInfoInterface *hw_info_intf);
virtual ~HWDeviceDRM() {}
virtual DisplayError Init();
@@ -94,6 +94,7 @@
virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+ virtual void InitializeConfigs();
enum {
kHWEventVSync,
@@ -116,10 +117,10 @@
void ResetDisplayParams();
bool EnableHotPlugDetection(int enable);
void UpdateMixerAttributes();
- void InitializeConfigs();
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);
@@ -133,6 +134,8 @@
void UnregisterNext();
// Call on display disconnect to release all gem handles and fb_ids
void Clear();
+ // Maps given fd to FB ID
+ void MapBufferToFbId(LayerBuffer* buffer);
// Finds an fb_id corresponding to an fd in current map
uint32_t GetFbId(int fd);
@@ -145,24 +148,30 @@
BufferAllocator *buffer_allocator_ = {};
};
- HWResourceInfo hw_resource_ = {};
- HWPanelInfo hw_panel_info_ = {};
+ protected:
+ const char *device_name_ = {};
+ bool deferred_initialize_ = false;
+ sde_drm::DRMDisplayType disp_type_ = {};
HWInfoInterface *hw_info_intf_ = {};
BufferSyncHandler *buffer_sync_handler_ = {};
+ int dev_fd_ = -1;
+ Registry registry_;
+ sde_drm::DRMDisplayToken token_ = {};
+ HWResourceInfo hw_resource_ = {};
+ HWPanelInfo hw_panel_info_ = {};
HWDeviceType device_type_ = {};
- const char *device_name_ = {};
- bool synchronous_commit_ = false;
- HWDisplayAttributes display_attributes_ = {};
- HWMixerAttributes mixer_attributes_ = {};
sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
- sde_drm::DRMDisplayToken token_ = {};
- drmModeModeInfo current_mode_ = {};
- bool default_mode_ = false;
sde_drm::DRMConnectorInfo connector_info_ = {};
+ drmModeModeInfo current_mode_ = {};
+ HWDisplayAttributes display_attributes_ = {};
+
+ private:
+ bool synchronous_commit_ = false;
+ HWMixerAttributes mixer_attributes_ = {};
+ bool default_mode_ = false;
std::string interface_str_ = "DSI";
HWScaleDRM *hw_scale_ = {};
- Registry registry_;
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 6258d73..d5bd5cf 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,
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
new file mode 100644
index 0000000..5fe1d86
--- /dev/null
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -0,0 +1,188 @@
+/*
+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 <stdio.h>
+#include <ctype.h>
+#include <drm_logger.h>
+#include <utils/debug.h>
+#include "hw_device_drm.h"
+#include "hw_virtual_drm.h"
+#include "hw_info_drm.h"
+
+#define __CLASS__ "HWVirtualDRM"
+
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMRect;
+using sde_drm::DRMOps;
+
+namespace sdm {
+
+HWVirtualDRM::HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator,
+ HWInfoInterface *hw_info_intf)
+ : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
+ HWDeviceDRM::deferred_initialize_ = true;
+ HWDeviceDRM::device_name_ = "Virtual Display Device";
+ HWDeviceDRM::hw_info_intf_ = hw_info_intf;
+ HWDeviceDRM::disp_type_ = DRMDisplayType::VIRTUAL;
+}
+
+DisplayError HWVirtualDRM::Init() {
+ return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::DeferredInit() {
+ if (HWDeviceDRM::Init() != kErrorNone)
+ return kErrorResources;
+
+ drm_mgr_intf_->SetScalerLUT(drm_lut_info_);
+ DLOGI_IF(kTagDriverConfig, "Setup CRTC %d, Connector %d for %s",
+ token_.crtc_id, token_.conn_id, device_name_);
+
+ return kErrorNone;
+}
+
+void HWVirtualDRM::ConfigureWbConnectorFbId(uint32_t fb_id) {
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, token_.conn_id, fb_id);
+ return;
+}
+
+void HWVirtualDRM::ConfigureWbConnectorDestRect() {
+ DRMRect dst = {};
+ dst.left = 0;
+ dst.bottom = height_;
+ dst.top = 0;
+ dst.right = width_;
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, token_.conn_id, dst);
+ return;
+}
+
+void HWVirtualDRM::InitializeConfigs() {
+ current_mode_.hdisplay = current_mode_.hsync_start = current_mode_.hsync_end \
+ = current_mode_.htotal = (uint16_t) width_;
+ current_mode_.vdisplay = current_mode_.vsync_start = current_mode_.vsync_end \
+ = current_mode_.vtotal = (uint16_t) height_;
+ // Not sure SF has a way to configure refresh rate. Hardcoding to 60 fps for now.
+ // TODO(user): Make this configurable.
+ current_mode_.vrefresh = 60;
+ current_mode_.clock = (current_mode_.htotal * current_mode_.vtotal \
+ * current_mode_.vrefresh) / 1000;
+ struct sde_drm_wb_cfg wb_cfg;
+ wb_cfg.connector_id = token_.conn_id;
+ wb_cfg.flags |= SDE_DRM_WB_CFG_FLAGS_CONNECTED;
+ wb_cfg.count_modes = 1;
+ wb_cfg.modes = (uint64_t)¤t_mode_;
+ #ifdef DRM_IOCTL_SDE_WB_CONFIG
+ int ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &wb_cfg);
+ #endif
+ if (ret) {
+ DLOGE("WB config failed\n");
+ } else {
+ drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+ current_mode_ = connector_info_.modes[0];
+ DumpConfigs();
+ }
+}
+
+void HWVirtualDRM::DumpConfigs() {
+ for (uint32_t i = 0; i < (uint32_t)connector_info_.num_modes; i++) {
+ DLOGI(
+ "Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t"
+ "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n",
+ connector_info_.modes[i].name, connector_info_.modes[i].vrefresh,
+ connector_info_.modes[i].hdisplay,
+ connector_info_.modes[i].hsync_start, connector_info_.modes[i].hsync_end,
+ connector_info_.modes[i].htotal, connector_info_.modes[i].vdisplay,
+ connector_info_.modes[i].vsync_start, connector_info_.modes[i].vsync_end,
+ connector_info_.modes[i].vtotal);
+ }
+}
+
+DisplayError HWVirtualDRM::Commit(HWLayers *hw_layers) {
+ LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+ DisplayError err = kErrorNone;
+
+ registry_.RegisterCurrent(hw_layers);
+ registry_.MapBufferToFbId(output_buffer);
+ uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+
+ ConfigureWbConnectorFbId(fb_id);
+ ConfigureWbConnectorDestRect();
+
+ err = HWDeviceDRM::AtomicCommit(hw_layers);
+ registry_.UnregisterNext();
+ return(err);
+}
+
+DisplayError HWVirtualDRM::Validate(HWLayers *hw_layers) {
+ // TODO(user) : Add validate support
+ return kErrorNone;
+}
+
+
+DisplayError HWVirtualDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+ if (display_attributes.x_pixels == 0 || display_attributes.y_pixels == 0) {
+ return kErrorParameters;
+ }
+
+ display_attributes_ = display_attributes;
+
+ if (display_attributes_.x_pixels > hw_resource_.max_mixer_width) {
+ display_attributes_.is_device_split = true;
+ }
+
+ width_ = display_attributes_.x_pixels;
+ height_ = display_attributes_.y_pixels;
+ DeferredInit();
+
+ return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+ return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+ drm_lut_info_.cir_lut = lut_info->cir_lut;
+ drm_lut_info_.dir_lut = lut_info->dir_lut;
+ drm_lut_info_.sep_lut = lut_info->sep_lut;
+ drm_lut_info_.cir_lut_size = lut_info->cir_lut_size;
+ drm_lut_info_.dir_lut_size = lut_info->dir_lut_size;
+ drm_lut_info_.sep_lut_size = lut_info->sep_lut_size;
+
+ // Due to differed Init in WB case, we cannot set scaler config immediately as we
+ // won't have SDE DRM initialized at this point. Hence have to cache LUT info here
+ // and set it in ::DeferredInit
+
+ return kErrorNone;
+}
+
+} // namespace sdm
+
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
new file mode 100644
index 0000000..b63519a
--- /dev/null
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -0,0 +1,71 @@
+/*
+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_VIRTUAL_DRM_H__
+#define __HW_VIRTUAL_DRM_H__
+
+#include "hw_device_drm.h"
+#include <drm/msm_drm.h>
+#include <drm/sde_drm.h>
+
+namespace sdm {
+
+class HWVirtualDRM : public HWDeviceDRM {
+ public:
+ HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
+ BufferAllocator *buffer_allocator, HWInfoInterface *hw_info_intf);
+ virtual ~HWVirtualDRM() {}
+ virtual DisplayError SetVSyncState(bool enable) { return kErrorNotSupported; }
+ virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+ return kErrorNotSupported;
+ }
+ virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+
+ protected:
+ virtual DisplayError Init();
+ virtual DisplayError Validate(HWLayers *hw_layers);
+ virtual DisplayError DeferredInit();
+ virtual void InitializeConfigs();
+ virtual DisplayError Commit(HWLayers *hw_layers);
+ virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+ virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+ void ConfigureWbConnectorFbId(uint32_t fb_id);
+ void ConfigureWbConnectorDestRect();
+ void DumpConfigs();
+
+ private:
+ uint32_t width_ = 0;
+ uint32_t height_ = 0;
+ sde_drm::DRMScalerLUTInfo drm_lut_info_ = {};
+};
+
+} // namespace sdm
+
+#endif // __HW_VIRTUAL_DRM_H__
+
diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp
index b5c9fe9..a7bcabd 100644
--- a/sdm/libs/core/hw_interface.cpp
+++ b/sdm/libs/core/hw_interface.cpp
@@ -37,6 +37,7 @@
#include "fb/hw_virtual.h"
#ifdef COMPILE_DRM
#include "drm/hw_device_drm.h"
+#include "drm/hw_virtual_drm.h"
#endif
#define __CLASS__ "HWInterface"
@@ -71,7 +72,9 @@
if (driver_type == DriverType::FB) {
hw = new HWVirtual(buffer_sync_handler, hw_info_intf);
} else {
- return kErrorNotSupported;
+#ifdef COMPILE_DRM
+ hw = new HWVirtualDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+#endif
}
break;
default:
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 07ec2ce..2c5c885 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -58,15 +58,6 @@
namespace sdm {
-static void ApplyDeInterlaceAdjustment(Layer *layer) {
- // De-interlacing adjustment
- if (layer->input_buffer.flags.interlace) {
- float height = (layer->src_rect.bottom - layer->src_rect.top) / 2.0f;
- layer->src_rect.top = ROUND_UP_ALIGN_DOWN(layer->src_rect.top / 2.0f, 2);
- layer->src_rect.bottom = layer->src_rect.top + floorf(height);
- }
-}
-
void HWCColorMode::Init() {
int ret = PopulateColorModes();
if (ret != 0) {
@@ -575,7 +566,6 @@
}
}
SetRect(hwc_layer.sourceCropf, &layer->src_rect);
- ApplyDeInterlaceAdjustment(layer);
uint32_t num_visible_rects = UINT32(hwc_layer.visibleRegionScreen.numRects);
uint32_t num_dirty_rects = UINT32(hwc_layer.surfaceDamage.numRects);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 8a5bd81..98e14ee 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -289,7 +289,7 @@
}
if (hwc_session->need_invalidate_) {
- hwc_procs->invalidate(hwc_procs);
+ hwc_session->AsyncRefresh();
hwc_session->need_invalidate_ = false;
}
@@ -420,6 +420,8 @@
hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
}
+ locker_.Signal();
+
// This is only indicative of how many times SurfaceFlinger posts
// frames to the display.
CALC_FPS();
@@ -693,6 +695,14 @@
return 0;
}
+static void PostRefresh(hwc_procs_t const *hwc_procs) {
+ hwc_procs->invalidate(hwc_procs);
+}
+
+void HWCSession::AsyncRefresh() {
+ future_ = std::async(PostRefresh, hwc_procs_);
+}
+
android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
SEQUENCE_WAIT_SCOPE_LOCK(locker_);
@@ -705,7 +715,7 @@
break;
case qService::IQService::SCREEN_REFRESH:
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case qService::IQService::SET_IDLE_TIMEOUT:
@@ -856,7 +866,7 @@
}
android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
- android::Parcel *out) {
+ android::Parcel *output_parcel) {
DisplayError error = kErrorNone;
int ret = 0;
uint32_t disp_id = UINT32(input_parcel->readInt32());
@@ -865,14 +875,14 @@
if (disp_id != HWC_DISPLAY_PRIMARY) {
DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
ret = -EINVAL;
- out->writeInt32(ret);
+ output_parcel->writeInt32(ret);
return ret;
}
if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
DLOGE("primary display object is not instantiated");
ret = -EINVAL;
- out->writeInt32(ret);
+ output_parcel->writeInt32(ret);
return ret;
}
@@ -881,31 +891,30 @@
if (error == kErrorNone) {
if (!pending) {
- out->writeInt32(ret);
+ output_parcel->writeInt32(ret);
return ret;
}
} else if (error == kErrorNotSupported) {
- out->writeInt32(ret);
+ output_parcel->writeInt32(ret);
return ret;
} else {
ret = -EINVAL;
- out->writeInt32(ret);
+ output_parcel->writeInt32(ret);
return ret;
}
- // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
// Wait until partial update control is complete
ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
- out->writeInt32(ret);
+ output_parcel->writeInt32(ret);
return ret;
}
android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
- android::Parcel *output_parcel) {
+ android::Parcel *output_parcel) {
int config = input_parcel->readInt32();
int dpy = input_parcel->readInt32();
int error = android::BAD_VALUE;
@@ -917,7 +926,7 @@
if (hwc_display_[dpy]) {
error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
if (error == 0) {
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
}
}
@@ -1128,7 +1137,7 @@
HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
// trigger invalidate to apply new bw caps.
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
error = core_intf_->SetMaxBandwidthMode(mode);
if (error != kErrorNone) {
@@ -1325,7 +1334,7 @@
switch (pending_action.action) {
case kInvalidating:
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case kEnterQDCMMode:
ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
@@ -1336,12 +1345,12 @@
case kApplySolidFill:
ret = color_mgr_->SetSolidFill(pending_action.params,
true, hwc_display_[HWC_DISPLAY_PRIMARY]);
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case kDisableSolidFill:
ret = color_mgr_->SetSolidFill(pending_action.params,
false, hwc_display_[HWC_DISPLAY_PRIMARY]);
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case kSetPanelBrightness:
brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
@@ -1355,7 +1364,7 @@
case kEnableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params,
true, hwc_display_[HWC_DISPLAY_PRIMARY]);
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case kDisableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params,
@@ -1364,7 +1373,7 @@
case kConfigureDetailedEnhancer:
ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
hwc_display_[HWC_DISPLAY_PRIMARY]);
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case kInvalidatingAndkSetPanelBrightness:
brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
@@ -1374,7 +1383,7 @@
}
if (HWC_DISPLAY_PRIMARY == display_id)
ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value);
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
break;
case kNoAction:
break;
@@ -1460,7 +1469,7 @@
if (panel_reset == 0) {
if (hwc_procs_) {
reset_panel_ = true;
- hwc_procs_->invalidate(hwc_procs_);
+ AsyncRefresh();
} else {
DLOGW("Ignore resetpanel - hwc_proc not registered");
}
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 1cd3e33..ce21c46 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -28,6 +28,7 @@
#include <hardware/hwcomposer.h>
#include <core/core_interface.h>
#include <utils/locker.h>
+#include <future> // NOLINT
#include "hwc_display_primary.h"
#include "hwc_display_external.h"
@@ -88,6 +89,7 @@
int GetVsyncPeriod(int disp);
int CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
bool use_primary_res);
+ void AsyncRefresh();
// QClient methods
virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -103,7 +105,8 @@
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 ControlPartialUpdate(const android::Parcel *input_parcel,
+ android::Parcel *output_parcel);
android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
android::Parcel *output_parcel);
android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
@@ -151,6 +154,7 @@
qService::QService *qservice_ = NULL;
bool is_hdmi_primary_ = false;
bool is_hdmi_yuv_ = false;
+ std::future<void> future_;
std::bitset<HWC_NUM_DISPLAY_TYPES> connected_displays_; // Bit mask of connected displays
HWCSocketHandler socket_handler_;
Locker uevent_locker_;
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index da40a34..3c8d460 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -114,10 +114,6 @@
alloc_buffer_info->fd = -1;
alloc_buffer_info->stride = 0;
alloc_buffer_info->size = 0;
- // Works around b/36355756
- if (hnd != nullptr) {
- delete hnd;
- }
buffer_info->private_data = NULL;
return err;
}
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index f48ed2d..4f623ce 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -54,26 +54,6 @@
namespace sdm {
-static void ApplyDeInterlaceAdjustment(HWCLayer *hwc_layer, Layer *sdm_layer) {
- // De-interlacing adjustment
- if (sdm_layer->input_buffer.flags.interlace) {
- // Adjust src_rect only if new source crop was set
- if (hwc_layer->GetGeometryChanges() & kSourceCrop) {
- float height = (sdm_layer->src_rect.bottom - sdm_layer->src_rect.top) / 2.0f;
- sdm_layer->src_rect.top = ROUND_UP_ALIGN_DOWN(sdm_layer->src_rect.top / 2.0f, 2);
- sdm_layer->src_rect.bottom = sdm_layer->src_rect.top + floorf(height);
- }
-
- // Handle deinterlacing for UBWC Interlaced format.
- if (IsUBWCFormat(sdm_layer->input_buffer.format)) {
- sdm_layer->input_buffer.height /= 2;
- sdm_layer->input_buffer.unaligned_height /= 2;
- // After adjustments layer needs to be treated as UBWC progressive. Reset interlace flag.
- sdm_layer->input_buffer.flags.interlace = 0;
- }
- }
-}
-
// This weight function is needed because the color primaries are not sorted by gamut size
static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
int weight = 10;
@@ -417,6 +397,7 @@
HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
layer_map_.emplace(std::make_pair(layer->GetId(), layer));
*out_layer_id = layer->GetId();
+ validated_ = false;
geometry_changes_ |= GeometryChanges::kAdded;
return HWC2::Error::None;
}
@@ -447,6 +428,7 @@
break;
}
}
+ validated_ = false;
geometry_changes_ |= GeometryChanges::kRemoved;
return HWC2::Error::None;
@@ -462,6 +444,9 @@
// Add one layer for fb target
// TODO(user): Add blit target layers
for (auto hwc_layer : layer_set_) {
+ // Reset layer data which SDM may change
+ hwc_layer->ResetPerFrameData();
+
Layer *layer = hwc_layer->GetSDMLayer();
layer->flags = {}; // Reset earlier flags
if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
@@ -536,7 +521,6 @@
INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
ApplyScanAdjustment(&scaled_display_frame);
hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
- ApplyDeInterlaceAdjustment(hwc_layer, layer);
// SDM requires these details even for solid fill
if (layer->flags.solid_fill) {
LayerBuffer *layer_buffer = &layer->input_buffer;
@@ -604,6 +588,7 @@
DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
return HWC2::Error::BadLayer;
}
+ validated_ = false;
const auto layer = map_layer->second;
const auto z_range = layer_set_.equal_range(layer);
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index a375831..1b04c84 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -137,6 +137,18 @@
virtual int GetDisplayConfigCount(uint32_t *count);
virtual int GetDisplayAttributesForConfig(int config,
DisplayConfigVariableInfo *display_attributes);
+ template <typename... Args>
+ int32_t CallLayerFunction(hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args... ),
+ Args... args) {
+ auto status = HWC2::Error::BadLayer;
+ validated_ = false;
+ auto hwc_layer = GetHWCLayer(layer);
+ if (hwc_layer != nullptr) {
+ status = (hwc_layer->*member)(std::forward<Args>(args)...);
+ }
+
+ return INT32(status);
+ }
int SetPanelBrightness(int level);
int GetPanelBrightness(int *level);
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 7fef9cf..7fcd56b 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -258,14 +258,21 @@
HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
LayerRect dst_rect = {};
+
SetRect(frame, &dst_rect);
- if (layer_->dst_rect != dst_rect) {
+ if (dst_rect_ != dst_rect) {
geometry_changes_ |= kDisplayFrame;
- layer_->dst_rect = dst_rect;
+ dst_rect_ = dst_rect;
}
+
return HWC2::Error::None;
}
+void HWCLayer::ResetPerFrameData() {
+ layer_->dst_rect = dst_rect_;
+ layer_->transform = layer_transform_;
+}
+
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));
@@ -322,10 +329,11 @@
break;
}
- if (layer_->transform != layer_transform) {
+ if (layer_transform_ != layer_transform) {
geometry_changes_ |= kTransform;
- layer_->transform = layer_transform;
+ layer_transform_ = layer_transform;
}
+
return HWC2::Error::None;
}
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index bc3d84d..82bf466 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -61,6 +61,7 @@
uint32_t GetZ() const { return z_; }
hwc2_layer_t GetId() const { return id_; }
Layer *GetSDMLayer() { return layer_; }
+ void ResetPerFrameData();
HWC2::Error SetLayerBlendMode(HWC2::BlendMode mode);
HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
@@ -96,6 +97,8 @@
int ion_fd_ = -1;
HWCBufferAllocator *buffer_allocator_ = NULL;
int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
+ LayerTransform layer_transform_ = {};
+ LayerRect dst_rect_ = {};
// Composition requested by client(SF)
HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 87d41d7..7d31a3a 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -70,15 +70,11 @@
}
HWCSession *hwc_session = static_cast<HWCSession *>(device);
- auto status = HWC2::Error::BadDisplay;
+ int32_t status = INT32(HWC2::Error::BadDisplay);
if (hwc_session->hwc_display_[display]) {
- status = HWC2::Error::BadLayer;
- auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
- if (hwc_layer != nullptr) {
- status = (hwc_layer->*member)(std::forward<Args>(args)...);
- }
+ status = hwc_session->hwc_display_[display]->CallLayerFunction(layer, member, args...);
}
- return INT32(status);
+ return status;
}
// HWC2 Functions that require a concrete implementation in hwc session
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
index fe89104..09e1414 100644
--- a/sdm/libs/utils/Android.mk
+++ b/sdm/libs/utils/Android.mk
@@ -25,6 +25,7 @@
$(SDM_HEADER_PATH)/utils/locker.h \
$(SDM_HEADER_PATH)/utils/rect.h \
$(SDM_HEADER_PATH)/utils/sys.h \
+ $(SDM_HEADER_PATH)/utils/sync_task.h \
$(SDM_HEADER_PATH)/utils/utils.h \
$(SDM_HEADER_PATH)/utils/factory.h
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